eth/catalyst: error on nil withdrawals post-shanghai (#26549)
This adds explicit checks for the presence of withdrawals in the engine API. Co-authored-by: Felix Lange <fjl@twurst.com>
This commit is contained in:
parent
55f41d198c
commit
245cff0a1a
@ -164,6 +164,18 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV1(update beacon.ForkchoiceStateV1, pa
|
||||
|
||||
// ForkchoiceUpdatedV2 is equivalent to V1 with the addition of withdrawals in the payload attributes.
|
||||
func (api *ConsensusAPI) ForkchoiceUpdatedV2(update beacon.ForkchoiceStateV1, payloadAttributes *beacon.PayloadAttributes) (beacon.ForkChoiceResponse, error) {
|
||||
if !api.eth.BlockChain().Config().IsShanghai(payloadAttributes.Timestamp) {
|
||||
// Reject payload attributes with withdrawals before shanghai
|
||||
if payloadAttributes != nil && payloadAttributes.Withdrawals != nil {
|
||||
return beacon.STATUS_INVALID, beacon.InvalidPayloadAttributes.With(errors.New("withdrawals before shanghai"))
|
||||
}
|
||||
} else {
|
||||
// Reject payload attributes with nil withdrawals after shanghai
|
||||
if payloadAttributes != nil && payloadAttributes.Withdrawals == nil {
|
||||
return beacon.STATUS_INVALID, beacon.InvalidPayloadAttributes.With(errors.New("missing withdrawals list"))
|
||||
}
|
||||
}
|
||||
|
||||
return api.forkchoiceUpdated(update, payloadAttributes)
|
||||
}
|
||||
|
||||
|
@ -1113,3 +1113,115 @@ func TestWithdrawals(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNilWithdrawals(t *testing.T) {
|
||||
genesis, blocks := generateMergeChain(10, true)
|
||||
// Set shanghai time to last block + 4 seconds (first post-merge block)
|
||||
time := blocks[len(blocks)-1].Time() + 4
|
||||
genesis.Config.ShanghaiTime = &time
|
||||
|
||||
n, ethservice := startEthService(t, genesis, blocks)
|
||||
ethservice.Merger().ReachTTD()
|
||||
defer n.Close()
|
||||
|
||||
api := NewConsensusAPI(ethservice)
|
||||
parent := ethservice.BlockChain().CurrentHeader()
|
||||
aa := common.Address{0xaa}
|
||||
|
||||
type test struct {
|
||||
blockParams beacon.PayloadAttributes
|
||||
wantErr bool
|
||||
}
|
||||
tests := []test{
|
||||
// Before Shanghai
|
||||
{
|
||||
blockParams: beacon.PayloadAttributes{
|
||||
Timestamp: parent.Time + 2,
|
||||
Withdrawals: nil,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
blockParams: beacon.PayloadAttributes{
|
||||
Timestamp: parent.Time + 2,
|
||||
Withdrawals: make([]*types.Withdrawal, 0),
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
blockParams: beacon.PayloadAttributes{
|
||||
Timestamp: parent.Time + 2,
|
||||
Withdrawals: []*types.Withdrawal{
|
||||
{
|
||||
Index: 0,
|
||||
Address: aa,
|
||||
Amount: 32,
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
// After Shanghai
|
||||
{
|
||||
blockParams: beacon.PayloadAttributes{
|
||||
Timestamp: parent.Time + 5,
|
||||
Withdrawals: nil,
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
blockParams: beacon.PayloadAttributes{
|
||||
Timestamp: parent.Time + 5,
|
||||
Withdrawals: make([]*types.Withdrawal, 0),
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
blockParams: beacon.PayloadAttributes{
|
||||
Timestamp: parent.Time + 5,
|
||||
Withdrawals: []*types.Withdrawal{
|
||||
{
|
||||
Index: 0,
|
||||
Address: aa,
|
||||
Amount: 32,
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
fcState := beacon.ForkchoiceStateV1{
|
||||
HeadBlockHash: parent.Hash(),
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
_, err := api.ForkchoiceUpdatedV2(fcState, &test.blockParams)
|
||||
if test.wantErr {
|
||||
if err == nil {
|
||||
t.Fatal("wanted error on fcuv2 with invalid withdrawals")
|
||||
}
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("error preparing payload, err=%v", err)
|
||||
}
|
||||
|
||||
// 11: verify locally build block.
|
||||
payloadID := (&miner.BuildPayloadArgs{
|
||||
Parent: fcState.HeadBlockHash,
|
||||
Timestamp: test.blockParams.Timestamp,
|
||||
FeeRecipient: test.blockParams.SuggestedFeeRecipient,
|
||||
Random: test.blockParams.Random,
|
||||
}).Id()
|
||||
execData, err := api.GetPayloadV2(payloadID)
|
||||
if err != nil {
|
||||
t.Fatalf("error getting payload, err=%v", err)
|
||||
}
|
||||
if status, err := api.NewPayloadV2(*execData.ExecutionPayload); err != nil {
|
||||
t.Fatalf("error validating payload: %v", err)
|
||||
} else if status.Status != beacon.VALID {
|
||||
t.Fatalf("invalid payload")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user