Skip to content

Commit

Permalink
Added Capella specs support to Erigon-CL (#7051)
Browse files Browse the repository at this point in the history
Passing consensus-specs tests for Capella. Processing of withdrawals and
ExecutionChanges. efficient non-validation implemented. Refactored:
ExecutionPayload/ExecutionPayloadHeader.
  • Loading branch information
Giulio2002 authored Mar 7, 2023
1 parent e59d37e commit e6ba82c
Show file tree
Hide file tree
Showing 35 changed files with 899 additions and 532 deletions.
30 changes: 20 additions & 10 deletions cl/clparams/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -373,11 +373,14 @@ type BeaconChainConfig struct {
ProportionalSlashingMultiplier uint64 `yaml:"PROPORTIONAL_SLASHING_MULTIPLIER" spec:"true"` // ProportionalSlashingMultiplier is used as a multiplier on slashed penalties.

// Max operations per block constants.
MaxProposerSlashings uint64 `yaml:"MAX_PROPOSER_SLASHINGS" spec:"true"` // MaxProposerSlashings defines the maximum number of slashings of proposers possible in a block.
MaxAttesterSlashings uint64 `yaml:"MAX_ATTESTER_SLASHINGS" spec:"true"` // MaxAttesterSlashings defines the maximum number of casper FFG slashings possible in a block.
MaxAttestations uint64 `yaml:"MAX_ATTESTATIONS" spec:"true"` // MaxAttestations defines the maximum allowed attestations in a beacon block.
MaxDeposits uint64 `yaml:"MAX_DEPOSITS" spec:"true"` // MaxDeposits defines the maximum number of validator deposits in a block.
MaxVoluntaryExits uint64 `yaml:"MAX_VOLUNTARY_EXITS" spec:"true"` // MaxVoluntaryExits defines the maximum number of validator exits in a block.
MaxProposerSlashings uint64 `yaml:"MAX_PROPOSER_SLASHINGS" spec:"true"` // MaxProposerSlashings defines the maximum number of slashings of proposers possible in a block.
MaxAttesterSlashings uint64 `yaml:"MAX_ATTESTER_SLASHINGS" spec:"true"` // MaxAttesterSlashings defines the maximum number of casper FFG slashings possible in a block.
MaxAttestations uint64 `yaml:"MAX_ATTESTATIONS" spec:"true"` // MaxAttestations defines the maximum allowed attestations in a beacon block.
MaxDeposits uint64 `yaml:"MAX_DEPOSITS" spec:"true"` // MaxDeposits defines the maximum number of validator deposits in a block.
MaxVoluntaryExits uint64 `yaml:"MAX_VOLUNTARY_EXITS" spec:"true"` // MaxVoluntaryExits defines the maximum number of validator exits in a block.
MaxWithdrawalsPerPayload uint64 `yaml:"MAX_WITHDRAWALS_PER_PAYLOAD" spec:"true"` // MaxWithdrawalsPerPayload defines the maximum number of withdrawals in a block.
MaxBlsToExecutionChanges uint64 `yaml:"MAX_BLS_TO_EXECUTION_CHANGES" spec:"true"` // MaxBlsToExecutionChanges defines the maximum number of BLS-to-execution-change objects in a block.
MaxValidatorsPerWithdrawalsSweep uint64 `yaml:"MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP" spec:"true"` //MaxValidatorsPerWithdrawalsSweep bounds the size of the sweep searching for withdrawals per slot.

// BLS domain values.
DomainBeaconProposer [4]byte `yaml:"DOMAIN_BEACON_PROPOSER" spec:"true"` // DomainBeaconProposer defines the BLS signature domain for beacon proposal verification.
Expand Down Expand Up @@ -617,11 +620,14 @@ var MainnetBeaconConfig BeaconChainConfig = BeaconChainConfig{
ProportionalSlashingMultiplier: 1,

// Max operations per block constants.
MaxProposerSlashings: 16,
MaxAttesterSlashings: 2,
MaxAttestations: 128,
MaxDeposits: 16,
MaxVoluntaryExits: 16,
MaxProposerSlashings: 16,
MaxAttesterSlashings: 2,
MaxAttestations: 128,
MaxDeposits: 16,
MaxVoluntaryExits: 16,
MaxWithdrawalsPerPayload: 16,
MaxBlsToExecutionChanges: 16,
MaxValidatorsPerWithdrawalsSweep: 16384,

// BLS domain values.
DomainBeaconProposer: utils.Uint32ToBytes4(0x00000000),
Expand Down Expand Up @@ -857,6 +863,8 @@ func (b *BeaconChainConfig) GetMinSlashingPenaltyQuotient(version StateVersion)
return b.MinSlashingPenaltyQuotientAltair
case BellatrixVersion:
return b.MinSlashingPenaltyQuotientBellatrix
case CapellaVersion:
return b.MinSlashingPenaltyQuotientBellatrix
default:
panic("not implemented")
}
Expand All @@ -870,6 +878,8 @@ func (b *BeaconChainConfig) GetPenaltyQuotient(version StateVersion) uint64 {
return b.InactivityPenaltyQuotientAltair
case BellatrixVersion:
return b.InactivityPenaltyQuotientBellatrix
case CapellaVersion:
return b.InactivityPenaltyQuotientBellatrix
default:
panic("not implemented")
}
Expand Down
22 changes: 16 additions & 6 deletions cl/cltypes/beacon_block.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type BeaconBlockForStorage struct {
AttesterSlashings []*AttesterSlashing
Deposits []*Deposit
VoluntaryExits []*SignedVoluntaryExit
AddressChanges []*SignedBLSToExecutionChange
SyncAggregate *SyncAggregate
// Metadatas
Eth1Number uint64
Expand Down Expand Up @@ -156,7 +157,7 @@ func (b *BeaconBody) EncodeSSZ(dst []byte) ([]byte, error) {
}
if b.Version >= clparams.BellatrixVersion {
buf = append(buf, ssz_utils.OffsetSSZ(offset)...)
offset += uint32(b.ExecutionPayload.EncodingSizeSSZ(b.Version))
offset += uint32(b.ExecutionPayload.EncodingSizeSSZ())
}
if b.Version >= clparams.CapellaVersion {
buf = append(buf, ssz_utils.OffsetSSZ(offset)...)
Expand Down Expand Up @@ -221,7 +222,7 @@ func (b *BeaconBody) EncodeSSZ(dst []byte) ([]byte, error) {
}

if b.Version >= clparams.BellatrixVersion {
buf, err = b.ExecutionPayload.EncodeSSZ(buf, b.Version)
buf, err = b.ExecutionPayload.EncodeSSZ(buf)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -259,7 +260,7 @@ func (b *BeaconBody) EncodingSizeSSZ() (size int) {
if b.ExecutionPayload == nil {
b.ExecutionPayload = new(Eth1Block)
}
size += b.ExecutionPayload.EncodingSizeSSZ(b.Version)
size += b.ExecutionPayload.EncodingSizeSSZ()
}

if b.Version >= clparams.CapellaVersion {
Expand Down Expand Up @@ -357,7 +358,7 @@ func (b *BeaconBody) DecodeSSZWithVersion(buf []byte, version int) error {
if offsetExecution > uint32(endOffset) || len(buf) < endOffset {
return ssz_utils.ErrBadOffset
}
if err := b.ExecutionPayload.DecodeSSZ(buf[offsetExecution:endOffset], b.Version); err != nil {
if err := b.ExecutionPayload.DecodeSSZWithVersion(buf[offsetExecution:endOffset], int(b.Version)); err != nil {
return err
}
}
Expand Down Expand Up @@ -434,6 +435,13 @@ func (b *BeaconBody) HashSSZ() ([32]byte, error) {
}
leaves = append(leaves, payloadLeaf)
}
if b.Version >= clparams.CapellaVersion {
blsExecutionLeaf, err := merkle_tree.ListObjectSSZRoot(b.ExecutionChanges, MaxExecutionChanges)
if err != nil {
return [32]byte{}, err
}
leaves = append(leaves, blsExecutionLeaf)
}
if b.Version == clparams.Phase0Version {
return merkle_tree.ArraysRoot(leaves, 8)
}
Expand Down Expand Up @@ -558,14 +566,15 @@ func (b *SignedBeaconBlock) EncodeForStorage() ([]byte, error) {
Deposits: b.Block.Body.Deposits,
VoluntaryExits: b.Block.Body.VoluntaryExits,
SyncAggregate: b.Block.Body.SyncAggregate,
AddressChanges: b.Block.Body.ExecutionChanges,
Version: uint8(b.Version()),
Eth2BlockRoot: blockRoot,
}

if b.Version() >= clparams.BellatrixVersion {
eth1Block := b.Block.Body.ExecutionPayload
storageObject.Eth1Number = eth1Block.NumberU64()
storageObject.Eth1BlockHash = eth1Block.Header.BlockHashCL
storageObject.Eth1Number = eth1Block.BlockNumber
storageObject.Eth1BlockHash = eth1Block.BlockHash
}
var buffer bytes.Buffer
if err := cbor.Marshal(&buffer, storageObject); err != nil {
Expand Down Expand Up @@ -605,6 +614,7 @@ func DecodeBeaconBlockForStorage(buf []byte) (block *SignedBeaconBlock, eth1Numb
Deposits: storageObject.Deposits,
VoluntaryExits: storageObject.VoluntaryExits,
SyncAggregate: storageObject.SyncAggregate,
ExecutionChanges: storageObject.AddressChanges,
Version: clparams.StateVersion(storageObject.Version),
},
},
Expand Down
22 changes: 4 additions & 18 deletions cl/cltypes/beacon_block_test.go
Original file line number Diff line number Diff line change
@@ -1,31 +1,15 @@
package cltypes_test

import (
"math/big"
"testing"

"github.com/ledgerwatch/erigon-lib/common"
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon/cl/clparams"
"github.com/ledgerwatch/erigon/cl/cltypes"
"github.com/ledgerwatch/erigon/cl/merkle_tree"
"github.com/ledgerwatch/erigon/core/types"
"github.com/stretchr/testify/require"
)

func getTestEth1Block() *cltypes.Eth1Block {
var emptyBlock = &cltypes.Eth1Block{
Header: &types.Header{
BaseFee: big.NewInt(0),
Number: big.NewInt(0),
},
Body: &types.RawBody{},
}
emptyBlock.Header.TxHashSSZ, _ = merkle_tree.TransactionsListRoot([][]byte{})
emptyBlock.Header.WithdrawalsHash = new(common.Hash)
return emptyBlock
}

func createDepositTest() *cltypes.Deposit {
// Make proof
proof := make([]libcommon.Hash, 33)
Expand Down Expand Up @@ -93,7 +77,7 @@ var testBeaconBlockVariation = &cltypes.SignedBeaconBlock{
},
Deposits: []*cltypes.Deposit{createDepositTest(), createDepositTest()},
SyncAggregate: &cltypes.SyncAggregate{},
ExecutionPayload: getTestEth1Block(),
ExecutionPayload: cltypes.NewEth1Block(clparams.BellatrixVersion),
ExecutionChanges: []*cltypes.SignedBLSToExecutionChange{
{
Message: &cltypes.BLSToExecutionChange{
Expand All @@ -108,14 +92,15 @@ var testBeaconBlockVariation = &cltypes.SignedBeaconBlock{

var (
// Hashes
capellaHash = common.HexToHash("0x00a1f1a46f4bcdd9030c11c1cf9a8062cd48478620e6fd3bd3a748263a49433f")
capellaHash = common.HexToHash("0xc4892f81461ed3a24db4b44f26a728219faf1f278d8a1c21d774e2efa73cf1a3")
bellatrixHash = common.HexToHash("9a5bc717ecaf6a8d6e879478003729b9ce4e71f5c4e9b4bd4dd166780894ee93")
altairHash = common.HexToHash("36aa8fe956265d171b7ad740077ea9579e25ed3b2f7b2010016513e4ac4754cb")
phase0Hash = common.HexToHash("83dd9e30bf61720822be889abf73760a26fb42dc9fb27fa872f845d68af92bc4")
)

func TestCapellaBlock(t *testing.T) {
testBeaconBlockVariation.Block.Body.Version = clparams.CapellaVersion
testBeaconBlockVariation.Block.Body.ExecutionPayload = cltypes.NewEth1Block(clparams.CapellaVersion)
require.Equal(t, testBeaconBlockVariation.Version(), clparams.CapellaVersion)
// Simple unit test: unmarshal + marshal + hashtreeroot
hash, err := testBeaconBlockVariation.HashSSZ()
Expand All @@ -129,6 +114,7 @@ func TestCapellaBlock(t *testing.T) {

func TestBellatrixBlock(t *testing.T) {
testBeaconBlockVariation.Block.Body.Version = clparams.BellatrixVersion
testBeaconBlockVariation.Block.Body.ExecutionPayload = cltypes.NewEth1Block(clparams.BellatrixVersion)
require.Equal(t, testBeaconBlockVariation.Version(), clparams.BellatrixVersion)
// Simple unit test: unmarshal + marshal + hashtreeroot
hash, err := testBeaconBlockVariation.HashSSZ()
Expand Down
4 changes: 4 additions & 0 deletions cl/cltypes/clone.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ func (*SignedBeaconBlock) Clone() clonable.Clonable {
return &SignedBeaconBlock{}
}

func (*Eth1Block) Clone() clonable.Clonable {
return &Eth1Block{}
}

func (*BeaconBlocksByRootRequest) Clone() clonable.Clonable {
return &BeaconBlocksByRootRequest{}
}
Expand Down
Loading

0 comments on commit e6ba82c

Please sign in to comment.