| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- // Copyright 2022 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/>.
- package catalyst
- import (
- "math/big"
- "testing"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/consensus/ethash"
- "github.com/ethereum/go-ethereum/core"
- "github.com/ethereum/go-ethereum/core/beacon"
- "github.com/ethereum/go-ethereum/core/rawdb"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/eth/downloader"
- "github.com/ethereum/go-ethereum/eth/ethconfig"
- "github.com/ethereum/go-ethereum/les"
- "github.com/ethereum/go-ethereum/node"
- "github.com/ethereum/go-ethereum/params"
- "github.com/ethereum/go-ethereum/trie"
- )
- var (
- // testKey is a private key to use for funding a tester account.
- testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
- // testAddr is the Ethereum address of the tester account.
- testAddr = crypto.PubkeyToAddress(testKey.PublicKey)
- testBalance = big.NewInt(2e18)
- )
- func generatePreMergeChain(n int) (*core.Genesis, []*types.Header, []*types.Block) {
- db := rawdb.NewMemoryDatabase()
- config := params.AllEthashProtocolChanges
- genesis := &core.Genesis{
- Config: config,
- Alloc: core.GenesisAlloc{testAddr: {Balance: testBalance}},
- ExtraData: []byte("test genesis"),
- Timestamp: 9000,
- BaseFee: big.NewInt(params.InitialBaseFee),
- }
- gblock := genesis.MustCommit(db)
- engine := ethash.NewFaker()
- blocks, _ := core.GenerateChain(config, gblock, engine, db, n, nil)
- totalDifficulty := big.NewInt(0)
- var headers []*types.Header
- for _, b := range blocks {
- totalDifficulty.Add(totalDifficulty, b.Difficulty())
- headers = append(headers, b.Header())
- }
- config.TerminalTotalDifficulty = totalDifficulty
- return genesis, headers, blocks
- }
- func TestSetHeadBeforeTotalDifficulty(t *testing.T) {
- genesis, headers, blocks := generatePreMergeChain(10)
- n, lesService := startLesService(t, genesis, headers)
- defer n.Close()
- api := NewConsensusAPI(lesService)
- fcState := beacon.ForkchoiceStateV1{
- HeadBlockHash: blocks[5].Hash(),
- SafeBlockHash: common.Hash{},
- FinalizedBlockHash: common.Hash{},
- }
- if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err == nil {
- t.Errorf("fork choice updated before total terminal difficulty should fail")
- }
- }
- func TestExecutePayloadV1(t *testing.T) {
- genesis, headers, blocks := generatePreMergeChain(10)
- n, lesService := startLesService(t, genesis, headers[:9])
- lesService.Merger().ReachTTD()
- defer n.Close()
- api := NewConsensusAPI(lesService)
- fcState := beacon.ForkchoiceStateV1{
- HeadBlockHash: blocks[8].Hash(),
- SafeBlockHash: common.Hash{},
- FinalizedBlockHash: common.Hash{},
- }
- if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil {
- t.Errorf("Failed to update head %v", err)
- }
- block := blocks[9]
- fakeBlock := types.NewBlock(&types.Header{
- ParentHash: block.ParentHash(),
- UncleHash: crypto.Keccak256Hash(nil),
- Coinbase: block.Coinbase(),
- Root: block.Root(),
- TxHash: crypto.Keccak256Hash(nil),
- ReceiptHash: crypto.Keccak256Hash(nil),
- Bloom: block.Bloom(),
- Difficulty: big.NewInt(0),
- Number: block.Number(),
- GasLimit: block.GasLimit(),
- GasUsed: block.GasUsed(),
- Time: block.Time(),
- Extra: block.Extra(),
- MixDigest: block.MixDigest(),
- Nonce: types.BlockNonce{},
- BaseFee: block.BaseFee(),
- }, nil, nil, nil, trie.NewStackTrie(nil))
- _, err := api.ExecutePayloadV1(beacon.ExecutableDataV1{
- ParentHash: fakeBlock.ParentHash(),
- FeeRecipient: fakeBlock.Coinbase(),
- StateRoot: fakeBlock.Root(),
- ReceiptsRoot: fakeBlock.ReceiptHash(),
- LogsBloom: fakeBlock.Bloom().Bytes(),
- Random: fakeBlock.MixDigest(),
- Number: fakeBlock.NumberU64(),
- GasLimit: fakeBlock.GasLimit(),
- GasUsed: fakeBlock.GasUsed(),
- Timestamp: fakeBlock.Time(),
- ExtraData: fakeBlock.Extra(),
- BaseFeePerGas: fakeBlock.BaseFee(),
- BlockHash: fakeBlock.Hash(),
- Transactions: encodeTransactions(fakeBlock.Transactions()),
- })
- if err != nil {
- t.Errorf("Failed to execute payload %v", err)
- }
- headHeader := api.les.BlockChain().CurrentHeader()
- if headHeader.Number.Uint64() != fakeBlock.NumberU64()-1 {
- t.Fatal("Unexpected chain head update")
- }
- fcState = beacon.ForkchoiceStateV1{
- HeadBlockHash: fakeBlock.Hash(),
- SafeBlockHash: common.Hash{},
- FinalizedBlockHash: common.Hash{},
- }
- if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil {
- t.Fatal("Failed to update head")
- }
- headHeader = api.les.BlockChain().CurrentHeader()
- if headHeader.Number.Uint64() != fakeBlock.NumberU64() {
- t.Fatal("Failed to update chain head")
- }
- }
- func TestEth2DeepReorg(t *testing.T) {
- // TODO (MariusVanDerWijden) TestEth2DeepReorg is currently broken, because it tries to reorg
- // before the totalTerminalDifficulty threshold
- /*
- genesis, preMergeBlocks := generatePreMergeChain(core.TriesInMemory * 2)
- n, ethservice := startEthService(t, genesis, preMergeBlocks)
- defer n.Close()
- var (
- api = NewConsensusAPI(ethservice, nil)
- parent = preMergeBlocks[len(preMergeBlocks)-core.TriesInMemory-1]
- head = ethservice.BlockChain().CurrentBlock().NumberU64()
- )
- if ethservice.BlockChain().HasBlockAndState(parent.Hash(), parent.NumberU64()) {
- t.Errorf("Block %d not pruned", parent.NumberU64())
- }
- for i := 0; i < 10; i++ {
- execData, err := api.assembleBlock(AssembleBlockParams{
- ParentHash: parent.Hash(),
- Timestamp: parent.Time() + 5,
- })
- if err != nil {
- t.Fatalf("Failed to create the executable data %v", err)
- }
- block, err := ExecutableDataToBlock(ethservice.BlockChain().Config(), parent.Header(), *execData)
- if err != nil {
- t.Fatalf("Failed to convert executable data to block %v", err)
- }
- newResp, err := api.ExecutePayload(*execData)
- if err != nil || newResp.Status != "VALID" {
- t.Fatalf("Failed to insert block: %v", err)
- }
- if ethservice.BlockChain().CurrentBlock().NumberU64() != head {
- t.Fatalf("Chain head shouldn't be updated")
- }
- if err := api.setCanonical(block.Hash()); err != nil {
- t.Fatalf("Failed to set head: %v", err)
- }
- if ethservice.BlockChain().CurrentBlock().NumberU64() != block.NumberU64() {
- t.Fatalf("Chain head should be updated")
- }
- parent, head = block, block.NumberU64()
- }
- */
- }
- // startEthService creates a full node instance for testing.
- func startLesService(t *testing.T, genesis *core.Genesis, headers []*types.Header) (*node.Node, *les.LightEthereum) {
- t.Helper()
- n, err := node.New(&node.Config{})
- if err != nil {
- t.Fatal("can't create node:", err)
- }
- ethcfg := ðconfig.Config{
- Genesis: genesis,
- Ethash: ethash.Config{PowMode: ethash.ModeFake},
- SyncMode: downloader.LightSync,
- TrieDirtyCache: 256,
- TrieCleanCache: 256,
- LightPeers: 10,
- }
- lesService, err := les.New(n, ethcfg)
- if err != nil {
- t.Fatal("can't create eth service:", err)
- }
- if err := n.Start(); err != nil {
- t.Fatal("can't start node:", err)
- }
- if _, err := lesService.BlockChain().InsertHeaderChain(headers, 0); err != nil {
- n.Close()
- t.Fatal("can't import test headers:", err)
- }
- return n, lesService
- }
- func encodeTransactions(txs []*types.Transaction) [][]byte {
- var enc = make([][]byte, len(txs))
- for i, tx := range txs {
- enc[i], _ = tx.MarshalBinary()
- }
- return enc
- }
|