From 2e7acc5db7df9a670f0e7d62c9cf60f6db9f115d Mon Sep 17 00:00:00 2001 From: rupam-04 Date: Sun, 8 Sep 2024 19:28:15 +0530 Subject: [PATCH 01/12] implement `block_to_light_client_header` upto Deneb --- beacon-chain/rpc/eth/light-client/helpers.go | 218 +++++++++++++++++++ 1 file changed, 218 insertions(+) diff --git a/beacon-chain/rpc/eth/light-client/helpers.go b/beacon-chain/rpc/eth/light-client/helpers.go index aa5f8a6b81d..6e2c30f60dc 100644 --- a/beacon-chain/rpc/eth/light-client/helpers.go +++ b/beacon-chain/rpc/eth/light-client/helpers.go @@ -651,3 +651,221 @@ func IsBetterUpdate(newUpdate, oldUpdate *v2.LightClientUpdate) (bool, error) { } return newUpdate.SignatureSlot < oldUpdate.SignatureSlot, nil } + +func BlockToLightClientHeaderAltair(block interfaces.ReadOnlySignedBeaconBlock) (*structs.LightClientHeader, error) { + parentRootArray := block.Block().ParentRoot() + parentRoot := parentRootArray[:] + + stateRootArray := block.Block().StateRoot() + stateRoot := stateRootArray[:] + + bodyRootArray, err := block.Block().Body().HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "could not get body root") + } + bodyRoot := bodyRootArray[:] + + return &structs.LightClientHeader{ + Beacon: &structs.BeaconBlockHeader{ + Slot: hexutil.EncodeUint64(uint64(block.Block().Slot())), + ProposerIndex: hexutil.EncodeUint64(uint64(block.Block().ProposerIndex())), + ParentRoot: hexutil.Encode(parentRoot), + StateRoot: hexutil.Encode(stateRoot), + BodyRoot: hexutil.Encode(bodyRoot), + }, + }, nil +} + +func BlockToLightClientHeaderCapella(ctx context.Context, block interfaces.ReadOnlySignedBeaconBlock) (*structs.LightClientHeaderCapella, error) { + epoch := slots.ToEpoch(block.Block().Slot()) + if epoch < params.BeaconConfig().CapellaForkEpoch { + return nil, fmt.Errorf("creating Capella light client header is not supported before Capella, invalid slot %d", block.Block().Slot()) + } + + payload, err := block.Block().Body().Execution() + if err != nil { + return nil, errors.Wrap(err, "could not get execution payload") + } + + transactionsRoot, err := payload.TransactionsRoot() + if errors.Is(err, consensus_types.ErrUnsupportedField) { + transactions, err := payload.Transactions() + if err != nil { + return nil, errors.Wrap(err, "could not get transactions") + } + transactionsRootArray, err := ssz.TransactionsRoot(transactions) + if err != nil { + return nil, errors.Wrap(err, "could not get transactions root") + } + transactionsRoot = transactionsRootArray[:] + } else if err != nil { + return nil, errors.Wrap(err, "could not get transactions root") + } + withdrawalsRoot, err := payload.WithdrawalsRoot() + if errors.Is(err, consensus_types.ErrUnsupportedField) { + withdrawals, err := payload.Withdrawals() + if err != nil { + return nil, errors.Wrap(err, "could not get withdrawals") + } + withdrawalsRootArray, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload) + if err != nil { + return nil, errors.Wrap(err, "could not get withdrawals root") + } + withdrawalsRoot = withdrawalsRootArray[:] + } else if err != nil { + return nil, errors.Wrap(err, "could not get withdrawals root") + } + + executionHeader := &structs.ExecutionPayloadHeaderCapella{ + ParentHash: hexutil.Encode(payload.ParentHash()), + FeeRecipient: hexutil.Encode(payload.FeeRecipient()), + StateRoot: hexutil.Encode(payload.StateRoot()), + ReceiptsRoot: hexutil.Encode(payload.ReceiptsRoot()), + LogsBloom: hexutil.Encode(payload.LogsBloom()), + PrevRandao: hexutil.Encode(payload.PrevRandao()), + BlockNumber: hexutil.EncodeUint64(payload.BlockNumber()), + GasLimit: hexutil.EncodeUint64(payload.GasLimit()), + GasUsed: hexutil.EncodeUint64(payload.GasUsed()), + Timestamp: hexutil.EncodeUint64(payload.Timestamp()), + ExtraData: hexutil.Encode(payload.ExtraData()), + BaseFeePerGas: hexutil.Encode(payload.BaseFeePerGas()), + BlockHash: hexutil.Encode(payload.BlockHash()), + TransactionsRoot: hexutil.Encode(transactionsRoot), + WithdrawalsRoot: hexutil.Encode(withdrawalsRoot), + } + + executionPayloadProof, err := blocks.PayloadProof(ctx, block.Block()) + if err != nil { + return nil, errors.Wrap(err, "could not get execution payload proof") + } + executionPayloadProofStr := make([]string, len(executionPayloadProof)) + for i, proof := range executionPayloadProof { + executionPayloadProofStr[i] = hexutil.Encode(proof) + } + + parentRootArray := block.Block().ParentRoot() + parentRoot := parentRootArray[:] + + stateRootArray := block.Block().StateRoot() + stateRoot := stateRootArray[:] + + bodyRootArray, err := block.Block().Body().HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "could not get body root") + } + bodyRoot := bodyRootArray[:] + + return &structs.LightClientHeaderCapella{ + Beacon: &structs.BeaconBlockHeader{ + Slot: hexutil.EncodeUint64(uint64(block.Block().Slot())), + ProposerIndex: hexutil.EncodeUint64(uint64(block.Block().ProposerIndex())), + ParentRoot: hexutil.Encode(parentRoot), + StateRoot: hexutil.Encode(stateRoot), + BodyRoot: hexutil.Encode(bodyRoot), + }, + Execution: executionHeader, + ExecutionBranch: executionPayloadProofStr, + }, nil +} + +func BlockToLightClientHeaderDeneb(ctx context.Context, block interfaces.ReadOnlySignedBeaconBlock) (*structs.LightClientHeaderDeneb, error) { + epoch := slots.ToEpoch(block.Block().Slot()) + if epoch < params.BeaconConfig().DenebForkEpoch { + return nil, fmt.Errorf("creating Deneb light client header is not supported before Deneb, invalid slot %d", block.Block().Slot()) + } + + payload, err := block.Block().Body().Execution() + if err != nil { + return nil, errors.Wrap(err, "could not get execution payload") + } + + transactionsRoot, err := payload.TransactionsRoot() + if errors.Is(err, consensus_types.ErrUnsupportedField) { + transactions, err := payload.Transactions() + if err != nil { + return nil, errors.Wrap(err, "could not get transactions") + } + transactionsRootArray, err := ssz.TransactionsRoot(transactions) + if err != nil { + return nil, errors.Wrap(err, "could not get transactions root") + } + transactionsRoot = transactionsRootArray[:] + } else if err != nil { + return nil, errors.Wrap(err, "could not get transactions root") + } + withdrawalsRoot, err := payload.WithdrawalsRoot() + if errors.Is(err, consensus_types.ErrUnsupportedField) { + withdrawals, err := payload.Withdrawals() + if err != nil { + return nil, errors.Wrap(err, "could not get withdrawals") + } + withdrawalsRootArray, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload) + if err != nil { + return nil, errors.Wrap(err, "could not get withdrawals root") + } + withdrawalsRoot = withdrawalsRootArray[:] + } else if err != nil { + return nil, errors.Wrap(err, "could not get withdrawals root") + } + blobGasUsed, err := payload.BlobGasUsed() + if err != nil { + return nil, errors.Wrap(err, "could not get blob gas used") + } + excessBlobGas, err := payload.ExcessBlobGas() + if err != nil { + return nil, errors.Wrap(err, "could not get excess blob gas") + } + + executionHeader := &structs.ExecutionPayloadHeaderDeneb{ + ParentHash: hexutil.Encode(payload.ParentHash()), + FeeRecipient: hexutil.Encode(payload.FeeRecipient()), + StateRoot: hexutil.Encode(payload.StateRoot()), + ReceiptsRoot: hexutil.Encode(payload.ReceiptsRoot()), + LogsBloom: hexutil.Encode(payload.LogsBloom()), + PrevRandao: hexutil.Encode(payload.PrevRandao()), + BlockNumber: hexutil.EncodeUint64(payload.BlockNumber()), + GasLimit: hexutil.EncodeUint64(payload.GasLimit()), + GasUsed: hexutil.EncodeUint64(payload.GasUsed()), + Timestamp: hexutil.EncodeUint64(payload.Timestamp()), + ExtraData: hexutil.Encode(payload.ExtraData()), + BaseFeePerGas: hexutil.Encode(payload.BaseFeePerGas()), + BlockHash: hexutil.Encode(payload.BlockHash()), + TransactionsRoot: hexutil.Encode(transactionsRoot), + WithdrawalsRoot: hexutil.Encode(withdrawalsRoot), + BlobGasUsed: hexutil.EncodeUint64(blobGasUsed), + ExcessBlobGas: hexutil.EncodeUint64(excessBlobGas), + } + + executionPayloadProof, err := blocks.PayloadProof(ctx, block.Block()) + if err != nil { + return nil, errors.Wrap(err, "could not get execution payload proof") + } + executionPayloadProofStr := make([]string, len(executionPayloadProof)) + for i, proof := range executionPayloadProof { + executionPayloadProofStr[i] = hexutil.Encode(proof) + } + + parentRootArray := block.Block().ParentRoot() + parentRoot := parentRootArray[:] + + stateRootArray := block.Block().StateRoot() + stateRoot := stateRootArray[:] + + bodyRootArray, err := block.Block().Body().HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "could not get body root") + } + bodyRoot := bodyRootArray[:] + + return &structs.LightClientHeaderDeneb{ + Beacon: &structs.BeaconBlockHeader{ + Slot: hexutil.EncodeUint64(uint64(block.Block().Slot())), + ProposerIndex: hexutil.EncodeUint64(uint64(block.Block().ProposerIndex())), + ParentRoot: hexutil.Encode(parentRoot), + StateRoot: hexutil.Encode(stateRoot), + BodyRoot: hexutil.Encode(bodyRoot), + }, + Execution: executionHeader, + ExecutionBranch: executionPayloadProofStr, + }, nil +} From 879a74b8526c2092612822420ec908f76ec20104 Mon Sep 17 00:00:00 2001 From: rupam-04 Date: Sun, 8 Sep 2024 19:44:09 +0530 Subject: [PATCH 02/12] update `CHANGELOG.md` --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c467c7d8fb4..eb4c26f3859 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ The format is based on Keep a Changelog, and this project adheres to Semantic Ve - Light client support: Implement `ComputeFieldRootsForBlockBody`. - Light client support: Add light client database changes. - Light client support: Implement capella and deneb changes. +- Light client support: Implement `BlockToLightClientHeaderXXX` functions upto Deneb ### Changed From 11eeb291ca9e5289b722a9847978599e0febf315 Mon Sep 17 00:00:00 2001 From: rupam-04 Date: Mon, 9 Sep 2024 01:22:43 +0530 Subject: [PATCH 03/12] refactor: remove unnecessary variables --- beacon-chain/rpc/eth/light-client/helpers.go | 45 ++++++++------------ 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/beacon-chain/rpc/eth/light-client/helpers.go b/beacon-chain/rpc/eth/light-client/helpers.go index 6e2c30f60dc..88f315c49e7 100644 --- a/beacon-chain/rpc/eth/light-client/helpers.go +++ b/beacon-chain/rpc/eth/light-client/helpers.go @@ -653,25 +653,22 @@ func IsBetterUpdate(newUpdate, oldUpdate *v2.LightClientUpdate) (bool, error) { } func BlockToLightClientHeaderAltair(block interfaces.ReadOnlySignedBeaconBlock) (*structs.LightClientHeader, error) { - parentRootArray := block.Block().ParentRoot() - parentRoot := parentRootArray[:] + parentRoot := block.Block().ParentRoot() - stateRootArray := block.Block().StateRoot() - stateRoot := stateRootArray[:] + stateRoot := block.Block().StateRoot() - bodyRootArray, err := block.Block().Body().HashTreeRoot() + bodyRoot, err := block.Block().Body().HashTreeRoot() if err != nil { return nil, errors.Wrap(err, "could not get body root") } - bodyRoot := bodyRootArray[:] return &structs.LightClientHeader{ Beacon: &structs.BeaconBlockHeader{ Slot: hexutil.EncodeUint64(uint64(block.Block().Slot())), ProposerIndex: hexutil.EncodeUint64(uint64(block.Block().ProposerIndex())), - ParentRoot: hexutil.Encode(parentRoot), - StateRoot: hexutil.Encode(stateRoot), - BodyRoot: hexutil.Encode(bodyRoot), + ParentRoot: hexutil.Encode(parentRoot[:]), + StateRoot: hexutil.Encode(stateRoot[:]), + BodyRoot: hexutil.Encode(bodyRoot[:]), }, }, nil } @@ -743,25 +740,22 @@ func BlockToLightClientHeaderCapella(ctx context.Context, block interfaces.ReadO executionPayloadProofStr[i] = hexutil.Encode(proof) } - parentRootArray := block.Block().ParentRoot() - parentRoot := parentRootArray[:] + parentRoot := block.Block().ParentRoot() - stateRootArray := block.Block().StateRoot() - stateRoot := stateRootArray[:] + stateRoot := block.Block().StateRoot() - bodyRootArray, err := block.Block().Body().HashTreeRoot() + bodyRoot, err := block.Block().Body().HashTreeRoot() if err != nil { return nil, errors.Wrap(err, "could not get body root") } - bodyRoot := bodyRootArray[:] return &structs.LightClientHeaderCapella{ Beacon: &structs.BeaconBlockHeader{ Slot: hexutil.EncodeUint64(uint64(block.Block().Slot())), ProposerIndex: hexutil.EncodeUint64(uint64(block.Block().ProposerIndex())), - ParentRoot: hexutil.Encode(parentRoot), - StateRoot: hexutil.Encode(stateRoot), - BodyRoot: hexutil.Encode(bodyRoot), + ParentRoot: hexutil.Encode(parentRoot[:]), + StateRoot: hexutil.Encode(stateRoot[:]), + BodyRoot: hexutil.Encode(bodyRoot[:]), }, Execution: executionHeader, ExecutionBranch: executionPayloadProofStr, @@ -845,25 +839,22 @@ func BlockToLightClientHeaderDeneb(ctx context.Context, block interfaces.ReadOnl executionPayloadProofStr[i] = hexutil.Encode(proof) } - parentRootArray := block.Block().ParentRoot() - parentRoot := parentRootArray[:] + parentRoot := block.Block().ParentRoot() - stateRootArray := block.Block().StateRoot() - stateRoot := stateRootArray[:] + stateRoot := block.Block().StateRoot() - bodyRootArray, err := block.Block().Body().HashTreeRoot() + bodyRoot, err := block.Block().Body().HashTreeRoot() if err != nil { return nil, errors.Wrap(err, "could not get body root") } - bodyRoot := bodyRootArray[:] return &structs.LightClientHeaderDeneb{ Beacon: &structs.BeaconBlockHeader{ Slot: hexutil.EncodeUint64(uint64(block.Block().Slot())), ProposerIndex: hexutil.EncodeUint64(uint64(block.Block().ProposerIndex())), - ParentRoot: hexutil.Encode(parentRoot), - StateRoot: hexutil.Encode(stateRoot), - BodyRoot: hexutil.Encode(bodyRoot), + ParentRoot: hexutil.Encode(parentRoot[:]), + StateRoot: hexutil.Encode(stateRoot[:]), + BodyRoot: hexutil.Encode(bodyRoot[:]), }, Execution: executionHeader, ExecutionBranch: executionPayloadProofStr, From 8f649a819497c5e14603c9416da96da17eef2ba2 Mon Sep 17 00:00:00 2001 From: rupam-04 Date: Tue, 10 Sep 2024 10:44:15 +0530 Subject: [PATCH 04/12] move functions to `core/light-client/lightclient.go` --- beacon-chain/core/light-client/lightclient.go | 202 +++++++++++++++++ beacon-chain/rpc/eth/light-client/helpers.go | 209 ------------------ 2 files changed, 202 insertions(+), 209 deletions(-) diff --git a/beacon-chain/core/light-client/lightclient.go b/beacon-chain/core/light-client/lightclient.go index c572a6325c2..b8be3df751c 100644 --- a/beacon-chain/core/light-client/lightclient.go +++ b/beacon-chain/core/light-client/lightclient.go @@ -13,6 +13,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/encoding/ssz" enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" + v11 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" ethpbv1 "github.com/prysmaticlabs/prysm/v5/proto/eth/v1" ethpbv2 "github.com/prysmaticlabs/prysm/v5/proto/eth/v2" "github.com/prysmaticlabs/prysm/v5/proto/migration" @@ -551,3 +552,204 @@ func NewLightClientUpdateFromOptimisticUpdate(update *ethpbv2.LightClientOptimis SignatureSlot: update.SignatureSlot, } } + +func BlockToLightClientHeaderAltair(block interfaces.ReadOnlySignedBeaconBlock) (*ethpbv2.LightClientHeader, error) { + parentRoot := block.Block().ParentRoot() + + stateRoot := block.Block().StateRoot() + + bodyRoot, err := block.Block().Body().HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "could not get body root") + } + + return ðpbv2.LightClientHeader{ + Beacon: ðpbv1.BeaconBlockHeader{ + Slot: block.Block().Slot(), + ProposerIndex: block.Block().ProposerIndex(), + ParentRoot: parentRoot[:], + StateRoot: stateRoot[:], + BodyRoot: bodyRoot[:], + }, + }, nil +} + +func BlockToLightClientHeaderCapella(ctx context.Context, block interfaces.ReadOnlySignedBeaconBlock) (*ethpbv2.LightClientHeaderCapella, error) { + epoch := slots.ToEpoch(block.Block().Slot()) + if epoch < params.BeaconConfig().CapellaForkEpoch { + return nil, fmt.Errorf("creating Capella light client header is not supported before Capella, invalid slot %d", block.Block().Slot()) + } + + payload, err := block.Block().Body().Execution() + if err != nil { + return nil, errors.Wrap(err, "could not get execution payload") + } + + transactionsRoot, err := payload.TransactionsRoot() + if errors.Is(err, consensus_types.ErrUnsupportedField) { + transactions, err := payload.Transactions() + if err != nil { + return nil, errors.Wrap(err, "could not get transactions") + } + transactionsRootArray, err := ssz.TransactionsRoot(transactions) + if err != nil { + return nil, errors.Wrap(err, "could not get transactions root") + } + transactionsRoot = transactionsRootArray[:] + } else if err != nil { + return nil, errors.Wrap(err, "could not get transactions root") + } + withdrawalsRoot, err := payload.WithdrawalsRoot() + if errors.Is(err, consensus_types.ErrUnsupportedField) { + withdrawals, err := payload.Withdrawals() + if err != nil { + return nil, errors.Wrap(err, "could not get withdrawals") + } + withdrawalsRootArray, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload) + if err != nil { + return nil, errors.Wrap(err, "could not get withdrawals root") + } + withdrawalsRoot = withdrawalsRootArray[:] + } else if err != nil { + return nil, errors.Wrap(err, "could not get withdrawals root") + } + + executionHeader := &v11.ExecutionPayloadHeaderCapella{ + ParentHash: payload.ParentHash(), + FeeRecipient: payload.FeeRecipient(), + StateRoot: payload.StateRoot(), + ReceiptsRoot: payload.ReceiptsRoot(), + LogsBloom: payload.LogsBloom(), + PrevRandao: payload.PrevRandao(), + BlockNumber: payload.BlockNumber(), + GasLimit: payload.GasLimit(), + GasUsed: payload.GasUsed(), + Timestamp: payload.Timestamp(), + ExtraData: payload.ExtraData(), + BaseFeePerGas: payload.BaseFeePerGas(), + BlockHash: payload.BlockHash(), + TransactionsRoot: transactionsRoot, + WithdrawalsRoot: withdrawalsRoot, + } + + executionPayloadProof, err := blocks.PayloadProof(ctx, block.Block()) + if err != nil { + return nil, errors.Wrap(err, "could not get execution payload proof") + } + + parentRoot := block.Block().ParentRoot() + + stateRoot := block.Block().StateRoot() + + bodyRoot, err := block.Block().Body().HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "could not get body root") + } + + return ðpbv2.LightClientHeaderCapella{ + Beacon: ðpbv1.BeaconBlockHeader{ + Slot: block.Block().Slot(), + ProposerIndex: block.Block().ProposerIndex(), + ParentRoot: parentRoot[:], + StateRoot: stateRoot[:], + BodyRoot: bodyRoot[:], + }, + Execution: executionHeader, + ExecutionBranch: executionPayloadProof, + }, nil +} + +func BlockToLightClientHeaderDeneb(ctx context.Context, block interfaces.ReadOnlySignedBeaconBlock) (*ethpbv2.LightClientHeaderDeneb, error) { + epoch := slots.ToEpoch(block.Block().Slot()) + if epoch < params.BeaconConfig().DenebForkEpoch { + return nil, fmt.Errorf("creating Deneb light client header is not supported before Deneb, invalid slot %d", block.Block().Slot()) + } + + payload, err := block.Block().Body().Execution() + if err != nil { + return nil, errors.Wrap(err, "could not get execution payload") + } + + transactionsRoot, err := payload.TransactionsRoot() + if errors.Is(err, consensus_types.ErrUnsupportedField) { + transactions, err := payload.Transactions() + if err != nil { + return nil, errors.Wrap(err, "could not get transactions") + } + transactionsRootArray, err := ssz.TransactionsRoot(transactions) + if err != nil { + return nil, errors.Wrap(err, "could not get transactions root") + } + transactionsRoot = transactionsRootArray[:] + } else if err != nil { + return nil, errors.Wrap(err, "could not get transactions root") + } + withdrawalsRoot, err := payload.WithdrawalsRoot() + if errors.Is(err, consensus_types.ErrUnsupportedField) { + withdrawals, err := payload.Withdrawals() + if err != nil { + return nil, errors.Wrap(err, "could not get withdrawals") + } + withdrawalsRootArray, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload) + if err != nil { + return nil, errors.Wrap(err, "could not get withdrawals root") + } + withdrawalsRoot = withdrawalsRootArray[:] + } else if err != nil { + return nil, errors.Wrap(err, "could not get withdrawals root") + } + blobGasUsed, err := payload.BlobGasUsed() + if err != nil { + return nil, errors.Wrap(err, "could not get blob gas used") + } + excessBlobGas, err := payload.ExcessBlobGas() + if err != nil { + return nil, errors.Wrap(err, "could not get excess blob gas") + } + + executionHeader := &v11.ExecutionPayloadHeaderDeneb{ + ParentHash: payload.ParentHash(), + FeeRecipient: payload.FeeRecipient(), + StateRoot: payload.StateRoot(), + ReceiptsRoot: payload.ReceiptsRoot(), + LogsBloom: payload.LogsBloom(), + PrevRandao: payload.PrevRandao(), + BlockNumber: payload.BlockNumber(), + GasLimit: payload.GasLimit(), + GasUsed: payload.GasUsed(), + Timestamp: payload.Timestamp(), + ExtraData: payload.ExtraData(), + BaseFeePerGas: payload.BaseFeePerGas(), + BlockHash: payload.BlockHash(), + TransactionsRoot: transactionsRoot, + WithdrawalsRoot: withdrawalsRoot, + BlobGasUsed: blobGasUsed, + ExcessBlobGas: excessBlobGas, + } + + executionPayloadProof, err := blocks.PayloadProof(ctx, block.Block()) + if err != nil { + return nil, errors.Wrap(err, "could not get execution payload proof") + } + + parentRoot := block.Block().ParentRoot() + + stateRoot := block.Block().StateRoot() + + bodyRoot, err := block.Block().Body().HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "could not get body root") + } + + return ðpbv2.LightClientHeaderDeneb{ + Beacon: ðpbv1.BeaconBlockHeader{ + Slot: block.Block().Slot(), + ProposerIndex: block.Block().ProposerIndex(), + ParentRoot: parentRoot[:], + StateRoot: stateRoot[:], + BodyRoot: bodyRoot[:], + }, + Execution: executionHeader, + ExecutionBranch: executionPayloadProof, + }, nil +} diff --git a/beacon-chain/rpc/eth/light-client/helpers.go b/beacon-chain/rpc/eth/light-client/helpers.go index 88f315c49e7..aa5f8a6b81d 100644 --- a/beacon-chain/rpc/eth/light-client/helpers.go +++ b/beacon-chain/rpc/eth/light-client/helpers.go @@ -651,212 +651,3 @@ func IsBetterUpdate(newUpdate, oldUpdate *v2.LightClientUpdate) (bool, error) { } return newUpdate.SignatureSlot < oldUpdate.SignatureSlot, nil } - -func BlockToLightClientHeaderAltair(block interfaces.ReadOnlySignedBeaconBlock) (*structs.LightClientHeader, error) { - parentRoot := block.Block().ParentRoot() - - stateRoot := block.Block().StateRoot() - - bodyRoot, err := block.Block().Body().HashTreeRoot() - if err != nil { - return nil, errors.Wrap(err, "could not get body root") - } - - return &structs.LightClientHeader{ - Beacon: &structs.BeaconBlockHeader{ - Slot: hexutil.EncodeUint64(uint64(block.Block().Slot())), - ProposerIndex: hexutil.EncodeUint64(uint64(block.Block().ProposerIndex())), - ParentRoot: hexutil.Encode(parentRoot[:]), - StateRoot: hexutil.Encode(stateRoot[:]), - BodyRoot: hexutil.Encode(bodyRoot[:]), - }, - }, nil -} - -func BlockToLightClientHeaderCapella(ctx context.Context, block interfaces.ReadOnlySignedBeaconBlock) (*structs.LightClientHeaderCapella, error) { - epoch := slots.ToEpoch(block.Block().Slot()) - if epoch < params.BeaconConfig().CapellaForkEpoch { - return nil, fmt.Errorf("creating Capella light client header is not supported before Capella, invalid slot %d", block.Block().Slot()) - } - - payload, err := block.Block().Body().Execution() - if err != nil { - return nil, errors.Wrap(err, "could not get execution payload") - } - - transactionsRoot, err := payload.TransactionsRoot() - if errors.Is(err, consensus_types.ErrUnsupportedField) { - transactions, err := payload.Transactions() - if err != nil { - return nil, errors.Wrap(err, "could not get transactions") - } - transactionsRootArray, err := ssz.TransactionsRoot(transactions) - if err != nil { - return nil, errors.Wrap(err, "could not get transactions root") - } - transactionsRoot = transactionsRootArray[:] - } else if err != nil { - return nil, errors.Wrap(err, "could not get transactions root") - } - withdrawalsRoot, err := payload.WithdrawalsRoot() - if errors.Is(err, consensus_types.ErrUnsupportedField) { - withdrawals, err := payload.Withdrawals() - if err != nil { - return nil, errors.Wrap(err, "could not get withdrawals") - } - withdrawalsRootArray, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload) - if err != nil { - return nil, errors.Wrap(err, "could not get withdrawals root") - } - withdrawalsRoot = withdrawalsRootArray[:] - } else if err != nil { - return nil, errors.Wrap(err, "could not get withdrawals root") - } - - executionHeader := &structs.ExecutionPayloadHeaderCapella{ - ParentHash: hexutil.Encode(payload.ParentHash()), - FeeRecipient: hexutil.Encode(payload.FeeRecipient()), - StateRoot: hexutil.Encode(payload.StateRoot()), - ReceiptsRoot: hexutil.Encode(payload.ReceiptsRoot()), - LogsBloom: hexutil.Encode(payload.LogsBloom()), - PrevRandao: hexutil.Encode(payload.PrevRandao()), - BlockNumber: hexutil.EncodeUint64(payload.BlockNumber()), - GasLimit: hexutil.EncodeUint64(payload.GasLimit()), - GasUsed: hexutil.EncodeUint64(payload.GasUsed()), - Timestamp: hexutil.EncodeUint64(payload.Timestamp()), - ExtraData: hexutil.Encode(payload.ExtraData()), - BaseFeePerGas: hexutil.Encode(payload.BaseFeePerGas()), - BlockHash: hexutil.Encode(payload.BlockHash()), - TransactionsRoot: hexutil.Encode(transactionsRoot), - WithdrawalsRoot: hexutil.Encode(withdrawalsRoot), - } - - executionPayloadProof, err := blocks.PayloadProof(ctx, block.Block()) - if err != nil { - return nil, errors.Wrap(err, "could not get execution payload proof") - } - executionPayloadProofStr := make([]string, len(executionPayloadProof)) - for i, proof := range executionPayloadProof { - executionPayloadProofStr[i] = hexutil.Encode(proof) - } - - parentRoot := block.Block().ParentRoot() - - stateRoot := block.Block().StateRoot() - - bodyRoot, err := block.Block().Body().HashTreeRoot() - if err != nil { - return nil, errors.Wrap(err, "could not get body root") - } - - return &structs.LightClientHeaderCapella{ - Beacon: &structs.BeaconBlockHeader{ - Slot: hexutil.EncodeUint64(uint64(block.Block().Slot())), - ProposerIndex: hexutil.EncodeUint64(uint64(block.Block().ProposerIndex())), - ParentRoot: hexutil.Encode(parentRoot[:]), - StateRoot: hexutil.Encode(stateRoot[:]), - BodyRoot: hexutil.Encode(bodyRoot[:]), - }, - Execution: executionHeader, - ExecutionBranch: executionPayloadProofStr, - }, nil -} - -func BlockToLightClientHeaderDeneb(ctx context.Context, block interfaces.ReadOnlySignedBeaconBlock) (*structs.LightClientHeaderDeneb, error) { - epoch := slots.ToEpoch(block.Block().Slot()) - if epoch < params.BeaconConfig().DenebForkEpoch { - return nil, fmt.Errorf("creating Deneb light client header is not supported before Deneb, invalid slot %d", block.Block().Slot()) - } - - payload, err := block.Block().Body().Execution() - if err != nil { - return nil, errors.Wrap(err, "could not get execution payload") - } - - transactionsRoot, err := payload.TransactionsRoot() - if errors.Is(err, consensus_types.ErrUnsupportedField) { - transactions, err := payload.Transactions() - if err != nil { - return nil, errors.Wrap(err, "could not get transactions") - } - transactionsRootArray, err := ssz.TransactionsRoot(transactions) - if err != nil { - return nil, errors.Wrap(err, "could not get transactions root") - } - transactionsRoot = transactionsRootArray[:] - } else if err != nil { - return nil, errors.Wrap(err, "could not get transactions root") - } - withdrawalsRoot, err := payload.WithdrawalsRoot() - if errors.Is(err, consensus_types.ErrUnsupportedField) { - withdrawals, err := payload.Withdrawals() - if err != nil { - return nil, errors.Wrap(err, "could not get withdrawals") - } - withdrawalsRootArray, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload) - if err != nil { - return nil, errors.Wrap(err, "could not get withdrawals root") - } - withdrawalsRoot = withdrawalsRootArray[:] - } else if err != nil { - return nil, errors.Wrap(err, "could not get withdrawals root") - } - blobGasUsed, err := payload.BlobGasUsed() - if err != nil { - return nil, errors.Wrap(err, "could not get blob gas used") - } - excessBlobGas, err := payload.ExcessBlobGas() - if err != nil { - return nil, errors.Wrap(err, "could not get excess blob gas") - } - - executionHeader := &structs.ExecutionPayloadHeaderDeneb{ - ParentHash: hexutil.Encode(payload.ParentHash()), - FeeRecipient: hexutil.Encode(payload.FeeRecipient()), - StateRoot: hexutil.Encode(payload.StateRoot()), - ReceiptsRoot: hexutil.Encode(payload.ReceiptsRoot()), - LogsBloom: hexutil.Encode(payload.LogsBloom()), - PrevRandao: hexutil.Encode(payload.PrevRandao()), - BlockNumber: hexutil.EncodeUint64(payload.BlockNumber()), - GasLimit: hexutil.EncodeUint64(payload.GasLimit()), - GasUsed: hexutil.EncodeUint64(payload.GasUsed()), - Timestamp: hexutil.EncodeUint64(payload.Timestamp()), - ExtraData: hexutil.Encode(payload.ExtraData()), - BaseFeePerGas: hexutil.Encode(payload.BaseFeePerGas()), - BlockHash: hexutil.Encode(payload.BlockHash()), - TransactionsRoot: hexutil.Encode(transactionsRoot), - WithdrawalsRoot: hexutil.Encode(withdrawalsRoot), - BlobGasUsed: hexutil.EncodeUint64(blobGasUsed), - ExcessBlobGas: hexutil.EncodeUint64(excessBlobGas), - } - - executionPayloadProof, err := blocks.PayloadProof(ctx, block.Block()) - if err != nil { - return nil, errors.Wrap(err, "could not get execution payload proof") - } - executionPayloadProofStr := make([]string, len(executionPayloadProof)) - for i, proof := range executionPayloadProof { - executionPayloadProofStr[i] = hexutil.Encode(proof) - } - - parentRoot := block.Block().ParentRoot() - - stateRoot := block.Block().StateRoot() - - bodyRoot, err := block.Block().Body().HashTreeRoot() - if err != nil { - return nil, errors.Wrap(err, "could not get body root") - } - - return &structs.LightClientHeaderDeneb{ - Beacon: &structs.BeaconBlockHeader{ - Slot: hexutil.EncodeUint64(uint64(block.Block().Slot())), - ProposerIndex: hexutil.EncodeUint64(uint64(block.Block().ProposerIndex())), - ParentRoot: hexutil.Encode(parentRoot[:]), - StateRoot: hexutil.Encode(stateRoot[:]), - BodyRoot: hexutil.Encode(bodyRoot[:]), - }, - Execution: executionHeader, - ExecutionBranch: executionPayloadProofStr, - }, nil -} From 0d6478d4d776d68a2dff37559ec317ccf38dec4b Mon Sep 17 00:00:00 2001 From: rupam-04 Date: Tue, 10 Sep 2024 12:35:08 +0530 Subject: [PATCH 05/12] feat: add tests --- .../core/light-client/lightclient_test.go | 178 ++++++++++++++++++ 1 file changed, 178 insertions(+) diff --git a/beacon-chain/core/light-client/lightclient_test.go b/beacon-chain/core/light-client/lightclient_test.go index 51e706706d2..13bced424c0 100644 --- a/beacon-chain/core/light-client/lightclient_test.go +++ b/beacon-chain/core/light-client/lightclient_test.go @@ -3,7 +3,14 @@ package light_client_test import ( "testing" + "github.com/pkg/errors" + consensus_types "github.com/prysmaticlabs/prysm/v5/consensus-types" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" + "github.com/prysmaticlabs/prysm/v5/encoding/ssz" + v11 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" + lightClient "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/light-client" + fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" v2 "github.com/prysmaticlabs/prysm/v5/proto/eth/v2" @@ -139,4 +146,175 @@ func TestLightClient_NewLightClientFinalityUpdateFromBeaconStateDeneb(t *testing } } +func TestLightClient_BlockToLightClientHeaderAltair(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestAltair() + + header, err := lightClient.BlockToLightClientHeaderAltair(l.Block) + require.NoError(t, err) + require.NotNil(t, header, "header is nil") + + parentRoot := l.Block.Block().ParentRoot() + + stateRoot := l.Block.Block().StateRoot() + + bodyRoot, err := l.Block.Block().Body().HashTreeRoot() + require.NoError(t, err) + + require.Equal(t, l.Block.Block().Slot(), header.Beacon.Slot, "Slot is not equal") + require.Equal(t, l.Block.Block().ProposerIndex(), header.Beacon.ProposerIndex, "Proposer index is not equal") + require.DeepSSZEqual(t, parentRoot[:], header.Beacon.ParentRoot, "Parent root is not equal") + require.DeepSSZEqual(t, stateRoot[:], header.Beacon.StateRoot, "State root is not equal") + require.DeepSSZEqual(t, bodyRoot[:], header.Beacon.BodyRoot, "Body root is not equal") +} + +func TestLightClient_BlockToLightClientHeaderCapella(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestCapella() + + header, err := lightClient.BlockToLightClientHeaderCapella(l.Ctx, l.Block) + require.NoError(t, err) + require.NotNil(t, header, "header is nil") + + parentRoot := l.Block.Block().ParentRoot() + + stateRoot := l.Block.Block().StateRoot() + + bodyRoot, err := l.Block.Block().Body().HashTreeRoot() + require.NoError(t, err) + + payload, err := l.Block.Block().Body().Execution() + require.NoError(t, err) + + transactionsRoot, err := payload.TransactionsRoot() + if errors.Is(err, consensus_types.ErrUnsupportedField) { + transactions, err := payload.Transactions() + require.NoError(t, err) + transactionsRootArray, err := ssz.TransactionsRoot(transactions) + require.NoError(t, err) + transactionsRoot = transactionsRootArray[:] + } else { + require.NoError(t, err) + } + + withdrawalsRoot, err := payload.WithdrawalsRoot() + if errors.Is(err, consensus_types.ErrUnsupportedField) { + withdrawals, err := payload.Withdrawals() + require.NoError(t, err) + withdrawalsRootArray, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload) + require.NoError(t, err) + withdrawalsRoot = withdrawalsRootArray[:] + } else { + require.NoError(t, err) + } + + executionHeader := &v11.ExecutionPayloadHeaderCapella{ + ParentHash: payload.ParentHash(), + FeeRecipient: payload.FeeRecipient(), + StateRoot: payload.StateRoot(), + ReceiptsRoot: payload.ReceiptsRoot(), + LogsBloom: payload.LogsBloom(), + PrevRandao: payload.PrevRandao(), + BlockNumber: payload.BlockNumber(), + GasLimit: payload.GasLimit(), + GasUsed: payload.GasUsed(), + Timestamp: payload.Timestamp(), + ExtraData: payload.ExtraData(), + BaseFeePerGas: payload.BaseFeePerGas(), + BlockHash: payload.BlockHash(), + TransactionsRoot: transactionsRoot, + WithdrawalsRoot: withdrawalsRoot, + } + + executionPayloadProof, err := blocks.PayloadProof(l.Ctx, l.Block.Block()) + require.NoError(t, err) + + require.Equal(t, l.Block.Block().Slot(), header.Beacon.Slot, "Slot is not equal") + require.Equal(t, l.Block.Block().ProposerIndex(), header.Beacon.ProposerIndex, "Proposer index is not equal") + require.DeepSSZEqual(t, parentRoot[:], header.Beacon.ParentRoot, "Parent root is not equal") + require.DeepSSZEqual(t, stateRoot[:], header.Beacon.StateRoot, "State root is not equal") + require.DeepSSZEqual(t, bodyRoot[:], header.Beacon.BodyRoot, "Body root is not equal") + + require.DeepSSZEqual(t, executionHeader, header.Execution, "Execution headers are not equal") + + require.DeepSSZEqual(t, executionPayloadProof, header.ExecutionBranch, "Execution payload proofs are not equal") +} + +func TestLightClient_BlockToLightClientHeaderDeneb(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestDeneb() + + header, err := lightClient.BlockToLightClientHeaderDeneb(l.Ctx, l.Block) + require.NoError(t, err) + require.NotNil(t, header, "header is nil") + + parentRoot := l.Block.Block().ParentRoot() + + stateRoot := l.Block.Block().StateRoot() + + bodyRoot, err := l.Block.Block().Body().HashTreeRoot() + require.NoError(t, err) + + payload, err := l.Block.Block().Body().Execution() + require.NoError(t, err) + + transactionsRoot, err := payload.TransactionsRoot() + if errors.Is(err, consensus_types.ErrUnsupportedField) { + transactions, err := payload.Transactions() + require.NoError(t, err) + transactionsRootArray, err := ssz.TransactionsRoot(transactions) + require.NoError(t, err) + transactionsRoot = transactionsRootArray[:] + } else { + require.NoError(t, err) + } + + withdrawalsRoot, err := payload.WithdrawalsRoot() + if errors.Is(err, consensus_types.ErrUnsupportedField) { + withdrawals, err := payload.Withdrawals() + require.NoError(t, err) + withdrawalsRootArray, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload) + require.NoError(t, err) + withdrawalsRoot = withdrawalsRootArray[:] + } else { + require.NoError(t, err) + } + + blobGasUsed, err := payload.BlobGasUsed() + require.NoError(t, err) + + excessBlobGas, err := payload.ExcessBlobGas() + require.NoError(t, err) + + executionHeader := &v11.ExecutionPayloadHeaderDeneb{ + ParentHash: payload.ParentHash(), + FeeRecipient: payload.FeeRecipient(), + StateRoot: payload.StateRoot(), + ReceiptsRoot: payload.ReceiptsRoot(), + LogsBloom: payload.LogsBloom(), + PrevRandao: payload.PrevRandao(), + BlockNumber: payload.BlockNumber(), + GasLimit: payload.GasLimit(), + GasUsed: payload.GasUsed(), + Timestamp: payload.Timestamp(), + ExtraData: payload.ExtraData(), + BaseFeePerGas: payload.BaseFeePerGas(), + BlockHash: payload.BlockHash(), + TransactionsRoot: transactionsRoot, + WithdrawalsRoot: withdrawalsRoot, + BlobGasUsed: blobGasUsed, + ExcessBlobGas: excessBlobGas, + } + + executionPayloadProof, err := blocks.PayloadProof(l.Ctx, l.Block.Block()) + require.NoError(t, err) + + require.Equal(t, l.Block.Block().Slot(), header.Beacon.Slot, "Slot is not equal") + require.Equal(t, l.Block.Block().ProposerIndex(), header.Beacon.ProposerIndex, "Proposer index is not equal") + require.DeepSSZEqual(t, parentRoot[:], header.Beacon.ParentRoot, "Parent root is not equal") + require.DeepSSZEqual(t, stateRoot[:], header.Beacon.StateRoot, "State root is not equal") + require.DeepSSZEqual(t, bodyRoot[:], header.Beacon.BodyRoot, "Body root is not equal") + + require.DeepSSZEqual(t, executionHeader, header.Execution, "Execution headers are not equal") + + require.DeepSSZEqual(t, executionPayloadProof, header.ExecutionBranch, "Execution payload proofs are not equal") +} + // TODO - add finality update tests with non-nil finalized block for different versions From db9dc33c2844a7d3ab4bddfea18f771f801c33f8 Mon Sep 17 00:00:00 2001 From: rupam-04 Date: Wed, 11 Sep 2024 22:52:50 +0530 Subject: [PATCH 06/12] refactors --- beacon-chain/core/light-client/lightclient.go | 108 ++++++++---------- .../core/light-client/lightclient_test.go | 59 ++-------- 2 files changed, 56 insertions(+), 111 deletions(-) diff --git a/beacon-chain/core/light-client/lightclient.go b/beacon-chain/core/light-client/lightclient.go index b8be3df751c..29319edba79 100644 --- a/beacon-chain/core/light-client/lightclient.go +++ b/beacon-chain/core/light-client/lightclient.go @@ -553,11 +553,45 @@ func NewLightClientUpdateFromOptimisticUpdate(update *ethpbv2.LightClientOptimis } } +func ComputeTransactionsRoot(payload interfaces.ExecutionData) ([]byte, error) { + transactionsRoot, err := payload.TransactionsRoot() + if errors.Is(err, consensus_types.ErrUnsupportedField) { + transactions, err := payload.Transactions() + if err != nil { + return nil, errors.Wrap(err, "could not get transactions") + } + transactionsRootArray, err := ssz.TransactionsRoot(transactions) + if err != nil { + return nil, errors.Wrap(err, "could not get transactions root") + } + transactionsRoot = transactionsRootArray[:] + } else if err != nil { + return nil, errors.Wrap(err, "could not get transactions root") + } + return transactionsRoot, nil +} + +func ComputeWithdrawalsRoot(payload interfaces.ExecutionData) ([]byte, error) { + withdrawalsRoot, err := payload.WithdrawalsRoot() + if errors.Is(err, consensus_types.ErrUnsupportedField) { + withdrawals, err := payload.Withdrawals() + if err != nil { + return nil, errors.Wrap(err, "could not get withdrawals") + } + withdrawalsRootArray, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload) + if err != nil { + return nil, errors.Wrap(err, "could not get withdrawals root") + } + withdrawalsRoot = withdrawalsRootArray[:] + } else if err != nil { + return nil, errors.Wrap(err, "could not get withdrawals root") + } + return withdrawalsRoot, nil +} + func BlockToLightClientHeaderAltair(block interfaces.ReadOnlySignedBeaconBlock) (*ethpbv2.LightClientHeader, error) { parentRoot := block.Block().ParentRoot() - stateRoot := block.Block().StateRoot() - bodyRoot, err := block.Block().Body().HashTreeRoot() if err != nil { return nil, errors.Wrap(err, "could not get body root") @@ -575,8 +609,7 @@ func BlockToLightClientHeaderAltair(block interfaces.ReadOnlySignedBeaconBlock) } func BlockToLightClientHeaderCapella(ctx context.Context, block interfaces.ReadOnlySignedBeaconBlock) (*ethpbv2.LightClientHeaderCapella, error) { - epoch := slots.ToEpoch(block.Block().Slot()) - if epoch < params.BeaconConfig().CapellaForkEpoch { + if block.Version() != version.Capella { return nil, fmt.Errorf("creating Capella light client header is not supported before Capella, invalid slot %d", block.Block().Slot()) } @@ -585,34 +618,11 @@ func BlockToLightClientHeaderCapella(ctx context.Context, block interfaces.ReadO return nil, errors.Wrap(err, "could not get execution payload") } - transactionsRoot, err := payload.TransactionsRoot() - if errors.Is(err, consensus_types.ErrUnsupportedField) { - transactions, err := payload.Transactions() - if err != nil { - return nil, errors.Wrap(err, "could not get transactions") - } - transactionsRootArray, err := ssz.TransactionsRoot(transactions) - if err != nil { - return nil, errors.Wrap(err, "could not get transactions root") - } - transactionsRoot = transactionsRootArray[:] - } else if err != nil { - return nil, errors.Wrap(err, "could not get transactions root") - } - withdrawalsRoot, err := payload.WithdrawalsRoot() - if errors.Is(err, consensus_types.ErrUnsupportedField) { - withdrawals, err := payload.Withdrawals() - if err != nil { - return nil, errors.Wrap(err, "could not get withdrawals") - } - withdrawalsRootArray, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload) - if err != nil { - return nil, errors.Wrap(err, "could not get withdrawals root") - } - withdrawalsRoot = withdrawalsRootArray[:] - } else if err != nil { - return nil, errors.Wrap(err, "could not get withdrawals root") + transactionsRoot, err := ComputeTransactionsRoot(payload) + if err != nil { + return nil, err } + withdrawalsRoot, err := ComputeWithdrawalsRoot(payload) executionHeader := &v11.ExecutionPayloadHeaderCapella{ ParentHash: payload.ParentHash(), @@ -638,9 +648,7 @@ func BlockToLightClientHeaderCapella(ctx context.Context, block interfaces.ReadO } parentRoot := block.Block().ParentRoot() - stateRoot := block.Block().StateRoot() - bodyRoot, err := block.Block().Body().HashTreeRoot() if err != nil { return nil, errors.Wrap(err, "could not get body root") @@ -670,33 +678,13 @@ func BlockToLightClientHeaderDeneb(ctx context.Context, block interfaces.ReadOnl return nil, errors.Wrap(err, "could not get execution payload") } - transactionsRoot, err := payload.TransactionsRoot() - if errors.Is(err, consensus_types.ErrUnsupportedField) { - transactions, err := payload.Transactions() - if err != nil { - return nil, errors.Wrap(err, "could not get transactions") - } - transactionsRootArray, err := ssz.TransactionsRoot(transactions) - if err != nil { - return nil, errors.Wrap(err, "could not get transactions root") - } - transactionsRoot = transactionsRootArray[:] - } else if err != nil { - return nil, errors.Wrap(err, "could not get transactions root") + transactionsRoot, err := ComputeTransactionsRoot(payload) + if err != nil { + return nil, err } - withdrawalsRoot, err := payload.WithdrawalsRoot() - if errors.Is(err, consensus_types.ErrUnsupportedField) { - withdrawals, err := payload.Withdrawals() - if err != nil { - return nil, errors.Wrap(err, "could not get withdrawals") - } - withdrawalsRootArray, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload) - if err != nil { - return nil, errors.Wrap(err, "could not get withdrawals root") - } - withdrawalsRoot = withdrawalsRootArray[:] - } else if err != nil { - return nil, errors.Wrap(err, "could not get withdrawals root") + withdrawalsRoot, err := ComputeWithdrawalsRoot(payload) + if err != nil { + return nil, err } blobGasUsed, err := payload.BlobGasUsed() if err != nil { @@ -733,9 +721,7 @@ func BlockToLightClientHeaderDeneb(ctx context.Context, block interfaces.ReadOnl } parentRoot := block.Block().ParentRoot() - stateRoot := block.Block().StateRoot() - bodyRoot, err := block.Block().Body().HashTreeRoot() if err != nil { return nil, errors.Wrap(err, "could not get body root") diff --git a/beacon-chain/core/light-client/lightclient_test.go b/beacon-chain/core/light-client/lightclient_test.go index 13bced424c0..e864bc16dd7 100644 --- a/beacon-chain/core/light-client/lightclient_test.go +++ b/beacon-chain/core/light-client/lightclient_test.go @@ -3,14 +3,11 @@ package light_client_test import ( "testing" - "github.com/pkg/errors" - consensus_types "github.com/prysmaticlabs/prysm/v5/consensus-types" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" - "github.com/prysmaticlabs/prysm/v5/encoding/ssz" v11 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" lightClient "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/light-client" - fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + light_client "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/light-client" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" v2 "github.com/prysmaticlabs/prysm/v5/proto/eth/v2" @@ -154,9 +151,7 @@ func TestLightClient_BlockToLightClientHeaderAltair(t *testing.T) { require.NotNil(t, header, "header is nil") parentRoot := l.Block.Block().ParentRoot() - stateRoot := l.Block.Block().StateRoot() - bodyRoot, err := l.Block.Block().Body().HashTreeRoot() require.NoError(t, err) @@ -175,36 +170,18 @@ func TestLightClient_BlockToLightClientHeaderCapella(t *testing.T) { require.NotNil(t, header, "header is nil") parentRoot := l.Block.Block().ParentRoot() - stateRoot := l.Block.Block().StateRoot() - bodyRoot, err := l.Block.Block().Body().HashTreeRoot() require.NoError(t, err) payload, err := l.Block.Block().Body().Execution() require.NoError(t, err) - transactionsRoot, err := payload.TransactionsRoot() - if errors.Is(err, consensus_types.ErrUnsupportedField) { - transactions, err := payload.Transactions() - require.NoError(t, err) - transactionsRootArray, err := ssz.TransactionsRoot(transactions) - require.NoError(t, err) - transactionsRoot = transactionsRootArray[:] - } else { - require.NoError(t, err) - } + transactionsRoot, err := light_client.ComputeTransactionsRoot(payload) + require.NoError(t, err) - withdrawalsRoot, err := payload.WithdrawalsRoot() - if errors.Is(err, consensus_types.ErrUnsupportedField) { - withdrawals, err := payload.Withdrawals() - require.NoError(t, err) - withdrawalsRootArray, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload) - require.NoError(t, err) - withdrawalsRoot = withdrawalsRootArray[:] - } else { - require.NoError(t, err) - } + withdrawalsRoot, err := light_client.ComputeWithdrawalsRoot(payload) + require.NoError(t, err) executionHeader := &v11.ExecutionPayloadHeaderCapella{ ParentHash: payload.ParentHash(), @@ -246,36 +223,18 @@ func TestLightClient_BlockToLightClientHeaderDeneb(t *testing.T) { require.NotNil(t, header, "header is nil") parentRoot := l.Block.Block().ParentRoot() - stateRoot := l.Block.Block().StateRoot() - bodyRoot, err := l.Block.Block().Body().HashTreeRoot() require.NoError(t, err) payload, err := l.Block.Block().Body().Execution() require.NoError(t, err) - transactionsRoot, err := payload.TransactionsRoot() - if errors.Is(err, consensus_types.ErrUnsupportedField) { - transactions, err := payload.Transactions() - require.NoError(t, err) - transactionsRootArray, err := ssz.TransactionsRoot(transactions) - require.NoError(t, err) - transactionsRoot = transactionsRootArray[:] - } else { - require.NoError(t, err) - } + transactionsRoot, err := light_client.ComputeTransactionsRoot(payload) + require.NoError(t, err) - withdrawalsRoot, err := payload.WithdrawalsRoot() - if errors.Is(err, consensus_types.ErrUnsupportedField) { - withdrawals, err := payload.Withdrawals() - require.NoError(t, err) - withdrawalsRootArray, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload) - require.NoError(t, err) - withdrawalsRoot = withdrawalsRootArray[:] - } else { - require.NoError(t, err) - } + withdrawalsRoot, err := light_client.ComputeWithdrawalsRoot(payload) + require.NoError(t, err) blobGasUsed, err := payload.BlobGasUsed() require.NoError(t, err) From 98692b225e98444247bde6858c688f78db24b8f0 Mon Sep 17 00:00:00 2001 From: rupam-04 Date: Wed, 11 Sep 2024 23:31:26 +0530 Subject: [PATCH 07/12] add blinded beacon block support to tests --- beacon-chain/core/light-client/lightclient.go | 84 +++++++++++-------- .../core/light-client/lightclient_test.go | 40 +++++++-- 2 files changed, 80 insertions(+), 44 deletions(-) diff --git a/beacon-chain/core/light-client/lightclient.go b/beacon-chain/core/light-client/lightclient.go index 29319edba79..dfb38057045 100644 --- a/beacon-chain/core/light-client/lightclient.go +++ b/beacon-chain/core/light-client/lightclient.go @@ -554,39 +554,27 @@ func NewLightClientUpdateFromOptimisticUpdate(update *ethpbv2.LightClientOptimis } func ComputeTransactionsRoot(payload interfaces.ExecutionData) ([]byte, error) { - transactionsRoot, err := payload.TransactionsRoot() - if errors.Is(err, consensus_types.ErrUnsupportedField) { - transactions, err := payload.Transactions() - if err != nil { - return nil, errors.Wrap(err, "could not get transactions") - } - transactionsRootArray, err := ssz.TransactionsRoot(transactions) - if err != nil { - return nil, errors.Wrap(err, "could not get transactions root") - } - transactionsRoot = transactionsRootArray[:] - } else if err != nil { + transactions, err := payload.Transactions() + if err != nil { + return nil, errors.Wrap(err, "could not get transactions") + } + transactionsRoot, err := ssz.TransactionsRoot(transactions) + if err != nil { return nil, errors.Wrap(err, "could not get transactions root") } - return transactionsRoot, nil + return transactionsRoot[:], nil } func ComputeWithdrawalsRoot(payload interfaces.ExecutionData) ([]byte, error) { - withdrawalsRoot, err := payload.WithdrawalsRoot() - if errors.Is(err, consensus_types.ErrUnsupportedField) { - withdrawals, err := payload.Withdrawals() - if err != nil { - return nil, errors.Wrap(err, "could not get withdrawals") - } - withdrawalsRootArray, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload) - if err != nil { - return nil, errors.Wrap(err, "could not get withdrawals root") - } - withdrawalsRoot = withdrawalsRootArray[:] - } else if err != nil { + withdrawals, err := payload.Withdrawals() + if err != nil { + return nil, errors.Wrap(err, "could not get withdrawals") + } + withdrawalsRoot, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload) + if err != nil { return nil, errors.Wrap(err, "could not get withdrawals root") } - return withdrawalsRoot, nil + return withdrawalsRoot[:], nil } func BlockToLightClientHeaderAltair(block interfaces.ReadOnlySignedBeaconBlock) (*ethpbv2.LightClientHeader, error) { @@ -618,11 +606,24 @@ func BlockToLightClientHeaderCapella(ctx context.Context, block interfaces.ReadO return nil, errors.Wrap(err, "could not get execution payload") } - transactionsRoot, err := ComputeTransactionsRoot(payload) - if err != nil { - return nil, err + transactionsRoot, err := payload.TransactionsRoot() + if errors.Is(err, consensus_types.ErrUnsupportedField) { + transactionsRoot, err = ComputeTransactionsRoot(payload) + if err != nil { + return nil, err + } + } else if err != nil { + return nil, errors.Wrap(err, "could not get transactions root") + } + withdrawalsRoot, err := payload.WithdrawalsRoot() + if errors.Is(err, consensus_types.ErrUnsupportedField) { + withdrawalsRoot, err = ComputeWithdrawalsRoot(payload) + if err != nil { + return nil, err + } + } else if err != nil { + return nil, errors.Wrap(err, "could not get withdrawals root") } - withdrawalsRoot, err := ComputeWithdrawalsRoot(payload) executionHeader := &v11.ExecutionPayloadHeaderCapella{ ParentHash: payload.ParentHash(), @@ -678,14 +679,25 @@ func BlockToLightClientHeaderDeneb(ctx context.Context, block interfaces.ReadOnl return nil, errors.Wrap(err, "could not get execution payload") } - transactionsRoot, err := ComputeTransactionsRoot(payload) - if err != nil { - return nil, err + transactionsRoot, err := payload.TransactionsRoot() + if errors.Is(err, consensus_types.ErrUnsupportedField) { + transactionsRoot, err = ComputeTransactionsRoot(payload) + if err != nil { + return nil, err + } + } else if err != nil { + return nil, errors.Wrap(err, "could not get transactions root") } - withdrawalsRoot, err := ComputeWithdrawalsRoot(payload) - if err != nil { - return nil, err + withdrawalsRoot, err := payload.WithdrawalsRoot() + if errors.Is(err, consensus_types.ErrUnsupportedField) { + withdrawalsRoot, err = ComputeWithdrawalsRoot(payload) + if err != nil { + return nil, err + } + } else if err != nil { + return nil, errors.Wrap(err, "could not get withdrawals root") } + blobGasUsed, err := payload.BlobGasUsed() if err != nil { return nil, errors.Wrap(err, "could not get blob gas used") diff --git a/beacon-chain/core/light-client/lightclient_test.go b/beacon-chain/core/light-client/lightclient_test.go index e864bc16dd7..5b537803eb0 100644 --- a/beacon-chain/core/light-client/lightclient_test.go +++ b/beacon-chain/core/light-client/lightclient_test.go @@ -177,11 +177,23 @@ func TestLightClient_BlockToLightClientHeaderCapella(t *testing.T) { payload, err := l.Block.Block().Body().Execution() require.NoError(t, err) - transactionsRoot, err := light_client.ComputeTransactionsRoot(payload) - require.NoError(t, err) + var transactionsRoot []byte + if !l.Block.Block().IsBlinded() { + transactionsRoot, err = light_client.ComputeTransactionsRoot(payload) + require.NoError(t, err) + } else { + transactionsRoot, err = payload.TransactionsRoot() + require.NoError(t, err) + } - withdrawalsRoot, err := light_client.ComputeWithdrawalsRoot(payload) - require.NoError(t, err) + var withdrawalsRoot []byte + if !l.Block.Block().IsBlinded() { + withdrawalsRoot, err = light_client.ComputeWithdrawalsRoot(payload) + require.NoError(t, err) + } else { + withdrawalsRoot, err = payload.WithdrawalsRoot() + require.NoError(t, err) + } executionHeader := &v11.ExecutionPayloadHeaderCapella{ ParentHash: payload.ParentHash(), @@ -230,11 +242,23 @@ func TestLightClient_BlockToLightClientHeaderDeneb(t *testing.T) { payload, err := l.Block.Block().Body().Execution() require.NoError(t, err) - transactionsRoot, err := light_client.ComputeTransactionsRoot(payload) - require.NoError(t, err) + var transactionsRoot []byte + if !l.Block.Block().IsBlinded() { + transactionsRoot, err = light_client.ComputeTransactionsRoot(payload) + require.NoError(t, err) + } else { + transactionsRoot, err = payload.TransactionsRoot() + require.NoError(t, err) + } - withdrawalsRoot, err := light_client.ComputeWithdrawalsRoot(payload) - require.NoError(t, err) + var withdrawalsRoot []byte + if !l.Block.Block().IsBlinded() { + withdrawalsRoot, err = light_client.ComputeWithdrawalsRoot(payload) + require.NoError(t, err) + } else { + withdrawalsRoot, err = payload.WithdrawalsRoot() + require.NoError(t, err) + } blobGasUsed, err := payload.BlobGasUsed() require.NoError(t, err) From 6050ced8e6d2dbf4dc6816616bb35ced09785f2c Mon Sep 17 00:00:00 2001 From: rupam-04 Date: Thu, 12 Sep 2024 00:47:22 +0530 Subject: [PATCH 08/12] revert "add blinded beacon block support to tests" --- beacon-chain/core/light-client/lightclient.go | 84 ++++++++----------- .../core/light-client/lightclient_test.go | 40 ++------- 2 files changed, 44 insertions(+), 80 deletions(-) diff --git a/beacon-chain/core/light-client/lightclient.go b/beacon-chain/core/light-client/lightclient.go index dfb38057045..29319edba79 100644 --- a/beacon-chain/core/light-client/lightclient.go +++ b/beacon-chain/core/light-client/lightclient.go @@ -554,27 +554,39 @@ func NewLightClientUpdateFromOptimisticUpdate(update *ethpbv2.LightClientOptimis } func ComputeTransactionsRoot(payload interfaces.ExecutionData) ([]byte, error) { - transactions, err := payload.Transactions() - if err != nil { - return nil, errors.Wrap(err, "could not get transactions") - } - transactionsRoot, err := ssz.TransactionsRoot(transactions) - if err != nil { + transactionsRoot, err := payload.TransactionsRoot() + if errors.Is(err, consensus_types.ErrUnsupportedField) { + transactions, err := payload.Transactions() + if err != nil { + return nil, errors.Wrap(err, "could not get transactions") + } + transactionsRootArray, err := ssz.TransactionsRoot(transactions) + if err != nil { + return nil, errors.Wrap(err, "could not get transactions root") + } + transactionsRoot = transactionsRootArray[:] + } else if err != nil { return nil, errors.Wrap(err, "could not get transactions root") } - return transactionsRoot[:], nil + return transactionsRoot, nil } func ComputeWithdrawalsRoot(payload interfaces.ExecutionData) ([]byte, error) { - withdrawals, err := payload.Withdrawals() - if err != nil { - return nil, errors.Wrap(err, "could not get withdrawals") - } - withdrawalsRoot, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload) - if err != nil { + withdrawalsRoot, err := payload.WithdrawalsRoot() + if errors.Is(err, consensus_types.ErrUnsupportedField) { + withdrawals, err := payload.Withdrawals() + if err != nil { + return nil, errors.Wrap(err, "could not get withdrawals") + } + withdrawalsRootArray, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload) + if err != nil { + return nil, errors.Wrap(err, "could not get withdrawals root") + } + withdrawalsRoot = withdrawalsRootArray[:] + } else if err != nil { return nil, errors.Wrap(err, "could not get withdrawals root") } - return withdrawalsRoot[:], nil + return withdrawalsRoot, nil } func BlockToLightClientHeaderAltair(block interfaces.ReadOnlySignedBeaconBlock) (*ethpbv2.LightClientHeader, error) { @@ -606,24 +618,11 @@ func BlockToLightClientHeaderCapella(ctx context.Context, block interfaces.ReadO return nil, errors.Wrap(err, "could not get execution payload") } - transactionsRoot, err := payload.TransactionsRoot() - if errors.Is(err, consensus_types.ErrUnsupportedField) { - transactionsRoot, err = ComputeTransactionsRoot(payload) - if err != nil { - return nil, err - } - } else if err != nil { - return nil, errors.Wrap(err, "could not get transactions root") - } - withdrawalsRoot, err := payload.WithdrawalsRoot() - if errors.Is(err, consensus_types.ErrUnsupportedField) { - withdrawalsRoot, err = ComputeWithdrawalsRoot(payload) - if err != nil { - return nil, err - } - } else if err != nil { - return nil, errors.Wrap(err, "could not get withdrawals root") + transactionsRoot, err := ComputeTransactionsRoot(payload) + if err != nil { + return nil, err } + withdrawalsRoot, err := ComputeWithdrawalsRoot(payload) executionHeader := &v11.ExecutionPayloadHeaderCapella{ ParentHash: payload.ParentHash(), @@ -679,25 +678,14 @@ func BlockToLightClientHeaderDeneb(ctx context.Context, block interfaces.ReadOnl return nil, errors.Wrap(err, "could not get execution payload") } - transactionsRoot, err := payload.TransactionsRoot() - if errors.Is(err, consensus_types.ErrUnsupportedField) { - transactionsRoot, err = ComputeTransactionsRoot(payload) - if err != nil { - return nil, err - } - } else if err != nil { - return nil, errors.Wrap(err, "could not get transactions root") + transactionsRoot, err := ComputeTransactionsRoot(payload) + if err != nil { + return nil, err } - withdrawalsRoot, err := payload.WithdrawalsRoot() - if errors.Is(err, consensus_types.ErrUnsupportedField) { - withdrawalsRoot, err = ComputeWithdrawalsRoot(payload) - if err != nil { - return nil, err - } - } else if err != nil { - return nil, errors.Wrap(err, "could not get withdrawals root") + withdrawalsRoot, err := ComputeWithdrawalsRoot(payload) + if err != nil { + return nil, err } - blobGasUsed, err := payload.BlobGasUsed() if err != nil { return nil, errors.Wrap(err, "could not get blob gas used") diff --git a/beacon-chain/core/light-client/lightclient_test.go b/beacon-chain/core/light-client/lightclient_test.go index 5b537803eb0..e864bc16dd7 100644 --- a/beacon-chain/core/light-client/lightclient_test.go +++ b/beacon-chain/core/light-client/lightclient_test.go @@ -177,23 +177,11 @@ func TestLightClient_BlockToLightClientHeaderCapella(t *testing.T) { payload, err := l.Block.Block().Body().Execution() require.NoError(t, err) - var transactionsRoot []byte - if !l.Block.Block().IsBlinded() { - transactionsRoot, err = light_client.ComputeTransactionsRoot(payload) - require.NoError(t, err) - } else { - transactionsRoot, err = payload.TransactionsRoot() - require.NoError(t, err) - } + transactionsRoot, err := light_client.ComputeTransactionsRoot(payload) + require.NoError(t, err) - var withdrawalsRoot []byte - if !l.Block.Block().IsBlinded() { - withdrawalsRoot, err = light_client.ComputeWithdrawalsRoot(payload) - require.NoError(t, err) - } else { - withdrawalsRoot, err = payload.WithdrawalsRoot() - require.NoError(t, err) - } + withdrawalsRoot, err := light_client.ComputeWithdrawalsRoot(payload) + require.NoError(t, err) executionHeader := &v11.ExecutionPayloadHeaderCapella{ ParentHash: payload.ParentHash(), @@ -242,23 +230,11 @@ func TestLightClient_BlockToLightClientHeaderDeneb(t *testing.T) { payload, err := l.Block.Block().Body().Execution() require.NoError(t, err) - var transactionsRoot []byte - if !l.Block.Block().IsBlinded() { - transactionsRoot, err = light_client.ComputeTransactionsRoot(payload) - require.NoError(t, err) - } else { - transactionsRoot, err = payload.TransactionsRoot() - require.NoError(t, err) - } + transactionsRoot, err := light_client.ComputeTransactionsRoot(payload) + require.NoError(t, err) - var withdrawalsRoot []byte - if !l.Block.Block().IsBlinded() { - withdrawalsRoot, err = light_client.ComputeWithdrawalsRoot(payload) - require.NoError(t, err) - } else { - withdrawalsRoot, err = payload.WithdrawalsRoot() - require.NoError(t, err) - } + withdrawalsRoot, err := light_client.ComputeWithdrawalsRoot(payload) + require.NoError(t, err) blobGasUsed, err := payload.BlobGasUsed() require.NoError(t, err) From 864b0460888405522d107cac62735e8dfa2fbd5a Mon Sep 17 00:00:00 2001 From: rupam-04 Date: Thu, 12 Sep 2024 04:02:18 +0530 Subject: [PATCH 09/12] add tests for blinded beacon block --- beacon-chain/core/light-client/lightclient.go | 3 + .../core/light-client/lightclient_test.go | 130 +++++++++++++- testing/util/lightclient.go | 169 ++++++++++++------ 3 files changed, 244 insertions(+), 58 deletions(-) diff --git a/beacon-chain/core/light-client/lightclient.go b/beacon-chain/core/light-client/lightclient.go index 29319edba79..d4d918a5f75 100644 --- a/beacon-chain/core/light-client/lightclient.go +++ b/beacon-chain/core/light-client/lightclient.go @@ -623,6 +623,9 @@ func BlockToLightClientHeaderCapella(ctx context.Context, block interfaces.ReadO return nil, err } withdrawalsRoot, err := ComputeWithdrawalsRoot(payload) + if err != nil { + return nil, err + } executionHeader := &v11.ExecutionPayloadHeaderCapella{ ParentHash: payload.ParentHash(), diff --git a/beacon-chain/core/light-client/lightclient_test.go b/beacon-chain/core/light-client/lightclient_test.go index e864bc16dd7..de4a6902d90 100644 --- a/beacon-chain/core/light-client/lightclient_test.go +++ b/beacon-chain/core/light-client/lightclient_test.go @@ -16,7 +16,7 @@ import ( ) func TestLightClient_NewLightClientOptimisticUpdateFromBeaconStateCapella(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestCapella() + l := util.NewTestLightClient(t).SetupTestCapella(false) update, err := lightClient.NewLightClientOptimisticUpdateFromBeaconState(l.Ctx, l.State, l.Block, l.AttestedState) require.NoError(t, err) @@ -48,7 +48,7 @@ func TestLightClient_NewLightClientOptimisticUpdateFromBeaconStateAltair(t *test } func TestLightClient_NewLightClientOptimisticUpdateFromBeaconStateDeneb(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestDeneb() + l := util.NewTestLightClient(t).SetupTestDeneb(false) update, err := lightClient.NewLightClientOptimisticUpdateFromBeaconState(l.Ctx, l.State, l.Block, l.AttestedState) require.NoError(t, err) @@ -63,7 +63,7 @@ func TestLightClient_NewLightClientOptimisticUpdateFromBeaconStateDeneb(t *testi require.DeepSSZEqual(t, ([][]byte)(nil), update.FinalityBranch, "Finality branch is not nil") } func TestLightClient_NewLightClientFinalityUpdateFromBeaconStateCapella(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestCapella() + l := util.NewTestLightClient(t).SetupTestCapella(false) update, err := lightClient.NewLightClientFinalityUpdateFromBeaconState(l.Ctx, l.State, l.Block, l.AttestedState, nil) require.NoError(t, err) require.NotNil(t, update, "update is nil") @@ -116,7 +116,7 @@ func TestLightClient_NewLightClientFinalityUpdateFromBeaconStateAltair(t *testin } func TestLightClient_NewLightClientFinalityUpdateFromBeaconStateDeneb(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestDeneb() + l := util.NewTestLightClient(t).SetupTestDeneb(false) update, err := lightClient.NewLightClientFinalityUpdateFromBeaconState(l.Ctx, l.State, l.Block, l.AttestedState, nil) require.NoError(t, err) @@ -162,8 +162,8 @@ func TestLightClient_BlockToLightClientHeaderAltair(t *testing.T) { require.DeepSSZEqual(t, bodyRoot[:], header.Beacon.BodyRoot, "Body root is not equal") } -func TestLightClient_BlockToLightClientHeaderCapella(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestCapella() +func TestLightClient_BlockToLightClientHeaderCapella_NonBlindedBeaconBlock(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestCapella(false) header, err := lightClient.BlockToLightClientHeaderCapella(l.Ctx, l.Block) require.NoError(t, err) @@ -215,8 +215,61 @@ func TestLightClient_BlockToLightClientHeaderCapella(t *testing.T) { require.DeepSSZEqual(t, executionPayloadProof, header.ExecutionBranch, "Execution payload proofs are not equal") } -func TestLightClient_BlockToLightClientHeaderDeneb(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestDeneb() +func TestLightClient_BlockToLightClientHeaderCapella_BlindedBeaconBlock(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestCapella(true) + + header, err := lightClient.BlockToLightClientHeaderCapella(l.Ctx, l.Block) + require.NoError(t, err) + require.NotNil(t, header, "header is nil") + + parentRoot := l.Block.Block().ParentRoot() + stateRoot := l.Block.Block().StateRoot() + bodyRoot, err := l.Block.Block().Body().HashTreeRoot() + require.NoError(t, err) + + payload, err := l.Block.Block().Body().Execution() + require.NoError(t, err) + + transactionsRoot, err := payload.TransactionsRoot() + require.NoError(t, err) + + withdrawalsRoot, err := payload.WithdrawalsRoot() + require.NoError(t, err) + + executionHeader := &v11.ExecutionPayloadHeaderCapella{ + ParentHash: payload.ParentHash(), + FeeRecipient: payload.FeeRecipient(), + StateRoot: payload.StateRoot(), + ReceiptsRoot: payload.ReceiptsRoot(), + LogsBloom: payload.LogsBloom(), + PrevRandao: payload.PrevRandao(), + BlockNumber: payload.BlockNumber(), + GasLimit: payload.GasLimit(), + GasUsed: payload.GasUsed(), + Timestamp: payload.Timestamp(), + ExtraData: payload.ExtraData(), + BaseFeePerGas: payload.BaseFeePerGas(), + BlockHash: payload.BlockHash(), + TransactionsRoot: transactionsRoot, + WithdrawalsRoot: withdrawalsRoot, + } + + executionPayloadProof, err := blocks.PayloadProof(l.Ctx, l.Block.Block()) + require.NoError(t, err) + + require.Equal(t, l.Block.Block().Slot(), header.Beacon.Slot, "Slot is not equal") + require.Equal(t, l.Block.Block().ProposerIndex(), header.Beacon.ProposerIndex, "Proposer index is not equal") + require.DeepSSZEqual(t, parentRoot[:], header.Beacon.ParentRoot, "Parent root is not equal") + require.DeepSSZEqual(t, stateRoot[:], header.Beacon.StateRoot, "State root is not equal") + require.DeepSSZEqual(t, bodyRoot[:], header.Beacon.BodyRoot, "Body root is not equal") + + require.DeepSSZEqual(t, executionHeader, header.Execution, "Execution headers are not equal") + + require.DeepSSZEqual(t, executionPayloadProof, header.ExecutionBranch, "Execution payload proofs are not equal") +} + +func TestLightClient_BlockToLightClientHeaderDeneb_NonBlindedBeaconBlock(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestDeneb(false) header, err := lightClient.BlockToLightClientHeaderDeneb(l.Ctx, l.Block) require.NoError(t, err) @@ -276,4 +329,65 @@ func TestLightClient_BlockToLightClientHeaderDeneb(t *testing.T) { require.DeepSSZEqual(t, executionPayloadProof, header.ExecutionBranch, "Execution payload proofs are not equal") } +func TestLightClient_BlockToLightClientHeaderDeneb_BlindedBeaconBlock(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestDeneb(true) + + header, err := lightClient.BlockToLightClientHeaderDeneb(l.Ctx, l.Block) + require.NoError(t, err) + require.NotNil(t, header, "header is nil") + + parentRoot := l.Block.Block().ParentRoot() + stateRoot := l.Block.Block().StateRoot() + bodyRoot, err := l.Block.Block().Body().HashTreeRoot() + require.NoError(t, err) + + payload, err := l.Block.Block().Body().Execution() + require.NoError(t, err) + + transactionsRoot, err := payload.TransactionsRoot() + require.NoError(t, err) + + withdrawalsRoot, err := payload.WithdrawalsRoot() + require.NoError(t, err) + + blobGasUsed, err := payload.BlobGasUsed() + require.NoError(t, err) + + excessBlobGas, err := payload.ExcessBlobGas() + require.NoError(t, err) + + executionHeader := &v11.ExecutionPayloadHeaderDeneb{ + ParentHash: payload.ParentHash(), + FeeRecipient: payload.FeeRecipient(), + StateRoot: payload.StateRoot(), + ReceiptsRoot: payload.ReceiptsRoot(), + LogsBloom: payload.LogsBloom(), + PrevRandao: payload.PrevRandao(), + BlockNumber: payload.BlockNumber(), + GasLimit: payload.GasLimit(), + GasUsed: payload.GasUsed(), + Timestamp: payload.Timestamp(), + ExtraData: payload.ExtraData(), + BaseFeePerGas: payload.BaseFeePerGas(), + BlockHash: payload.BlockHash(), + TransactionsRoot: transactionsRoot, + WithdrawalsRoot: withdrawalsRoot, + BlobGasUsed: blobGasUsed, + ExcessBlobGas: excessBlobGas, + } + + executionPayloadProof, err := blocks.PayloadProof(l.Ctx, l.Block.Block()) + require.NoError(t, err) + + require.Equal(t, l.Block.Block().Slot(), header.Beacon.Slot, "Slot is not equal") + require.Equal(t, l.Block.Block().ProposerIndex(), header.Beacon.ProposerIndex, "Proposer index is not equal") + require.DeepSSZEqual(t, parentRoot[:], header.Beacon.ParentRoot, "Parent root is not equal") + require.DeepSSZEqual(t, stateRoot[:], header.Beacon.StateRoot, "State root is not equal") + require.DeepSSZEqual(t, bodyRoot[:], header.Beacon.BodyRoot, "Body root is not equal") + + require.DeepSSZEqual(t, executionHeader, header.Execution, "Execution headers are not equal") + + require.DeepSSZEqual(t, executionPayloadProof, header.ExecutionBranch, "Execution payload proofs are not equal") +} + // TODO - add finality update tests with non-nil finalized block for different versions diff --git a/testing/util/lightclient.go b/testing/util/lightclient.go index dbdbaec9fb3..5dd17f9f8df 100644 --- a/testing/util/lightclient.go +++ b/testing/util/lightclient.go @@ -28,7 +28,7 @@ func NewTestLightClient(t *testing.T) *TestLightClient { return &TestLightClient{T: t} } -func (l *TestLightClient) SetupTestCapella() *TestLightClient { +func (l *TestLightClient) SetupTestCapella(blinded bool) *TestLightClient { ctx := context.Background() slot := primitives.Slot(params.BeaconConfig().CapellaForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) @@ -66,37 +66,71 @@ func (l *TestLightClient) SetupTestCapella() *TestLightClient { parentRoot, err := signedParent.Block().HashTreeRoot() require.NoError(l.T, err) - block := NewBeaconBlockCapella() - block.Block.Slot = slot - block.Block.ParentRoot = parentRoot[:] + if blinded { + block := NewBlindedBeaconBlockCapella() + block.Block.Slot = slot + block.Block.ParentRoot = parentRoot[:] - for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ { - block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) - } + for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ { + block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + } - signedBlock, err := blocks.NewSignedBeaconBlock(block) - require.NoError(l.T, err) + signedBlock, err := blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) - h, err := signedBlock.Header() - require.NoError(l.T, err) + h, err := signedBlock.Header() + require.NoError(l.T, err) - err = state.SetLatestBlockHeader(h.Header) - require.NoError(l.T, err) - stateRoot, err := state.HashTreeRoot(ctx) - require.NoError(l.T, err) + err = state.SetLatestBlockHeader(h.Header) + require.NoError(l.T, err) + stateRoot, err := state.HashTreeRoot(ctx) + require.NoError(l.T, err) - // get a new signed block so the root is updated with the new state root - block.Block.StateRoot = stateRoot[:] - signedBlock, err = blocks.NewSignedBeaconBlock(block) - require.NoError(l.T, err) + // get a new signed block so the root is updated with the new state root + block.Block.StateRoot = stateRoot[:] + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) - l.State = state - l.AttestedState = attestedState - l.AttestedHeader = attestedHeader - l.Block = signedBlock - l.Ctx = ctx + l.State = state + l.AttestedState = attestedState + l.AttestedHeader = attestedHeader + l.Block = signedBlock + l.Ctx = ctx - return l + return l + } else { + block := NewBeaconBlockCapella() + block.Block.Slot = slot + block.Block.ParentRoot = parentRoot[:] + + for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ { + block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + } + + signedBlock, err := blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + + h, err := signedBlock.Header() + require.NoError(l.T, err) + + err = state.SetLatestBlockHeader(h.Header) + require.NoError(l.T, err) + stateRoot, err := state.HashTreeRoot(ctx) + require.NoError(l.T, err) + + // get a new signed block so the root is updated with the new state root + block.Block.StateRoot = stateRoot[:] + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + + l.State = state + l.AttestedState = attestedState + l.AttestedHeader = attestedHeader + l.Block = signedBlock + l.Ctx = ctx + + return l + } } func (l *TestLightClient) SetupTestAltair() *TestLightClient { @@ -170,7 +204,7 @@ func (l *TestLightClient) SetupTestAltair() *TestLightClient { return l } -func (l *TestLightClient) SetupTestDeneb() *TestLightClient { +func (l *TestLightClient) SetupTestDeneb(blinded bool) *TestLightClient { ctx := context.Background() slot := primitives.Slot(params.BeaconConfig().DenebForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) @@ -208,37 +242,72 @@ func (l *TestLightClient) SetupTestDeneb() *TestLightClient { parentRoot, err := signedParent.Block().HashTreeRoot() require.NoError(l.T, err) - block := NewBeaconBlockDeneb() - block.Block.Slot = slot - block.Block.ParentRoot = parentRoot[:] + if blinded { + block := NewBlindedBeaconBlockDeneb() + block.Message.Slot = slot + block.Message.ParentRoot = parentRoot[:] - for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ { - block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) - } + for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ { + block.Message.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + } - signedBlock, err := blocks.NewSignedBeaconBlock(block) - require.NoError(l.T, err) + signedBlock, err := blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) - h, err := signedBlock.Header() - require.NoError(l.T, err) + h, err := signedBlock.Header() + require.NoError(l.T, err) - err = state.SetLatestBlockHeader(h.Header) - require.NoError(l.T, err) - stateRoot, err := state.HashTreeRoot(ctx) - require.NoError(l.T, err) + err = state.SetLatestBlockHeader(h.Header) + require.NoError(l.T, err) + stateRoot, err := state.HashTreeRoot(ctx) + require.NoError(l.T, err) - // get a new signed block so the root is updated with the new state root - block.Block.StateRoot = stateRoot[:] - signedBlock, err = blocks.NewSignedBeaconBlock(block) - require.NoError(l.T, err) + // get a new signed block so the root is updated with the new state root + block.Message.StateRoot = stateRoot[:] + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) - l.State = state - l.AttestedState = attestedState - l.AttestedHeader = attestedHeader - l.Block = signedBlock - l.Ctx = ctx + l.State = state + l.AttestedState = attestedState + l.AttestedHeader = attestedHeader + l.Block = signedBlock + l.Ctx = ctx - return l + return l + } else { + + block := NewBeaconBlockDeneb() + block.Block.Slot = slot + block.Block.ParentRoot = parentRoot[:] + + for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ { + block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + } + + signedBlock, err := blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + + h, err := signedBlock.Header() + require.NoError(l.T, err) + + err = state.SetLatestBlockHeader(h.Header) + require.NoError(l.T, err) + stateRoot, err := state.HashTreeRoot(ctx) + require.NoError(l.T, err) + + // get a new signed block so the root is updated with the new state root + block.Block.StateRoot = stateRoot[:] + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + + l.State = state + l.AttestedState = attestedState + l.AttestedHeader = attestedHeader + l.Block = signedBlock + l.Ctx = ctx + + return l + } } func (l *TestLightClient) CheckAttestedHeader(update *ethpbv2.LightClientUpdate) { From a805401184f78b630239410e04cb8c8868d5d2c4 Mon Sep 17 00:00:00 2001 From: rupam-04 Date: Thu, 12 Sep 2024 04:07:51 +0530 Subject: [PATCH 10/12] lint --- testing/util/lightclient.go | 1 - 1 file changed, 1 deletion(-) diff --git a/testing/util/lightclient.go b/testing/util/lightclient.go index 5dd17f9f8df..bd44641e843 100644 --- a/testing/util/lightclient.go +++ b/testing/util/lightclient.go @@ -275,7 +275,6 @@ func (l *TestLightClient) SetupTestDeneb(blinded bool) *TestLightClient { return l } else { - block := NewBeaconBlockDeneb() block.Block.Slot = slot block.Block.ParentRoot = parentRoot[:] From 97b789f057d91d756a17f1c618c5003de3847ef9 Mon Sep 17 00:00:00 2001 From: rupam-04 Date: Thu, 12 Sep 2024 20:49:10 +0530 Subject: [PATCH 11/12] refactor: move common code outside of if-else --- testing/util/lightclient.go | 54 ++++++++++++++----------------------- 1 file changed, 20 insertions(+), 34 deletions(-) diff --git a/testing/util/lightclient.go b/testing/util/lightclient.go index bd44641e843..cece6018ed2 100644 --- a/testing/util/lightclient.go +++ b/testing/util/lightclient.go @@ -66,6 +66,7 @@ func (l *TestLightClient) SetupTestCapella(blinded bool) *TestLightClient { parentRoot, err := signedParent.Block().HashTreeRoot() require.NoError(l.T, err) + var signedBlock interfaces.SignedBeaconBlock if blinded { block := NewBlindedBeaconBlockCapella() block.Block.Slot = slot @@ -75,7 +76,7 @@ func (l *TestLightClient) SetupTestCapella(blinded bool) *TestLightClient { block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) } - signedBlock, err := blocks.NewSignedBeaconBlock(block) + signedBlock, err = blocks.NewSignedBeaconBlock(block) require.NoError(l.T, err) h, err := signedBlock.Header() @@ -90,14 +91,6 @@ func (l *TestLightClient) SetupTestCapella(blinded bool) *TestLightClient { block.Block.StateRoot = stateRoot[:] signedBlock, err = blocks.NewSignedBeaconBlock(block) require.NoError(l.T, err) - - l.State = state - l.AttestedState = attestedState - l.AttestedHeader = attestedHeader - l.Block = signedBlock - l.Ctx = ctx - - return l } else { block := NewBeaconBlockCapella() block.Block.Slot = slot @@ -107,7 +100,7 @@ func (l *TestLightClient) SetupTestCapella(blinded bool) *TestLightClient { block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) } - signedBlock, err := blocks.NewSignedBeaconBlock(block) + signedBlock, err = blocks.NewSignedBeaconBlock(block) require.NoError(l.T, err) h, err := signedBlock.Header() @@ -122,15 +115,15 @@ func (l *TestLightClient) SetupTestCapella(blinded bool) *TestLightClient { block.Block.StateRoot = stateRoot[:] signedBlock, err = blocks.NewSignedBeaconBlock(block) require.NoError(l.T, err) + } - l.State = state - l.AttestedState = attestedState - l.AttestedHeader = attestedHeader - l.Block = signedBlock - l.Ctx = ctx + l.State = state + l.AttestedState = attestedState + l.AttestedHeader = attestedHeader + l.Block = signedBlock + l.Ctx = ctx - return l - } + return l } func (l *TestLightClient) SetupTestAltair() *TestLightClient { @@ -242,6 +235,7 @@ func (l *TestLightClient) SetupTestDeneb(blinded bool) *TestLightClient { parentRoot, err := signedParent.Block().HashTreeRoot() require.NoError(l.T, err) + var signedBlock interfaces.SignedBeaconBlock if blinded { block := NewBlindedBeaconBlockDeneb() block.Message.Slot = slot @@ -251,7 +245,7 @@ func (l *TestLightClient) SetupTestDeneb(blinded bool) *TestLightClient { block.Message.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) } - signedBlock, err := blocks.NewSignedBeaconBlock(block) + signedBlock, err = blocks.NewSignedBeaconBlock(block) require.NoError(l.T, err) h, err := signedBlock.Header() @@ -266,14 +260,6 @@ func (l *TestLightClient) SetupTestDeneb(blinded bool) *TestLightClient { block.Message.StateRoot = stateRoot[:] signedBlock, err = blocks.NewSignedBeaconBlock(block) require.NoError(l.T, err) - - l.State = state - l.AttestedState = attestedState - l.AttestedHeader = attestedHeader - l.Block = signedBlock - l.Ctx = ctx - - return l } else { block := NewBeaconBlockDeneb() block.Block.Slot = slot @@ -283,7 +269,7 @@ func (l *TestLightClient) SetupTestDeneb(blinded bool) *TestLightClient { block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) } - signedBlock, err := blocks.NewSignedBeaconBlock(block) + signedBlock, err = blocks.NewSignedBeaconBlock(block) require.NoError(l.T, err) h, err := signedBlock.Header() @@ -298,15 +284,15 @@ func (l *TestLightClient) SetupTestDeneb(blinded bool) *TestLightClient { block.Block.StateRoot = stateRoot[:] signedBlock, err = blocks.NewSignedBeaconBlock(block) require.NoError(l.T, err) + } - l.State = state - l.AttestedState = attestedState - l.AttestedHeader = attestedHeader - l.Block = signedBlock - l.Ctx = ctx + l.State = state + l.AttestedState = attestedState + l.AttestedHeader = attestedHeader + l.Block = signedBlock + l.Ctx = ctx - return l - } + return l } func (l *TestLightClient) CheckAttestedHeader(update *ethpbv2.LightClientUpdate) { From dbb570947d41e401d503f450e5a7900274fd999b Mon Sep 17 00:00:00 2001 From: rupam-04 Date: Thu, 12 Sep 2024 21:11:25 +0530 Subject: [PATCH 12/12] fix dependencies --- beacon-chain/core/light-client/BUILD.bazel | 2 ++ 1 file changed, 2 insertions(+) diff --git a/beacon-chain/core/light-client/BUILD.bazel b/beacon-chain/core/light-client/BUILD.bazel index 094c8782a2f..febad0829c5 100644 --- a/beacon-chain/core/light-client/BUILD.bazel +++ b/beacon-chain/core/light-client/BUILD.bazel @@ -30,7 +30,9 @@ go_test( deps = [ ":go_default_library", "//config/params:go_default_library", + "//consensus-types/blocks:go_default_library", "//consensus-types/primitives:go_default_library", + "//proto/engine/v1:go_default_library", "//proto/eth/v2:go_default_library", "//testing/require:go_default_library", "//testing/util:go_default_library",