Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prague & Pascal #524

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
5 changes: 3 additions & 2 deletions consensus/merge/merge.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ import (
"bytes"
"errors"
"fmt"
"math/big"

"github.com/erigontech/erigon-lib/kv"
"github.com/holiman/uint256"
"math/big"

"github.com/erigontech/erigon-lib/chain"
libcommon "github.com/erigontech/erigon-lib/common"
Expand Down Expand Up @@ -353,7 +354,7 @@ func (s *Merge) Initialize(config *chain.Config, chain consensus.ChainHeaderRead
}, tracer)
}
if chain.Config().IsPrague(header.Time) {
misc.StoreBlockHashesEip2935(header, state, config, chain)
misc.StoreBlockHashesEip2935(header, state)
}
return nil
}
Expand Down
12 changes: 9 additions & 3 deletions consensus/misc/eip2935.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,15 @@ package misc
import (
"github.com/holiman/uint256"

"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"
"github.com/erigontech/erigon/core/state"
"github.com/erigontech/erigon/core/types"
"github.com/erigontech/erigon/params"
)

func StoreBlockHashesEip2935(header *types.Header, state *state.IntraBlockState, config *chain.Config, headerReader consensus.ChainHeaderReader) {
func StoreBlockHashesEip2935(header *types.Header, state *state.IntraBlockState) {
if state.GetCodeSize(params.HistoryStorageAddress) == 0 {
log.Debug("[EIP-2935] No code deployed to HistoryStorageAddress before call to store EIP-2935 history")
return
Expand All @@ -47,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)
}
17 changes: 11 additions & 6 deletions consensus/parlia/parlia.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,17 @@ import (
"encoding/hex"
"errors"
"fmt"
"github.com/erigontech/erigon/consensus/parlia/finality"
"github.com/erigontech/erigon/core/tracing"
"github.com/erigontech/erigon/core/vm/evmtypes"
"io"
"math/big"
"sort"
"strings"
"sync"
"time"

"github.com/erigontech/erigon/consensus/parlia/finality"
"github.com/erigontech/erigon/core/tracing"
"github.com/erigontech/erigon/core/vm/evmtypes"

"github.com/erigontech/erigon/crypto/cryptopool"
"github.com/erigontech/erigon/turbo/services"

Expand Down Expand Up @@ -892,6 +893,12 @@ func (p *Parlia) Initialize(config *chain.Config, chain consensus.ChainHeaderRea
if err = p.verifyTurnLength(chain, header, state); err != nil {
return err
}

// store block hashes for EIP-2935 (BEP440) upgrade
if config.IsPrague(header.Time) {
misc.StoreBlockHashesEip2935(header, state)
}

// update validators every day
if p.chainConfig.IsFeynman(header.Number.Uint64(), header.Time) && isBreatheBlock(parentHeader.Time, header.Time) {
// we should avoid update validators in the Feynman upgrade block
Expand Down Expand Up @@ -970,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
4 changes: 3 additions & 1 deletion core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ import (
"cmp"
"encoding/json"
"fmt"
"github.com/erigontech/erigon/core/systemcontracts"

"slices"
"time"

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

"golang.org/x/crypto/sha3"

"github.com/erigontech/erigon-lib/chain"
Expand Down
54 changes: 36 additions & 18 deletions core/systemcontracts/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,17 @@ package systemcontracts

import (
"fmt"
"math/big"
"strconv"

"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"
"math/big"
"strconv"
)

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 @@ -51,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 @@ -60,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
41 changes: 40 additions & 1 deletion core/vm/contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ import (
"crypto/sha256"
"encoding/binary"
"errors"
"github.com/erigontech/erigon-lib/log/v3"
"math/big"

"github.com/erigontech/erigon-lib/log/v3"

"github.com/erigontech/erigon/core/types"
"github.com/erigontech/secp256k1"

Expand Down Expand Up @@ -227,6 +228,37 @@ var PrecompiledContractsPrague = map[libcommon.Address]PrecompiledContract{
libcommon.BytesToAddress([]byte{0x13}): &bls12381MapFp2ToG2{},
}

var PrecompiledContractsPragueForBSC = map[libcommon.Address]PrecompiledContract{
libcommon.BytesToAddress([]byte{0x01}): &ecrecover{},
libcommon.BytesToAddress([]byte{0x02}): &sha256hash{},
libcommon.BytesToAddress([]byte{0x03}): &ripemd160hash{},
libcommon.BytesToAddress([]byte{0x04}): &dataCopy{},
libcommon.BytesToAddress([]byte{0x05}): &bigModExp{eip2565: true},
libcommon.BytesToAddress([]byte{0x06}): &bn256AddIstanbul{},
libcommon.BytesToAddress([]byte{0x07}): &bn256ScalarMulIstanbul{},
libcommon.BytesToAddress([]byte{0x08}): &bn256PairingIstanbul{},
libcommon.BytesToAddress([]byte{0x09}): &blake2F{},
libcommon.BytesToAddress([]byte{0x0a}): &pointEvaluation{},
libcommon.BytesToAddress([]byte{0x0b}): &bls12381G1Add{},
libcommon.BytesToAddress([]byte{0x0c}): &bls12381G1Mul{},
libcommon.BytesToAddress([]byte{0x0d}): &bls12381G1MultiExp{},
libcommon.BytesToAddress([]byte{0x0e}): &bls12381G2Add{},
libcommon.BytesToAddress([]byte{0x0f}): &bls12381G2Mul{},
libcommon.BytesToAddress([]byte{0x10}): &bls12381G2MultiExp{},
libcommon.BytesToAddress([]byte{0x11}): &bls12381Pairing{},
libcommon.BytesToAddress([]byte{0x12}): &bls12381MapFpToG1{},
libcommon.BytesToAddress([]byte{0x13}): &bls12381MapFp2ToG2{},

libcommon.BytesToAddress([]byte{100}): &tmHeaderValidate{},
libcommon.BytesToAddress([]byte{101}): &iavlMerkleProofValidatePlato{},
libcommon.BytesToAddress([]byte{102}): &blsSignatureVerify{},
libcommon.BytesToAddress([]byte{103}): &cometBFTLightBlockValidateHertz{},
libcommon.BytesToAddress([]byte{104}): &verifyDoubleSignEvidence{},
libcommon.BytesToAddress([]byte{105}): &secp256k1SignatureRecover{},

libcommon.BytesToAddress([]byte{0x01, 0x00}): &p256Verify{},
}

// PrecompiledContractsHaber contains the default set of pre-compiled Ethereum
// contracts used in the Haber release.
var PrecompiledContractsHaber = map[libcommon.Address]PrecompiledContract{
Expand Down Expand Up @@ -352,6 +384,7 @@ var (
PrecompiledAddressesMoran []libcommon.Address
PrecompiledAddressesNano []libcommon.Address
PrecompiledAddressesPrague []libcommon.Address
PrecompiledAddressesPragueForBSC []libcommon.Address
PrecompiledAddressesNapoli []libcommon.Address
PrecompiledAddressesCancun []libcommon.Address
PrecompiledAddressesCancunForBSC []libcommon.Address
Expand Down Expand Up @@ -414,12 +447,18 @@ func init() {
for k := range PrecompiledContractsPrague {
PrecompiledAddressesPrague = append(PrecompiledAddressesPrague, k)
}
for k := range PrecompiledContractsPragueForBSC {
PrecompiledAddressesPragueForBSC = append(PrecompiledAddressesPragueForBSC, k)
}
}

// ActivePrecompiles returns the precompiles enabled with the current configuration.
func ActivePrecompiles(rules *chain.Rules) []libcommon.Address {
switch {
case rules.IsPrague:
if rules.IsParlia {
return PrecompiledAddressesPragueForBSC
}
return PrecompiledAddressesPrague
case rules.IsNapoli:
return PrecompiledAddressesNapoli
Expand Down
6 changes: 5 additions & 1 deletion core/vm/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ func (evm *EVM) precompile(addr libcommon.Address) (PrecompiledContract, bool) {
var precompiles map[libcommon.Address]PrecompiledContract
switch {
case evm.chainRules.IsPrague:
precompiles = PrecompiledContractsPrague
if evm.chainRules.IsParlia {
precompiles = PrecompiledContractsPragueForBSC
} else {
precompiles = PrecompiledContractsPrague
}
case evm.chainRules.IsNapoli:
precompiles = PrecompiledContractsNapoli
case evm.chainRules.IsHaber:
Expand Down
Loading