bsc/core/blockchain_notries_test.go
NathanBSC 202ab70922
Big merge v1.10.16 v1.12.2 fix ci (#1850)
* fix: crash of highestVerifiedHeader

* fix: panic of blobpool

* fix: genesis set up

* 1. modify NewDatabaseWithNodeDB to upstream
2. fix race use of hasher in statedb
3. fix use wrong value when updateTrie

* fix dir legacypool

* fix dir blobpool

* fix dir vote

* remove diffsync related code

* fix core/state/snapshot

* disable pipeCommit for now

* fix applyTransaction for bloom setting

* CI: fast finality in gasprice test

* CI: diffFetcher was removed

* CI: downloader, remove beaconsync test

* CI: no beaconsync in downloader, remove a failed case

TestCheckpointChallenge was removed in:
https://github.com/ethereum/go-ethereum/pull/27147
since after merge, it is useless for ethereum, but might be useful for BSC.
disable the case right now, as it is not a big issue.

* CI: bsc protocol decHandlers

* CI: receipt Bloom process

* 1. skip CheckConfigForkOrder for non-parlia engine
2. all test cases in core work well now
	cd core && go test ./... -v

* fix test cases in trie dir

* CI: no beaconsync in downloader, remove a failed case(redo)

* fix dir miner

* fix dir cmd/geth

* CI: filter test, BaseFee & Finality

* fix dir graphql

* remove diffStore

* fix ethclient

* fix TestRPCGetTransactionReceipt

* fix dir internal

* ut add dir ethstats and signer

* disable pipeCommit thoroughly; fix concurrent map iteration and map write in statedb

* CI: fix snap sync

it could be changed by mistake

* fix tests/Run to generate snapshot

* prepare for merge

* remove useless

* use common hasher in getDeletedStateObject, no race here

* an critical comment for state.Prepare

* do not copy nil accessList

* add omitempty tag for unused new fields of core.Genesis

* remove totalFees

* calculate fees before FinalizeAndAssemble

* revert interface Finalize of consensus

* do not double gas limit upon london block

* use Leveldb as default

* Revert "remove diffStore"

This reverts commit df343b137412b0beb25298a6ba9c3c19e47f20b1.

* Revert "remove diffsync related code"

This reverts commit 8d84b81feae5d794cb5d7fcfdb7f5f7da751941b.

* compile pass after revert

* remove diffsync

* fix dir eth/protocols/trust

* fix TestFastNode

* decHandlers for trust protocol

* keep persist diff in test
2023-09-07 16:39:29 +08:00

227 lines
7.3 KiB
Go

// Copyright 2020 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// Tests that abnormal program termination (i.e.crash) and restart doesn't leave
// the database in some strange state with gaps in the chain, nor with block data
// dangling in the future.
package core
import (
"math/big"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/ethdb/memorydb"
"github.com/ethereum/go-ethereum/params"
)
func newMockVerifyPeer() *mockVerifyPeer {
return &mockVerifyPeer{}
}
type requestRoot struct {
blockNumber uint64
blockHash common.Hash
diffHash common.Hash
}
type verifFailedStatus struct {
status types.VerifyStatus
blockNumber uint64
}
// mockVerifyPeer is a mocking struct that simulates p2p signals for verification tasks.
type mockVerifyPeer struct {
callback func(*requestRoot)
}
func (peer *mockVerifyPeer) setCallBack(callback func(*requestRoot)) {
peer.callback = callback
}
func (peer *mockVerifyPeer) RequestRoot(blockNumber uint64, blockHash common.Hash, diffHash common.Hash) error {
if peer.callback != nil {
peer.callback(&requestRoot{blockNumber, blockHash, diffHash})
}
return nil
}
func (peer *mockVerifyPeer) ID() string {
return "mock_peer"
}
type mockVerifyPeers struct {
peers []VerifyPeer
}
func (peers *mockVerifyPeers) GetVerifyPeers() []VerifyPeer {
return peers.peers
}
func newMockRemoteVerifyPeer(peers []VerifyPeer) *mockVerifyPeers {
return &mockVerifyPeers{peers}
}
func makeTestBackendWithRemoteValidator(blocks int, mode VerifyMode, failed *verifFailedStatus) (*testBackend, *testBackend, []*types.Block, error) {
signer := types.HomesteadSigner{}
// Create a database pre-initialize with a genesis block
db := rawdb.NewMemoryDatabase()
db.SetDiffStore(memorydb.New())
gspec := &Genesis{
Config: params.TestChainConfig,
Alloc: GenesisAlloc{testAddr: {Balance: big.NewInt(100000000000000000)}},
}
engine := ethash.NewFaker()
db2 := rawdb.NewMemoryDatabase()
db2.SetDiffStore(memorydb.New())
gspec2 := &Genesis{
Config: params.TestChainConfig,
Alloc: GenesisAlloc{testAddr: {Balance: big.NewInt(100000000000000000)}},
}
engine2 := ethash.NewFaker()
peer := newMockVerifyPeer()
peers := []VerifyPeer{peer}
verifier, err := NewBlockChain(db, nil, gspec, nil, engine, vm.Config{},
nil, nil, EnablePersistDiff(100000), EnableBlockValidator(params.TestChainConfig, engine2, LocalVerify, nil))
if err != nil {
return nil, nil, nil, err
}
fastnode, err := NewBlockChain(db2, nil, gspec2, nil, engine2, vm.Config{},
nil, nil, EnableBlockValidator(params.TestChainConfig, engine2, mode, newMockRemoteVerifyPeer(peers)))
if err != nil {
return nil, nil, nil, err
}
generator := func(i int, block *BlockGen) {
// The chain maker doesn't have access to a chain, so the difficulty will be
// lets unset (nil). Set it here to the correct value.
block.SetCoinbase(testAddr)
for idx, testBlock := range testBlocks {
// Specific block setting, the index in this generator has 1 diff from specified blockNr.
if i+1 == testBlock.blockNr {
for _, testTransaction := range testBlock.txs {
var transaction *types.Transaction
if testTransaction.to == nil {
transaction = types.NewContractCreation(block.TxNonce(testAddr),
testTransaction.value, uint64(commonGas), testTransaction.gasPrice, testTransaction.data)
} else {
transaction = types.NewTransaction(block.TxNonce(testAddr), *testTransaction.to,
testTransaction.value, uint64(commonGas), testTransaction.gasPrice, testTransaction.data)
}
tx, err := types.SignTx(transaction, signer, testKey)
if err != nil {
panic(err)
}
block.AddTxWithChain(verifier, tx)
}
break
}
// Default block setting.
if idx == len(testBlocks)-1 {
// We want to simulate an empty middle block, having the same state as the
// first one. The last is needs a state change again to force a reorg.
for _, testTransaction := range testBlocks[0].txs {
tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddr), *testTransaction.to,
testTransaction.value, uint64(commonGas), testTransaction.gasPrice, testTransaction.data), signer, testKey)
if err != nil {
panic(err)
}
block.AddTxWithChain(verifier, tx)
}
}
}
}
peer.setCallBack(func(req *requestRoot) {
if fastnode.validator != nil && fastnode.validator.RemoteVerifyManager() != nil {
resp := verifier.GetVerifyResult(req.blockNumber, req.blockHash, req.diffHash)
if failed != nil && req.blockNumber == failed.blockNumber {
resp.Status = failed.status
}
fastnode.validator.RemoteVerifyManager().
HandleRootResponse(
resp, peer.ID())
}
})
bs, _ := GenerateChain(params.TestChainConfig, verifier.Genesis(), ethash.NewFaker(), db, blocks, generator)
if _, err := verifier.InsertChain(bs); err != nil {
return nil, nil, nil, err
}
waitDifflayerCached(verifier, bs)
return &testBackend{
db: db,
chain: verifier,
},
&testBackend{
db: db2,
chain: fastnode,
}, bs, nil
}
func TestFastNode(t *testing.T) {
// test full mode and succeed
_, fastnode, blocks, err := makeTestBackendWithRemoteValidator(2048, FullVerify, nil)
if err != nil {
t.Fatalf(err.Error())
}
_, err = fastnode.chain.InsertChain(blocks)
if err != nil {
t.Fatalf(err.Error())
}
// test full mode and failed
failed := &verifFailedStatus{status: types.StatusDiffHashMismatch, blockNumber: 204}
_, fastnode, blocks, err = makeTestBackendWithRemoteValidator(2048, FullVerify, failed)
if err != nil {
t.Fatalf(err.Error())
}
_, err = fastnode.chain.InsertChain(blocks)
if err == nil || fastnode.chain.CurrentBlock().Number.Uint64() != failed.blockNumber+10 {
t.Fatalf("blocks insert should be failed at height %d", failed.blockNumber+11)
}
// test insecure mode and succeed
_, fastnode, blocks, err = makeTestBackendWithRemoteValidator(2048, InsecureVerify, nil)
if err != nil {
t.Fatalf(err.Error())
}
_, err = fastnode.chain.InsertChain(blocks)
if err != nil {
t.Fatalf(err.Error())
}
// test insecure mode and failed
failed = &verifFailedStatus{status: types.StatusImpossibleFork, blockNumber: 204}
_, fastnode, blocks, err = makeTestBackendWithRemoteValidator(2048, FullVerify, failed)
if err != nil {
t.Fatalf(err.Error())
}
_, err = fastnode.chain.InsertChain(blocks)
if err == nil || fastnode.chain.CurrentBlock().Number.Uint64() != failed.blockNumber+10 {
t.Fatalf("blocks insert should be failed at height %d", failed.blockNumber+11)
}
}