diff --git a/beacon-chain/blockchain/process_block.go b/beacon-chain/blockchain/process_block.go index 968b9af1ee..2a3bbccda0 100644 --- a/beacon-chain/blockchain/process_block.go +++ b/beacon-chain/blockchain/process_block.go @@ -605,11 +605,16 @@ func (s *Service) validateMergeTransitionBlock(ctx context.Context, stateVersion } // Skip validation if the block is not a merge transition block. - atTransition, err := blocks.IsMergeTransitionBlockUsingPreStatePayloadHeader(stateHeader, blk.Block().Body()) + // To reach here. The payload must be non-empty. If the state header is empty then it's at transition. + wh, err := wrapper.WrappedExecutionPayloadHeader(stateHeader) if err != nil { - return errors.Wrap(err, "could not check if merge block is terminal") + return err } - if !atTransition { + empty, err := wrapper.IsEmptyExecutionData(wh) + if err != nil { + return err + } + if !empty { return nil } return s.validateMergeBlock(ctx, blk) diff --git a/beacon-chain/blockchain/process_block_test.go b/beacon-chain/blockchain/process_block_test.go index f89c5d7bec..5dbe3ebb59 100644 --- a/beacon-chain/blockchain/process_block_test.go +++ b/beacon-chain/blockchain/process_block_test.go @@ -1622,7 +1622,7 @@ func Test_validateMergeTransitionBlock(t *testing.T) { payload: &enginev1.ExecutionPayload{ ParentHash: aHash[:], }, - errString: "nil header or block body", + errString: "attempted to wrap nil object", }, } for _, tt := range tests { diff --git a/beacon-chain/core/blocks/payload.go b/beacon-chain/core/blocks/payload.go index 821cb538f0..627621edca 100644 --- a/beacon-chain/core/blocks/payload.go +++ b/beacon-chain/core/blocks/payload.go @@ -49,27 +49,6 @@ func IsMergeTransitionComplete(st state.BeaconState) (bool, error) { return !isEmpty, nil } -// IsMergeTransitionBlockUsingPreStatePayloadHeader returns true if the input block is the terminal merge block. -// Terminal merge block must be associated with an empty payload header. -// This assumes the header `h` is referenced as the parent state for block body `body. -func IsMergeTransitionBlockUsingPreStatePayloadHeader(h *enginev1.ExecutionPayloadHeader, body interfaces.BeaconBlockBody) (bool, error) { - if h == nil || body == nil { - return false, errors.New("nil header or block body") - } - wrappedHeader, err := wrapper.WrappedExecutionPayloadHeader(h) - if err != nil { - return false, err - } - isEmpty, err := wrapper.IsEmptyExecutionData(wrappedHeader) - if err != nil { - return false, err - } - if !isEmpty { - return false, nil - } - return IsExecutionBlock(body) -} - // IsExecutionBlock returns whether the block has a non-empty ExecutionPayload. // // Spec code: diff --git a/beacon-chain/core/blocks/payload_test.go b/beacon-chain/core/blocks/payload_test.go index 570adb76b1..cc2aad8043 100644 --- a/beacon-chain/core/blocks/payload_test.go +++ b/beacon-chain/core/blocks/payload_test.go @@ -171,185 +171,6 @@ func Test_IsMergeComplete(t *testing.T) { } } -func Test_IsMergeTransitionBlockUsingPayloadHeader(t *testing.T) { - tests := []struct { - name string - payload *enginev1.ExecutionPayload - header *enginev1.ExecutionPayloadHeader - want bool - }{ - { - name: "empty header, empty payload", - payload: emptyPayload(), - header: emptyPayloadHeader(), - want: false, - }, - { - name: "non-empty header, empty payload", - payload: emptyPayload(), - header: func() *enginev1.ExecutionPayloadHeader { - h := emptyPayloadHeader() - h.ParentHash = bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength) - return h - }(), - want: false, - }, - { - name: "empty header, payload has parent hash", - payload: func() *enginev1.ExecutionPayload { - p := emptyPayload() - p.ParentHash = bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength) - return p - }(), - header: emptyPayloadHeader(), - want: true, - }, - { - name: "empty header, payload has fee recipient", - payload: func() *enginev1.ExecutionPayload { - p := emptyPayload() - p.FeeRecipient = bytesutil.PadTo([]byte{'a'}, fieldparams.FeeRecipientLength) - return p - }(), - header: emptyPayloadHeader(), - want: true, - }, - { - name: "empty header, payload has state root", - payload: func() *enginev1.ExecutionPayload { - p := emptyPayload() - p.StateRoot = bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength) - return p - }(), - header: emptyPayloadHeader(), - want: true, - }, - { - name: "empty header, payload has receipt root", - payload: func() *enginev1.ExecutionPayload { - p := emptyPayload() - p.ReceiptsRoot = bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength) - return p - }(), - header: emptyPayloadHeader(), - want: true, - }, - { - name: "empty header, payload has logs bloom", - payload: func() *enginev1.ExecutionPayload { - p := emptyPayload() - p.LogsBloom = bytesutil.PadTo([]byte{'a'}, fieldparams.LogsBloomLength) - return p - }(), - header: emptyPayloadHeader(), - want: true, - }, - { - name: "empty header, payload has random", - payload: func() *enginev1.ExecutionPayload { - p := emptyPayload() - p.PrevRandao = bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength) - return p - }(), - header: emptyPayloadHeader(), - want: true, - }, - { - name: "empty header, payload has base fee", - payload: func() *enginev1.ExecutionPayload { - p := emptyPayload() - p.BaseFeePerGas = bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength) - return p - }(), - header: emptyPayloadHeader(), - want: true, - }, - { - name: "empty header, payload has block hash", - payload: func() *enginev1.ExecutionPayload { - p := emptyPayload() - p.BlockHash = bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength) - return p - }(), - header: emptyPayloadHeader(), - want: true, - }, - { - name: "empty header, payload has tx", - payload: func() *enginev1.ExecutionPayload { - p := emptyPayload() - p.Transactions = [][]byte{{'a'}} - return p - }(), - header: emptyPayloadHeader(), - want: true, - }, - { - name: "empty header, payload has extra data", - payload: func() *enginev1.ExecutionPayload { - p := emptyPayload() - p.ExtraData = bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength) - return p - }(), - header: emptyPayloadHeader(), - want: true, - }, - { - name: "empty header, payload has block number", - payload: func() *enginev1.ExecutionPayload { - p := emptyPayload() - p.BlockNumber = 1 - return p - }(), - header: emptyPayloadHeader(), - want: true, - }, - { - name: "empty header, payload has gas limit", - payload: func() *enginev1.ExecutionPayload { - p := emptyPayload() - p.GasLimit = 1 - return p - }(), - header: emptyPayloadHeader(), - want: true, - }, - { - name: "empty header, payload has gas used", - payload: func() *enginev1.ExecutionPayload { - p := emptyPayload() - p.GasUsed = 1 - return p - }(), - header: emptyPayloadHeader(), - want: true, - }, - { - name: "empty header, payload has timestamp", - payload: func() *enginev1.ExecutionPayload { - p := emptyPayload() - p.Timestamp = 1 - return p - }(), - header: emptyPayloadHeader(), - want: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - blk := util.NewBeaconBlockBellatrix() - blk.Block.Body.ExecutionPayload = tt.payload - body, err := wrapper.WrappedBeaconBlockBody(blk.Block.Body) - require.NoError(t, err) - got, err := blocks.IsMergeTransitionBlockUsingPreStatePayloadHeader(tt.header, body) - require.NoError(t, err) - if got != tt.want { - t.Errorf("MergeTransitionBlock() got = %v, want %v", got, tt.want) - } - }) - } -} - func Test_IsExecutionBlock(t *testing.T) { tests := []struct { name string