Skip to content

Commit

Permalink
feat: introduce begin/end block system contract apply
Browse files Browse the repository at this point in the history
  • Loading branch information
MatusKysel committed Dec 4, 2024
1 parent 92d8bb2 commit 2e668c0
Show file tree
Hide file tree
Showing 9 changed files with 66 additions and 41 deletions.
11 changes: 6 additions & 5 deletions cmd/state/exec3/historical_trace_worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@ package exec3
import (
"context"
"fmt"
"github.com/erigontech/erigon/core/systemcontracts"
"sync"
"sync/atomic"
"time"

"github.com/erigontech/erigon/core/systemcontracts"

"golang.org/x/sync/errgroup"

"github.com/erigontech/erigon-lib/chain"
Expand Down Expand Up @@ -169,8 +170,8 @@ func (rw *HistoricalTraceWorker) RunTxTask(txTask *state.TxTask) {
syscall := func(contract common.Address, data []byte, ibs *state.IntraBlockState, header *types.Header, constCall bool) ([]byte, error) {
return core.SysCallContract(contract, data, rw.execArgs.ChainConfig, ibs, header, rw.execArgs.Engine, constCall /* constCall */)
}
if isPoSA && !rw.execArgs.ChainConfig.IsFeynman(header.Number.Uint64(), header.Time) {
systemcontracts.UpgradeBuildInSystemContract(rw.execArgs.ChainConfig, header.Number, lastBlockTime, header.Time, ibs, rw.logger)
if isPoSA {
systemcontracts.BeginBlockUpgradeBuildInSystemContract(rw.execArgs.ChainConfig, header.Number, lastBlockTime, header.Time, ibs, rw.logger)
}
if err := rw.execArgs.Engine.Initialize(rw.execArgs.ChainConfig, rw.chain, header, ibs, syscall, rw.logger, nil); err != nil {
txTask.Error = err
Expand All @@ -184,8 +185,8 @@ func (rw *HistoricalTraceWorker) RunTxTask(txTask *state.TxTask) {

if _, isPoSa := rw.execArgs.Engine.(consensus.PoSA); isPoSa {
// Is an empty block
if rw.execArgs.ChainConfig.IsFeynman(header.Number.Uint64(), header.Time) && txTask.TxIndex == 0 {
systemcontracts.UpgradeBuildInSystemContract(rw.execArgs.ChainConfig, header.Number, lastBlockTime, header.Time, ibs, rw.logger)
if txTask.TxIndex == 0 {
systemcontracts.EndBlockUpgradeBuildInSystemContract(rw.execArgs.ChainConfig, header.Number, lastBlockTime, header.Time, ibs, rw.logger)
}
break
}
Expand Down
11 changes: 6 additions & 5 deletions cmd/state/exec3/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ package exec3

import (
"context"
"github.com/erigontech/erigon/core/systemcontracts"
"sync"

"github.com/erigontech/erigon/core/systemcontracts"

"golang.org/x/sync/errgroup"

"github.com/erigontech/erigon-lib/log/v3"
Expand Down Expand Up @@ -229,8 +230,8 @@ func (rw *Worker) RunTxTaskNoLock(txTask *state.TxTask, isMining bool) {
syscall := func(contract libcommon.Address, data []byte, ibs *state.IntraBlockState, header *types.Header, constCall bool) ([]byte, error) {
return core.SysCallContract(contract, data, rw.chainConfig, ibs, header, rw.engine, constCall /* constCall */)
}
if rw.isPoSA && !rw.chainConfig.IsFeynman(header.Number.Uint64(), header.Time) {
systemcontracts.UpgradeBuildInSystemContract(rw.chainConfig, header.Number, lastBlockTime, header.Time, ibs, rw.logger)
if rw.isPoSA {
systemcontracts.BeginBlockUpgradeBuildInSystemContract(rw.chainConfig, header.Number, lastBlockTime, header.Time, ibs, rw.logger)
}
if err := rw.engine.Initialize(rw.chainConfig, rw.chain, header, ibs, syscall, rw.logger, nil); err != nil {
txTask.Error = err
Expand All @@ -244,8 +245,8 @@ func (rw *Worker) RunTxTaskNoLock(txTask *state.TxTask, isMining bool) {

if _, isPoSa := rw.engine.(consensus.PoSA); isPoSa {
// Is an empty block
if rw.chainConfig.IsFeynman(header.Number.Uint64(), header.Time) && txTask.TxIndex == 0 {
systemcontracts.UpgradeBuildInSystemContract(rw.chainConfig, header.Number, lastBlockTime, header.Time, ibs, rw.logger)
if txTask.TxIndex == 0 {
systemcontracts.EndBlockUpgradeBuildInSystemContract(rw.chainConfig, header.Number, lastBlockTime, header.Time, ibs, rw.logger)
}
break
}
Expand Down
8 changes: 8 additions & 0 deletions consensus/misc/eip2935.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,11 @@ func storeHash(num uint64, hash libcommon.Hash, state *state.IntraBlockState) {
parentHashInt := uint256.NewInt(0).SetBytes32(hash.Bytes())
state.SetState(params.HistoryStorageAddress, &storageSlot, *parentHashInt)
}

func InitializeBlockHashesEip2935(state *state.IntraBlockState) {
if state.GetCodeSize(params.HistoryStorageAddress) != 0 {
return
}
state.SetCode(params.HistoryStorageAddress, params.HistoryStorageCode)
state.SetNonce(params.HistoryStorageAddress, 1)
}
4 changes: 1 addition & 3 deletions consensus/parlia/parlia.go
Original file line number Diff line number Diff line change
Expand Up @@ -977,9 +977,7 @@ func (p *Parlia) finalize(header *types.Header, ibs *state.IntraBlockState, txs
}()

if curIndex == txIndex {
if p.chainConfig.IsFeynman(header.Number.Uint64(), header.Time) {
systemcontracts.UpgradeBuildInSystemContract(p.chainConfig, header.Number, parentHeader.Time, header.Time, ibs, logger)
}
systemcontracts.EndBlockUpgradeBuildInSystemContract(p.chainConfig, header.Number, parentHeader.Time, header.Time, ibs, logger)
}

if p.chainConfig.IsOnFeynman(header.Number, parentHeader.Time, header.Time) {
Expand Down
49 changes: 33 additions & 16 deletions core/systemcontracts/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,11 @@ import (
"github.com/erigontech/erigon-lib/chain"
libcommon "github.com/erigontech/erigon-lib/common"
"github.com/erigontech/erigon-lib/log/v3"
"github.com/erigontech/erigon/consensus/misc"
"github.com/erigontech/erigon/core/state"
"github.com/erigontech/erigon/core/types"
)

type UpgradeConfig struct {
BeforeUpgrade upgradeHook
AfterUpgrade upgradeHook
ContractAddr libcommon.Address
CommitUrl string
Code string
}

type Upgrade struct {
UpgradeName string
Configs []*UpgradeConfig
}

type upgradeHook func(blockNumber *big.Int, contractAddr libcommon.Address, statedb *state.IntraBlockState) error

var (
// SystemContractCodeLookup is used to address a flaw in the upgrade logic of the system contracts. Since they are updated directly, without first being self-destructed
// and then re-created, the usual incarnation logic does not get activated, and all historical records of the code of these contracts are retrieved as the most
Expand All @@ -52,7 +38,15 @@ var (
SystemContractCodeLookup = map[string]map[libcommon.Address][]libcommon.CodeRecord{}
)

func UpgradeBuildInSystemContract(config *chain.Config, blockNumber *big.Int, lastBlockTime uint64, blockTime uint64, state *state.IntraBlockState, logger log.Logger) {
func BeginBlockUpgradeBuildInSystemContract(config *chain.Config, blockNumber *big.Int, lastBlockTime uint64, blockTime uint64, state *state.IntraBlockState, logger log.Logger) {
TryUpgradeBuildInSystemContract(config, blockNumber, lastBlockTime, blockTime, state, logger, false)
}

func EndBlockUpgradeBuildInSystemContract(config *chain.Config, blockNumber *big.Int, lastBlockTime uint64, blockTime uint64, state *state.IntraBlockState, logger log.Logger) {
TryUpgradeBuildInSystemContract(config, blockNumber, lastBlockTime, blockTime, state, logger, true)
}

func TryUpgradeBuildInSystemContract(config *chain.Config, blockNumber *big.Int, lastBlockTime uint64, blockTime uint64, state *state.IntraBlockState, logger log.Logger, endBlock bool) {
if config == nil || blockNumber == nil || state == nil {
return
}
Expand All @@ -61,6 +55,29 @@ func UpgradeBuildInSystemContract(config *chain.Config, blockNumber *big.Int, la
return
}

// Everything after Faynman is initialized in the end block
if endBlock {
if config.IsFeynman(blockNumber.Uint64(), lastBlockTime) {
upgradeBuildInSystemContract(config, blockNumber, lastBlockTime, blockTime, state, logger)
}
return
}

// this will execute in the begin block

// Everything before Feynman is initialized in the begin block
if !config.IsFeynman(blockNumber.Uint64(), lastBlockTime) {
upgradeBuildInSystemContract(config, blockNumber, lastBlockTime, blockTime, state, logger)
}

// HistoryStorageAddress is a special system contract in bsc, which can't be upgraded
if config.IsOnPrague(blockNumber, lastBlockTime, blockTime) {
misc.InitializeBlockHashesEip2935(state)
log.Info("Set code for HistoryStorageAddress", "blockNumber", blockNumber.Int64(), "blockTime", blockTime)
}
}

func upgradeBuildInSystemContract(config *chain.Config, blockNumber *big.Int, lastBlockTime uint64, blockTime uint64, state *state.IntraBlockState, logger log.Logger) {
for blockNumberOrTime, genesisAlloc := range config.Parlia.BlockAlloc {
numOrTime, err := strconv.ParseUint(blockNumberOrTime, 10, 64)
if err != nil {
Expand Down
9 changes: 9 additions & 0 deletions erigon-lib/chain/chain_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,15 @@ func (c *Config) IsPrague(time uint64) bool {
return isForked(c.PragueTime, time)
}

// IsOnPrague returns whether currentBlockTime is either equal to the Prague fork time or greater firstly.
func (c *Config) 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(lastBlockTime) && c.IsPrague(currentBlockTime)
}

// IsOsaka returns whether time is either equal to the Osaka fork time or greater.
func (c *Config) IsOsaka(time uint64) bool {
return isForked(c.OsakaTime, time)
Expand Down
Loading

0 comments on commit 2e668c0

Please sign in to comment.