generate_test.go 9.4 KB

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