mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-21 12:16:44 +00:00
add codes origin
This commit is contained in:
parent
b9d45acf90
commit
d11a86f275
4 changed files with 56 additions and 20 deletions
|
|
@ -423,7 +423,7 @@ func (s *stateObject) commitStorage(op *accountUpdate) {
|
|||
//
|
||||
// Note, commit may run concurrently across all the state objects. Do not assume
|
||||
// thread-safe access to the statedb.
|
||||
func (s *stateObject) commit() (*accountUpdate, *trienode.NodeSet, error) {
|
||||
func (s *stateObject) commit(resolveCode bool) (*accountUpdate, *trienode.NodeSet, error) {
|
||||
// commit the account metadata changes
|
||||
op := &accountUpdate{
|
||||
address: s.address,
|
||||
|
|
@ -439,6 +439,20 @@ func (s *stateObject) commit() (*accountUpdate, *trienode.NodeSet, error) {
|
|||
blob: s.code,
|
||||
}
|
||||
s.dirtyCode = false // reset the dirty flag
|
||||
|
||||
// retrieve the original code if requested and the code was not empty
|
||||
if resolveCode && s.origin != nil && !bytes.Equal(s.origin.CodeHash, types.EmptyCodeHash.Bytes()) {
|
||||
code, err := s.db.reader.Code(s.address, common.BytesToHash(s.origin.CodeHash))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
op.codeOrigin = &contractCode{
|
||||
hash: common.BytesToHash(s.origin.CodeHash),
|
||||
blob: code,
|
||||
exists: true, // the code exists before the update
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// Commit storage changes and the associated storage trie
|
||||
s.commitStorage(op)
|
||||
|
|
|
|||
|
|
@ -1162,7 +1162,7 @@ func (s *StateDB) GetTrie() Trie {
|
|||
|
||||
// commit gathers the state mutations accumulated along with the associated
|
||||
// trie changes, resetting all internal flags with the new state as the base.
|
||||
func (s *StateDB) commit(deleteEmptyObjects bool, noStorageWiping bool, blockNumber uint64) (*stateUpdate, error) {
|
||||
func (s *StateDB) commit(deleteEmptyObjects bool, noStorageWiping bool, blockNumber uint64, resolveCode bool) (*stateUpdate, error) {
|
||||
// Short circuit in case any database failure occurred earlier.
|
||||
if s.dbErr != nil {
|
||||
return nil, fmt.Errorf("commit aborted due to earlier error: %v", s.dbErr)
|
||||
|
|
@ -1272,7 +1272,7 @@ func (s *StateDB) commit(deleteEmptyObjects bool, noStorageWiping bool, blockNum
|
|||
// Run the storage updates concurrently to one another
|
||||
workers.Go(func() error {
|
||||
// Write any storage changes in the state object to its storage trie
|
||||
update, set, err := obj.commit()
|
||||
update, set, err := obj.commit(resolveCode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -1319,13 +1319,13 @@ func (s *StateDB) commit(deleteEmptyObjects bool, noStorageWiping bool, blockNum
|
|||
|
||||
// commitAndFlush is a wrapper of commit which also commits the state mutations
|
||||
// to the configured data stores.
|
||||
func (s *StateDB) commitAndFlush(block uint64, deleteEmptyObjects bool, noStorageWiping bool, dedupCode bool) (*stateUpdate, error) {
|
||||
ret, err := s.commit(deleteEmptyObjects, noStorageWiping, block)
|
||||
func (s *StateDB) commitAndFlush(block uint64, deleteEmptyObjects bool, noStorageWiping bool, resolveCode bool) (*stateUpdate, error) {
|
||||
ret, err := s.commit(deleteEmptyObjects, noStorageWiping, block, resolveCode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if dedupCode {
|
||||
if resolveCode {
|
||||
ret.markCodeExistence(s.reader)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,11 +52,12 @@ type accountDelete struct {
|
|||
|
||||
// accountUpdate represents an operation for updating an Ethereum account.
|
||||
type accountUpdate struct {
|
||||
address common.Address // address is the unique account identifier
|
||||
data []byte // data is the slim-RLP encoded account data.
|
||||
origin []byte // origin is the original value of account data in slim-RLP encoding.
|
||||
code *contractCode // code represents mutated contract code; nil means it's not modified.
|
||||
storages map[common.Hash][]byte // storages stores mutated slots in prefix-zero-trimmed RLP format.
|
||||
address common.Address // address is the unique account identifier
|
||||
data []byte // data is the slim-RLP encoded account data.
|
||||
origin []byte // origin is the original value of account data in slim-RLP encoding.
|
||||
code *contractCode // code represents mutated contract code; nil means it's not modified.
|
||||
codeOrigin *contractCode // codeOrigin is the original value of contract code; nil means it does not exist before the update.
|
||||
storages map[common.Hash][]byte // storages stores mutated slots in prefix-zero-trimmed RLP format.
|
||||
|
||||
// storagesOriginByKey and storagesOriginByHash both store the original values
|
||||
// of mutated slots in prefix-zero-trimmed RLP format. The difference is that
|
||||
|
|
@ -88,8 +89,9 @@ type stateUpdate struct {
|
|||
storagesOrigin map[common.Address]map[common.Hash][]byte
|
||||
rawStorageKey bool
|
||||
|
||||
codes map[common.Address]*contractCode // codes contains the set of dirty codes
|
||||
nodes *trienode.MergedNodeSet // Aggregated dirty nodes caused by state changes
|
||||
codes map[common.Address]*contractCode // codes contains the set of dirty codes
|
||||
codesOrigin map[common.Address]*contractCode // codesOrigin contains the original code data of the mutated accounts
|
||||
nodes *trienode.MergedNodeSet // Aggregated dirty nodes caused by state changes
|
||||
}
|
||||
|
||||
// empty returns a flag indicating the state transition is empty or not.
|
||||
|
|
@ -110,6 +112,7 @@ func newStateUpdate(rawStorageKey bool, originRoot common.Hash, root common.Hash
|
|||
storages = make(map[common.Hash]map[common.Hash][]byte)
|
||||
storagesOrigin = make(map[common.Address]map[common.Hash][]byte)
|
||||
codes = make(map[common.Address]*contractCode)
|
||||
codesOrigin = make(map[common.Address]*contractCode)
|
||||
)
|
||||
// Since some accounts might be destroyed and recreated within the same
|
||||
// block, deletions must be aggregated first.
|
||||
|
|
@ -133,6 +136,9 @@ func newStateUpdate(rawStorageKey bool, originRoot common.Hash, root common.Hash
|
|||
if op.code != nil {
|
||||
codes[addr] = op.code
|
||||
}
|
||||
if op.codeOrigin != nil {
|
||||
codesOrigin[addr] = op.codeOrigin
|
||||
}
|
||||
accounts[addrHash] = op.data
|
||||
|
||||
// Aggregate the account original value. If the account is already
|
||||
|
|
@ -179,6 +185,7 @@ func newStateUpdate(rawStorageKey bool, originRoot common.Hash, root common.Hash
|
|||
storagesOrigin: storagesOrigin,
|
||||
rawStorageKey: rawStorageKey,
|
||||
codes: codes,
|
||||
codesOrigin: codesOrigin,
|
||||
nodes: nodes,
|
||||
}
|
||||
}
|
||||
|
|
@ -311,11 +318,21 @@ func (sc *stateUpdate) ToTracingUpdate() (*tracing.StateUpdate, error) {
|
|||
}
|
||||
|
||||
for addr, code := range sc.codes {
|
||||
update.CodeChanges[addr] = &tracing.CodeChange{
|
||||
Hash: code.hash,
|
||||
Code: code.blob,
|
||||
Exists: code.exists,
|
||||
change := &tracing.CodeChange{
|
||||
New: &tracing.ContractCode{
|
||||
Hash: code.hash,
|
||||
Code: code.blob,
|
||||
Exists: code.exists,
|
||||
},
|
||||
}
|
||||
if origin, ok := sc.codesOrigin[addr]; ok {
|
||||
change.Prev = &tracing.ContractCode{
|
||||
Hash: origin.hash,
|
||||
Code: origin.blob,
|
||||
Exists: origin.exists,
|
||||
}
|
||||
}
|
||||
update.CodeChanges[addr] = change
|
||||
}
|
||||
|
||||
if sc.nodes != nil {
|
||||
|
|
|
|||
|
|
@ -109,11 +109,16 @@ type StorageChange struct {
|
|||
New common.Hash // new value (zero if slot was deleted)
|
||||
}
|
||||
|
||||
// CodeChange represents a contract code deployment or change.
|
||||
type CodeChange struct {
|
||||
type ContractCode struct {
|
||||
Hash common.Hash
|
||||
Code []byte
|
||||
Exists bool // true if the code already deployed before
|
||||
Exists bool // true if the code was existent
|
||||
}
|
||||
|
||||
// CodeChange represents a change in contract code of an account.
|
||||
type CodeChange struct {
|
||||
Prev *ContractCode // nil if no code existed before
|
||||
New *ContractCode
|
||||
}
|
||||
|
||||
type TrieNodeChange struct {
|
||||
|
|
|
|||
Loading…
Reference in a new issue