Skip to content

Commit

Permalink
BEP-440: Implement EIP-2935: Serve historical block hashes from state
Browse files Browse the repository at this point in the history
  • Loading branch information
buddh0 committed Nov 29, 2024
1 parent 2ae712b commit 00875f4
Show file tree
Hide file tree
Showing 9 changed files with 76 additions and 63 deletions.
8 changes: 2 additions & 6 deletions consensus/parlia/parlia.go
Original file line number Diff line number Diff line change
Expand Up @@ -1287,9 +1287,7 @@ func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Heade
return errors.New("parent not found")
}

if p.chainConfig.IsFeynman(header.Number, header.Time) {
systemcontracts.UpgradeBuildInSystemContract(p.chainConfig, header.Number, parent.Time, header.Time, state)
}
systemcontracts.ModifyBuildInSystemContract(p.chainConfig, header.Number, parent.Time, header.Time, state, false)

if p.chainConfig.IsOnFeynman(header.Number, parent.Time, header.Time) {
err := p.initializeFeynmanContract(state, header, cx, txs, receipts, systemTxs, usedGas, false)
Expand Down Expand Up @@ -1374,9 +1372,7 @@ func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *
return nil, nil, errors.New("parent not found")
}

if p.chainConfig.IsFeynman(header.Number, header.Time) {
systemcontracts.UpgradeBuildInSystemContract(p.chainConfig, header.Number, parent.Time, header.Time, state)
}
systemcontracts.ModifyBuildInSystemContract(p.chainConfig, header.Number, parent.Time, header.Time, state, false)

if p.chainConfig.IsOnFeynman(header.Number, parent.Time, header.Time) {
err := p.initializeFeynmanContract(state, header, cx, &body.Transactions, &receipts, nil, &header.GasUsed, true)
Expand Down
4 changes: 1 addition & 3 deletions core/chain_makers.go
Original file line number Diff line number Diff line change
Expand Up @@ -363,9 +363,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
misc.ApplyDAOHardFork(statedb)
}

if !config.IsFeynman(b.header.Number, b.header.Time) {
systemcontracts.UpgradeBuildInSystemContract(config, b.header.Number, parent.Time(), b.header.Time, statedb)
}
systemcontracts.ModifyBuildInSystemContract(config, b.header.Number, parent.Time(), b.header.Time, statedb, true)

// Execute any user modifications to the block
if gen != nil {
Expand Down
6 changes: 2 additions & 4 deletions core/state_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,8 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
if lastBlock == nil {
return nil, errors.New("could not get parent block")
}
if !p.config.IsFeynman(block.Number(), block.Time()) {
// Handle upgrade build-in system contract code
systemcontracts.UpgradeBuildInSystemContract(p.config, blockNumber, lastBlock.Time, block.Time(), statedb)
}
// Handle upgrade build-in system contract code
systemcontracts.ModifyBuildInSystemContract(p.config, blockNumber, lastBlock.Time, block.Time(), statedb, true)

var (
context vm.BlockContext
Expand Down
22 changes: 20 additions & 2 deletions core/systemcontracts/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -1050,7 +1050,25 @@ func init() {
}
}

func UpgradeBuildInSystemContract(config *params.ChainConfig, blockNumber *big.Int, lastBlockTime uint64, blockTime uint64, statedb vm.StateDB) {
func ModifyBuildInSystemContract(config *params.ChainConfig, blockNumber *big.Int, lastBlockTime uint64, blockTime uint64, statedb vm.StateDB, atBlockBegin bool) {
if atBlockBegin {
if !config.IsFeynman(blockNumber, lastBlockTime) {
upgradeBuildInSystemContract(config, blockNumber, lastBlockTime, blockTime, statedb)
}
// HistoryStorageAddress is a special system contract in bsc, which can't be upgraded
if config.IsOnPrague(blockNumber, lastBlockTime, blockTime) {
statedb.SetCode(params.HistoryStorageAddress, params.HistoryStorageCode)
statedb.SetNonce(params.HistoryStorageAddress, 1)
log.Info("Set code for HistoryStorageAddress", "blockNumber", blockNumber.Int64(), "blockTime", blockTime)
}
} else {
if config.IsFeynman(blockNumber, lastBlockTime) {
upgradeBuildInSystemContract(config, blockNumber, lastBlockTime, blockTime, statedb)
}
}
}

func upgradeBuildInSystemContract(config *params.ChainConfig, blockNumber *big.Int, lastBlockTime uint64, blockTime uint64, statedb vm.StateDB) {
if config == nil || blockNumber == nil || statedb == nil || reflect.ValueOf(statedb).IsNil() {
return
}
Expand Down Expand Up @@ -1144,7 +1162,7 @@ func UpgradeBuildInSystemContract(config *params.ChainConfig, blockNumber *big.I

func applySystemContractUpgrade(upgrade *Upgrade, blockNumber *big.Int, statedb vm.StateDB, logger log.Logger) {
if upgrade == nil {
logger.Info("Empty upgrade config", "height", blockNumber.String())
logger.Info(fmt.Sprintf("Empty upgrade %s at height %d", upgrade.UpgradeName, blockNumber.Int64()))
return
}

Expand Down
4 changes: 2 additions & 2 deletions core/systemcontracts/upgrade_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func TestUpgradeBuildInSystemContractNilInterface(t *testing.T) {

GenesisHash = params.BSCGenesisHash

UpgradeBuildInSystemContract(config, blockNumber, lastBlockTime, blockTime, statedb)
upgradeBuildInSystemContract(config, blockNumber, lastBlockTime, blockTime, statedb)
}

func TestUpgradeBuildInSystemContractNilValue(t *testing.T) {
Expand All @@ -69,5 +69,5 @@ func TestUpgradeBuildInSystemContractNilValue(t *testing.T) {

GenesisHash = params.BSCGenesisHash

UpgradeBuildInSystemContract(config, blockNumber, lastBlockTime, blockTime, statedb)
upgradeBuildInSystemContract(config, blockNumber, lastBlockTime, blockTime, statedb)
}
9 changes: 3 additions & 6 deletions eth/state_accessor.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,15 +242,14 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block,
return nil, vm.BlockContext{}, nil, nil, err
}
// upgrade build-in system contract before normal txs if Feynman is not enabled
if !eth.blockchain.Config().IsFeynman(block.Number(), block.Time()) {
systemcontracts.UpgradeBuildInSystemContract(eth.blockchain.Config(), block.Number(), parent.Time(), block.Time(), statedb)
}
systemcontracts.ModifyBuildInSystemContract(eth.blockchain.Config(), block.Number(), parent.Time(), block.Time(), statedb, true)
// Insert parent beacon block root in the state as per EIP-4788.
if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
context := core.NewEVMBlockContext(block.Header(), eth.blockchain, nil)
vmenv := vm.NewEVM(context, vm.TxContext{}, statedb, eth.blockchain.Config(), vm.Config{})
core.ProcessBeaconBlockRoot(*beaconRoot, vmenv, statedb)
}

// If prague hardfork, insert parent block hash in the state as per EIP-2935.
if eth.blockchain.Config().IsPrague(block.Number(), block.Time()) {
context := core.NewEVMBlockContext(block.Header(), eth.blockchain, nil)
Expand All @@ -276,9 +275,7 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block,
statedb.AddBalance(block.Header().Coinbase, balance, tracing.BalanceChangeUnspecified)
}

if eth.blockchain.Config().IsFeynman(block.Number(), block.Time()) {
systemcontracts.UpgradeBuildInSystemContract(eth.blockchain.Config(), block.Number(), parent.Time(), block.Time(), statedb)
}
systemcontracts.ModifyBuildInSystemContract(eth.blockchain.Config(), block.Number(), parent.Time(), block.Time(), statedb, false)
beforeSystemTx = false
}
}
Expand Down
64 changes: 29 additions & 35 deletions eth/tracers/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,9 +288,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
task.statedb.AddBalance(blockCtx.Coinbase, balance, tracing.BalanceChangeUnspecified)
}

if api.backend.ChainConfig().IsFeynman(task.block.Number(), task.block.Time()) {
systemcontracts.UpgradeBuildInSystemContract(api.backend.ChainConfig(), task.block.Number(), task.parent.Time(), task.block.Time(), task.statedb)
}
systemcontracts.ModifyBuildInSystemContract(api.backend.ChainConfig(), task.block.Number(), task.parent.Time(), task.block.Time(), task.statedb, false)
beforeSystemTx = false
}
}
Expand Down Expand Up @@ -422,9 +420,19 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
tracker.callReleases()

// upgrade build-in system contract before normal txs if Feynman is not enabled
if !api.backend.ChainConfig().IsFeynman(next.Number(), next.Time()) {
systemcontracts.UpgradeBuildInSystemContract(api.backend.ChainConfig(), next.Number(), block.Time(), next.Time(), statedb)
systemcontracts.ModifyBuildInSystemContract(api.backend.ChainConfig(), next.Number(), block.Time(), next.Time(), statedb, true)

// Insert parent hash in history contract.
if api.backend.ChainConfig().IsPrague(next.Number(), next.Time()) {
context := core.NewEVMBlockContext(next.Header(), api.chainContext(ctx), nil)
vmenv := vm.NewEVM(context, vm.TxContext{}, statedb, api.backend.ChainConfig(), vm.Config{})
core.ProcessParentBlockHash(next.ParentHash(), vmenv, statedb)
}
// Clean out any pending release functions of trace state. Note this
// step must be done after constructing tracing state, because the
// tracing state of block next depends on the parent state and construction
// may fail if we release too early.
tracker.callReleases()

// Send the block over to the concurrent tracers (if not in the fast-forward phase)
txs := next.Transactions()
Expand Down Expand Up @@ -563,9 +571,7 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
defer release()

// upgrade build-in system contract before normal txs if Feynman is not enabled
if !api.backend.ChainConfig().IsFeynman(block.Number(), block.Time()) {
systemcontracts.UpgradeBuildInSystemContract(api.backend.ChainConfig(), block.Number(), parent.Time(), block.Time(), statedb)
}
systemcontracts.ModifyBuildInSystemContract(api.backend.ChainConfig(), block.Number(), parent.Time(), block.Time(), statedb, true)

var (
roots []common.Hash
Expand All @@ -592,16 +598,16 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
vmenv = vm.NewEVM(vmctx, txContext, statedb, chainConfig, vm.Config{})
)

if posa, ok := api.backend.Engine().(consensus.PoSA); ok {
if isSystem, _ := posa.IsSystemTransaction(tx, block.Header()); isSystem {
balance := statedb.GetBalance(consensus.SystemAddress)
if balance.Cmp(common.U2560) > 0 {
statedb.SetBalance(consensus.SystemAddress, uint256.NewInt(0), tracing.BalanceChangeUnspecified)
statedb.AddBalance(vmctx.Coinbase, balance, tracing.BalanceChangeUnspecified)
}
if beforeSystemTx {
if posa, ok := api.backend.Engine().(consensus.PoSA); ok {
if isSystem, _ := posa.IsSystemTransaction(tx, block.Header()); isSystem {
balance := statedb.GetBalance(consensus.SystemAddress)
if balance.Cmp(common.U2560) > 0 {
statedb.SetBalance(consensus.SystemAddress, uint256.NewInt(0), tracing.BalanceChangeUnspecified)
statedb.AddBalance(vmctx.Coinbase, balance, tracing.BalanceChangeUnspecified)
}

if beforeSystemTx && api.backend.ChainConfig().IsFeynman(block.Number(), block.Time()) {
systemcontracts.UpgradeBuildInSystemContract(api.backend.ChainConfig(), block.Number(), parent.Time(), block.Time(), statedb)
systemcontracts.ModifyBuildInSystemContract(api.backend.ChainConfig(), block.Number(), parent.Time(), block.Time(), statedb, false)
beforeSystemTx = false
}
}
Expand Down Expand Up @@ -661,9 +667,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
defer release()

// upgrade build-in system contract before normal txs if Feynman is not enabled
if !api.backend.ChainConfig().IsFeynman(block.Number(), block.Time()) {
systemcontracts.UpgradeBuildInSystemContract(api.backend.ChainConfig(), block.Number(), parent.Time(), block.Time(), statedb)
}
systemcontracts.ModifyBuildInSystemContract(api.backend.ChainConfig(), block.Number(), parent.Time(), block.Time(), statedb, true)

// JS tracers have high overhead. In this case run a parallel
// process that generates states in one thread and traces txes
Expand Down Expand Up @@ -702,9 +706,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
statedb.AddBalance(blockCtx.Coinbase, balance, tracing.BalanceChangeUnspecified)
}

if api.backend.ChainConfig().IsFeynman(block.Number(), block.Time()) {
systemcontracts.UpgradeBuildInSystemContract(api.backend.ChainConfig(), block.Number(), parent.Time(), block.Time(), statedb)
}
systemcontracts.ModifyBuildInSystemContract(api.backend.ChainConfig(), block.Number(), parent.Time(), block.Time(), statedb, false)
beforeSystemTx = false
}
}
Expand Down Expand Up @@ -795,9 +797,7 @@ txloop:
statedb.AddBalance(block.Header().Coinbase, balance, tracing.BalanceChangeUnspecified)
}

if api.backend.ChainConfig().IsFeynman(block.Number(), block.Time()) {
systemcontracts.UpgradeBuildInSystemContract(api.backend.ChainConfig(), block.Number(), parent.Time(), block.Time(), statedb)
}
systemcontracts.ModifyBuildInSystemContract(api.backend.ChainConfig(), block.Number(), parent.Time(), block.Time(), statedb, false)
beforeSystemTx = false
}
}
Expand Down Expand Up @@ -863,9 +863,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
defer release()

// upgrade build-in system contract before normal txs if Feynman is not enabled
if !api.backend.ChainConfig().IsFeynman(block.Number(), block.Time()) {
systemcontracts.UpgradeBuildInSystemContract(api.backend.ChainConfig(), block.Number(), parent.Time(), block.Time(), statedb)
}
systemcontracts.ModifyBuildInSystemContract(api.backend.ChainConfig(), block.Number(), parent.Time(), block.Time(), statedb, true)

// Retrieve the tracing configurations, or use default values
var (
Expand Down Expand Up @@ -915,9 +913,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
statedb.AddBalance(vmctx.Coinbase, balance, tracing.BalanceChangeUnspecified)
}

if api.backend.ChainConfig().IsFeynman(block.Number(), block.Time()) {
systemcontracts.UpgradeBuildInSystemContract(api.backend.ChainConfig(), block.Number(), parent.Time(), block.Time(), statedb)
}
systemcontracts.ModifyBuildInSystemContract(api.backend.ChainConfig(), block.Number(), parent.Time(), block.Time(), statedb, false)
beforeSystemTx = false
}
}
Expand Down Expand Up @@ -1099,9 +1095,7 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
if err != nil {
return nil, err
}
if !api.backend.ChainConfig().IsFeynman(block.Number(), block.Time()) {
systemcontracts.UpgradeBuildInSystemContract(api.backend.ChainConfig(), block.Number(), parent.Time(), block.Time(), statedb)
}
systemcontracts.ModifyBuildInSystemContract(api.backend.ChainConfig(), block.Number(), parent.Time(), block.Time(), statedb, true)
}

vmctx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
Expand Down
11 changes: 7 additions & 4 deletions miner/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -1042,16 +1042,19 @@ func (w *worker) prepareWork(genParams *generateParams, witness bool) (*environm
return nil, err
}

if !w.chainConfig.IsFeynman(header.Number, header.Time) {
// Handle upgrade build-in system contract code
systemcontracts.UpgradeBuildInSystemContract(w.chainConfig, header.Number, parent.Time, header.Time, env.state)
}
// Handle upgrade build-in system contract code
systemcontracts.ModifyBuildInSystemContract(w.chainConfig, header.Number, parent.Time, header.Time, env.state, true)

if header.ParentBeaconRoot != nil {
context := core.NewEVMBlockContext(header, w.chain, nil)
vmenv := vm.NewEVM(context, vm.TxContext{}, env.state, w.chainConfig, vm.Config{})
core.ProcessBeaconBlockRoot(*header.ParentBeaconRoot, vmenv, env.state)
}
if w.chainConfig.IsPrague(header.Number, header.Time) {
context := core.NewEVMBlockContext(header, w.chain, nil)
vmenv := vm.NewEVM(context, vm.TxContext{}, env.state, w.chainConfig, vm.Config{})
core.ProcessParentBlockHash(header.ParentHash, vmenv, env.state)
}

if w.chainConfig.IsPrague(header.Number, header.Time) {
context := core.NewEVMBlockContext(header, w.chain, nil)
Expand Down
11 changes: 10 additions & 1 deletion params/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -1024,7 +1024,16 @@ func (c *ChainConfig) IsPrague(num *big.Int, time uint64) bool {
return c.IsLondon(num) && isTimestampForked(c.PragueTime, time)
}

// IsVerkle returns whether time is either equal to the Verkle fork time or greater.
// IsOnPrague returns whether currentBlockTime is either equal to the Prague fork time or greater firstly.
func (c *ChainConfig) IsOnPrague(currentBlockNumber *big.Int, lastBlockTime uint64, currentBlockTime uint64) bool {
lastBlockNumber := new(big.Int)
if currentBlockNumber.Cmp(big.NewInt(1)) >= 0 {
lastBlockNumber.Sub(currentBlockNumber, big.NewInt(1))
}
return !c.IsPrague(lastBlockNumber, lastBlockTime) && c.IsPrague(currentBlockNumber, currentBlockTime)
}

// IsVerkle returns whether num is either equal to the Verkle fork time or greater.
func (c *ChainConfig) IsVerkle(num *big.Int, time uint64) bool {
return c.IsLondon(num) && isTimestampForked(c.VerkleTime, time)
}
Expand Down

0 comments on commit 00875f4

Please sign in to comment.