github.com/electroneum/electroneum-sc@v0.0.0-20230105223411-3bc1d078281e/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/electroneum/electroneum-sc/common" 27 "github.com/electroneum/electroneum-sc/core/rawdb" 28 "github.com/electroneum/electroneum-sc/ethdb" 29 "github.com/electroneum/electroneum-sc/ethdb/memorydb" 30 "github.com/electroneum/electroneum-sc/log" 31 "github.com/electroneum/electroneum-sc/rlp" 32 "github.com/electroneum/electroneum-sc/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 // 243 // - the contract(non-empty storage) has wrong storage slots 244 // - wrong slots in the beginning 245 // - wrong slots in the middle 246 // - wrong slots in the end 247 // 248 // - the contract(non-empty storage) has extra storage slots 249 // - extra slots in the beginning 250 // - extra slots in the middle 251 // - extra slots in the end 252 func TestGenerateExistentStateWithWrongStorage(t *testing.T) { 253 helper := newHelper() 254 stRoot := helper.makeStorageTrie([]string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 255 256 // Account one, empty root but non-empty database 257 helper.addAccount("acc-1", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) 258 helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 259 260 // Account two, non empty root but empty database 261 helper.addAccount("acc-2", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 262 263 // Miss slots 264 { 265 // Account three, non empty root but misses slots in the beginning 266 helper.addAccount("acc-3", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 267 helper.addSnapStorage("acc-3", []string{"key-2", "key-3"}, []string{"val-2", "val-3"}) 268 269 // Account four, non empty root but misses slots in the middle 270 helper.addAccount("acc-4", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 271 helper.addSnapStorage("acc-4", []string{"key-1", "key-3"}, []string{"val-1", "val-3"}) 272 273 // Account five, non empty root but misses slots in the end 274 helper.addAccount("acc-5", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 275 helper.addSnapStorage("acc-5", []string{"key-1", "key-2"}, []string{"val-1", "val-2"}) 276 } 277 278 // Wrong storage slots 279 { 280 // Account six, non empty root but wrong slots in the beginning 281 helper.addAccount("acc-6", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 282 helper.addSnapStorage("acc-6", []string{"key-1", "key-2", "key-3"}, []string{"badval-1", "val-2", "val-3"}) 283 284 // Account seven, non empty root but wrong slots in the middle 285 helper.addAccount("acc-7", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 286 helper.addSnapStorage("acc-7", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "badval-2", "val-3"}) 287 288 // Account eight, non empty root but wrong slots in the end 289 helper.addAccount("acc-8", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 290 helper.addSnapStorage("acc-8", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "badval-3"}) 291 292 // Account 9, non empty root but rotated slots 293 helper.addAccount("acc-9", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 294 helper.addSnapStorage("acc-9", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-3", "val-2"}) 295 } 296 297 // Extra storage slots 298 { 299 // Account 10, non empty root but extra slots in the beginning 300 helper.addAccount("acc-10", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 301 helper.addSnapStorage("acc-10", []string{"key-0", "key-1", "key-2", "key-3"}, []string{"val-0", "val-1", "val-2", "val-3"}) 302 303 // Account 11, non empty root but extra slots in the middle 304 helper.addAccount("acc-11", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 305 helper.addSnapStorage("acc-11", []string{"key-1", "key-2", "key-2-1", "key-3"}, []string{"val-1", "val-2", "val-2-1", "val-3"}) 306 307 // Account 12, non empty root but extra slots in the end 308 helper.addAccount("acc-12", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 309 helper.addSnapStorage("acc-12", []string{"key-1", "key-2", "key-3", "key-4"}, []string{"val-1", "val-2", "val-3", "val-4"}) 310 } 311 312 root, snap := helper.Generate() 313 t.Logf("Root: %#x\n", root) // Root = 0x8746cce9fd9c658b2cfd639878ed6584b7a2b3e73bb40f607fcfa156002429a0 314 315 select { 316 case <-snap.genPending: 317 // Snapshot generation succeeded 318 319 case <-time.After(3 * time.Second): 320 t.Errorf("Snapshot generation failed") 321 } 322 checkSnapRoot(t, snap, root) 323 // Signal abortion to the generator and wait for it to tear down 324 stop := make(chan *generatorStats) 325 snap.genAbort <- stop 326 <-stop 327 } 328 329 // Tests that snapshot generation with existent flat state, where the flat state 330 // contains some errors: 331 // - miss accounts 332 // - wrong accounts 333 // - extra accounts 334 func TestGenerateExistentStateWithWrongAccounts(t *testing.T) { 335 helper := newHelper() 336 stRoot := helper.makeStorageTrie([]string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 337 338 // Trie accounts [acc-1, acc-2, acc-3, acc-4, acc-6] 339 // Extra accounts [acc-0, acc-5, acc-7] 340 341 // Missing accounts, only in the trie 342 { 343 helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // Beginning 344 helper.addTrieAccount("acc-4", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // Middle 345 helper.addTrieAccount("acc-6", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // End 346 } 347 348 // Wrong accounts 349 { 350 helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 351 helper.addSnapAccount("acc-2", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: common.Hex2Bytes("0x1234")}) 352 353 helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 354 helper.addSnapAccount("acc-3", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) 355 } 356 357 // Extra accounts, only in the snap 358 { 359 helper.addSnapAccount("acc-0", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyRoot.Bytes()}) // before the beginning 360 helper.addSnapAccount("acc-5", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: common.Hex2Bytes("0x1234")}) // Middle 361 helper.addSnapAccount("acc-7", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyRoot.Bytes()}) // after the end 362 } 363 364 root, snap := helper.Generate() 365 t.Logf("Root: %#x\n", root) // Root = 0x825891472281463511e7ebcc7f109e4f9200c20fa384754e11fd605cd98464e8 366 367 select { 368 case <-snap.genPending: 369 // Snapshot generation succeeded 370 371 case <-time.After(3 * time.Second): 372 t.Errorf("Snapshot generation failed") 373 } 374 checkSnapRoot(t, snap, root) 375 376 // Signal abortion to the generator and wait for it to tear down 377 stop := make(chan *generatorStats) 378 snap.genAbort <- stop 379 <-stop 380 } 381 382 // Tests that snapshot generation errors out correctly in case of a missing trie 383 // node in the account trie. 384 func TestGenerateCorruptAccountTrie(t *testing.T) { 385 // We can't use statedb to make a test trie (circular dependency), so make 386 // a fake one manually. We're going with a small account trie of 3 accounts, 387 // without any storage slots to keep the test smaller. 388 var ( 389 diskdb = memorydb.New() 390 triedb = trie.NewDatabase(diskdb) 391 ) 392 tr, _ := trie.NewSecure(common.Hash{}, triedb) 393 acc := &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} 394 val, _ := rlp.EncodeToBytes(acc) 395 tr.Update([]byte("acc-1"), val) // 0xc7a30f39aff471c95d8a837497ad0e49b65be475cc0953540f80cfcdbdcd9074 396 397 acc = &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} 398 val, _ = rlp.EncodeToBytes(acc) 399 tr.Update([]byte("acc-2"), val) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 400 401 acc = &Account{Balance: big.NewInt(3), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} 402 val, _ = rlp.EncodeToBytes(acc) 403 tr.Update([]byte("acc-3"), val) // 0x19ead688e907b0fab07176120dceec244a72aff2f0aa51e8b827584e378772f4 404 tr.Commit(nil) // Root: 0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978 405 406 // Delete an account trie leaf and ensure the generator chokes 407 triedb.Commit(common.HexToHash("0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978"), false, nil) 408 diskdb.Delete(common.HexToHash("0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7").Bytes()) 409 410 snap := generateSnapshot(diskdb, triedb, 16, common.HexToHash("0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978")) 411 select { 412 case <-snap.genPending: 413 // Snapshot generation succeeded 414 t.Errorf("Snapshot generated against corrupt account trie") 415 416 case <-time.After(time.Second): 417 // Not generated fast enough, hopefully blocked inside on missing trie node fail 418 } 419 // Signal abortion to the generator and wait for it to tear down 420 stop := make(chan *generatorStats) 421 snap.genAbort <- stop 422 <-stop 423 } 424 425 // Tests that snapshot generation errors out correctly in case of a missing root 426 // trie node for a storage trie. It's similar to internal corruption but it is 427 // handled differently inside the generator. 428 func TestGenerateMissingStorageTrie(t *testing.T) { 429 // We can't use statedb to make a test trie (circular dependency), so make 430 // a fake one manually. We're going with a small account trie of 3 accounts, 431 // two of which also has the same 3-slot storage trie attached. 432 var ( 433 diskdb = memorydb.New() 434 triedb = trie.NewDatabase(diskdb) 435 ) 436 stTrie, _ := trie.NewSecure(common.Hash{}, triedb) 437 stTrie.Update([]byte("key-1"), []byte("val-1")) // 0x1314700b81afc49f94db3623ef1df38f3ed18b73a1b7ea2f6c095118cf6118a0 438 stTrie.Update([]byte("key-2"), []byte("val-2")) // 0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371 439 stTrie.Update([]byte("key-3"), []byte("val-3")) // 0x51c71a47af0695957647fb68766d0becee77e953df17c29b3c2f25436f055c78 440 stTrie.Commit(nil) // Root: 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67 441 442 accTrie, _ := trie.NewSecure(common.Hash{}, triedb) 443 acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} 444 val, _ := rlp.EncodeToBytes(acc) 445 accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e 446 447 acc = &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} 448 val, _ = rlp.EncodeToBytes(acc) 449 accTrie.Update([]byte("acc-2"), val) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 450 451 acc = &Account{Balance: big.NewInt(3), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} 452 val, _ = rlp.EncodeToBytes(acc) 453 accTrie.Update([]byte("acc-3"), val) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2 454 accTrie.Commit(nil) // Root: 0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd 455 456 // We can only corrupt the disk database, so flush the tries out 457 triedb.Reference( 458 common.HexToHash("0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67"), 459 common.HexToHash("0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e"), 460 ) 461 triedb.Reference( 462 common.HexToHash("0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67"), 463 common.HexToHash("0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2"), 464 ) 465 triedb.Commit(common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd"), false, nil) 466 467 // Delete a storage trie root and ensure the generator chokes 468 diskdb.Delete(common.HexToHash("0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67").Bytes()) 469 470 snap := generateSnapshot(diskdb, triedb, 16, common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd")) 471 select { 472 case <-snap.genPending: 473 // Snapshot generation succeeded 474 t.Errorf("Snapshot generated against corrupt storage trie") 475 476 case <-time.After(time.Second): 477 // Not generated fast enough, hopefully blocked inside on missing trie node fail 478 } 479 // Signal abortion to the generator and wait for it to tear down 480 stop := make(chan *generatorStats) 481 snap.genAbort <- stop 482 <-stop 483 } 484 485 // Tests that snapshot generation errors out correctly in case of a missing trie 486 // node in a storage trie. 487 func TestGenerateCorruptStorageTrie(t *testing.T) { 488 // We can't use statedb to make a test trie (circular dependency), so make 489 // a fake one manually. We're going with a small account trie of 3 accounts, 490 // two of which also has the same 3-slot storage trie attached. 491 var ( 492 diskdb = memorydb.New() 493 triedb = trie.NewDatabase(diskdb) 494 ) 495 stTrie, _ := trie.NewSecure(common.Hash{}, triedb) 496 stTrie.Update([]byte("key-1"), []byte("val-1")) // 0x1314700b81afc49f94db3623ef1df38f3ed18b73a1b7ea2f6c095118cf6118a0 497 stTrie.Update([]byte("key-2"), []byte("val-2")) // 0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371 498 stTrie.Update([]byte("key-3"), []byte("val-3")) // 0x51c71a47af0695957647fb68766d0becee77e953df17c29b3c2f25436f055c78 499 stTrie.Commit(nil) // Root: 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67 500 501 accTrie, _ := trie.NewSecure(common.Hash{}, triedb) 502 acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} 503 val, _ := rlp.EncodeToBytes(acc) 504 accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e 505 506 acc = &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} 507 val, _ = rlp.EncodeToBytes(acc) 508 accTrie.Update([]byte("acc-2"), val) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 509 510 acc = &Account{Balance: big.NewInt(3), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} 511 val, _ = rlp.EncodeToBytes(acc) 512 accTrie.Update([]byte("acc-3"), val) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2 513 accTrie.Commit(nil) // Root: 0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd 514 515 // We can only corrupt the disk database, so flush the tries out 516 triedb.Reference( 517 common.HexToHash("0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67"), 518 common.HexToHash("0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e"), 519 ) 520 triedb.Reference( 521 common.HexToHash("0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67"), 522 common.HexToHash("0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2"), 523 ) 524 triedb.Commit(common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd"), false, nil) 525 526 // Delete a storage trie leaf and ensure the generator chokes 527 diskdb.Delete(common.HexToHash("0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371").Bytes()) 528 529 snap := generateSnapshot(diskdb, triedb, 16, common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd")) 530 select { 531 case <-snap.genPending: 532 // Snapshot generation succeeded 533 t.Errorf("Snapshot generated against corrupt storage trie") 534 535 case <-time.After(time.Second): 536 // Not generated fast enough, hopefully blocked inside on missing trie node fail 537 } 538 // Signal abortion to the generator and wait for it to tear down 539 stop := make(chan *generatorStats) 540 snap.genAbort <- stop 541 <-stop 542 } 543 544 func getStorageTrie(n int, triedb *trie.Database) *trie.SecureTrie { 545 stTrie, _ := trie.NewSecure(common.Hash{}, triedb) 546 for i := 0; i < n; i++ { 547 k := fmt.Sprintf("key-%d", i) 548 v := fmt.Sprintf("val-%d", i) 549 stTrie.Update([]byte(k), []byte(v)) 550 } 551 stTrie.Commit(nil) 552 return stTrie 553 } 554 555 // Tests that snapshot generation when an extra account with storage exists in the snap state. 556 func TestGenerateWithExtraAccounts(t *testing.T) { 557 var ( 558 diskdb = memorydb.New() 559 triedb = trie.NewDatabase(diskdb) 560 stTrie = getStorageTrie(5, triedb) 561 ) 562 accTrie, _ := trie.NewSecure(common.Hash{}, triedb) 563 { // Account one in the trie 564 acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} 565 val, _ := rlp.EncodeToBytes(acc) 566 accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e 567 // Identical in the snap 568 key := hashData([]byte("acc-1")) 569 rawdb.WriteAccountSnapshot(diskdb, key, val) 570 rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-1")), []byte("val-1")) 571 rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-2")), []byte("val-2")) 572 rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-3")), []byte("val-3")) 573 rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-4")), []byte("val-4")) 574 rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-5")), []byte("val-5")) 575 } 576 { // Account two exists only in the snapshot 577 acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} 578 val, _ := rlp.EncodeToBytes(acc) 579 key := hashData([]byte("acc-2")) 580 rawdb.WriteAccountSnapshot(diskdb, key, val) 581 rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("b-key-1")), []byte("b-val-1")) 582 rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("b-key-2")), []byte("b-val-2")) 583 rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("b-key-3")), []byte("b-val-3")) 584 } 585 root, _, _ := accTrie.Commit(nil) 586 t.Logf("root: %x", root) 587 triedb.Commit(root, false, nil) 588 // To verify the test: If we now inspect the snap db, there should exist extraneous storage items 589 if data := rawdb.ReadStorageSnapshot(diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data == nil { 590 t.Fatalf("expected snap storage to exist") 591 } 592 593 snap := generateSnapshot(diskdb, triedb, 16, root) 594 select { 595 case <-snap.genPending: 596 // Snapshot generation succeeded 597 598 case <-time.After(3 * time.Second): 599 t.Errorf("Snapshot generation failed") 600 } 601 checkSnapRoot(t, snap, root) 602 // Signal abortion to the generator and wait for it to tear down 603 stop := make(chan *generatorStats) 604 snap.genAbort <- stop 605 <-stop 606 // If we now inspect the snap db, there should exist no extraneous storage items 607 if data := rawdb.ReadStorageSnapshot(diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data != nil { 608 t.Fatalf("expected slot to be removed, got %v", string(data)) 609 } 610 } 611 612 func enableLogging() { 613 log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) 614 } 615 616 // Tests that snapshot generation when an extra account with storage exists in the snap state. 617 func TestGenerateWithManyExtraAccounts(t *testing.T) { 618 if false { 619 enableLogging() 620 } 621 var ( 622 diskdb = memorydb.New() 623 triedb = trie.NewDatabase(diskdb) 624 stTrie = getStorageTrie(3, triedb) 625 ) 626 accTrie, _ := trie.NewSecure(common.Hash{}, triedb) 627 { // Account one in the trie 628 acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} 629 val, _ := rlp.EncodeToBytes(acc) 630 accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e 631 // Identical in the snap 632 key := hashData([]byte("acc-1")) 633 rawdb.WriteAccountSnapshot(diskdb, key, val) 634 rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-1")), []byte("val-1")) 635 rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-2")), []byte("val-2")) 636 rawdb.WriteStorageSnapshot(diskdb, key, hashData([]byte("key-3")), []byte("val-3")) 637 } 638 { // 100 accounts exist only in snapshot 639 for i := 0; i < 1000; i++ { 640 //acc := &Account{Balance: big.NewInt(int64(i)), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} 641 acc := &Account{Balance: big.NewInt(int64(i)), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} 642 val, _ := rlp.EncodeToBytes(acc) 643 key := hashData([]byte(fmt.Sprintf("acc-%d", i))) 644 rawdb.WriteAccountSnapshot(diskdb, key, val) 645 } 646 } 647 root, _, _ := accTrie.Commit(nil) 648 t.Logf("root: %x", root) 649 triedb.Commit(root, false, nil) 650 651 snap := generateSnapshot(diskdb, triedb, 16, root) 652 select { 653 case <-snap.genPending: 654 // Snapshot generation succeeded 655 656 case <-time.After(3 * time.Second): 657 t.Errorf("Snapshot generation failed") 658 } 659 checkSnapRoot(t, snap, root) 660 // Signal abortion to the generator and wait for it to tear down 661 stop := make(chan *generatorStats) 662 snap.genAbort <- stop 663 <-stop 664 } 665 666 // Tests this case 667 // maxAccountRange 3 668 // snapshot-accounts: 01, 02, 03, 04, 05, 06, 07 669 // trie-accounts: 03, 07 670 // 671 // We iterate three snapshot storage slots (max = 3) from the database. They are 0x01, 0x02, 0x03. 672 // The trie has a lot of deletions. 673 // 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. 674 // But in the database, we still have the stale storage slots 0x04, 0x05. They are not iterated yet, but the procedure is finished. 675 func TestGenerateWithExtraBeforeAndAfter(t *testing.T) { 676 accountCheckRange = 3 677 if false { 678 enableLogging() 679 } 680 var ( 681 diskdb = memorydb.New() 682 triedb = trie.NewDatabase(diskdb) 683 ) 684 accTrie, _ := trie.New(common.Hash{}, triedb) 685 { 686 acc := &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} 687 val, _ := rlp.EncodeToBytes(acc) 688 accTrie.Update(common.HexToHash("0x03").Bytes(), val) 689 accTrie.Update(common.HexToHash("0x07").Bytes(), val) 690 691 rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x01"), val) 692 rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x02"), val) 693 rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x03"), val) 694 rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x04"), val) 695 rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x05"), val) 696 rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x06"), val) 697 rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x07"), val) 698 } 699 700 root, _, _ := accTrie.Commit(nil) 701 t.Logf("root: %x", root) 702 triedb.Commit(root, false, nil) 703 704 snap := generateSnapshot(diskdb, triedb, 16, root) 705 select { 706 case <-snap.genPending: 707 // Snapshot generation succeeded 708 709 case <-time.After(3 * time.Second): 710 t.Errorf("Snapshot generation failed") 711 } 712 checkSnapRoot(t, snap, root) 713 // Signal abortion to the generator and wait for it to tear down 714 stop := make(chan *generatorStats) 715 snap.genAbort <- stop 716 <-stop 717 } 718 719 // TestGenerateWithMalformedSnapdata tests what happes if we have some junk 720 // in the snapshot database, which cannot be parsed back to an account 721 func TestGenerateWithMalformedSnapdata(t *testing.T) { 722 accountCheckRange = 3 723 if false { 724 enableLogging() 725 } 726 var ( 727 diskdb = memorydb.New() 728 triedb = trie.NewDatabase(diskdb) 729 ) 730 accTrie, _ := trie.New(common.Hash{}, triedb) 731 { 732 acc := &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} 733 val, _ := rlp.EncodeToBytes(acc) 734 accTrie.Update(common.HexToHash("0x03").Bytes(), val) 735 736 junk := make([]byte, 100) 737 copy(junk, []byte{0xde, 0xad}) 738 rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x02"), junk) 739 rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x03"), junk) 740 rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x04"), junk) 741 rawdb.WriteAccountSnapshot(diskdb, common.HexToHash("0x05"), junk) 742 } 743 744 root, _, _ := accTrie.Commit(nil) 745 t.Logf("root: %x", root) 746 triedb.Commit(root, false, nil) 747 748 snap := generateSnapshot(diskdb, triedb, 16, root) 749 select { 750 case <-snap.genPending: 751 // Snapshot generation succeeded 752 753 case <-time.After(3 * time.Second): 754 t.Errorf("Snapshot generation failed") 755 } 756 checkSnapRoot(t, snap, root) 757 // Signal abortion to the generator and wait for it to tear down 758 stop := make(chan *generatorStats) 759 snap.genAbort <- stop 760 <-stop 761 // If we now inspect the snap db, there should exist no extraneous storage items 762 if data := rawdb.ReadStorageSnapshot(diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data != nil { 763 t.Fatalf("expected slot to be removed, got %v", string(data)) 764 } 765 } 766 767 func TestGenerateFromEmptySnap(t *testing.T) { 768 //enableLogging() 769 accountCheckRange = 10 770 storageCheckRange = 20 771 helper := newHelper() 772 stRoot := helper.makeStorageTrie([]string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 773 // Add 1K accounts to the trie 774 for i := 0; i < 400; i++ { 775 helper.addTrieAccount(fmt.Sprintf("acc-%d", i), 776 &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 777 } 778 root, snap := helper.Generate() 779 t.Logf("Root: %#x\n", root) // Root: 0x6f7af6d2e1a1bf2b84a3beb3f8b64388465fbc1e274ca5d5d3fc787ca78f59e4 780 781 select { 782 case <-snap.genPending: 783 // Snapshot generation succeeded 784 785 case <-time.After(3 * time.Second): 786 t.Errorf("Snapshot generation failed") 787 } 788 checkSnapRoot(t, snap, root) 789 // Signal abortion to the generator and wait for it to tear down 790 stop := make(chan *generatorStats) 791 snap.genAbort <- stop 792 <-stop 793 } 794 795 // Tests that snapshot generation with existent flat state, where the flat state 796 // storage is correct, but incomplete. 797 // The incomplete part is on the second range 798 // snap: [ 0x01, 0x02, 0x03, 0x04] , [ 0x05, 0x06, 0x07, {missing}] (with storageCheck = 4) 799 // trie: 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 800 // This hits a case where the snap verification passes, but there are more elements in the trie 801 // which we must also add. 802 func TestGenerateWithIncompleteStorage(t *testing.T) { 803 storageCheckRange = 4 804 helper := newHelper() 805 stKeys := []string{"1", "2", "3", "4", "5", "6", "7", "8"} 806 stVals := []string{"v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8"} 807 stRoot := helper.makeStorageTrie(stKeys, stVals) 808 // We add 8 accounts, each one is missing exactly one of the storage slots. This means 809 // we don't have to order the keys and figure out exactly which hash-key winds up 810 // on the sensitive spots at the boundaries 811 for i := 0; i < 8; i++ { 812 accKey := fmt.Sprintf("acc-%d", i) 813 helper.addAccount(accKey, &Account{Balance: big.NewInt(int64(i)), Root: stRoot, CodeHash: emptyCode.Bytes()}) 814 var moddedKeys []string 815 var moddedVals []string 816 for ii := 0; ii < 8; ii++ { 817 if ii != i { 818 moddedKeys = append(moddedKeys, stKeys[ii]) 819 moddedVals = append(moddedVals, stVals[ii]) 820 } 821 } 822 helper.addSnapStorage(accKey, moddedKeys, moddedVals) 823 } 824 825 root, snap := helper.Generate() 826 t.Logf("Root: %#x\n", root) // Root: 0xca73f6f05ba4ca3024ef340ef3dfca8fdabc1b677ff13f5a9571fd49c16e67ff 827 828 select { 829 case <-snap.genPending: 830 // Snapshot generation succeeded 831 832 case <-time.After(3 * time.Second): 833 t.Errorf("Snapshot generation failed") 834 } 835 checkSnapRoot(t, snap, root) 836 // Signal abortion to the generator and wait for it to tear down 837 stop := make(chan *generatorStats) 838 snap.genAbort <- stop 839 <-stop 840 } 841 842 func incKey(key []byte) []byte { 843 for i := len(key) - 1; i >= 0; i-- { 844 key[i]++ 845 if key[i] != 0x0 { 846 break 847 } 848 } 849 return key 850 } 851 852 func decKey(key []byte) []byte { 853 for i := len(key) - 1; i >= 0; i-- { 854 key[i]-- 855 if key[i] != 0xff { 856 break 857 } 858 } 859 return key 860 } 861 862 func populateDangling(disk ethdb.KeyValueStore) { 863 populate := func(accountHash common.Hash, keys []string, vals []string) { 864 for i, key := range keys { 865 rawdb.WriteStorageSnapshot(disk, accountHash, hashData([]byte(key)), []byte(vals[i])) 866 } 867 } 868 // Dangling storages of the "first" account 869 populate(common.Hash{}, []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 870 871 // Dangling storages of the "last" account 872 populate(common.HexToHash("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 873 874 // Dangling storages around the account 1 875 hash := decKey(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 hash = incKey(hashData([]byte("acc-1")).Bytes()) 878 populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 879 880 // Dangling storages around the account 2 881 hash = decKey(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 hash = incKey(hashData([]byte("acc-2")).Bytes()) 884 populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 885 886 // Dangling storages around the account 3 887 hash = decKey(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 hash = incKey(hashData([]byte("acc-3")).Bytes()) 890 populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 891 892 // Dangling storages of the random account 893 populate(randomHash(), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 894 populate(randomHash(), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 895 populate(randomHash(), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 896 } 897 898 // Tests that snapshot generation with dangling storages. Dangling storage means 899 // the storage data is existent while the corresponding account data is missing. 900 // 901 // This test will populate some dangling storages to see if they can be cleaned up. 902 func TestGenerateCompleteSnapshotWithDanglingStorage(t *testing.T) { 903 var helper = newHelper() 904 stRoot := helper.makeStorageTrie([]string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 905 906 helper.addAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 907 helper.addAccount("acc-2", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) 908 helper.addAccount("acc-3", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 909 910 helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 911 helper.addSnapStorage("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 912 913 populateDangling(helper.diskdb) 914 915 root, snap := helper.Generate() 916 select { 917 case <-snap.genPending: 918 // Snapshot generation succeeded 919 920 case <-time.After(3 * time.Second): 921 t.Errorf("Snapshot generation failed") 922 } 923 checkSnapRoot(t, snap, root) 924 925 // Signal abortion to the generator and wait for it to tear down 926 stop := make(chan *generatorStats) 927 snap.genAbort <- stop 928 <-stop 929 } 930 931 // Tests that snapshot generation with dangling storages. Dangling storage means 932 // the storage data is existent while the corresponding account data is missing. 933 // 934 // This test will populate some dangling storages to see if they can be cleaned up. 935 func TestGenerateBrokenSnapshotWithDanglingStorage(t *testing.T) { 936 var helper = newHelper() 937 stRoot := helper.makeStorageTrie([]string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) 938 939 helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) 940 helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) 941 helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: emptyCode.Bytes()}) 942 943 populateDangling(helper.diskdb) 944 945 root, snap := helper.Generate() 946 select { 947 case <-snap.genPending: 948 // Snapshot generation succeeded 949 950 case <-time.After(3 * time.Second): 951 t.Errorf("Snapshot generation failed") 952 } 953 checkSnapRoot(t, snap, root) 954 955 // Signal abortion to the generator and wait for it to tear down 956 stop := make(chan *generatorStats) 957 snap.genAbort <- stop 958 <-stop 959 }