github.com/bearnetworkchain/go-bearnetwork@v1.10.19-0.20220604150648-d63890c2e42b/core/state/snapshot/generate_test.go (about) 1 // Copyright 2019 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package snapshot 18 19 import ( 20 "fmt" 21 "math/big" 22 "os" 23 "testing" 24 "time" 25 26 "github.com/bearnetworkchain/go-bearnetwork/common" 27 "github.com/bearnetworkchain/go-bearnetwork/core/rawdb" 28 "github.com/bearnetworkchain/go-bearnetwork/ethdb" 29 "github.com/bearnetworkchain/go-bearnetwork/ethdb/memorydb" 30 "github.com/bearnetworkchain/go-bearnetwork/log" 31 "github.com/bearnetworkchain/go-bearnetwork/rlp" 32 "github.com/bearnetworkchain/go-bearnetwork/trie" 33 "golang.org/x/crypto/sha3" 34 ) 35 36 // Tests that snapshot generation from an empty database. 37 func TestGeneration(t *testing.T) { 38 // We can't use statedb to make a test trie (circular dependency), so make 39 // a fake one manually. We're going with a small account trie of 3 accounts, 40 // two of which also has the same 3-slot storage trie attached. 41 var ( 42 diskdb = memorydb.New() 43 triedb = trie.NewDatabase(diskdb) 44 ) 45 stTrie, _ := trie.NewSecure(common.Hash{}, triedb) 46 stTrie.Update([]byte("key-1"), []byte("val-1")) // 0x1314700b81afc49f94db3623ef1df38f3ed18b73a1b7ea2f6c095118cf6118a0 47 stTrie.Update([]byte("key-2"), []byte("val-2")) // 0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371 48 stTrie.Update([]byte("key-3"), []byte("val-3")) // 0x51c71a47af0695957647fb68766d0becee77e953df17c29b3c2f25436f055c78 49 stTrie.Commit(nil) // Root: 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67 50 51 accTrie, _ := trie.NewSecure(common.Hash{}, triedb) 52 acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} 53 val, _ := rlp.EncodeToBytes(acc) 54 accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e 55 56 acc = &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} 57 val, _ = rlp.EncodeToBytes(acc) 58 accTrie.Update([]byte("acc-2"), val) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 59 60 acc = &Account{Balance: big.NewInt(3), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} 61 val, _ = rlp.EncodeToBytes(acc) 62 accTrie.Update([]byte("acc-3"), val) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2 63 root, _, _ := accTrie.Commit(nil) // Root: 0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd 64 triedb.Commit(root, false, nil) 65 66 if have, want := root, common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd"); have != want { 67 t.Fatalf("have %#x want %#x", have, want) 68 } 69 snap := generateSnapshot(diskdb, triedb, 16, root) 70 select { 71 case <-snap.genPending: 72 // Snapshot generation succeeded 73 74 case <-time.After(3 * time.Second): 75 t.Errorf("Snapshot generation failed") 76 } 77 checkSnapRoot(t, snap, root) 78 // Signal abortion to the generator and wait for it to tear down 79 stop := make(chan *generatorStats) 80 snap.genAbort <- stop 81 <-stop 82 } 83 84 func hashData(input []byte) common.Hash { 85 var hasher = sha3.NewLegacyKeccak256() 86 var hash common.Hash 87 hasher.Reset() 88 hasher.Write(input) 89 hasher.Sum(hash[:0]) 90 return hash 91 } 92 93 // Tests that snapshot generation with existent flat state. 94 func TestGenerateExistentState(t *testing.T) { 95 // We can't use statedb to make a test trie (circular dependency), so make 96 // a fake one manually. We're going with a small account trie of 3 accounts, 97 // two of which also has the same 3-slot storage trie attached. 98 var ( 99 diskdb = memorydb.New() 100 triedb = trie.NewDatabase(diskdb) 101 ) 102 stTrie, _ := trie.NewSecure(common.Hash{}, triedb) 103 stTrie.Update([]byte("key-1"), []byte("val-1")) // 0x1314700b81afc49f94db3623ef1df38f3ed18b73a1b7ea2f6c095118cf6118a0 104 stTrie.Update([]byte("key-2"), []byte("val-2")) // 0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371 105 stTrie.Update([]byte("key-3"), []byte("val-3")) // 0x51c71a47af0695957647fb68766d0becee77e953df17c29b3c2f25436f055c78 106 stTrie.Commit(nil) // Root: 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67 107 108 accTrie, _ := trie.NewSecure(common.Hash{}, triedb) 109 acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} 110 val, _ := rlp.EncodeToBytes(acc) 111 accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e 112 rawdb.WriteAccountSnapshot(diskdb, hashData([]byte("acc-1")), val) 113 rawdb.WriteStorageSnapshot(diskdb, hashData([]byte("acc-1")), hashData([]byte("key-1")), []byte("val-1")) 114 rawdb.WriteStorageSnapshot(diskdb, hashData([]byte("acc-1")), hashData([]byte("key-2")), []byte("val-2")) 115 rawdb.WriteStorageSnapshot(diskdb, hashData([]byte("acc-1")), hashData([]byte("key-3")), []byte("val-3")) 116 117 acc = &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} 118 val, _ = rlp.EncodeToBytes(acc) 119 accTrie.Update([]byte("acc-2"), val) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 120 diskdb.Put(hashData([]byte("acc-2")).Bytes(), val) 121 rawdb.WriteAccountSnapshot(diskdb, hashData([]byte("acc-2")), val) 122 123 acc = &Account{Balance: big.NewInt(3), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} 124 val, _ = rlp.EncodeToBytes(acc) 125 accTrie.Update([]byte("acc-3"), val) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2 126 rawdb.WriteAccountSnapshot(diskdb, hashData([]byte("acc-3")), val) 127 rawdb.WriteStorageSnapshot(diskdb, hashData([]byte("acc-3")), hashData([]byte("key-1")), []byte("val-1")) 128 rawdb.WriteStorageSnapshot(diskdb, hashData([]byte("acc-3")), hashData([]byte("key-2")), []byte("val-2")) 129 rawdb.WriteStorageSnapshot(diskdb, hashData([]byte("acc-3")), hashData([]byte("key-3")), []byte("val-3")) 130 131 root, _, _ := accTrie.Commit(nil) // Root: 0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd 132 triedb.Commit(root, false, nil) 133 134 snap := generateSnapshot(diskdb, triedb, 16, root) 135 select { 136 case <-snap.genPending: 137 // Snapshot generation succeeded 138 139 case <-time.After(3 * time.Second): 140 t.Errorf("Snapshot generation failed") 141 } 142 checkSnapRoot(t, snap, root) 143 // Signal abortion to the generator and wait for it to tear down 144 stop := make(chan *generatorStats) 145 snap.genAbort <- stop 146 <-stop 147 } 148 149 func checkSnapRoot(t *testing.T, snap *diskLayer, trieRoot common.Hash) { 150 t.Helper() 151 152 accIt := snap.AccountIterator(common.Hash{}) 153 defer accIt.Release() 154 155 snapRoot, err := generateTrieRoot(nil, accIt, common.Hash{}, stackTrieGenerate, 156 func(db ethdb.KeyValueWriter, accountHash, codeHash common.Hash, stat *generateStats) (common.Hash, error) { 157 storageIt, _ := snap.StorageIterator(accountHash, common.Hash{}) 158 defer storageIt.Release() 159 160 hash, err := generateTrieRoot(nil, storageIt, accountHash, stackTrieGenerate, nil, stat, false) 161 if err != nil { 162 return common.Hash{}, err 163 } 164 return hash, nil 165 }, newGenerateStats(), true) 166 167 if err != nil { 168 t.Fatal(err) 169 } 170 if snapRoot != trieRoot { 171 t.Fatalf("snaproot: %#x != trieroot #%x", snapRoot, trieRoot) 172 } 173 if err := CheckDanglingStorage(snap.diskdb); err != nil { 174 t.Fatalf("Detected dangling storages %v", err) 175 } 176 } 177 178 type testHelper struct { 179 diskdb *memorydb.Database 180 triedb *trie.Database 181 accTrie *trie.SecureTrie 182 } 183 184 func newHelper() *testHelper { 185 diskdb := memorydb.New() 186 triedb := trie.NewDatabase(diskdb) 187 accTrie, _ := trie.NewSecure(common.Hash{}, triedb) 188 return &testHelper{ 189 diskdb: diskdb, 190 triedb: triedb, 191 accTrie: accTrie, 192 } 193 } 194 195 func (t *testHelper) addTrieAccount(acckey string, acc *Account) { 196 val, _ := rlp.EncodeToBytes(acc) 197 t.accTrie.Update([]byte(acckey), val) 198 } 199 200 func (t *testHelper) addSnapAccount(acckey string, acc *Account) { 201 val, _ := rlp.EncodeToBytes(acc) 202 key := hashData([]byte(acckey)) 203 rawdb.WriteAccountSnapshot(t.diskdb, key, val) 204 } 205 206 func (t *testHelper) addAccount(acckey string, acc *Account) { 207 t.addTrieAccount(acckey, acc) 208 t.addSnapAccount(acckey, acc) 209 } 210 211 func (t *testHelper) addSnapStorage(accKey string, keys []string, vals []string) { 212 accHash := hashData([]byte(accKey)) 213 for i, key := range keys { 214 rawdb.WriteStorageSnapshot(t.diskdb, accHash, hashData([]byte(key)), []byte(vals[i])) 215 } 216 } 217 218 func (t *testHelper) makeStorageTrie(keys []string, vals []string) []byte { 219 stTrie, _ := trie.NewSecure(common.Hash{}, t.triedb) 220 for i, k := range keys { 221 stTrie.Update([]byte(k), []byte(vals[i])) 222 } 223 root, _, _ := stTrie.Commit(nil) 224 return root.Bytes() 225 } 226 227 func (t *testHelper) Generate() (common.Hash, *diskLayer) { 228 root, _, _ := t.accTrie.Commit(nil) 229 t.triedb.Commit(root, false, nil) 230 snap := generateSnapshot(t.diskdb, t.triedb, 16, root) 231 return root, snap 232 } 233 234 // Tests that snapshot generation with existent flat state, where the flat state 235 // contains some errors: 236 // - the contract with empty storage root but has storage entries in the disk 237 // - the contract with non empty storage root but empty storage slots 238 // - the contract(non-empty storage) misses some storage slots 239 // - miss in the beginning 240 // - miss in the middle 241 // - miss in the end 242 // - the contract(non-empty storage) has wrong storage slots 243 // - wrong slots in the beginning 244 // - wrong slots in the middle 245 // - wrong slots in the end 246 // - the contract(non-empty storage) has extra storage slots 247 // - extra slots in the beginning 248 // - extra slots in the middle 249 // - extra slots in the end 250 func TestGenerateExistentStateWithWrongStorage(t *testing.T) { 251 helper := newHelper() 252 stRoot := helper.makeStorageTrie([]string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 253 254 // Account one, empty root but non-empty database 255 helper.addAccount("acc-1", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) 256 helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 257 258 // Account two, non empty root but empty database 259 helper.addAccount("acc-2", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 260 261 // Miss slots 262 { 263 // Account three, non empty root but misses slots in the beginning 264 helper.addAccount("acc-3", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 265 helper.addSnapStorage("acc-3", []string{"key-2", "key-3"}, []string{"val-2", "val-3"}) 266 267 // Account four, non empty root but misses slots in the middle 268 helper.addAccount("acc-4", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 269 helper.addSnapStorage("acc-4", []string{"key-1", "key-3"}, []string{"val-1", "val-3"}) 270 271 // Account five, non empty root but misses slots in the end 272 helper.addAccount("acc-5", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 273 helper.addSnapStorage("acc-5", []string{"key-1", "key-2"}, []string{"val-1", "val-2"}) 274 } 275 276 // Wrong storage slots 277 { 278 // Account six, non empty root but wrong slots in the beginning 279 helper.addAccount("acc-6", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 280 helper.addSnapStorage("acc-6", []string{"key-1", "key-2", "key-3"}, []string{"badval-1", "val-2", "val-3"}) 281 282 // Account seven, non empty root but wrong slots in the middle 283 helper.addAccount("acc-7", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 284 helper.addSnapStorage("acc-7", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "badval-2", "val-3"}) 285 286 // Account eight, non empty root but wrong slots in the end 287 helper.addAccount("acc-8", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 288 helper.addSnapStorage("acc-8", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "badval-3"}) 289 290 // Account 9, non empty root but rotated slots 291 helper.addAccount("acc-9", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 292 helper.addSnapStorage("acc-9", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-3", "val-2"}) 293 } 294 295 // Extra storage slots 296 { 297 // Account 10, non empty root but extra slots in the beginning 298 helper.addAccount("acc-10", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 299 helper.addSnapStorage("acc-10", []string{"key-0", "key-1", "key-2", "key-3"}, []string{"val-0", "val-1", "val-2", "val-3"}) 300 301 // Account 11, non empty root but extra slots in the middle 302 helper.addAccount("acc-11", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 303 helper.addSnapStorage("acc-11", []string{"key-1", "key-2", "key-2-1", "key-3"}, []string{"val-1", "val-2", "val-2-1", "val-3"}) 304 305 // Account 12, non empty root but extra slots in the end 306 helper.addAccount("acc-12", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 307 helper.addSnapStorage("acc-12", []string{"key-1", "key-2", "key-3", "key-4"}, []string{"val-1", "val-2", "val-3", "val-4"}) 308 } 309 310 root, snap := helper.Generate() 311 t.Logf("Root: %#x\n", root) // Root = 0x8746cce9fd9c658b2cfd639878ed6584b7a2b3e73bb40f607fcfa156002429a0 312 313 select { 314 case <-snap.genPending: 315 // Snapshot generation succeeded 316 317 case <-time.After(3 * time.Second): 318 t.Errorf("Snapshot generation failed") 319 } 320 checkSnapRoot(t, snap, root) 321 // Signal abortion to the generator and wait for it to tear down 322 stop := make(chan *generatorStats) 323 snap.genAbort <- stop 324 <-stop 325 } 326 327 // Tests that snapshot generation with existent flat state, where the flat state 328 // contains some errors: 329 // - miss accounts 330 // - wrong accounts 331 // - extra accounts 332 func TestGenerateExistentStateWithWrongAccounts(t *testing.T) { 333 helper := newHelper() 334 stRoot := helper.makeStorageTrie([]string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 335 336 // Trie accounts [acc-1, acc-2, acc-3, acc-4, acc-6] 337 // Extra accounts [acc-0, acc-5, acc-7] 338 339 // Missing accounts, only in the trie 340 { 341 helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // Beginning 342 helper.addTrieAccount("acc-4", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // Middle 343 helper.addTrieAccount("acc-6", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // End 344 } 345 346 // Wrong accounts 347 { 348 helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 349 helper.addSnapAccount("acc-2", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: common.Hex2Bytes("0x1234")}) 350 351 helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 352 helper.addSnapAccount("acc-3", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) 353 } 354 355 // Extra accounts, only in the snap 356 { 357 helper.addSnapAccount("acc-0", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyRoot.Bytes()}) // before the beginning 358 helper.addSnapAccount("acc-5", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: common.Hex2Bytes("0x1234")}) // Middle 359 helper.addSnapAccount("acc-7", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyRoot.Bytes()}) // after the end 360 } 361 362 root, snap := helper.Generate() 363 t.Logf("Root: %#x\n", root) // Root = 0x825891472281463511e7ebcc7f109e4f9200c20fa384754e11fd605cd98464e8 364 365 select { 366 case <-snap.genPending: 367 // Snapshot generation succeeded 368 369 case <-time.After(3 * time.Second): 370 t.Errorf("Snapshot generation failed") 371 } 372 checkSnapRoot(t, snap, root) 373 374 // Signal abortion to the generator and wait for it to tear down 375 stop := make(chan *generatorStats) 376 snap.genAbort <- stop 377 <-stop 378 } 379 380 // Tests that snapshot generation errors out correctly in case of a missing trie 381 // node in the account trie. 382 func TestGenerateCorruptAccountTrie(t *testing.T) { 383 // We can't use statedb to make a test trie (circular dependency), so make 384 // a fake one manually. We're going with a small account trie of 3 accounts, 385 // without any storage slots to keep the test smaller. 386 var ( 387 diskdb = memorydb.New() 388 triedb = trie.NewDatabase(diskdb) 389 ) 390 tr, _ := trie.NewSecure(common.Hash{}, triedb) 391 acc := &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} 392 val, _ := rlp.EncodeToBytes(acc) 393 tr.Update([]byte("acc-1"), val) // 0xc7a30f39aff471c95d8a837497ad0e49b65be475cc0953540f80cfcdbdcd9074 394 395 acc = &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} 396 val, _ = rlp.EncodeToBytes(acc) 397 tr.Update([]byte("acc-2"), val) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 398 399 acc = &Account{Balance: big.NewInt(3), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} 400 val, _ = rlp.EncodeToBytes(acc) 401 tr.Update([]byte("acc-3"), val) // 0x19ead688e907b0fab07176120dceec244a72aff2f0aa51e8b827584e378772f4 402 tr.Commit(nil) // Root: 0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978 403 404 // Delete an account trie leaf and ensure the generator chokes 405 triedb.Commit(common.HexToHash("0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978"), false, nil) 406 diskdb.Delete(common.HexToHash("0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7").Bytes()) 407 408 snap := generateSnapshot(diskdb, triedb, 16, common.HexToHash("0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978")) 409 select { 410 case <-snap.genPending: 411 // Snapshot generation succeeded 412 t.Errorf("Snapshot generated against corrupt account trie") 413 414 case <-time.After(time.Second): 415 // Not generated fast enough, hopefully blocked inside on missing trie node fail 416 } 417 // Signal abortion to the generator and wait for it to tear down 418 stop := make(chan *generatorStats) 419 snap.genAbort <- stop 420 <-stop 421 } 422 423 // Tests that snapshot generation errors out correctly in case of a missing root 424 // trie node for a storage trie. It's similar to internal corruption but it is 425 // handled differently inside the generator. 426 func TestGenerateMissingStorageTrie(t *testing.T) { 427 // We can't use statedb to make a test trie (circular dependency), so make 428 // a fake one manually. We're going with a small account trie of 3 accounts, 429 // two of which also has the same 3-slot storage trie attached. 430 var ( 431 diskdb = memorydb.New() 432 triedb = trie.NewDatabase(diskdb) 433 ) 434 stTrie, _ := trie.NewSecure(common.Hash{}, triedb) 435 stTrie.Update([]byte("key-1"), []byte("val-1")) // 0x1314700b81afc49f94db3623ef1df38f3ed18b73a1b7ea2f6c095118cf6118a0 436 stTrie.Update([]byte("key-2"), []byte("val-2")) // 0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371 437 stTrie.Update([]byte("key-3"), []byte("val-3")) // 0x51c71a47af0695957647fb68766d0becee77e953df17c29b3c2f25436f055c78 438 stTrie.Commit(nil) // Root: 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67 439 440 accTrie, _ := trie.NewSecure(common.Hash{}, triedb) 441 acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} 442 val, _ := rlp.EncodeToBytes(acc) 443 accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e 444 445 acc = &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} 446 val, _ = rlp.EncodeToBytes(acc) 447 accTrie.Update([]byte("acc-2"), val) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 448 449 acc = &Account{Balance: big.NewInt(3), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} 450 val, _ = rlp.EncodeToBytes(acc) 451 accTrie.Update([]byte("acc-3"), val) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2 452 accTrie.Commit(nil) // Root: 0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd 453 454 // We can only corrupt the disk database, so flush the tries out 455 triedb.Reference( 456 common.HexToHash("0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67"), 457 common.HexToHash("0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e"), 458 ) 459 triedb.Reference( 460 common.HexToHash("0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67"), 461 common.HexToHash("0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2"), 462 ) 463 triedb.Commit(common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd"), false, nil) 464 465 // Delete a storage trie root and ensure the generator chokes 466 diskdb.Delete(common.HexToHash("0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67").Bytes()) 467 468 snap := generateSnapshot(diskdb, triedb, 16, common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd")) 469 select { 470 case <-snap.genPending: 471 // Snapshot generation succeeded 472 t.Errorf("Snapshot generated against corrupt storage trie") 473 474 case <-time.After(time.Second): 475 // Not generated fast enough, hopefully blocked inside on missing trie node fail 476 } 477 // Signal abortion to the generator and wait for it to tear down 478 stop := make(chan *generatorStats) 479 snap.genAbort <- stop 480 <-stop 481 } 482 483 // Tests that snapshot generation errors out correctly in case of a missing trie 484 // node in a storage trie. 485 func TestGenerateCorruptStorageTrie(t *testing.T) { 486 // We can't use statedb to make a test trie (circular dependency), so make 487 // a fake one manually. We're going with a small account trie of 3 accounts, 488 // two of which also has the same 3-slot storage trie attached. 489 var ( 490 diskdb = memorydb.New() 491 triedb = trie.NewDatabase(diskdb) 492 ) 493 stTrie, _ := trie.NewSecure(common.Hash{}, triedb) 494 stTrie.Update([]byte("key-1"), []byte("val-1")) // 0x1314700b81afc49f94db3623ef1df38f3ed18b73a1b7ea2f6c095118cf6118a0 495 stTrie.Update([]byte("key-2"), []byte("val-2")) // 0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371 496 stTrie.Update([]byte("key-3"), []byte("val-3")) // 0x51c71a47af0695957647fb68766d0becee77e953df17c29b3c2f25436f055c78 497 stTrie.Commit(nil) // Root: 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67 498 499 accTrie, _ := trie.NewSecure(common.Hash{}, triedb) 500 acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} 501 val, _ := rlp.EncodeToBytes(acc) 502 accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e 503 504 acc = &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} 505 val, _ = rlp.EncodeToBytes(acc) 506 accTrie.Update([]byte("acc-2"), val) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 507 508 acc = &Account{Balance: big.NewInt(3), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} 509 val, _ = rlp.EncodeToBytes(acc) 510 accTrie.Update([]byte("acc-3"), val) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2 511 accTrie.Commit(nil) // Root: 0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd 512 513 // We can only corrupt the disk database, so flush the tries out 514 triedb.Reference( 515 common.HexToHash("0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67"), 516 common.HexToHash("0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e"), 517 ) 518 triedb.Reference( 519 common.HexToHash("0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67"), 520 common.HexToHash("0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2"), 521 ) 522 triedb.Commit(common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd"), false, nil) 523 524 // Delete a storage trie leaf and ensure the generator chokes 525 diskdb.Delete(common.HexToHash("0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371").Bytes()) 526 527 snap := generateSnapshot(diskdb, triedb, 16, common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd")) 528 select { 529 case <-snap.genPending: 530 // Snapshot generation succeeded 531 t.Errorf("Snapshot generated against corrupt storage trie") 532 533 case <-time.After(time.Second): 534 // Not generated fast enough, hopefully blocked inside on missing trie node fail 535 } 536 // Signal abortion to the generator and wait for it to tear down 537 stop := make(chan *generatorStats) 538 snap.genAbort <- stop 539 <-stop 540 } 541 542 func getStorageTrie(n int, triedb *trie.Database) *trie.SecureTrie { 543 stTrie, _ := trie.NewSecure(common.Hash{}, triedb) 544 for i := 0; i < n; i++ { 545 k := fmt.Sprintf("key-%d", i) 546 v := fmt.Sprintf("val-%d", i) 547 stTrie.Update([]byte(k), []byte(v)) 548 } 549 stTrie.Commit(nil) 550 return stTrie 551 } 552 553 // Tests that snapshot generation when an extra account with storage exists in the snap state. 554 func TestGenerateWithExtraAccounts(t *testing.T) { 555 var ( 556 diskdb = memorydb.New() 557 triedb = trie.NewDatabase(diskdb) 558 stTrie = getStorageTrie(5, triedb) 559 ) 560 accTrie, _ := trie.NewSecure(common.Hash{}, triedb) 561 { // Account one in the trie 562 acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} 563 val, _ := rlp.EncodeToBytes(acc) 564 accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e 565 // Identical in the snap 566 key := hashData([]byte("acc-1")) 567 rawdb.WriteAccountSnapshot(diskdb, key, val) 568 rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-1")), []byte("val-1")) 569 rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-2")), []byte("val-2")) 570 rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-3")), []byte("val-3")) 571 rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-4")), []byte("val-4")) 572 rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-5")), []byte("val-5")) 573 } 574 { // Account two exists only in the snapshot 575 acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} 576 val, _ := rlp.EncodeToBytes(acc) 577 key := hashData([]byte("acc-2")) 578 rawdb.WriteAccountSnapshot(diskdb, key, val) 579 rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("b-key-1")), []byte("b-val-1")) 580 rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("b-key-2")), []byte("b-val-2")) 581 rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("b-key-3")), []byte("b-val-3")) 582 } 583 root, _, _ := accTrie.Commit(nil) 584 t.Logf("root: %x", root) 585 triedb.Commit(root, false, nil) 586 // To verify the test: If we now inspect the snap db, there should exist extraneous storage items 587 if data := rawdb.ReadStorageSnapshot(diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data == nil { 588 t.Fatalf("expected snap storage to exist") 589 } 590 591 snap := generateSnapshot(diskdb, triedb, 16, root) 592 select { 593 case <-snap.genPending: 594 // Snapshot generation succeeded 595 596 case <-time.After(3 * time.Second): 597 t.Errorf("Snapshot generation failed") 598 } 599 checkSnapRoot(t, snap, root) 600 // Signal abortion to the generator and wait for it to tear down 601 stop := make(chan *generatorStats) 602 snap.genAbort <- stop 603 <-stop 604 // If we now inspect the snap db, there should exist no extraneous storage items 605 if data := rawdb.ReadStorageSnapshot(diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data != nil { 606 t.Fatalf("expected slot to be removed, got %v", string(data)) 607 } 608 } 609 610 func enableLogging() { 611 log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) 612 } 613 614 // Tests that snapshot generation when an extra account with storage exists in the snap state. 615 func TestGenerateWithManyExtraAccounts(t *testing.T) { 616 if false { 617 enableLogging() 618 } 619 var ( 620 diskdb = memorydb.New() 621 triedb = trie.NewDatabase(diskdb) 622 stTrie = getStorageTrie(3, triedb) 623 ) 624 accTrie, _ := trie.NewSecure(common.Hash{}, triedb) 625 { // Account one in the trie 626 acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} 627 val, _ := rlp.EncodeToBytes(acc) 628 accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e 629 // Identical in the snap 630 key := hashData([]byte("acc-1")) 631 rawdb.WriteAccountSnapshot(diskdb, key, val) 632 rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-1")), []byte("val-1")) 633 rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-2")), []byte("val-2")) 634 rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-3")), []byte("val-3")) 635 } 636 { // 100 accounts exist only in snapshot 637 for i := 0; i < 1000; i++ { 638 //acc := &Account{Balance: big.NewInt(int64(i)), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} 639 acc := &Account{Balance: big.NewInt(int64(i)), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} 640 val, _ := rlp.EncodeToBytes(acc) 641 key := hashData([]byte(fmt.Sprintf("acc-%d", i))) 642 rawdb.WriteAccountSnapshot(diskdb, key, val) 643 } 644 } 645 root, _, _ := accTrie.Commit(nil) 646 t.Logf("root: %x", root) 647 triedb.Commit(root, false, nil) 648 649 snap := generateSnapshot(diskdb, triedb, 16, root) 650 select { 651 case <-snap.genPending: 652 // Snapshot generation succeeded 653 654 case <-time.After(3 * time.Second): 655 t.Errorf("Snapshot generation failed") 656 } 657 checkSnapRoot(t, snap, root) 658 // Signal abortion to the generator and wait for it to tear down 659 stop := make(chan *generatorStats) 660 snap.genAbort <- stop 661 <-stop 662 } 663 664 // Tests this case 665 // maxAccountRange 3 666 // snapshot-accounts: 01, 02, 03, 04, 05, 06, 07 667 // trie-accounts: 03, 07 668 // 669 // We iterate three snapshot storage slots (max = 3) from the database. They are 0x01, 0x02, 0x03. 670 // The trie has a lot of deletions. 671 // So in trie, we iterate 2 entries 0x03, 0x07. We create the 0x07 in the database and abort the procedure, because the trie is exhausted. 672 // But in the database, we still have the stale storage slots 0x04, 0x05. They are not iterated yet, but the procedure is finished. 673 func TestGenerateWithExtraBeforeAndAfter(t *testing.T) { 674 accountCheckRange = 3 675 if false { 676 enableLogging() 677 } 678 var ( 679 diskdb = memorydb.New() 680 triedb = trie.NewDatabase(diskdb) 681 ) 682 accTrie, _ := trie.New(common.Hash{}, triedb) 683 { 684 acc := &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} 685 val, _ := rlp.EncodeToBytes(acc) 686 accTrie.Update(common.HexToHash("0x03").Bytes(), val) 687 accTrie.Update(common.HexToHash("0x07").Bytes(), val) 688 689 rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x01"), val) 690 rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x02"), val) 691 rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x03"), val) 692 rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x04"), val) 693 rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x05"), val) 694 rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x06"), val) 695 rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x07"), val) 696 } 697 698 root, _, _ := accTrie.Commit(nil) 699 t.Logf("root: %x", root) 700 triedb.Commit(root, false, nil) 701 702 snap := generateSnapshot(diskdb, triedb, 16, root) 703 select { 704 case <-snap.genPending: 705 // Snapshot generation succeeded 706 707 case <-time.After(3 * time.Second): 708 t.Errorf("Snapshot generation failed") 709 } 710 checkSnapRoot(t, snap, root) 711 // Signal abortion to the generator and wait for it to tear down 712 stop := make(chan *generatorStats) 713 snap.genAbort <- stop 714 <-stop 715 } 716 717 // TestGenerateWithMalformedSnapdata tests what happes if we have some junk 718 // in the snapshot database, which cannot be parsed back to an account 719 func TestGenerateWithMalformedSnapdata(t *testing.T) { 720 accountCheckRange = 3 721 if false { 722 enableLogging() 723 } 724 var ( 725 diskdb = memorydb.New() 726 triedb = trie.NewDatabase(diskdb) 727 ) 728 accTrie, _ := trie.New(common.Hash{}, triedb) 729 { 730 acc := &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} 731 val, _ := rlp.EncodeToBytes(acc) 732 accTrie.Update(common.HexToHash("0x03").Bytes(), val) 733 734 junk := make([]byte, 100) 735 copy(junk, []byte{0xde, 0xad}) 736 rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x02"), junk) 737 rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x03"), junk) 738 rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x04"), junk) 739 rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x05"), junk) 740 } 741 742 root, _, _ := accTrie.Commit(nil) 743 t.Logf("root: %x", root) 744 triedb.Commit(root, false, nil) 745 746 snap := generateSnapshot(diskdb, triedb, 16, root) 747 select { 748 case <-snap.genPending: 749 // Snapshot generation succeeded 750 751 case <-time.After(3 * time.Second): 752 t.Errorf("Snapshot generation failed") 753 } 754 checkSnapRoot(t, snap, root) 755 // Signal abortion to the generator and wait for it to tear down 756 stop := make(chan *generatorStats) 757 snap.genAbort <- stop 758 <-stop 759 // If we now inspect the snap db, there should exist no extraneous storage items 760 if data := rawdb.ReadStorageSnapshot(diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data != nil { 761 t.Fatalf("expected slot to be removed, got %v", string(data)) 762 } 763 } 764 765 func TestGenerateFromEmptySnap(t *testing.T) { 766 //enableLogging() 767 accountCheckRange = 10 768 storageCheckRange = 20 769 helper := newHelper() 770 stRoot := helper.makeStorageTrie([]string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 771 // Add 1K accounts to the trie 772 for i := 0; i < 400; i++ { 773 helper.addTrieAccount(fmt.Sprintf("acc-%d", i), 774 &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 775 } 776 root, snap := helper.Generate() 777 t.Logf("Root: %#x\n", root) // Root: 0x6f7af6d2e1a1bf2b84a3beb3f8b64388465fbc1e274ca5d5d3fc787ca78f59e4 778 779 select { 780 case <-snap.genPending: 781 // Snapshot generation succeeded 782 783 case <-time.After(3 * time.Second): 784 t.Errorf("Snapshot generation failed") 785 } 786 checkSnapRoot(t, snap, root) 787 // Signal abortion to the generator and wait for it to tear down 788 stop := make(chan *generatorStats) 789 snap.genAbort <- stop 790 <-stop 791 } 792 793 // Tests that snapshot generation with existent flat state, where the flat state 794 // storage is correct, but incomplete. 795 // The incomplete part is on the second range 796 // snap: [ 0x01, 0x02, 0x03, 0x04] , [ 0x05, 0x06, 0x07, {missing}] (with storageCheck = 4) 797 // trie: 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 798 // This hits a case where the snap verification passes, but there are more elements in the trie 799 // which we must also add. 800 func TestGenerateWithIncompleteStorage(t *testing.T) { 801 storageCheckRange = 4 802 helper := newHelper() 803 stKeys := []string{"1", "2", "3", "4", "5", "6", "7", "8"} 804 stVals := []string{"v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8"} 805 stRoot := helper.makeStorageTrie(stKeys, stVals) 806 // We add 8 accounts, each one is missing exactly one of the storage slots. This means 807 // we don't have to order the keys and figure out exactly which hash-key winds up 808 // on the sensitive spots at the boundaries 809 for i := 0; i < 8; i++ { 810 accKey := fmt.Sprintf("acc-%d", i) 811 helper.addAccount(accKey, &Account{Balance: big.NewInt(int64(i)), Root: stRoot, CodeHash: emptyCode.Bytes()}) 812 var moddedKeys []string 813 var moddedVals []string 814 for ii := 0; ii < 8; ii++ { 815 if ii != i { 816 moddedKeys = append(moddedKeys, stKeys[ii]) 817 moddedVals = append(moddedVals, stVals[ii]) 818 } 819 } 820 helper.addSnapStorage(accKey, moddedKeys, moddedVals) 821 } 822 823 root, snap := helper.Generate() 824 t.Logf("Root: %#x\n", root) // Root: 0xca73f6f05ba4ca3024ef340ef3dfca8fdabc1b677ff13f5a9571fd49c16e67ff 825 826 select { 827 case <-snap.genPending: 828 // Snapshot generation succeeded 829 830 case <-time.After(3 * time.Second): 831 t.Errorf("Snapshot generation failed") 832 } 833 checkSnapRoot(t, snap, root) 834 // Signal abortion to the generator and wait for it to tear down 835 stop := make(chan *generatorStats) 836 snap.genAbort <- stop 837 <-stop 838 } 839 840 func incKey(key []byte) []byte { 841 for i := len(key) - 1; i >= 0; i-- { 842 key[i]++ 843 if key[i] != 0x0 { 844 break 845 } 846 } 847 return key 848 } 849 850 func decKey(key []byte) []byte { 851 for i := len(key) - 1; i >= 0; i-- { 852 key[i]-- 853 if key[i] != 0xff { 854 break 855 } 856 } 857 return key 858 } 859 860 func populateDangling(disk ethdb.KeyValueStore) { 861 populate := func(accountHash common.Hash, keys []string, vals []string) { 862 for i, key := range keys { 863 rawdb.WriteStorageSnapshot(disk, accountHash, hashData([]byte(key)), []byte(vals[i])) 864 } 865 } 866 // Dangling storages of the "first" account 867 populate(common.Hash{}, []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 868 869 // Dangling storages of the "last" account 870 populate(common.HexToHash("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 871 872 // Dangling storages around the account 1 873 hash := decKey(hashData([]byte("acc-1")).Bytes()) 874 populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 875 hash = incKey(hashData([]byte("acc-1")).Bytes()) 876 populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 877 878 // Dangling storages around the account 2 879 hash = decKey(hashData([]byte("acc-2")).Bytes()) 880 populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 881 hash = incKey(hashData([]byte("acc-2")).Bytes()) 882 populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 883 884 // Dangling storages around the account 3 885 hash = decKey(hashData([]byte("acc-3")).Bytes()) 886 populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 887 hash = incKey(hashData([]byte("acc-3")).Bytes()) 888 populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 889 890 // Dangling storages of the random account 891 populate(randomHash(), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 892 populate(randomHash(), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 893 populate(randomHash(), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 894 } 895 896 // Tests that snapshot generation with dangling storages. Dangling storage means 897 // the storage data is existent while the corresponding account data is missing. 898 // 899 // This test will populate some dangling storages to see if they can be cleaned up. 900 func TestGenerateCompleteSnapshotWithDanglingStorage(t *testing.T) { 901 var helper = newHelper() 902 stRoot := helper.makeStorageTrie([]string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 903 904 helper.addAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 905 helper.addAccount("acc-2", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) 906 helper.addAccount("acc-3", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 907 908 helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 909 helper.addSnapStorage("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 910 911 populateDangling(helper.diskdb) 912 913 root, snap := helper.Generate() 914 select { 915 case <-snap.genPending: 916 // Snapshot generation succeeded 917 918 case <-time.After(3 * time.Second): 919 t.Errorf("Snapshot generation failed") 920 } 921 checkSnapRoot(t, snap, root) 922 923 // Signal abortion to the generator and wait for it to tear down 924 stop := make(chan *generatorStats) 925 snap.genAbort <- stop 926 <-stop 927 } 928 929 // Tests that snapshot generation with dangling storages. Dangling storage means 930 // the storage data is existent while the corresponding account data is missing. 931 // 932 // This test will populate some dangling storages to see if they can be cleaned up. 933 func TestGenerateBrokenSnapshotWithDanglingStorage(t *testing.T) { 934 var helper = newHelper() 935 stRoot := helper.makeStorageTrie([]string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 936 937 helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 938 helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) 939 helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: emptyCode.Bytes()}) 940 941 populateDangling(helper.diskdb) 942 943 root, snap := helper.Generate() 944 select { 945 case <-snap.genPending: 946 // Snapshot generation succeeded 947 948 case <-time.After(3 * time.Second): 949 t.Errorf("Snapshot generation failed") 950 } 951 checkSnapRoot(t, snap, root) 952 953 // Signal abortion to the generator and wait for it to tear down 954 stop := make(chan *generatorStats) 955 snap.genAbort <- stop 956 <-stop 957 }