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

core, params, beacon/engine: implement EIP 4788 BeaconRoot #27849

Merged
merged 14 commits into from
Aug 22, 2023
Merged
Show file tree
Hide file tree
Changes from 7 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
2 changes: 2 additions & 0 deletions beacon/engine/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ func ExecutableDataToBlock(params ExecutableData, versionedHashes []common.Hash)
WithdrawalsHash: withdrawalsRoot,
ExcessBlobGas: params.ExcessBlobGas,
BlobGasUsed: params.BlobGasUsed,
// TODO BeaconRoot
}
block := types.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */).WithWithdrawals(params.Withdrawals)
if block.Hash() != params.BlockHash {
Expand Down Expand Up @@ -255,6 +256,7 @@ func BlockToExecutableData(block *types.Block, fees *big.Int, blobs []kzg4844.Bl
Withdrawals: block.Withdrawals(),
BlobGasUsed: block.BlobGasUsed(),
ExcessBlobGas: block.ExcessBlobGas(),
// TODO BeaconRoot
}
blobsBundle := BlobsBundleV1{
Commitments: make([]hexutil.Bytes, 0),
Expand Down
22 changes: 14 additions & 8 deletions consensus/beacon/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,15 +269,21 @@ func (beacon *Beacon) verifyHeader(chain consensus.ChainHeaderReader, header, pa
if !shanghai && header.WithdrawalsHash != nil {
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)
if !cancun && header.ExcessBlobGas != nil {
return fmt.Errorf("invalid excessBlobGas: have %d, expected nil", header.ExcessBlobGas)
}
if !cancun && header.BlobGasUsed != nil {
return fmt.Errorf("invalid blobGasUsed: have %d, expected nil", header.BlobGasUsed)
}
if cancun {
if !cancun {
switch {
case header.ExcessBlobGas != nil:
return fmt.Errorf("invalid excessBlobGas: have %d, expected nil", header.ExcessBlobGas)
case header.BlobGasUsed != nil:
return fmt.Errorf("invalid blobGasUsed: have %d, expected nil", header.BlobGasUsed)
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 {
return err
}
Expand Down
3 changes: 3 additions & 0 deletions core/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,9 @@ func (g *Genesis) ToBlock() *types.Block {
if head.BlobGasUsed == nil {
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)
Expand Down
19 changes: 19 additions & 0 deletions core/state_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
blockNumber = block.Number()
allLogs []*types.Log
gp = new(GasPool).AddGas(block.GasLimit())
beaconRoot *common.Hash
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this just a placeholder until we later activate this by checking block.BeaconRoot?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, yeah we should remove this and use block.BeaconRoot instead. Looks very odd like that

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yeah that change is probably in the follow-up PR

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, #27872 is the follow-up, but it still doesn't fill this placeholder :/

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah no worries, I have these changes in the devnet-8 branch. I'm not sure the best way to be tracking this for everyone as it pretty out-of-sync with master.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lightclient thanks for adding your updates, I have also pushed some changes now -- primarily, hooking it into evm t8n so I could actually test it and see it working in practice.
PTAL

)
// Mutate the block and state according to any hard-fork specs
if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 {
Expand All @@ -76,6 +77,24 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
vmenv = vm.NewEVM(context, vm.TxContext{}, statedb, p.config, cfg)
signer = types.MakeSigner(p.config, header.Number, header.Time)
)
if beaconRoot != nil {
// If EIP-4788 is enabled, we need to invoke the beaconroot storage contract with
// the new root
// TODO: Right now, I set the GasXX fields to 0. If this does not work,
// we can use the header.BaseFee and set that instead.
msg := &Message{
From: params.SystemAddress,
GasLimit: 100_000,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest to use gas limit of 30_000_000 to be in line with the Gnosis Chain spec for system transactions.

GasPrice: new(big.Int).SetUint64(0), // TODO use nil?
GasFeeCap: new(big.Int).SetUint64(0), // TODO use basefee?
GasTipCap: new(big.Int).SetUint64(0), // TODO use zero?
To: &params.BeaconRootsStorageAddress,
Data: (*beaconRoot)[:], // TODO use 4byte invocation?
}
vmenv.Reset(NewEVMTxContext(msg), statedb)
_, _, _ = vmenv.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 100_000, nil)
statedb.Finalise(true)
}
// Iterate over and process the individual transactions
for i, tx := range block.Transactions() {
msg, err := TransactionToMessage(tx, signer, header.BaseFee)
Expand Down
3 changes: 3 additions & 0 deletions core/state_processor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,9 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr
used := uint64(nBlobs * params.BlobTxBlobGasPerBlob)
header.ExcessBlobGas = &excess
header.BlobGasUsed = &used

beaconRoot := common.HexToHash("0xbeac00")
header.BeaconRoot = &beaconRoot
}
// Assemble and return the final block for sealing
if config.IsShanghai(header.Number, header.Time) {
Expand Down
7 changes: 7 additions & 0 deletions core/types/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ type Header struct {

// ExcessBlobGas was added by EIP-4844 and is ignored in legacy headers.
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
Expand Down Expand Up @@ -297,6 +300,10 @@ func CopyHeader(h *Header) *Header {
cpy.BlobGasUsed = new(uint64)
*cpy.BlobGasUsed = *h.BlobGasUsed
}
if h.BeaconRoot != nil {
cpy.BeaconRoot = new(common.Hash)
*cpy.BeaconRoot = *h.BeaconRoot
}
return &cpy
}

Expand Down
6 changes: 6 additions & 0 deletions core/types/gen_header_json.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 12 additions & 4 deletions core/types/gen_header_rlp.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 8 additions & 1 deletion params/protocol_params.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@

package params

import "math/big"
import (
"math/big"

"github.com/ethereum/go-ethereum/common"
)

const (
GasLimitBoundDivisor uint64 = 1024 // The bound divisor of the gas limit, used in update calculations.
Expand Down Expand Up @@ -179,4 +183,7 @@ var (
GenesisDifficulty = big.NewInt(131072) // Difficulty of the Genesis block.
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.

BeaconRootsStorageAddress common.Address = common.BytesToAddress([]byte{0xb}) // Address where historical beacon roots are stored as per EIP-4788
SystemAddress common.Address = common.Address{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe}
)