blockchain_diff_test.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  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. // Tests that abnormal program termination (i.e.crash) and restart doesn't leave
  17. // the database in some strange state with gaps in the chain, nor with block data
  18. // dangling in the future.
  19. package core
  20. import (
  21. "bytes"
  22. "encoding/hex"
  23. "math/big"
  24. "testing"
  25. "time"
  26. "golang.org/x/crypto/sha3"
  27. "github.com/ethereum/go-ethereum/common"
  28. "github.com/ethereum/go-ethereum/consensus/ethash"
  29. "github.com/ethereum/go-ethereum/core/rawdb"
  30. "github.com/ethereum/go-ethereum/core/state/snapshot"
  31. "github.com/ethereum/go-ethereum/core/types"
  32. "github.com/ethereum/go-ethereum/core/vm"
  33. "github.com/ethereum/go-ethereum/crypto"
  34. "github.com/ethereum/go-ethereum/ethdb"
  35. "github.com/ethereum/go-ethereum/ethdb/memorydb"
  36. "github.com/ethereum/go-ethereum/params"
  37. "github.com/ethereum/go-ethereum/rlp"
  38. )
  39. var (
  40. // testKey is a private key to use for funding a tester account.
  41. testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
  42. contractCode, _ = hex.DecodeString("608060405260016000806101000a81548160ff02191690831515021790555034801561002a57600080fd5b506101688061003a6000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806389a2d8011461003b578063b0483f4814610059575b600080fd5b610043610075565b60405161005091906100f4565b60405180910390f35b610073600480360381019061006e91906100bc565b61008b565b005b60008060009054906101000a900460ff16905090565b806000806101000a81548160ff02191690831515021790555050565b6000813590506100b68161011b565b92915050565b6000602082840312156100ce57600080fd5b60006100dc848285016100a7565b91505092915050565b6100ee8161010f565b82525050565b600060208201905061010960008301846100e5565b92915050565b60008115159050919050565b6101248161010f565b811461012f57600080fd5b5056fea264697066735822122092f788b569bfc3786e90601b5dbec01cfc3d76094164fd66ca7d599c4239fc5164736f6c63430008000033")
  43. contractAddr = common.HexToAddress("0xe74a3c7427cda785e0000d42a705b1f3fd371e09")
  44. contractSlot = common.HexToHash("0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563")
  45. contractData1, _ = hex.DecodeString("b0483f480000000000000000000000000000000000000000000000000000000000000000")
  46. contractData2, _ = hex.DecodeString("b0483f480000000000000000000000000000000000000000000000000000000000000001")
  47. commonGas = 192138
  48. // testAddr is the Ethereum address of the tester account.
  49. testAddr = crypto.PubkeyToAddress(testKey.PublicKey)
  50. checkBlocks = map[int]checkBlockParam{
  51. 12: {
  52. txs: []checkTransactionParam{
  53. {
  54. to: &contractAddr,
  55. slot: contractSlot,
  56. value: []byte{01},
  57. },
  58. }},
  59. 13: {
  60. txs: []checkTransactionParam{
  61. {
  62. to: &contractAddr,
  63. slot: contractSlot,
  64. value: []byte{},
  65. },
  66. }},
  67. 14: {
  68. txs: []checkTransactionParam{
  69. {
  70. to: &contractAddr,
  71. slot: contractSlot,
  72. value: []byte{01},
  73. },
  74. }},
  75. }
  76. // testBlocks is the test parameters array for specific blocks.
  77. testBlocks = []testBlockParam{
  78. {
  79. // This txs params also used to default block.
  80. blockNr: 11,
  81. txs: []testTransactionParam{
  82. {
  83. to: &common.Address{0x01},
  84. value: big.NewInt(1),
  85. gasPrice: big.NewInt(1),
  86. data: nil,
  87. },
  88. },
  89. },
  90. {
  91. blockNr: 12,
  92. txs: []testTransactionParam{
  93. {
  94. to: &common.Address{0x01},
  95. value: big.NewInt(1),
  96. gasPrice: big.NewInt(1),
  97. data: nil,
  98. },
  99. {
  100. to: &common.Address{0x02},
  101. value: big.NewInt(2),
  102. gasPrice: big.NewInt(2),
  103. data: nil,
  104. },
  105. {
  106. to: nil,
  107. value: big.NewInt(0),
  108. gasPrice: big.NewInt(2),
  109. data: contractCode,
  110. },
  111. },
  112. },
  113. {
  114. blockNr: 13,
  115. txs: []testTransactionParam{
  116. {
  117. to: &common.Address{0x01},
  118. value: big.NewInt(1),
  119. gasPrice: big.NewInt(1),
  120. data: nil,
  121. },
  122. {
  123. to: &common.Address{0x02},
  124. value: big.NewInt(2),
  125. gasPrice: big.NewInt(2),
  126. data: nil,
  127. },
  128. {
  129. to: &common.Address{0x03},
  130. value: big.NewInt(3),
  131. gasPrice: big.NewInt(3),
  132. data: nil,
  133. },
  134. {
  135. to: &contractAddr,
  136. value: big.NewInt(0),
  137. gasPrice: big.NewInt(3),
  138. data: contractData1,
  139. },
  140. },
  141. },
  142. {
  143. blockNr: 14,
  144. txs: []testTransactionParam{
  145. {
  146. to: &contractAddr,
  147. value: big.NewInt(0),
  148. gasPrice: big.NewInt(3),
  149. data: contractData2,
  150. },
  151. },
  152. },
  153. {
  154. blockNr: 15,
  155. txs: []testTransactionParam{},
  156. },
  157. }
  158. )
  159. type testTransactionParam struct {
  160. to *common.Address
  161. value *big.Int
  162. gasPrice *big.Int
  163. data []byte
  164. }
  165. type testBlockParam struct {
  166. blockNr int
  167. txs []testTransactionParam
  168. }
  169. type checkTransactionParam struct {
  170. to *common.Address
  171. slot common.Hash
  172. value []byte
  173. }
  174. type checkBlockParam struct {
  175. txs []checkTransactionParam
  176. }
  177. // testBackend is a mock implementation of the live Ethereum message handler. Its
  178. // purpose is to allow testing the request/reply workflows and wire serialization
  179. // in the `eth` protocol without actually doing any data processing.
  180. type testBackend struct {
  181. db ethdb.Database
  182. chain *BlockChain
  183. }
  184. // newTestBackend creates an empty chain and wraps it into a mock backend.
  185. func newTestBackend(blocks int, light bool) *testBackend {
  186. return newTestBackendWithGenerator(blocks, light)
  187. }
  188. // newTestBackend creates a chain with a number of explicitly defined blocks and
  189. // wraps it into a mock backend.
  190. func newTestBackendWithGenerator(blocks int, lightProcess bool) *testBackend {
  191. signer := types.HomesteadSigner{}
  192. // Create a database pre-initialize with a genesis block
  193. db := rawdb.NewMemoryDatabase()
  194. db.SetDiffStore(memorydb.New())
  195. (&Genesis{
  196. Config: params.TestChainConfig,
  197. Alloc: GenesisAlloc{testAddr: {Balance: big.NewInt(100000000000000000)}},
  198. }).MustCommit(db)
  199. chain, _ := NewBlockChain(db, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, nil, EnablePersistDiff(860000))
  200. generator := func(i int, block *BlockGen) {
  201. // The chain maker doesn't have access to a chain, so the difficulty will be
  202. // lets unset (nil). Set it here to the correct value.
  203. block.SetCoinbase(testAddr)
  204. for idx, testBlock := range testBlocks {
  205. // Specific block setting, the index in this generator has 1 diff from specified blockNr.
  206. if i+1 == testBlock.blockNr {
  207. for _, testTransaction := range testBlock.txs {
  208. var transaction *types.Transaction
  209. if testTransaction.to == nil {
  210. transaction = types.NewContractCreation(block.TxNonce(testAddr),
  211. testTransaction.value, uint64(commonGas), testTransaction.gasPrice, testTransaction.data)
  212. } else {
  213. transaction = types.NewTransaction(block.TxNonce(testAddr), *testTransaction.to,
  214. testTransaction.value, uint64(commonGas), testTransaction.gasPrice, testTransaction.data)
  215. }
  216. tx, err := types.SignTx(transaction, signer, testKey)
  217. if err != nil {
  218. panic(err)
  219. }
  220. block.AddTxWithChain(chain, tx)
  221. }
  222. break
  223. }
  224. // Default block setting.
  225. if idx == len(testBlocks)-1 {
  226. // We want to simulate an empty middle block, having the same state as the
  227. // first one. The last is needs a state change again to force a reorg.
  228. for _, testTransaction := range testBlocks[0].txs {
  229. tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddr), *testTransaction.to,
  230. testTransaction.value, uint64(commonGas), testTransaction.gasPrice, testTransaction.data), signer, testKey)
  231. if err != nil {
  232. panic(err)
  233. }
  234. block.AddTxWithChain(chain, tx)
  235. }
  236. }
  237. }
  238. }
  239. bs, _ := GenerateChain(params.TestChainConfig, chain.Genesis(), ethash.NewFaker(), db, blocks, generator)
  240. if _, err := chain.InsertChain(bs); err != nil {
  241. panic(err)
  242. }
  243. if lightProcess {
  244. EnableLightProcessor(chain)
  245. }
  246. return &testBackend{
  247. db: db,
  248. chain: chain,
  249. }
  250. }
  251. // close tears down the transaction pool and chain behind the mock backend.
  252. func (b *testBackend) close() {
  253. b.chain.Stop()
  254. }
  255. func (b *testBackend) Chain() *BlockChain { return b.chain }
  256. func rawDataToDiffLayer(data rlp.RawValue) (*types.DiffLayer, error) {
  257. var diff types.DiffLayer
  258. hasher := sha3.NewLegacyKeccak256()
  259. err := rlp.DecodeBytes(data, &diff)
  260. if err != nil {
  261. return nil, err
  262. }
  263. hasher.Write(data)
  264. var diffHash common.Hash
  265. hasher.Sum(diffHash[:0])
  266. diff.DiffHash = diffHash
  267. hasher.Reset()
  268. return &diff, nil
  269. }
  270. func TestProcessDiffLayer(t *testing.T) {
  271. blockNum := 128
  272. fullBackend := newTestBackend(blockNum, false)
  273. falseDiff := 5
  274. defer fullBackend.close()
  275. lightBackend := newTestBackend(0, true)
  276. defer lightBackend.close()
  277. for i := 1; i <= blockNum-falseDiff; i++ {
  278. block := fullBackend.chain.GetBlockByNumber(uint64(i))
  279. if block == nil {
  280. t.Fatal("block should not be nil")
  281. }
  282. blockHash := block.Hash()
  283. rawDiff := fullBackend.chain.GetDiffLayerRLP(blockHash)
  284. if len(rawDiff) != 0 {
  285. diff, err := rawDataToDiffLayer(rawDiff)
  286. if err != nil {
  287. t.Errorf("failed to decode rawdata %v", err)
  288. }
  289. if diff == nil {
  290. continue
  291. }
  292. lightBackend.Chain().HandleDiffLayer(diff, "testpid", true)
  293. }
  294. _, err := lightBackend.chain.insertChain([]*types.Block{block}, true)
  295. if checks, exist := checkBlocks[i]; exist {
  296. for _, check := range checks.txs {
  297. s, _ := lightBackend.Chain().Snapshots().Snapshot(block.Root()).Storage(crypto.Keccak256Hash((*check.to)[:]), check.slot)
  298. if !bytes.Equal(s, check.value) {
  299. t.Fatalf("Expected value %x, get %x", check.value, s)
  300. }
  301. }
  302. }
  303. if err != nil {
  304. t.Errorf("failed to insert block %v", err)
  305. }
  306. }
  307. currentBlock := lightBackend.chain.CurrentBlock()
  308. nextBlock := fullBackend.chain.GetBlockByNumber(currentBlock.NumberU64() + 1)
  309. rawDiff := fullBackend.chain.GetDiffLayerRLP(nextBlock.Hash())
  310. diff, _ := rawDataToDiffLayer(rawDiff)
  311. latestAccount, _ := snapshot.FullAccount(diff.Accounts[0].Blob)
  312. latestAccount.Balance = big.NewInt(0)
  313. bz, _ := rlp.EncodeToBytes(&latestAccount)
  314. diff.Accounts[0].Blob = bz
  315. lightBackend.Chain().HandleDiffLayer(diff, "testpid", true)
  316. _, err := lightBackend.chain.insertChain([]*types.Block{nextBlock}, true)
  317. if err != nil {
  318. t.Errorf("failed to process block %v", err)
  319. }
  320. // the diff cache should be cleared
  321. if len(lightBackend.chain.diffPeersToDiffHashes) != 0 {
  322. t.Errorf("the size of diffPeersToDiffHashes should be 0, but get %d", len(lightBackend.chain.diffPeersToDiffHashes))
  323. }
  324. if len(lightBackend.chain.diffHashToPeers) != 0 {
  325. t.Errorf("the size of diffHashToPeers should be 0, but get %d", len(lightBackend.chain.diffHashToPeers))
  326. }
  327. if len(lightBackend.chain.diffHashToBlockHash) != 0 {
  328. t.Errorf("the size of diffHashToBlockHash should be 0, but get %d", len(lightBackend.chain.diffHashToBlockHash))
  329. }
  330. if len(lightBackend.chain.blockHashToDiffLayers) != 0 {
  331. t.Errorf("the size of blockHashToDiffLayers should be 0, but get %d", len(lightBackend.chain.blockHashToDiffLayers))
  332. }
  333. }
  334. func TestFreezeDiffLayer(t *testing.T) {
  335. blockNum := 1024
  336. fullBackend := newTestBackend(blockNum, true)
  337. defer fullBackend.close()
  338. for len(fullBackend.chain.diffQueueBuffer) > 0 {
  339. // Wait for the buffer to be zero.
  340. }
  341. // Minus one empty block.
  342. if fullBackend.chain.diffQueue.Size() != blockNum-1 {
  343. t.Errorf("size of diff queue is wrong, expected: %d, get: %d", blockNum-1, fullBackend.chain.diffQueue.Size())
  344. }
  345. time.Sleep(diffLayerFreezerRecheckInterval + 2*time.Second)
  346. if fullBackend.chain.diffQueue.Size() != int(fullBackend.chain.triesInMemory) {
  347. t.Errorf("size of diff queue is wrong, expected: %d, get: %d", blockNum, fullBackend.chain.diffQueue.Size())
  348. }
  349. block := fullBackend.chain.GetBlockByNumber(uint64(blockNum / 2))
  350. diffStore := fullBackend.chain.db.DiffStore()
  351. rawData := rawdb.ReadDiffLayerRLP(diffStore, block.Hash())
  352. if len(rawData) == 0 {
  353. t.Error("do not find diff layer in db")
  354. }
  355. }
  356. func TestPruneDiffLayer(t *testing.T) {
  357. blockNum := 1024
  358. fullBackend := newTestBackend(blockNum, true)
  359. defer fullBackend.close()
  360. anotherFullBackend := newTestBackend(2*blockNum, true)
  361. defer anotherFullBackend.close()
  362. for num := uint64(1); num < uint64(blockNum); num++ {
  363. header := fullBackend.chain.GetHeaderByNumber(num)
  364. rawDiff := fullBackend.chain.GetDiffLayerRLP(header.Hash())
  365. if len(rawDiff) != 0 {
  366. diff, _ := rawDataToDiffLayer(rawDiff)
  367. fullBackend.Chain().HandleDiffLayer(diff, "testpid1", true)
  368. fullBackend.Chain().HandleDiffLayer(diff, "testpid2", true)
  369. }
  370. }
  371. fullBackend.chain.pruneDiffLayer()
  372. if len(fullBackend.chain.diffNumToBlockHashes) != maxDiffForkDist {
  373. t.Error("unexpected size of diffNumToBlockHashes")
  374. }
  375. if len(fullBackend.chain.diffPeersToDiffHashes) != 1 {
  376. t.Error("unexpected size of diffPeersToDiffHashes")
  377. }
  378. if len(fullBackend.chain.blockHashToDiffLayers) != maxDiffForkDist {
  379. t.Error("unexpected size of diffNumToBlockHashes")
  380. }
  381. if len(fullBackend.chain.diffHashToBlockHash) != maxDiffForkDist {
  382. t.Error("unexpected size of diffHashToBlockHash")
  383. }
  384. if len(fullBackend.chain.diffHashToPeers) != maxDiffForkDist {
  385. t.Error("unexpected size of diffHashToPeers")
  386. }
  387. blocks := make([]*types.Block, 0, blockNum)
  388. for i := blockNum + 1; i <= 2*blockNum; i++ {
  389. b := anotherFullBackend.chain.GetBlockByNumber(uint64(i))
  390. blocks = append(blocks, b)
  391. }
  392. fullBackend.chain.insertChain(blocks, true)
  393. fullBackend.chain.pruneDiffLayer()
  394. if len(fullBackend.chain.diffNumToBlockHashes) != 0 {
  395. t.Error("unexpected size of diffNumToBlockHashes")
  396. }
  397. if len(fullBackend.chain.diffPeersToDiffHashes) != 0 {
  398. t.Error("unexpected size of diffPeersToDiffHashes")
  399. }
  400. if len(fullBackend.chain.blockHashToDiffLayers) != 0 {
  401. t.Error("unexpected size of diffNumToBlockHashes")
  402. }
  403. if len(fullBackend.chain.diffHashToBlockHash) != 0 {
  404. t.Error("unexpected size of diffHashToBlockHash")
  405. }
  406. if len(fullBackend.chain.diffHashToPeers) != 0 {
  407. t.Error("unexpected size of diffHashToPeers")
  408. }
  409. }
  410. func TestGetDiffAccounts(t *testing.T) {
  411. blockNum := 128
  412. fullBackend := newTestBackend(blockNum, false)
  413. defer fullBackend.close()
  414. for _, testBlock := range testBlocks {
  415. block := fullBackend.chain.GetBlockByNumber(uint64(testBlock.blockNr))
  416. if block == nil {
  417. t.Fatal("block should not be nil")
  418. }
  419. blockHash := block.Hash()
  420. accounts, err := fullBackend.chain.GetDiffAccounts(blockHash)
  421. if err != nil {
  422. t.Errorf("get diff accounts eror for block number (%d): %v", testBlock.blockNr, err)
  423. }
  424. for idx, account := range accounts {
  425. if testAddr == account {
  426. break
  427. }
  428. if idx == len(accounts)-1 {
  429. t.Errorf("the diff accounts does't include addr: %v", testAddr)
  430. }
  431. }
  432. for _, transaction := range testBlock.txs {
  433. if transaction.to == nil || len(transaction.data) > 0 {
  434. continue
  435. }
  436. for idx, account := range accounts {
  437. if *transaction.to == account {
  438. break
  439. }
  440. if idx == len(accounts)-1 {
  441. t.Errorf("the diff accounts does't include addr: %v", transaction.to)
  442. }
  443. }
  444. }
  445. }
  446. }