mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-17 17:33:47 +00:00
consensus, core, eth, internal: further removal of td
This commit is contained in:
parent
89a5e1a29b
commit
6539c399ae
9 changed files with 42 additions and 64 deletions
|
|
@ -61,7 +61,8 @@ var (
|
|||
// is only used for necessary consensus checks. The legacy consensus engine can be any
|
||||
// engine implements the consensus interface (except the beacon itself).
|
||||
type Beacon struct {
|
||||
ethone consensus.Engine // Original consensus engine used in eth1, e.g. ethash or clique
|
||||
ethone consensus.Engine // Original consensus engine used in eth1, e.g. ethash or clique
|
||||
ttdblock *uint64 // Merge block-number for testchain generation without TTDs
|
||||
}
|
||||
|
||||
// New creates a consensus engine with the given embedded eth1 engine.
|
||||
|
|
@ -72,6 +73,16 @@ func New(ethone consensus.Engine) *Beacon {
|
|||
return &Beacon{ethone: ethone}
|
||||
}
|
||||
|
||||
// TestingTTDBlock is a replacement mechanism for TTD-based pre-/post-merge
|
||||
// splitting. With chain history deletion, TD calculations become impossible.
|
||||
// This is fine for progressing the live chain, but to be able to generate test
|
||||
// chains, we do need a split point. This method supports setting an explicit
|
||||
// block number to use as the splitter *for testing*, instead of having to keep
|
||||
// the notion of TDs in the client just for testing.
|
||||
func (beacon *Beacon) TestingTTDBlock(number uint64) {
|
||||
beacon.ttdblock = &number
|
||||
}
|
||||
|
||||
// Author implements consensus.Engine, returning the verified author of the block.
|
||||
func (beacon *Beacon) Author(header *types.Header) (common.Address, error) {
|
||||
if !beacon.IsPoSHeader(header) {
|
||||
|
|
@ -83,8 +94,8 @@ func (beacon *Beacon) Author(header *types.Header) (common.Address, error) {
|
|||
// VerifyHeader checks whether a header conforms to the consensus rules of the
|
||||
// stock Ethereum consensus engine.
|
||||
func (beacon *Beacon) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header) error {
|
||||
// During the live merge transision, the consensus engine used the terminal
|
||||
// total difficulty to detect when PoW (PoA) switched to PoS. Maintainig the
|
||||
// During the live merge transition, the consensus engine used the terminal
|
||||
// total difficulty to detect when PoW (PoA) switched to PoS. Maintaining the
|
||||
// total difficulty values however require applying all the blocks from the
|
||||
// genesis to build up the TD. This stops being a possibility if the tail of
|
||||
// the chain is pruned already during sync.
|
||||
|
|
@ -92,7 +103,7 @@ func (beacon *Beacon) VerifyHeader(chain consensus.ChainHeaderReader, header *ty
|
|||
// One heuristic that can be used to distinguis pre-merge and post-merge
|
||||
// blocks is whether their *difficulty* is >0 or ==0 respectively. This of
|
||||
// course would mean that we cannot prove anymore for a past chain that it
|
||||
// truly transisioned at the correct TTD, but if we consider that ancient
|
||||
// truly transitioned at the correct TTD, but if we consider that ancient
|
||||
// point in time finalized a long time ago, there should be no attempt from
|
||||
// the consensus client to rewrite very old history.
|
||||
//
|
||||
|
|
@ -130,34 +141,16 @@ func errOut(n int, err error) chan error {
|
|||
// will be treated legacy PoW headers.
|
||||
// Note, this function will not verify the header validity but just split them.
|
||||
func (beacon *Beacon) splitHeaders(chain consensus.ChainHeaderReader, headers []*types.Header) ([]*types.Header, []*types.Header, error) {
|
||||
// TTD is not defined yet, all headers should be in legacy format.
|
||||
ttd := chain.Config().TerminalTotalDifficulty
|
||||
ptd := chain.GetTd(headers[0].ParentHash, headers[0].Number.Uint64()-1)
|
||||
if ptd == nil {
|
||||
return nil, nil, consensus.ErrUnknownAncestor
|
||||
}
|
||||
// The entire header batch already crosses the transition.
|
||||
if ptd.Cmp(ttd) >= 0 {
|
||||
return nil, headers, nil
|
||||
}
|
||||
var (
|
||||
preHeaders = headers
|
||||
postHeaders []*types.Header
|
||||
td = new(big.Int).Set(ptd)
|
||||
tdPassed bool
|
||||
)
|
||||
for i, header := range headers {
|
||||
if tdPassed {
|
||||
if header.Difficulty.Sign() == 0 {
|
||||
preHeaders = headers[:i]
|
||||
postHeaders = headers[i:]
|
||||
break
|
||||
}
|
||||
td = td.Add(td, header.Difficulty)
|
||||
if td.Cmp(ttd) >= 0 {
|
||||
// This is the last PoW header, it still belongs to
|
||||
// the preHeaders, so we cannot split+break yet.
|
||||
tdPassed = true
|
||||
}
|
||||
}
|
||||
return preHeaders, postHeaders, nil
|
||||
}
|
||||
|
|
@ -350,12 +343,15 @@ func (beacon *Beacon) verifyHeaders(chain consensus.ChainHeaderReader, headers [
|
|||
// Prepare implements consensus.Engine, initializing the difficulty field of a
|
||||
// header to conform to the beacon protocol. The changes are done inline.
|
||||
func (beacon *Beacon) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error {
|
||||
// Transition isn't triggered yet, use the legacy rules for preparation.
|
||||
reached, err := IsTTDReached(chain, header.ParentHash, header.Number.Uint64()-1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !reached {
|
||||
// The beacon engine requires access to total difficulties to be able to
|
||||
// seal pre-merge and post-merge blocks. With the transition to removing
|
||||
// old blocks, TDs become unaccessible, thus making TTD based pre-/post-
|
||||
// merge decisions impossible.
|
||||
//
|
||||
// We do not need to seal non-merge blocks anymore live, but we do need
|
||||
// to be able to generate test chains, thus we're reverting to a testing-
|
||||
// settable field to direct that.
|
||||
if beacon.ttdblock != nil && *beacon.ttdblock >= header.Number.Uint64() {
|
||||
return beacon.ethone.Prepare(chain, header)
|
||||
}
|
||||
header.Difficulty = beaconDifficulty
|
||||
|
|
@ -465,8 +461,15 @@ func (beacon *Beacon) SealHash(header *types.Header) common.Hash {
|
|||
// the difficulty that a new block should have when created at time
|
||||
// given the parent block's time and difficulty.
|
||||
func (beacon *Beacon) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int {
|
||||
// Transition isn't triggered yet, use the legacy rules for calculation
|
||||
if reached, _ := IsTTDReached(chain, parent.Hash(), parent.Number.Uint64()); !reached {
|
||||
// The beacon engine requires access to total difficulties to be able to
|
||||
// seal pre-merge and post-merge blocks. With the transition to removing
|
||||
// old blocks, TDs become unaccessible, thus making TTD based pre-/post-
|
||||
// merge decisions impossible.
|
||||
//
|
||||
// We do not need to seal non-merge blocks anymore live, but we do need
|
||||
// to be able to generate test chains, thus we're reverting to a testing-
|
||||
// settable field to direct that.
|
||||
if beacon.ttdblock != nil && *beacon.ttdblock > parent.Number.Uint64() {
|
||||
return beacon.ethone.CalcDifficulty(chain, time, parent)
|
||||
}
|
||||
return beaconDifficulty
|
||||
|
|
@ -507,14 +510,3 @@ func (beacon *Beacon) SetThreads(threads int) {
|
|||
th.SetThreads(threads)
|
||||
}
|
||||
}
|
||||
|
||||
// IsTTDReached checks if the TotalTerminalDifficulty has been surpassed on the `parentHash` block.
|
||||
// It depends on the parentHash already being stored in the database.
|
||||
// If the parentHash is not stored in the database a UnknownAncestor error is returned.
|
||||
func IsTTDReached(chain consensus.ChainHeaderReader, parentHash common.Hash, parentNumber uint64) (bool, error) {
|
||||
td := chain.GetTd(parentHash, parentNumber)
|
||||
if td == nil {
|
||||
return false, consensus.ErrUnknownAncestor
|
||||
}
|
||||
return td.Cmp(chain.Config().TerminalTotalDifficulty) >= 0, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,9 +45,6 @@ type ChainHeaderReader interface {
|
|||
|
||||
// GetHeaderByHash retrieves a block header from the database by its hash.
|
||||
GetHeaderByHash(hash common.Hash) *types.Header
|
||||
|
||||
// GetTd retrieves the total difficulty from the database by hash and number.
|
||||
GetTd(hash common.Hash, number uint64) *big.Int
|
||||
}
|
||||
|
||||
// ChainReader defines a small collection of methods needed to access the local
|
||||
|
|
|
|||
|
|
@ -726,7 +726,3 @@ func (cm *chainMaker) GetHeader(hash common.Hash, number uint64) *types.Header {
|
|||
func (cm *chainMaker) GetBlock(hash common.Hash, number uint64) *types.Block {
|
||||
return cm.blockByNumber(number)
|
||||
}
|
||||
|
||||
func (cm *chainMaker) GetTd(hash common.Hash, number uint64) *big.Int {
|
||||
return nil // not supported
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,6 +66,8 @@ func generateMergeChain(n int, merged bool) (*core.Genesis, []*types.Block) {
|
|||
if merged {
|
||||
config.TerminalTotalDifficulty = common.Big0
|
||||
engine = beaconConsensus.NewFaker()
|
||||
} else {
|
||||
engine.(*beaconConsensus.Beacon).TestingTTDBlock(uint64(n))
|
||||
}
|
||||
genesis := &core.Genesis{
|
||||
Config: &config,
|
||||
|
|
@ -101,7 +103,6 @@ func generateMergeChain(n int, merged bool) (*core.Genesis, []*types.Block) {
|
|||
}
|
||||
config.TerminalTotalDifficulty = totalDifficulty
|
||||
}
|
||||
|
||||
return genesis, blocks
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/consensus"
|
||||
"github.com/ethereum/go-ethereum/consensus/beacon"
|
||||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
|
|
@ -148,7 +147,10 @@ func newTestBackend(t *testing.T, londonBlock *big.Int, cancunBlock *big.Int, pe
|
|||
config.LondonBlock = londonBlock
|
||||
config.ArrowGlacierBlock = londonBlock
|
||||
config.GrayGlacierBlock = londonBlock
|
||||
var engine consensus.Engine = beacon.New(ethash.NewFaker())
|
||||
|
||||
engine := beacon.New(ethash.NewFaker())
|
||||
engine.TestingTTDBlock(testHead + 1)
|
||||
|
||||
td := params.GenesisDifficulty.Uint64()
|
||||
|
||||
if cancunBlock != nil {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ package eth
|
|||
|
||||
import (
|
||||
"math/rand"
|
||||
"sync"
|
||||
|
||||
mapset "github.com/deckarep/golang-set/v2"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
|
|
@ -59,7 +58,6 @@ type Peer struct {
|
|||
resDispatch chan *response // Dispatch channel to fulfil pending requests and untrack them
|
||||
|
||||
term chan struct{} // Termination channel to stop the broadcasters
|
||||
lock sync.RWMutex // Mutex protecting the internal fields
|
||||
}
|
||||
|
||||
// NewPeer creates a wrapper for a network connection and negotiated protocol
|
||||
|
|
|
|||
|
|
@ -544,9 +544,8 @@ func TestSupplySelfdestructItselfAndRevert(t *testing.T) {
|
|||
}
|
||||
|
||||
func testSupplyTracer(t *testing.T, genesis *core.Genesis, gen func(*core.BlockGen)) ([]supplyInfo, *core.BlockChain, error) {
|
||||
var (
|
||||
engine = beacon.New(ethash.NewFaker())
|
||||
)
|
||||
engine := beacon.New(ethash.NewFaker())
|
||||
engine.TestingTTDBlock(1)
|
||||
|
||||
traceOutputPath := filepath.ToSlash(t.TempDir())
|
||||
traceOutputFilename := path.Join(traceOutputPath, "supply.jsonl")
|
||||
|
|
|
|||
|
|
@ -565,12 +565,6 @@ func (b testBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.R
|
|||
receipts := rawdb.ReadReceipts(b.db, hash, header.Number.Uint64(), header.Time, b.chain.Config())
|
||||
return receipts, nil
|
||||
}
|
||||
func (b testBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int {
|
||||
if b.pending != nil && hash == b.pending.Hash() {
|
||||
return nil
|
||||
}
|
||||
return big.NewInt(1)
|
||||
}
|
||||
func (b testBackend) GetEVM(ctx context.Context, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockContext *vm.BlockContext) *vm.EVM {
|
||||
if vmConfig == nil {
|
||||
vmConfig = b.chain.GetVMConfig()
|
||||
|
|
|
|||
|
|
@ -369,7 +369,6 @@ func (b *backendMock) GetReceipts(ctx context.Context, hash common.Hash) (types.
|
|||
func (b *backendMock) GetLogs(ctx context.Context, blockHash common.Hash, number uint64) ([][]*types.Log, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (b *backendMock) GetTd(ctx context.Context, hash common.Hash) *big.Int { return nil }
|
||||
func (b *backendMock) GetEVM(ctx context.Context, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) *vm.EVM {
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue