Unverified Commit 93f196c4 authored by Marius van der Wijden's avatar Marius van der Wijden Committed by GitHub

eth/catalyst: implement kintsugi spec v1.0.0-alpha.4 (#23984)

This PR implements the new kintsugi specification which can be found here: https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.4/src/engine/specification.md
parent 46f701ca
...@@ -159,7 +159,7 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) { ...@@ -159,7 +159,7 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
cfg.Eth.OverrideArrowGlacier = new(big.Int).SetUint64(ctx.GlobalUint64(utils.OverrideArrowGlacierFlag.Name)) cfg.Eth.OverrideArrowGlacier = new(big.Int).SetUint64(ctx.GlobalUint64(utils.OverrideArrowGlacierFlag.Name))
} }
if ctx.GlobalIsSet(utils.OverrideTerminalTotalDifficulty.Name) { if ctx.GlobalIsSet(utils.OverrideTerminalTotalDifficulty.Name) {
cfg.Eth.Genesis.Config.TerminalTotalDifficulty = new(big.Int).SetUint64(ctx.GlobalUint64(utils.OverrideTerminalTotalDifficulty.Name)) cfg.Eth.OverrideTerminalTotalDifficulty = new(big.Int).SetUint64(ctx.GlobalUint64(utils.OverrideTerminalTotalDifficulty.Name))
} }
backend, _ := utils.RegisterEthService(stack, &cfg.Eth, ctx.GlobalBool(utils.CatalystFlag.Name)) backend, _ := utils.RegisterEthService(stack, &cfg.Eth, ctx.GlobalBool(utils.CatalystFlag.Name))
......
This diff is collapsed.
...@@ -85,11 +85,10 @@ func TestEth2AssembleBlock(t *testing.T) { ...@@ -85,11 +85,10 @@ func TestEth2AssembleBlock(t *testing.T) {
t.Fatalf("error signing transaction, err=%v", err) t.Fatalf("error signing transaction, err=%v", err)
} }
ethservice.TxPool().AddLocal(tx) ethservice.TxPool().AddLocal(tx)
blockParams := AssembleBlockParams{ blockParams := PayloadAttributesV1{
ParentHash: blocks[9].Hash(), Timestamp: blocks[9].Time() + 5,
Timestamp: blocks[9].Time() + 5,
} }
execData, err := api.assembleBlock(blockParams) execData, err := api.assembleBlock(blocks[9].Hash(), &blockParams)
if err != nil { if err != nil {
t.Fatalf("error producing block, err=%v", err) t.Fatalf("error producing block, err=%v", err)
} }
...@@ -107,11 +106,10 @@ func TestEth2AssembleBlockWithAnotherBlocksTxs(t *testing.T) { ...@@ -107,11 +106,10 @@ func TestEth2AssembleBlockWithAnotherBlocksTxs(t *testing.T) {
// Put the 10th block's tx in the pool and produce a new block // Put the 10th block's tx in the pool and produce a new block
api.insertTransactions(blocks[9].Transactions()) api.insertTransactions(blocks[9].Transactions())
blockParams := AssembleBlockParams{ blockParams := PayloadAttributesV1{
ParentHash: blocks[8].Hash(), Timestamp: blocks[8].Time() + 5,
Timestamp: blocks[8].Time() + 5,
} }
execData, err := api.assembleBlock(blockParams) execData, err := api.assembleBlock(blocks[8].Hash(), &blockParams)
if err != nil { if err != nil {
t.Fatalf("error producing block, err=%v", err) t.Fatalf("error producing block, err=%v", err)
} }
...@@ -126,14 +124,20 @@ func TestSetHeadBeforeTotalDifficulty(t *testing.T) { ...@@ -126,14 +124,20 @@ func TestSetHeadBeforeTotalDifficulty(t *testing.T) {
defer n.Close() defer n.Close()
api := NewConsensusAPI(ethservice, nil) api := NewConsensusAPI(ethservice, nil)
fcState := ForkchoiceStateV1{
if err := api.ForkchoiceUpdated(ForkChoiceParams{HeadBlockHash: blocks[5].Hash()}); err == nil { HeadBlockHash: blocks[5].Hash(),
SafeBlockHash: common.Hash{},
FinalizedBlockHash: common.Hash{},
}
if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err == nil {
t.Errorf("fork choice updated before total terminal difficulty should fail") t.Errorf("fork choice updated before total terminal difficulty should fail")
} }
} }
func TestEth2PrepareAndGetPayload(t *testing.T) { func TestEth2PrepareAndGetPayload(t *testing.T) {
genesis, blocks := generatePreMergeChain(10) genesis, blocks := generatePreMergeChain(10)
// We need to properly set the terminal total difficulty
genesis.Config.TerminalTotalDifficulty.Sub(genesis.Config.TerminalTotalDifficulty, blocks[9].Difficulty())
n, ethservice := startEthService(t, genesis, blocks[:9]) n, ethservice := startEthService(t, genesis, blocks[:9])
defer n.Close() defer n.Close()
...@@ -141,15 +145,20 @@ func TestEth2PrepareAndGetPayload(t *testing.T) { ...@@ -141,15 +145,20 @@ func TestEth2PrepareAndGetPayload(t *testing.T) {
// Put the 10th block's tx in the pool and produce a new block // Put the 10th block's tx in the pool and produce a new block
api.insertTransactions(blocks[9].Transactions()) api.insertTransactions(blocks[9].Transactions())
blockParams := AssembleBlockParams{ blockParams := PayloadAttributesV1{
ParentHash: blocks[8].Hash(), Timestamp: blocks[8].Time() + 5,
Timestamp: blocks[8].Time() + 5, }
fcState := ForkchoiceStateV1{
HeadBlockHash: blocks[8].Hash(),
SafeBlockHash: common.Hash{},
FinalizedBlockHash: common.Hash{},
} }
respID, err := api.PreparePayload(blockParams) _, err := api.ForkchoiceUpdatedV1(fcState, &blockParams)
if err != nil { if err != nil {
t.Fatalf("error preparing payload, err=%v", err) t.Fatalf("error preparing payload, err=%v", err)
} }
execData, err := api.GetPayload(hexutil.Uint64(respID.PayloadID)) payloadID := computePayloadId(fcState.HeadBlockHash, &blockParams)
execData, err := api.GetPayloadV1(hexutil.Bytes(payloadID))
if err != nil { if err != nil {
t.Fatalf("error getting payload, err=%v", err) t.Fatalf("error getting payload, err=%v", err)
} }
...@@ -201,9 +210,8 @@ func TestEth2NewBlock(t *testing.T) { ...@@ -201,9 +210,8 @@ func TestEth2NewBlock(t *testing.T) {
tx, _ := types.SignTx(types.NewContractCreation(nonce, new(big.Int), 1000000, big.NewInt(2*params.InitialBaseFee), logCode), types.LatestSigner(ethservice.BlockChain().Config()), testKey) tx, _ := types.SignTx(types.NewContractCreation(nonce, new(big.Int), 1000000, big.NewInt(2*params.InitialBaseFee), logCode), types.LatestSigner(ethservice.BlockChain().Config()), testKey)
ethservice.TxPool().AddLocal(tx) ethservice.TxPool().AddLocal(tx)
execData, err := api.assembleBlock(AssembleBlockParams{ execData, err := api.assembleBlock(parent.Hash(), &PayloadAttributesV1{
ParentHash: parent.Hash(), Timestamp: parent.Time() + 5,
Timestamp: parent.Time() + 5,
}) })
if err != nil { if err != nil {
t.Fatalf("Failed to create the executable data %v", err) t.Fatalf("Failed to create the executable data %v", err)
...@@ -212,7 +220,7 @@ func TestEth2NewBlock(t *testing.T) { ...@@ -212,7 +220,7 @@ func TestEth2NewBlock(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("Failed to convert executable data to block %v", err) t.Fatalf("Failed to convert executable data to block %v", err)
} }
newResp, err := api.ExecutePayload(*execData) newResp, err := api.ExecutePayloadV1(*execData)
if err != nil || newResp.Status != "VALID" { if err != nil || newResp.Status != "VALID" {
t.Fatalf("Failed to insert block: %v", err) t.Fatalf("Failed to insert block: %v", err)
} }
...@@ -220,8 +228,12 @@ func TestEth2NewBlock(t *testing.T) { ...@@ -220,8 +228,12 @@ func TestEth2NewBlock(t *testing.T) {
t.Fatalf("Chain head shouldn't be updated") t.Fatalf("Chain head shouldn't be updated")
} }
checkLogEvents(t, newLogCh, rmLogsCh, 0, 0) checkLogEvents(t, newLogCh, rmLogsCh, 0, 0)
fcState := ForkchoiceStateV1{
if err := api.ForkchoiceUpdated(ForkChoiceParams{HeadBlockHash: block.Hash(), FinalizedBlockHash: block.Hash()}); err != nil { HeadBlockHash: block.Hash(),
SafeBlockHash: block.Hash(),
FinalizedBlockHash: block.Hash(),
}
if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil {
t.Fatalf("Failed to insert block: %v", err) t.Fatalf("Failed to insert block: %v", err)
} }
if ethservice.BlockChain().CurrentBlock().NumberU64() != block.NumberU64() { if ethservice.BlockChain().CurrentBlock().NumberU64() != block.NumberU64() {
...@@ -238,9 +250,8 @@ func TestEth2NewBlock(t *testing.T) { ...@@ -238,9 +250,8 @@ func TestEth2NewBlock(t *testing.T) {
) )
parent = preMergeBlocks[len(preMergeBlocks)-1] parent = preMergeBlocks[len(preMergeBlocks)-1]
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
execData, err := api.assembleBlock(AssembleBlockParams{ execData, err := api.assembleBlock(parent.Hash(), &PayloadAttributesV1{
ParentHash: parent.Hash(), Timestamp: parent.Time() + 6,
Timestamp: parent.Time() + 6,
}) })
if err != nil { if err != nil {
t.Fatalf("Failed to create the executable data %v", err) t.Fatalf("Failed to create the executable data %v", err)
...@@ -249,7 +260,7 @@ func TestEth2NewBlock(t *testing.T) { ...@@ -249,7 +260,7 @@ func TestEth2NewBlock(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("Failed to convert executable data to block %v", err) t.Fatalf("Failed to convert executable data to block %v", err)
} }
newResp, err := api.ExecutePayload(*execData) newResp, err := api.ExecutePayloadV1(*execData)
if err != nil || newResp.Status != "VALID" { if err != nil || newResp.Status != "VALID" {
t.Fatalf("Failed to insert block: %v", err) t.Fatalf("Failed to insert block: %v", err)
} }
...@@ -257,10 +268,12 @@ func TestEth2NewBlock(t *testing.T) { ...@@ -257,10 +268,12 @@ func TestEth2NewBlock(t *testing.T) {
t.Fatalf("Chain head shouldn't be updated") t.Fatalf("Chain head shouldn't be updated")
} }
if err := api.ConsensusValidated(ConsensusValidatedParams{BlockHash: block.Hash(), Status: "VALID"}); err != nil { fcState := ForkchoiceStateV1{
t.Fatalf("Failed to insert block: %v", err) HeadBlockHash: block.Hash(),
SafeBlockHash: block.Hash(),
FinalizedBlockHash: block.Hash(),
} }
if err := api.ForkchoiceUpdated(ForkChoiceParams{FinalizedBlockHash: block.Hash(), HeadBlockHash: block.Hash()}); err != nil { if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil {
t.Fatalf("Failed to insert block: %v", err) t.Fatalf("Failed to insert block: %v", err)
} }
if ethservice.BlockChain().CurrentBlock().NumberU64() != block.NumberU64() { if ethservice.BlockChain().CurrentBlock().NumberU64() != block.NumberU64() {
...@@ -360,33 +373,41 @@ func TestFullAPI(t *testing.T) { ...@@ -360,33 +373,41 @@ func TestFullAPI(t *testing.T) {
tx, _ := types.SignTx(types.NewContractCreation(nonce, new(big.Int), 1000000, big.NewInt(2*params.InitialBaseFee), logCode), types.LatestSigner(ethservice.BlockChain().Config()), testKey) tx, _ := types.SignTx(types.NewContractCreation(nonce, new(big.Int), 1000000, big.NewInt(2*params.InitialBaseFee), logCode), types.LatestSigner(ethservice.BlockChain().Config()), testKey)
ethservice.TxPool().AddLocal(tx) ethservice.TxPool().AddLocal(tx)
params := AssembleBlockParams{ params := PayloadAttributesV1{
ParentHash: parent.Hash(),
Timestamp: parent.Time() + 1, Timestamp: parent.Time() + 1,
Random: crypto.Keccak256Hash([]byte{byte(i)}), Random: crypto.Keccak256Hash([]byte{byte(i)}),
FeeRecipient: parent.Coinbase(), FeeRecipient: parent.Coinbase(),
} }
resp, err := api.PreparePayload(params) fcState := ForkchoiceStateV1{
HeadBlockHash: parent.Hash(),
SafeBlockHash: common.Hash{},
FinalizedBlockHash: common.Hash{},
}
resp, err := api.ForkchoiceUpdatedV1(fcState, &params)
if err != nil { if err != nil {
t.Fatalf("can't prepare payload: %v", err) t.Fatalf("error preparing payload, err=%v", err)
}
if resp.Status != SUCCESS.Status {
t.Fatalf("error preparing payload, invalid status: %v", resp.Status)
} }
payload, err := api.GetPayload(hexutil.Uint64(resp.PayloadID)) payloadID := computePayloadId(parent.Hash(), &params)
payload, err := api.GetPayloadV1(hexutil.Bytes(payloadID))
if err != nil { if err != nil {
t.Fatalf("can't get payload: %v", err) t.Fatalf("can't get payload: %v", err)
} }
execResp, err := api.ExecutePayload(*payload) execResp, err := api.ExecutePayloadV1(*payload)
if err != nil { if err != nil {
t.Fatalf("can't execute payload: %v", err) t.Fatalf("can't execute payload: %v", err)
} }
if execResp.Status != VALID.Status { if execResp.Status != VALID.Status {
t.Fatalf("invalid status: %v", execResp.Status) t.Fatalf("invalid status: %v", execResp.Status)
} }
fcState = ForkchoiceStateV1{
if err := api.ConsensusValidated(ConsensusValidatedParams{BlockHash: payload.BlockHash, Status: VALID.Status}); err != nil { HeadBlockHash: payload.BlockHash,
t.Fatalf("failed to validate consensus: %v", err) SafeBlockHash: payload.ParentHash,
FinalizedBlockHash: payload.ParentHash,
} }
if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil {
if err := api.ForkchoiceUpdated(ForkChoiceParams{HeadBlockHash: payload.BlockHash, FinalizedBlockHash: payload.BlockHash}); err != nil {
t.Fatalf("Failed to insert block: %v", err) t.Fatalf("Failed to insert block: %v", err)
} }
if ethservice.BlockChain().CurrentBlock().NumberU64() != payload.Number { if ethservice.BlockChain().CurrentBlock().NumberU64() != payload.Number {
......
...@@ -23,26 +23,24 @@ import ( ...@@ -23,26 +23,24 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
) )
//go:generate go run github.com/fjl/gencodec -type AssembleBlockParams -field-override assembleBlockParamsMarshaling -out gen_blockparams.go //go:generate go run github.com/fjl/gencodec -type PayloadAttributesV1 -field-override payloadAttributesMarshaling -out gen_blockparams.go
// Structure described at https://github.com/ethereum/execution-apis/pull/74 // Structure described at https://github.com/ethereum/execution-apis/pull/74
type AssembleBlockParams struct { type PayloadAttributesV1 struct {
ParentHash common.Hash `json:"parentHash" gencodec:"required"`
Timestamp uint64 `json:"timestamp" gencodec:"required"` Timestamp uint64 `json:"timestamp" gencodec:"required"`
Random common.Hash `json:"random" gencodec:"required"` Random common.Hash `json:"random" gencodec:"required"`
FeeRecipient common.Address `json:"feeRecipient" gencodec:"required"` FeeRecipient common.Address `json:"feeRecipient" gencodec:"required"`
} }
// JSON type overrides for assembleBlockParams. // JSON type overrides for PayloadAttributesV1.
type assembleBlockParamsMarshaling struct { type payloadAttributesMarshaling struct {
Timestamp hexutil.Uint64 Timestamp hexutil.Uint64
} }
//go:generate go run github.com/fjl/gencodec -type ExecutableData -field-override executableDataMarshaling -out gen_ed.go //go:generate go run github.com/fjl/gencodec -type ExecutableDataV1 -field-override executableDataMarshaling -out gen_ed.go
// Structure described at https://github.com/ethereum/execution-apis/pull/74/files // Structure described at https://github.com/ethereum/execution-apis/src/engine/specification.md
type ExecutableData struct { type ExecutableDataV1 struct {
BlockHash common.Hash `json:"blockHash" gencodec:"required"`
ParentHash common.Hash `json:"parentHash" gencodec:"required"` ParentHash common.Hash `json:"parentHash" gencodec:"required"`
Coinbase common.Address `json:"coinbase" gencodec:"required"` Coinbase common.Address `json:"coinbase" gencodec:"required"`
StateRoot common.Hash `json:"stateRoot" gencodec:"required"` StateRoot common.Hash `json:"stateRoot" gencodec:"required"`
...@@ -55,6 +53,7 @@ type ExecutableData struct { ...@@ -55,6 +53,7 @@ type ExecutableData struct {
Timestamp uint64 `json:"timestamp" gencodec:"required"` Timestamp uint64 `json:"timestamp" gencodec:"required"`
ExtraData []byte `json:"extraData" gencodec:"required"` ExtraData []byte `json:"extraData" gencodec:"required"`
BaseFeePerGas *big.Int `json:"baseFeePerGas" gencodec:"required"` BaseFeePerGas *big.Int `json:"baseFeePerGas" gencodec:"required"`
BlockHash common.Hash `json:"blockHash" gencodec:"required"`
Transactions [][]byte `json:"transactions" gencodec:"required"` Transactions [][]byte `json:"transactions" gencodec:"required"`
} }
...@@ -93,12 +92,23 @@ type GenericStringResponse struct { ...@@ -93,12 +92,23 @@ type GenericStringResponse struct {
Status string `json:"status"` Status string `json:"status"`
} }
type ExecutePayloadResponse struct {
Status string `json:"status"`
LatestValidHash common.Hash `json:"latestValidHash"`
}
type ConsensusValidatedParams struct { type ConsensusValidatedParams struct {
BlockHash common.Hash `json:"blockHash"` BlockHash common.Hash `json:"blockHash"`
Status string `json:"status"` Status string `json:"status"`
} }
type ForkChoiceParams struct { type ForkChoiceResponse struct {
Status string `json:"status"`
PayloadID *hexutil.Bytes `json:"payloadId"`
}
type ForkchoiceStateV1 struct {
HeadBlockHash common.Hash `json:"headBlockHash"` HeadBlockHash common.Hash `json:"headBlockHash"`
SafeBlockHash common.Hash `json:"safeBlockHash"`
FinalizedBlockHash common.Hash `json:"finalizedBlockHash"` FinalizedBlockHash common.Hash `json:"finalizedBlockHash"`
} }
...@@ -10,51 +10,44 @@ import ( ...@@ -10,51 +10,44 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
) )
var _ = (*assembleBlockParamsMarshaling)(nil) var _ = (*payloadAttributesMarshaling)(nil)
// MarshalJSON marshals as JSON. // MarshalJSON marshals as JSON.
func (a AssembleBlockParams) MarshalJSON() ([]byte, error) { func (p PayloadAttributesV1) MarshalJSON() ([]byte, error) {
type AssembleBlockParams struct { type PayloadAttributesV1 struct {
ParentHash common.Hash `json:"parentHash" gencodec:"required"`
Timestamp hexutil.Uint64 `json:"timestamp" gencodec:"required"` Timestamp hexutil.Uint64 `json:"timestamp" gencodec:"required"`
Random common.Hash `json:"random" gencodec:"required"` Random common.Hash `json:"random" gencodec:"required"`
FeeRecipient common.Address `json:"feeRecipient" gencodec:"required"` FeeRecipient common.Address `json:"feeRecipient" gencodec:"required"`
} }
var enc AssembleBlockParams var enc PayloadAttributesV1
enc.ParentHash = a.ParentHash enc.Timestamp = hexutil.Uint64(p.Timestamp)
enc.Timestamp = hexutil.Uint64(a.Timestamp) enc.Random = p.Random
enc.Random = a.Random enc.FeeRecipient = p.FeeRecipient
enc.FeeRecipient = a.FeeRecipient
return json.Marshal(&enc) return json.Marshal(&enc)
} }
// UnmarshalJSON unmarshals from JSON. // UnmarshalJSON unmarshals from JSON.
func (a *AssembleBlockParams) UnmarshalJSON(input []byte) error { func (p *PayloadAttributesV1) UnmarshalJSON(input []byte) error {
type AssembleBlockParams struct { type PayloadAttributesV1 struct {
ParentHash *common.Hash `json:"parentHash" gencodec:"required"`
Timestamp *hexutil.Uint64 `json:"timestamp" gencodec:"required"` Timestamp *hexutil.Uint64 `json:"timestamp" gencodec:"required"`
Random *common.Hash `json:"random" gencodec:"required"` Random *common.Hash `json:"random" gencodec:"required"`
FeeRecipient *common.Address `json:"feeRecipient" gencodec:"required"` FeeRecipient *common.Address `json:"feeRecipient" gencodec:"required"`
} }
var dec AssembleBlockParams var dec PayloadAttributesV1
if err := json.Unmarshal(input, &dec); err != nil { if err := json.Unmarshal(input, &dec); err != nil {
return err return err
} }
if dec.ParentHash == nil {
return errors.New("missing required field 'parentHash' for AssembleBlockParams")
}
a.ParentHash = *dec.ParentHash
if dec.Timestamp == nil { if dec.Timestamp == nil {
return errors.New("missing required field 'timestamp' for AssembleBlockParams") return errors.New("missing required field 'timestamp' for PayloadAttributesV1")
} }
a.Timestamp = uint64(*dec.Timestamp) p.Timestamp = uint64(*dec.Timestamp)
if dec.Random == nil { if dec.Random == nil {
return errors.New("missing required field 'random' for AssembleBlockParams") return errors.New("missing required field 'random' for PayloadAttributesV1")
} }
a.Random = *dec.Random p.Random = *dec.Random
if dec.FeeRecipient == nil { if dec.FeeRecipient == nil {
return errors.New("missing required field 'feeRecipient' for AssembleBlockParams") return errors.New("missing required field 'feeRecipient' for PayloadAttributesV1")
} }
a.FeeRecipient = *dec.FeeRecipient p.FeeRecipient = *dec.FeeRecipient
return nil return nil
} }
...@@ -14,9 +14,8 @@ import ( ...@@ -14,9 +14,8 @@ import (
var _ = (*executableDataMarshaling)(nil) var _ = (*executableDataMarshaling)(nil)
// MarshalJSON marshals as JSON. // MarshalJSON marshals as JSON.
func (e ExecutableData) MarshalJSON() ([]byte, error) { func (e ExecutableDataV1) MarshalJSON() ([]byte, error) {
type ExecutableData struct { type ExecutableDataV1 struct {
BlockHash common.Hash `json:"blockHash" gencodec:"required"`
ParentHash common.Hash `json:"parentHash" gencodec:"required"` ParentHash common.Hash `json:"parentHash" gencodec:"required"`
Coinbase common.Address `json:"coinbase" gencodec:"required"` Coinbase common.Address `json:"coinbase" gencodec:"required"`
StateRoot common.Hash `json:"stateRoot" gencodec:"required"` StateRoot common.Hash `json:"stateRoot" gencodec:"required"`
...@@ -29,10 +28,10 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) { ...@@ -29,10 +28,10 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) {
Timestamp hexutil.Uint64 `json:"timestamp" gencodec:"required"` Timestamp hexutil.Uint64 `json:"timestamp" gencodec:"required"`
ExtraData hexutil.Bytes `json:"extraData" gencodec:"required"` ExtraData hexutil.Bytes `json:"extraData" gencodec:"required"`
BaseFeePerGas *hexutil.Big `json:"baseFeePerGas" gencodec:"required"` BaseFeePerGas *hexutil.Big `json:"baseFeePerGas" gencodec:"required"`
BlockHash common.Hash `json:"blockHash" gencodec:"required"`
Transactions []hexutil.Bytes `json:"transactions" gencodec:"required"` Transactions []hexutil.Bytes `json:"transactions" gencodec:"required"`
} }
var enc ExecutableData var enc ExecutableDataV1
enc.BlockHash = e.BlockHash
enc.ParentHash = e.ParentHash enc.ParentHash = e.ParentHash
enc.Coinbase = e.Coinbase enc.Coinbase = e.Coinbase
enc.StateRoot = e.StateRoot enc.StateRoot = e.StateRoot
...@@ -45,6 +44,7 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) { ...@@ -45,6 +44,7 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) {
enc.Timestamp = hexutil.Uint64(e.Timestamp) enc.Timestamp = hexutil.Uint64(e.Timestamp)
enc.ExtraData = e.ExtraData enc.ExtraData = e.ExtraData
enc.BaseFeePerGas = (*hexutil.Big)(e.BaseFeePerGas) enc.BaseFeePerGas = (*hexutil.Big)(e.BaseFeePerGas)
enc.BlockHash = e.BlockHash
if e.Transactions != nil { if e.Transactions != nil {
enc.Transactions = make([]hexutil.Bytes, len(e.Transactions)) enc.Transactions = make([]hexutil.Bytes, len(e.Transactions))
for k, v := range e.Transactions { for k, v := range e.Transactions {
...@@ -55,9 +55,8 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) { ...@@ -55,9 +55,8 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) {
} }
// UnmarshalJSON unmarshals from JSON. // UnmarshalJSON unmarshals from JSON.
func (e *ExecutableData) UnmarshalJSON(input []byte) error { func (e *ExecutableDataV1) UnmarshalJSON(input []byte) error {
type ExecutableData struct { type ExecutableDataV1 struct {
BlockHash *common.Hash `json:"blockHash" gencodec:"required"`
ParentHash *common.Hash `json:"parentHash" gencodec:"required"` ParentHash *common.Hash `json:"parentHash" gencodec:"required"`
Coinbase *common.Address `json:"coinbase" gencodec:"required"` Coinbase *common.Address `json:"coinbase" gencodec:"required"`
StateRoot *common.Hash `json:"stateRoot" gencodec:"required"` StateRoot *common.Hash `json:"stateRoot" gencodec:"required"`
...@@ -70,66 +69,67 @@ func (e *ExecutableData) UnmarshalJSON(input []byte) error { ...@@ -70,66 +69,67 @@ func (e *ExecutableData) UnmarshalJSON(input []byte) error {
Timestamp *hexutil.Uint64 `json:"timestamp" gencodec:"required"` Timestamp *hexutil.Uint64 `json:"timestamp" gencodec:"required"`
ExtraData *hexutil.Bytes `json:"extraData" gencodec:"required"` ExtraData *hexutil.Bytes `json:"extraData" gencodec:"required"`
BaseFeePerGas *hexutil.Big `json:"baseFeePerGas" gencodec:"required"` BaseFeePerGas *hexutil.Big `json:"baseFeePerGas" gencodec:"required"`
BlockHash *common.Hash `json:"blockHash" gencodec:"required"`
Transactions []hexutil.Bytes `json:"transactions" gencodec:"required"` Transactions []hexutil.Bytes `json:"transactions" gencodec:"required"`
} }
var dec ExecutableData var dec ExecutableDataV1
if err := json.Unmarshal(input, &dec); err != nil { if err := json.Unmarshal(input, &dec); err != nil {
return err return err
} }
if dec.BlockHash == nil {
return errors.New("missing required field 'blockHash' for ExecutableData")
}
e.BlockHash = *dec.BlockHash
if dec.ParentHash == nil { if dec.ParentHash == nil {
return errors.New("missing required field 'parentHash' for ExecutableData") return errors.New("missing required field 'parentHash' for ExecutableDataV1")
} }
e.ParentHash = *dec.ParentHash e.ParentHash = *dec.ParentHash
if dec.Coinbase == nil { if dec.Coinbase == nil {
return errors.New("missing required field 'coinbase' for ExecutableData") return errors.New("missing required field 'coinbase' for ExecutableDataV1")
} }
e.Coinbase = *dec.Coinbase e.Coinbase = *dec.Coinbase
if dec.StateRoot == nil { if dec.StateRoot == nil {
return errors.New("missing required field 'stateRoot' for ExecutableData") return errors.New("missing required field 'stateRoot' for ExecutableDataV1")
} }
e.StateRoot = *dec.StateRoot e.StateRoot = *dec.StateRoot
if dec.ReceiptRoot == nil { if dec.ReceiptRoot == nil {
return errors.New("missing required field 'receiptRoot' for ExecutableData") return errors.New("missing required field 'receiptRoot' for ExecutableDataV1")
} }
e.ReceiptRoot = *dec.ReceiptRoot e.ReceiptRoot = *dec.ReceiptRoot
if dec.LogsBloom == nil { if dec.LogsBloom == nil {
return errors.New("missing required field 'logsBloom' for ExecutableData") return errors.New("missing required field 'logsBloom' for ExecutableDataV1")
} }
e.LogsBloom = *dec.LogsBloom e.LogsBloom = *dec.LogsBloom
if dec.Random == nil { if dec.Random == nil {
return errors.New("missing required field 'random' for ExecutableData") return errors.New("missing required field 'random' for ExecutableDataV1")
} }
e.Random = *dec.Random e.Random = *dec.Random
if dec.Number == nil { if dec.Number == nil {
return errors.New("missing required field 'blockNumber' for ExecutableData") return errors.New("missing required field 'blockNumber' for ExecutableDataV1")
} }
e.Number = uint64(*dec.Number) e.Number = uint64(*dec.Number)
if dec.GasLimit == nil { if dec.GasLimit == nil {
return errors.New("missing required field 'gasLimit' for ExecutableData") return errors.New("missing required field 'gasLimit' for ExecutableDataV1")
} }
e.GasLimit = uint64(*dec.GasLimit) e.GasLimit = uint64(*dec.GasLimit)
if dec.GasUsed == nil { if dec.GasUsed == nil {
return errors.New("missing required field 'gasUsed' for ExecutableData") return errors.New("missing required field 'gasUsed' for ExecutableDataV1")
} }
e.GasUsed = uint64(*dec.GasUsed) e.GasUsed = uint64(*dec.GasUsed)
if dec.Timestamp == nil { if dec.Timestamp == nil {
return errors.New("missing required field 'timestamp' for ExecutableData") return errors.New("missing required field 'timestamp' for ExecutableDataV1")
} }
e.Timestamp = uint64(*dec.Timestamp) e.Timestamp = uint64(*dec.Timestamp)
if dec.ExtraData == nil { if dec.ExtraData == nil {
return errors.New("missing required field 'extraData' for ExecutableData") return errors.New("missing required field 'extraData' for ExecutableDataV1")
} }
e.ExtraData = *dec.ExtraData e.ExtraData = *dec.ExtraData
if dec.BaseFeePerGas == nil { if dec.BaseFeePerGas == nil {
return errors.New("missing required field 'baseFeePerGas' for ExecutableData") return errors.New("missing required field 'baseFeePerGas' for ExecutableDataV1")
} }
e.BaseFeePerGas = (*big.Int)(dec.BaseFeePerGas) e.BaseFeePerGas = (*big.Int)(dec.BaseFeePerGas)
if dec.BlockHash == nil {
return errors.New("missing required field 'blockHash' for ExecutableDataV1")
}
e.BlockHash = *dec.BlockHash
if dec.Transactions == nil { if dec.Transactions == nil {
return errors.New("missing required field 'transactions' for ExecutableData") return errors.New("missing required field 'transactions' for ExecutableDataV1")
} }
e.Transactions = make([][]byte, len(dec.Transactions)) e.Transactions = make([][]byte, len(dec.Transactions))
for k, v := range dec.Transactions { for k, v := range dec.Transactions {
......
...@@ -30,7 +30,6 @@ import ( ...@@ -30,7 +30,6 @@ import (
"github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/fdlimit" "github.com/ethereum/go-ethereum/common/fdlimit"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
...@@ -138,25 +137,30 @@ func newNode(typ nodetype, genesis *core.Genesis, enodes []*enode.Node) *ethNode ...@@ -138,25 +137,30 @@ func newNode(typ nodetype, genesis *core.Genesis, enodes []*enode.Node) *ethNode
} }
} }
func (n *ethNode) assembleBlock(parentHash common.Hash, parentTimestamp uint64) (*catalyst.ExecutableData, error) { func (n *ethNode) assembleBlock(parentHash common.Hash, parentTimestamp uint64) (*catalyst.ExecutableDataV1, error) {
if n.typ != eth2MiningNode { if n.typ != eth2MiningNode {
return nil, errors.New("invalid node type") return nil, errors.New("invalid node type")
} }
payload, err := n.api.PreparePayload(catalyst.AssembleBlockParams{ payloadAttribute := catalyst.PayloadAttributesV1{
ParentHash: parentHash, Timestamp: uint64(time.Now().Unix()),
Timestamp: uint64(time.Now().Unix()), }
}) fcState := catalyst.ForkchoiceStateV1{
HeadBlockHash: parentHash,
SafeBlockHash: common.Hash{},
FinalizedBlockHash: common.Hash{},
}
payload, err := n.api.ForkchoiceUpdatedV1(fcState, &payloadAttribute)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return n.api.GetPayload(hexutil.Uint64(payload.PayloadID)) return n.api.GetPayloadV1(*payload.PayloadID)
} }
func (n *ethNode) insertBlock(eb catalyst.ExecutableData) error { func (n *ethNode) insertBlock(eb catalyst.ExecutableDataV1) error {
if !eth2types(n.typ) { if !eth2types(n.typ) {
return errors.New("invalid node type") return errors.New("invalid node type")
} }
newResp, err := n.api.ExecutePayload(eb) newResp, err := n.api.ExecutePayloadV1(eb)
if err != nil { if err != nil {
return err return err
} else if newResp.Status != "VALID" { } else if newResp.Status != "VALID" {
...@@ -165,7 +169,7 @@ func (n *ethNode) insertBlock(eb catalyst.ExecutableData) error { ...@@ -165,7 +169,7 @@ func (n *ethNode) insertBlock(eb catalyst.ExecutableData) error {
return nil return nil
} }
func (n *ethNode) insertBlockAndSetHead(parent *types.Header, ed catalyst.ExecutableData) error { func (n *ethNode) insertBlockAndSetHead(parent *types.Header, ed catalyst.ExecutableDataV1) error {
if !eth2types(n.typ) { if !eth2types(n.typ) {
return errors.New("invalid node type") return errors.New("invalid node type")
} }
...@@ -176,7 +180,12 @@ func (n *ethNode) insertBlockAndSetHead(parent *types.Header, ed catalyst.Execut ...@@ -176,7 +180,12 @@ func (n *ethNode) insertBlockAndSetHead(parent *types.Header, ed catalyst.Execut
if err != nil { if err != nil {
return err return err
} }
if err := n.api.ConsensusValidated(catalyst.ConsensusValidatedParams{BlockHash: block.Hash(), Status: "VALID"}); err != nil { fcState := catalyst.ForkchoiceStateV1{
HeadBlockHash: block.ParentHash(),
SafeBlockHash: common.Hash{},
FinalizedBlockHash: common.Hash{},
}
if _, err := n.api.ForkchoiceUpdatedV1(fcState, nil); err != nil {
return err return err
} }
return nil return nil
...@@ -275,7 +284,12 @@ func (mgr *nodeManager) run() { ...@@ -275,7 +284,12 @@ func (mgr *nodeManager) run() {
nodes = append(nodes, mgr.getNodes(eth2NormalNode)...) nodes = append(nodes, mgr.getNodes(eth2NormalNode)...)
nodes = append(nodes, mgr.getNodes(eth2LightClient)...) nodes = append(nodes, mgr.getNodes(eth2LightClient)...)
for _, node := range append(nodes) { for _, node := range append(nodes) {
node.api.ConsensusValidated(catalyst.ConsensusValidatedParams{BlockHash: oldest.Hash(), Status: catalyst.VALID.Status}) fcState := catalyst.ForkchoiceStateV1{
HeadBlockHash: oldest.Hash(),
SafeBlockHash: common.Hash{},
FinalizedBlockHash: common.Hash{},
}
node.api.ForkchoiceUpdatedV1(fcState, nil)
} }
log.Info("Finalised eth2 block", "number", oldest.NumberU64(), "hash", oldest.Hash()) log.Info("Finalised eth2 block", "number", oldest.NumberU64(), "hash", oldest.Hash())
waitFinalise = waitFinalise[1:] waitFinalise = waitFinalise[1:]
......
...@@ -1040,7 +1040,13 @@ func (w *worker) commit(uncles []*types.Header, interval func(), update bool, st ...@@ -1040,7 +1040,13 @@ func (w *worker) commit(uncles []*types.Header, interval func(), update bool, st
return err return err
} }
if w.isRunning() && !w.merger.TDDReached() { // If we're post merge, just ignore
td, ttd := w.chain.GetTd(block.ParentHash(), block.NumberU64()-1), w.chain.Config().TerminalTotalDifficulty
if td != nil && ttd != nil && td.Cmp(ttd) >= 0 {
return nil
}
if w.isRunning() {
if interval != nil { if interval != nil {
interval() interval()
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment