| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-18 16:24:35 +03:00
										 |  |  | 	originStorage Storage // Storage cache of original entries to dedup rewrites | 
					
						
							| 
									
										
										
										
											2016-10-03 10:48:01 +03:00
										 |  |  | 	dirtyStorage  Storage // Storage entries that need to be flushed to disk | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | 	return &stateObject{ | 
					
						
							|  |  |  | 		db:            db, | 
					
						
							|  |  |  | 		address:       address, | 
					
						
							|  |  |  | 		addrHash:      crypto.Keccak256Hash(address[:]), | 
					
						
							|  |  |  | 		data:          data, | 
					
						
							| 
									
										
										
										
											2018-09-18 16:24:35 +03:00
										 |  |  | 		originStorage: make(Storage), | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | 		dirtyStorage:  make(Storage), | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											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 { | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | 		var err error | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 		s.trie, err = db.OpenStorageTrie(s.addrHash, s.data.Root) | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 			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 { | 
					
						
							| 
									
										
										
										
											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 { | 
					
						
							| 
									
										
										
										
											2018-09-18 16:24:35 +03:00
										 |  |  | 	// If we have the original value cached, return that | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 	value, cached := s.originStorage[key] | 
					
						
							| 
									
										
										
										
											2018-09-18 16:24:35 +03:00
										 |  |  | 	if cached { | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | 		return value | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-03-25 10:01:18 +02:00
										 |  |  | 	// Track the amount of time wasted on reading the storge trie | 
					
						
							|  |  |  | 	if metrics.EnabledExpensive { | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 		defer func(start time.Time) { s.db.StorageReads += time.Since(start) }(time.Now()) | 
					
						
							| 
									
										
										
										
											2019-03-25 10:01:18 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-09-18 16:24:35 +03:00
										 |  |  | 	// Otherwise load the value from the database | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 	enc, err := s.getTrie(db).TryGet(key[:]) | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 		s.setError(err) | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | 		return common.Hash{} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	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) { | 
					
						
							| 
									
										
										
										
											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-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
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | // updateTrie writes cached storage modifications into the object's storage trie. | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | func (s *stateObject) updateTrie(db Database) Trie { | 
					
						
							| 
									
										
										
										
											2019-03-25 10:01:18 +02:00
										 |  |  | 	// Track the amount of time wasted on updating the storge trie | 
					
						
							|  |  |  | 	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
										 |  |  | 	} | 
					
						
							|  |  |  | 	// Update all the dirty slots in the trie | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 	tr := s.getTrie(db) | 
					
						
							|  |  |  | 	for key, value := range s.dirtyStorage { | 
					
						
							|  |  |  | 		delete(s.dirtyStorage, key) | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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[:])) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | 		// Encoding []byte cannot fail, ok to ignore the error. | 
					
						
							|  |  |  | 		v, _ := rlp.EncodeToBytes(bytes.TrimLeft(value[:], "\x00")) | 
					
						
							| 
									
										
										
										
											2019-05-26 05:52:10 +08:00
										 |  |  | 		s.setError(tr.TryUpdate(key[:], v)) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											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) { | 
					
						
							|  |  |  | 	s.updateTrie(db) | 
					
						
							| 
									
										
										
										
											2019-03-25 10:01:18 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Track the amount of time wasted on hashing the storge trie | 
					
						
							|  |  |  | 	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 { | 
					
						
							|  |  |  | 	s.updateTrie(db) | 
					
						
							|  |  |  | 	if s.dbErr != nil { | 
					
						
							|  |  |  | 		return s.dbErr | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-03-25 10:01:18 +02:00
										 |  |  | 	// Track the amount of time wasted on committing the storge trie | 
					
						
							|  |  |  | 	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 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-20 13:36:29 +02:00
										 |  |  | // AddBalance removes amount from c's balance. | 
					
						
							|  |  |  | // 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) { | 
					
						
							| 
									
										
										
										
											2016-10-20 13:36:29 +02:00
										 |  |  | 	// EIP158: We must check emptiness for the objects such that the account | 
					
						
							|  |  |  | 	// 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
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-20 13:36:29 +02:00
										 |  |  | // SubBalance removes amount from c's balance. | 
					
						
							|  |  |  | // 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() | 
					
						
							|  |  |  | 	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
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  | } |