|
|
|
@ -26,47 +26,40 @@ import ( |
|
|
|
|
"github.com/ethereum/go-ethereum/common" |
|
|
|
|
"github.com/ethereum/go-ethereum/core/rawdb" |
|
|
|
|
"github.com/ethereum/go-ethereum/ethdb" |
|
|
|
|
"github.com/ethereum/go-ethereum/ethdb/memorydb" |
|
|
|
|
"github.com/ethereum/go-ethereum/log" |
|
|
|
|
"github.com/ethereum/go-ethereum/rlp" |
|
|
|
|
"github.com/ethereum/go-ethereum/trie" |
|
|
|
|
"golang.org/x/crypto/sha3" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
func hashData(input []byte) common.Hash { |
|
|
|
|
var hasher = sha3.NewLegacyKeccak256() |
|
|
|
|
var hash common.Hash |
|
|
|
|
hasher.Reset() |
|
|
|
|
hasher.Write(input) |
|
|
|
|
hasher.Sum(hash[:0]) |
|
|
|
|
return hash |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Tests that snapshot generation from an empty database.
|
|
|
|
|
func TestGeneration(t *testing.T) { |
|
|
|
|
// We can't use statedb to make a test trie (circular dependency), so make
|
|
|
|
|
// a fake one manually. We're going with a small account trie of 3 accounts,
|
|
|
|
|
// two of which also has the same 3-slot storage trie attached.
|
|
|
|
|
var ( |
|
|
|
|
diskdb = memorydb.New() |
|
|
|
|
triedb = trie.NewDatabase(diskdb) |
|
|
|
|
) |
|
|
|
|
stTrie, _ := trie.NewSecure(common.Hash{}, triedb) |
|
|
|
|
stTrie.Update([]byte("key-1"), []byte("val-1")) // 0x1314700b81afc49f94db3623ef1df38f3ed18b73a1b7ea2f6c095118cf6118a0
|
|
|
|
|
stTrie.Update([]byte("key-2"), []byte("val-2")) // 0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371
|
|
|
|
|
stTrie.Update([]byte("key-3"), []byte("val-3")) // 0x51c71a47af0695957647fb68766d0becee77e953df17c29b3c2f25436f055c78
|
|
|
|
|
stTrie.Commit(nil) // Root: 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
|
|
|
|
|
|
|
|
|
|
accTrie, _ := trie.NewSecure(common.Hash{}, triedb) |
|
|
|
|
acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} |
|
|
|
|
val, _ := rlp.EncodeToBytes(acc) |
|
|
|
|
accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
|
|
|
|
|
var helper = newHelper() |
|
|
|
|
stRoot := helper.makeStorageTrie(common.Hash{}, common.Hash{}, []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, false) |
|
|
|
|
|
|
|
|
|
acc = &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} |
|
|
|
|
val, _ = rlp.EncodeToBytes(acc) |
|
|
|
|
accTrie.Update([]byte("acc-2"), val) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
|
|
|
|
|
helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) |
|
|
|
|
helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) |
|
|
|
|
helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: emptyCode.Bytes()}) |
|
|
|
|
|
|
|
|
|
acc = &Account{Balance: big.NewInt(3), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} |
|
|
|
|
val, _ = rlp.EncodeToBytes(acc) |
|
|
|
|
accTrie.Update([]byte("acc-3"), val) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
|
|
|
|
|
root, _, _ := accTrie.Commit(nil) // Root: 0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd
|
|
|
|
|
triedb.Commit(root, false, nil) |
|
|
|
|
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) |
|
|
|
|
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) |
|
|
|
|
|
|
|
|
|
root, snap := helper.CommitAndGenerate() |
|
|
|
|
if have, want := root, common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd"); have != want { |
|
|
|
|
t.Fatalf("have %#x want %#x", have, want) |
|
|
|
|
} |
|
|
|
|
snap := generateSnapshot(diskdb, triedb, 16, root) |
|
|
|
|
select { |
|
|
|
|
case <-snap.genPending: |
|
|
|
|
// Snapshot generation succeeded
|
|
|
|
@ -75,63 +68,34 @@ func TestGeneration(t *testing.T) { |
|
|
|
|
t.Errorf("Snapshot generation failed") |
|
|
|
|
} |
|
|
|
|
checkSnapRoot(t, snap, root) |
|
|
|
|
|
|
|
|
|
// Signal abortion to the generator and wait for it to tear down
|
|
|
|
|
stop := make(chan *generatorStats) |
|
|
|
|
snap.genAbort <- stop |
|
|
|
|
<-stop |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func hashData(input []byte) common.Hash { |
|
|
|
|
var hasher = sha3.NewLegacyKeccak256() |
|
|
|
|
var hash common.Hash |
|
|
|
|
hasher.Reset() |
|
|
|
|
hasher.Write(input) |
|
|
|
|
hasher.Sum(hash[:0]) |
|
|
|
|
return hash |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Tests that snapshot generation with existent flat state.
|
|
|
|
|
func TestGenerateExistentState(t *testing.T) { |
|
|
|
|
// We can't use statedb to make a test trie (circular dependency), so make
|
|
|
|
|
// a fake one manually. We're going with a small account trie of 3 accounts,
|
|
|
|
|
// two of which also has the same 3-slot storage trie attached.
|
|
|
|
|
var ( |
|
|
|
|
diskdb = memorydb.New() |
|
|
|
|
triedb = trie.NewDatabase(diskdb) |
|
|
|
|
) |
|
|
|
|
stTrie, _ := trie.NewSecure(common.Hash{}, triedb) |
|
|
|
|
stTrie.Update([]byte("key-1"), []byte("val-1")) // 0x1314700b81afc49f94db3623ef1df38f3ed18b73a1b7ea2f6c095118cf6118a0
|
|
|
|
|
stTrie.Update([]byte("key-2"), []byte("val-2")) // 0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371
|
|
|
|
|
stTrie.Update([]byte("key-3"), []byte("val-3")) // 0x51c71a47af0695957647fb68766d0becee77e953df17c29b3c2f25436f055c78
|
|
|
|
|
stTrie.Commit(nil) // Root: 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
|
|
|
|
|
|
|
|
|
|
accTrie, _ := trie.NewSecure(common.Hash{}, triedb) |
|
|
|
|
acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} |
|
|
|
|
val, _ := rlp.EncodeToBytes(acc) |
|
|
|
|
accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
|
|
|
|
|
rawdb.WriteAccountSnapshot(diskdb, hashData([]byte("acc-1")), val) |
|
|
|
|
rawdb.WriteStorageSnapshot(diskdb, hashData([]byte("acc-1")), hashData([]byte("key-1")), []byte("val-1")) |
|
|
|
|
rawdb.WriteStorageSnapshot(diskdb, hashData([]byte("acc-1")), hashData([]byte("key-2")), []byte("val-2")) |
|
|
|
|
rawdb.WriteStorageSnapshot(diskdb, hashData([]byte("acc-1")), hashData([]byte("key-3")), []byte("val-3")) |
|
|
|
|
|
|
|
|
|
acc = &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} |
|
|
|
|
val, _ = rlp.EncodeToBytes(acc) |
|
|
|
|
accTrie.Update([]byte("acc-2"), val) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
|
|
|
|
|
diskdb.Put(hashData([]byte("acc-2")).Bytes(), val) |
|
|
|
|
rawdb.WriteAccountSnapshot(diskdb, hashData([]byte("acc-2")), val) |
|
|
|
|
|
|
|
|
|
acc = &Account{Balance: big.NewInt(3), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} |
|
|
|
|
val, _ = rlp.EncodeToBytes(acc) |
|
|
|
|
accTrie.Update([]byte("acc-3"), val) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
|
|
|
|
|
rawdb.WriteAccountSnapshot(diskdb, hashData([]byte("acc-3")), val) |
|
|
|
|
rawdb.WriteStorageSnapshot(diskdb, hashData([]byte("acc-3")), hashData([]byte("key-1")), []byte("val-1")) |
|
|
|
|
rawdb.WriteStorageSnapshot(diskdb, hashData([]byte("acc-3")), hashData([]byte("key-2")), []byte("val-2")) |
|
|
|
|
rawdb.WriteStorageSnapshot(diskdb, hashData([]byte("acc-3")), hashData([]byte("key-3")), []byte("val-3")) |
|
|
|
|
|
|
|
|
|
root, _, _ := accTrie.Commit(nil) // Root: 0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd
|
|
|
|
|
triedb.Commit(root, false, nil) |
|
|
|
|
|
|
|
|
|
snap := generateSnapshot(diskdb, triedb, 16, root) |
|
|
|
|
var helper = newHelper() |
|
|
|
|
|
|
|
|
|
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) |
|
|
|
|
helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) |
|
|
|
|
helper.addSnapAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) |
|
|
|
|
helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) |
|
|
|
|
|
|
|
|
|
helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) |
|
|
|
|
helper.addSnapAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) |
|
|
|
|
|
|
|
|
|
stRoot = helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) |
|
|
|
|
helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: emptyCode.Bytes()}) |
|
|
|
|
helper.addSnapAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: emptyCode.Bytes()}) |
|
|
|
|
helper.addSnapStorage("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) |
|
|
|
|
|
|
|
|
|
root, snap := helper.CommitAndGenerate() |
|
|
|
|
select { |
|
|
|
|
case <-snap.genPending: |
|
|
|
|
// Snapshot generation succeeded
|
|
|
|
@ -140,6 +104,7 @@ func TestGenerateExistentState(t *testing.T) { |
|
|
|
|
t.Errorf("Snapshot generation failed") |
|
|
|
|
} |
|
|
|
|
checkSnapRoot(t, snap, root) |
|
|
|
|
|
|
|
|
|
// Signal abortion to the generator and wait for it to tear down
|
|
|
|
|
stop := make(chan *generatorStats) |
|
|
|
|
snap.genAbort <- stop |
|
|
|
@ -163,7 +128,6 @@ func checkSnapRoot(t *testing.T, snap *diskLayer, trieRoot common.Hash) { |
|
|
|
|
} |
|
|
|
|
return hash, nil |
|
|
|
|
}, newGenerateStats(), true) |
|
|
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
@ -176,15 +140,15 @@ func checkSnapRoot(t *testing.T, snap *diskLayer, trieRoot common.Hash) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
type testHelper struct { |
|
|
|
|
diskdb *memorydb.Database |
|
|
|
|
diskdb ethdb.Database |
|
|
|
|
triedb *trie.Database |
|
|
|
|
accTrie *trie.SecureTrie |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func newHelper() *testHelper { |
|
|
|
|
diskdb := memorydb.New() |
|
|
|
|
diskdb := rawdb.NewMemoryDatabase() |
|
|
|
|
triedb := trie.NewDatabase(diskdb) |
|
|
|
|
accTrie, _ := trie.NewSecure(common.Hash{}, triedb) |
|
|
|
|
accTrie, _ := trie.NewSecure(common.Hash{}, common.Hash{}, triedb) |
|
|
|
|
return &testHelper{ |
|
|
|
|
diskdb: diskdb, |
|
|
|
|
triedb: triedb, |
|
|
|
@ -215,18 +179,28 @@ func (t *testHelper) addSnapStorage(accKey string, keys []string, vals []string) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (t *testHelper) makeStorageTrie(keys []string, vals []string) []byte { |
|
|
|
|
stTrie, _ := trie.NewSecure(common.Hash{}, t.triedb) |
|
|
|
|
func (t *testHelper) makeStorageTrie(stateRoot, owner common.Hash, keys []string, vals []string, commit bool) []byte { |
|
|
|
|
stTrie, _ := trie.NewSecure(owner, common.Hash{}, t.triedb) |
|
|
|
|
for i, k := range keys { |
|
|
|
|
stTrie.Update([]byte(k), []byte(vals[i])) |
|
|
|
|
} |
|
|
|
|
root, _, _ := stTrie.Commit(nil) |
|
|
|
|
var root common.Hash |
|
|
|
|
if !commit { |
|
|
|
|
root = stTrie.Hash() |
|
|
|
|
} else { |
|
|
|
|
root, _, _ = stTrie.Commit(nil) |
|
|
|
|
} |
|
|
|
|
return root.Bytes() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (t *testHelper) Generate() (common.Hash, *diskLayer) { |
|
|
|
|
func (t *testHelper) Commit() common.Hash { |
|
|
|
|
root, _, _ := t.accTrie.Commit(nil) |
|
|
|
|
t.triedb.Commit(root, false, nil) |
|
|
|
|
return root |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (t *testHelper) CommitAndGenerate() (common.Hash, *diskLayer) { |
|
|
|
|
root := t.Commit() |
|
|
|
|
snap := generateSnapshot(t.diskdb, t.triedb, 16, root) |
|
|
|
|
return root, snap |
|
|
|
|
} |
|
|
|
@ -249,26 +223,29 @@ func (t *testHelper) Generate() (common.Hash, *diskLayer) { |
|
|
|
|
// - extra slots in the end
|
|
|
|
|
func TestGenerateExistentStateWithWrongStorage(t *testing.T) { |
|
|
|
|
helper := newHelper() |
|
|
|
|
stRoot := helper.makeStorageTrie([]string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) |
|
|
|
|
|
|
|
|
|
// Account one, empty root but non-empty database
|
|
|
|
|
helper.addAccount("acc-1", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) |
|
|
|
|
helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) |
|
|
|
|
|
|
|
|
|
// Account two, non empty root but empty database
|
|
|
|
|
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-2")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) |
|
|
|
|
helper.addAccount("acc-2", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) |
|
|
|
|
|
|
|
|
|
// Miss slots
|
|
|
|
|
{ |
|
|
|
|
// Account three, non empty root but misses slots in the beginning
|
|
|
|
|
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) |
|
|
|
|
helper.addAccount("acc-3", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) |
|
|
|
|
helper.addSnapStorage("acc-3", []string{"key-2", "key-3"}, []string{"val-2", "val-3"}) |
|
|
|
|
|
|
|
|
|
// Account four, non empty root but misses slots in the middle
|
|
|
|
|
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-4")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) |
|
|
|
|
helper.addAccount("acc-4", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) |
|
|
|
|
helper.addSnapStorage("acc-4", []string{"key-1", "key-3"}, []string{"val-1", "val-3"}) |
|
|
|
|
|
|
|
|
|
// Account five, non empty root but misses slots in the end
|
|
|
|
|
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-5")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) |
|
|
|
|
helper.addAccount("acc-5", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) |
|
|
|
|
helper.addSnapStorage("acc-5", []string{"key-1", "key-2"}, []string{"val-1", "val-2"}) |
|
|
|
|
} |
|
|
|
@ -276,18 +253,22 @@ func TestGenerateExistentStateWithWrongStorage(t *testing.T) { |
|
|
|
|
// Wrong storage slots
|
|
|
|
|
{ |
|
|
|
|
// Account six, non empty root but wrong slots in the beginning
|
|
|
|
|
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-6")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) |
|
|
|
|
helper.addAccount("acc-6", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) |
|
|
|
|
helper.addSnapStorage("acc-6", []string{"key-1", "key-2", "key-3"}, []string{"badval-1", "val-2", "val-3"}) |
|
|
|
|
|
|
|
|
|
// Account seven, non empty root but wrong slots in the middle
|
|
|
|
|
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-7")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) |
|
|
|
|
helper.addAccount("acc-7", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) |
|
|
|
|
helper.addSnapStorage("acc-7", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "badval-2", "val-3"}) |
|
|
|
|
|
|
|
|
|
// Account eight, non empty root but wrong slots in the end
|
|
|
|
|
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-8")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) |
|
|
|
|
helper.addAccount("acc-8", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) |
|
|
|
|
helper.addSnapStorage("acc-8", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "badval-3"}) |
|
|
|
|
|
|
|
|
|
// Account 9, non empty root but rotated slots
|
|
|
|
|
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-9")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) |
|
|
|
|
helper.addAccount("acc-9", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) |
|
|
|
|
helper.addSnapStorage("acc-9", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-3", "val-2"}) |
|
|
|
|
} |
|
|
|
@ -295,19 +276,22 @@ func TestGenerateExistentStateWithWrongStorage(t *testing.T) { |
|
|
|
|
// Extra storage slots
|
|
|
|
|
{ |
|
|
|
|
// Account 10, non empty root but extra slots in the beginning
|
|
|
|
|
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-10")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) |
|
|
|
|
helper.addAccount("acc-10", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) |
|
|
|
|
helper.addSnapStorage("acc-10", []string{"key-0", "key-1", "key-2", "key-3"}, []string{"val-0", "val-1", "val-2", "val-3"}) |
|
|
|
|
|
|
|
|
|
// Account 11, non empty root but extra slots in the middle
|
|
|
|
|
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-11")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) |
|
|
|
|
helper.addAccount("acc-11", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) |
|
|
|
|
helper.addSnapStorage("acc-11", []string{"key-1", "key-2", "key-2-1", "key-3"}, []string{"val-1", "val-2", "val-2-1", "val-3"}) |
|
|
|
|
|
|
|
|
|
// Account 12, non empty root but extra slots in the end
|
|
|
|
|
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-12")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) |
|
|
|
|
helper.addAccount("acc-12", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) |
|
|
|
|
helper.addSnapStorage("acc-12", []string{"key-1", "key-2", "key-3", "key-4"}, []string{"val-1", "val-2", "val-3", "val-4"}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
root, snap := helper.Generate() |
|
|
|
|
root, snap := helper.CommitAndGenerate() |
|
|
|
|
t.Logf("Root: %#x\n", root) // Root = 0x8746cce9fd9c658b2cfd639878ed6584b7a2b3e73bb40f607fcfa156002429a0
|
|
|
|
|
|
|
|
|
|
select { |
|
|
|
@ -331,7 +315,12 @@ func TestGenerateExistentStateWithWrongStorage(t *testing.T) { |
|
|
|
|
// - extra accounts
|
|
|
|
|
func TestGenerateExistentStateWithWrongAccounts(t *testing.T) { |
|
|
|
|
helper := newHelper() |
|
|
|
|
stRoot := helper.makeStorageTrie([]string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) |
|
|
|
|
|
|
|
|
|
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) |
|
|
|
|
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-2")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) |
|
|
|
|
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) |
|
|
|
|
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-4")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) |
|
|
|
|
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-6")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) |
|
|
|
|
|
|
|
|
|
// Trie accounts [acc-1, acc-2, acc-3, acc-4, acc-6]
|
|
|
|
|
// Extra accounts [acc-0, acc-5, acc-7]
|
|
|
|
@ -359,7 +348,7 @@ func TestGenerateExistentStateWithWrongAccounts(t *testing.T) { |
|
|
|
|
helper.addSnapAccount("acc-7", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyRoot.Bytes()}) // after the end
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
root, snap := helper.Generate() |
|
|
|
|
root, snap := helper.CommitAndGenerate() |
|
|
|
|
t.Logf("Root: %#x\n", root) // Root = 0x825891472281463511e7ebcc7f109e4f9200c20fa384754e11fd605cd98464e8
|
|
|
|
|
|
|
|
|
|
select { |
|
|
|
@ -383,29 +372,19 @@ func TestGenerateCorruptAccountTrie(t *testing.T) { |
|
|
|
|
// We can't use statedb to make a test trie (circular dependency), so make
|
|
|
|
|
// a fake one manually. We're going with a small account trie of 3 accounts,
|
|
|
|
|
// without any storage slots to keep the test smaller.
|
|
|
|
|
var ( |
|
|
|
|
diskdb = memorydb.New() |
|
|
|
|
triedb = trie.NewDatabase(diskdb) |
|
|
|
|
) |
|
|
|
|
tr, _ := trie.NewSecure(common.Hash{}, triedb) |
|
|
|
|
acc := &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} |
|
|
|
|
val, _ := rlp.EncodeToBytes(acc) |
|
|
|
|
tr.Update([]byte("acc-1"), val) // 0xc7a30f39aff471c95d8a837497ad0e49b65be475cc0953540f80cfcdbdcd9074
|
|
|
|
|
helper := newHelper() |
|
|
|
|
|
|
|
|
|
acc = &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} |
|
|
|
|
val, _ = rlp.EncodeToBytes(acc) |
|
|
|
|
tr.Update([]byte("acc-2"), val) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
|
|
|
|
|
helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) // 0xc7a30f39aff471c95d8a837497ad0e49b65be475cc0953540f80cfcdbdcd9074
|
|
|
|
|
helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
|
|
|
|
|
helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) // 0x19ead688e907b0fab07176120dceec244a72aff2f0aa51e8b827584e378772f4
|
|
|
|
|
|
|
|
|
|
acc = &Account{Balance: big.NewInt(3), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} |
|
|
|
|
val, _ = rlp.EncodeToBytes(acc) |
|
|
|
|
tr.Update([]byte("acc-3"), val) // 0x19ead688e907b0fab07176120dceec244a72aff2f0aa51e8b827584e378772f4
|
|
|
|
|
tr.Commit(nil) // Root: 0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978
|
|
|
|
|
root, _, _ := helper.accTrie.Commit(nil) // Root: 0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978
|
|
|
|
|
|
|
|
|
|
// Delete an account trie leaf and ensure the generator chokes
|
|
|
|
|
triedb.Commit(common.HexToHash("0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978"), false, nil) |
|
|
|
|
diskdb.Delete(common.HexToHash("0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7").Bytes()) |
|
|
|
|
helper.triedb.Commit(root, false, nil) |
|
|
|
|
helper.diskdb.Delete(common.HexToHash("0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7").Bytes()) |
|
|
|
|
|
|
|
|
|
snap := generateSnapshot(diskdb, triedb, 16, common.HexToHash("0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978")) |
|
|
|
|
snap := generateSnapshot(helper.diskdb, helper.triedb, 16, root) |
|
|
|
|
select { |
|
|
|
|
case <-snap.genPending: |
|
|
|
|
// Snapshot generation succeeded
|
|
|
|
@ -427,45 +406,30 @@ func TestGenerateMissingStorageTrie(t *testing.T) { |
|
|
|
|
// We can't use statedb to make a test trie (circular dependency), so make
|
|
|
|
|
// a fake one manually. We're going with a small account trie of 3 accounts,
|
|
|
|
|
// two of which also has the same 3-slot storage trie attached.
|
|
|
|
|
var ( |
|
|
|
|
diskdb = memorydb.New() |
|
|
|
|
triedb = trie.NewDatabase(diskdb) |
|
|
|
|
) |
|
|
|
|
stTrie, _ := trie.NewSecure(common.Hash{}, triedb) |
|
|
|
|
stTrie.Update([]byte("key-1"), []byte("val-1")) // 0x1314700b81afc49f94db3623ef1df38f3ed18b73a1b7ea2f6c095118cf6118a0
|
|
|
|
|
stTrie.Update([]byte("key-2"), []byte("val-2")) // 0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371
|
|
|
|
|
stTrie.Update([]byte("key-3"), []byte("val-3")) // 0x51c71a47af0695957647fb68766d0becee77e953df17c29b3c2f25436f055c78
|
|
|
|
|
stTrie.Commit(nil) // Root: 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
|
|
|
|
|
|
|
|
|
|
accTrie, _ := trie.NewSecure(common.Hash{}, triedb) |
|
|
|
|
acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} |
|
|
|
|
val, _ := rlp.EncodeToBytes(acc) |
|
|
|
|
accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
|
|
|
|
|
|
|
|
|
|
acc = &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} |
|
|
|
|
val, _ = rlp.EncodeToBytes(acc) |
|
|
|
|
accTrie.Update([]byte("acc-2"), val) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
|
|
|
|
|
helper := newHelper() |
|
|
|
|
|
|
|
|
|
acc = &Account{Balance: big.NewInt(3), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} |
|
|
|
|
val, _ = rlp.EncodeToBytes(acc) |
|
|
|
|
accTrie.Update([]byte("acc-3"), val) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
|
|
|
|
|
accTrie.Commit(nil) // Root: 0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd
|
|
|
|
|
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
|
|
|
|
|
helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
|
|
|
|
|
helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
|
|
|
|
|
stRoot = helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) |
|
|
|
|
helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: emptyCode.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
|
|
|
|
|
root, _, _ := helper.accTrie.Commit(nil) |
|
|
|
|
|
|
|
|
|
// We can only corrupt the disk database, so flush the tries out
|
|
|
|
|
triedb.Reference( |
|
|
|
|
common.HexToHash("0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67"), |
|
|
|
|
helper.triedb.Reference( |
|
|
|
|
common.BytesToHash(stRoot), |
|
|
|
|
common.HexToHash("0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e"), |
|
|
|
|
) |
|
|
|
|
triedb.Reference( |
|
|
|
|
common.HexToHash("0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67"), |
|
|
|
|
helper.triedb.Reference( |
|
|
|
|
common.BytesToHash(stRoot), |
|
|
|
|
common.HexToHash("0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2"), |
|
|
|
|
) |
|
|
|
|
triedb.Commit(common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd"), false, nil) |
|
|
|
|
helper.triedb.Commit(root, false, nil) |
|
|
|
|
|
|
|
|
|
// Delete a storage trie root and ensure the generator chokes
|
|
|
|
|
diskdb.Delete(common.HexToHash("0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67").Bytes()) |
|
|
|
|
helper.diskdb.Delete(stRoot) |
|
|
|
|
|
|
|
|
|
snap := generateSnapshot(diskdb, triedb, 16, common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd")) |
|
|
|
|
snap := generateSnapshot(helper.diskdb, helper.triedb, 16, root) |
|
|
|
|
select { |
|
|
|
|
case <-snap.genPending: |
|
|
|
|
// Snapshot generation succeeded
|
|
|
|
@ -486,45 +450,31 @@ func TestGenerateCorruptStorageTrie(t *testing.T) { |
|
|
|
|
// We can't use statedb to make a test trie (circular dependency), so make
|
|
|
|
|
// a fake one manually. We're going with a small account trie of 3 accounts,
|
|
|
|
|
// two of which also has the same 3-slot storage trie attached.
|
|
|
|
|
var ( |
|
|
|
|
diskdb = memorydb.New() |
|
|
|
|
triedb = trie.NewDatabase(diskdb) |
|
|
|
|
) |
|
|
|
|
stTrie, _ := trie.NewSecure(common.Hash{}, triedb) |
|
|
|
|
stTrie.Update([]byte("key-1"), []byte("val-1")) // 0x1314700b81afc49f94db3623ef1df38f3ed18b73a1b7ea2f6c095118cf6118a0
|
|
|
|
|
stTrie.Update([]byte("key-2"), []byte("val-2")) // 0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371
|
|
|
|
|
stTrie.Update([]byte("key-3"), []byte("val-3")) // 0x51c71a47af0695957647fb68766d0becee77e953df17c29b3c2f25436f055c78
|
|
|
|
|
stTrie.Commit(nil) // Root: 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
|
|
|
|
|
|
|
|
|
|
accTrie, _ := trie.NewSecure(common.Hash{}, triedb) |
|
|
|
|
acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} |
|
|
|
|
val, _ := rlp.EncodeToBytes(acc) |
|
|
|
|
accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
|
|
|
|
|
helper := newHelper() |
|
|
|
|
|
|
|
|
|
acc = &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} |
|
|
|
|
val, _ = rlp.EncodeToBytes(acc) |
|
|
|
|
accTrie.Update([]byte("acc-2"), val) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
|
|
|
|
|
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
|
|
|
|
|
helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
|
|
|
|
|
helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
|
|
|
|
|
stRoot = helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) |
|
|
|
|
helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: emptyCode.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
|
|
|
|
|
|
|
|
|
|
acc = &Account{Balance: big.NewInt(3), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} |
|
|
|
|
val, _ = rlp.EncodeToBytes(acc) |
|
|
|
|
accTrie.Update([]byte("acc-3"), val) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
|
|
|
|
|
accTrie.Commit(nil) // Root: 0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd
|
|
|
|
|
root, _, _ := helper.accTrie.Commit(nil) |
|
|
|
|
|
|
|
|
|
// We can only corrupt the disk database, so flush the tries out
|
|
|
|
|
triedb.Reference( |
|
|
|
|
common.HexToHash("0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67"), |
|
|
|
|
helper.triedb.Reference( |
|
|
|
|
common.BytesToHash(stRoot), |
|
|
|
|
common.HexToHash("0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e"), |
|
|
|
|
) |
|
|
|
|
triedb.Reference( |
|
|
|
|
common.HexToHash("0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67"), |
|
|
|
|
helper.triedb.Reference( |
|
|
|
|
common.BytesToHash(stRoot), |
|
|
|
|
common.HexToHash("0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2"), |
|
|
|
|
) |
|
|
|
|
triedb.Commit(common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd"), false, nil) |
|
|
|
|
helper.triedb.Commit(root, false, nil) |
|
|
|
|
|
|
|
|
|
// Delete a storage trie leaf and ensure the generator chokes
|
|
|
|
|
diskdb.Delete(common.HexToHash("0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371").Bytes()) |
|
|
|
|
helper.diskdb.Delete(common.HexToHash("0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371").Bytes()) |
|
|
|
|
|
|
|
|
|
snap := generateSnapshot(diskdb, triedb, 16, common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd")) |
|
|
|
|
snap := generateSnapshot(helper.diskdb, helper.triedb, 16, root) |
|
|
|
|
select { |
|
|
|
|
case <-snap.genPending: |
|
|
|
|
// Snapshot generation succeeded
|
|
|
|
@ -539,56 +489,51 @@ func TestGenerateCorruptStorageTrie(t *testing.T) { |
|
|
|
|
<-stop |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func getStorageTrie(n int, triedb *trie.Database) *trie.SecureTrie { |
|
|
|
|
stTrie, _ := trie.NewSecure(common.Hash{}, triedb) |
|
|
|
|
for i := 0; i < n; i++ { |
|
|
|
|
k := fmt.Sprintf("key-%d", i) |
|
|
|
|
v := fmt.Sprintf("val-%d", i) |
|
|
|
|
stTrie.Update([]byte(k), []byte(v)) |
|
|
|
|
} |
|
|
|
|
stTrie.Commit(nil) |
|
|
|
|
return stTrie |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Tests that snapshot generation when an extra account with storage exists in the snap state.
|
|
|
|
|
func TestGenerateWithExtraAccounts(t *testing.T) { |
|
|
|
|
var ( |
|
|
|
|
diskdb = memorydb.New() |
|
|
|
|
triedb = trie.NewDatabase(diskdb) |
|
|
|
|
stTrie = getStorageTrie(5, triedb) |
|
|
|
|
) |
|
|
|
|
accTrie, _ := trie.NewSecure(common.Hash{}, triedb) |
|
|
|
|
{ // Account one in the trie
|
|
|
|
|
acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} |
|
|
|
|
helper := newHelper() |
|
|
|
|
{ |
|
|
|
|
// Account one in the trie
|
|
|
|
|
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), |
|
|
|
|
[]string{"key-1", "key-2", "key-3", "key-4", "key-5"}, |
|
|
|
|
[]string{"val-1", "val-2", "val-3", "val-4", "val-5"}, |
|
|
|
|
true, |
|
|
|
|
) |
|
|
|
|
acc := &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()} |
|
|
|
|
val, _ := rlp.EncodeToBytes(acc) |
|
|
|
|
accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
|
|
|
|
|
helper.accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
|
|
|
|
|
|
|
|
|
|
// Identical in the snap
|
|
|
|
|
key := hashData([]byte("acc-1")) |
|
|
|
|
rawdb.WriteAccountSnapshot(diskdb, key, val) |
|
|
|
|
rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-1")), []byte("val-1")) |
|
|
|
|
rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-2")), []byte("val-2")) |
|
|
|
|
rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-3")), []byte("val-3")) |
|
|
|
|
rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-4")), []byte("val-4")) |
|
|
|
|
rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-5")), []byte("val-5")) |
|
|
|
|
} |
|
|
|
|
{ // Account two exists only in the snapshot
|
|
|
|
|
acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} |
|
|
|
|
rawdb.WriteAccountSnapshot(helper.triedb.DiskDB(), key, val) |
|
|
|
|
rawdb.WriteStorageSnapshot(helper.triedb.DiskDB(), key, hashData([]byte("key-1")), []byte("val-1")) |
|
|
|
|
rawdb.WriteStorageSnapshot(helper.triedb.DiskDB(), key, hashData([]byte("key-2")), []byte("val-2")) |
|
|
|
|
rawdb.WriteStorageSnapshot(helper.triedb.DiskDB(), key, hashData([]byte("key-3")), []byte("val-3")) |
|
|
|
|
rawdb.WriteStorageSnapshot(helper.triedb.DiskDB(), key, hashData([]byte("key-4")), []byte("val-4")) |
|
|
|
|
rawdb.WriteStorageSnapshot(helper.triedb.DiskDB(), key, hashData([]byte("key-5")), []byte("val-5")) |
|
|
|
|
} |
|
|
|
|
{ |
|
|
|
|
// Account two exists only in the snapshot
|
|
|
|
|
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-2")), |
|
|
|
|
[]string{"key-1", "key-2", "key-3", "key-4", "key-5"}, |
|
|
|
|
[]string{"val-1", "val-2", "val-3", "val-4", "val-5"}, |
|
|
|
|
true, |
|
|
|
|
) |
|
|
|
|
acc := &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()} |
|
|
|
|
val, _ := rlp.EncodeToBytes(acc) |
|
|
|
|
key := hashData([]byte("acc-2")) |
|
|
|
|
rawdb.WriteAccountSnapshot(diskdb, key, val) |
|
|
|
|
rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("b-key-1")), []byte("b-val-1")) |
|
|
|
|
rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("b-key-2")), []byte("b-val-2")) |
|
|
|
|
rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("b-key-3")), []byte("b-val-3")) |
|
|
|
|
} |
|
|
|
|
root, _, _ := accTrie.Commit(nil) |
|
|
|
|
t.Logf("root: %x", root) |
|
|
|
|
triedb.Commit(root, false, nil) |
|
|
|
|
rawdb.WriteAccountSnapshot(helper.triedb.DiskDB(), key, val) |
|
|
|
|
rawdb.WriteStorageSnapshot(helper.triedb.DiskDB(), key, hashData([]byte("b-key-1")), []byte("b-val-1")) |
|
|
|
|
rawdb.WriteStorageSnapshot(helper.triedb.DiskDB(), key, hashData([]byte("b-key-2")), []byte("b-val-2")) |
|
|
|
|
rawdb.WriteStorageSnapshot(helper.triedb.DiskDB(), key, hashData([]byte("b-key-3")), []byte("b-val-3")) |
|
|
|
|
} |
|
|
|
|
root := helper.Commit() |
|
|
|
|
|
|
|
|
|
// To verify the test: If we now inspect the snap db, there should exist extraneous storage items
|
|
|
|
|
if data := rawdb.ReadStorageSnapshot(diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data == nil { |
|
|
|
|
if data := rawdb.ReadStorageSnapshot(helper.triedb.DiskDB(), hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data == nil { |
|
|
|
|
t.Fatalf("expected snap storage to exist") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
snap := generateSnapshot(diskdb, triedb, 16, root) |
|
|
|
|
snap := generateSnapshot(helper.diskdb, helper.triedb, 16, root) |
|
|
|
|
select { |
|
|
|
|
case <-snap.genPending: |
|
|
|
|
// Snapshot generation succeeded
|
|
|
|
@ -597,12 +542,13 @@ func TestGenerateWithExtraAccounts(t *testing.T) { |
|
|
|
|
t.Errorf("Snapshot generation failed") |
|
|
|
|
} |
|
|
|
|
checkSnapRoot(t, snap, root) |
|
|
|
|
|
|
|
|
|
// Signal abortion to the generator and wait for it to tear down
|
|
|
|
|
stop := make(chan *generatorStats) |
|
|
|
|
snap.genAbort <- stop |
|
|
|
|
<-stop |
|
|
|
|
// If we now inspect the snap db, there should exist no extraneous storage items
|
|
|
|
|
if data := rawdb.ReadStorageSnapshot(diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data != nil { |
|
|
|
|
if data := rawdb.ReadStorageSnapshot(helper.triedb.DiskDB(), hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data != nil { |
|
|
|
|
t.Fatalf("expected slot to be removed, got %v", string(data)) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -616,37 +562,36 @@ func TestGenerateWithManyExtraAccounts(t *testing.T) { |
|
|
|
|
if false { |
|
|
|
|
enableLogging() |
|
|
|
|
} |
|
|
|
|
var ( |
|
|
|
|
diskdb = memorydb.New() |
|
|
|
|
triedb = trie.NewDatabase(diskdb) |
|
|
|
|
stTrie = getStorageTrie(3, triedb) |
|
|
|
|
) |
|
|
|
|
accTrie, _ := trie.NewSecure(common.Hash{}, triedb) |
|
|
|
|
{ // Account one in the trie
|
|
|
|
|
acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} |
|
|
|
|
helper := newHelper() |
|
|
|
|
{ |
|
|
|
|
// Account one in the trie
|
|
|
|
|
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), |
|
|
|
|
[]string{"key-1", "key-2", "key-3"}, |
|
|
|
|
[]string{"val-1", "val-2", "val-3"}, |
|
|
|
|
true, |
|
|
|
|
) |
|
|
|
|
acc := &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()} |
|
|
|
|
val, _ := rlp.EncodeToBytes(acc) |
|
|
|
|
accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
|
|
|
|
|
helper.accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
|
|
|
|
|
|
|
|
|
|
// Identical in the snap
|
|
|
|
|
key := hashData([]byte("acc-1")) |
|
|
|
|
rawdb.WriteAccountSnapshot(diskdb, key, val) |
|
|
|
|
rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-1")), []byte("val-1")) |
|
|
|
|
rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-2")), []byte("val-2")) |
|
|
|
|
rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-3")), []byte("val-3")) |
|
|
|
|
rawdb.WriteAccountSnapshot(helper.diskdb, key, val) |
|
|
|
|
rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-1")), []byte("val-1")) |
|
|
|
|
rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-2")), []byte("val-2")) |
|
|
|
|
rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-3")), []byte("val-3")) |
|
|
|
|
} |
|
|
|
|
{ // 100 accounts exist only in snapshot
|
|
|
|
|
{ |
|
|
|
|
// 100 accounts exist only in snapshot
|
|
|
|
|
for i := 0; i < 1000; i++ { |
|
|
|
|
//acc := &Account{Balance: big.NewInt(int64(i)), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()}
|
|
|
|
|
acc := &Account{Balance: big.NewInt(int64(i)), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} |
|
|
|
|
val, _ := rlp.EncodeToBytes(acc) |
|
|
|
|
key := hashData([]byte(fmt.Sprintf("acc-%d", i))) |
|
|
|
|
rawdb.WriteAccountSnapshot(diskdb, key, val) |
|
|
|
|
rawdb.WriteAccountSnapshot(helper.diskdb, key, val) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
root, _, _ := accTrie.Commit(nil) |
|
|
|
|
t.Logf("root: %x", root) |
|
|
|
|
triedb.Commit(root, false, nil) |
|
|
|
|
|
|
|
|
|
snap := generateSnapshot(diskdb, triedb, 16, root) |
|
|
|
|
root, snap := helper.CommitAndGenerate() |
|
|
|
|
select { |
|
|
|
|
case <-snap.genPending: |
|
|
|
|
// Snapshot generation succeeded
|
|
|
|
@ -675,31 +620,22 @@ func TestGenerateWithExtraBeforeAndAfter(t *testing.T) { |
|
|
|
|
if false { |
|
|
|
|
enableLogging() |
|
|
|
|
} |
|
|
|
|
var ( |
|
|
|
|
diskdb = memorydb.New() |
|
|
|
|
triedb = trie.NewDatabase(diskdb) |
|
|
|
|
) |
|
|
|
|
accTrie, _ := trie.New(common.Hash{}, triedb) |
|
|
|
|
helper := newHelper() |
|
|
|
|
{ |
|
|
|
|
acc := &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} |
|
|
|
|
val, _ := rlp.EncodeToBytes(acc) |
|
|
|
|
accTrie.Update(common.HexToHash("0x03").Bytes(), val) |
|
|
|
|
accTrie.Update(common.HexToHash("0x07").Bytes(), val) |
|
|
|
|
|
|
|
|
|
rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x01"), val) |
|
|
|
|
rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x02"), val) |
|
|
|
|
rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x03"), val) |
|
|
|
|
rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x04"), val) |
|
|
|
|
rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x05"), val) |
|
|
|
|
rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x06"), val) |
|
|
|
|
rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x07"), val) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
root, _, _ := accTrie.Commit(nil) |
|
|
|
|
t.Logf("root: %x", root) |
|
|
|
|
triedb.Commit(root, false, nil) |
|
|
|
|
|
|
|
|
|
snap := generateSnapshot(diskdb, triedb, 16, root) |
|
|
|
|
helper.accTrie.Update(common.HexToHash("0x03").Bytes(), val) |
|
|
|
|
helper.accTrie.Update(common.HexToHash("0x07").Bytes(), val) |
|
|
|
|
|
|
|
|
|
rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x01"), val) |
|
|
|
|
rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x02"), val) |
|
|
|
|
rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x03"), val) |
|
|
|
|
rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x04"), val) |
|
|
|
|
rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x05"), val) |
|
|
|
|
rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x06"), val) |
|
|
|
|
rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x07"), val) |
|
|
|
|
} |
|
|
|
|
root, snap := helper.CommitAndGenerate() |
|
|
|
|
select { |
|
|
|
|
case <-snap.genPending: |
|
|
|
|
// Snapshot generation succeeded
|
|
|
|
@ -721,29 +657,20 @@ func TestGenerateWithMalformedSnapdata(t *testing.T) { |
|
|
|
|
if false { |
|
|
|
|
enableLogging() |
|
|
|
|
} |
|
|
|
|
var ( |
|
|
|
|
diskdb = memorydb.New() |
|
|
|
|
triedb = trie.NewDatabase(diskdb) |
|
|
|
|
) |
|
|
|
|
accTrie, _ := trie.New(common.Hash{}, triedb) |
|
|
|
|
helper := newHelper() |
|
|
|
|
{ |
|
|
|
|
acc := &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} |
|
|
|
|
val, _ := rlp.EncodeToBytes(acc) |
|
|
|
|
accTrie.Update(common.HexToHash("0x03").Bytes(), val) |
|
|
|
|
helper.accTrie.Update(common.HexToHash("0x03").Bytes(), val) |
|
|
|
|
|
|
|
|
|
junk := make([]byte, 100) |
|
|
|
|
copy(junk, []byte{0xde, 0xad}) |
|
|
|
|
rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x02"), junk) |
|
|
|
|
rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x03"), junk) |
|
|
|
|
rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x04"), junk) |
|
|
|
|
rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x05"), junk) |
|
|
|
|
rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x02"), junk) |
|
|
|
|
rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x03"), junk) |
|
|
|
|
rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x04"), junk) |
|
|
|
|
rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x05"), junk) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
root, _, _ := accTrie.Commit(nil) |
|
|
|
|
t.Logf("root: %x", root) |
|
|
|
|
triedb.Commit(root, false, nil) |
|
|
|
|
|
|
|
|
|
snap := generateSnapshot(diskdb, triedb, 16, root) |
|
|
|
|
root, snap := helper.CommitAndGenerate() |
|
|
|
|
select { |
|
|
|
|
case <-snap.genPending: |
|
|
|
|
// Snapshot generation succeeded
|
|
|
|
@ -757,7 +684,7 @@ func TestGenerateWithMalformedSnapdata(t *testing.T) { |
|
|
|
|
snap.genAbort <- stop |
|
|
|
|
<-stop |
|
|
|
|
// If we now inspect the snap db, there should exist no extraneous storage items
|
|
|
|
|
if data := rawdb.ReadStorageSnapshot(diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data != nil { |
|
|
|
|
if data := rawdb.ReadStorageSnapshot(helper.diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data != nil { |
|
|
|
|
t.Fatalf("expected slot to be removed, got %v", string(data)) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -767,13 +694,13 @@ func TestGenerateFromEmptySnap(t *testing.T) { |
|
|
|
|
accountCheckRange = 10 |
|
|
|
|
storageCheckRange = 20 |
|
|
|
|
helper := newHelper() |
|
|
|
|
stRoot := helper.makeStorageTrie([]string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) |
|
|
|
|
// Add 1K accounts to the trie
|
|
|
|
|
for i := 0; i < 400; i++ { |
|
|
|
|
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte(fmt.Sprintf("acc-%d", i))), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) |
|
|
|
|
helper.addTrieAccount(fmt.Sprintf("acc-%d", i), |
|
|
|
|
&Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) |
|
|
|
|
} |
|
|
|
|
root, snap := helper.Generate() |
|
|
|
|
root, snap := helper.CommitAndGenerate() |
|
|
|
|
t.Logf("Root: %#x\n", root) // Root: 0x6f7af6d2e1a1bf2b84a3beb3f8b64388465fbc1e274ca5d5d3fc787ca78f59e4
|
|
|
|
|
|
|
|
|
|
select { |
|
|
|
@ -802,12 +729,12 @@ func TestGenerateWithIncompleteStorage(t *testing.T) { |
|
|
|
|
helper := newHelper() |
|
|
|
|
stKeys := []string{"1", "2", "3", "4", "5", "6", "7", "8"} |
|
|
|
|
stVals := []string{"v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8"} |
|
|
|
|
stRoot := helper.makeStorageTrie(stKeys, stVals) |
|
|
|
|
// We add 8 accounts, each one is missing exactly one of the storage slots. This means
|
|
|
|
|
// we don't have to order the keys and figure out exactly which hash-key winds up
|
|
|
|
|
// on the sensitive spots at the boundaries
|
|
|
|
|
for i := 0; i < 8; i++ { |
|
|
|
|
accKey := fmt.Sprintf("acc-%d", i) |
|
|
|
|
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte(accKey)), stKeys, stVals, true) |
|
|
|
|
helper.addAccount(accKey, &Account{Balance: big.NewInt(int64(i)), Root: stRoot, CodeHash: emptyCode.Bytes()}) |
|
|
|
|
var moddedKeys []string |
|
|
|
|
var moddedVals []string |
|
|
|
@ -819,8 +746,7 @@ func TestGenerateWithIncompleteStorage(t *testing.T) { |
|
|
|
|
} |
|
|
|
|
helper.addSnapStorage(accKey, moddedKeys, moddedVals) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
root, snap := helper.Generate() |
|
|
|
|
root, snap := helper.CommitAndGenerate() |
|
|
|
|
t.Logf("Root: %#x\n", root) // Root: 0xca73f6f05ba4ca3024ef340ef3dfca8fdabc1b677ff13f5a9571fd49c16e67ff
|
|
|
|
|
|
|
|
|
|
select { |
|
|
|
@ -899,7 +825,7 @@ func populateDangling(disk ethdb.KeyValueStore) { |
|
|
|
|
// This test will populate some dangling storages to see if they can be cleaned up.
|
|
|
|
|
func TestGenerateCompleteSnapshotWithDanglingStorage(t *testing.T) { |
|
|
|
|
var helper = newHelper() |
|
|
|
|
stRoot := helper.makeStorageTrie([]string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) |
|
|
|
|
stRoot := helper.makeStorageTrie(common.Hash{}, common.Hash{}, []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) |
|
|
|
|
|
|
|
|
|
helper.addAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) |
|
|
|
|
helper.addAccount("acc-2", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) |
|
|
|
@ -910,7 +836,7 @@ func TestGenerateCompleteSnapshotWithDanglingStorage(t *testing.T) { |
|
|
|
|
|
|
|
|
|
populateDangling(helper.diskdb) |
|
|
|
|
|
|
|
|
|
root, snap := helper.Generate() |
|
|
|
|
root, snap := helper.CommitAndGenerate() |
|
|
|
|
select { |
|
|
|
|
case <-snap.genPending: |
|
|
|
|
// Snapshot generation succeeded
|
|
|
|
@ -932,7 +858,7 @@ func TestGenerateCompleteSnapshotWithDanglingStorage(t *testing.T) { |
|
|
|
|
// This test will populate some dangling storages to see if they can be cleaned up.
|
|
|
|
|
func TestGenerateBrokenSnapshotWithDanglingStorage(t *testing.T) { |
|
|
|
|
var helper = newHelper() |
|
|
|
|
stRoot := helper.makeStorageTrie([]string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) |
|
|
|
|
stRoot := helper.makeStorageTrie(common.Hash{}, common.Hash{}, []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) |
|
|
|
|
|
|
|
|
|
helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) |
|
|
|
|
helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) |
|
|
|
@ -940,7 +866,7 @@ func TestGenerateBrokenSnapshotWithDanglingStorage(t *testing.T) { |
|
|
|
|
|
|
|
|
|
populateDangling(helper.diskdb) |
|
|
|
|
|
|
|
|
|
root, snap := helper.Generate() |
|
|
|
|
root, snap := helper.CommitAndGenerate() |
|
|
|
|
select { |
|
|
|
|
case <-snap.genPending: |
|
|
|
|
// Snapshot generation succeeded
|
|
|
|
|