mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
eth/protocols/snap: integrate stacktrie handling
This commit is contained in:
parent
1e837e21f9
commit
d3b0894f3f
2 changed files with 36 additions and 21 deletions
|
|
@ -145,6 +145,11 @@ type accountResponse struct {
|
||||||
hashes []common.Hash // Account hashes in the returned range
|
hashes []common.Hash // Account hashes in the returned range
|
||||||
accounts []*types.StateAccount // Expanded accounts in the returned range
|
accounts []*types.StateAccount // Expanded accounts in the returned range
|
||||||
|
|
||||||
|
// origin requested, and, more importantly, the path for which the proof is valid.
|
||||||
|
origin common.Hash
|
||||||
|
root common.Hash // root for which this response is valid
|
||||||
|
proof ethdb.KeyValueReader // proof for origin and last value.
|
||||||
|
|
||||||
cont bool // Whether the account range has a continuation
|
cont bool // Whether the account range has a continuation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -223,6 +228,10 @@ type storageResponse struct {
|
||||||
hashes [][]common.Hash // Storage slot hashes in the returned range
|
hashes [][]common.Hash // Storage slot hashes in the returned range
|
||||||
slots [][][]byte // Storage slot values in the returned range
|
slots [][][]byte // Storage slot values in the returned range
|
||||||
|
|
||||||
|
// origin requested, and, more importantly, the path for which the proof is valid.
|
||||||
|
origin common.Hash
|
||||||
|
proof ethdb.KeyValueReader // proof for origin and last value.
|
||||||
|
|
||||||
cont bool // Whether the last storage range has a continuation
|
cont bool // Whether the last storage range has a continuation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -312,8 +321,8 @@ type accountTask struct {
|
||||||
codeTasks map[common.Hash]struct{} // Code hashes that need retrieval
|
codeTasks map[common.Hash]struct{} // Code hashes that need retrieval
|
||||||
stateTasks map[common.Hash]common.Hash // Account hashes->roots that need full state retrieval
|
stateTasks map[common.Hash]common.Hash // Account hashes->roots that need full state retrieval
|
||||||
|
|
||||||
genBatch ethdb.Batch // Batch used by the node generator
|
genBatch ethdb.Batch // Batch used by the node generator
|
||||||
genTrie *trie.StackTrie // Node generator from storage slots
|
genTrie *trie.GenerativeTrie // Node generator from storage slots
|
||||||
|
|
||||||
done bool // Flag whether the task can be removed
|
done bool // Flag whether the task can be removed
|
||||||
}
|
}
|
||||||
|
|
@ -327,8 +336,8 @@ type storageTask struct {
|
||||||
root common.Hash // Storage root hash for this instance
|
root common.Hash // Storage root hash for this instance
|
||||||
req *storageRequest // Pending request to fill this task
|
req *storageRequest // Pending request to fill this task
|
||||||
|
|
||||||
genBatch ethdb.Batch // Batch used by the node generator
|
genBatch ethdb.Batch // Batch used by the node generator
|
||||||
genTrie *trie.StackTrie // Node generator from storage slots
|
genTrie *trie.GenerativeTrie // Node generator from storage slots
|
||||||
|
|
||||||
done bool // Flag whether the task can be removed
|
done bool // Flag whether the task can be removed
|
||||||
}
|
}
|
||||||
|
|
@ -738,7 +747,7 @@ func (s *Syncer) loadSyncStatus() {
|
||||||
s.accountBytes += common.StorageSize(len(key) + len(value))
|
s.accountBytes += common.StorageSize(len(key) + len(value))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
task.genTrie = trie.NewStackTrie(func(path []byte, hash common.Hash, val []byte) {
|
task.genTrie = trie.NewGentrie(task.Next, task.Last, func(path []byte, hash common.Hash, val []byte) {
|
||||||
rawdb.WriteTrieNode(task.genBatch, common.Hash{}, path, hash, val, s.scheme)
|
rawdb.WriteTrieNode(task.genBatch, common.Hash{}, path, hash, val, s.scheme)
|
||||||
})
|
})
|
||||||
for accountHash, subtasks := range task.SubTasks {
|
for accountHash, subtasks := range task.SubTasks {
|
||||||
|
|
@ -752,7 +761,7 @@ func (s *Syncer) loadSyncStatus() {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
owner := accountHash // local assignment for stacktrie writer closure
|
owner := accountHash // local assignment for stacktrie writer closure
|
||||||
subtask.genTrie = trie.NewStackTrie(func(path []byte, hash common.Hash, val []byte) {
|
subtask.genTrie = trie.NewGentrie(subtask.Next, subtask.Last, func(path []byte, hash common.Hash, val []byte) {
|
||||||
rawdb.WriteTrieNode(subtask.genBatch, owner, path, hash, val, s.scheme)
|
rawdb.WriteTrieNode(subtask.genBatch, owner, path, hash, val, s.scheme)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -811,7 +820,7 @@ func (s *Syncer) loadSyncStatus() {
|
||||||
Last: last,
|
Last: last,
|
||||||
SubTasks: make(map[common.Hash][]*storageTask),
|
SubTasks: make(map[common.Hash][]*storageTask),
|
||||||
genBatch: batch,
|
genBatch: batch,
|
||||||
genTrie: trie.NewStackTrie(func(path []byte, hash common.Hash, val []byte) {
|
genTrie: trie.NewGentrie(next, last, func(path []byte, hash common.Hash, val []byte) {
|
||||||
rawdb.WriteTrieNode(batch, common.Hash{}, path, hash, val, s.scheme)
|
rawdb.WriteTrieNode(batch, common.Hash{}, path, hash, val, s.scheme)
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
@ -2011,7 +2020,7 @@ func (s *Syncer) processStorageResponse(res *storageResponse) {
|
||||||
Last: r.End(),
|
Last: r.End(),
|
||||||
root: acc.Root,
|
root: acc.Root,
|
||||||
genBatch: batch,
|
genBatch: batch,
|
||||||
genTrie: trie.NewStackTrie(func(path []byte, hash common.Hash, val []byte) {
|
genTrie: trie.NewGentrie((common.Hash{}), r.End(), func(path []byte, hash common.Hash, val []byte) {
|
||||||
rawdb.WriteTrieNode(batch, owner, path, hash, val, s.scheme)
|
rawdb.WriteTrieNode(batch, owner, path, hash, val, s.scheme)
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
@ -2027,7 +2036,7 @@ func (s *Syncer) processStorageResponse(res *storageResponse) {
|
||||||
Last: r.End(),
|
Last: r.End(),
|
||||||
root: acc.Root,
|
root: acc.Root,
|
||||||
genBatch: batch,
|
genBatch: batch,
|
||||||
genTrie: trie.NewStackTrie(func(path []byte, hash common.Hash, val []byte) {
|
genTrie: trie.NewGentrie(r.Start(), r.End(), func(path []byte, hash common.Hash, val []byte) {
|
||||||
rawdb.WriteTrieNode(batch, owner, path, hash, val, s.scheme)
|
rawdb.WriteTrieNode(batch, owner, path, hash, val, s.scheme)
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
@ -2083,17 +2092,17 @@ func (s *Syncer) processStorageResponse(res *storageResponse) {
|
||||||
}
|
}
|
||||||
tr.Commit()
|
tr.Commit()
|
||||||
}
|
}
|
||||||
|
// If we're storing large contracts, generate the trie nodes
|
||||||
|
// on the fly to not trash the gluing points
|
||||||
|
if i == len(res.hashes)-1 && res.subTask != nil {
|
||||||
|
res.subTask.genTrie.AddProof(res.roots[i], res.origin[:], res.proof)
|
||||||
|
res.subTask.genTrie.UpdateAll(res.hashes[i], res.slots[i])
|
||||||
|
}
|
||||||
// Persist the received storage segments. These flat state maybe
|
// Persist the received storage segments. These flat state maybe
|
||||||
// outdated during the sync, but it can be fixed later during the
|
// outdated during the sync, but it can be fixed later during the
|
||||||
// snapshot generation.
|
// snapshot generation.
|
||||||
for j := 0; j < len(res.hashes[i]); j++ {
|
for j := 0; j < len(res.hashes[i]); j++ {
|
||||||
rawdb.WriteStorageSnapshot(batch, account, res.hashes[i][j], res.slots[i][j])
|
rawdb.WriteStorageSnapshot(batch, account, res.hashes[i][j], res.slots[i][j])
|
||||||
|
|
||||||
// If we're storing large contracts, generate the trie nodes
|
|
||||||
// on the fly to not trash the gluing points
|
|
||||||
if i == len(res.hashes)-1 && res.subTask != nil {
|
|
||||||
res.subTask.genTrie.Update(res.hashes[i][j][:], res.slots[i][j])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Large contracts could have generated new trie nodes, flush them to disk
|
// Large contracts could have generated new trie nodes, flush them to disk
|
||||||
|
|
@ -2279,6 +2288,7 @@ func (s *Syncer) forwardAccountTask(task *accountTask) {
|
||||||
s.accountBytes += common.StorageSize(len(key) + len(value))
|
s.accountBytes += common.StorageSize(len(key) + len(value))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
task.genTrie.AddProof(res.root, res.origin[:], res.proof)
|
||||||
for i, hash := range res.hashes {
|
for i, hash := range res.hashes {
|
||||||
if task.needCode[i] || task.needState[i] {
|
if task.needCode[i] || task.needState[i] {
|
||||||
break
|
break
|
||||||
|
|
@ -2420,6 +2430,9 @@ func (s *Syncer) OnAccounts(peer SyncPeer, id uint64, hashes []common.Hash, acco
|
||||||
task: req.task,
|
task: req.task,
|
||||||
hashes: hashes,
|
hashes: hashes,
|
||||||
accounts: accs,
|
accounts: accs,
|
||||||
|
proof: nodes.Set(),
|
||||||
|
origin: req.origin,
|
||||||
|
root: root,
|
||||||
cont: cont,
|
cont: cont,
|
||||||
}
|
}
|
||||||
select {
|
select {
|
||||||
|
|
@ -2637,6 +2650,8 @@ func (s *Syncer) OnStorage(peer SyncPeer, id uint64, hashes [][]common.Hash, slo
|
||||||
hashes = append(hashes, []common.Hash{})
|
hashes = append(hashes, []common.Hash{})
|
||||||
slots = append(slots, [][]byte{})
|
slots = append(slots, [][]byte{})
|
||||||
}
|
}
|
||||||
|
var proofdb ethdb.KeyValueReader
|
||||||
|
|
||||||
for i := 0; i < len(hashes); i++ {
|
for i := 0; i < len(hashes); i++ {
|
||||||
// Convert the keys and proofs into an internal format
|
// Convert the keys and proofs into an internal format
|
||||||
keys := make([][]byte, len(hashes[i]))
|
keys := make([][]byte, len(hashes[i]))
|
||||||
|
|
@ -2662,7 +2677,7 @@ func (s *Syncer) OnStorage(peer SyncPeer, id uint64, hashes [][]common.Hash, slo
|
||||||
} else {
|
} else {
|
||||||
// A proof was attached, the response is only partial, check that the
|
// A proof was attached, the response is only partial, check that the
|
||||||
// returned data is indeed part of the storage trie
|
// returned data is indeed part of the storage trie
|
||||||
proofdb := nodes.Set()
|
proofdb = nodes.Set()
|
||||||
|
|
||||||
cont, err = trie.VerifyRangeProof(req.roots[i], req.origin[:], keys, slots[i], proofdb)
|
cont, err = trie.VerifyRangeProof(req.roots[i], req.origin[:], keys, slots[i], proofdb)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -2680,6 +2695,8 @@ func (s *Syncer) OnStorage(peer SyncPeer, id uint64, hashes [][]common.Hash, slo
|
||||||
roots: req.roots,
|
roots: req.roots,
|
||||||
hashes: hashes,
|
hashes: hashes,
|
||||||
slots: slots,
|
slots: slots,
|
||||||
|
origin: req.origin,
|
||||||
|
proof: proofdb,
|
||||||
cont: cont,
|
cont: cont,
|
||||||
}
|
}
|
||||||
select {
|
select {
|
||||||
|
|
|
||||||
|
|
@ -418,25 +418,24 @@ func wrapWriteFunction(origin, last []byte, w NodeWriteFunc) NodeWriteFunc {
|
||||||
|
|
||||||
type GenerativeTrie struct {
|
type GenerativeTrie struct {
|
||||||
proofsSet bool
|
proofsSet bool
|
||||||
owner common.Hash
|
|
||||||
writeFn NodeWriteFunc
|
writeFn NodeWriteFunc
|
||||||
stack *StackTrie
|
stack *StackTrie
|
||||||
|
|
||||||
rightHandBorder []byte
|
rightHandBorder []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGentrieWithOwner(origin, end, owner common.Hash, writeFn NodeWriteFunc) *GenerativeTrie {
|
func NewGentrie(origin, end common.Hash, writeFn NodeWriteFunc) *GenerativeTrie {
|
||||||
// Wrap the write function
|
// Wrap the write function
|
||||||
var originBorder = keybytesToHex(origin[:])
|
var originBorder = keybytesToHex(origin[:])
|
||||||
var g = &GenerativeTrie{}
|
var g = &GenerativeTrie{}
|
||||||
wrapper := func(origin common.Hash, path []byte, hash common.Hash, blob []byte) {
|
wrapper := func(path []byte, hash common.Hash, blob []byte) {
|
||||||
if bytes.HasPrefix(originBorder, path) {
|
if bytes.HasPrefix(originBorder, path) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if bytes.HasPrefix(g.rightHandBorder, path) {
|
if bytes.HasPrefix(g.rightHandBorder, path) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
writeFn(origin, path, hash, blob)
|
writeFn(path, hash, blob)
|
||||||
}
|
}
|
||||||
return &GenerativeTrie{writeFn: wrapper}
|
return &GenerativeTrie{writeFn: wrapper}
|
||||||
}
|
}
|
||||||
|
|
@ -449,7 +448,6 @@ func (g *GenerativeTrie) AddProof(rootHash common.Hash, origin []byte, proof eth
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
g.stack = stack
|
g.stack = stack
|
||||||
g.stack.owner = g.owner
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue