github.com/core-coin/go-core/v2@v2.1.9/core/state/snapshot/generate_test.go (about) 1 // Copyright 2019 by the Authors 2 // This file is part of the go-core library. 3 // 4 // The go-core 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-core 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-core library. If not, see <http://www.gnu.org/licenses/>. 16 17 package snapshot 18 19 import ( 20 "math/big" 21 "testing" 22 "time" 23 24 "github.com/core-coin/go-core/v2/xcbdb/memorydb" 25 26 "github.com/core-coin/go-core/v2/common" 27 "github.com/core-coin/go-core/v2/rlp" 28 "github.com/core-coin/go-core/v2/trie" 29 ) 30 31 // Tests that snapshot generation errors out correctly in case of a missing trie 32 // node in the account trie. 33 func TestGenerateCorruptAccountTrie(t *testing.T) { 34 // We can't use statedb to make a test trie (circular dependency), so make 35 // a fake one manually. We're going with a small account trie of 3 accounts, 36 // without any storage slots to keep the test smaller. 37 var ( 38 diskdb = memorydb.New() 39 triedb = trie.NewDatabase(diskdb) 40 ) 41 tr, _ := trie.NewSecure(common.Hash{}, triedb) 42 acc := &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} 43 val, _ := rlp.EncodeToBytes(acc) 44 tr.Update([]byte("acc-1"), val) // 0xc7a30f39aff471c95d8a837497ad0e49b65be475cc0953540f80cfcdbdcd9074 45 46 acc = &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} 47 val, _ = rlp.EncodeToBytes(acc) 48 tr.Update([]byte("acc-2"), val) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 49 50 acc = &Account{Balance: big.NewInt(3), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} 51 val, _ = rlp.EncodeToBytes(acc) 52 tr.Update([]byte("acc-3"), val) // 0x19ead688e907b0fab07176120dceec244a72aff2f0aa51e8b827584e378772f4 53 tr.Commit(nil) // Root: 0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978 54 55 // Delete an account trie leaf and ensure the generator chokes 56 triedb.Commit(common.HexToHash("0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978"), false, nil) 57 diskdb.Delete(common.HexToHash("0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7").Bytes()) 58 59 snap := generateSnapshot(diskdb, triedb, 16, common.HexToHash("0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978"), nil) 60 select { 61 case <-snap.genPending: 62 // Snapshot generation succeeded 63 t.Errorf("Snapshot generated against corrupt account trie") 64 65 case <-time.After(250 * time.Millisecond): 66 // Not generated fast enough, hopefully blocked inside on missing trie node fail 67 } 68 // Signal abortion to the generator and wait for it to tear down 69 stop := make(chan *generatorStats) 70 snap.genAbort <- stop 71 <-stop 72 } 73 74 // Tests that snapshot generation errors out correctly in case of a missing root 75 // trie node for a storage trie. It's similar to internal corruption but it is 76 // handled differently inside the generator. 77 func TestGenerateMissingStorageTrie(t *testing.T) { 78 // We can't use statedb to make a test trie (circular dependency), so make 79 // a fake one manually. We're going with a small account trie of 3 accounts, 80 // two of which also has the same 3-slot storage trie attached. 81 var ( 82 diskdb = memorydb.New() 83 triedb = trie.NewDatabase(diskdb) 84 ) 85 stTrie, _ := trie.NewSecure(common.Hash{}, triedb) 86 stTrie.Update([]byte("key-1"), []byte("val-1")) // 0x1314700b81afc49f94db3623ef1df38f3ed18b73a1b7ea2f6c095118cf6118a0 87 stTrie.Update([]byte("key-2"), []byte("val-2")) // 0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371 88 stTrie.Update([]byte("key-3"), []byte("val-3")) // 0x51c71a47af0695957647fb68766d0becee77e953df17c29b3c2f25436f055c78 89 stTrie.Commit(nil) // Root: 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67 90 91 accTrie, _ := trie.NewSecure(common.Hash{}, triedb) 92 acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} 93 val, _ := rlp.EncodeToBytes(acc) 94 accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e 95 96 acc = &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} 97 val, _ = rlp.EncodeToBytes(acc) 98 accTrie.Update([]byte("acc-2"), val) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 99 100 acc = &Account{Balance: big.NewInt(3), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} 101 val, _ = rlp.EncodeToBytes(acc) 102 accTrie.Update([]byte("acc-3"), val) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2 103 accTrie.Commit(nil) // Root: 0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd 104 105 // We can only corrupt the disk database, so flush the tries out 106 triedb.Reference( 107 common.HexToHash("0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67"), 108 common.HexToHash("0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e"), 109 ) 110 triedb.Reference( 111 common.HexToHash("0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67"), 112 common.HexToHash("0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2"), 113 ) 114 triedb.Commit(common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd"), false, nil) 115 116 // Delete a storage trie root and ensure the generator chokes 117 diskdb.Delete(common.HexToHash("0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67").Bytes()) 118 119 snap := generateSnapshot(diskdb, triedb, 16, common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd"), nil) 120 select { 121 case <-snap.genPending: 122 // Snapshot generation succeeded 123 t.Errorf("Snapshot generated against corrupt storage trie") 124 125 case <-time.After(250 * time.Millisecond): 126 // Not generated fast enough, hopefully blocked inside on missing trie node fail 127 } 128 // Signal abortion to the generator and wait for it to tear down 129 stop := make(chan *generatorStats) 130 snap.genAbort <- stop 131 <-stop 132 } 133 134 // Tests that snapshot generation errors out correctly in case of a missing trie 135 // node in a storage trie. 136 func TestGenerateCorruptStorageTrie(t *testing.T) { 137 // We can't use statedb to make a test trie (circular dependency), so make 138 // a fake one manually. We're going with a small account trie of 3 accounts, 139 // two of which also has the same 3-slot storage trie attached. 140 var ( 141 diskdb = memorydb.New() 142 triedb = trie.NewDatabase(diskdb) 143 ) 144 stTrie, _ := trie.NewSecure(common.Hash{}, triedb) 145 stTrie.Update([]byte("key-1"), []byte("val-1")) // 0x1314700b81afc49f94db3623ef1df38f3ed18b73a1b7ea2f6c095118cf6118a0 146 stTrie.Update([]byte("key-2"), []byte("val-2")) // 0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371 147 stTrie.Update([]byte("key-3"), []byte("val-3")) // 0x51c71a47af0695957647fb68766d0becee77e953df17c29b3c2f25436f055c78 148 stTrie.Commit(nil) // Root: 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67 149 150 accTrie, _ := trie.NewSecure(common.Hash{}, triedb) 151 acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} 152 val, _ := rlp.EncodeToBytes(acc) 153 accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e 154 155 acc = &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} 156 val, _ = rlp.EncodeToBytes(acc) 157 accTrie.Update([]byte("acc-2"), val) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 158 159 acc = &Account{Balance: big.NewInt(3), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} 160 val, _ = rlp.EncodeToBytes(acc) 161 accTrie.Update([]byte("acc-3"), val) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2 162 accTrie.Commit(nil) // Root: 0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd 163 164 // We can only corrupt the disk database, so flush the tries out 165 triedb.Reference( 166 common.HexToHash("0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67"), 167 common.HexToHash("0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e"), 168 ) 169 triedb.Reference( 170 common.HexToHash("0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67"), 171 common.HexToHash("0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2"), 172 ) 173 triedb.Commit(common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd"), false, nil) 174 175 // Delete a storage trie leaf and ensure the generator chokes 176 diskdb.Delete(common.HexToHash("0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371").Bytes()) 177 178 snap := generateSnapshot(diskdb, triedb, 16, common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd"), nil) 179 select { 180 case <-snap.genPending: 181 // Snapshot generation succeeded 182 t.Errorf("Snapshot generated against corrupt storage trie") 183 184 case <-time.After(250 * time.Millisecond): 185 // Not generated fast enough, hopefully blocked inside on missing trie node fail 186 } 187 // Signal abortion to the generator and wait for it to tear down 188 stop := make(chan *generatorStats) 189 snap.genAbort <- stop 190 <-stop 191 }