trie: enable batch updates

This commit is contained in:
Martin Holst Swende 2019-12-31 15:10:29 +01:00
parent aa281e7d7e
commit 478d0ee00d
No known key found for this signature in database
GPG key ID: 683B438C05A5DDF0
5 changed files with 36 additions and 3 deletions

View file

@ -69,7 +69,8 @@ type Trie interface {
// by the caller while they are stored in the trie. If a node was not found in the
// database, a trie.MissingNodeError is returned.
TryUpdate(key, value []byte) error
BatchStart()
BatchEnd()
// TryDelete removes any existing value for key from the trie. If a node was not
// found in the database, a trie.MissingNodeError is returned.
TryDelete(key []byte) error

View file

@ -688,7 +688,7 @@ func (s *StateDB) Finalise(deleteEmptyObjects bool) {
func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
// Finalise all the dirty storage states and write them into the tries
s.Finalise(deleteEmptyObjects)
s.trie.BatchStart()
for addr := range s.stateObjectsPending {
obj := s.stateObjects[addr]
if obj.deleted {
@ -698,6 +698,7 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
s.updateStateObject(obj)
}
}
s.trie.BatchEnd()
if len(s.stateObjectsPending) > 0 {
s.stateObjectsPending = make(map[common.Address]struct{})
}

View file

@ -112,6 +112,9 @@ func (t *odrTrie) TryUpdate(key, value []byte) error {
})
}
func (t *odrTrie) BatchStart() {}
func (t *odrTrie) BatchEnd() {}
func (t *odrTrie) TryDelete(key []byte) error {
key = crypto.Keccak256(key)
return t.do(key, func() error {

View file

@ -109,6 +109,13 @@ func (t *SecureTrie) TryUpdate(key, value []byte) error {
return nil
}
func (t *SecureTrie) BatchStart(){
t.trie.batchStart()
}
func (t *SecureTrie) BatchEnd(){
t.trie.batchEnd()
}
// Delete removes any existing value for key from the trie.
func (t *SecureTrie) Delete(key []byte) {
if err := t.TryDelete(key); err != nil {

View file

@ -52,6 +52,7 @@ type Trie struct {
dirtyCount int
// And leafs to hash
unhashedCount int
batchMode bool
}
// newFlag returns the cache flag value for a newly created node.
@ -186,6 +187,13 @@ func (t *Trie) TryUpdate(key, value []byte) error {
return nil
}
func (t *Trie) batchStart(){
t.batchMode = true
}
func (t *Trie) batchEnd(){
t.batchMode = false
}
func (t *Trie) insert(n node, prefix, key []byte, value node) (bool, node, error) {
if len(key) == 0 {
if v, ok := n.(valueNode); ok {
@ -228,7 +236,20 @@ func (t *Trie) insert(n node, prefix, key []byte, value node) (bool, node, error
if !dirty || err != nil {
return false, n, err
}
n = n.copy()
// If we're in batch-mode, we don't keep 'ephemeral' changes.
// When we modify a node, we only copy it in case it is an old committed
// node.
// If the node is "new", we just update in place.
if t.batchMode{
if h, dirty := n.cache(); !dirty || h != nil{
// This node is either not dirty, or already hashed. We copy it
n = n.copy()
}else{
// No copy
}
}else{
n = n.copy()
}
n.flags = t.newFlag()
n.Children[key[0]] = nn
return true, n, nil