core, params, beacon/engine: implement EIP 4788 BeaconRoot (#27849)
This change implements "EIP 4788 : Beacon block root in the EVM". It implements version-2 of EPI-4788, main difference being that the contract is an actual contract rather than a precompile, as in #27289.
This commit is contained in:
parent
0b4b299099
commit
b8d38e76ef
@ -226,6 +226,7 @@ func ExecutableDataToBlock(params ExecutableData, versionedHashes []common.Hash)
|
|||||||
WithdrawalsHash: withdrawalsRoot,
|
WithdrawalsHash: withdrawalsRoot,
|
||||||
ExcessBlobGas: params.ExcessBlobGas,
|
ExcessBlobGas: params.ExcessBlobGas,
|
||||||
BlobGasUsed: params.BlobGasUsed,
|
BlobGasUsed: params.BlobGasUsed,
|
||||||
|
// TODO BeaconRoot
|
||||||
}
|
}
|
||||||
block := types.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */).WithWithdrawals(params.Withdrawals)
|
block := types.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */).WithWithdrawals(params.Withdrawals)
|
||||||
if block.Hash() != params.BlockHash {
|
if block.Hash() != params.BlockHash {
|
||||||
@ -255,6 +256,7 @@ func BlockToExecutableData(block *types.Block, fees *big.Int, blobs []kzg4844.Bl
|
|||||||
Withdrawals: block.Withdrawals(),
|
Withdrawals: block.Withdrawals(),
|
||||||
BlobGasUsed: block.BlobGasUsed(),
|
BlobGasUsed: block.BlobGasUsed(),
|
||||||
ExcessBlobGas: block.ExcessBlobGas(),
|
ExcessBlobGas: block.ExcessBlobGas(),
|
||||||
|
// TODO BeaconRoot
|
||||||
}
|
}
|
||||||
blobsBundle := BlobsBundleV1{
|
blobsBundle := BlobsBundleV1{
|
||||||
Commitments: make([]hexutil.Bytes, 0),
|
Commitments: make([]hexutil.Bytes, 0),
|
||||||
|
@ -69,25 +69,26 @@ type ommer struct {
|
|||||||
|
|
||||||
//go:generate go run github.com/fjl/gencodec -type stEnv -field-override stEnvMarshaling -out gen_stenv.go
|
//go:generate go run github.com/fjl/gencodec -type stEnv -field-override stEnvMarshaling -out gen_stenv.go
|
||||||
type stEnv struct {
|
type stEnv struct {
|
||||||
Coinbase common.Address `json:"currentCoinbase" gencodec:"required"`
|
Coinbase common.Address `json:"currentCoinbase" gencodec:"required"`
|
||||||
Difficulty *big.Int `json:"currentDifficulty"`
|
Difficulty *big.Int `json:"currentDifficulty"`
|
||||||
Random *big.Int `json:"currentRandom"`
|
Random *big.Int `json:"currentRandom"`
|
||||||
ParentDifficulty *big.Int `json:"parentDifficulty"`
|
ParentDifficulty *big.Int `json:"parentDifficulty"`
|
||||||
ParentBaseFee *big.Int `json:"parentBaseFee,omitempty"`
|
ParentBaseFee *big.Int `json:"parentBaseFee,omitempty"`
|
||||||
ParentGasUsed uint64 `json:"parentGasUsed,omitempty"`
|
ParentGasUsed uint64 `json:"parentGasUsed,omitempty"`
|
||||||
ParentGasLimit uint64 `json:"parentGasLimit,omitempty"`
|
ParentGasLimit uint64 `json:"parentGasLimit,omitempty"`
|
||||||
GasLimit uint64 `json:"currentGasLimit" gencodec:"required"`
|
GasLimit uint64 `json:"currentGasLimit" gencodec:"required"`
|
||||||
Number uint64 `json:"currentNumber" gencodec:"required"`
|
Number uint64 `json:"currentNumber" gencodec:"required"`
|
||||||
Timestamp uint64 `json:"currentTimestamp" gencodec:"required"`
|
Timestamp uint64 `json:"currentTimestamp" gencodec:"required"`
|
||||||
ParentTimestamp uint64 `json:"parentTimestamp,omitempty"`
|
ParentTimestamp uint64 `json:"parentTimestamp,omitempty"`
|
||||||
BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"`
|
BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"`
|
||||||
Ommers []ommer `json:"ommers,omitempty"`
|
Ommers []ommer `json:"ommers,omitempty"`
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"`
|
||||||
BaseFee *big.Int `json:"currentBaseFee,omitempty"`
|
BaseFee *big.Int `json:"currentBaseFee,omitempty"`
|
||||||
ParentUncleHash common.Hash `json:"parentUncleHash"`
|
ParentUncleHash common.Hash `json:"parentUncleHash"`
|
||||||
ExcessBlobGas *uint64 `json:"excessBlobGas,omitempty"`
|
ExcessBlobGas *uint64 `json:"excessBlobGas,omitempty"`
|
||||||
ParentExcessBlobGas *uint64 `json:"parentExcessBlobGas,omitempty"`
|
ParentExcessBlobGas *uint64 `json:"parentExcessBlobGas,omitempty"`
|
||||||
ParentBlobGasUsed *uint64 `json:"parentBlobGasUsed,omitempty"`
|
ParentBlobGasUsed *uint64 `json:"parentBlobGasUsed,omitempty"`
|
||||||
|
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type stEnvMarshaling struct {
|
type stEnvMarshaling struct {
|
||||||
@ -182,6 +183,10 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
|||||||
chainConfig.DAOForkBlock.Cmp(new(big.Int).SetUint64(pre.Env.Number)) == 0 {
|
chainConfig.DAOForkBlock.Cmp(new(big.Int).SetUint64(pre.Env.Number)) == 0 {
|
||||||
misc.ApplyDAOHardFork(statedb)
|
misc.ApplyDAOHardFork(statedb)
|
||||||
}
|
}
|
||||||
|
if beaconRoot := pre.Env.ParentBeaconBlockRoot; beaconRoot != nil {
|
||||||
|
evm := vm.NewEVM(vmContext, vm.TxContext{}, statedb, chainConfig, vmConfig)
|
||||||
|
core.ProcessBeaconBlockRoot(*beaconRoot, evm, statedb)
|
||||||
|
}
|
||||||
var blobGasUsed uint64
|
var blobGasUsed uint64
|
||||||
for i, tx := range txs {
|
for i, tx := range txs {
|
||||||
if tx.Type() == types.BlobTxType && vmContext.ExcessBlobGas == nil {
|
if tx.Type() == types.BlobTxType && vmContext.ExcessBlobGas == nil {
|
||||||
|
@ -17,25 +17,26 @@ var _ = (*stEnvMarshaling)(nil)
|
|||||||
// MarshalJSON marshals as JSON.
|
// MarshalJSON marshals as JSON.
|
||||||
func (s stEnv) MarshalJSON() ([]byte, error) {
|
func (s stEnv) MarshalJSON() ([]byte, error) {
|
||||||
type stEnv struct {
|
type stEnv struct {
|
||||||
Coinbase common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
|
Coinbase common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
|
||||||
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty"`
|
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty"`
|
||||||
Random *math.HexOrDecimal256 `json:"currentRandom"`
|
Random *math.HexOrDecimal256 `json:"currentRandom"`
|
||||||
ParentDifficulty *math.HexOrDecimal256 `json:"parentDifficulty"`
|
ParentDifficulty *math.HexOrDecimal256 `json:"parentDifficulty"`
|
||||||
ParentBaseFee *math.HexOrDecimal256 `json:"parentBaseFee,omitempty"`
|
ParentBaseFee *math.HexOrDecimal256 `json:"parentBaseFee,omitempty"`
|
||||||
ParentGasUsed math.HexOrDecimal64 `json:"parentGasUsed,omitempty"`
|
ParentGasUsed math.HexOrDecimal64 `json:"parentGasUsed,omitempty"`
|
||||||
ParentGasLimit math.HexOrDecimal64 `json:"parentGasLimit,omitempty"`
|
ParentGasLimit math.HexOrDecimal64 `json:"parentGasLimit,omitempty"`
|
||||||
GasLimit math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
|
GasLimit math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
|
||||||
Number math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
|
Number math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
|
||||||
Timestamp math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
|
Timestamp math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
|
||||||
ParentTimestamp math.HexOrDecimal64 `json:"parentTimestamp,omitempty"`
|
ParentTimestamp math.HexOrDecimal64 `json:"parentTimestamp,omitempty"`
|
||||||
BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"`
|
BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"`
|
||||||
Ommers []ommer `json:"ommers,omitempty"`
|
Ommers []ommer `json:"ommers,omitempty"`
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"`
|
||||||
BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"`
|
BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"`
|
||||||
ParentUncleHash common.Hash `json:"parentUncleHash"`
|
ParentUncleHash common.Hash `json:"parentUncleHash"`
|
||||||
ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas,omitempty"`
|
ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas,omitempty"`
|
||||||
ParentExcessBlobGas *math.HexOrDecimal64 `json:"parentExcessBlobGas,omitempty"`
|
ParentExcessBlobGas *math.HexOrDecimal64 `json:"parentExcessBlobGas,omitempty"`
|
||||||
ParentBlobGasUsed *math.HexOrDecimal64 `json:"parentBlobGasUsed,omitempty"`
|
ParentBlobGasUsed *math.HexOrDecimal64 `json:"parentBlobGasUsed,omitempty"`
|
||||||
|
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
||||||
}
|
}
|
||||||
var enc stEnv
|
var enc stEnv
|
||||||
enc.Coinbase = common.UnprefixedAddress(s.Coinbase)
|
enc.Coinbase = common.UnprefixedAddress(s.Coinbase)
|
||||||
@ -57,31 +58,33 @@ func (s stEnv) MarshalJSON() ([]byte, error) {
|
|||||||
enc.ExcessBlobGas = (*math.HexOrDecimal64)(s.ExcessBlobGas)
|
enc.ExcessBlobGas = (*math.HexOrDecimal64)(s.ExcessBlobGas)
|
||||||
enc.ParentExcessBlobGas = (*math.HexOrDecimal64)(s.ParentExcessBlobGas)
|
enc.ParentExcessBlobGas = (*math.HexOrDecimal64)(s.ParentExcessBlobGas)
|
||||||
enc.ParentBlobGasUsed = (*math.HexOrDecimal64)(s.ParentBlobGasUsed)
|
enc.ParentBlobGasUsed = (*math.HexOrDecimal64)(s.ParentBlobGasUsed)
|
||||||
|
enc.ParentBeaconBlockRoot = s.ParentBeaconBlockRoot
|
||||||
return json.Marshal(&enc)
|
return json.Marshal(&enc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON unmarshals from JSON.
|
// UnmarshalJSON unmarshals from JSON.
|
||||||
func (s *stEnv) UnmarshalJSON(input []byte) error {
|
func (s *stEnv) UnmarshalJSON(input []byte) error {
|
||||||
type stEnv struct {
|
type stEnv struct {
|
||||||
Coinbase *common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
|
Coinbase *common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
|
||||||
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty"`
|
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty"`
|
||||||
Random *math.HexOrDecimal256 `json:"currentRandom"`
|
Random *math.HexOrDecimal256 `json:"currentRandom"`
|
||||||
ParentDifficulty *math.HexOrDecimal256 `json:"parentDifficulty"`
|
ParentDifficulty *math.HexOrDecimal256 `json:"parentDifficulty"`
|
||||||
ParentBaseFee *math.HexOrDecimal256 `json:"parentBaseFee,omitempty"`
|
ParentBaseFee *math.HexOrDecimal256 `json:"parentBaseFee,omitempty"`
|
||||||
ParentGasUsed *math.HexOrDecimal64 `json:"parentGasUsed,omitempty"`
|
ParentGasUsed *math.HexOrDecimal64 `json:"parentGasUsed,omitempty"`
|
||||||
ParentGasLimit *math.HexOrDecimal64 `json:"parentGasLimit,omitempty"`
|
ParentGasLimit *math.HexOrDecimal64 `json:"parentGasLimit,omitempty"`
|
||||||
GasLimit *math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
|
GasLimit *math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
|
||||||
Number *math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
|
Number *math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
|
||||||
Timestamp *math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
|
Timestamp *math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
|
||||||
ParentTimestamp *math.HexOrDecimal64 `json:"parentTimestamp,omitempty"`
|
ParentTimestamp *math.HexOrDecimal64 `json:"parentTimestamp,omitempty"`
|
||||||
BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"`
|
BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"`
|
||||||
Ommers []ommer `json:"ommers,omitempty"`
|
Ommers []ommer `json:"ommers,omitempty"`
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"`
|
||||||
BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"`
|
BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"`
|
||||||
ParentUncleHash *common.Hash `json:"parentUncleHash"`
|
ParentUncleHash *common.Hash `json:"parentUncleHash"`
|
||||||
ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas,omitempty"`
|
ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas,omitempty"`
|
||||||
ParentExcessBlobGas *math.HexOrDecimal64 `json:"parentExcessBlobGas,omitempty"`
|
ParentExcessBlobGas *math.HexOrDecimal64 `json:"parentExcessBlobGas,omitempty"`
|
||||||
ParentBlobGasUsed *math.HexOrDecimal64 `json:"parentBlobGasUsed,omitempty"`
|
ParentBlobGasUsed *math.HexOrDecimal64 `json:"parentBlobGasUsed,omitempty"`
|
||||||
|
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
||||||
}
|
}
|
||||||
var dec stEnv
|
var dec stEnv
|
||||||
if err := json.Unmarshal(input, &dec); err != nil {
|
if err := json.Unmarshal(input, &dec); err != nil {
|
||||||
@ -148,5 +151,8 @@ func (s *stEnv) UnmarshalJSON(input []byte) error {
|
|||||||
if dec.ParentBlobGasUsed != nil {
|
if dec.ParentBlobGasUsed != nil {
|
||||||
s.ParentBlobGasUsed = (*uint64)(dec.ParentBlobGasUsed)
|
s.ParentBlobGasUsed = (*uint64)(dec.ParentBlobGasUsed)
|
||||||
}
|
}
|
||||||
|
if dec.ParentBeaconBlockRoot != nil {
|
||||||
|
s.ParentBeaconBlockRoot = dec.ParentBeaconBlockRoot
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -192,105 +192,20 @@ func Transition(ctx *cli.Context) error {
|
|||||||
// Set the chain id
|
// Set the chain id
|
||||||
chainConfig.ChainID = big.NewInt(ctx.Int64(ChainIDFlag.Name))
|
chainConfig.ChainID = big.NewInt(ctx.Int64(ChainIDFlag.Name))
|
||||||
|
|
||||||
var txsWithKeys []*txWithKey
|
if txs, err = loadTransactions(txStr, inputData, prestate.Env, chainConfig); err != nil {
|
||||||
if txStr != stdinSelector {
|
return err
|
||||||
inFile, err := os.Open(txStr)
|
|
||||||
if err != nil {
|
|
||||||
return NewError(ErrorIO, fmt.Errorf("failed reading txs file: %v", err))
|
|
||||||
}
|
|
||||||
defer inFile.Close()
|
|
||||||
decoder := json.NewDecoder(inFile)
|
|
||||||
if strings.HasSuffix(txStr, ".rlp") {
|
|
||||||
var body hexutil.Bytes
|
|
||||||
if err := decoder.Decode(&body); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
var txs types.Transactions
|
|
||||||
if err := rlp.DecodeBytes(body, &txs); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, tx := range txs {
|
|
||||||
txsWithKeys = append(txsWithKeys, &txWithKey{
|
|
||||||
key: nil,
|
|
||||||
tx: tx,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if err := decoder.Decode(&txsWithKeys); err != nil {
|
|
||||||
return NewError(ErrorJson, fmt.Errorf("failed unmarshaling txs-file: %v", err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if len(inputData.TxRlp) > 0 {
|
|
||||||
// Decode the body of already signed transactions
|
|
||||||
body := common.FromHex(inputData.TxRlp)
|
|
||||||
var txs types.Transactions
|
|
||||||
if err := rlp.DecodeBytes(body, &txs); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, tx := range txs {
|
|
||||||
txsWithKeys = append(txsWithKeys, &txWithKey{
|
|
||||||
key: nil,
|
|
||||||
tx: tx,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// JSON encoded transactions
|
|
||||||
txsWithKeys = inputData.Txs
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// We may have to sign the transactions.
|
if err := applyLondonChecks(&prestate.Env, chainConfig); err != nil {
|
||||||
signer := types.MakeSigner(chainConfig, big.NewInt(int64(prestate.Env.Number)), prestate.Env.Timestamp)
|
return err
|
||||||
|
|
||||||
if txs, err = signUnsignedTransactions(txsWithKeys, signer); err != nil {
|
|
||||||
return NewError(ErrorJson, fmt.Errorf("failed signing transactions: %v", err))
|
|
||||||
}
|
}
|
||||||
// Sanity check, to not `panic` in state_transition
|
if err := applyShanghaiChecks(&prestate.Env, chainConfig); err != nil {
|
||||||
if chainConfig.IsLondon(big.NewInt(int64(prestate.Env.Number))) {
|
return err
|
||||||
if prestate.Env.BaseFee != nil {
|
|
||||||
// Already set, base fee has precedent over parent base fee.
|
|
||||||
} else if prestate.Env.ParentBaseFee != nil && prestate.Env.Number != 0 {
|
|
||||||
parent := &types.Header{
|
|
||||||
Number: new(big.Int).SetUint64(prestate.Env.Number - 1),
|
|
||||||
BaseFee: prestate.Env.ParentBaseFee,
|
|
||||||
GasUsed: prestate.Env.ParentGasUsed,
|
|
||||||
GasLimit: prestate.Env.ParentGasLimit,
|
|
||||||
}
|
|
||||||
prestate.Env.BaseFee = eip1559.CalcBaseFee(chainConfig, parent)
|
|
||||||
} else {
|
|
||||||
return NewError(ErrorConfig, errors.New("EIP-1559 config but missing 'currentBaseFee' in env section"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if chainConfig.IsShanghai(big.NewInt(int64(prestate.Env.Number)), prestate.Env.Timestamp) && prestate.Env.Withdrawals == nil {
|
if err := applyMergeChecks(&prestate.Env, chainConfig); err != nil {
|
||||||
return NewError(ErrorConfig, errors.New("Shanghai config but missing 'withdrawals' in env section"))
|
return err
|
||||||
}
|
}
|
||||||
isMerged := chainConfig.TerminalTotalDifficulty != nil && chainConfig.TerminalTotalDifficulty.BitLen() == 0
|
if err := applyCancunChecks(&prestate.Env, chainConfig); err != nil {
|
||||||
env := prestate.Env
|
return err
|
||||||
if isMerged {
|
|
||||||
// post-merge:
|
|
||||||
// - random must be supplied
|
|
||||||
// - difficulty must be zero
|
|
||||||
switch {
|
|
||||||
case env.Random == nil:
|
|
||||||
return NewError(ErrorConfig, errors.New("post-merge requires currentRandom to be defined in env"))
|
|
||||||
case env.Difficulty != nil && env.Difficulty.BitLen() != 0:
|
|
||||||
return NewError(ErrorConfig, errors.New("post-merge difficulty must be zero (or omitted) in env"))
|
|
||||||
}
|
|
||||||
prestate.Env.Difficulty = nil
|
|
||||||
} else if env.Difficulty == nil {
|
|
||||||
// pre-merge:
|
|
||||||
// If difficulty was not provided by caller, we need to calculate it.
|
|
||||||
switch {
|
|
||||||
case env.ParentDifficulty == nil:
|
|
||||||
return NewError(ErrorConfig, errors.New("currentDifficulty was not provided, and cannot be calculated due to missing parentDifficulty"))
|
|
||||||
case env.Number == 0:
|
|
||||||
return NewError(ErrorConfig, errors.New("currentDifficulty needs to be provided for block number 0"))
|
|
||||||
case env.Timestamp <= env.ParentTimestamp:
|
|
||||||
return NewError(ErrorConfig, fmt.Errorf("currentDifficulty cannot be calculated -- currentTime (%d) needs to be after parent time (%d)",
|
|
||||||
env.Timestamp, env.ParentTimestamp))
|
|
||||||
}
|
|
||||||
prestate.Env.Difficulty = calcDifficulty(chainConfig, env.Number, env.Timestamp,
|
|
||||||
env.ParentTimestamp, env.ParentDifficulty, env.ParentUncleHash)
|
|
||||||
}
|
}
|
||||||
// Run the test and aggregate the result
|
// Run the test and aggregate the result
|
||||||
s, result, err := prestate.Apply(vmConfig, chainConfig, txs, ctx.Int64(RewardFlag.Name), getTracer)
|
s, result, err := prestate.Apply(vmConfig, chainConfig, txs, ctx.Int64(RewardFlag.Name), getTracer)
|
||||||
@ -358,33 +273,149 @@ func (t *txWithKey) UnmarshalJSON(input []byte) error {
|
|||||||
// and secondly to read them with the standard tx json format
|
// and secondly to read them with the standard tx json format
|
||||||
func signUnsignedTransactions(txs []*txWithKey, signer types.Signer) (types.Transactions, error) {
|
func signUnsignedTransactions(txs []*txWithKey, signer types.Signer) (types.Transactions, error) {
|
||||||
var signedTxs []*types.Transaction
|
var signedTxs []*types.Transaction
|
||||||
for i, txWithKey := range txs {
|
for i, tx := range txs {
|
||||||
tx := txWithKey.tx
|
var (
|
||||||
key := txWithKey.key
|
v, r, s = tx.tx.RawSignatureValues()
|
||||||
v, r, s := tx.RawSignatureValues()
|
signed *types.Transaction
|
||||||
if key != nil && v.BitLen()+r.BitLen()+s.BitLen() == 0 {
|
err error
|
||||||
// This transaction needs to be signed
|
)
|
||||||
var (
|
if tx.key == nil || v.BitLen()+r.BitLen()+s.BitLen() != 0 {
|
||||||
signed *types.Transaction
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
if txWithKey.protected {
|
|
||||||
signed, err = types.SignTx(tx, signer, key)
|
|
||||||
} else {
|
|
||||||
signed, err = types.SignTx(tx, types.FrontierSigner{}, key)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, NewError(ErrorJson, fmt.Errorf("tx %d: failed to sign tx: %v", i, err))
|
|
||||||
}
|
|
||||||
signedTxs = append(signedTxs, signed)
|
|
||||||
} else {
|
|
||||||
// Already signed
|
// Already signed
|
||||||
signedTxs = append(signedTxs, tx)
|
signedTxs = append(signedTxs, tx.tx)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
// This transaction needs to be signed
|
||||||
|
if tx.protected {
|
||||||
|
signed, err = types.SignTx(tx.tx, signer, tx.key)
|
||||||
|
} else {
|
||||||
|
signed, err = types.SignTx(tx.tx, types.FrontierSigner{}, tx.key)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, NewError(ErrorJson, fmt.Errorf("tx %d: failed to sign tx: %v", i, err))
|
||||||
|
}
|
||||||
|
signedTxs = append(signedTxs, signed)
|
||||||
}
|
}
|
||||||
return signedTxs, nil
|
return signedTxs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func loadTransactions(txStr string, inputData *input, env stEnv, chainConfig *params.ChainConfig) (types.Transactions, error) {
|
||||||
|
var txsWithKeys []*txWithKey
|
||||||
|
var signed types.Transactions
|
||||||
|
if txStr != stdinSelector {
|
||||||
|
data, err := os.ReadFile(txStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, NewError(ErrorIO, fmt.Errorf("failed reading txs file: %v", err))
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(txStr, ".rlp") { // A file containing an rlp list
|
||||||
|
var body hexutil.Bytes
|
||||||
|
if err := json.Unmarshal(data, &body); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Already signed transactions
|
||||||
|
if err := rlp.DecodeBytes(body, &signed); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return signed, nil
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(data, &txsWithKeys); err != nil {
|
||||||
|
return nil, NewError(ErrorJson, fmt.Errorf("failed unmarshaling txs-file: %v", err))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if len(inputData.TxRlp) > 0 {
|
||||||
|
// Decode the body of already signed transactions
|
||||||
|
body := common.FromHex(inputData.TxRlp)
|
||||||
|
// Already signed transactions
|
||||||
|
if err := rlp.DecodeBytes(body, &signed); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return signed, nil
|
||||||
|
}
|
||||||
|
// JSON encoded transactions
|
||||||
|
txsWithKeys = inputData.Txs
|
||||||
|
}
|
||||||
|
// We may have to sign the transactions.
|
||||||
|
signer := types.MakeSigner(chainConfig, big.NewInt(int64(env.Number)), env.Timestamp)
|
||||||
|
return signUnsignedTransactions(txsWithKeys, signer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func applyLondonChecks(env *stEnv, chainConfig *params.ChainConfig) error {
|
||||||
|
if !chainConfig.IsLondon(big.NewInt(int64(env.Number))) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// Sanity check, to not `panic` in state_transition
|
||||||
|
if env.BaseFee != nil {
|
||||||
|
// Already set, base fee has precedent over parent base fee.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if env.ParentBaseFee == nil || env.Number == 0 {
|
||||||
|
return NewError(ErrorConfig, errors.New("EIP-1559 config but missing 'currentBaseFee' in env section"))
|
||||||
|
}
|
||||||
|
env.BaseFee = eip1559.CalcBaseFee(chainConfig, &types.Header{
|
||||||
|
Number: new(big.Int).SetUint64(env.Number - 1),
|
||||||
|
BaseFee: env.ParentBaseFee,
|
||||||
|
GasUsed: env.ParentGasUsed,
|
||||||
|
GasLimit: env.ParentGasLimit,
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func applyShanghaiChecks(env *stEnv, chainConfig *params.ChainConfig) error {
|
||||||
|
if !chainConfig.IsShanghai(big.NewInt(int64(env.Number)), env.Timestamp) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if env.Withdrawals == nil {
|
||||||
|
return NewError(ErrorConfig, errors.New("Shanghai config but missing 'withdrawals' in env section"))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func applyMergeChecks(env *stEnv, chainConfig *params.ChainConfig) error {
|
||||||
|
isMerged := chainConfig.TerminalTotalDifficulty != nil && chainConfig.TerminalTotalDifficulty.BitLen() == 0
|
||||||
|
if !isMerged {
|
||||||
|
// pre-merge: If difficulty was not provided by caller, we need to calculate it.
|
||||||
|
if env.Difficulty != nil {
|
||||||
|
// already set
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case env.ParentDifficulty == nil:
|
||||||
|
return NewError(ErrorConfig, errors.New("currentDifficulty was not provided, and cannot be calculated due to missing parentDifficulty"))
|
||||||
|
case env.Number == 0:
|
||||||
|
return NewError(ErrorConfig, errors.New("currentDifficulty needs to be provided for block number 0"))
|
||||||
|
case env.Timestamp <= env.ParentTimestamp:
|
||||||
|
return NewError(ErrorConfig, fmt.Errorf("currentDifficulty cannot be calculated -- currentTime (%d) needs to be after parent time (%d)",
|
||||||
|
env.Timestamp, env.ParentTimestamp))
|
||||||
|
}
|
||||||
|
env.Difficulty = calcDifficulty(chainConfig, env.Number, env.Timestamp,
|
||||||
|
env.ParentTimestamp, env.ParentDifficulty, env.ParentUncleHash)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// post-merge:
|
||||||
|
// - random must be supplied
|
||||||
|
// - difficulty must be zero
|
||||||
|
switch {
|
||||||
|
case env.Random == nil:
|
||||||
|
return NewError(ErrorConfig, errors.New("post-merge requires currentRandom to be defined in env"))
|
||||||
|
case env.Difficulty != nil && env.Difficulty.BitLen() != 0:
|
||||||
|
return NewError(ErrorConfig, errors.New("post-merge difficulty must be zero (or omitted) in env"))
|
||||||
|
}
|
||||||
|
env.Difficulty = nil
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func applyCancunChecks(env *stEnv, chainConfig *params.ChainConfig) error {
|
||||||
|
if !chainConfig.IsCancun(big.NewInt(int64(env.Number)), env.Timestamp) {
|
||||||
|
env.ParentBeaconBlockRoot = nil // un-set it if it has been set too early
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// Post-cancun
|
||||||
|
// We require EIP-4788 beacon root to be set in the env
|
||||||
|
if env.ParentBeaconBlockRoot == nil {
|
||||||
|
return NewError(ErrorConfig, errors.New("post-cancun env requires parentBeaconBlockRoot to be set"))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type Alloc map[common.Address]core.GenesisAccount
|
type Alloc map[common.Address]core.GenesisAccount
|
||||||
|
|
||||||
func (g Alloc) OnRoot(common.Hash) {}
|
func (g Alloc) OnRoot(common.Hash) {}
|
||||||
|
@ -267,6 +267,14 @@ func TestT8n(t *testing.T) {
|
|||||||
output: t8nOutput{alloc: true, result: true},
|
output: t8nOutput{alloc: true, result: true},
|
||||||
expOut: "exp.json",
|
expOut: "exp.json",
|
||||||
},
|
},
|
||||||
|
{ // More cancun tests
|
||||||
|
base: "./testdata/29",
|
||||||
|
input: t8nInput{
|
||||||
|
"alloc.json", "txs.json", "env.json", "Cancun", "",
|
||||||
|
},
|
||||||
|
output: t8nOutput{alloc: true, result: true},
|
||||||
|
expOut: "exp.json",
|
||||||
|
},
|
||||||
} {
|
} {
|
||||||
args := []string{"t8n"}
|
args := []string{"t8n"}
|
||||||
args = append(args, tc.output.get()...)
|
args = append(args, tc.output.get()...)
|
||||||
|
3
cmd/evm/testdata/28/env.json
vendored
3
cmd/evm/testdata/28/env.json
vendored
@ -18,5 +18,6 @@
|
|||||||
"parentBlobGasUsed" : "0x00",
|
"parentBlobGasUsed" : "0x00",
|
||||||
"blockHashes" : {
|
"blockHashes" : {
|
||||||
"0" : "0x3a9b485972e7353edd9152712492f0c58d89ef80623686b6bf947a4a6dce6cb6"
|
"0" : "0x3a9b485972e7353edd9152712492f0c58d89ef80623686b6bf947a4a6dce6cb6"
|
||||||
}
|
},
|
||||||
|
"parentBeaconBlockRoot": "0x0000beac00beac00beac00beac00beac00beac00beac00beac00beac00beac00"
|
||||||
}
|
}
|
16
cmd/evm/testdata/29/alloc.json
vendored
Normal file
16
cmd/evm/testdata/29/alloc.json
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||||
|
"balance" : "0x016345785d8a0000",
|
||||||
|
"code" : "0x",
|
||||||
|
"nonce" : "0x00",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"0xbEac00dDB15f3B6d645C48263dC93862413A222D" : {
|
||||||
|
"balance" : "0x1",
|
||||||
|
"code" : "0x3373fffffffffffffffffffffffffffffffffffffffe14604457602036146024575f5ffd5b620180005f350680545f35146037575f5ffd5b6201800001545f5260205ff35b6201800042064281555f359062018000015500",
|
||||||
|
"nonce" : "0x00",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
cmd/evm/testdata/29/env.json
vendored
Normal file
20
cmd/evm/testdata/29/env.json
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
|
||||||
|
"currentNumber" : "0x01",
|
||||||
|
"currentTimestamp" : "0x079e",
|
||||||
|
"currentGasLimit" : "0x7fffffffffffffff",
|
||||||
|
"previousHash" : "0x3a9b485972e7353edd9152712492f0c58d89ef80623686b6bf947a4a6dce6cb6",
|
||||||
|
"currentBlobGasUsed" : "0x00",
|
||||||
|
"parentTimestamp" : "0x03b6",
|
||||||
|
"parentDifficulty" : "0x00",
|
||||||
|
"parentUncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||||
|
"currentRandom" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
|
"withdrawals" : [
|
||||||
|
],
|
||||||
|
"parentBaseFee" : "0x0a",
|
||||||
|
"parentGasUsed" : "0x00",
|
||||||
|
"parentGasLimit" : "0x7fffffffffffffff",
|
||||||
|
"parentExcessBlobGas" : "0x00",
|
||||||
|
"parentBlobGasUsed" : "0x00",
|
||||||
|
"parentBeaconBlockRoot": "0x0000beac00beac00beac00beac00beac00beac00beac00beac00beac00beac00"
|
||||||
|
}
|
45
cmd/evm/testdata/29/exp.json
vendored
Normal file
45
cmd/evm/testdata/29/exp.json
vendored
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
{
|
||||||
|
"alloc": {
|
||||||
|
"0xbeac00ddb15f3b6d645c48263dc93862413a222d": {
|
||||||
|
"code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604457602036146024575f5ffd5b620180005f350680545f35146037575f5ffd5b6201800001545f5260205ff35b6201800042064281555f359062018000015500",
|
||||||
|
"storage": {
|
||||||
|
"0x000000000000000000000000000000000000000000000000000000000000079e": "0x000000000000000000000000000000000000000000000000000000000000079e",
|
||||||
|
"0x000000000000000000000000000000000000000000000000000000000001879e": "0x0000beac00beac00beac00beac00beac00beac00beac00beac00beac00beac00"
|
||||||
|
},
|
||||||
|
"balance": "0x1"
|
||||||
|
},
|
||||||
|
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
|
||||||
|
"balance": "0x16345785d871db8",
|
||||||
|
"nonce": "0x1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"result": {
|
||||||
|
"stateRoot": "0x2db9f6bc233e8fd0af2d8023404493a19b37d9d69ace71f4e73158851fced574",
|
||||||
|
"txRoot": "0x248074fabe112f7d93917f292b64932394f835bb98da91f21501574d58ec92ab",
|
||||||
|
"receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
|
||||||
|
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||||
|
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"receipts": [
|
||||||
|
{
|
||||||
|
"type": "0x2",
|
||||||
|
"root": "0x",
|
||||||
|
"status": "0x1",
|
||||||
|
"cumulativeGasUsed": "0x5208",
|
||||||
|
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"logs": null,
|
||||||
|
"transactionHash": "0x84f70aba406a55628a0620f26d260f90aeb6ccc55fed6ec2ac13dd4f727032ed",
|
||||||
|
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||||
|
"gasUsed": "0x5208",
|
||||||
|
"effectiveGasPrice": null,
|
||||||
|
"blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"transactionIndex": "0x0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"currentDifficulty": null,
|
||||||
|
"gasUsed": "0x5208",
|
||||||
|
"currentBaseFee": "0x9",
|
||||||
|
"withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
|
"currentExcessBlobGas": "0x0",
|
||||||
|
"currentBlobGasUsed": "0x0"
|
||||||
|
}
|
||||||
|
}
|
29
cmd/evm/testdata/29/readme.md
vendored
Normal file
29
cmd/evm/testdata/29/readme.md
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
## EIP 4788
|
||||||
|
|
||||||
|
This test contains testcases for EIP-4788. The 4788-contract is
|
||||||
|
located at address `0xbeac00ddb15f3b6d645c48263dc93862413a222d`, and this test executes a simple transaction. It also
|
||||||
|
implicitly invokes the system tx, which sets calls the contract and sets the
|
||||||
|
storage values
|
||||||
|
```
|
||||||
|
$ dir=./testdata/29/ && go run . t8n --state.fork=Cancun --input.alloc=$dir/alloc.json --input.txs=$dir/txs.json --input.env=$dir/env.json --output.alloc=stdout
|
||||||
|
INFO [08-15|20:07:56.335] Trie dumping started root=ecde45..2af8a7
|
||||||
|
INFO [08-15|20:07:56.335] Trie dumping complete accounts=2 elapsed="225.848µs"
|
||||||
|
INFO [08-15|20:07:56.335] Wrote file file=result.json
|
||||||
|
{
|
||||||
|
"alloc": {
|
||||||
|
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
|
||||||
|
"balance": "0x16345785d871db8",
|
||||||
|
"nonce": "0x1"
|
||||||
|
},
|
||||||
|
"0xbeac00541d49391ed88abf392bfc1f4dea8c4143": {
|
||||||
|
"code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604457602036146024575f5ffd5b620180005f350680545f35146037575f5ffd5b6201800001545f5260205ff35b6201800042064281555f359062018000015500",
|
||||||
|
"storage": {
|
||||||
|
"0x000000000000000000000000000000000000000000000000000000000000079e": "0x000000000000000000000000000000000000000000000000000000000000079e",
|
||||||
|
"0x000000000000000000000000000000000000000000000000000000000001879e": "0x0000beac00beac00beac00beac00beac00beac00beac00beac00beac00beac00"
|
||||||
|
},
|
||||||
|
"balance": "0x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
19
cmd/evm/testdata/29/txs.json
vendored
Normal file
19
cmd/evm/testdata/29/txs.json
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"input" : "0x",
|
||||||
|
"gas" : "0x10000000",
|
||||||
|
"nonce" : "0x0",
|
||||||
|
"to" : "0x1111111111111111111111111111111111111111",
|
||||||
|
"value" : "0x0",
|
||||||
|
"secretKey" : "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
|
||||||
|
"chainId" : "0x1",
|
||||||
|
"type" : "0x2",
|
||||||
|
"v": "0x0",
|
||||||
|
"r": "0x0",
|
||||||
|
"s": "0x0",
|
||||||
|
"maxFeePerGas" : "0xfa0",
|
||||||
|
"maxPriorityFeePerGas" : "0x0",
|
||||||
|
"accessList" : [
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
@ -269,15 +269,21 @@ func (beacon *Beacon) verifyHeader(chain consensus.ChainHeaderReader, header, pa
|
|||||||
if !shanghai && header.WithdrawalsHash != nil {
|
if !shanghai && header.WithdrawalsHash != nil {
|
||||||
return fmt.Errorf("invalid withdrawalsHash: have %x, expected nil", header.WithdrawalsHash)
|
return fmt.Errorf("invalid withdrawalsHash: have %x, expected nil", header.WithdrawalsHash)
|
||||||
}
|
}
|
||||||
// Verify the existence / non-existence of excessBlobGas
|
// Verify the existence / non-existence of cancun-specific header fields
|
||||||
cancun := chain.Config().IsCancun(header.Number, header.Time)
|
cancun := chain.Config().IsCancun(header.Number, header.Time)
|
||||||
if !cancun && header.ExcessBlobGas != nil {
|
if !cancun {
|
||||||
return fmt.Errorf("invalid excessBlobGas: have %d, expected nil", header.ExcessBlobGas)
|
switch {
|
||||||
}
|
case header.ExcessBlobGas != nil:
|
||||||
if !cancun && header.BlobGasUsed != nil {
|
return fmt.Errorf("invalid excessBlobGas: have %d, expected nil", header.ExcessBlobGas)
|
||||||
return fmt.Errorf("invalid blobGasUsed: have %d, expected nil", header.BlobGasUsed)
|
case header.BlobGasUsed != nil:
|
||||||
}
|
return fmt.Errorf("invalid blobGasUsed: have %d, expected nil", header.BlobGasUsed)
|
||||||
if cancun {
|
case header.BeaconRoot != nil:
|
||||||
|
return fmt.Errorf("invalid beaconRoot, have %#x, expected nil", header.BeaconRoot)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if header.BeaconRoot == nil {
|
||||||
|
return errors.New("header is missing beaconRoot")
|
||||||
|
}
|
||||||
if err := eip4844.VerifyEIP4844Header(parent, header); err != nil {
|
if err := eip4844.VerifyEIP4844Header(parent, header); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -487,6 +487,9 @@ func (g *Genesis) ToBlock() *types.Block {
|
|||||||
if head.BlobGasUsed == nil {
|
if head.BlobGasUsed == nil {
|
||||||
head.BlobGasUsed = new(uint64)
|
head.BlobGasUsed = new(uint64)
|
||||||
}
|
}
|
||||||
|
if head.BeaconRoot == nil {
|
||||||
|
head.BeaconRoot = new(common.Hash)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return types.NewBlock(head, nil, nil, nil, trie.NewStackTrie(nil)).WithWithdrawals(withdrawals)
|
return types.NewBlock(head, nil, nil, nil, trie.NewStackTrie(nil)).WithWithdrawals(withdrawals)
|
||||||
|
@ -76,6 +76,9 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
|||||||
vmenv = vm.NewEVM(context, vm.TxContext{}, statedb, p.config, cfg)
|
vmenv = vm.NewEVM(context, vm.TxContext{}, statedb, p.config, cfg)
|
||||||
signer = types.MakeSigner(p.config, header.Number, header.Time)
|
signer = types.MakeSigner(p.config, header.Number, header.Time)
|
||||||
)
|
)
|
||||||
|
if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
|
||||||
|
ProcessBeaconBlockRoot(*beaconRoot, vmenv, statedb)
|
||||||
|
}
|
||||||
// Iterate over and process the individual transactions
|
// Iterate over and process the individual transactions
|
||||||
for i, tx := range block.Transactions() {
|
for i, tx := range block.Transactions() {
|
||||||
msg, err := TransactionToMessage(tx, signer, header.BaseFee)
|
msg, err := TransactionToMessage(tx, signer, header.BaseFee)
|
||||||
@ -160,3 +163,23 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo
|
|||||||
vmenv := vm.NewEVM(blockContext, vm.TxContext{BlobHashes: tx.BlobHashes()}, statedb, config, cfg)
|
vmenv := vm.NewEVM(blockContext, vm.TxContext{BlobHashes: tx.BlobHashes()}, statedb, config, cfg)
|
||||||
return applyTransaction(msg, config, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv)
|
return applyTransaction(msg, config, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ProcessBeaconBlockRoot applies the EIP-4788 system call to the beacon block root
|
||||||
|
// contract. This method is exported to be used in tests.
|
||||||
|
func ProcessBeaconBlockRoot(beaconRoot common.Hash, vmenv *vm.EVM, statedb *state.StateDB) {
|
||||||
|
// If EIP-4788 is enabled, we need to invoke the beaconroot storage contract with
|
||||||
|
// the new root
|
||||||
|
msg := &Message{
|
||||||
|
From: params.SystemAddress,
|
||||||
|
GasLimit: 30_000_000,
|
||||||
|
GasPrice: common.Big0,
|
||||||
|
GasFeeCap: common.Big0,
|
||||||
|
GasTipCap: common.Big0,
|
||||||
|
To: ¶ms.BeaconRootsStorageAddress,
|
||||||
|
Data: beaconRoot[:],
|
||||||
|
}
|
||||||
|
vmenv.Reset(NewEVMTxContext(msg), statedb)
|
||||||
|
statedb.AddAddressToAccessList(params.BeaconRootsStorageAddress)
|
||||||
|
_, _, _ = vmenv.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.Big0)
|
||||||
|
statedb.Finalise(true)
|
||||||
|
}
|
||||||
|
@ -410,6 +410,9 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr
|
|||||||
used := uint64(nBlobs * params.BlobTxBlobGasPerBlob)
|
used := uint64(nBlobs * params.BlobTxBlobGasPerBlob)
|
||||||
header.ExcessBlobGas = &excess
|
header.ExcessBlobGas = &excess
|
||||||
header.BlobGasUsed = &used
|
header.BlobGasUsed = &used
|
||||||
|
|
||||||
|
beaconRoot := common.HexToHash("0xbeac00")
|
||||||
|
header.BeaconRoot = &beaconRoot
|
||||||
}
|
}
|
||||||
// Assemble and return the final block for sealing
|
// Assemble and return the final block for sealing
|
||||||
if config.IsShanghai(header.Number, header.Time) {
|
if config.IsShanghai(header.Number, header.Time) {
|
||||||
|
@ -90,6 +90,9 @@ type Header struct {
|
|||||||
|
|
||||||
// ExcessBlobGas was added by EIP-4844 and is ignored in legacy headers.
|
// ExcessBlobGas was added by EIP-4844 and is ignored in legacy headers.
|
||||||
ExcessBlobGas *uint64 `json:"excessBlobGas" rlp:"optional"`
|
ExcessBlobGas *uint64 `json:"excessBlobGas" rlp:"optional"`
|
||||||
|
|
||||||
|
// BeaconRoot was added by EIP-4788 and is ignored in legacy headers.
|
||||||
|
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// field type overrides for gencodec
|
// field type overrides for gencodec
|
||||||
@ -297,6 +300,10 @@ func CopyHeader(h *Header) *Header {
|
|||||||
cpy.BlobGasUsed = new(uint64)
|
cpy.BlobGasUsed = new(uint64)
|
||||||
*cpy.BlobGasUsed = *h.BlobGasUsed
|
*cpy.BlobGasUsed = *h.BlobGasUsed
|
||||||
}
|
}
|
||||||
|
if h.BeaconRoot != nil {
|
||||||
|
cpy.BeaconRoot = new(common.Hash)
|
||||||
|
*cpy.BeaconRoot = *h.BeaconRoot
|
||||||
|
}
|
||||||
return &cpy
|
return &cpy
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,6 +383,8 @@ func (b *Block) BaseFee() *big.Int {
|
|||||||
return new(big.Int).Set(b.header.BaseFee)
|
return new(big.Int).Set(b.header.BaseFee)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Block) BeaconRoot() *common.Hash { return b.header.BeaconRoot }
|
||||||
|
|
||||||
func (b *Block) ExcessBlobGas() *uint64 {
|
func (b *Block) ExcessBlobGas() *uint64 {
|
||||||
var excessBlobGas *uint64
|
var excessBlobGas *uint64
|
||||||
if b.header.ExcessBlobGas != nil {
|
if b.header.ExcessBlobGas != nil {
|
||||||
|
@ -35,6 +35,7 @@ func (h Header) MarshalJSON() ([]byte, error) {
|
|||||||
WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
|
WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
|
||||||
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"`
|
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"`
|
||||||
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"`
|
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"`
|
||||||
|
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
||||||
Hash common.Hash `json:"hash"`
|
Hash common.Hash `json:"hash"`
|
||||||
}
|
}
|
||||||
var enc Header
|
var enc Header
|
||||||
@ -57,6 +58,7 @@ func (h Header) MarshalJSON() ([]byte, error) {
|
|||||||
enc.WithdrawalsHash = h.WithdrawalsHash
|
enc.WithdrawalsHash = h.WithdrawalsHash
|
||||||
enc.BlobGasUsed = (*hexutil.Uint64)(h.BlobGasUsed)
|
enc.BlobGasUsed = (*hexutil.Uint64)(h.BlobGasUsed)
|
||||||
enc.ExcessBlobGas = (*hexutil.Uint64)(h.ExcessBlobGas)
|
enc.ExcessBlobGas = (*hexutil.Uint64)(h.ExcessBlobGas)
|
||||||
|
enc.BeaconRoot = h.BeaconRoot
|
||||||
enc.Hash = h.Hash()
|
enc.Hash = h.Hash()
|
||||||
return json.Marshal(&enc)
|
return json.Marshal(&enc)
|
||||||
}
|
}
|
||||||
@ -83,6 +85,7 @@ func (h *Header) UnmarshalJSON(input []byte) error {
|
|||||||
WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
|
WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
|
||||||
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"`
|
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"`
|
||||||
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"`
|
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"`
|
||||||
|
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
||||||
}
|
}
|
||||||
var dec Header
|
var dec Header
|
||||||
if err := json.Unmarshal(input, &dec); err != nil {
|
if err := json.Unmarshal(input, &dec); err != nil {
|
||||||
@ -157,5 +160,8 @@ func (h *Header) UnmarshalJSON(input []byte) error {
|
|||||||
if dec.ExcessBlobGas != nil {
|
if dec.ExcessBlobGas != nil {
|
||||||
h.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas)
|
h.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas)
|
||||||
}
|
}
|
||||||
|
if dec.BeaconRoot != nil {
|
||||||
|
h.BeaconRoot = dec.BeaconRoot
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,8 @@ func (obj *Header) EncodeRLP(_w io.Writer) error {
|
|||||||
_tmp2 := obj.WithdrawalsHash != nil
|
_tmp2 := obj.WithdrawalsHash != nil
|
||||||
_tmp3 := obj.BlobGasUsed != nil
|
_tmp3 := obj.BlobGasUsed != nil
|
||||||
_tmp4 := obj.ExcessBlobGas != nil
|
_tmp4 := obj.ExcessBlobGas != nil
|
||||||
if _tmp1 || _tmp2 || _tmp3 || _tmp4 {
|
_tmp5 := obj.BeaconRoot != nil
|
||||||
|
if _tmp1 || _tmp2 || _tmp3 || _tmp4 || _tmp5 {
|
||||||
if obj.BaseFee == nil {
|
if obj.BaseFee == nil {
|
||||||
w.Write(rlp.EmptyString)
|
w.Write(rlp.EmptyString)
|
||||||
} else {
|
} else {
|
||||||
@ -54,27 +55,34 @@ func (obj *Header) EncodeRLP(_w io.Writer) error {
|
|||||||
w.WriteBigInt(obj.BaseFee)
|
w.WriteBigInt(obj.BaseFee)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _tmp2 || _tmp3 || _tmp4 {
|
if _tmp2 || _tmp3 || _tmp4 || _tmp5 {
|
||||||
if obj.WithdrawalsHash == nil {
|
if obj.WithdrawalsHash == nil {
|
||||||
w.Write([]byte{0x80})
|
w.Write([]byte{0x80})
|
||||||
} else {
|
} else {
|
||||||
w.WriteBytes(obj.WithdrawalsHash[:])
|
w.WriteBytes(obj.WithdrawalsHash[:])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _tmp3 || _tmp4 {
|
if _tmp3 || _tmp4 || _tmp5 {
|
||||||
if obj.BlobGasUsed == nil {
|
if obj.BlobGasUsed == nil {
|
||||||
w.Write([]byte{0x80})
|
w.Write([]byte{0x80})
|
||||||
} else {
|
} else {
|
||||||
w.WriteUint64((*obj.BlobGasUsed))
|
w.WriteUint64((*obj.BlobGasUsed))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _tmp4 {
|
if _tmp4 || _tmp5 {
|
||||||
if obj.ExcessBlobGas == nil {
|
if obj.ExcessBlobGas == nil {
|
||||||
w.Write([]byte{0x80})
|
w.Write([]byte{0x80})
|
||||||
} else {
|
} else {
|
||||||
w.WriteUint64((*obj.ExcessBlobGas))
|
w.WriteUint64((*obj.ExcessBlobGas))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if _tmp5 {
|
||||||
|
if obj.BeaconRoot == nil {
|
||||||
|
w.Write([]byte{0x80})
|
||||||
|
} else {
|
||||||
|
w.WriteBytes(obj.BeaconRoot[:])
|
||||||
|
}
|
||||||
|
}
|
||||||
w.ListEnd(_tmp0)
|
w.ListEnd(_tmp0)
|
||||||
return w.Flush()
|
return w.Flush()
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,11 @@
|
|||||||
|
|
||||||
package params
|
package params
|
||||||
|
|
||||||
import "math/big"
|
import (
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
GasLimitBoundDivisor uint64 = 1024 // The bound divisor of the gas limit, used in update calculations.
|
GasLimitBoundDivisor uint64 = 1024 // The bound divisor of the gas limit, used in update calculations.
|
||||||
@ -179,4 +183,9 @@ var (
|
|||||||
GenesisDifficulty = big.NewInt(131072) // Difficulty of the Genesis block.
|
GenesisDifficulty = big.NewInt(131072) // Difficulty of the Genesis block.
|
||||||
MinimumDifficulty = big.NewInt(131072) // The minimum that the difficulty may ever be.
|
MinimumDifficulty = big.NewInt(131072) // The minimum that the difficulty may ever be.
|
||||||
DurationLimit = big.NewInt(13) // The decision boundary on the blocktime duration used to determine whether difficulty should go up or not.
|
DurationLimit = big.NewInt(13) // The decision boundary on the blocktime duration used to determine whether difficulty should go up or not.
|
||||||
|
|
||||||
|
// BeaconRootsStorageAddress is the address where historical beacon roots are stored as per EIP-4788
|
||||||
|
BeaconRootsStorageAddress = common.HexToAddress("0xbEac00dDB15f3B6d645C48263dC93862413A222D")
|
||||||
|
// SystemAddress is where the system-transaction is sent from as per EIP-4788
|
||||||
|
SystemAddress common.Address = common.HexToAddress("0xfffffffffffffffffffffffffffffffffffffffe")
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user