Patch for concurrent iterator & others (onto v1.11.6) #386

Closed
roysc wants to merge 1565 commits from v1.11.6-statediff-v5 into master
8 changed files with 54 additions and 55 deletions
Showing only changes of commit 41f89ca944 - Show all commits

View File

@ -68,36 +68,36 @@ type Trie interface {
// TODO(fjl): remove this when StateTrie is removed // TODO(fjl): remove this when StateTrie is removed
GetKey([]byte) []byte GetKey([]byte) []byte
// TryGetStorage returns the value for key stored in the trie. The value bytes // GetStorage returns the value for key stored in the trie. The value bytes
// must not be modified by the caller. If a node was not found in the database, // must not be modified by the caller. If a node was not found in the database,
// a trie.MissingNodeError is returned. // a trie.MissingNodeError is returned.
TryGetStorage(addr common.Address, key []byte) ([]byte, error) GetStorage(addr common.Address, key []byte) ([]byte, error)
// TryGetAccount abstracts an account read from the trie. It retrieves the // GetAccount abstracts an account read from the trie. It retrieves the
// account blob from the trie with provided account address and decodes it // account blob from the trie with provided account address and decodes it
// with associated decoding algorithm. If the specified account is not in // with associated decoding algorithm. If the specified account is not in
// the trie, nil will be returned. If the trie is corrupted(e.g. some nodes // the trie, nil will be returned. If the trie is corrupted(e.g. some nodes
// are missing or the account blob is incorrect for decoding), an error will // are missing or the account blob is incorrect for decoding), an error will
// be returned. // be returned.
TryGetAccount(address common.Address) (*types.StateAccount, error) GetAccount(address common.Address) (*types.StateAccount, error)
// TryUpdateStorage associates key with value in the trie. If value has length zero, // UpdateStorage associates key with value in the trie. If value has length zero,
// any existing value is deleted from the trie. The value bytes must not be modified // any existing value is deleted from the trie. The value bytes must not be modified
// by the caller while they are stored in the trie. If a node was not found in the // by the caller while they are stored in the trie. If a node was not found in the
// database, a trie.MissingNodeError is returned. // database, a trie.MissingNodeError is returned.
TryUpdateStorage(addr common.Address, key, value []byte) error UpdateStorage(addr common.Address, key, value []byte) error
// TryUpdateAccount abstracts an account write to the trie. It encodes the // UpdateAccount abstracts an account write to the trie. It encodes the
// provided account object with associated algorithm and then updates it // provided account object with associated algorithm and then updates it
// in the trie with provided address. // in the trie with provided address.
TryUpdateAccount(address common.Address, account *types.StateAccount) error UpdateAccount(address common.Address, account *types.StateAccount) error
// TryDeleteStorage removes any existing value for key from the trie. If a node // DeleteStorage removes any existing value for key from the trie. If a node
// was not found in the database, a trie.MissingNodeError is returned. // was not found in the database, a trie.MissingNodeError is returned.
TryDeleteStorage(addr common.Address, key []byte) error DeleteStorage(addr common.Address, key []byte) error
// TryDeleteAccount abstracts an account deletion from the trie. // DeleteAccount abstracts an account deletion from the trie.
TryDeleteAccount(address common.Address) error DeleteAccount(address common.Address) error
// Hash returns the root hash of the trie. It does not write to the database and // Hash returns the root hash of the trie. It does not write to the database and
// can be used even if the trie doesn't have one. // can be used even if the trie doesn't have one.

View File

@ -201,7 +201,7 @@ func (s *stateObject) GetCommittedState(db Database, key common.Hash) common.Has
s.db.setError(err) s.db.setError(err)
return common.Hash{} return common.Hash{}
} }
enc, err = tr.TryGetStorage(s.address, key.Bytes()) enc, err = tr.GetStorage(s.address, key.Bytes())
if metrics.EnabledExpensive { if metrics.EnabledExpensive {
s.db.StorageReads += time.Since(start) s.db.StorageReads += time.Since(start)
} }
@ -294,7 +294,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.TryDeleteStorage(s.address, key[:]); err != nil { if err := tr.DeleteStorage(s.address, key[:]); err != nil {
s.db.setError(err) s.db.setError(err)
return nil, err return nil, err
} }
@ -302,7 +302,7 @@ func (s *stateObject) updateTrie(db Database) (Trie, error) {
} else { } else {
// 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.TryUpdateStorage(s.address, key[:], v); err != nil { if err := tr.UpdateStorage(s.address, key[:], v); err != nil {
s.db.setError(err) s.db.setError(err)
return nil, err return nil, err
} }

View File

@ -512,7 +512,7 @@ func (s *StateDB) updateStateObject(obj *stateObject) {
} }
// Encode the account and update the account trie // Encode the account and update the account trie
addr := obj.Address() addr := obj.Address()
if err := s.trie.TryUpdateAccount(addr, &obj.data); err != nil { if err := s.trie.UpdateAccount(addr, &obj.data); err != nil {
s.setError(fmt.Errorf("updateStateObject (%x) error: %v", addr[:], err)) s.setError(fmt.Errorf("updateStateObject (%x) error: %v", addr[:], err))
} }
@ -533,7 +533,7 @@ func (s *StateDB) deleteStateObject(obj *stateObject) {
} }
// Delete the account from the trie // Delete the account from the trie
addr := obj.Address() addr := obj.Address()
if err := s.trie.TryDeleteAccount(addr); err != nil { if err := s.trie.DeleteAccount(addr); err != nil {
s.setError(fmt.Errorf("deleteStateObject (%x) error: %v", addr[:], err)) s.setError(fmt.Errorf("deleteStateObject (%x) error: %v", addr[:], err))
} }
} }
@ -587,7 +587,7 @@ func (s *StateDB) getDeletedStateObject(addr common.Address) *stateObject {
if data == nil { if data == nil {
start := time.Now() start := time.Now()
var err error var err error
data, err = s.trie.TryGetAccount(addr) data, err = s.trie.GetAccount(addr)
if metrics.EnabledExpensive { if metrics.EnabledExpensive {
s.AccountReads += time.Since(start) s.AccountReads += time.Since(start)
} }

View File

@ -339,9 +339,9 @@ func (sf *subfetcher) loop() {
sf.dups++ sf.dups++
} else { } else {
if len(task) == common.AddressLength { if len(task) == common.AddressLength {
sf.trie.TryGetAccount(common.BytesToAddress(task)) sf.trie.GetAccount(common.BytesToAddress(task))
} else { } else {
sf.trie.TryGetStorage(sf.addr, task) sf.trie.GetStorage(sf.addr, task)
} }
sf.seen[string(task)] = struct{}{} sf.seen[string(task)] = struct{}{}
} }

View File

@ -418,7 +418,7 @@ func ServiceGetStorageRangesQuery(chain *core.BlockChain, req *GetStorageRangesP
if err != nil { if err != nil {
return nil, nil return nil, nil
} }
acc, err := accTrie.TryGetAccountByHash(account) acc, err := accTrie.GetAccountByHash(account)
if err != nil || acc == nil { if err != nil || acc == nil {
return nil, nil return nil, nil
} }
@ -510,7 +510,7 @@ func ServiceGetTrieNodesQuery(chain *core.BlockChain, req *GetTrieNodesPacket, s
case 1: case 1:
// If we're only retrieving an account trie node, fetch it directly // If we're only retrieving an account trie node, fetch it directly
blob, resolved, err := accTrie.TryGetNode(pathset[0]) blob, resolved, err := accTrie.GetNode(pathset[0])
loads += resolved // always account database reads, even for failures loads += resolved // always account database reads, even for failures
if err != nil { if err != nil {
break break
@ -524,7 +524,7 @@ func ServiceGetTrieNodesQuery(chain *core.BlockChain, req *GetTrieNodesPacket, s
if snap == nil { if snap == nil {
// We don't have the requested state snapshotted yet (or it is stale), // We don't have the requested state snapshotted yet (or it is stale),
// but can look up the account via the trie instead. // but can look up the account via the trie instead.
account, err := accTrie.TryGetAccountByHash(common.BytesToHash(pathset[0])) account, err := accTrie.GetAccountByHash(common.BytesToHash(pathset[0]))
loads += 8 // We don't know the exact cost of lookup, this is an estimate loads += 8 // We don't know the exact cost of lookup, this is an estimate
if err != nil || account == nil { if err != nil || account == nil {
break break
@ -545,7 +545,7 @@ func ServiceGetTrieNodesQuery(chain *core.BlockChain, req *GetTrieNodesPacket, s
break break
} }
for _, path := range pathset[1:] { for _, path := range pathset[1:] {
blob, resolved, err := stTrie.TryGetNode(path) blob, resolved, err := stTrie.GetNode(path)
loads += resolved // always account database reads, even for failures loads += resolved // always account database reads, even for failures
if err != nil { if err != nil {
break break

View File

@ -105,7 +105,7 @@ type odrTrie struct {
trie *trie.Trie trie *trie.Trie
} }
func (t *odrTrie) TryGetStorage(_ common.Address, key []byte) ([]byte, error) { func (t *odrTrie) GetStorage(_ common.Address, key []byte) ([]byte, error) {
key = crypto.Keccak256(key) key = crypto.Keccak256(key)
var res []byte var res []byte
err := t.do(key, func() (err error) { err := t.do(key, func() (err error) {
@ -115,7 +115,7 @@ func (t *odrTrie) TryGetStorage(_ common.Address, key []byte) ([]byte, error) {
return res, err return res, err
} }
func (t *odrTrie) TryGetAccount(address common.Address) (*types.StateAccount, error) { func (t *odrTrie) GetAccount(address common.Address) (*types.StateAccount, error) {
var res types.StateAccount var res types.StateAccount
key := crypto.Keccak256(address.Bytes()) key := crypto.Keccak256(address.Bytes())
err := t.do(key, func() (err error) { err := t.do(key, func() (err error) {
@ -131,7 +131,7 @@ func (t *odrTrie) TryGetAccount(address common.Address) (*types.StateAccount, er
return &res, err return &res, err
} }
func (t *odrTrie) TryUpdateAccount(address common.Address, acc *types.StateAccount) error { func (t *odrTrie) UpdateAccount(address common.Address, acc *types.StateAccount) error {
key := crypto.Keccak256(address.Bytes()) key := crypto.Keccak256(address.Bytes())
value, err := rlp.EncodeToBytes(acc) value, err := rlp.EncodeToBytes(acc)
if err != nil { if err != nil {
@ -142,14 +142,14 @@ func (t *odrTrie) TryUpdateAccount(address common.Address, acc *types.StateAccou
}) })
} }
func (t *odrTrie) TryUpdateStorage(_ common.Address, key, value []byte) error { func (t *odrTrie) UpdateStorage(_ common.Address, key, value []byte) error {
key = crypto.Keccak256(key) key = crypto.Keccak256(key)
return t.do(key, func() error { return t.do(key, func() error {
return t.trie.TryUpdate(key, value) return t.trie.TryUpdate(key, value)
}) })
} }
func (t *odrTrie) TryDeleteStorage(_ common.Address, key []byte) error { func (t *odrTrie) DeleteStorage(_ common.Address, key []byte) error {
key = crypto.Keccak256(key) key = crypto.Keccak256(key)
return t.do(key, func() error { return t.do(key, func() error {
return t.trie.TryDelete(key) return t.trie.TryDelete(key)
@ -157,7 +157,7 @@ func (t *odrTrie) TryDeleteStorage(_ common.Address, key []byte) error {
} }
// TryDeleteAccount abstracts an account deletion from the trie. // TryDeleteAccount abstracts an account deletion from the trie.
func (t *odrTrie) TryDeleteAccount(address common.Address) error { func (t *odrTrie) DeleteAccount(address common.Address) error {
key := crypto.Keccak256(address.Bytes()) key := crypto.Keccak256(address.Bytes())
return t.do(key, func() error { return t.do(key, func() error {
return t.trie.TryDelete(key) return t.trie.TryDelete(key)

View File

@ -75,25 +75,25 @@ func NewStateTrie(id *ID, db *Database) (*StateTrie, error) {
// Get returns the value for key stored in the trie. // Get returns the value for key stored in the trie.
// The value bytes must not be modified by the caller. // The value bytes must not be modified by the caller.
func (t *StateTrie) Get(key []byte) []byte { func (t *StateTrie) Get(key []byte) []byte {
res, err := t.TryGetStorage(common.Address{}, key) res, err := t.GetStorage(common.Address{}, key)
if err != nil { if err != nil {
log.Error("Unhandled trie error in StateTrie.Get", "err", err) log.Error("Unhandled trie error in StateTrie.Get", "err", err)
} }
return res return res
} }
// TryGet returns the value for key stored in the trie. // GetStorage attempts to retrieve a storage slot with provided account address
// The value bytes must not be modified by the caller. // and slot key. The value bytes must not be modified by the caller.
// If the specified node is not in the trie, nil will be returned. // If the specified storage slot is not in the trie, nil will be returned.
// If a trie node is not found in the database, a MissingNodeError is returned. // If a trie node is not found in the database, a MissingNodeError is returned.
func (t *StateTrie) TryGetStorage(_ common.Address, key []byte) ([]byte, error) { func (t *StateTrie) GetStorage(_ common.Address, key []byte) ([]byte, error) {
return t.trie.TryGet(t.hashKey(key)) return t.trie.TryGet(t.hashKey(key))
} }
// TryGetAccount attempts to retrieve an account with provided account address. // GetAccount attempts to retrieve an account with provided account address.
// If the specified account is not in the trie, nil will be returned. // If the specified account is not in the trie, nil will be returned.
// If a trie node is not found in the database, a MissingNodeError is returned. // If a trie node is not found in the database, a MissingNodeError is returned.
func (t *StateTrie) TryGetAccount(address common.Address) (*types.StateAccount, error) { func (t *StateTrie) GetAccount(address common.Address) (*types.StateAccount, error) {
res, err := t.trie.TryGet(t.hashKey(address.Bytes())) res, err := t.trie.TryGet(t.hashKey(address.Bytes()))
if res == nil || err != nil { if res == nil || err != nil {
return nil, err return nil, err
@ -103,10 +103,10 @@ func (t *StateTrie) TryGetAccount(address common.Address) (*types.StateAccount,
return ret, err return ret, err
} }
// TryGetAccountByHash does the same thing as TryGetAccount, however // GetAccountByHash does the same thing as GetAccount, however it expects an
// it expects an account hash that is the hash of address. This constitutes an // account hash that is the hash of address. This constitutes an abstraction
// abstraction leak, since the client code needs to know the key format. // leak, since the client code needs to know the key format.
func (t *StateTrie) TryGetAccountByHash(addrHash common.Hash) (*types.StateAccount, error) { func (t *StateTrie) GetAccountByHash(addrHash common.Hash) (*types.StateAccount, error) {
res, err := t.trie.TryGet(addrHash.Bytes()) res, err := t.trie.TryGet(addrHash.Bytes())
if res == nil || err != nil { if res == nil || err != nil {
return nil, err return nil, err
@ -116,11 +116,11 @@ func (t *StateTrie) TryGetAccountByHash(addrHash common.Hash) (*types.StateAccou
return ret, err return ret, err
} }
// TryGetNode attempts to retrieve a trie node by compact-encoded path. It is not // GetNode attempts to retrieve a trie node by compact-encoded path. It is not
// possible to use keybyte-encoding as the path might contain odd nibbles. // possible to use keybyte-encoding as the path might contain odd nibbles.
// If the specified trie node is not in the trie, nil will be returned. // If the specified trie node is not in the trie, nil will be returned.
// If a trie node is not found in the database, a MissingNodeError is returned. // If a trie node is not found in the database, a MissingNodeError is returned.
func (t *StateTrie) TryGetNode(path []byte) ([]byte, int, error) { func (t *StateTrie) GetNode(path []byte) ([]byte, int, error) {
return t.trie.TryGetNode(path) return t.trie.TryGetNode(path)
} }
@ -131,12 +131,12 @@ func (t *StateTrie) TryGetNode(path []byte) ([]byte, int, error) {
// The value bytes must not be modified by the caller while they are // The value bytes must not be modified by the caller while they are
// stored in the trie. // stored in the trie.
func (t *StateTrie) Update(key, value []byte) { func (t *StateTrie) Update(key, value []byte) {
if err := t.TryUpdateStorage(common.Address{}, key, value); err != nil { if err := t.UpdateStorage(common.Address{}, key, value); err != nil {
log.Error("Unhandled trie error in StateTrie.Update", "err", err) log.Error("Unhandled trie error in StateTrie.Update", "err", err)
} }
} }
// TryUpdate associates key with value in the trie. Subsequent calls to // UpdateStorage associates key with value in the trie. Subsequent calls to
// Get will return value. If value has length zero, any existing value // Get will return value. If value has length zero, any existing value
// is deleted from the trie and calls to Get will return nil. // is deleted from the trie and calls to Get will return nil.
// //
@ -144,7 +144,7 @@ func (t *StateTrie) Update(key, value []byte) {
// stored in the trie. // stored in the trie.
// //
// If a node is not found in the database, a MissingNodeError is returned. // If a node is not found in the database, a MissingNodeError is returned.
func (t *StateTrie) TryUpdateStorage(_ common.Address, key, value []byte) error { func (t *StateTrie) UpdateStorage(_ common.Address, key, value []byte) error {
hk := t.hashKey(key) hk := t.hashKey(key)
err := t.trie.TryUpdate(hk, value) err := t.trie.TryUpdate(hk, value)
if err != nil { if err != nil {
@ -154,9 +154,8 @@ func (t *StateTrie) TryUpdateStorage(_ common.Address, key, value []byte) error
return nil return nil
} }
// TryUpdateAccount account will abstract the write of an account to the // UpdateAccount will abstract the write of an account to the secure trie.
// secure trie. func (t *StateTrie) UpdateAccount(address common.Address, acc *types.StateAccount) error {
func (t *StateTrie) TryUpdateAccount(address common.Address, acc *types.StateAccount) error {
hk := t.hashKey(address.Bytes()) hk := t.hashKey(address.Bytes())
data, err := rlp.EncodeToBytes(acc) data, err := rlp.EncodeToBytes(acc)
if err != nil { if err != nil {
@ -171,22 +170,22 @@ func (t *StateTrie) TryUpdateAccount(address common.Address, acc *types.StateAcc
// Delete removes any existing value for key from the trie. // Delete removes any existing value for key from the trie.
func (t *StateTrie) Delete(key []byte) { func (t *StateTrie) Delete(key []byte) {
if err := t.TryDeleteStorage(common.Address{}, key); err != nil { if err := t.DeleteStorage(common.Address{}, key); err != nil {
log.Error("Unhandled trie error in StateTrie.Delete", "err", err) log.Error("Unhandled trie error in StateTrie.Delete", "err", err)
} }
} }
// TryDelete removes any existing value for key from the trie. // DeleteStorage removes any existing storage slot from the trie.
// If the specified trie node is not in the trie, nothing will be changed. // If the specified trie node is not in the trie, nothing will be changed.
// If a node is not found in the database, a MissingNodeError is returned. // If a node is not found in the database, a MissingNodeError is returned.
func (t *StateTrie) TryDeleteStorage(_ common.Address, key []byte) error { func (t *StateTrie) DeleteStorage(_ common.Address, key []byte) error {
hk := t.hashKey(key) hk := t.hashKey(key)
delete(t.getSecKeyCache(), string(hk)) delete(t.getSecKeyCache(), string(hk))
return t.trie.TryDelete(hk) return t.trie.TryDelete(hk)
} }
// TryDeleteAccount abstracts an account deletion from the trie. // DeleteAccount abstracts an account deletion from the trie.
func (t *StateTrie) TryDeleteAccount(address common.Address) error { func (t *StateTrie) DeleteAccount(address common.Address) error {
hk := t.hashKey(address.Bytes()) hk := t.hashKey(address.Bytes())
delete(t.getSecKeyCache(), string(hk)) delete(t.getSecKeyCache(), string(hk))
return t.trie.TryDelete(hk) return t.trie.TryDelete(hk)

View File

@ -154,7 +154,7 @@ func testIterativeSync(t *testing.T, count int, bypath bool) {
} }
} else { } else {
for i, element := range elements { for i, element := range elements {
data, _, err := srcTrie.TryGetNode(element.syncPath[len(element.syncPath)-1]) data, _, err := srcTrie.GetNode(element.syncPath[len(element.syncPath)-1])
if err != nil { if err != nil {
t.Fatalf("failed to retrieve node data for path %x: %v", element.path, err) t.Fatalf("failed to retrieve node data for path %x: %v", element.path, err)
} }