From e20c4598401bcf8f771791e275ea1bd1bf3ac85c Mon Sep 17 00:00:00 2001 From: nidhi-singh02 Date: Wed, 27 Nov 2024 22:59:09 +0530 Subject: [PATCH 01/25] validate genesis stuff Signed-off-by: nidhi-singh02 --- consensus/cometbft/service/abci.go | 11 +- consensus/cometbft/service/genesis.go | 194 +++++++++++++++++++++++++- 2 files changed, 201 insertions(+), 4 deletions(-) diff --git a/consensus/cometbft/service/abci.go b/consensus/cometbft/service/abci.go index 4298ce7dd4..c72820bea2 100644 --- a/consensus/cometbft/service/abci.go +++ b/consensus/cometbft/service/abci.go @@ -47,10 +47,19 @@ var ( errNilFinalizeBlockState = errors.New("finalizeBlockState is nil") ) +//nolint:gocognit // this is fine. func (s *Service[LoggerT]) InitChain( _ context.Context, req *cmtabci.InitChainRequest, ) (*cmtabci.InitChainResponse, error) { + // Validate the genesis state. + err := s.validateGenesisState(req.AppStateBytes) + if err != nil { + return nil, err + } + + s.logger.Info("genesis state validation successful") + if req.ChainId != s.chainID { return nil, fmt.Errorf( "invalid chain-id on InitChain; expected: %s, got: %s", @@ -78,7 +87,7 @@ func (s *Service[LoggerT]) InitChain( // if req.InitialHeight is > 1, then we set the initial version on all // stores if req.InitialHeight > 1 { - if err := s.sm.CommitMultiStore(). + if err = s.sm.CommitMultiStore(). SetInitialVersion(req.InitialHeight); err != nil { return nil, err } diff --git a/consensus/cometbft/service/genesis.go b/consensus/cometbft/service/genesis.go index a5869bc3d9..89774643b9 100644 --- a/consensus/cometbft/service/genesis.go +++ b/consensus/cometbft/service/genesis.go @@ -21,15 +21,22 @@ package cometbft import ( + "bytes" "crypto/sha256" + "fmt" + "strings" - "github.com/berachain/beacon-kit/consensus-types/types" - "github.com/berachain/beacon-kit/primitives/encoding/json" + "github.com/berachain/beacon-kit/mod/consensus-types/pkg/types" + "github.com/berachain/beacon-kit/mod/errors" + "github.com/berachain/beacon-kit/mod/primitives/pkg/common" + "github.com/berachain/beacon-kit/mod/primitives/pkg/encoding/json" cmtcfg "github.com/cometbft/cometbft/config" "github.com/cometbft/cometbft/node" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" ) +const maxExtraDataSize = 32 + // DefaultGenesis returns the default genesis state for the application. func (s *Service[_]) DefaultGenesis() map[string]json.RawMessage { // Implement the default genesis state for the application. @@ -44,13 +51,194 @@ func (s *Service[_]) DefaultGenesis() map[string]json.RawMessage { return gen } +// validateGenesisState unmarshal and validates the genesis state. +func (s *Service[LoggerT]) validateGenesisState( + appStateBytes []byte, +) error { + var genesisState map[string]json.RawMessage + if err := json.Unmarshal(appStateBytes, &genesisState); err != nil { + return err + } + + if err := s.ValidateGenesis(genesisState); err != nil { + return err + } + + return nil +} + +// BeaconGenesisState represents the structure of the +// beacon module's genesis state. +// +//nolint:lll +type BeaconGenesisState struct { + ForkVersion string `json:"fork_version"` + Deposits []types.Deposit `json:"deposits"` + ExecutionPayloadHeader types.ExecutionPayloadHeader `json:"execution_payload_header"` +} + // ValidateGenesis validates the provided genesis state. func (s *Service[_]) ValidateGenesis( - _ map[string]json.RawMessage, + genesisState map[string]json.RawMessage, ) error { // Implement the validation logic for the provided genesis state. // This should validate the genesis state for each module in the // application. + + // Validate that required modules are present in genesis + beaconGenesisBz, ok := genesisState["beacon"] + if !ok { + return errors.New( + "beacon module genesis state is required but was not found", + ) + } + + // Unmarshal and validate beacon module genesis state + var beaconGenesis BeaconGenesisState + if err := json.Unmarshal(beaconGenesisBz, &beaconGenesis); err != nil { + return fmt.Errorf( + "failed to unmarshal beacon genesis state: %w", + err, + ) + } + + // Validate fork version format (should be 0x followed by 8 hex characters) + if !strings.HasPrefix(beaconGenesis.ForkVersion, "0x") || + len(beaconGenesis.ForkVersion) != 10 { + return fmt.Errorf("invalid fork version format: %s", + beaconGenesis.ForkVersion, + ) + } + + if err := validateDeposits(beaconGenesis.Deposits); err != nil { + return fmt.Errorf("invalid deposits: %w", err) + } + + if err := validateExecutionHeader( + beaconGenesis.ExecutionPayloadHeader, + ); err != nil { + return fmt.Errorf("invalid execution payload header: %w", err) + } + + return nil +} + +func validateDeposits(deposits []types.Deposit) error { + if len(deposits) == 0 { + return errors.New("at least one deposit is required") + } + + seenPubkeys := make(map[string]bool) + + for i, deposit := range deposits { + // Validate BLS public key is not zero + if isZeroBytes(deposit.Pubkey[:]) { + return fmt.Errorf("deposit %d has zero public key", i) + } + // Check for duplicate pubkeys + pubkeyStr := string(deposit.Pubkey[:]) + if seenPubkeys[pubkeyStr] { + return fmt.Errorf("duplicate pubkey found in deposit %d", i) + } + seenPubkeys[pubkeyStr] = true + + // Validate withdrawal credentials + if isZeroBytes(deposit.Credentials[:]) { + return fmt.Errorf( + "invalid withdrawal credentials length for deposit %d", + i, + ) + } + + // Validate amount is non-zero + if deposit.Amount == 0 { + return fmt.Errorf("deposit %d has zero amount", i) + } + + // Validate signature is not empty + if isZeroBytes(deposit.Signature[:]) { + return fmt.Errorf("invalid signature length for deposit %d", i) + } + + // Validate index matches position + if uint64(deposit.GetIndex()) != uint64(i) { + return fmt.Errorf( + "deposit index %d does not match position %d", + deposit.GetIndex(), + i, + ) + } + } + + return nil +} + +func isZeroBytes(b []byte) bool { + for _, byte2 := range b { + if byte2 != 0 { + return false + } + } + return true +} + +func validateExecutionHeader(header types.ExecutionPayloadHeader) error { + // Validate hash fields are not zero + zeroHash := common.ExecutionHash{} + // For genesis block (when block number is 0), ParentHash must be zero + // For non-genesis blocks, ParentHash cannot be zero + if header.Number == 0 { + if !bytes.Equal(header.ParentHash[:], zeroHash[:]) { + return errors.New("parent hash must be zero for genesis block") + } + } else { + if bytes.Equal(header.ParentHash[:], zeroHash[:]) { + return errors.New("parent hash cannot be zero for non-genesis block") + } + } + + if bytes.Equal(header.StateRoot[:], zeroHash[:]) { + return errors.New("state root cannot be zero") + } + if bytes.Equal(header.ReceiptsRoot[:], zeroHash[:]) { + return errors.New("receipts root cannot be zero") + } + if bytes.Equal(header.BlockHash[:], zeroHash[:]) { + return errors.New("block hash cannot be zero") + } + if bytes.Equal(header.TransactionsRoot[:], zeroHash[:]) { + return errors.New("transactions root cannot be zero") + } + + // Fee recipient can be zero in genesis block + // No need to validate fee recipient for genesis + + // We don't validate LogsBloom as it can legitimately be + // all zeros in a genesis block or in blocks with no logs + + // Validate numeric fields + if header.GasLimit == 0 { + return errors.New("gas limit cannot be zero") + } + + // Extra data length check (max 32 bytes as per SSZ definition) + if len(header.ExtraData) > maxExtraDataSize { + return fmt.Errorf( + "extra data too long: got %d bytes, max 32 bytes", + len(header.ExtraData), + ) + } + + // Validate base fee per gas + if header.BaseFeePerGas == nil { + return errors.New("base fee per gas cannot be nil") + } + + // Additional Deneb-specific validations for blob gas + if header.BlobGasUsed > header.GetGasLimit() { + return errors.New("blob gas used exceeds gas limit") + } + return nil } From 91a03b0ed81dcfe6d9559e098423203b98b2f334 Mon Sep 17 00:00:00 2001 From: nidhi-singh02 Date: Thu, 28 Nov 2024 12:20:32 +0530 Subject: [PATCH 02/25] cleanup and gosec Signed-off-by: nidhi-singh02 --- consensus/cometbft/service/abci.go | 8 ++-- consensus/cometbft/service/genesis.go | 53 ++++++++++++--------------- 2 files changed, 28 insertions(+), 33 deletions(-) diff --git a/consensus/cometbft/service/abci.go b/consensus/cometbft/service/abci.go index c72820bea2..6d23155418 100644 --- a/consensus/cometbft/service/abci.go +++ b/consensus/cometbft/service/abci.go @@ -52,14 +52,16 @@ func (s *Service[LoggerT]) InitChain( _ context.Context, req *cmtabci.InitChainRequest, ) (*cmtabci.InitChainResponse, error) { + var genesisState map[string]json.RawMessage + if err := json.Unmarshal(req.AppStateBytes, &genesisState); err != nil { + return nil, err + } // Validate the genesis state. - err := s.validateGenesisState(req.AppStateBytes) + err := s.ValidateGenesis(genesisState) if err != nil { return nil, err } - s.logger.Info("genesis state validation successful") - if req.ChainId != s.chainID { return nil, fmt.Errorf( "invalid chain-id on InitChain; expected: %s, got: %s", diff --git a/consensus/cometbft/service/genesis.go b/consensus/cometbft/service/genesis.go index 89774643b9..b6d22be7f4 100644 --- a/consensus/cometbft/service/genesis.go +++ b/consensus/cometbft/service/genesis.go @@ -24,6 +24,7 @@ import ( "bytes" "crypto/sha256" "fmt" + "math" "strings" "github.com/berachain/beacon-kit/mod/consensus-types/pkg/types" @@ -51,22 +52,6 @@ func (s *Service[_]) DefaultGenesis() map[string]json.RawMessage { return gen } -// validateGenesisState unmarshal and validates the genesis state. -func (s *Service[LoggerT]) validateGenesisState( - appStateBytes []byte, -) error { - var genesisState map[string]json.RawMessage - if err := json.Unmarshal(appStateBytes, &genesisState); err != nil { - return err - } - - if err := s.ValidateGenesis(genesisState); err != nil { - return err - } - - return nil -} - // BeaconGenesisState represents the structure of the // beacon module's genesis state. // @@ -93,7 +78,6 @@ func (s *Service[_]) ValidateGenesis( ) } - // Unmarshal and validate beacon module genesis state var beaconGenesis BeaconGenesisState if err := json.Unmarshal(beaconGenesisBz, &beaconGenesis); err != nil { return fmt.Errorf( @@ -131,7 +115,28 @@ func validateDeposits(deposits []types.Deposit) error { seenPubkeys := make(map[string]bool) for i, deposit := range deposits { - // Validate BLS public key is not zero + depositIndex := deposit.GetIndex() + + // Validate deposit index bounds + if depositIndex < 0 { + return fmt.Errorf("deposit has invalid negative index: %d", depositIndex) + } + + // Check depositIndex bounds before conversion + if depositIndex > math.MaxInt64 { + return fmt.Errorf("deposit index %d exceeds maximum allowed value", depositIndex) + } + + //#nosec:G701 // realistically fine in practice. + // Validate index matches position + if int64(depositIndex) != int64(i) { + return fmt.Errorf( + "deposit index %d does not match position %d", + depositIndex, + i, + ) + } + if isZeroBytes(deposit.Pubkey[:]) { return fmt.Errorf("deposit %d has zero public key", i) } @@ -142,7 +147,6 @@ func validateDeposits(deposits []types.Deposit) error { } seenPubkeys[pubkeyStr] = true - // Validate withdrawal credentials if isZeroBytes(deposit.Credentials[:]) { return fmt.Errorf( "invalid withdrawal credentials length for deposit %d", @@ -150,24 +154,13 @@ func validateDeposits(deposits []types.Deposit) error { ) } - // Validate amount is non-zero if deposit.Amount == 0 { return fmt.Errorf("deposit %d has zero amount", i) } - // Validate signature is not empty if isZeroBytes(deposit.Signature[:]) { return fmt.Errorf("invalid signature length for deposit %d", i) } - - // Validate index matches position - if uint64(deposit.GetIndex()) != uint64(i) { - return fmt.Errorf( - "deposit index %d does not match position %d", - deposit.GetIndex(), - i, - ) - } } return nil From 0a3d099afc43dbd058a324ea3bfe98a289f21a7d Mon Sep 17 00:00:00 2001 From: nidhi-singh02 Date: Thu, 28 Nov 2024 12:30:17 +0530 Subject: [PATCH 03/25] linter and block no check Signed-off-by: nidhi-singh02 --- consensus/cometbft/service/genesis.go | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/consensus/cometbft/service/genesis.go b/consensus/cometbft/service/genesis.go index b6d22be7f4..69e6e02a6b 100644 --- a/consensus/cometbft/service/genesis.go +++ b/consensus/cometbft/service/genesis.go @@ -24,7 +24,6 @@ import ( "bytes" "crypto/sha256" "fmt" - "math" "strings" "github.com/berachain/beacon-kit/mod/consensus-types/pkg/types" @@ -116,17 +115,6 @@ func validateDeposits(deposits []types.Deposit) error { for i, deposit := range deposits { depositIndex := deposit.GetIndex() - - // Validate deposit index bounds - if depositIndex < 0 { - return fmt.Errorf("deposit has invalid negative index: %d", depositIndex) - } - - // Check depositIndex bounds before conversion - if depositIndex > math.MaxInt64 { - return fmt.Errorf("deposit index %d exceeds maximum allowed value", depositIndex) - } - //#nosec:G701 // realistically fine in practice. // Validate index matches position if int64(depositIndex) != int64(i) { @@ -203,6 +191,11 @@ func validateExecutionHeader(header types.ExecutionPayloadHeader) error { return errors.New("transactions root cannot be zero") } + // Check block number to be 0 + if header.Number != 0 { + return errors.New("block number must be 0 for genesis block") + } + // Fee recipient can be zero in genesis block // No need to validate fee recipient for genesis From abf7f73e8d6f23f3913b68a53b35e737a21e8727 Mon Sep 17 00:00:00 2001 From: nidhi-singh02 Date: Thu, 28 Nov 2024 12:49:21 +0530 Subject: [PATCH 04/25] helper func above the calling func Signed-off-by: nidhi-singh02 --- consensus/cometbft/service/genesis.go | 127 +++++++++++++------------- 1 file changed, 62 insertions(+), 65 deletions(-) diff --git a/consensus/cometbft/service/genesis.go b/consensus/cometbft/service/genesis.go index 69e6e02a6b..035e26e64f 100644 --- a/consensus/cometbft/service/genesis.go +++ b/consensus/cometbft/service/genesis.go @@ -37,6 +37,16 @@ import ( const maxExtraDataSize = 32 +// BeaconGenesisState represents the structure of the +// beacon module's genesis state. +// +//nolint:lll // JSON tags are long. +type BeaconGenesisState struct { + ForkVersion string `json:"fork_version"` + Deposits []types.Deposit `json:"deposits"` + ExecutionPayloadHeader types.ExecutionPayloadHeader `json:"execution_payload_header"` +} + // DefaultGenesis returns the default genesis state for the application. func (s *Service[_]) DefaultGenesis() map[string]json.RawMessage { // Implement the default genesis state for the application. @@ -51,61 +61,7 @@ func (s *Service[_]) DefaultGenesis() map[string]json.RawMessage { return gen } -// BeaconGenesisState represents the structure of the -// beacon module's genesis state. -// -//nolint:lll -type BeaconGenesisState struct { - ForkVersion string `json:"fork_version"` - Deposits []types.Deposit `json:"deposits"` - ExecutionPayloadHeader types.ExecutionPayloadHeader `json:"execution_payload_header"` -} - -// ValidateGenesis validates the provided genesis state. -func (s *Service[_]) ValidateGenesis( - genesisState map[string]json.RawMessage, -) error { - // Implement the validation logic for the provided genesis state. - // This should validate the genesis state for each module in the - // application. - - // Validate that required modules are present in genesis - beaconGenesisBz, ok := genesisState["beacon"] - if !ok { - return errors.New( - "beacon module genesis state is required but was not found", - ) - } - - var beaconGenesis BeaconGenesisState - if err := json.Unmarshal(beaconGenesisBz, &beaconGenesis); err != nil { - return fmt.Errorf( - "failed to unmarshal beacon genesis state: %w", - err, - ) - } - - // Validate fork version format (should be 0x followed by 8 hex characters) - if !strings.HasPrefix(beaconGenesis.ForkVersion, "0x") || - len(beaconGenesis.ForkVersion) != 10 { - return fmt.Errorf("invalid fork version format: %s", - beaconGenesis.ForkVersion, - ) - } - - if err := validateDeposits(beaconGenesis.Deposits); err != nil { - return fmt.Errorf("invalid deposits: %w", err) - } - - if err := validateExecutionHeader( - beaconGenesis.ExecutionPayloadHeader, - ); err != nil { - return fmt.Errorf("invalid execution payload header: %w", err) - } - - return nil -} - +// validateDeposits validates the provided deposits. func validateDeposits(deposits []types.Deposit) error { if len(deposits) == 0 { return errors.New("at least one deposit is required") @@ -154,6 +110,7 @@ func validateDeposits(deposits []types.Deposit) error { return nil } +// isZeroBytes returns true if the provided byte slice is all zeros. func isZeroBytes(b []byte) bool { for _, byte2 := range b { if byte2 != 0 { @@ -163,19 +120,13 @@ func isZeroBytes(b []byte) bool { return true } +// validateExecutionHeader validates the provided execution payload header. func validateExecutionHeader(header types.ExecutionPayloadHeader) error { // Validate hash fields are not zero zeroHash := common.ExecutionHash{} // For genesis block (when block number is 0), ParentHash must be zero - // For non-genesis blocks, ParentHash cannot be zero - if header.Number == 0 { - if !bytes.Equal(header.ParentHash[:], zeroHash[:]) { - return errors.New("parent hash must be zero for genesis block") - } - } else { - if bytes.Equal(header.ParentHash[:], zeroHash[:]) { - return errors.New("parent hash cannot be zero for non-genesis block") - } + if !bytes.Equal(header.ParentHash[:], zeroHash[:]) { + return errors.New("parent hash must be zero for genesis block") } if bytes.Equal(header.StateRoot[:], zeroHash[:]) { @@ -207,7 +158,7 @@ func validateExecutionHeader(header types.ExecutionPayloadHeader) error { return errors.New("gas limit cannot be zero") } - // Extra data length check (max 32 bytes as per SSZ definition) + // Extra data length check (max 32 bytes) if len(header.ExtraData) > maxExtraDataSize { return fmt.Errorf( "extra data too long: got %d bytes, max 32 bytes", @@ -228,6 +179,52 @@ func validateExecutionHeader(header types.ExecutionPayloadHeader) error { return nil } +// ValidateGenesis validates the provided genesis state. +func (s *Service[_]) ValidateGenesis( + genesisState map[string]json.RawMessage, +) error { + // Implemented the validation logic for the provided genesis state. + // This should validate the genesis state for each module in the + // application. + + // Validate that required modules are present in genesis. Currently, + // only the beacon module is required. + beaconGenesisBz, ok := genesisState["beacon"] + if !ok { + return errors.New( + "beacon module genesis state is required but was not found", + ) + } + + var beaconGenesis BeaconGenesisState + if err := json.Unmarshal(beaconGenesisBz, &beaconGenesis); err != nil { + return fmt.Errorf( + "failed to unmarshal beacon genesis state: %w", + err, + ) + } + + // Validate fork version format (should be 0x followed by 8 hex characters) + if !strings.HasPrefix(beaconGenesis.ForkVersion, "0x") || + len(beaconGenesis.ForkVersion) != 10 { + return fmt.Errorf("invalid fork version format: %s", + beaconGenesis.ForkVersion, + ) + } + + if err := validateDeposits(beaconGenesis.Deposits); err != nil { + return fmt.Errorf("invalid deposits: %w", err) + } + + if err := validateExecutionHeader( + beaconGenesis.ExecutionPayloadHeader, + ); err != nil { + return fmt.Errorf("invalid execution payload header: %w", err) + } + + return nil +} + // GetGenDocProvider returns a function which returns the genesis doc from the // genesis file. func GetGenDocProvider( From 4e351a64006c204bca9d7f161a1bc608d9bff36d Mon Sep 17 00:00:00 2001 From: nidhi-singh02 Date: Thu, 28 Nov 2024 13:03:34 +0530 Subject: [PATCH 05/25] prev randao check Signed-off-by: nidhi-singh02 --- consensus/cometbft/service/genesis.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/consensus/cometbft/service/genesis.go b/consensus/cometbft/service/genesis.go index 035e26e64f..4189fc6ed7 100644 --- a/consensus/cometbft/service/genesis.go +++ b/consensus/cometbft/service/genesis.go @@ -147,6 +147,11 @@ func validateExecutionHeader(header types.ExecutionPayloadHeader) error { return errors.New("block number must be 0 for genesis block") } + // Validate prevRandao is zero for genesis + if !bytes.Equal(header.Random[:], zeroHash[:]) { + return errors.New("prevRandao must be zero for genesis block") + } + // Fee recipient can be zero in genesis block // No need to validate fee recipient for genesis From 729259e0cee13c2ca4ded3743e42d01f06f33e8e Mon Sep 17 00:00:00 2001 From: nidhi-singh02 Date: Thu, 28 Nov 2024 13:50:20 +0530 Subject: [PATCH 06/25] enhancements and new func added Signed-off-by: nidhi-singh02 --- consensus/cometbft/service/abci.go | 18 +++++------ consensus/cometbft/service/genesis.go | 43 +++++++++++++++++++-------- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/consensus/cometbft/service/abci.go b/consensus/cometbft/service/abci.go index 6d23155418..cbcddb3e3f 100644 --- a/consensus/cometbft/service/abci.go +++ b/consensus/cometbft/service/abci.go @@ -52,9 +52,17 @@ func (s *Service[LoggerT]) InitChain( _ context.Context, req *cmtabci.InitChainRequest, ) (*cmtabci.InitChainResponse, error) { + if req.ChainId != s.chainID { + return nil, fmt.Errorf( + "invalid chain-id on InitChain; expected: %s, got: %s", + s.chainID, + req.ChainId, + ) + } + var genesisState map[string]json.RawMessage if err := json.Unmarshal(req.AppStateBytes, &genesisState); err != nil { - return nil, err + return nil, fmt.Errorf("failed to unmarshal genesis state: %w", err) } // Validate the genesis state. err := s.ValidateGenesis(genesisState) @@ -62,14 +70,6 @@ func (s *Service[LoggerT]) InitChain( return nil, err } - if req.ChainId != s.chainID { - return nil, fmt.Errorf( - "invalid chain-id on InitChain; expected: %s, got: %s", - s.chainID, - req.ChainId, - ) - } - s.logger.Info( "InitChain", "initialHeight", diff --git a/consensus/cometbft/service/genesis.go b/consensus/cometbft/service/genesis.go index 4189fc6ed7..e6fa2ae551 100644 --- a/consensus/cometbft/service/genesis.go +++ b/consensus/cometbft/service/genesis.go @@ -23,6 +23,7 @@ package cometbft import ( "bytes" "crypto/sha256" + "encoding/hex" "fmt" "strings" @@ -61,6 +62,27 @@ func (s *Service[_]) DefaultGenesis() map[string]json.RawMessage { return gen } +// isZeroBytes returns true if the provided byte slice is all zeros. +func isZeroBytes(b []byte) bool { + for _, byteValue := range b { + if byteValue != 0 { + return false + } + } + return true +} + +// isValidForkVersion returns true if the provided fork version is valid. +// Validate fork version format (should be 0x followed by 8 hex characters) +func isValidForkVersion(forkVersion string) bool { + if !strings.HasPrefix(forkVersion, "0x") || len(forkVersion) != 10 { + return false + } + _, err := hex.DecodeString(forkVersion[2:]) + return err == nil + +} + // validateDeposits validates the provided deposits. func validateDeposits(deposits []types.Deposit) error { if len(deposits) == 0 { @@ -85,11 +107,11 @@ func validateDeposits(deposits []types.Deposit) error { return fmt.Errorf("deposit %d has zero public key", i) } // Check for duplicate pubkeys - pubkeyStr := string(deposit.Pubkey[:]) - if seenPubkeys[pubkeyStr] { + pubkeyHex := hex.EncodeToString(deposit.Pubkey[:]) + if seenPubkeys[pubkeyHex] { return fmt.Errorf("duplicate pubkey found in deposit %d", i) } - seenPubkeys[pubkeyStr] = true + seenPubkeys[pubkeyHex] = true if isZeroBytes(deposit.Credentials[:]) { return fmt.Errorf( @@ -110,16 +132,6 @@ func validateDeposits(deposits []types.Deposit) error { return nil } -// isZeroBytes returns true if the provided byte slice is all zeros. -func isZeroBytes(b []byte) bool { - for _, byte2 := range b { - if byte2 != 0 { - return false - } - } - return true -} - // validateExecutionHeader validates the provided execution payload header. func validateExecutionHeader(header types.ExecutionPayloadHeader) error { // Validate hash fields are not zero @@ -209,6 +221,11 @@ func (s *Service[_]) ValidateGenesis( ) } + if !isValidForkVersion(beaconGenesis.ForkVersion) { + return fmt.Errorf("invalid fork version format: %s", + beaconGenesis.ForkVersion, + ) + } // Validate fork version format (should be 0x followed by 8 hex characters) if !strings.HasPrefix(beaconGenesis.ForkVersion, "0x") || len(beaconGenesis.ForkVersion) != 10 { From 0bea76b65960611bee19964788d0b511bcd7c2cf Mon Sep 17 00:00:00 2001 From: nidhi-singh02 Date: Thu, 28 Nov 2024 13:58:25 +0530 Subject: [PATCH 07/25] lint Signed-off-by: nidhi-singh02 --- consensus/cometbft/service/genesis.go | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/consensus/cometbft/service/genesis.go b/consensus/cometbft/service/genesis.go index e6fa2ae551..f93505b6fe 100644 --- a/consensus/cometbft/service/genesis.go +++ b/consensus/cometbft/service/genesis.go @@ -73,7 +73,7 @@ func isZeroBytes(b []byte) bool { } // isValidForkVersion returns true if the provided fork version is valid. -// Validate fork version format (should be 0x followed by 8 hex characters) +// Validate fork version format (should be 0x followed by 8 hex characters). func isValidForkVersion(forkVersion string) bool { if !strings.HasPrefix(forkVersion, "0x") || len(forkVersion) != 10 { return false @@ -95,7 +95,7 @@ func validateDeposits(deposits []types.Deposit) error { depositIndex := deposit.GetIndex() //#nosec:G701 // realistically fine in practice. // Validate index matches position - if int64(depositIndex) != int64(i) { + if depositIndex.Unwrap() != uint64(i) { return fmt.Errorf( "deposit index %d does not match position %d", depositIndex, @@ -226,13 +226,6 @@ func (s *Service[_]) ValidateGenesis( beaconGenesis.ForkVersion, ) } - // Validate fork version format (should be 0x followed by 8 hex characters) - if !strings.HasPrefix(beaconGenesis.ForkVersion, "0x") || - len(beaconGenesis.ForkVersion) != 10 { - return fmt.Errorf("invalid fork version format: %s", - beaconGenesis.ForkVersion, - ) - } if err := validateDeposits(beaconGenesis.Deposits); err != nil { return fmt.Errorf("invalid deposits: %w", err) From 8fece51fccb503409d33e555ea5688d0a39c0181 Mon Sep 17 00:00:00 2001 From: nidhi-singh02 Date: Thu, 28 Nov 2024 14:03:13 +0530 Subject: [PATCH 08/25] linter work work work Signed-off-by: nidhi-singh02 --- consensus/cometbft/service/genesis.go | 1 - 1 file changed, 1 deletion(-) diff --git a/consensus/cometbft/service/genesis.go b/consensus/cometbft/service/genesis.go index f93505b6fe..f08eb4c294 100644 --- a/consensus/cometbft/service/genesis.go +++ b/consensus/cometbft/service/genesis.go @@ -80,7 +80,6 @@ func isValidForkVersion(forkVersion string) bool { } _, err := hex.DecodeString(forkVersion[2:]) return err == nil - } // validateDeposits validates the provided deposits. From 11ed660df6d511631593c46124c08b2738f774fa Mon Sep 17 00:00:00 2001 From: nidhi-singh02 Date: Thu, 28 Nov 2024 14:25:53 +0530 Subject: [PATCH 09/25] refactor validations into separate files Signed-off-by: nidhi-singh02 --- consensus/cometbft/service/genesis.go | 129 ------------------ .../cometbft/service/validate_deposits.go | 78 +++++++++++ .../service/validate_execution_header.go | 96 +++++++++++++ .../cometbft/service/validate_fork_version.go | 36 +++++ 4 files changed, 210 insertions(+), 129 deletions(-) create mode 100644 consensus/cometbft/service/validate_deposits.go create mode 100644 consensus/cometbft/service/validate_execution_header.go create mode 100644 consensus/cometbft/service/validate_fork_version.go diff --git a/consensus/cometbft/service/genesis.go b/consensus/cometbft/service/genesis.go index f08eb4c294..049b989165 100644 --- a/consensus/cometbft/service/genesis.go +++ b/consensus/cometbft/service/genesis.go @@ -21,23 +21,17 @@ package cometbft import ( - "bytes" "crypto/sha256" - "encoding/hex" "fmt" - "strings" "github.com/berachain/beacon-kit/mod/consensus-types/pkg/types" "github.com/berachain/beacon-kit/mod/errors" - "github.com/berachain/beacon-kit/mod/primitives/pkg/common" "github.com/berachain/beacon-kit/mod/primitives/pkg/encoding/json" cmtcfg "github.com/cometbft/cometbft/config" "github.com/cometbft/cometbft/node" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" ) -const maxExtraDataSize = 32 - // BeaconGenesisState represents the structure of the // beacon module's genesis state. // @@ -72,129 +66,6 @@ func isZeroBytes(b []byte) bool { return true } -// isValidForkVersion returns true if the provided fork version is valid. -// Validate fork version format (should be 0x followed by 8 hex characters). -func isValidForkVersion(forkVersion string) bool { - if !strings.HasPrefix(forkVersion, "0x") || len(forkVersion) != 10 { - return false - } - _, err := hex.DecodeString(forkVersion[2:]) - return err == nil -} - -// validateDeposits validates the provided deposits. -func validateDeposits(deposits []types.Deposit) error { - if len(deposits) == 0 { - return errors.New("at least one deposit is required") - } - - seenPubkeys := make(map[string]bool) - - for i, deposit := range deposits { - depositIndex := deposit.GetIndex() - //#nosec:G701 // realistically fine in practice. - // Validate index matches position - if depositIndex.Unwrap() != uint64(i) { - return fmt.Errorf( - "deposit index %d does not match position %d", - depositIndex, - i, - ) - } - - if isZeroBytes(deposit.Pubkey[:]) { - return fmt.Errorf("deposit %d has zero public key", i) - } - // Check for duplicate pubkeys - pubkeyHex := hex.EncodeToString(deposit.Pubkey[:]) - if seenPubkeys[pubkeyHex] { - return fmt.Errorf("duplicate pubkey found in deposit %d", i) - } - seenPubkeys[pubkeyHex] = true - - if isZeroBytes(deposit.Credentials[:]) { - return fmt.Errorf( - "invalid withdrawal credentials length for deposit %d", - i, - ) - } - - if deposit.Amount == 0 { - return fmt.Errorf("deposit %d has zero amount", i) - } - - if isZeroBytes(deposit.Signature[:]) { - return fmt.Errorf("invalid signature length for deposit %d", i) - } - } - - return nil -} - -// validateExecutionHeader validates the provided execution payload header. -func validateExecutionHeader(header types.ExecutionPayloadHeader) error { - // Validate hash fields are not zero - zeroHash := common.ExecutionHash{} - // For genesis block (when block number is 0), ParentHash must be zero - if !bytes.Equal(header.ParentHash[:], zeroHash[:]) { - return errors.New("parent hash must be zero for genesis block") - } - - if bytes.Equal(header.StateRoot[:], zeroHash[:]) { - return errors.New("state root cannot be zero") - } - if bytes.Equal(header.ReceiptsRoot[:], zeroHash[:]) { - return errors.New("receipts root cannot be zero") - } - if bytes.Equal(header.BlockHash[:], zeroHash[:]) { - return errors.New("block hash cannot be zero") - } - if bytes.Equal(header.TransactionsRoot[:], zeroHash[:]) { - return errors.New("transactions root cannot be zero") - } - - // Check block number to be 0 - if header.Number != 0 { - return errors.New("block number must be 0 for genesis block") - } - - // Validate prevRandao is zero for genesis - if !bytes.Equal(header.Random[:], zeroHash[:]) { - return errors.New("prevRandao must be zero for genesis block") - } - - // Fee recipient can be zero in genesis block - // No need to validate fee recipient for genesis - - // We don't validate LogsBloom as it can legitimately be - // all zeros in a genesis block or in blocks with no logs - - // Validate numeric fields - if header.GasLimit == 0 { - return errors.New("gas limit cannot be zero") - } - - // Extra data length check (max 32 bytes) - if len(header.ExtraData) > maxExtraDataSize { - return fmt.Errorf( - "extra data too long: got %d bytes, max 32 bytes", - len(header.ExtraData), - ) - } - - // Validate base fee per gas - if header.BaseFeePerGas == nil { - return errors.New("base fee per gas cannot be nil") - } - - // Additional Deneb-specific validations for blob gas - if header.BlobGasUsed > header.GetGasLimit() { - return errors.New("blob gas used exceeds gas limit") - } - - return nil -} - // ValidateGenesis validates the provided genesis state. func (s *Service[_]) ValidateGenesis( genesisState map[string]json.RawMessage, diff --git a/consensus/cometbft/service/validate_deposits.go b/consensus/cometbft/service/validate_deposits.go new file mode 100644 index 0000000000..dbd1320e97 --- /dev/null +++ b/consensus/cometbft/service/validate_deposits.go @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: BUSL-1.1 +// +// Copyright (C) 2024, Berachain Foundation. All rights reserved. +// Use of this software is governed by the Business Source License included +// in the LICENSE file of this repository and at www.mariadb.com/bsl11. +// +// ANY USE OF THE LICENSED WORK IN VIOLATION OF THIS LICENSE WILL AUTOMATICALLY +// TERMINATE YOUR RIGHTS UNDER THIS LICENSE FOR THE CURRENT AND ALL OTHER +// VERSIONS OF THE LICENSED WORK. +// +// THIS LICENSE DOES NOT GRANT YOU ANY RIGHT IN ANY TRADEMARK OR LOGO OF +// LICENSOR OR ITS AFFILIATES (PROVIDED THAT YOU MAY USE A TRADEMARK OR LOGO OF +// LICENSOR AS EXPRESSLY REQUIRED BY THIS LICENSE). +// +// TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON +// AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, +// EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND +// TITLE. + +package cometbft + +import ( + "encoding/hex" + "fmt" + + "github.com/berachain/beacon-kit/mod/consensus-types/pkg/types" + "github.com/berachain/beacon-kit/mod/errors" +) + +// validateDeposits validates the provided deposits. +func validateDeposits(deposits []types.Deposit) error { + if len(deposits) == 0 { + return errors.New("at least one deposit is required") + } + + seenPubkeys := make(map[string]bool) + + for i, deposit := range deposits { + depositIndex := deposit.GetIndex() + //#nosec:G701 // realistically fine in practice. + // Validate index matches position + if depositIndex.Unwrap() != uint64(i) { + return fmt.Errorf( + "deposit index %d does not match position %d", + depositIndex, + i, + ) + } + + if isZeroBytes(deposit.Pubkey[:]) { + return fmt.Errorf("deposit %d has a zeroed public key", i) + } + // Check for duplicate pubkeys + pubkeyHex := hex.EncodeToString(deposit.Pubkey[:]) + if seenPubkeys[pubkeyHex] { + return fmt.Errorf("duplicate pubkey found in deposit %d", i) + } + seenPubkeys[pubkeyHex] = true + + if isZeroBytes(deposit.Credentials[:]) { + return fmt.Errorf( + "deposit %d has zeroed withdrawal credentials", + i, + ) + } + + if deposit.Amount == 0 { + return fmt.Errorf("deposit %d has zero amount", i) + } + + if isZeroBytes(deposit.Signature[:]) { + return fmt.Errorf("deposit %d has a zeroed signature", i) + } + } + + return nil +} diff --git a/consensus/cometbft/service/validate_execution_header.go b/consensus/cometbft/service/validate_execution_header.go new file mode 100644 index 0000000000..4391827fc9 --- /dev/null +++ b/consensus/cometbft/service/validate_execution_header.go @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: BUSL-1.1 +// +// Copyright (C) 2024, Berachain Foundation. All rights reserved. +// Use of this software is governed by the Business Source License included +// in the LICENSE file of this repository and at www.mariadb.com/bsl11. +// +// ANY USE OF THE LICENSED WORK IN VIOLATION OF THIS LICENSE WILL AUTOMATICALLY +// TERMINATE YOUR RIGHTS UNDER THIS LICENSE FOR THE CURRENT AND ALL OTHER +// VERSIONS OF THE LICENSED WORK. +// +// THIS LICENSE DOES NOT GRANT YOU ANY RIGHT IN ANY TRADEMARK OR LOGO OF +// LICENSOR OR ITS AFFILIATES (PROVIDED THAT YOU MAY USE A TRADEMARK OR LOGO OF +// LICENSOR AS EXPRESSLY REQUIRED BY THIS LICENSE). +// +// TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON +// AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, +// EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND +// TITLE. + +package cometbft + +import ( + "bytes" + "fmt" + + "github.com/berachain/beacon-kit/mod/consensus-types/pkg/types" + "github.com/berachain/beacon-kit/mod/errors" + "github.com/berachain/beacon-kit/mod/primitives/pkg/common" +) + +const maxExtraDataSize = 32 + +// validateExecutionHeader validates the provided execution payload header. +func validateExecutionHeader(header types.ExecutionPayloadHeader) error { + // Validate hash fields are not zero + zeroHash := common.ExecutionHash{} + // For genesis block (when block number is 0), ParentHash must be zero + if !bytes.Equal(header.ParentHash[:], zeroHash[:]) { + return errors.New("parent hash must be zero for genesis block") + } + + if bytes.Equal(header.StateRoot[:], zeroHash[:]) { + return errors.New("state root cannot be zero") + } + if bytes.Equal(header.ReceiptsRoot[:], zeroHash[:]) { + return errors.New("receipts root cannot be zero") + } + if bytes.Equal(header.BlockHash[:], zeroHash[:]) { + return errors.New("block hash cannot be zero") + } + if bytes.Equal(header.TransactionsRoot[:], zeroHash[:]) { + return errors.New("transactions root cannot be zero") + } + + // Check block number to be 0 + if header.Number != 0 { + return errors.New("block number must be 0 for genesis block") + } + + // Validate prevRandao is zero for genesis + if !bytes.Equal(header.Random[:], zeroHash[:]) { + return errors.New("prevRandao must be zero for genesis block") + } + + // Fee recipient can be zero in genesis block + // No need to validate fee recipient for genesis + + // We don't validate LogsBloom as it can legitimately be + // all zeros in a genesis block or in blocks with no logs + + // Validate numeric fields + if header.GasLimit == 0 { + return errors.New("gas limit cannot be zero") + } + + // Extra data length check (max 32 bytes) + if len(header.ExtraData) > maxExtraDataSize { + return fmt.Errorf( + "extra data too long: got %d bytes, max 32 bytes", + len(header.ExtraData), + ) + } + + // Validate base fee per gas + if header.BaseFeePerGas == nil { + return errors.New("base fee per gas cannot be nil") + } + + // Additional Deneb-specific validations for blob gas + if header.BlobGasUsed > header.GetGasLimit() { + return errors.New("blob gas used exceeds gas limit") + } + + return nil +} diff --git a/consensus/cometbft/service/validate_fork_version.go b/consensus/cometbft/service/validate_fork_version.go new file mode 100644 index 0000000000..05be47d9cb --- /dev/null +++ b/consensus/cometbft/service/validate_fork_version.go @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: BUSL-1.1 +// +// Copyright (C) 2024, Berachain Foundation. All rights reserved. +// Use of this software is governed by the Business Source License included +// in the LICENSE file of this repository and at www.mariadb.com/bsl11. +// +// ANY USE OF THE LICENSED WORK IN VIOLATION OF THIS LICENSE WILL AUTOMATICALLY +// TERMINATE YOUR RIGHTS UNDER THIS LICENSE FOR THE CURRENT AND ALL OTHER +// VERSIONS OF THE LICENSED WORK. +// +// THIS LICENSE DOES NOT GRANT YOU ANY RIGHT IN ANY TRADEMARK OR LOGO OF +// LICENSOR OR ITS AFFILIATES (PROVIDED THAT YOU MAY USE A TRADEMARK OR LOGO OF +// LICENSOR AS EXPRESSLY REQUIRED BY THIS LICENSE). +// +// TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON +// AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, +// EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND +// TITLE. + +package cometbft + +import ( + "encoding/hex" + "strings" +) + +// isValidForkVersion returns true if the provided fork version is valid. +// Validate fork version format (should be 0x followed by 8 hex characters). +func isValidForkVersion(forkVersion string) bool { + if !strings.HasPrefix(forkVersion, "0x") || len(forkVersion) != 10 { + return false + } + _, err := hex.DecodeString(forkVersion[2:]) + return err == nil +} From 8e782b6d4c478dc803574d8adcb0ffe8a5778335 Mon Sep 17 00:00:00 2001 From: nidhi-singh02 Date: Thu, 28 Nov 2024 14:50:47 +0530 Subject: [PATCH 10/25] add more detailed comments Signed-off-by: nidhi-singh02 --- consensus/cometbft/service/validate_deposits.go | 10 ++++++++-- .../cometbft/service/validate_execution_header.go | 9 +++++++-- consensus/cometbft/service/validate_fork_version.go | 2 +- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/consensus/cometbft/service/validate_deposits.go b/consensus/cometbft/service/validate_deposits.go index dbd1320e97..ca91b9b66d 100644 --- a/consensus/cometbft/service/validate_deposits.go +++ b/consensus/cometbft/service/validate_deposits.go @@ -28,7 +28,13 @@ import ( "github.com/berachain/beacon-kit/mod/errors" ) -// validateDeposits validates the provided deposits. +// validateDeposits performs validation of the provided deposits. +// It ensures: +// - At least one deposit is present +// - Deposit indices match their position in the slice +// - No duplicate public keys +// - Non-zero values for required fields (pubkey, credentials, amount, signature) +// Returns an error with details if any validation fails. func validateDeposits(deposits []types.Deposit) error { if len(deposits) == 0 { return errors.New("at least one deposit is required") @@ -40,7 +46,7 @@ func validateDeposits(deposits []types.Deposit) error { depositIndex := deposit.GetIndex() //#nosec:G701 // realistically fine in practice. // Validate index matches position - if depositIndex.Unwrap() != uint64(i) { + if i < 0 || depositIndex.Unwrap() != uint64(i) { return fmt.Errorf( "deposit index %d does not match position %d", depositIndex, diff --git a/consensus/cometbft/service/validate_execution_header.go b/consensus/cometbft/service/validate_execution_header.go index 4391827fc9..9863a73b84 100644 --- a/consensus/cometbft/service/validate_execution_header.go +++ b/consensus/cometbft/service/validate_execution_header.go @@ -29,9 +29,12 @@ import ( "github.com/berachain/beacon-kit/mod/primitives/pkg/common" ) +// maxExtraDataSize defines the maximum allowed size in bytes for the ExtraData +// field in the execution payload header. const maxExtraDataSize = 32 -// validateExecutionHeader validates the provided execution payload header. +// validateExecutionHeader validates the provided execution payload header +// for the genesis block. func validateExecutionHeader(header types.ExecutionPayloadHeader) error { // Validate hash fields are not zero zeroHash := common.ExecutionHash{} @@ -89,7 +92,9 @@ func validateExecutionHeader(header types.ExecutionPayloadHeader) error { // Additional Deneb-specific validations for blob gas if header.BlobGasUsed > header.GetGasLimit() { - return errors.New("blob gas used exceeds gas limit") + return fmt.Errorf("blob gas used (%d) exceeds gas limit (%d)", + header.BlobGasUsed, header.GetGasLimit(), + ) } return nil diff --git a/consensus/cometbft/service/validate_fork_version.go b/consensus/cometbft/service/validate_fork_version.go index 05be47d9cb..f9f8132d64 100644 --- a/consensus/cometbft/service/validate_fork_version.go +++ b/consensus/cometbft/service/validate_fork_version.go @@ -26,8 +26,8 @@ import ( ) // isValidForkVersion returns true if the provided fork version is valid. -// Validate fork version format (should be 0x followed by 8 hex characters). func isValidForkVersion(forkVersion string) bool { + // Validate fork version format (should be 0x followed by 8 hex characters). if !strings.HasPrefix(forkVersion, "0x") || len(forkVersion) != 10 { return false } From fa660923fa312844febf7c3b37ab58d44ea132bf Mon Sep 17 00:00:00 2001 From: nidhi-singh02 Date: Thu, 28 Nov 2024 16:07:19 +0530 Subject: [PATCH 11/25] lint Signed-off-by: nidhi-singh02 --- consensus/cometbft/service/validate_deposits.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/consensus/cometbft/service/validate_deposits.go b/consensus/cometbft/service/validate_deposits.go index ca91b9b66d..ce1b79265b 100644 --- a/consensus/cometbft/service/validate_deposits.go +++ b/consensus/cometbft/service/validate_deposits.go @@ -33,7 +33,8 @@ import ( // - At least one deposit is present // - Deposit indices match their position in the slice // - No duplicate public keys -// - Non-zero values for required fields (pubkey, credentials, amount, signature) +// - Non-zero values for required fields +// (pubkey, credentials, amount, signature) // Returns an error with details if any validation fails. func validateDeposits(deposits []types.Deposit) error { if len(deposits) == 0 { From f2adb92bd9eb6119706f9d6f46939eb4e0e0d83d Mon Sep 17 00:00:00 2001 From: nidhi-singh02 Date: Mon, 2 Dec 2024 14:58:39 +0530 Subject: [PATCH 12/25] nit Signed-off-by: nidhi-singh02 --- consensus/cometbft/service/validate_deposits.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/consensus/cometbft/service/validate_deposits.go b/consensus/cometbft/service/validate_deposits.go index ce1b79265b..ec44a82aa4 100644 --- a/consensus/cometbft/service/validate_deposits.go +++ b/consensus/cometbft/service/validate_deposits.go @@ -47,7 +47,7 @@ func validateDeposits(deposits []types.Deposit) error { depositIndex := deposit.GetIndex() //#nosec:G701 // realistically fine in practice. // Validate index matches position - if i < 0 || depositIndex.Unwrap() != uint64(i) { + if depositIndex.Unwrap() != uint64(i) { return fmt.Errorf( "deposit index %d does not match position %d", depositIndex, From fb61aeea0a0a9c8633fd7cdcde47042d857c575b Mon Sep 17 00:00:00 2001 From: nidhi-singh02 Date: Mon, 2 Dec 2024 15:02:29 +0530 Subject: [PATCH 13/25] define func in file Signed-off-by: nidhi-singh02 --- consensus/cometbft/service/genesis.go | 10 ---------- consensus/cometbft/service/validate_deposits.go | 10 ++++++++++ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/consensus/cometbft/service/genesis.go b/consensus/cometbft/service/genesis.go index 049b989165..23fa8ee201 100644 --- a/consensus/cometbft/service/genesis.go +++ b/consensus/cometbft/service/genesis.go @@ -56,16 +56,6 @@ func (s *Service[_]) DefaultGenesis() map[string]json.RawMessage { return gen } -// isZeroBytes returns true if the provided byte slice is all zeros. -func isZeroBytes(b []byte) bool { - for _, byteValue := range b { - if byteValue != 0 { - return false - } - } - return true -} - // ValidateGenesis validates the provided genesis state. func (s *Service[_]) ValidateGenesis( genesisState map[string]json.RawMessage, diff --git a/consensus/cometbft/service/validate_deposits.go b/consensus/cometbft/service/validate_deposits.go index ec44a82aa4..3a3118ef37 100644 --- a/consensus/cometbft/service/validate_deposits.go +++ b/consensus/cometbft/service/validate_deposits.go @@ -28,6 +28,16 @@ import ( "github.com/berachain/beacon-kit/mod/errors" ) +// isZeroBytes returns true if the provided byte slice is all zeros. +func isZeroBytes(b []byte) bool { + for _, byteValue := range b { + if byteValue != 0 { + return false + } + } + return true +} + // validateDeposits performs validation of the provided deposits. // It ensures: // - At least one deposit is present From f770029a80c4bad64c62ee66e20edada2150bc46 Mon Sep 17 00:00:00 2001 From: nidhi-singh02 Date: Mon, 2 Dec 2024 22:31:22 +0530 Subject: [PATCH 14/25] use genesis from types, and review comments Signed-off-by: nidhi-singh02 --- consensus/cometbft/service/genesis.go | 12 +++++--- .../cometbft/service/validate_deposits.go | 22 +++++--------- .../service/validate_execution_header.go | 5 +++- .../cometbft/service/validate_fork_version.go | 29 +++++++++++++++---- 4 files changed, 44 insertions(+), 24 deletions(-) diff --git a/consensus/cometbft/service/genesis.go b/consensus/cometbft/service/genesis.go index 23fa8ee201..7cd78d1913 100644 --- a/consensus/cometbft/service/genesis.go +++ b/consensus/cometbft/service/genesis.go @@ -73,7 +73,11 @@ func (s *Service[_]) ValidateGenesis( ) } - var beaconGenesis BeaconGenesisState + beaconGenesis := &types.Genesis[ + *types.Deposit, + *types.ExecutionPayloadHeader, + ]{} + if err := json.Unmarshal(beaconGenesisBz, &beaconGenesis); err != nil { return fmt.Errorf( "failed to unmarshal beacon genesis state: %w", @@ -81,18 +85,18 @@ func (s *Service[_]) ValidateGenesis( ) } - if !isValidForkVersion(beaconGenesis.ForkVersion) { + if !isValidForkVersion(beaconGenesis.GetForkVersion()) { return fmt.Errorf("invalid fork version format: %s", beaconGenesis.ForkVersion, ) } - if err := validateDeposits(beaconGenesis.Deposits); err != nil { + if err := validateDeposits(beaconGenesis.GetDeposits()); err != nil { return fmt.Errorf("invalid deposits: %w", err) } if err := validateExecutionHeader( - beaconGenesis.ExecutionPayloadHeader, + beaconGenesis.GetExecutionPayloadHeader(), ); err != nil { return fmt.Errorf("invalid execution payload header: %w", err) } diff --git a/consensus/cometbft/service/validate_deposits.go b/consensus/cometbft/service/validate_deposits.go index 3a3118ef37..d054b11819 100644 --- a/consensus/cometbft/service/validate_deposits.go +++ b/consensus/cometbft/service/validate_deposits.go @@ -46,34 +46,28 @@ func isZeroBytes(b []byte) bool { // - Non-zero values for required fields // (pubkey, credentials, amount, signature) // Returns an error with details if any validation fails. -func validateDeposits(deposits []types.Deposit) error { +func validateDeposits(deposits []*types.Deposit) error { if len(deposits) == 0 { return errors.New("at least one deposit is required") } - seenPubkeys := make(map[string]bool) + seenPubkeys := make(map[string]struct{}) + // In genesis, we have 1:1 mapping between deposits and validators. Hence, + // we check for duplicate public key. for i, deposit := range deposits { - depositIndex := deposit.GetIndex() - //#nosec:G701 // realistically fine in practice. - // Validate index matches position - if depositIndex.Unwrap() != uint64(i) { - return fmt.Errorf( - "deposit index %d does not match position %d", - depositIndex, - i, - ) + if deposit == nil { + return fmt.Errorf("deposit %d is nil", i) } - if isZeroBytes(deposit.Pubkey[:]) { return fmt.Errorf("deposit %d has a zeroed public key", i) } // Check for duplicate pubkeys pubkeyHex := hex.EncodeToString(deposit.Pubkey[:]) - if seenPubkeys[pubkeyHex] { + if _, seen := seenPubkeys[pubkeyHex]; seen { return fmt.Errorf("duplicate pubkey found in deposit %d", i) } - seenPubkeys[pubkeyHex] = true + seenPubkeys[pubkeyHex] = struct{}{} if isZeroBytes(deposit.Credentials[:]) { return fmt.Errorf( diff --git a/consensus/cometbft/service/validate_execution_header.go b/consensus/cometbft/service/validate_execution_header.go index 9863a73b84..afaf03db7c 100644 --- a/consensus/cometbft/service/validate_execution_header.go +++ b/consensus/cometbft/service/validate_execution_header.go @@ -35,7 +35,10 @@ const maxExtraDataSize = 32 // validateExecutionHeader validates the provided execution payload header // for the genesis block. -func validateExecutionHeader(header types.ExecutionPayloadHeader) error { +func validateExecutionHeader(header *types.ExecutionPayloadHeader) error { + if header == nil { + return errors.New("execution payload header cannot be nil") + } // Validate hash fields are not zero zeroHash := common.ExecutionHash{} // For genesis block (when block number is 0), ParentHash must be zero diff --git a/consensus/cometbft/service/validate_fork_version.go b/consensus/cometbft/service/validate_fork_version.go index f9f8132d64..0c99691c93 100644 --- a/consensus/cometbft/service/validate_fork_version.go +++ b/consensus/cometbft/service/validate_fork_version.go @@ -23,14 +23,33 @@ package cometbft import ( "encoding/hex" "strings" + + "github.com/berachain/beacon-kit/mod/primitives/pkg/common" ) // isValidForkVersion returns true if the provided fork version is valid. -func isValidForkVersion(forkVersion string) bool { - // Validate fork version format (should be 0x followed by 8 hex characters). - if !strings.HasPrefix(forkVersion, "0x") || len(forkVersion) != 10 { +// A valid fork version must: +// - Start with "0x" +// - Be followed by exactly 8 hexadecimal characters +func isValidForkVersion(forkVersion common.Version) bool { + forkVersionStr := forkVersion.String() + if !strings.HasPrefix(forkVersionStr, "0x") { + return false + } + + // Remove "0x" prefix and verify remaining characters + hexPart := strings.TrimPrefix(forkVersionStr, "0x") + + // Should have exactly 8 characters after 0x prefix + if len(hexPart) != 8 { return false } - _, err := hex.DecodeString(forkVersion[2:]) - return err == nil + + // Verify it's a valid hex number + _, err := hex.DecodeString(hexPart) + if err != nil { + return false + } + + return true } From 2ddb7c3b177eae7496c4e5a817dc9e4e705df7b8 Mon Sep 17 00:00:00 2001 From: nidhi-singh02 Date: Mon, 2 Dec 2024 22:41:47 +0530 Subject: [PATCH 15/25] lint fix Signed-off-by: nidhi-singh02 --- consensus/cometbft/service/validate_fork_version.go | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/consensus/cometbft/service/validate_fork_version.go b/consensus/cometbft/service/validate_fork_version.go index 0c99691c93..c62db1237c 100644 --- a/consensus/cometbft/service/validate_fork_version.go +++ b/consensus/cometbft/service/validate_fork_version.go @@ -27,10 +27,12 @@ import ( "github.com/berachain/beacon-kit/mod/primitives/pkg/common" ) +const expectedHexLength = 8 + // isValidForkVersion returns true if the provided fork version is valid. // A valid fork version must: // - Start with "0x" -// - Be followed by exactly 8 hexadecimal characters +// - Be followed by exactly 8 hexadecimal characters. func isValidForkVersion(forkVersion common.Version) bool { forkVersionStr := forkVersion.String() if !strings.HasPrefix(forkVersionStr, "0x") { @@ -41,15 +43,11 @@ func isValidForkVersion(forkVersion common.Version) bool { hexPart := strings.TrimPrefix(forkVersionStr, "0x") // Should have exactly 8 characters after 0x prefix - if len(hexPart) != 8 { + if len(hexPart) != expectedHexLength { return false } // Verify it's a valid hex number _, err := hex.DecodeString(hexPart) - if err != nil { - return false - } - - return true + return err == nil } From 11551a00d44b7a9f5dbcf846d81b4fc2cd63e3d4 Mon Sep 17 00:00:00 2001 From: nidhi-singh02 Date: Mon, 2 Dec 2024 22:42:52 +0530 Subject: [PATCH 16/25] remove struct for genesisState Signed-off-by: nidhi-singh02 --- consensus/cometbft/service/genesis.go | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/consensus/cometbft/service/genesis.go b/consensus/cometbft/service/genesis.go index 7cd78d1913..9409163b32 100644 --- a/consensus/cometbft/service/genesis.go +++ b/consensus/cometbft/service/genesis.go @@ -32,16 +32,6 @@ import ( genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" ) -// BeaconGenesisState represents the structure of the -// beacon module's genesis state. -// -//nolint:lll // JSON tags are long. -type BeaconGenesisState struct { - ForkVersion string `json:"fork_version"` - Deposits []types.Deposit `json:"deposits"` - ExecutionPayloadHeader types.ExecutionPayloadHeader `json:"execution_payload_header"` -} - // DefaultGenesis returns the default genesis state for the application. func (s *Service[_]) DefaultGenesis() map[string]json.RawMessage { // Implement the default genesis state for the application. From 38e7e0eee68dd7f3c0cc73a13003731a65dba55c Mon Sep 17 00:00:00 2001 From: nidhi-singh02 Date: Tue, 3 Dec 2024 17:01:43 +0530 Subject: [PATCH 17/25] optimized zerobytes func Signed-off-by: nidhi-singh02 --- consensus/cometbft/service/validate_deposits.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/consensus/cometbft/service/validate_deposits.go b/consensus/cometbft/service/validate_deposits.go index d054b11819..caa318d702 100644 --- a/consensus/cometbft/service/validate_deposits.go +++ b/consensus/cometbft/service/validate_deposits.go @@ -21,6 +21,7 @@ package cometbft import ( + "bytes" "encoding/hex" "fmt" @@ -30,12 +31,7 @@ import ( // isZeroBytes returns true if the provided byte slice is all zeros. func isZeroBytes(b []byte) bool { - for _, byteValue := range b { - if byteValue != 0 { - return false - } - } - return true + return bytes.Equal(b, make([]byte, len(b))) } // validateDeposits performs validation of the provided deposits. From 07e3136803a3576198869f802c510177d52005db Mon Sep 17 00:00:00 2001 From: nidhi-singh02 Date: Fri, 6 Dec 2024 14:17:26 +0530 Subject: [PATCH 18/25] depedency correct path Signed-off-by: nidhi-singh02 --- consensus/cometbft/service/genesis.go | 6 +++--- consensus/cometbft/service/validate_deposits.go | 4 ++-- consensus/cometbft/service/validate_execution_header.go | 6 +++--- consensus/cometbft/service/validate_fork_version.go | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/consensus/cometbft/service/genesis.go b/consensus/cometbft/service/genesis.go index 9409163b32..9c6699b69b 100644 --- a/consensus/cometbft/service/genesis.go +++ b/consensus/cometbft/service/genesis.go @@ -24,9 +24,9 @@ import ( "crypto/sha256" "fmt" - "github.com/berachain/beacon-kit/mod/consensus-types/pkg/types" - "github.com/berachain/beacon-kit/mod/errors" - "github.com/berachain/beacon-kit/mod/primitives/pkg/encoding/json" + "github.com/berachain/beacon-kit/consensus-types/types" + "github.com/berachain/beacon-kit/errors" + "github.com/berachain/beacon-kit/primitives/encoding/json" cmtcfg "github.com/cometbft/cometbft/config" "github.com/cometbft/cometbft/node" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" diff --git a/consensus/cometbft/service/validate_deposits.go b/consensus/cometbft/service/validate_deposits.go index caa318d702..7c1d76755a 100644 --- a/consensus/cometbft/service/validate_deposits.go +++ b/consensus/cometbft/service/validate_deposits.go @@ -25,8 +25,8 @@ import ( "encoding/hex" "fmt" - "github.com/berachain/beacon-kit/mod/consensus-types/pkg/types" - "github.com/berachain/beacon-kit/mod/errors" + "github.com/berachain/beacon-kit/consensus-types/types" + "github.com/berachain/beacon-kit/errors" ) // isZeroBytes returns true if the provided byte slice is all zeros. diff --git a/consensus/cometbft/service/validate_execution_header.go b/consensus/cometbft/service/validate_execution_header.go index afaf03db7c..17b1bcfe05 100644 --- a/consensus/cometbft/service/validate_execution_header.go +++ b/consensus/cometbft/service/validate_execution_header.go @@ -24,9 +24,9 @@ import ( "bytes" "fmt" - "github.com/berachain/beacon-kit/mod/consensus-types/pkg/types" - "github.com/berachain/beacon-kit/mod/errors" - "github.com/berachain/beacon-kit/mod/primitives/pkg/common" + "github.com/berachain/beacon-kit/consensus-types/types" + "github.com/berachain/beacon-kit/errors" + "github.com/berachain/beacon-kit/primitives/common" ) // maxExtraDataSize defines the maximum allowed size in bytes for the ExtraData diff --git a/consensus/cometbft/service/validate_fork_version.go b/consensus/cometbft/service/validate_fork_version.go index c62db1237c..ee94b3a361 100644 --- a/consensus/cometbft/service/validate_fork_version.go +++ b/consensus/cometbft/service/validate_fork_version.go @@ -24,7 +24,7 @@ import ( "encoding/hex" "strings" - "github.com/berachain/beacon-kit/mod/primitives/pkg/common" + "github.com/berachain/beacon-kit/primitives/common" ) const expectedHexLength = 8 From 3015664af9f93dd10372b9d353de96f7d6b212ed Mon Sep 17 00:00:00 2001 From: nidhi-singh02 Date: Fri, 6 Dec 2024 17:53:58 +0530 Subject: [PATCH 19/25] blob gas vals added Signed-off-by: nidhi-singh02 --- .../cometbft/service/validate_execution_header.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/consensus/cometbft/service/validate_execution_header.go b/consensus/cometbft/service/validate_execution_header.go index 17b1bcfe05..52a29f9808 100644 --- a/consensus/cometbft/service/validate_execution_header.go +++ b/consensus/cometbft/service/validate_execution_header.go @@ -94,6 +94,17 @@ func validateExecutionHeader(header *types.ExecutionPayloadHeader) error { } // Additional Deneb-specific validations for blob gas + if header.BlobGasUsed != 0 { + return errors.New( + "blob gas used must be zero for genesis block", + ) + } + if header.ExcessBlobGas != 0 { + return errors.New( + "excess blob gas must be zero for genesis block", + ) + } + if header.BlobGasUsed > header.GetGasLimit() { return fmt.Errorf("blob gas used (%d) exceeds gas limit (%d)", header.BlobGasUsed, header.GetGasLimit(), From 3eba1d938565ecc538b666f53fde97c0addb1477 Mon Sep 17 00:00:00 2001 From: nidhi-singh02 Date: Fri, 6 Dec 2024 18:44:45 +0530 Subject: [PATCH 20/25] validation in execution headers for root - rn commented Signed-off-by: nidhi-singh02 --- .../service/validate_execution_header.go | 47 +++++++++++++++---- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/consensus/cometbft/service/validate_execution_header.go b/consensus/cometbft/service/validate_execution_header.go index 52a29f9808..c2ff74c34e 100644 --- a/consensus/cometbft/service/validate_execution_header.go +++ b/consensus/cometbft/service/validate_execution_header.go @@ -39,25 +39,49 @@ func validateExecutionHeader(header *types.ExecutionPayloadHeader) error { if header == nil { return errors.New("execution payload header cannot be nil") } + // Validate hash fields are not zero zeroHash := common.ExecutionHash{} + emptyTrieRoot := common.Bytes32( + common.NewExecutionHashFromHex( + "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + )) + // emptyRoot := common.Root( + // common.NewExecutionHashFromHex( + // "0x0000000000000000000000000000000000000000000000000000000000000000", + // )) + // For genesis block (when block number is 0), ParentHash must be zero if !bytes.Equal(header.ParentHash[:], zeroHash[:]) { return errors.New("parent hash must be zero for genesis block") } - if bytes.Equal(header.StateRoot[:], zeroHash[:]) { - return errors.New("state root cannot be zero") - } - if bytes.Equal(header.ReceiptsRoot[:], zeroHash[:]) { - return errors.New("receipts root cannot be zero") + //if header.StateRoot != emptyTrieRoot { + // return errors.New( + // "state root must be empty trie root for genesis block", + // ) + // } + + if header.ReceiptsRoot != emptyTrieRoot { + return errors.New( + "receipts root must be empty trie root for genesis block", + ) } + + // if header.TransactionsRoot != emptyRoot { + // return errors.New( + // "transactions root must be empty list root for genesis block", + // ) + // } + // if header.WithdrawalsRoot != emptyRoot { + // return errors.New( + // "withdrawals root must be empty list root for genesis block", + // ) + // } + if bytes.Equal(header.BlockHash[:], zeroHash[:]) { return errors.New("block hash cannot be zero") } - if bytes.Equal(header.TransactionsRoot[:], zeroHash[:]) { - return errors.New("transactions root cannot be zero") - } // Check block number to be 0 if header.Number != 0 { @@ -65,7 +89,8 @@ func validateExecutionHeader(header *types.ExecutionPayloadHeader) error { } // Validate prevRandao is zero for genesis - if !bytes.Equal(header.Random[:], zeroHash[:]) { + var zeroBytes32 common.Bytes32 + if !bytes.Equal(header.Random[:], zeroBytes32[:]) { return errors.New("prevRandao must be zero for genesis block") } @@ -80,6 +105,10 @@ func validateExecutionHeader(header *types.ExecutionPayloadHeader) error { return errors.New("gas limit cannot be zero") } + if header.GasUsed != 0 { + return errors.New("gas used must be zero for genesis block") + } + // Extra data length check (max 32 bytes) if len(header.ExtraData) > maxExtraDataSize { return fmt.Errorf( From 65983de23f305be1b922b64290366611f38f0a2c Mon Sep 17 00:00:00 2001 From: nidhi-singh02 Date: Fri, 6 Dec 2024 18:59:24 +0530 Subject: [PATCH 21/25] lint Signed-off-by: nidhi-singh02 --- consensus/cometbft/service/validate_execution_header.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/consensus/cometbft/service/validate_execution_header.go b/consensus/cometbft/service/validate_execution_header.go index c2ff74c34e..db7fcae3f2 100644 --- a/consensus/cometbft/service/validate_execution_header.go +++ b/consensus/cometbft/service/validate_execution_header.go @@ -56,7 +56,7 @@ func validateExecutionHeader(header *types.ExecutionPayloadHeader) error { return errors.New("parent hash must be zero for genesis block") } - //if header.StateRoot != emptyTrieRoot { + // if header.StateRoot != emptyTrieRoot { // return errors.New( // "state root must be empty trie root for genesis block", // ) From 465259fd63368dd09b7b0063fc7ebea18026ea9b Mon Sep 17 00:00:00 2001 From: nidhi-singh02 Date: Fri, 6 Dec 2024 19:14:34 +0530 Subject: [PATCH 22/25] nits Signed-off-by: nidhi-singh02 --- consensus/cometbft/service/validate_execution_header.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/consensus/cometbft/service/validate_execution_header.go b/consensus/cometbft/service/validate_execution_header.go index db7fcae3f2..35f87b99d4 100644 --- a/consensus/cometbft/service/validate_execution_header.go +++ b/consensus/cometbft/service/validate_execution_header.go @@ -134,9 +134,9 @@ func validateExecutionHeader(header *types.ExecutionPayloadHeader) error { ) } - if header.BlobGasUsed > header.GetGasLimit() { + if header.BlobGasUsed > header.GasLimit { return fmt.Errorf("blob gas used (%d) exceeds gas limit (%d)", - header.BlobGasUsed, header.GetGasLimit(), + header.BlobGasUsed, header.GasLimit, ) } From 62ded03ef27593c10840c2fc6f579a2ba9565926 Mon Sep 17 00:00:00 2001 From: nidhi-singh02 Date: Fri, 6 Dec 2024 21:37:48 +0530 Subject: [PATCH 23/25] removed code val for empty roots Signed-off-by: nidhi-singh02 --- .../cometbft/service/validate_deposits.go | 1 - .../service/validate_execution_header.go | 21 ------------------- 2 files changed, 22 deletions(-) diff --git a/consensus/cometbft/service/validate_deposits.go b/consensus/cometbft/service/validate_deposits.go index 7c1d76755a..4c5a75835f 100644 --- a/consensus/cometbft/service/validate_deposits.go +++ b/consensus/cometbft/service/validate_deposits.go @@ -37,7 +37,6 @@ func isZeroBytes(b []byte) bool { // validateDeposits performs validation of the provided deposits. // It ensures: // - At least one deposit is present -// - Deposit indices match their position in the slice // - No duplicate public keys // - Non-zero values for required fields // (pubkey, credentials, amount, signature) diff --git a/consensus/cometbft/service/validate_execution_header.go b/consensus/cometbft/service/validate_execution_header.go index 35f87b99d4..7d69a9cb7b 100644 --- a/consensus/cometbft/service/validate_execution_header.go +++ b/consensus/cometbft/service/validate_execution_header.go @@ -46,39 +46,18 @@ func validateExecutionHeader(header *types.ExecutionPayloadHeader) error { common.NewExecutionHashFromHex( "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", )) - // emptyRoot := common.Root( - // common.NewExecutionHashFromHex( - // "0x0000000000000000000000000000000000000000000000000000000000000000", - // )) // For genesis block (when block number is 0), ParentHash must be zero if !bytes.Equal(header.ParentHash[:], zeroHash[:]) { return errors.New("parent hash must be zero for genesis block") } - // if header.StateRoot != emptyTrieRoot { - // return errors.New( - // "state root must be empty trie root for genesis block", - // ) - // } - if header.ReceiptsRoot != emptyTrieRoot { return errors.New( "receipts root must be empty trie root for genesis block", ) } - // if header.TransactionsRoot != emptyRoot { - // return errors.New( - // "transactions root must be empty list root for genesis block", - // ) - // } - // if header.WithdrawalsRoot != emptyRoot { - // return errors.New( - // "withdrawals root must be empty list root for genesis block", - // ) - // } - if bytes.Equal(header.BlockHash[:], zeroHash[:]) { return errors.New("block hash cannot be zero") } From 6b481ea541a9026f52e8e6a0fb4fc3b9b17783e8 Mon Sep 17 00:00:00 2001 From: nidhi-singh02 Date: Fri, 6 Dec 2024 21:50:52 +0530 Subject: [PATCH 24/25] optimized the order of validations Signed-off-by: nidhi-singh02 --- .../service/validate_execution_header.go | 72 +++++++++---------- 1 file changed, 35 insertions(+), 37 deletions(-) diff --git a/consensus/cometbft/service/validate_execution_header.go b/consensus/cometbft/service/validate_execution_header.go index 7d69a9cb7b..bff57b7f5a 100644 --- a/consensus/cometbft/service/validate_execution_header.go +++ b/consensus/cometbft/service/validate_execution_header.go @@ -40,6 +40,41 @@ func validateExecutionHeader(header *types.ExecutionPayloadHeader) error { return errors.New("execution payload header cannot be nil") } + // Check block number to be 0 + if header.Number != 0 { + return errors.New("block number must be 0 for genesis block") + } + + if header.GasLimit == 0 { + return errors.New("gas limit cannot be zero") + } + + if header.GasUsed != 0 { + return errors.New("gas used must be zero for genesis block") + } + + if header.BaseFeePerGas == nil { + return errors.New("base fee per gas cannot be nil") + } + + // Additional Deneb-specific validations for blob gas + if header.BlobGasUsed != 0 { + return errors.New( + "blob gas used must be zero for genesis block", + ) + } + if header.ExcessBlobGas != 0 { + return errors.New( + "excess blob gas must be zero for genesis block", + ) + } + + if header.BlobGasUsed > header.GasLimit { + return fmt.Errorf("blob gas used (%d) exceeds gas limit (%d)", + header.BlobGasUsed, header.GasLimit, + ) + } + // Validate hash fields are not zero zeroHash := common.ExecutionHash{} emptyTrieRoot := common.Bytes32( @@ -62,11 +97,6 @@ func validateExecutionHeader(header *types.ExecutionPayloadHeader) error { return errors.New("block hash cannot be zero") } - // Check block number to be 0 - if header.Number != 0 { - return errors.New("block number must be 0 for genesis block") - } - // Validate prevRandao is zero for genesis var zeroBytes32 common.Bytes32 if !bytes.Equal(header.Random[:], zeroBytes32[:]) { @@ -79,15 +109,6 @@ func validateExecutionHeader(header *types.ExecutionPayloadHeader) error { // We don't validate LogsBloom as it can legitimately be // all zeros in a genesis block or in blocks with no logs - // Validate numeric fields - if header.GasLimit == 0 { - return errors.New("gas limit cannot be zero") - } - - if header.GasUsed != 0 { - return errors.New("gas used must be zero for genesis block") - } - // Extra data length check (max 32 bytes) if len(header.ExtraData) > maxExtraDataSize { return fmt.Errorf( @@ -96,28 +117,5 @@ func validateExecutionHeader(header *types.ExecutionPayloadHeader) error { ) } - // Validate base fee per gas - if header.BaseFeePerGas == nil { - return errors.New("base fee per gas cannot be nil") - } - - // Additional Deneb-specific validations for blob gas - if header.BlobGasUsed != 0 { - return errors.New( - "blob gas used must be zero for genesis block", - ) - } - if header.ExcessBlobGas != 0 { - return errors.New( - "excess blob gas must be zero for genesis block", - ) - } - - if header.BlobGasUsed > header.GasLimit { - return fmt.Errorf("blob gas used (%d) exceeds gas limit (%d)", - header.BlobGasUsed, header.GasLimit, - ) - } - return nil } From 0feec46ddf2efb912710b1bd46a4acccb6feab6f Mon Sep 17 00:00:00 2001 From: nidhi-singh02 Date: Fri, 6 Dec 2024 22:10:38 +0530 Subject: [PATCH 25/25] removed zero valued check for deposits Signed-off-by: nidhi-singh02 --- .../cometbft/service/validate_deposits.go | 27 +------------------ 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/consensus/cometbft/service/validate_deposits.go b/consensus/cometbft/service/validate_deposits.go index 4c5a75835f..4e69cf5707 100644 --- a/consensus/cometbft/service/validate_deposits.go +++ b/consensus/cometbft/service/validate_deposits.go @@ -21,7 +21,6 @@ package cometbft import ( - "bytes" "encoding/hex" "fmt" @@ -29,17 +28,10 @@ import ( "github.com/berachain/beacon-kit/errors" ) -// isZeroBytes returns true if the provided byte slice is all zeros. -func isZeroBytes(b []byte) bool { - return bytes.Equal(b, make([]byte, len(b))) -} - // validateDeposits performs validation of the provided deposits. // It ensures: // - At least one deposit is present // - No duplicate public keys -// - Non-zero values for required fields -// (pubkey, credentials, amount, signature) // Returns an error with details if any validation fails. func validateDeposits(deposits []*types.Deposit) error { if len(deposits) == 0 { @@ -54,30 +46,13 @@ func validateDeposits(deposits []*types.Deposit) error { if deposit == nil { return fmt.Errorf("deposit %d is nil", i) } - if isZeroBytes(deposit.Pubkey[:]) { - return fmt.Errorf("deposit %d has a zeroed public key", i) - } + // Check for duplicate pubkeys pubkeyHex := hex.EncodeToString(deposit.Pubkey[:]) if _, seen := seenPubkeys[pubkeyHex]; seen { return fmt.Errorf("duplicate pubkey found in deposit %d", i) } seenPubkeys[pubkeyHex] = struct{}{} - - if isZeroBytes(deposit.Credentials[:]) { - return fmt.Errorf( - "deposit %d has zeroed withdrawal credentials", - i, - ) - } - - if deposit.Amount == 0 { - return fmt.Errorf("deposit %d has zero amount", i) - } - - if isZeroBytes(deposit.Signature[:]) { - return fmt.Errorf("deposit %d has a zeroed signature", i) - } } return nil