mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-18 01:43: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
|
// is only used for necessary consensus checks. The legacy consensus engine can be any
|
||||||
// engine implements the consensus interface (except the beacon itself).
|
// engine implements the consensus interface (except the beacon itself).
|
||||||
type Beacon struct {
|
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.
|
// 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}
|
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.
|
// Author implements consensus.Engine, returning the verified author of the block.
|
||||||
func (beacon *Beacon) Author(header *types.Header) (common.Address, error) {
|
func (beacon *Beacon) Author(header *types.Header) (common.Address, error) {
|
||||||
if !beacon.IsPoSHeader(header) {
|
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
|
// VerifyHeader checks whether a header conforms to the consensus rules of the
|
||||||
// stock Ethereum consensus engine.
|
// stock Ethereum consensus engine.
|
||||||
func (beacon *Beacon) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header) error {
|
func (beacon *Beacon) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header) error {
|
||||||
// During the live merge transision, the consensus engine used the terminal
|
// During the live merge transition, the consensus engine used the terminal
|
||||||
// total difficulty to detect when PoW (PoA) switched to PoS. Maintainig the
|
// total difficulty to detect when PoW (PoA) switched to PoS. Maintaining the
|
||||||
// total difficulty values however require applying all the blocks from 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
|
// genesis to build up the TD. This stops being a possibility if the tail of
|
||||||
// the chain is pruned already during sync.
|
// 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
|
// 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
|
// 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
|
// 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
|
// point in time finalized a long time ago, there should be no attempt from
|
||||||
// the consensus client to rewrite very old history.
|
// 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.
|
// will be treated legacy PoW headers.
|
||||||
// Note, this function will not verify the header validity but just split them.
|
// 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) {
|
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 (
|
var (
|
||||||
preHeaders = headers
|
preHeaders = headers
|
||||||
postHeaders []*types.Header
|
postHeaders []*types.Header
|
||||||
td = new(big.Int).Set(ptd)
|
|
||||||
tdPassed bool
|
|
||||||
)
|
)
|
||||||
for i, header := range headers {
|
for i, header := range headers {
|
||||||
if tdPassed {
|
if header.Difficulty.Sign() == 0 {
|
||||||
preHeaders = headers[:i]
|
preHeaders = headers[:i]
|
||||||
postHeaders = headers[i:]
|
postHeaders = headers[i:]
|
||||||
break
|
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
|
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
|
// Prepare implements consensus.Engine, initializing the difficulty field of a
|
||||||
// header to conform to the beacon protocol. The changes are done inline.
|
// header to conform to the beacon protocol. The changes are done inline.
|
||||||
func (beacon *Beacon) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error {
|
func (beacon *Beacon) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error {
|
||||||
// Transition isn't triggered yet, use the legacy rules for preparation.
|
// The beacon engine requires access to total difficulties to be able to
|
||||||
reached, err := IsTTDReached(chain, header.ParentHash, header.Number.Uint64()-1)
|
// seal pre-merge and post-merge blocks. With the transition to removing
|
||||||
if err != nil {
|
// old blocks, TDs become unaccessible, thus making TTD based pre-/post-
|
||||||
return err
|
// merge decisions impossible.
|
||||||
}
|
//
|
||||||
if !reached {
|
// 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)
|
return beacon.ethone.Prepare(chain, header)
|
||||||
}
|
}
|
||||||
header.Difficulty = beaconDifficulty
|
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
|
// the difficulty that a new block should have when created at time
|
||||||
// given the parent block's time and difficulty.
|
// given the parent block's time and difficulty.
|
||||||
func (beacon *Beacon) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int {
|
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
|
// The beacon engine requires access to total difficulties to be able to
|
||||||
if reached, _ := IsTTDReached(chain, parent.Hash(), parent.Number.Uint64()); !reached {
|
// 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 beacon.ethone.CalcDifficulty(chain, time, parent)
|
||||||
}
|
}
|
||||||
return beaconDifficulty
|
return beaconDifficulty
|
||||||
|
|
@ -507,14 +510,3 @@ func (beacon *Beacon) SetThreads(threads int) {
|
||||||
th.SetThreads(threads)
|
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 retrieves a block header from the database by its hash.
|
||||||
GetHeaderByHash(hash common.Hash) *types.Header
|
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
|
// 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 {
|
func (cm *chainMaker) GetBlock(hash common.Hash, number uint64) *types.Block {
|
||||||
return cm.blockByNumber(number)
|
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 {
|
if merged {
|
||||||
config.TerminalTotalDifficulty = common.Big0
|
config.TerminalTotalDifficulty = common.Big0
|
||||||
engine = beaconConsensus.NewFaker()
|
engine = beaconConsensus.NewFaker()
|
||||||
|
} else {
|
||||||
|
engine.(*beaconConsensus.Beacon).TestingTTDBlock(uint64(n))
|
||||||
}
|
}
|
||||||
genesis := &core.Genesis{
|
genesis := &core.Genesis{
|
||||||
Config: &config,
|
Config: &config,
|
||||||
|
|
@ -101,7 +103,6 @@ func generateMergeChain(n int, merged bool) (*core.Genesis, []*types.Block) {
|
||||||
}
|
}
|
||||||
config.TerminalTotalDifficulty = totalDifficulty
|
config.TerminalTotalDifficulty = totalDifficulty
|
||||||
}
|
}
|
||||||
|
|
||||||
return genesis, blocks
|
return genesis, blocks
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"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/beacon"
|
||||||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"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.LondonBlock = londonBlock
|
||||||
config.ArrowGlacierBlock = londonBlock
|
config.ArrowGlacierBlock = londonBlock
|
||||||
config.GrayGlacierBlock = 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()
|
td := params.GenesisDifficulty.Uint64()
|
||||||
|
|
||||||
if cancunBlock != nil {
|
if cancunBlock != nil {
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ package eth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"sync"
|
|
||||||
|
|
||||||
mapset "github.com/deckarep/golang-set/v2"
|
mapset "github.com/deckarep/golang-set/v2"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"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
|
resDispatch chan *response // Dispatch channel to fulfil pending requests and untrack them
|
||||||
|
|
||||||
term chan struct{} // Termination channel to stop the broadcasters
|
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
|
// 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) {
|
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())
|
traceOutputPath := filepath.ToSlash(t.TempDir())
|
||||||
traceOutputFilename := path.Join(traceOutputPath, "supply.jsonl")
|
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())
|
receipts := rawdb.ReadReceipts(b.db, hash, header.Number.Uint64(), header.Time, b.chain.Config())
|
||||||
return receipts, nil
|
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 {
|
func (b testBackend) GetEVM(ctx context.Context, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockContext *vm.BlockContext) *vm.EVM {
|
||||||
if vmConfig == nil {
|
if vmConfig == nil {
|
||||||
vmConfig = b.chain.GetVMConfig()
|
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) {
|
func (b *backendMock) GetLogs(ctx context.Context, blockHash common.Hash, number uint64) ([][]*types.Log, error) {
|
||||||
return nil, nil
|
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 {
|
func (b *backendMock) GetEVM(ctx context.Context, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) *vm.EVM {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue