trie, les, tests, core: implement trie tracer (#24403)

Trie tracer is an auxiliary tool to capture all deleted nodes
which can't be captured by trie.Committer. The deleted nodes
can be removed from the disk later.
This commit is contained in:
rjl493456442
2022-03-31 15:28:32 +08:00
committed by GitHub
parent 127dc5982e
commit da16d089c0
13 changed files with 413 additions and 35 deletions

View File

@ -32,6 +32,7 @@ import (
"github.com/davecgh/go-spew/spew"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
@ -53,7 +54,7 @@ func newEmpty() *Trie {
}
func TestEmptyTrie(t *testing.T) {
var trie Trie
trie, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()))
res := trie.Hash()
exp := emptyRoot
if res != exp {
@ -62,7 +63,7 @@ func TestEmptyTrie(t *testing.T) {
}
func TestNull(t *testing.T) {
var trie Trie
trie, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()))
key := make([]byte, 32)
value := []byte("test")
trie.Update(key, value)
@ -374,6 +375,7 @@ const (
opHash
opReset
opItercheckhash
opNodeDiff
opMax // boundary value, not an actual op
)
@ -408,10 +410,13 @@ func (randTest) Generate(r *rand.Rand, size int) reflect.Value {
}
func runRandTest(rt randTest) bool {
triedb := NewDatabase(memorydb.New())
tr, _ := New(common.Hash{}, triedb)
values := make(map[string]string) // tracks content of the trie
var (
triedb = NewDatabase(memorydb.New())
tr, _ = New(common.Hash{}, triedb)
values = make(map[string]string) // tracks content of the trie
origTrie, _ = New(common.Hash{}, triedb)
)
tr.tracer = newTracer()
for i, step := range rt {
// fmt.Printf("{op: %d, key: common.Hex2Bytes(\"%x\"), value: common.Hex2Bytes(\"%x\")}, // step %d\n",
@ -432,6 +437,7 @@ func runRandTest(rt randTest) bool {
}
case opCommit:
_, _, rt[i].err = tr.Commit(nil)
origTrie = tr.Copy()
case opHash:
tr.Hash()
case opReset:
@ -446,6 +452,9 @@ func runRandTest(rt randTest) bool {
return false
}
tr = newtr
tr.tracer = newTracer()
origTrie = tr.Copy()
case opItercheckhash:
checktr, _ := New(common.Hash{}, triedb)
it := NewIterator(tr.NodeIterator(nil))
@ -455,6 +464,59 @@ func runRandTest(rt randTest) bool {
if tr.Hash() != checktr.Hash() {
rt[i].err = fmt.Errorf("hash mismatch in opItercheckhash")
}
case opNodeDiff:
var (
inserted = tr.tracer.insertList()
deleted = tr.tracer.deleteList()
origIter = origTrie.NodeIterator(nil)
curIter = tr.NodeIterator(nil)
origSeen = make(map[string]struct{})
curSeen = make(map[string]struct{})
)
for origIter.Next(true) {
if origIter.Leaf() {
continue
}
origSeen[string(origIter.Path())] = struct{}{}
}
for curIter.Next(true) {
if curIter.Leaf() {
continue
}
curSeen[string(curIter.Path())] = struct{}{}
}
var (
insertExp = make(map[string]struct{})
deleteExp = make(map[string]struct{})
)
for path := range curSeen {
_, present := origSeen[path]
if !present {
insertExp[path] = struct{}{}
}
}
for path := range origSeen {
_, present := curSeen[path]
if !present {
deleteExp[path] = struct{}{}
}
}
if len(insertExp) != len(inserted) {
rt[i].err = fmt.Errorf("insert set mismatch")
}
if len(deleteExp) != len(deleted) {
rt[i].err = fmt.Errorf("delete set mismatch")
}
for _, insert := range inserted {
if _, present := insertExp[string(insert)]; !present {
rt[i].err = fmt.Errorf("missing inserted node")
}
}
for _, del := range deleted {
if _, present := deleteExp[string(del)]; !present {
rt[i].err = fmt.Errorf("missing deleted node")
}
}
}
// Abort the test on error.
if rt[i].err != nil {
@ -481,7 +543,7 @@ func BenchmarkUpdateLE(b *testing.B) { benchUpdate(b, binary.LittleEndian) }
const benchElemCount = 20000
func benchGet(b *testing.B, commit bool) {
trie := new(Trie)
trie, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()))
if commit {
_, tmpdb := tempDB()
trie, _ = New(common.Hash{}, tmpdb)