generate_test.go 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873
  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. package snapshot
  17. import (
  18. "fmt"
  19. "math/big"
  20. "os"
  21. "testing"
  22. "time"
  23. "github.com/ethereum/go-ethereum/common"
  24. "github.com/ethereum/go-ethereum/core/rawdb"
  25. "github.com/ethereum/go-ethereum/ethdb"
  26. "github.com/ethereum/go-ethereum/log"
  27. "github.com/ethereum/go-ethereum/rlp"
  28. "github.com/ethereum/go-ethereum/trie"
  29. "golang.org/x/crypto/sha3"
  30. )
  31. func hashData(input []byte) common.Hash {
  32. var hasher = sha3.NewLegacyKeccak256()
  33. var hash common.Hash
  34. hasher.Reset()
  35. hasher.Write(input)
  36. hasher.Sum(hash[:0])
  37. return hash
  38. }
  39. // Tests that snapshot generation from an empty database.
  40. func TestGeneration(t *testing.T) {
  41. // We can't use statedb to make a test trie (circular dependency), so make
  42. // a fake one manually. We're going with a small account trie of 3 accounts,
  43. // two of which also has the same 3-slot storage trie attached.
  44. var helper = newHelper()
  45. stRoot := helper.makeStorageTrie(common.Hash{}, common.Hash{}, []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, false)
  46. helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
  47. helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()})
  48. helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: emptyCode.Bytes()})
  49. helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
  50. helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
  51. root, snap := helper.CommitAndGenerate()
  52. if have, want := root, common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd"); have != want {
  53. t.Fatalf("have %#x want %#x", have, want)
  54. }
  55. select {
  56. case <-snap.genPending:
  57. // Snapshot generation succeeded
  58. case <-time.After(3 * time.Second):
  59. t.Errorf("Snapshot generation failed")
  60. }
  61. checkSnapRoot(t, snap, root)
  62. // Signal abortion to the generator and wait for it to tear down
  63. stop := make(chan *generatorStats)
  64. snap.genAbort <- stop
  65. <-stop
  66. }
  67. // Tests that snapshot generation with existent flat state.
  68. func TestGenerateExistentState(t *testing.T) {
  69. // We can't use statedb to make a test trie (circular dependency), so make
  70. // a fake one manually. We're going with a small account trie of 3 accounts,
  71. // two of which also has the same 3-slot storage trie attached.
  72. var helper = newHelper()
  73. stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
  74. helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
  75. helper.addSnapAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
  76. helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
  77. helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()})
  78. helper.addSnapAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()})
  79. stRoot = helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
  80. helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: emptyCode.Bytes()})
  81. helper.addSnapAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: emptyCode.Bytes()})
  82. helper.addSnapStorage("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
  83. root, snap := helper.CommitAndGenerate()
  84. select {
  85. case <-snap.genPending:
  86. // Snapshot generation succeeded
  87. case <-time.After(3 * time.Second):
  88. t.Errorf("Snapshot generation failed")
  89. }
  90. checkSnapRoot(t, snap, root)
  91. // Signal abortion to the generator and wait for it to tear down
  92. stop := make(chan *generatorStats)
  93. snap.genAbort <- stop
  94. <-stop
  95. }
  96. func checkSnapRoot(t *testing.T, snap *diskLayer, trieRoot common.Hash) {
  97. t.Helper()
  98. accIt := snap.AccountIterator(common.Hash{})
  99. defer accIt.Release()
  100. snapRoot, err := generateTrieRoot(nil, accIt, common.Hash{}, stackTrieGenerate,
  101. func(db ethdb.KeyValueWriter, accountHash, codeHash common.Hash, stat *generateStats) (common.Hash, error) {
  102. storageIt, _ := snap.StorageIterator(accountHash, common.Hash{})
  103. defer storageIt.Release()
  104. hash, err := generateTrieRoot(nil, storageIt, accountHash, stackTrieGenerate, nil, stat, false)
  105. if err != nil {
  106. return common.Hash{}, err
  107. }
  108. return hash, nil
  109. }, newGenerateStats(), true)
  110. if err != nil {
  111. t.Fatal(err)
  112. }
  113. if snapRoot != trieRoot {
  114. t.Fatalf("snaproot: %#x != trieroot #%x", snapRoot, trieRoot)
  115. }
  116. if err := CheckDanglingStorage(snap.diskdb); err != nil {
  117. t.Fatalf("Detected dangling storages: %v", err)
  118. }
  119. }
  120. type testHelper struct {
  121. diskdb ethdb.Database
  122. triedb *trie.Database
  123. accTrie *trie.StateTrie
  124. nodes *trie.MergedNodeSet
  125. }
  126. func newHelper() *testHelper {
  127. diskdb := rawdb.NewMemoryDatabase()
  128. triedb := trie.NewDatabase(diskdb)
  129. accTrie, _ := trie.NewStateTrie(common.Hash{}, common.Hash{}, triedb)
  130. return &testHelper{
  131. diskdb: diskdb,
  132. triedb: triedb,
  133. accTrie: accTrie,
  134. nodes: trie.NewMergedNodeSet(),
  135. }
  136. }
  137. func (t *testHelper) addTrieAccount(acckey string, acc *Account) {
  138. val, _ := rlp.EncodeToBytes(acc)
  139. t.accTrie.Update([]byte(acckey), val)
  140. }
  141. func (t *testHelper) addSnapAccount(acckey string, acc *Account) {
  142. val, _ := rlp.EncodeToBytes(acc)
  143. key := hashData([]byte(acckey))
  144. rawdb.WriteAccountSnapshot(t.diskdb, key, val)
  145. }
  146. func (t *testHelper) addAccount(acckey string, acc *Account) {
  147. t.addTrieAccount(acckey, acc)
  148. t.addSnapAccount(acckey, acc)
  149. }
  150. func (t *testHelper) addSnapStorage(accKey string, keys []string, vals []string) {
  151. accHash := hashData([]byte(accKey))
  152. for i, key := range keys {
  153. rawdb.WriteStorageSnapshot(t.diskdb, accHash, hashData([]byte(key)), []byte(vals[i]))
  154. }
  155. }
  156. func (t *testHelper) makeStorageTrie(stateRoot, owner common.Hash, keys []string, vals []string, commit bool) []byte {
  157. stTrie, _ := trie.NewStateTrie(owner, common.Hash{}, t.triedb)
  158. for i, k := range keys {
  159. stTrie.Update([]byte(k), []byte(vals[i]))
  160. }
  161. if !commit {
  162. return stTrie.Hash().Bytes()
  163. }
  164. root, nodes, _ := stTrie.Commit(false)
  165. if nodes != nil {
  166. t.nodes.Merge(nodes)
  167. }
  168. return root.Bytes()
  169. }
  170. func (t *testHelper) Commit() common.Hash {
  171. root, nodes, _ := t.accTrie.Commit(true)
  172. if nodes != nil {
  173. t.nodes.Merge(nodes)
  174. }
  175. t.triedb.Update(t.nodes)
  176. t.triedb.Commit(root, false, nil)
  177. return root
  178. }
  179. func (t *testHelper) CommitAndGenerate() (common.Hash, *diskLayer) {
  180. root := t.Commit()
  181. snap := generateSnapshot(t.diskdb, t.triedb, 16, root)
  182. return root, snap
  183. }
  184. // Tests that snapshot generation with existent flat state, where the flat state
  185. // contains some errors:
  186. // - the contract with empty storage root but has storage entries in the disk
  187. // - the contract with non empty storage root but empty storage slots
  188. // - the contract(non-empty storage) misses some storage slots
  189. // - miss in the beginning
  190. // - miss in the middle
  191. // - miss in the end
  192. // - the contract(non-empty storage) has wrong storage slots
  193. // - wrong slots in the beginning
  194. // - wrong slots in the middle
  195. // - wrong slots in the end
  196. // - the contract(non-empty storage) has extra storage slots
  197. // - extra slots in the beginning
  198. // - extra slots in the middle
  199. // - extra slots in the end
  200. func TestGenerateExistentStateWithWrongStorage(t *testing.T) {
  201. helper := newHelper()
  202. // Account one, empty root but non-empty database
  203. helper.addAccount("acc-1", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()})
  204. helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
  205. // Account two, non empty root but empty database
  206. stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-2")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
  207. helper.addAccount("acc-2", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
  208. // Miss slots
  209. {
  210. // Account three, non empty root but misses slots in the beginning
  211. helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
  212. helper.addAccount("acc-3", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
  213. helper.addSnapStorage("acc-3", []string{"key-2", "key-3"}, []string{"val-2", "val-3"})
  214. // Account four, non empty root but misses slots in the middle
  215. helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-4")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
  216. helper.addAccount("acc-4", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
  217. helper.addSnapStorage("acc-4", []string{"key-1", "key-3"}, []string{"val-1", "val-3"})
  218. // Account five, non empty root but misses slots in the end
  219. helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-5")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
  220. helper.addAccount("acc-5", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
  221. helper.addSnapStorage("acc-5", []string{"key-1", "key-2"}, []string{"val-1", "val-2"})
  222. }
  223. // Wrong storage slots
  224. {
  225. // Account six, non empty root but wrong slots in the beginning
  226. helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-6")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
  227. helper.addAccount("acc-6", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
  228. helper.addSnapStorage("acc-6", []string{"key-1", "key-2", "key-3"}, []string{"badval-1", "val-2", "val-3"})
  229. // Account seven, non empty root but wrong slots in the middle
  230. helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-7")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
  231. helper.addAccount("acc-7", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
  232. helper.addSnapStorage("acc-7", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "badval-2", "val-3"})
  233. // Account eight, non empty root but wrong slots in the end
  234. helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-8")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
  235. helper.addAccount("acc-8", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
  236. helper.addSnapStorage("acc-8", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "badval-3"})
  237. // Account 9, non empty root but rotated slots
  238. helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-9")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
  239. helper.addAccount("acc-9", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
  240. helper.addSnapStorage("acc-9", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-3", "val-2"})
  241. }
  242. // Extra storage slots
  243. {
  244. // Account 10, non empty root but extra slots in the beginning
  245. helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-10")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
  246. helper.addAccount("acc-10", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
  247. helper.addSnapStorage("acc-10", []string{"key-0", "key-1", "key-2", "key-3"}, []string{"val-0", "val-1", "val-2", "val-3"})
  248. // Account 11, non empty root but extra slots in the middle
  249. helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-11")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
  250. helper.addAccount("acc-11", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
  251. helper.addSnapStorage("acc-11", []string{"key-1", "key-2", "key-2-1", "key-3"}, []string{"val-1", "val-2", "val-2-1", "val-3"})
  252. // Account 12, non empty root but extra slots in the end
  253. helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-12")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
  254. helper.addAccount("acc-12", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
  255. helper.addSnapStorage("acc-12", []string{"key-1", "key-2", "key-3", "key-4"}, []string{"val-1", "val-2", "val-3", "val-4"})
  256. }
  257. root, snap := helper.CommitAndGenerate()
  258. t.Logf("Root: %#x\n", root) // Root = 0x8746cce9fd9c658b2cfd639878ed6584b7a2b3e73bb40f607fcfa156002429a0
  259. select {
  260. case <-snap.genPending:
  261. // Snapshot generation succeeded
  262. case <-time.After(3 * time.Second):
  263. t.Errorf("Snapshot generation failed")
  264. }
  265. checkSnapRoot(t, snap, root)
  266. // Signal abortion to the generator and wait for it to tear down
  267. stop := make(chan *generatorStats)
  268. snap.genAbort <- stop
  269. <-stop
  270. }
  271. // Tests that snapshot generation with existent flat state, where the flat state
  272. // contains some errors:
  273. // - miss accounts
  274. // - wrong accounts
  275. // - extra accounts
  276. func TestGenerateExistentStateWithWrongAccounts(t *testing.T) {
  277. helper := newHelper()
  278. helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
  279. helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-2")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
  280. helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
  281. helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-4")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
  282. stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-6")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
  283. // Trie accounts [acc-1, acc-2, acc-3, acc-4, acc-6]
  284. // Extra accounts [acc-0, acc-5, acc-7]
  285. // Missing accounts, only in the trie
  286. {
  287. helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // Beginning
  288. helper.addTrieAccount("acc-4", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // Middle
  289. helper.addTrieAccount("acc-6", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // End
  290. }
  291. // Wrong accounts
  292. {
  293. helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
  294. helper.addSnapAccount("acc-2", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: common.Hex2Bytes("0x1234")})
  295. helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
  296. helper.addSnapAccount("acc-3", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()})
  297. }
  298. // Extra accounts, only in the snap
  299. {
  300. helper.addSnapAccount("acc-0", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyRoot.Bytes()}) // before the beginning
  301. helper.addSnapAccount("acc-5", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: common.Hex2Bytes("0x1234")}) // Middle
  302. helper.addSnapAccount("acc-7", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyRoot.Bytes()}) // after the end
  303. }
  304. root, snap := helper.CommitAndGenerate()
  305. t.Logf("Root: %#x\n", root) // Root = 0x825891472281463511e7ebcc7f109e4f9200c20fa384754e11fd605cd98464e8
  306. select {
  307. case <-snap.genPending:
  308. // Snapshot generation succeeded
  309. case <-time.After(3 * time.Second):
  310. t.Errorf("Snapshot generation failed")
  311. }
  312. checkSnapRoot(t, snap, root)
  313. // Signal abortion to the generator and wait for it to tear down
  314. stop := make(chan *generatorStats)
  315. snap.genAbort <- stop
  316. <-stop
  317. }
  318. // Tests that snapshot generation errors out correctly in case of a missing trie
  319. // node in the account trie.
  320. func TestGenerateCorruptAccountTrie(t *testing.T) {
  321. // We can't use statedb to make a test trie (circular dependency), so make
  322. // a fake one manually. We're going with a small account trie of 3 accounts,
  323. // without any storage slots to keep the test smaller.
  324. helper := newHelper()
  325. helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) // 0xc7a30f39aff471c95d8a837497ad0e49b65be475cc0953540f80cfcdbdcd9074
  326. helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
  327. helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) // 0x19ead688e907b0fab07176120dceec244a72aff2f0aa51e8b827584e378772f4
  328. root := helper.Commit() // Root: 0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978
  329. // Delete an account trie leaf and ensure the generator chokes
  330. helper.triedb.Commit(root, false, nil)
  331. helper.diskdb.Delete(common.HexToHash("0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7").Bytes())
  332. snap := generateSnapshot(helper.diskdb, helper.triedb, 16, root)
  333. select {
  334. case <-snap.genPending:
  335. // Snapshot generation succeeded
  336. t.Errorf("Snapshot generated against corrupt account trie")
  337. case <-time.After(time.Second):
  338. // Not generated fast enough, hopefully blocked inside on missing trie node fail
  339. }
  340. // Signal abortion to the generator and wait for it to tear down
  341. stop := make(chan *generatorStats)
  342. snap.genAbort <- stop
  343. <-stop
  344. }
  345. // Tests that snapshot generation errors out correctly in case of a missing root
  346. // trie node for a storage trie. It's similar to internal corruption but it is
  347. // handled differently inside the generator.
  348. func TestGenerateMissingStorageTrie(t *testing.T) {
  349. // We can't use statedb to make a test trie (circular dependency), so make
  350. // a fake one manually. We're going with a small account trie of 3 accounts,
  351. // two of which also has the same 3-slot storage trie attached.
  352. helper := newHelper()
  353. stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
  354. helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
  355. helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
  356. stRoot = helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
  357. helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: emptyCode.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
  358. root := helper.Commit()
  359. // Delete a storage trie root and ensure the generator chokes
  360. helper.diskdb.Delete(stRoot)
  361. snap := generateSnapshot(helper.diskdb, helper.triedb, 16, root)
  362. select {
  363. case <-snap.genPending:
  364. // Snapshot generation succeeded
  365. t.Errorf("Snapshot generated against corrupt storage trie")
  366. case <-time.After(time.Second):
  367. // Not generated fast enough, hopefully blocked inside on missing trie node fail
  368. }
  369. // Signal abortion to the generator and wait for it to tear down
  370. stop := make(chan *generatorStats)
  371. snap.genAbort <- stop
  372. <-stop
  373. }
  374. // Tests that snapshot generation errors out correctly in case of a missing trie
  375. // node in a storage trie.
  376. func TestGenerateCorruptStorageTrie(t *testing.T) {
  377. // We can't use statedb to make a test trie (circular dependency), so make
  378. // a fake one manually. We're going with a small account trie of 3 accounts,
  379. // two of which also has the same 3-slot storage trie attached.
  380. helper := newHelper()
  381. stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
  382. helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
  383. helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
  384. stRoot = helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
  385. helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: emptyCode.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
  386. root := helper.Commit()
  387. // Delete a storage trie leaf and ensure the generator chokes
  388. helper.diskdb.Delete(common.HexToHash("0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371").Bytes())
  389. snap := generateSnapshot(helper.diskdb, helper.triedb, 16, root)
  390. select {
  391. case <-snap.genPending:
  392. // Snapshot generation succeeded
  393. t.Errorf("Snapshot generated against corrupt storage trie")
  394. case <-time.After(time.Second):
  395. // Not generated fast enough, hopefully blocked inside on missing trie node fail
  396. }
  397. // Signal abortion to the generator and wait for it to tear down
  398. stop := make(chan *generatorStats)
  399. snap.genAbort <- stop
  400. <-stop
  401. }
  402. // Tests that snapshot generation when an extra account with storage exists in the snap state.
  403. func TestGenerateWithExtraAccounts(t *testing.T) {
  404. helper := newHelper()
  405. {
  406. // Account one in the trie
  407. stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")),
  408. []string{"key-1", "key-2", "key-3", "key-4", "key-5"},
  409. []string{"val-1", "val-2", "val-3", "val-4", "val-5"},
  410. true,
  411. )
  412. acc := &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}
  413. val, _ := rlp.EncodeToBytes(acc)
  414. helper.accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
  415. // Identical in the snap
  416. key := hashData([]byte("acc-1"))
  417. rawdb.WriteAccountSnapshot(helper.triedb.DiskDB(), key, val)
  418. rawdb.WriteStorageSnapshot(helper.triedb.DiskDB(), key, hashData([]byte("key-1")), []byte("val-1"))
  419. rawdb.WriteStorageSnapshot(helper.triedb.DiskDB(), key, hashData([]byte("key-2")), []byte("val-2"))
  420. rawdb.WriteStorageSnapshot(helper.triedb.DiskDB(), key, hashData([]byte("key-3")), []byte("val-3"))
  421. rawdb.WriteStorageSnapshot(helper.triedb.DiskDB(), key, hashData([]byte("key-4")), []byte("val-4"))
  422. rawdb.WriteStorageSnapshot(helper.triedb.DiskDB(), key, hashData([]byte("key-5")), []byte("val-5"))
  423. }
  424. {
  425. // Account two exists only in the snapshot
  426. stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-2")),
  427. []string{"key-1", "key-2", "key-3", "key-4", "key-5"},
  428. []string{"val-1", "val-2", "val-3", "val-4", "val-5"},
  429. true,
  430. )
  431. acc := &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}
  432. val, _ := rlp.EncodeToBytes(acc)
  433. key := hashData([]byte("acc-2"))
  434. rawdb.WriteAccountSnapshot(helper.triedb.DiskDB(), key, val)
  435. rawdb.WriteStorageSnapshot(helper.triedb.DiskDB(), key, hashData([]byte("b-key-1")), []byte("b-val-1"))
  436. rawdb.WriteStorageSnapshot(helper.triedb.DiskDB(), key, hashData([]byte("b-key-2")), []byte("b-val-2"))
  437. rawdb.WriteStorageSnapshot(helper.triedb.DiskDB(), key, hashData([]byte("b-key-3")), []byte("b-val-3"))
  438. }
  439. root := helper.Commit()
  440. // To verify the test: If we now inspect the snap db, there should exist extraneous storage items
  441. if data := rawdb.ReadStorageSnapshot(helper.triedb.DiskDB(), hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data == nil {
  442. t.Fatalf("expected snap storage to exist")
  443. }
  444. snap := generateSnapshot(helper.diskdb, helper.triedb, 16, root)
  445. select {
  446. case <-snap.genPending:
  447. // Snapshot generation succeeded
  448. case <-time.After(3 * time.Second):
  449. t.Errorf("Snapshot generation failed")
  450. }
  451. checkSnapRoot(t, snap, root)
  452. // Signal abortion to the generator and wait for it to tear down
  453. stop := make(chan *generatorStats)
  454. snap.genAbort <- stop
  455. <-stop
  456. // If we now inspect the snap db, there should exist no extraneous storage items
  457. if data := rawdb.ReadStorageSnapshot(helper.triedb.DiskDB(), hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data != nil {
  458. t.Fatalf("expected slot to be removed, got %v", string(data))
  459. }
  460. }
  461. func enableLogging() {
  462. log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
  463. }
  464. // Tests that snapshot generation when an extra account with storage exists in the snap state.
  465. func TestGenerateWithManyExtraAccounts(t *testing.T) {
  466. if false {
  467. enableLogging()
  468. }
  469. helper := newHelper()
  470. {
  471. // Account one in the trie
  472. stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")),
  473. []string{"key-1", "key-2", "key-3"},
  474. []string{"val-1", "val-2", "val-3"},
  475. true,
  476. )
  477. acc := &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}
  478. val, _ := rlp.EncodeToBytes(acc)
  479. helper.accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
  480. // Identical in the snap
  481. key := hashData([]byte("acc-1"))
  482. rawdb.WriteAccountSnapshot(helper.diskdb, key, val)
  483. rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-1")), []byte("val-1"))
  484. rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-2")), []byte("val-2"))
  485. rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-3")), []byte("val-3"))
  486. }
  487. {
  488. // 100 accounts exist only in snapshot
  489. for i := 0; i < 1000; i++ {
  490. //acc := &Account{Balance: big.NewInt(int64(i)), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()}
  491. acc := &Account{Balance: big.NewInt(int64(i)), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}
  492. val, _ := rlp.EncodeToBytes(acc)
  493. key := hashData([]byte(fmt.Sprintf("acc-%d", i)))
  494. rawdb.WriteAccountSnapshot(helper.diskdb, key, val)
  495. }
  496. }
  497. root, snap := helper.CommitAndGenerate()
  498. select {
  499. case <-snap.genPending:
  500. // Snapshot generation succeeded
  501. case <-time.After(3 * time.Second):
  502. t.Errorf("Snapshot generation failed")
  503. }
  504. checkSnapRoot(t, snap, root)
  505. // Signal abortion to the generator and wait for it to tear down
  506. stop := make(chan *generatorStats)
  507. snap.genAbort <- stop
  508. <-stop
  509. }
  510. // Tests this case
  511. // maxAccountRange 3
  512. // snapshot-accounts: 01, 02, 03, 04, 05, 06, 07
  513. // trie-accounts: 03, 07
  514. //
  515. // We iterate three snapshot storage slots (max = 3) from the database. They are 0x01, 0x02, 0x03.
  516. // The trie has a lot of deletions.
  517. // 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.
  518. // But in the database, we still have the stale storage slots 0x04, 0x05. They are not iterated yet, but the procedure is finished.
  519. func TestGenerateWithExtraBeforeAndAfter(t *testing.T) {
  520. accountCheckRange = 3
  521. if false {
  522. enableLogging()
  523. }
  524. helper := newHelper()
  525. {
  526. acc := &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}
  527. val, _ := rlp.EncodeToBytes(acc)
  528. helper.accTrie.Update(common.HexToHash("0x03").Bytes(), val)
  529. helper.accTrie.Update(common.HexToHash("0x07").Bytes(), val)
  530. rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x01"), val)
  531. rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x02"), val)
  532. rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x03"), val)
  533. rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x04"), val)
  534. rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x05"), val)
  535. rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x06"), val)
  536. rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x07"), val)
  537. }
  538. root, snap := helper.CommitAndGenerate()
  539. select {
  540. case <-snap.genPending:
  541. // Snapshot generation succeeded
  542. case <-time.After(3 * time.Second):
  543. t.Errorf("Snapshot generation failed")
  544. }
  545. checkSnapRoot(t, snap, root)
  546. // Signal abortion to the generator and wait for it to tear down
  547. stop := make(chan *generatorStats)
  548. snap.genAbort <- stop
  549. <-stop
  550. }
  551. // TestGenerateWithMalformedSnapdata tests what happes if we have some junk
  552. // in the snapshot database, which cannot be parsed back to an account
  553. func TestGenerateWithMalformedSnapdata(t *testing.T) {
  554. accountCheckRange = 3
  555. if false {
  556. enableLogging()
  557. }
  558. helper := newHelper()
  559. {
  560. acc := &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}
  561. val, _ := rlp.EncodeToBytes(acc)
  562. helper.accTrie.Update(common.HexToHash("0x03").Bytes(), val)
  563. junk := make([]byte, 100)
  564. copy(junk, []byte{0xde, 0xad})
  565. rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x02"), junk)
  566. rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x03"), junk)
  567. rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x04"), junk)
  568. rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x05"), junk)
  569. }
  570. root, snap := helper.CommitAndGenerate()
  571. select {
  572. case <-snap.genPending:
  573. // Snapshot generation succeeded
  574. case <-time.After(3 * time.Second):
  575. t.Errorf("Snapshot generation failed")
  576. }
  577. checkSnapRoot(t, snap, root)
  578. // Signal abortion to the generator and wait for it to tear down
  579. stop := make(chan *generatorStats)
  580. snap.genAbort <- stop
  581. <-stop
  582. // If we now inspect the snap db, there should exist no extraneous storage items
  583. if data := rawdb.ReadStorageSnapshot(helper.diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data != nil {
  584. t.Fatalf("expected slot to be removed, got %v", string(data))
  585. }
  586. }
  587. func TestGenerateFromEmptySnap(t *testing.T) {
  588. //enableLogging()
  589. accountCheckRange = 10
  590. storageCheckRange = 20
  591. helper := newHelper()
  592. // Add 1K accounts to the trie
  593. for i := 0; i < 400; i++ {
  594. stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte(fmt.Sprintf("acc-%d", i))), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
  595. helper.addTrieAccount(fmt.Sprintf("acc-%d", i),
  596. &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
  597. }
  598. root, snap := helper.CommitAndGenerate()
  599. t.Logf("Root: %#x\n", root) // Root: 0x6f7af6d2e1a1bf2b84a3beb3f8b64388465fbc1e274ca5d5d3fc787ca78f59e4
  600. select {
  601. case <-snap.genPending:
  602. // Snapshot generation succeeded
  603. case <-time.After(3 * time.Second):
  604. t.Errorf("Snapshot generation failed")
  605. }
  606. checkSnapRoot(t, snap, root)
  607. // Signal abortion to the generator and wait for it to tear down
  608. stop := make(chan *generatorStats)
  609. snap.genAbort <- stop
  610. <-stop
  611. }
  612. // Tests that snapshot generation with existent flat state, where the flat state
  613. // storage is correct, but incomplete.
  614. // The incomplete part is on the second range
  615. // snap: [ 0x01, 0x02, 0x03, 0x04] , [ 0x05, 0x06, 0x07, {missing}] (with storageCheck = 4)
  616. // trie: 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
  617. // This hits a case where the snap verification passes, but there are more elements in the trie
  618. // which we must also add.
  619. func TestGenerateWithIncompleteStorage(t *testing.T) {
  620. storageCheckRange = 4
  621. helper := newHelper()
  622. stKeys := []string{"1", "2", "3", "4", "5", "6", "7", "8"}
  623. stVals := []string{"v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8"}
  624. // We add 8 accounts, each one is missing exactly one of the storage slots. This means
  625. // we don't have to order the keys and figure out exactly which hash-key winds up
  626. // on the sensitive spots at the boundaries
  627. for i := 0; i < 8; i++ {
  628. accKey := fmt.Sprintf("acc-%d", i)
  629. stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte(accKey)), stKeys, stVals, true)
  630. helper.addAccount(accKey, &Account{Balance: big.NewInt(int64(i)), Root: stRoot, CodeHash: emptyCode.Bytes()})
  631. var moddedKeys []string
  632. var moddedVals []string
  633. for ii := 0; ii < 8; ii++ {
  634. if ii != i {
  635. moddedKeys = append(moddedKeys, stKeys[ii])
  636. moddedVals = append(moddedVals, stVals[ii])
  637. }
  638. }
  639. helper.addSnapStorage(accKey, moddedKeys, moddedVals)
  640. }
  641. root, snap := helper.CommitAndGenerate()
  642. t.Logf("Root: %#x\n", root) // Root: 0xca73f6f05ba4ca3024ef340ef3dfca8fdabc1b677ff13f5a9571fd49c16e67ff
  643. select {
  644. case <-snap.genPending:
  645. // Snapshot generation succeeded
  646. case <-time.After(3 * time.Second):
  647. t.Errorf("Snapshot generation failed")
  648. }
  649. checkSnapRoot(t, snap, root)
  650. // Signal abortion to the generator and wait for it to tear down
  651. stop := make(chan *generatorStats)
  652. snap.genAbort <- stop
  653. <-stop
  654. }
  655. func incKey(key []byte) []byte {
  656. for i := len(key) - 1; i >= 0; i-- {
  657. key[i]++
  658. if key[i] != 0x0 {
  659. break
  660. }
  661. }
  662. return key
  663. }
  664. func decKey(key []byte) []byte {
  665. for i := len(key) - 1; i >= 0; i-- {
  666. key[i]--
  667. if key[i] != 0xff {
  668. break
  669. }
  670. }
  671. return key
  672. }
  673. func populateDangling(disk ethdb.KeyValueStore) {
  674. populate := func(accountHash common.Hash, keys []string, vals []string) {
  675. for i, key := range keys {
  676. rawdb.WriteStorageSnapshot(disk, accountHash, hashData([]byte(key)), []byte(vals[i]))
  677. }
  678. }
  679. // Dangling storages of the "first" account
  680. populate(common.Hash{}, []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
  681. // Dangling storages of the "last" account
  682. populate(common.HexToHash("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
  683. // Dangling storages around the account 1
  684. hash := decKey(hashData([]byte("acc-1")).Bytes())
  685. populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
  686. hash = incKey(hashData([]byte("acc-1")).Bytes())
  687. populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
  688. // Dangling storages around the account 2
  689. hash = decKey(hashData([]byte("acc-2")).Bytes())
  690. populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
  691. hash = incKey(hashData([]byte("acc-2")).Bytes())
  692. populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
  693. // Dangling storages around the account 3
  694. hash = decKey(hashData([]byte("acc-3")).Bytes())
  695. populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
  696. hash = incKey(hashData([]byte("acc-3")).Bytes())
  697. populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
  698. // Dangling storages of the random account
  699. populate(randomHash(), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
  700. populate(randomHash(), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
  701. populate(randomHash(), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
  702. }
  703. // Tests that snapshot generation with dangling storages. Dangling storage means
  704. // the storage data is existent while the corresponding account data is missing.
  705. //
  706. // This test will populate some dangling storages to see if they can be cleaned up.
  707. func TestGenerateCompleteSnapshotWithDanglingStorage(t *testing.T) {
  708. var helper = newHelper()
  709. stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
  710. helper.addAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
  711. helper.addAccount("acc-2", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()})
  712. helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
  713. helper.addAccount("acc-3", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
  714. helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
  715. helper.addSnapStorage("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
  716. populateDangling(helper.diskdb)
  717. root, snap := helper.CommitAndGenerate()
  718. select {
  719. case <-snap.genPending:
  720. // Snapshot generation succeeded
  721. case <-time.After(3 * time.Second):
  722. t.Errorf("Snapshot generation failed")
  723. }
  724. checkSnapRoot(t, snap, root)
  725. // Signal abortion to the generator and wait for it to tear down
  726. stop := make(chan *generatorStats)
  727. snap.genAbort <- stop
  728. <-stop
  729. }
  730. // Tests that snapshot generation with dangling storages. Dangling storage means
  731. // the storage data is existent while the corresponding account data is missing.
  732. //
  733. // This test will populate some dangling storages to see if they can be cleaned up.
  734. func TestGenerateBrokenSnapshotWithDanglingStorage(t *testing.T) {
  735. var helper = newHelper()
  736. stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
  737. helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
  738. helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()})
  739. helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
  740. helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: emptyCode.Bytes()})
  741. populateDangling(helper.diskdb)
  742. root, snap := helper.CommitAndGenerate()
  743. select {
  744. case <-snap.genPending:
  745. // Snapshot generation succeeded
  746. case <-time.After(3 * time.Second):
  747. t.Errorf("Snapshot generation failed")
  748. }
  749. checkSnapRoot(t, snap, root)
  750. // Signal abortion to the generator and wait for it to tear down
  751. stop := make(chan *generatorStats)
  752. snap.genAbort <- stop
  753. <-stop
  754. }