diff --git a/core/blockchain.go b/core/blockchain.go index e234b5a5ba53..4f12690f4baa 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -244,10 +244,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par engine: engine, vmConfig: vmConfig, } - bc.forker = NewForkChoice(bc, merger.LeftPoW(), shouldPreserve) - merger.SubscribeLeavePoW(func() { - bc.forker.MarkTransitioned() - }) + bc.forker = NewForkChoice(bc, shouldPreserve) bc.validator = NewBlockValidator(chainConfig, bc, engine) bc.prefetcher = newStatePrefetcher(chainConfig, bc, engine) bc.processor = NewStateProcessor(chainConfig, bc, engine) diff --git a/core/blockchain_test.go b/core/blockchain_test.go index f1e130b19ff1..99db78fcf707 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -230,9 +230,6 @@ func testInsertAfterMerge(t *testing.T, blockchain *BlockChain, i, n int, full b t.Errorf("chain content mismatch at %d: have hash %v, want hash %v", i, hash2, hash1) } - // Trigger the transition explicitly - blockchain2.forker.MarkTransitioned() - // Extend the newly created chain if full { blockChainB := makeBlockChain(blockchain2.CurrentBlock(), n, ethash.NewFaker(), db, forkSeed) @@ -1963,7 +1960,6 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon if mergePoint == 0 { genEngine.MarkTransitioned() runEngine.MarkTransitioned() - chain.forker.MarkTransitioned() } blocks, _ := GenerateChain(params.TestChainConfig, genesis, genEngine, db, 2*TriesInMemory, func(i int, gen *BlockGen) { tx, err := types.SignTx(types.NewTransaction(nonce, common.HexToAddress("deadbeef"), big.NewInt(100), 21000, big.NewInt(int64(i+1)*params.GWei), nil), signer, key) @@ -1994,7 +1990,6 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon if mergePoint == 1 { genEngine.MarkTransitioned() runEngine.MarkTransitioned() - chain.forker.MarkTransitioned() } // Generate the sidechain @@ -2218,9 +2213,6 @@ func testInsertKnownChainDataWithMerging(t *testing.T, typ string, mergeHeight i if engine != nil { engine.MarkTransitioned() } - if forker != nil { - forker.MarkTransitioned() - } } // Apply merging since genesis diff --git a/core/forkchoice.go b/core/forkchoice.go index 9bc1f79facef..e3b8e591201f 100644 --- a/core/forkchoice.go +++ b/core/forkchoice.go @@ -27,12 +27,16 @@ import ( "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" ) // ChainReader defines a small collection of methods needed to access the local // blockchain during header verification. It's implemented by both blockchain // and lightchain. type ChainReader interface { + // Config retrieves the header chain's chain configuration. + Config() *params.ChainConfig + // GetTd returns the total difficulty of a local block. GetTd(common.Hash, uint64) *big.Int } @@ -45,12 +49,7 @@ type ChainReader interface { type ForkChoice struct { chain ChainReader rand *mrand.Rand - - // transitioned is the flag whether the chain has started(or finished) - // the transition. It's triggered by receiving the first "NewHead" message - // from the external consensus engine. - transitioned bool - lock sync.RWMutex + lock sync.RWMutex // preserve is a helper function used in td fork choice. // Miners will prefer to choose the local mined block if the @@ -59,17 +58,16 @@ type ForkChoice struct { preserve func(header *types.Header) bool } -func NewForkChoice(chainReader ChainReader, transitioned bool, preserve func(header *types.Header) bool) *ForkChoice { +func NewForkChoice(chainReader ChainReader, preserve func(header *types.Header) bool) *ForkChoice { // Seed a fast but crypto originating random generator seed, err := crand.Int(crand.Reader, big.NewInt(math.MaxInt64)) if err != nil { log.Crit("Failed to initialize random seed", "err", err) } return &ForkChoice{ - chain: chainReader, - rand: mrand.New(mrand.NewSource(seed.Int64())), - transitioned: transitioned, - preserve: preserve, + chain: chainReader, + rand: mrand.New(mrand.NewSource(seed.Int64())), + preserve: preserve, } } @@ -82,12 +80,6 @@ func (f *ForkChoice) Reorg(current *types.Header, header *types.Header) (bool, e f.lock.RLock() defer f.lock.RUnlock() - // Accept the new header as the chain head if the transition - // is already triggered. We assume all the headers after the - // transition come from the trusted consensus layer. - if f.transitioned { - return true, nil - } var ( localTD = f.chain.GetTd(current.Hash(), current.Number.Uint64()) externTd = f.chain.GetTd(header.Hash(), header.Number.Uint64()) @@ -95,6 +87,12 @@ func (f *ForkChoice) Reorg(current *types.Header, header *types.Header) (bool, e if localTD == nil || externTd == nil { return false, errors.New("missing td") } + // Accept the new header as the chain head if the transition + // is already triggered. We assume all the headers after the + // transition come from the trusted consensus layer. + if ttd := f.chain.Config().TerminalTotalDifficulty; ttd != nil && ttd.Cmp(externTd) <= 0 { + return true, nil + } // If the total difficulty is higher than our known, add it to the canonical chain // Second clause in the if statement reduces the vulnerability to selfish mining. // Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf @@ -113,11 +111,3 @@ func (f *ForkChoice) Reorg(current *types.Header, header *types.Header) (bool, e } return reorg, nil } - -// MarkTransitioned marks the transition has started. -func (f *ForkChoice) MarkTransitioned() { - f.lock.Lock() - defer f.lock.Unlock() - - f.transitioned = true -} diff --git a/core/headerchain_test.go b/core/headerchain_test.go index 5371ff98642d..ed0522671fb8 100644 --- a/core/headerchain_test.go +++ b/core/headerchain_test.go @@ -84,7 +84,7 @@ func TestHeaderInsertion(t *testing.T) { chainB := makeHeaderChain(chainA[0], 128, ethash.NewFaker(), db, 10) log.Root().SetHandler(log.StdoutHandler) - forker := NewForkChoice(hc, false, nil) + forker := NewForkChoice(hc, nil) // Inserting 64 headers on an empty chain, expecting // 1 callbacks, 1 canon-status, 0 sidestatus, testInsert(t, hc, chainA[:64], CanonStatTy, nil, forker) diff --git a/eth/catalyst/api.go b/eth/catalyst/api.go index 344acb9eb4b3..77144cb78998 100644 --- a/eth/catalyst/api.go +++ b/eth/catalyst/api.go @@ -231,7 +231,7 @@ func (api *ConsensusAPI) ExecutePayload(params ExecutableData) (GenericStringRes if parent == nil { return INVALID, fmt.Errorf("could not find parent %x", params.ParentHash) } - block, err := ExecutableDataToBlock(api.les.BlockChain().Config(), parent, params) + block, err := ExecutableDataToBlock(params) if err != nil { return INVALID, err } @@ -240,17 +240,7 @@ func (api *ConsensusAPI) ExecutePayload(params ExecutableData) (GenericStringRes } return VALID, nil } - parent := api.eth.BlockChain().GetBlockByHash(params.ParentHash) - if parent == nil { - return INVALID, fmt.Errorf("could not find parent %x", params.ParentHash) - } - - td := api.eth.BlockChain().GetTdByHash(parent.Hash()) - ttd := api.eth.BlockChain().Config().TerminalTotalDifficulty - if td.Cmp(ttd) < 0 { - return INVALID, fmt.Errorf("can not execute payload on top of block with low td got: %v threshold %v", td, ttd) - } - block, err := ExecutableDataToBlock(api.eth.BlockChain().Config(), parent.Header(), params) + block, err := ExecutableDataToBlock(params) if err != nil { return INVALID, err } @@ -260,6 +250,12 @@ func (api *ConsensusAPI) ExecutePayload(params ExecutableData) (GenericStringRes } return SYNCING, nil } + parent := api.eth.BlockChain().GetBlockByHash(params.ParentHash) + td := api.eth.BlockChain().GetTdByHash(parent.Hash()) + ttd := api.eth.BlockChain().Config().TerminalTotalDifficulty + if td.Cmp(ttd) < 0 { + return INVALID, fmt.Errorf("can not execute payload on top of block with low td got: %v threshold %v", td, ttd) + } if err := api.eth.BlockChain().InsertBlock(block); err != nil { return INVALID, err } @@ -392,7 +388,7 @@ func decodeTransactions(enc [][]byte) ([]*types.Transaction, error) { return txs, nil } -func ExecutableDataToBlock(config *chainParams.ChainConfig, parent *types.Header, params ExecutableData) (*types.Block, error) { +func ExecutableDataToBlock(params ExecutableData) (*types.Block, error) { txs, err := decodeTransactions(params.Transactions) if err != nil { return nil, err @@ -419,9 +415,6 @@ func ExecutableDataToBlock(config *chainParams.ChainConfig, parent *types.Header Extra: params.ExtraData, // TODO (MariusVanDerWijden) add params.Random to header once required } - if config.IsLondon(number) { - header.BaseFee = misc.CalcBaseFee(config, parent) - } block := types.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */) if block.Hash() != params.BlockHash { return nil, fmt.Errorf("blockhash mismatch, want %x, got %x", params.BlockHash, block.Hash()) diff --git a/eth/catalyst/api_test.go b/eth/catalyst/api_test.go index 720a678ceac6..50db1a82b940 100644 --- a/eth/catalyst/api_test.go +++ b/eth/catalyst/api_test.go @@ -255,7 +255,7 @@ func TestEth2NewBlock(t *testing.T) { if err != nil { t.Fatalf("Failed to create the executable data %v", err) } - block, err := ExecutableDataToBlock(ethservice.BlockChain().Config(), parent.Header(), *execData) + block, err := ExecutableDataToBlock(*execData) if err != nil { t.Fatalf("Failed to convert executable data to block %v", err) } @@ -292,7 +292,7 @@ func TestEth2NewBlock(t *testing.T) { if err != nil { t.Fatalf("Failed to create the executable data %v", err) } - block, err := ExecutableDataToBlock(ethservice.BlockChain().Config(), parent.Header(), *execData) + block, err := ExecutableDataToBlock(*execData) if err != nil { t.Fatalf("Failed to convert executable data to block %v", err) } diff --git a/light/lightchain.go b/light/lightchain.go index 93d474a967e2..6bb621ff2994 100644 --- a/light/lightchain.go +++ b/light/lightchain.go @@ -93,10 +93,7 @@ func NewLightChain(odr OdrBackend, config *params.ChainConfig, engine consensus. blockCache: blockCache, engine: engine, } - bc.forker = core.NewForkChoice(bc, merger.LeftPoW(), nil) - merger.SubscribeLeavePoW(func() { - bc.forker.MarkTransitioned() - }) + bc.forker = core.NewForkChoice(bc, nil) var err error bc.hc, err = core.NewHeaderChain(odr.Database(), config, bc.engine, bc.getProcInterrupt) if err != nil { diff --git a/miner/stress/beacon/main.go b/miner/stress/beacon/main.go index 46bf6d7e1476..dc5c229410cf 100644 --- a/miner/stress/beacon/main.go +++ b/miner/stress/beacon/main.go @@ -172,13 +172,7 @@ func (n *ethNode) insertBlockAndSetHead(parent *types.Header, ed catalyst.Execut if err := n.insertBlock(ed); err != nil { return err } - var config *params.ChainConfig - if n.typ == eth2LightClient { - config = n.lesBackend.BlockChain().Config() - } else { - config = n.ethBackend.BlockChain().Config() - } - block, err := catalyst.ExecutableDataToBlock(config, parent, ed) + block, err := catalyst.ExecutableDataToBlock(ed) if err != nil { return err } @@ -319,7 +313,7 @@ func (mgr *nodeManager) run() { log.Error("Failed to assemble the block", "err", err) continue } - block, _ := catalyst.ExecutableDataToBlock(chain.Config(), parentBlock.Header(), *ed) + block, _ := catalyst.ExecutableDataToBlock(*ed) nodes := mgr.getNodes(eth2MiningNode) nodes = append(nodes, mgr.getNodes(eth2NormalNode)...)