Patch for concurrent iterator & others (onto v1.11.6) #386
@ -113,7 +113,7 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD
|
|||||||
// Validate the state root against the received state root and throw
|
// Validate the state root against the received state root and throw
|
||||||
// an error if they don't match.
|
// an error if they don't match.
|
||||||
if root := statedb.IntermediateRoot(v.config.IsEIP158(header.Number)); header.Root != root {
|
if root := statedb.IntermediateRoot(v.config.IsEIP158(header.Number)); header.Root != root {
|
||||||
return fmt.Errorf("invalid merkle root (remote: %x local: %x)", header.Root, root)
|
return fmt.Errorf("invalid merkle root (remote: %x local: %x) dberr: %w", header.Root, root, statedb.Error())
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,6 @@ func (s Storage) String() (str string) {
|
|||||||
for key, value := range s {
|
for key, value := range s {
|
||||||
str += fmt.Sprintf("%X : %X\n", key, value)
|
str += fmt.Sprintf("%X : %X\n", key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,7 +51,6 @@ func (s Storage) Copy() Storage {
|
|||||||
for key, value := range s {
|
for key, value := range s {
|
||||||
cpy[key] = value
|
cpy[key] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
return cpy
|
return cpy
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,13 +66,6 @@ type stateObject struct {
|
|||||||
data types.StateAccount
|
data types.StateAccount
|
||||||
db *StateDB
|
db *StateDB
|
||||||
|
|
||||||
// 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.
|
// Write caches.
|
||||||
trie Trie // storage trie, which becomes non-nil on first access
|
trie Trie // storage trie, which becomes non-nil on first access
|
||||||
code Code // contract bytecode, which gets set when code is loaded
|
code Code // contract bytecode, which gets set when code is loaded
|
||||||
@ -84,7 +75,7 @@ type stateObject struct {
|
|||||||
dirtyStorage Storage // Storage entries that have been modified in the current transaction execution
|
dirtyStorage Storage // Storage entries that have been modified in the current transaction execution
|
||||||
|
|
||||||
// Cache flags.
|
// Cache flags.
|
||||||
// When an object is marked suicided it will be delete from the trie
|
// When an object is marked suicided it will be deleted from the trie
|
||||||
// during the "update" phase of the state transition.
|
// during the "update" phase of the state transition.
|
||||||
dirtyCode bool // true if the code was updated
|
dirtyCode bool // true if the code was updated
|
||||||
suicided bool
|
suicided bool
|
||||||
@ -123,13 +114,6 @@ func (s *stateObject) EncodeRLP(w io.Writer) error {
|
|||||||
return rlp.Encode(w, &s.data)
|
return rlp.Encode(w, &s.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// setError remembers the first non-nil error it is called with.
|
|
||||||
func (s *stateObject) setError(err error) {
|
|
||||||
if s.dbErr == nil {
|
|
||||||
s.dbErr = err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stateObject) markSuicided() {
|
func (s *stateObject) markSuicided() {
|
||||||
s.suicided = true
|
s.suicided = true
|
||||||
}
|
}
|
||||||
@ -214,7 +198,7 @@ func (s *stateObject) GetCommittedState(db Database, key common.Hash) common.Has
|
|||||||
start := time.Now()
|
start := time.Now()
|
||||||
tr, err := s.getTrie(db)
|
tr, err := s.getTrie(db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.setError(err)
|
s.db.setError(err)
|
||||||
return common.Hash{}
|
return common.Hash{}
|
||||||
}
|
}
|
||||||
enc, err = tr.TryGet(key.Bytes())
|
enc, err = tr.TryGet(key.Bytes())
|
||||||
@ -222,7 +206,7 @@ func (s *stateObject) GetCommittedState(db Database, key common.Hash) common.Has
|
|||||||
s.db.StorageReads += time.Since(start)
|
s.db.StorageReads += time.Since(start)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.setError(err)
|
s.db.setError(err)
|
||||||
return common.Hash{}
|
return common.Hash{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -230,7 +214,7 @@ func (s *stateObject) GetCommittedState(db Database, key common.Hash) common.Has
|
|||||||
if len(enc) > 0 {
|
if len(enc) > 0 {
|
||||||
_, content, _, err := rlp.Split(enc)
|
_, content, _, err := rlp.Split(enc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.setError(err)
|
s.db.setError(err)
|
||||||
}
|
}
|
||||||
value.SetBytes(content)
|
value.SetBytes(content)
|
||||||
}
|
}
|
||||||
@ -296,7 +280,7 @@ func (s *stateObject) updateTrie(db Database) (Trie, error) {
|
|||||||
)
|
)
|
||||||
tr, err := s.getTrie(db)
|
tr, err := s.getTrie(db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.setError(err)
|
s.db.setError(err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// Insert all the pending updates into the trie
|
// Insert all the pending updates into the trie
|
||||||
@ -311,7 +295,7 @@ func (s *stateObject) updateTrie(db Database) (Trie, error) {
|
|||||||
var v []byte
|
var v []byte
|
||||||
if (value == common.Hash{}) {
|
if (value == common.Hash{}) {
|
||||||
if err := tr.TryDelete(key[:]); err != nil {
|
if err := tr.TryDelete(key[:]); err != nil {
|
||||||
s.setError(err)
|
s.db.setError(err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
s.db.StorageDeleted += 1
|
s.db.StorageDeleted += 1
|
||||||
@ -319,7 +303,7 @@ func (s *stateObject) updateTrie(db Database) (Trie, error) {
|
|||||||
// Encoding []byte cannot fail, ok to ignore the error.
|
// Encoding []byte cannot fail, ok to ignore the error.
|
||||||
v, _ = rlp.EncodeToBytes(common.TrimLeftZeroes(value[:]))
|
v, _ = rlp.EncodeToBytes(common.TrimLeftZeroes(value[:]))
|
||||||
if err := tr.TryUpdate(key[:], v); err != nil {
|
if err := tr.TryUpdate(key[:], v); err != nil {
|
||||||
s.setError(err)
|
s.db.setError(err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
s.db.StorageUpdated += 1
|
s.db.StorageUpdated += 1
|
||||||
@ -351,7 +335,6 @@ func (s *stateObject) updateTrie(db Database) (Trie, error) {
|
|||||||
func (s *stateObject) updateRoot(db Database) {
|
func (s *stateObject) updateRoot(db Database) {
|
||||||
tr, err := s.updateTrie(db)
|
tr, err := s.updateTrie(db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.setError(fmt.Errorf("updateRoot (%x) error: %w", s.address, err))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// If nothing changed, don't bother with hashing anything
|
// If nothing changed, don't bother with hashing anything
|
||||||
@ -372,9 +355,6 @@ func (s *stateObject) commitTrie(db Database) (*trie.NodeSet, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if s.dbErr != nil {
|
|
||||||
return nil, s.dbErr
|
|
||||||
}
|
|
||||||
// If nothing changed, don't bother with committing anything
|
// If nothing changed, don't bother with committing anything
|
||||||
if tr == nil {
|
if tr == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@ -385,7 +365,7 @@ func (s *stateObject) commitTrie(db Database) (*trie.NodeSet, error) {
|
|||||||
}
|
}
|
||||||
root, nodes := tr.Commit(false)
|
root, nodes := tr.Commit(false)
|
||||||
s.data.Root = root
|
s.data.Root = root
|
||||||
return nodes, err
|
return nodes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddBalance adds amount to s's balance.
|
// AddBalance adds amount to s's balance.
|
||||||
@ -457,7 +437,7 @@ func (s *stateObject) Code(db Database) []byte {
|
|||||||
}
|
}
|
||||||
code, err := db.ContractCode(s.addrHash, common.BytesToHash(s.CodeHash()))
|
code, err := db.ContractCode(s.addrHash, common.BytesToHash(s.CodeHash()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.setError(fmt.Errorf("can't load code hash %x: %v", s.CodeHash(), err))
|
s.db.setError(fmt.Errorf("can't load code hash %x: %v", s.CodeHash(), err))
|
||||||
}
|
}
|
||||||
s.code = code
|
s.code = code
|
||||||
return code
|
return code
|
||||||
@ -475,7 +455,7 @@ func (s *stateObject) CodeSize(db Database) int {
|
|||||||
}
|
}
|
||||||
size, err := db.ContractCodeSize(s.addrHash, common.BytesToHash(s.CodeHash()))
|
size, err := db.ContractCodeSize(s.addrHash, common.BytesToHash(s.CodeHash()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.setError(fmt.Errorf("can't load code size %x: %v", s.CodeHash(), err))
|
s.db.setError(fmt.Errorf("can't load code size %x: %v", s.CodeHash(), err))
|
||||||
}
|
}
|
||||||
return size
|
return size
|
||||||
}
|
}
|
||||||
@ -519,10 +499,3 @@ func (s *stateObject) Balance() *big.Int {
|
|||||||
func (s *stateObject) Nonce() uint64 {
|
func (s *stateObject) Nonce() uint64 {
|
||||||
return s.data.Nonce
|
return s.data.Nonce
|
||||||
}
|
}
|
||||||
|
|
||||||
// Value is never called, but must be present to allow stateObject to be used
|
|
||||||
// as a vm.Account interface that also satisfies the vm.ContractRef
|
|
||||||
// interface. Interfaces are awesome.
|
|
||||||
func (s *stateObject) Value() *big.Int {
|
|
||||||
panic("Value on stateObject should never be called")
|
|
||||||
}
|
|
||||||
|
@ -81,8 +81,10 @@ type StateDB struct {
|
|||||||
// DB error.
|
// DB error.
|
||||||
// State objects are used by the consensus core and VM which are
|
// State objects are used by the consensus core and VM which are
|
||||||
// unable to deal with database-level errors. Any error that occurs
|
// unable to deal with database-level errors. Any error that occurs
|
||||||
// during a database read is memoized here and will eventually be returned
|
// during a database read is memoized here and will eventually be
|
||||||
// by StateDB.Commit.
|
// returned by StateDB.Commit. Notably, this error is also shared
|
||||||
|
// by all cached state objects in case the database failure occurs
|
||||||
|
// when accessing state of accounts.
|
||||||
dbErr error
|
dbErr error
|
||||||
|
|
||||||
// The refund counter, also used by state transitioning.
|
// The refund counter, also used by state transitioning.
|
||||||
@ -187,6 +189,7 @@ func (s *StateDB) setError(err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Error returns the memorized database failure occurred earlier.
|
||||||
func (s *StateDB) Error() error {
|
func (s *StateDB) Error() error {
|
||||||
return s.dbErr
|
return s.dbErr
|
||||||
}
|
}
|
||||||
@ -478,13 +481,11 @@ func (s *StateDB) SetTransientState(addr common.Address, key, value common.Hash)
|
|||||||
if prev == value {
|
if prev == value {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
s.journal.append(transientStorageChange{
|
s.journal.append(transientStorageChange{
|
||||||
account: &addr,
|
account: &addr,
|
||||||
key: key,
|
key: key,
|
||||||
prevalue: prev,
|
prevalue: prev,
|
||||||
})
|
})
|
||||||
|
|
||||||
s.setTransientState(addr, key, value)
|
s.setTransientState(addr, key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -957,6 +958,7 @@ func (s *StateDB) clearJournalAndRefund() {
|
|||||||
|
|
||||||
// Commit writes the state to the underlying in-memory trie database.
|
// Commit writes the state to the underlying in-memory trie database.
|
||||||
func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
|
func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
|
||||||
|
// Short circuit in case any database failure occurred earlier.
|
||||||
if s.dbErr != nil {
|
if s.dbErr != nil {
|
||||||
return common.Hash{}, fmt.Errorf("commit aborted due to earlier error: %v", s.dbErr)
|
return common.Hash{}, fmt.Errorf("commit aborted due to earlier error: %v", s.dbErr)
|
||||||
}
|
}
|
||||||
|
@ -76,8 +76,6 @@ type StateDB interface {
|
|||||||
|
|
||||||
AddLog(*types.Log)
|
AddLog(*types.Log)
|
||||||
AddPreimage(common.Hash, []byte)
|
AddPreimage(common.Hash, []byte)
|
||||||
|
|
||||||
ForEachStorage(common.Address, func(common.Hash, common.Hash) bool) error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CallContext provides a basic interface for the EVM calling conventions. The EVM
|
// CallContext provides a basic interface for the EVM calling conventions. The EVM
|
||||||
|
Loading…
Reference in New Issue
Block a user