| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // Copyright 2014 The go-ethereum Authors | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // This file is part of the go-ethereum library. | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // | 
					
						
							| 
									
										
										
										
											2015-07-23 18:35:11 +02:00
										 |  |  | // The go-ethereum library is free software: you can redistribute it and/or modify | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // it under the terms of the GNU Lesser General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // The go-ethereum library is distributed in the hope that it will be useful, | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // GNU Lesser General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Lesser General Public License | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-31 14:43:14 +01:00
										 |  |  | package state | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2015-02-17 13:10:18 +01:00
										 |  |  | 	"bytes" | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2015-12-11 01:29:41 +01:00
										 |  |  | 	"io" | 
					
						
							| 
									
										
										
										
											2014-07-30 00:31:15 +02:00
										 |  |  | 	"math/big" | 
					
						
							| 
									
										
										
										
											2019-03-25 10:01:18 +02:00
										 |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2014-07-30 00:31:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							| 
									
										
										
										
											2015-03-16 11:59:52 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/crypto" | 
					
						
							| 
									
										
										
										
											2019-03-25 10:01:18 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/metrics" | 
					
						
							| 
									
										
										
										
											2015-02-17 13:10:18 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/rlp" | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-21 18:40:27 +00:00
										 |  |  | var emptyCodeHash = crypto.Keccak256(nil) | 
					
						
							| 
									
										
										
										
											2015-12-11 01:29:41 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | type Code []byte | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | func (c Code) String() string { | 
					
						
							|  |  |  | 	return string(c) //strings.Join(Disassemble(c), " ") | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-03 23:46:27 +01:00
										 |  |  | type Storage map[common.Hash]common.Hash | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | func (s Storage) String() (str string) { | 
					
						
							|  |  |  | 	for key, value := range s { | 
					
						
							| 
									
										
										
										
											2015-06-17 11:24:40 +02:00
										 |  |  | 		str += fmt.Sprintf("%X : %X\n", key, value) | 
					
						
							| 
									
										
										
										
											2015-02-26 18:39:05 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | func (s Storage) Copy() Storage { | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 	cpy := make(Storage) | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 	for key, value := range s { | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 		cpy[key] = value | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return cpy | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 23:29:59 +01:00
										 |  |  | // stateObject represents an Ethereum account which is being modified. | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | // | 
					
						
							|  |  |  | // The usage pattern is as follows: | 
					
						
							|  |  |  | // First you need to obtain a state object. | 
					
						
							|  |  |  | // Account values can be accessed and modified through the object. | 
					
						
							|  |  |  | // Finally, call CommitTrie to write the modified storage trie into a database. | 
					
						
							| 
									
										
										
										
											2017-02-22 23:29:59 +01:00
										 |  |  | type stateObject struct { | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | 	address  common.Address | 
					
						
							|  |  |  | 	addrHash common.Hash // hash of ethereum address of the account | 
					
						
							|  |  |  | 	data     Account | 
					
						
							|  |  |  | 	db       *StateDB | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// DB error. | 
					
						
							|  |  |  | 	// State objects are used by the consensus core and VM which are | 
					
						
							|  |  |  | 	// unable to deal with database-level errors. Any error that occurs | 
					
						
							|  |  |  | 	// during a database read is memoized here and will eventually be returned | 
					
						
							|  |  |  | 	// by StateDB.Commit. | 
					
						
							|  |  |  | 	dbErr error | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Write caches. | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | 	trie Trie // storage trie, which becomes non-nil on first access | 
					
						
							|  |  |  | 	code Code // contract bytecode, which gets set when code is loaded | 
					
						
							| 
									
										
										
										
											2016-10-03 10:48:01 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-12 22:56:07 +03:00
										 |  |  | 	originStorage  Storage // Storage cache of original entries to dedup rewrites, reset for every transaction | 
					
						
							|  |  |  | 	pendingStorage Storage // Storage entries that need to be flushed to disk, at the end of an entire block | 
					
						
							|  |  |  | 	dirtyStorage   Storage // Storage entries that have been modified in the current transaction execution | 
					
						
							|  |  |  | 	fakeStorage    Storage // Fake storage which constructed by caller for debugging purpose. | 
					
						
							| 
									
										
										
										
											2018-09-18 16:24:35 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | 	// Cache flags. | 
					
						
							| 
									
										
										
										
											2016-10-05 22:22:31 +02:00
										 |  |  | 	// When an object is marked suicided it will be delete from the trie | 
					
						
							|  |  |  | 	// during the "update" phase of the state transition. | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | 	dirtyCode bool // true if the code was updated | 
					
						
							| 
									
										
										
										
											2016-10-05 22:22:31 +02:00
										 |  |  | 	suicided  bool | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | 	deleted   bool | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-20 13:36:29 +02:00
										 |  |  | // empty returns whether the account is considered empty. | 
					
						
							| 
									
										
										
										
											2017-02-22 23:29:59 +01:00
										 |  |  | func (s *stateObject) empty() bool { | 
					
						
							| 
									
										
										
										
											2017-02-28 15:09:11 +01:00
										 |  |  | 	return s.data.Nonce == 0 && s.data.Balance.Sign() == 0 && bytes.Equal(s.data.CodeHash, emptyCodeHash) | 
					
						
							| 
									
										
										
										
											2016-10-20 13:36:29 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | // Account is the Ethereum consensus representation of accounts. | 
					
						
							|  |  |  | // These objects are stored in the main account trie. | 
					
						
							|  |  |  | type Account struct { | 
					
						
							|  |  |  | 	Nonce    uint64 | 
					
						
							|  |  |  | 	Balance  *big.Int | 
					
						
							|  |  |  | 	Root     common.Hash // merkle root of the storage trie | 
					
						
							|  |  |  | 	CodeHash []byte | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-04-04 12:40:11 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-04 12:36:02 +02:00
										 |  |  | // newObject creates a state object. | 
					
						
							| 
									
										
										
										
											2017-10-01 21:07:30 +02:00
										 |  |  | func newObject(db *StateDB, address common.Address, data Account) *stateObject { | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | 	if data.Balance == nil { | 
					
						
							|  |  |  | 		data.Balance = new(big.Int) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if data.CodeHash == nil { | 
					
						
							|  |  |  | 		data.CodeHash = emptyCodeHash | 
					
						
							| 
									
										
										
										
											2015-04-04 12:40:11 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-08-12 22:56:07 +03:00
										 |  |  | 	if data.Root == (common.Hash{}) { | 
					
						
							|  |  |  | 		data.Root = emptyRoot | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | 	return &stateObject{ | 
					
						
							| 
									
										
										
										
											2019-08-12 22:56:07 +03:00
										 |  |  | 		db:             db, | 
					
						
							|  |  |  | 		address:        address, | 
					
						
							|  |  |  | 		addrHash:       crypto.Keccak256Hash(address[:]), | 
					
						
							|  |  |  | 		data:           data, | 
					
						
							|  |  |  | 		originStorage:  make(Storage), | 
					
						
							|  |  |  | 		pendingStorage: make(Storage), | 
					
						
							|  |  |  | 		dirtyStorage:   make(Storage), | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | // EncodeRLP implements rlp.Encoder. | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | func (s *stateObject) EncodeRLP(w io.Writer) error { | 
					
						
							|  |  |  | 	return rlp.Encode(w, s.data) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | // setError remembers the first non-nil error it is called with. | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | func (s *stateObject) setError(err error) { | 
					
						
							|  |  |  | 	if s.dbErr == nil { | 
					
						
							|  |  |  | 		s.dbErr = err | 
					
						
							| 
									
										
										
										
											2015-06-17 11:24:40 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | func (s *stateObject) markSuicided() { | 
					
						
							|  |  |  | 	s.suicided = true | 
					
						
							| 
									
										
										
										
											2014-10-16 13:38:21 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | func (s *stateObject) touch() { | 
					
						
							|  |  |  | 	s.db.journal.append(touchChange{ | 
					
						
							|  |  |  | 		account: &s.address, | 
					
						
							| 
									
										
										
										
											2016-11-24 16:24:04 +01:00
										 |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 	if s.address == ripemd { | 
					
						
							| 
									
										
										
										
											2018-03-27 15:13:30 +03:00
										 |  |  | 		// Explicitly put it in the dirty-cache, which is otherwise generated from | 
					
						
							|  |  |  | 		// flattened journals. | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 		s.db.journal.dirty(s.address) | 
					
						
							| 
									
										
										
										
											2016-11-24 16:24:04 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | func (s *stateObject) getTrie(db Database) Trie { | 
					
						
							|  |  |  | 	if s.trie == nil { | 
					
						
							| 
									
										
										
										
											2020-02-05 13:12:09 +01:00
										 |  |  | 		// Try fetching from prefetcher first | 
					
						
							|  |  |  | 		// We don't prefetch empty tries | 
					
						
							|  |  |  | 		if s.data.Root != emptyRoot && s.db.prefetcher != nil { | 
					
						
							|  |  |  | 			// When the miner is creating the pending state, there is no | 
					
						
							|  |  |  | 			// prefetcher | 
					
						
							| 
									
										
										
										
											2021-01-08 15:01:49 +02:00
										 |  |  | 			s.trie = s.db.prefetcher.trie(s.data.Root) | 
					
						
							| 
									
										
										
										
											2020-02-05 13:12:09 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if s.trie == nil { | 
					
						
							|  |  |  | 			var err error | 
					
						
							|  |  |  | 			s.trie, err = db.OpenStorageTrie(s.addrHash, s.data.Root) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				s.trie, _ = db.OpenStorageTrie(s.addrHash, common.Hash{}) | 
					
						
							|  |  |  | 				s.setError(fmt.Errorf("can't create storage trie: %v", err)) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 	return s.trie | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-18 16:24:35 +03:00
										 |  |  | // GetState retrieves a value from the account storage trie. | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | func (s *stateObject) GetState(db Database, key common.Hash) common.Hash { | 
					
						
							| 
									
										
										
										
											2019-08-08 21:44:11 +08:00
										 |  |  | 	// If the fake storage is set, only lookup the state here(in the debugging mode) | 
					
						
							|  |  |  | 	if s.fakeStorage != nil { | 
					
						
							|  |  |  | 		return s.fakeStorage[key] | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-09-18 16:24:35 +03:00
										 |  |  | 	// If we have a dirty value for this state entry, return it | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 	value, dirty := s.dirtyStorage[key] | 
					
						
							| 
									
										
										
										
											2018-09-18 16:24:35 +03:00
										 |  |  | 	if dirty { | 
					
						
							|  |  |  | 		return value | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Otherwise return the entry's original value | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 	return s.GetCommittedState(db, key) | 
					
						
							| 
									
										
										
										
											2018-09-18 16:24:35 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // GetCommittedState retrieves a value from the committed account storage trie. | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | func (s *stateObject) GetCommittedState(db Database, key common.Hash) common.Hash { | 
					
						
							| 
									
										
										
										
											2019-08-08 21:44:11 +08:00
										 |  |  | 	// If the fake storage is set, only lookup the state here(in the debugging mode) | 
					
						
							|  |  |  | 	if s.fakeStorage != nil { | 
					
						
							|  |  |  | 		return s.fakeStorage[key] | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-08-12 22:56:07 +03:00
										 |  |  | 	// If we have a pending write or clean cached, return that | 
					
						
							|  |  |  | 	if value, pending := s.pendingStorage[key]; pending { | 
					
						
							|  |  |  | 		return value | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if value, cached := s.originStorage[key]; cached { | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | 		return value | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-08-06 13:40:28 +03:00
										 |  |  | 	// If no live objects are available, attempt to use snapshots | 
					
						
							|  |  |  | 	var ( | 
					
						
							| 
									
										
										
										
											2020-02-05 13:12:09 +01:00
										 |  |  | 		enc   []byte | 
					
						
							|  |  |  | 		err   error | 
					
						
							|  |  |  | 		meter *time.Duration | 
					
						
							| 
									
										
										
										
											2019-08-06 13:40:28 +03:00
										 |  |  | 	) | 
					
						
							| 
									
										
										
										
											2020-02-05 13:12:09 +01:00
										 |  |  | 	readStart := time.Now() | 
					
						
							|  |  |  | 	if metrics.EnabledExpensive { | 
					
						
							|  |  |  | 		// If the snap is 'under construction', the first lookup may fail. If that | 
					
						
							|  |  |  | 		// happens, we don't want to double-count the time elapsed. Thus this | 
					
						
							|  |  |  | 		// dance with the metering. | 
					
						
							|  |  |  | 		defer func() { | 
					
						
							|  |  |  | 			if meter != nil { | 
					
						
							|  |  |  | 				*meter += time.Since(readStart) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}() | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-08-06 13:40:28 +03:00
										 |  |  | 	if s.db.snap != nil { | 
					
						
							|  |  |  | 		if metrics.EnabledExpensive { | 
					
						
							| 
									
										
										
										
											2020-02-05 13:12:09 +01:00
										 |  |  | 			meter = &s.db.SnapshotStorageReads | 
					
						
							| 
									
										
										
										
											2019-08-06 13:40:28 +03:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-03-04 10:19:53 +02:00
										 |  |  | 		// If the object was destructed in *this* block (and potentially resurrected), | 
					
						
							|  |  |  | 		// the storage has been cleared out, and we should *not* consult the previous | 
					
						
							|  |  |  | 		// snapshot about any storage values. The only possible alternatives are: | 
					
						
							|  |  |  | 		//   1) resurrect happened, and new slot values were set -- those should | 
					
						
							|  |  |  | 		//      have been handles via pendingStorage above. | 
					
						
							|  |  |  | 		//   2) we don't have new values, and can deliver empty response back | 
					
						
							|  |  |  | 		if _, destructed := s.db.snapDestructs[s.addrHash]; destructed { | 
					
						
							|  |  |  | 			return common.Hash{} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-06-08 16:11:37 +03:00
										 |  |  | 		enc, err = s.db.snap.Storage(s.addrHash, crypto.Keccak256Hash(key.Bytes())) | 
					
						
							| 
									
										
										
										
											2019-10-04 15:24:01 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	// If snapshot unavailable or reading from it failed, load from the database | 
					
						
							|  |  |  | 	if s.db.snap == nil || err != nil { | 
					
						
							| 
									
										
										
										
											2020-02-05 13:12:09 +01:00
										 |  |  | 		if meter != nil { | 
					
						
							|  |  |  | 			// If we already spent time checking the snapshot, account for it | 
					
						
							|  |  |  | 			// and reset the readStart | 
					
						
							|  |  |  | 			*meter += time.Since(readStart) | 
					
						
							|  |  |  | 			readStart = time.Now() | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-08-06 13:40:28 +03:00
										 |  |  | 		if metrics.EnabledExpensive { | 
					
						
							| 
									
										
										
										
											2020-02-05 13:12:09 +01:00
										 |  |  | 			meter = &s.db.StorageReads | 
					
						
							| 
									
										
										
										
											2019-08-06 13:40:28 +03:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-06-08 16:11:37 +03:00
										 |  |  | 		if enc, err = s.getTrie(db).TryGet(key.Bytes()); err != nil { | 
					
						
							| 
									
										
										
										
											2019-08-06 13:40:28 +03:00
										 |  |  | 			s.setError(err) | 
					
						
							|  |  |  | 			return common.Hash{} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-08-12 22:56:07 +03:00
										 |  |  | 	var value common.Hash | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | 	if len(enc) > 0 { | 
					
						
							| 
									
										
										
										
											2016-10-05 22:56:07 +02:00
										 |  |  | 		_, content, _, err := rlp.Split(enc) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 			s.setError(err) | 
					
						
							| 
									
										
										
										
											2016-10-05 22:56:07 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		value.SetBytes(content) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 	s.originStorage[key] = value | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 	return value | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | // SetState updates a value in account storage. | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | func (s *stateObject) SetState(db Database, key, value common.Hash) { | 
					
						
							| 
									
										
										
										
											2019-08-08 21:44:11 +08:00
										 |  |  | 	// If the fake storage is set, put the temporary state update here. | 
					
						
							|  |  |  | 	if s.fakeStorage != nil { | 
					
						
							|  |  |  | 		s.fakeStorage[key] = value | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-09-18 16:24:35 +03:00
										 |  |  | 	// If the new value is the same as old, don't set | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 	prev := s.GetState(db, key) | 
					
						
							| 
									
										
										
										
											2018-09-18 16:24:35 +03:00
										 |  |  | 	if prev == value { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// New value is different, update and journal the change | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 	s.db.journal.append(storageChange{ | 
					
						
							|  |  |  | 		account:  &s.address, | 
					
						
							| 
									
										
										
										
											2016-10-04 12:36:02 +02:00
										 |  |  | 		key:      key, | 
					
						
							| 
									
										
										
										
											2018-08-11 23:03:54 +02:00
										 |  |  | 		prevalue: prev, | 
					
						
							| 
									
										
										
										
											2016-10-04 12:36:02 +02:00
										 |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 	s.setState(key, value) | 
					
						
							| 
									
										
										
										
											2016-10-04 12:36:02 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-08 21:44:11 +08:00
										 |  |  | // SetStorage replaces the entire state storage with the given one. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // After this function is called, all original state will be ignored and state | 
					
						
							|  |  |  | // lookup only happens in the fake state storage. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // Note this function should only be used for debugging purpose. | 
					
						
							|  |  |  | func (s *stateObject) SetStorage(storage map[common.Hash]common.Hash) { | 
					
						
							|  |  |  | 	// Allocate fake storage if it's nil. | 
					
						
							|  |  |  | 	if s.fakeStorage == nil { | 
					
						
							|  |  |  | 		s.fakeStorage = make(Storage) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for key, value := range storage { | 
					
						
							|  |  |  | 		s.fakeStorage[key] = value | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Don't bother journal since this function should only be used for | 
					
						
							|  |  |  | 	// debugging and the `fake` storage won't be committed to database. | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | func (s *stateObject) setState(key, value common.Hash) { | 
					
						
							|  |  |  | 	s.dirtyStorage[key] = value | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-12 22:56:07 +03:00
										 |  |  | // finalise moves all dirty storage slots into the pending area to be hashed or | 
					
						
							|  |  |  | // committed later. It is invoked at the end of every transaction. | 
					
						
							| 
									
										
										
										
											2021-01-08 15:01:49 +02:00
										 |  |  | func (s *stateObject) finalise(prefetch bool) { | 
					
						
							|  |  |  | 	slotsToPrefetch := make([][]byte, 0, len(s.dirtyStorage)) | 
					
						
							| 
									
										
										
										
											2019-08-12 22:56:07 +03:00
										 |  |  | 	for key, value := range s.dirtyStorage { | 
					
						
							|  |  |  | 		s.pendingStorage[key] = value | 
					
						
							| 
									
										
										
										
											2021-01-08 15:01:49 +02:00
										 |  |  | 		if value != s.originStorage[key] { | 
					
						
							|  |  |  | 			slotsToPrefetch = append(slotsToPrefetch, common.CopyBytes(key[:])) // Copy needed for closure | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-02-05 13:12:09 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-01-08 15:01:49 +02:00
										 |  |  | 	if s.db.prefetcher != nil && prefetch && len(slotsToPrefetch) > 0 && s.data.Root != emptyRoot { | 
					
						
							|  |  |  | 		s.db.prefetcher.prefetch(s.data.Root, slotsToPrefetch) | 
					
						
							| 
									
										
										
										
											2019-08-12 22:56:07 +03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if len(s.dirtyStorage) > 0 { | 
					
						
							|  |  |  | 		s.dirtyStorage = make(Storage) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | // updateTrie writes cached storage modifications into the object's storage trie. | 
					
						
							| 
									
										
										
										
											2020-02-03 16:28:30 +01:00
										 |  |  | // It will return nil if the trie has not been loaded and no changes have been made | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | func (s *stateObject) updateTrie(db Database) Trie { | 
					
						
							| 
									
										
										
										
											2019-08-12 22:56:07 +03:00
										 |  |  | 	// Make sure all dirty slots are finalized into the pending storage area | 
					
						
							| 
									
										
										
										
											2021-01-08 15:01:49 +02:00
										 |  |  | 	s.finalise(false) // Don't prefetch any more, pull directly if need be | 
					
						
							| 
									
										
										
										
											2020-02-03 16:28:30 +01:00
										 |  |  | 	if len(s.pendingStorage) == 0 { | 
					
						
							|  |  |  | 		return s.trie | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-10-12 21:02:38 +08:00
										 |  |  | 	// Track the amount of time wasted on updating the storage trie | 
					
						
							| 
									
										
										
										
											2019-03-25 10:01:18 +02:00
										 |  |  | 	if metrics.EnabledExpensive { | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 		defer func(start time.Time) { s.db.StorageUpdates += time.Since(start) }(time.Now()) | 
					
						
							| 
									
										
										
										
											2019-03-25 10:01:18 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-02-05 13:12:09 +01:00
										 |  |  | 	// The snapshot storage map for the object | 
					
						
							| 
									
										
										
										
											2019-08-06 13:40:28 +03:00
										 |  |  | 	var storage map[common.Hash][]byte | 
					
						
							| 
									
										
										
										
											2019-08-12 22:56:07 +03:00
										 |  |  | 	// Insert all the pending updates into the trie | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 	tr := s.getTrie(db) | 
					
						
							| 
									
										
										
										
											2020-02-05 13:12:09 +01:00
										 |  |  | 	hasher := s.db.hasher | 
					
						
							| 
									
										
										
										
											2021-01-08 15:01:49 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	usedStorage := make([][]byte, 0, len(s.pendingStorage)) | 
					
						
							| 
									
										
										
										
											2019-08-12 22:56:07 +03:00
										 |  |  | 	for key, value := range s.pendingStorage { | 
					
						
							| 
									
										
										
										
											2018-09-18 16:24:35 +03:00
										 |  |  | 		// Skip noop changes, persist actual changes | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 		if value == s.originStorage[key] { | 
					
						
							| 
									
										
										
										
											2018-09-18 16:24:35 +03:00
										 |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 		s.originStorage[key] = value | 
					
						
							| 
									
										
										
										
											2018-09-18 16:24:35 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-06 13:40:28 +03:00
										 |  |  | 		var v []byte | 
					
						
							| 
									
										
										
										
											2015-06-17 11:24:40 +02:00
										 |  |  | 		if (value == common.Hash{}) { | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 			s.setError(tr.TryDelete(key[:])) | 
					
						
							| 
									
										
										
										
											2019-08-06 13:40:28 +03:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 			// Encoding []byte cannot fail, ok to ignore the error. | 
					
						
							|  |  |  | 			v, _ = rlp.EncodeToBytes(common.TrimLeftZeroes(value[:])) | 
					
						
							|  |  |  | 			s.setError(tr.TryUpdate(key[:], v)) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// If state snapshotting is active, cache the data til commit | 
					
						
							| 
									
										
										
										
											2020-02-05 13:12:09 +01:00
										 |  |  | 		if s.db.snap != nil { | 
					
						
							|  |  |  | 			if storage == nil { | 
					
						
							|  |  |  | 				// Retrieve the old storage map, if available, create a new one otherwise | 
					
						
							|  |  |  | 				if storage = s.db.snapStorage[s.addrHash]; storage == nil { | 
					
						
							|  |  |  | 					storage = make(map[common.Hash][]byte) | 
					
						
							|  |  |  | 					s.db.snapStorage[s.addrHash] = storage | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			storage[crypto.HashData(hasher, key[:])] = v // v will be nil if value is 0x00 | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-01-08 15:01:49 +02:00
										 |  |  | 		usedStorage = append(usedStorage, common.CopyBytes(key[:])) // Copy needed for closure | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if s.db.prefetcher != nil { | 
					
						
							|  |  |  | 		s.db.prefetcher.used(s.data.Root, usedStorage) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-08-12 22:56:07 +03:00
										 |  |  | 	if len(s.pendingStorage) > 0 { | 
					
						
							|  |  |  | 		s.pendingStorage = make(Storage) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-19 12:09:04 +02:00
										 |  |  | 	return tr | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | // UpdateRoot sets the trie root to the current root hash of | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | func (s *stateObject) updateRoot(db Database) { | 
					
						
							| 
									
										
										
										
											2020-02-03 16:28:30 +01:00
										 |  |  | 	// If nothing changed, don't bother with hashing anything | 
					
						
							|  |  |  | 	if s.updateTrie(db) == nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-10-12 21:02:38 +08:00
										 |  |  | 	// Track the amount of time wasted on hashing the storage trie | 
					
						
							| 
									
										
										
										
											2019-03-25 10:01:18 +02:00
										 |  |  | 	if metrics.EnabledExpensive { | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 		defer func(start time.Time) { s.db.StorageHashes += time.Since(start) }(time.Now()) | 
					
						
							| 
									
										
										
										
											2019-03-25 10:01:18 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 	s.data.Root = s.trie.Hash() | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-05 09:56:45 +07:00
										 |  |  | // CommitTrie the storage trie of the object to db. | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | // This updates the trie root. | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | func (s *stateObject) CommitTrie(db Database) error { | 
					
						
							| 
									
										
										
										
											2020-02-03 16:28:30 +01:00
										 |  |  | 	// If nothing changed, don't bother with hashing anything | 
					
						
							|  |  |  | 	if s.updateTrie(db) == nil { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 	if s.dbErr != nil { | 
					
						
							|  |  |  | 		return s.dbErr | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-10-12 21:02:38 +08:00
										 |  |  | 	// Track the amount of time wasted on committing the storage trie | 
					
						
							| 
									
										
										
										
											2019-03-25 10:01:18 +02:00
										 |  |  | 	if metrics.EnabledExpensive { | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 		defer func(start time.Time) { s.db.StorageCommits += time.Since(start) }(time.Now()) | 
					
						
							| 
									
										
										
										
											2019-03-25 10:01:18 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 	root, err := s.trie.Commit(nil) | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | 	if err == nil { | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 		s.data.Root = root | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return err | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-19 08:54:21 +02:00
										 |  |  | // AddBalance adds amount to s's balance. | 
					
						
							| 
									
										
										
										
											2016-10-20 13:36:29 +02:00
										 |  |  | // It is used to add funds to the destination account of a transfer. | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | func (s *stateObject) AddBalance(amount *big.Int) { | 
					
						
							| 
									
										
										
										
											2020-08-19 08:54:21 +02:00
										 |  |  | 	// EIP161: We must check emptiness for the objects such that the account | 
					
						
							| 
									
										
										
										
											2016-10-20 13:36:29 +02:00
										 |  |  | 	// clearing (0,0,0 objects) can take effect. | 
					
						
							| 
									
										
										
										
											2017-02-28 15:09:11 +01:00
										 |  |  | 	if amount.Sign() == 0 { | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 		if s.empty() { | 
					
						
							|  |  |  | 			s.touch() | 
					
						
							| 
									
										
										
										
											2016-11-24 16:24:04 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-09-26 01:25:50 -04:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 	s.SetBalance(new(big.Int).Add(s.Balance(), amount)) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-19 08:54:21 +02:00
										 |  |  | // SubBalance removes amount from s's balance. | 
					
						
							| 
									
										
										
										
											2016-10-20 13:36:29 +02:00
										 |  |  | // It is used to remove funds from the origin account of a transfer. | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | func (s *stateObject) SubBalance(amount *big.Int) { | 
					
						
							| 
									
										
										
										
											2017-02-28 15:09:11 +01:00
										 |  |  | 	if amount.Sign() == 0 { | 
					
						
							| 
									
										
										
										
											2016-09-26 01:25:50 -04:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 	s.SetBalance(new(big.Int).Sub(s.Balance(), amount)) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | func (s *stateObject) SetBalance(amount *big.Int) { | 
					
						
							|  |  |  | 	s.db.journal.append(balanceChange{ | 
					
						
							|  |  |  | 		account: &s.address, | 
					
						
							|  |  |  | 		prev:    new(big.Int).Set(s.data.Balance), | 
					
						
							| 
									
										
										
										
											2016-10-04 12:36:02 +02:00
										 |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 	s.setBalance(amount) | 
					
						
							| 
									
										
										
										
											2016-10-04 12:36:02 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | func (s *stateObject) setBalance(amount *big.Int) { | 
					
						
							|  |  |  | 	s.data.Balance = amount | 
					
						
							| 
									
										
										
										
											2015-02-26 18:39:05 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | // Return the gas back to the origin. Used by the Virtual machine or Closures | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | func (s *stateObject) ReturnGas(gas *big.Int) {} | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | func (s *stateObject) deepCopy(db *StateDB) *stateObject { | 
					
						
							|  |  |  | 	stateObject := newObject(db, s.address, s.data) | 
					
						
							|  |  |  | 	if s.trie != nil { | 
					
						
							|  |  |  | 		stateObject.trie = db.db.CopyTrie(s.trie) | 
					
						
							| 
									
										
										
										
											2017-04-19 12:09:04 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 	stateObject.code = s.code | 
					
						
							|  |  |  | 	stateObject.dirtyStorage = s.dirtyStorage.Copy() | 
					
						
							|  |  |  | 	stateObject.originStorage = s.originStorage.Copy() | 
					
						
							| 
									
										
										
										
											2019-09-20 17:55:44 +08:00
										 |  |  | 	stateObject.pendingStorage = s.pendingStorage.Copy() | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 	stateObject.suicided = s.suicided | 
					
						
							|  |  |  | 	stateObject.dirtyCode = s.dirtyCode | 
					
						
							|  |  |  | 	stateObject.deleted = s.deleted | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 	return stateObject | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // Attribute accessors | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Returns the address of the contract/account | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | func (s *stateObject) Address() common.Address { | 
					
						
							|  |  |  | 	return s.address | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | // Code returns the contract code associated with this object, if any. | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | func (s *stateObject) Code(db Database) []byte { | 
					
						
							|  |  |  | 	if s.code != nil { | 
					
						
							|  |  |  | 		return s.code | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 	if bytes.Equal(s.CodeHash(), emptyCodeHash) { | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 	code, err := db.ContractCode(s.addrHash, common.BytesToHash(s.CodeHash())) | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 		s.setError(fmt.Errorf("can't load code hash %x: %v", s.CodeHash(), err)) | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 	s.code = code | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | 	return code | 
					
						
							| 
									
										
										
										
											2014-11-03 23:45:44 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-11 10:14:49 +03:00
										 |  |  | // CodeSize returns the size of the contract code associated with this object, | 
					
						
							| 
									
										
										
										
											2020-08-19 08:54:21 +02:00
										 |  |  | // or zero if none. This method is an almost mirror of Code, but uses a cache | 
					
						
							| 
									
										
										
										
											2020-05-11 10:14:49 +03:00
										 |  |  | // inside the database to avoid loading codes seen recently. | 
					
						
							|  |  |  | func (s *stateObject) CodeSize(db Database) int { | 
					
						
							|  |  |  | 	if s.code != nil { | 
					
						
							|  |  |  | 		return len(s.code) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if bytes.Equal(s.CodeHash(), emptyCodeHash) { | 
					
						
							|  |  |  | 		return 0 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	size, err := db.ContractCodeSize(s.addrHash, common.BytesToHash(s.CodeHash())) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		s.setError(fmt.Errorf("can't load code size %x: %v", s.CodeHash(), err)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return size | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | func (s *stateObject) SetCode(codeHash common.Hash, code []byte) { | 
					
						
							|  |  |  | 	prevcode := s.Code(s.db.db) | 
					
						
							|  |  |  | 	s.db.journal.append(codeChange{ | 
					
						
							|  |  |  | 		account:  &s.address, | 
					
						
							|  |  |  | 		prevhash: s.CodeHash(), | 
					
						
							| 
									
										
										
										
											2016-10-04 12:36:02 +02:00
										 |  |  | 		prevcode: prevcode, | 
					
						
							|  |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 	s.setCode(codeHash, code) | 
					
						
							| 
									
										
										
										
											2016-10-04 12:36:02 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | func (s *stateObject) setCode(codeHash common.Hash, code []byte) { | 
					
						
							|  |  |  | 	s.code = code | 
					
						
							|  |  |  | 	s.data.CodeHash = codeHash[:] | 
					
						
							|  |  |  | 	s.dirtyCode = true | 
					
						
							| 
									
										
										
										
											2015-02-20 14:19:34 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | func (s *stateObject) SetNonce(nonce uint64) { | 
					
						
							|  |  |  | 	s.db.journal.append(nonceChange{ | 
					
						
							|  |  |  | 		account: &s.address, | 
					
						
							|  |  |  | 		prev:    s.data.Nonce, | 
					
						
							| 
									
										
										
										
											2016-10-04 12:36:02 +02:00
										 |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 	s.setNonce(nonce) | 
					
						
							| 
									
										
										
										
											2016-10-04 12:36:02 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | func (s *stateObject) setNonce(nonce uint64) { | 
					
						
							|  |  |  | 	s.data.Nonce = nonce | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | func (s *stateObject) CodeHash() []byte { | 
					
						
							|  |  |  | 	return s.data.CodeHash | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | func (s *stateObject) Balance() *big.Int { | 
					
						
							|  |  |  | 	return s.data.Balance | 
					
						
							| 
									
										
										
										
											2015-02-20 14:19:34 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | func (s *stateObject) Nonce() uint64 { | 
					
						
							|  |  |  | 	return s.data.Nonce | 
					
						
							| 
									
										
										
										
											2014-12-03 17:06:54 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 23:29:59 +01:00
										 |  |  | // Never called, but must be present to allow stateObject to be used | 
					
						
							| 
									
										
										
										
											2015-11-27 15:40:29 +01:00
										 |  |  | // as a vm.Account interface that also satisfies the vm.ContractRef | 
					
						
							|  |  |  | // interface. Interfaces are awesome. | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | func (s *stateObject) Value() *big.Int { | 
					
						
							| 
									
										
										
										
											2017-02-22 23:29:59 +01:00
										 |  |  | 	panic("Value on stateObject should never be called") | 
					
						
							| 
									
										
										
										
											2015-06-10 12:57:37 +02:00
										 |  |  | } |