bsc/core/blockchain_notries_test.go

227 lines
7.3 KiB
Go
Raw Permalink Normal View History

// 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)
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
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)
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
if err == nil || fastnode.chain.CurrentBlock().Number.Uint64() != failed.blockNumber+10 {
t.Fatalf("blocks insert should be failed at height %d", failed.blockNumber+11)
}
}