From 16269dec99947e69fbbc7ff3445a04a0315b8407 Mon Sep 17 00:00:00 2001 From: Kasey Kirkham Date: Tue, 4 Aug 2026 17:40:10 -0500 Subject: [PATCH 01/23] Move spectests to v1.7.0-alpha.12 --- WORKSPACE | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/WORKSPACE b/WORKSPACE index db4d05ca208d..333592b19ead 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -282,16 +282,16 @@ filegroup( url = "https://github.com/ethereum/EIPs/archive/5480440fe51742ed23342b68cf106cefd427e39d.tar.gz", ) -consensus_spec_version = "v1.7.0-alpha.11" +consensus_spec_version = "v1.7.0-alpha.12" load("@prysm//tools:download_spectests.bzl", "consensus_spec_tests") consensus_spec_tests( name = "consensus_spec_tests", flavors = { - "general": "sha256-szDpBVO2Ebi8/bwbiWFpW6H4c5gxnpU3hAUS31AF02E=", - "minimal": "sha256-irUv63gOA03eGIFD23Ca3PsDq87ovrA/HVAvtSG6/0o=", - "mainnet": "sha256-lWzAX5uy50Xs0Etg+yu5FnnIDt6C6BtIm11HqdZetms=", + "general": "sha256-Mp889Ykn3yYU7K+8546zxSWKE+hzHS9BC7Mdjkpbnq8=", + "minimal": "sha256-fXng6W/dZmqnDLdBNyk1xdMNStYHrjmYhSEulxSliwc=", + "mainnet": "sha256-8AV9Ks3qJzDsaMrCx5aq2JF04Q6bOKxorX2KocDL2Fw=", }, version = consensus_spec_version, ) @@ -307,7 +307,7 @@ filegroup( visibility = ["//visibility:public"], ) """, - integrity = "sha256-6XWl6m5tkPIlx5eh3DxrHAShRzWh3gz4LlLjIM78wJo=", + integrity = "sha256-bd1ii7rnjYwiEun4br2U/E+zJ9lXZ72WxIditScOM/0=", strip_prefix = "consensus-specs-" + consensus_spec_version[1:], url = "https://github.com/ethereum/consensus-specs/archive/refs/tags/%s.tar.gz" % consensus_spec_version, ) From 4ef371693a68851baba34f6de4dc8998b81f2e7e Mon Sep 17 00:00:00 2001 From: Kasey Kirkham Date: Tue, 4 Aug 2026 17:41:28 -0500 Subject: [PATCH 02/23] Annotate gloas types for progressive container and field merkleization Marks the Gloas containers and collections that EIP-7688 makes progressive: the beacon state, block body, attestation and its aggregate wrappers, the payload bid and envelope, the Gloas execution payload and execution requests, and the data column sidecar. Generation stays gated off by default, so this commit changes no generated code: the emitted hash tree roots still match the pinned spectest fixtures. Building with --//tools:disable_progressive_merkleization=false, or regenerating with SSZ_PROGRESSIVE=1, switches the annotated types over to ProgressiveHashTreeRoot and the progressive collection validators. --- proto/prysm/v1alpha1/gloas.yaml | 36 +++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/proto/prysm/v1alpha1/gloas.yaml b/proto/prysm/v1alpha1/gloas.yaml index c5f875c07018..018ad0742d47 100644 --- a/proto/prysm/v1alpha1/gloas.yaml +++ b/proto/prysm/v1alpha1/gloas.yaml @@ -1,13 +1,38 @@ package: "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1" types: - name: "AttestationGloas" + progressive: {} + fields: + AggregationBits: {type: "ProgressiveBitlist"} - name: "AggregateAttestationAndProofGloas" - name: "SignedAggregateAttestationAndProofGloas" - name: "AttesterSlashingGloas" - name: "BeaconBlockBodyGloas" + progressive: {} + fields: + ProposerSlashings: {type: "ProgressiveList"} + AttesterSlashings: {type: "ProgressiveList"} + Attestations: {type: "ProgressiveList"} + Deposits: {type: "ProgressiveList"} + VoluntaryExits: {type: "ProgressiveList"} + BlsToExecutionChanges: {type: "ProgressiveList"} + PayloadAttestations: {type: "ProgressiveList"} - name: "BeaconBlockContentsGloas" - name: "BeaconBlockGloas" - name: "BeaconStateGloas" + progressive: {} + fields: + Validators: {type: "ProgressiveList"} + Balances: {type: "ProgressiveList"} + PreviousEpochParticipation: {type: "ProgressiveList"} + CurrentEpochParticipation: {type: "ProgressiveList"} + InactivityScores: {type: "ProgressiveList"} + PendingDeposits: {type: "ProgressiveList"} + PendingPartialWithdrawals: {type: "ProgressiveList"} + PendingConsolidations: {type: "ProgressiveList"} + Builders: {type: "ProgressiveList"} + BuilderPendingWithdrawals: {type: "ProgressiveList"} + PayloadExpectedWithdrawals: {type: "ProgressiveList"} - name: "BlindedExecutionPayloadEnvelope" - name: "Builder" - name: "BuilderPendingPayment" @@ -15,10 +40,21 @@ types: - name: "BuilderPreferencesRequest" - name: "BuilderPreferences" - name: "DataColumnSidecarGloas" + fields: + Column: {type: "ProgressiveList"} + KzgProofs: {type: "ProgressiveList"} - name: "ExecutionPayloadBid" + progressive: {} + fields: + BlobKzgCommitments: {type: "ProgressiveList"} - name: "ExecutionPayloadEnvelope" + progressive: {} - name: "IndexedAttestationGloas" + progressive: {} + fields: + AttestingIndices: {type: "ProgressiveList"} - name: "PayloadAttestation" + progressive: {} - name: "PayloadAttestationData" - name: "PayloadAttestationMessage" - name: "ProposerPreferences" From 44f7e059f4d80920dcdda80af73c26e4014b8692 Mon Sep 17 00:00:00 2001 From: Kasey Kirkham Date: Tue, 4 Aug 2026 17:44:41 -0500 Subject: [PATCH 03/23] Invert config and tests to expect progressive merkleization on by default Note: the generated code is modified in the following commit, so at this commit the generated code does not match the output of the build toolchain. --- .bazelrc | 5 +++++ beacon-chain/light-client/lightclient.go | 2 +- .../light-client/progressive_ssz_test.go | 2 +- .../state/fieldtrie/progressive_test.go | 2 +- .../state-native/progressive_ssz_test.go | 16 +++++---------- .../state/stateutil/progressive_root_test.go | 12 +++++------ build/gen/ssz.go | 20 +++++++++++-------- config/features/config.go | 10 +++++----- config/features/config_test.go | 14 ++++++------- config/features/flags.go | 8 ++++---- consensus-types/blocks/proofs_test.go | 4 ++-- .../shared/gloas/ssz_static/ssz_static.go | 4 ++-- 12 files changed, 50 insertions(+), 49 deletions(-) diff --git a/.bazelrc b/.bazelrc index 4ff0eba34949..67b397ae65bf 100644 --- a/.bazelrc +++ b/.bazelrc @@ -24,6 +24,11 @@ build --workspace_status_command=./hack/workspace_status.sh build --define blst_disabled=false run --define blst_disabled=false +# SSZ progressive merkleization is ON by default: gloas (EIP-7688) mandates it +# and the consensus-spec fixtures expect the progressive hash_tree_root values. +# Pass --//tools:disable_progressive_merkleization to build/test the bounded +# form instead. See //tools:BUILD.bazel. + build:blst_disabled --define blst_disabled=true build:blst_disabled --define gotags=blst_disabled diff --git a/beacon-chain/light-client/lightclient.go b/beacon-chain/light-client/lightclient.go index df91e3ac360a..277463a1a966 100644 --- a/beacon-chain/light-client/lightclient.go +++ b/beacon-chain/light-client/lightclient.go @@ -525,7 +525,7 @@ func ComputeWithdrawalsRoot(payload interfaces.ExecutionData) ([]byte, error) { } func progressiveExecutionPayloadSSZEnabled(payload interfaces.ExecutionData) bool { - if payload == nil || !features.Get().EnableProgressiveSSZ { + if payload == nil || !features.ProgressiveSSZEnabled(version.Gloas) { return false } _, ok := payload.Proto().(*enginev1.ExecutionPayloadGloas) diff --git a/beacon-chain/light-client/progressive_ssz_test.go b/beacon-chain/light-client/progressive_ssz_test.go index 349b96d4f010..c2cd5039c1de 100644 --- a/beacon-chain/light-client/progressive_ssz_test.go +++ b/beacon-chain/light-client/progressive_ssz_test.go @@ -29,7 +29,7 @@ func TestProgressiveExecutionPayloadSSZEnabled(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - reset := features.InitWithReset(&features.Flags{EnableProgressiveSSZ: tt.enabled}) + reset := features.InitWithReset(&features.Flags{DisableProgressiveSSZ: !tt.enabled}) defer reset() require.Equal(t, tt.want, progressiveExecutionPayloadSSZEnabled(tt.payload)) diff --git a/beacon-chain/state/fieldtrie/progressive_test.go b/beacon-chain/state/fieldtrie/progressive_test.go index 5861c7f29274..e9307e0aaa0b 100644 --- a/beacon-chain/state/fieldtrie/progressive_test.go +++ b/beacon-chain/state/fieldtrie/progressive_test.go @@ -19,7 +19,7 @@ import ( // stateutil reference helpers return the progressive form. func progressiveRootsEnabled(t *testing.T) { t.Helper() - reset := features.InitWithReset(&features.Flags{EnableProgressiveSSZ: true}) + reset := features.InitWithReset(&features.Flags{}) t.Cleanup(reset) } diff --git a/beacon-chain/state/state-native/progressive_ssz_test.go b/beacon-chain/state/state-native/progressive_ssz_test.go index d85a622706ff..b1b9d5118ce9 100644 --- a/beacon-chain/state/state-native/progressive_ssz_test.go +++ b/beacon-chain/state/state-native/progressive_ssz_test.go @@ -20,11 +20,11 @@ import ( ) func TestProgressiveSSZEnabled(t *testing.T) { - reset := features.InitWithReset(&features.Flags{}) + reset := features.InitWithReset(&features.Flags{DisableProgressiveSSZ: true}) defer reset() require.Equal(t, false, features.ProgressiveSSZEnabled(version.Gloas)) - reset = features.InitWithReset(&features.Flags{EnableProgressiveSSZ: true}) + reset = features.InitWithReset(&features.Flags{}) defer reset() require.Equal(t, true, features.ProgressiveSSZEnabled(version.Gloas)) require.Equal(t, false, features.ProgressiveSSZEnabled(version.Fulu)) @@ -43,7 +43,7 @@ func TestComputeFieldRootsWithHasher_ProgressiveSSZFields(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - reset := features.InitWithReset(&features.Flags{EnableProgressiveSSZ: tt.progressive}) + reset := features.InitWithReset(&features.Flags{DisableProgressiveSSZ: !tt.progressive}) defer reset() roots, err := ComputeFieldRootsWithHasher(context.Background(), st) @@ -116,7 +116,7 @@ func TestHashTreeRoot(t *testing.T) { t.Run("ProgressiveSSZGate", func(t *testing.T) { st := newGloasStateForProgressiveSSZTests(t) - reset := features.InitWithReset(&features.Flags{}) + reset := features.InitWithReset(&features.Flags{DisableProgressiveSSZ: true}) defer reset() legacyRoot, err := st.HashTreeRoot(context.Background()) @@ -128,7 +128,7 @@ func TestHashTreeRoot(t *testing.T) { expectedLegacyRoot := bytesutil.ToBytes32(legacyLayers[len(legacyLayers)-1][0]) require.Equal(t, expectedLegacyRoot, legacyRoot) - reset = features.InitWithReset(&features.Flags{EnableProgressiveSSZ: true}) + reset = features.InitWithReset(&features.Flags{DisableProgressiveSSZ: false}) defer reset() progressiveRoot, err := st.HashTreeRoot(context.Background()) @@ -157,9 +157,6 @@ func TestHashTreeRoot(t *testing.T) { }) t.Run("ProgressiveSSZIncremental", func(t *testing.T) { - reset := features.InitWithReset(&features.Flags{EnableProgressiveSSZ: true}) - defer reset() - st := newGloasStateForProgressiveSSZTests(t) initialRoot, err := st.HashTreeRoot(context.Background()) require.NoError(t, err) @@ -195,9 +192,6 @@ func TestHashTreeRoot(t *testing.T) { }) t.Run("ProgressiveSSZCopy", func(t *testing.T) { - reset := features.InitWithReset(&features.Flags{EnableProgressiveSSZ: true}) - defer reset() - st := newGloasStateForProgressiveSSZTests(t) originalRoot, err := st.HashTreeRoot(context.Background()) require.NoError(t, err) diff --git a/beacon-chain/state/stateutil/progressive_root_test.go b/beacon-chain/state/stateutil/progressive_root_test.go index 4c388f341d22..33e7a7ead1fd 100644 --- a/beacon-chain/state/stateutil/progressive_root_test.go +++ b/beacon-chain/state/stateutil/progressive_root_test.go @@ -14,7 +14,7 @@ import ( ) func TestValidatorRegistryRootProgressive(t *testing.T) { - reset := features.InitWithReset(&features.Flags{EnableProgressiveSSZ: true}) + reset := features.InitWithReset(&features.Flags{}) defer reset() pubkey := make([]byte, fieldparams.BLSPubkeyLength) @@ -49,7 +49,7 @@ func TestValidatorRegistryRootProgressive(t *testing.T) { } func TestUint64ListRootProgressive(t *testing.T) { - reset := features.InitWithReset(&features.Flags{EnableProgressiveSSZ: true}) + reset := features.InitWithReset(&features.Flags{}) defer reset() vals := []uint64{1, 2, 3, 4, 5, 6, 7} @@ -67,7 +67,7 @@ func TestUint64ListRootProgressive(t *testing.T) { } func TestParticipationBitsRootProgressive(t *testing.T) { - reset := features.InitWithReset(&features.Flags{EnableProgressiveSSZ: true}) + reset := features.InitWithReset(&features.Flags{}) defer reset() bits := []byte{0x01, 0x02, 0x03, 0x04} @@ -81,7 +81,7 @@ func TestParticipationBitsRootProgressive(t *testing.T) { } func TestBuildersRootProgressive(t *testing.T) { - reset := features.InitWithReset(&features.Flags{EnableProgressiveSSZ: true}) + reset := features.InitWithReset(&features.Flags{}) defer reset() builders := []*ethpb.Builder{{ @@ -101,7 +101,7 @@ func TestBuildersRootProgressive(t *testing.T) { } func TestPendingRootsProgressive(t *testing.T) { - reset := features.InitWithReset(&features.Flags{EnableProgressiveSSZ: true}) + reset := features.InitWithReset(&features.Flags{}) defer reset() pendingDeposits := []*ethpb.PendingDeposit{{ @@ -131,7 +131,7 @@ func TestPendingRootsProgressive(t *testing.T) { } func TestBuilderPendingWithdrawalsRootProgressive(t *testing.T) { - reset := features.InitWithReset(&features.Flags{EnableProgressiveSSZ: true}) + reset := features.InitWithReset(&features.Flags{}) defer reset() withdrawals := []*ethpb.BuilderPendingWithdrawal{{ diff --git a/build/gen/ssz.go b/build/gen/ssz.go index bf0513a1286a..2430dd517ae6 100644 --- a/build/gen/ssz.go +++ b/build/gen/ssz.go @@ -32,14 +32,18 @@ func genSSZ() error { return fmt.Errorf("load methodical targets: %w", err) } - // Progressive merkleization is gated OFF by default so that generated - // hash_tree_root values match the current (non-progressive) spectest - // fixtures. This mirrors the //tools:disable_progressive_merkleization - // default set in .bazelrc. Set SSZ_PROGRESSIVE=1 to generate the - // progressive form once upstream fixtures move to it. - progressive, _ := strconv.ParseBool(os.Getenv("SSZ_PROGRESSIVE")) - if progressive { - fmt.Println("SSZ_PROGRESSIVE=1: generating with progressive merkleization ON") + // Progressive merkleization is ON by default: gloas (EIP-7688) mandates it + // and the consensus-spec fixtures expect the progressive hash_tree_root + // values. This mirrors the //tools:disable_progressive_merkleization + // default in .bazelrc. Set SSZ_PROGRESSIVE=0 to generate the bounded form. + progressive := true + if v, ok := os.LookupEnv("SSZ_PROGRESSIVE"); ok { + if parsed, err := strconv.ParseBool(v); err == nil { + progressive = parsed + } + } + if !progressive { + fmt.Println("SSZ_PROGRESSIVE=0: generating with progressive merkleization OFF") } for _, t := range targets { diff --git a/config/features/config.go b/config/features/config.go index 1e87c0623774..8415d2e5b119 100644 --- a/config/features/config.go +++ b/config/features/config.go @@ -50,7 +50,7 @@ type Flags struct { DisableDutiesV2 bool // DisableDutiesV2 sets validator client to use the get Duties endpoint EnableWeb bool // EnableWeb enables the webui on the validator client EnableStateDiff bool // EnableStateDiff enables the experimental state diff feature for the beacon node. - EnableProgressiveSSZ bool // EnableProgressiveSSZ enables experimental progressive SSZ merkleization for converted consensus types. + DisableProgressiveSSZ bool // DisableProgressiveSSZ turns off progressive SSZ merkleization for Gloas consensus types. ReorgLatePayloads bool // ReorgLatePayloads enables reorging late payloads in the beacon node. // Logging related toggles. @@ -113,7 +113,7 @@ func Get() *Flags { // ProgressiveSSZEnabled reports whether progressive SSZ is enabled for the // supplied state version. func ProgressiveSSZEnabled(stateVersion int) bool { - return stateVersion >= version.Gloas && Get().EnableProgressiveSSZ + return stateVersion >= version.Gloas && !Get().DisableProgressiveSSZ } // Init sets the global config equal to the config that is passed in. @@ -305,9 +305,9 @@ func ConfigureBeaconChain(ctx *cli.Context) error { cfg.EnableHistoricalSpaceRepresentation = false } } - if ctx.IsSet(EnableProgressiveSSZ.Name) { - logEnabled(EnableProgressiveSSZ) - cfg.EnableProgressiveSSZ = true + if ctx.IsSet(DisableProgressiveSSZ.Name) { + logDisabled(DisableProgressiveSSZ) + cfg.DisableProgressiveSSZ = true } if ctx.Bool(reorgLatePayloads.Name) { logEnabled(reorgLatePayloads) diff --git a/config/features/config_test.go b/config/features/config_test.go index 7cbcbc7d2980..cf862edd447d 100644 --- a/config/features/config_test.go +++ b/config/features/config_test.go @@ -70,16 +70,14 @@ func TestConfigureBeaconConfig(t *testing.T) { assert.Equal(t, true, c.SaveInvalidBlock) } -func TestConfigureBeaconConfig_EnableProgressiveSSZ(t *testing.T) { - defer Init(&Flags{}) - +func TestConfigureBeaconConfig_DisableProgressiveSSZ(t *testing.T) { app := cli.App{} set := flag.NewFlagSet("test", 0) - set.Bool(EnableProgressiveSSZ.Name, false, "test") - require.NoError(t, set.Set(EnableProgressiveSSZ.Name, "true")) - context := cli.NewContext(&app, set, nil) - require.NoError(t, ConfigureBeaconChain(context)) - assert.Equal(t, true, Get().EnableProgressiveSSZ) + ctx := cli.NewContext(&app, set, nil) + set.Bool(DisableProgressiveSSZ.Name, false, "test") + require.NoError(t, set.Set(DisableProgressiveSSZ.Name, "true")) + require.NoError(t, ConfigureBeaconChain(ctx)) + assert.Equal(t, true, Get().DisableProgressiveSSZ) } func TestConfigureBeaconConfig_ReorgLatePayloads(t *testing.T) { diff --git a/config/features/flags.go b/config/features/flags.go index c90ffd2b5d13..25788cf1eb3d 100644 --- a/config/features/flags.go +++ b/config/features/flags.go @@ -182,9 +182,9 @@ var ( Name: "enable-state-diff", Usage: "Enables the experimental state diff feature.", } - EnableProgressiveSSZ = &cli.BoolFlag{ - Name: "enable-progressive-ssz", - Usage: "Enables experimental progressive SSZ merkleization for converted consensus types.", + DisableProgressiveSSZ = &cli.BoolFlag{ + Name: "disable-progressive-ssz", + Usage: "Disables progressive SSZ merkleization for Gloas consensus types. Gloas (EIP-7688) mandates it, so this is an escape hatch for debugging only.", Hidden: true, } reorgLatePayloads = &cli.BoolFlag{ @@ -293,7 +293,7 @@ var BeaconChainFlags = combinedFlags([]cli.Flag{ EnableDiscoveryReboot, enableExperimentalAttestationPool, EnableStateDiff, - EnableProgressiveSSZ, + DisableProgressiveSSZ, reorgLatePayloads, forceHeadFlag, blacklistRoots, diff --git a/consensus-types/blocks/proofs_test.go b/consensus-types/blocks/proofs_test.go index d6d751cfaf10..6a1a56ba955f 100644 --- a/consensus-types/blocks/proofs_test.go +++ b/consensus-types/blocks/proofs_test.go @@ -156,7 +156,7 @@ func TestComputeBlockBodyFieldRoots_Gloas_ProgressiveSSZGate(t *testing.T) { b, ok := i.(*BeaconBlockBody) require.Equal(t, true, ok) - reset := features.InitWithReset(&features.Flags{}) + reset := features.InitWithReset(&features.Flags{DisableProgressiveSSZ: true}) defer reset() legacyRoots, err := ComputeBlockBodyFieldRoots(t.Context(), b) @@ -169,7 +169,7 @@ func TestComputeBlockBodyFieldRoots_Gloas_ProgressiveSSZGate(t *testing.T) { require.NoError(t, err) require.DeepEqual(t, expectedLegacyPayloadAttestationsRoot[:], legacyRoots[11]) - reset = features.InitWithReset(&features.Flags{EnableProgressiveSSZ: true}) + reset = features.InitWithReset(&features.Flags{}) defer reset() progressiveRoots, err := ComputeBlockBodyFieldRoots(t.Context(), b) diff --git a/testing/spectest/shared/gloas/ssz_static/ssz_static.go b/testing/spectest/shared/gloas/ssz_static/ssz_static.go index bdef5cae9dec..1940107af20b 100644 --- a/testing/spectest/shared/gloas/ssz_static/ssz_static.go +++ b/testing/spectest/shared/gloas/ssz_static/ssz_static.go @@ -20,7 +20,7 @@ import ( // RunSSZStaticTests executes "ssz_static" tests. // // The native-state (`custom`) HashTreeRoot uses progressive merkleization only -// when features.EnableProgressiveSSZ is set (and version >= Gloas). That runtime +// for Gloas types unless features.DisableProgressiveSSZ is set. That runtime // flag is independent of the --//tools:disable_progressive_merkleization codegen // flag, so when running gloas against progressive fixtures set PROGRESSIVE_SSZ=1 // to align the native-state root with the generated one. Leave it unset for the @@ -28,7 +28,7 @@ import ( func RunSSZStaticTests(t *testing.T, config string) { if os.Getenv("PROGRESSIVE_SSZ") != "" { cfg := *features.Get() // nil-safe; copy so other flags are preserved - cfg.EnableProgressiveSSZ = true + cfg.DisableProgressiveSSZ = false reset := features.InitWithReset(&cfg) defer reset() } From 7baffead8ba1c6b8fd8b8f8d2a4558b757d23036 Mon Sep 17 00:00:00 2001 From: Kasey Kirkham Date: Tue, 4 Aug 2026 17:46:15 -0500 Subject: [PATCH 04/23] Commit updated methodical codegen with progressive merkleization flipped to default-on --- proto/engine/v1/engine.minimal.ssz.go | 131 +++----- proto/engine/v1/engine.ssz.go | 131 +++----- proto/engine/v1/engine.yaml | 17 + proto/prysm/v1alpha1/gloas.minimal.ssz.go | 364 +++++++--------------- proto/prysm/v1alpha1/gloas.ssz.go | 364 +++++++--------------- 5 files changed, 317 insertions(+), 690 deletions(-) diff --git a/proto/engine/v1/engine.minimal.ssz.go b/proto/engine/v1/engine.minimal.ssz.go index fdecf76a4d6d..14f77f2687f2 100644 --- a/proto/engine/v1/engine.minimal.ssz.go +++ b/proto/engine/v1/engine.minimal.ssz.go @@ -2088,9 +2088,6 @@ func (c *ExecutionPayloadGloas) MarshalSSZTo(dst []byte) ([]byte, error) { dst = append(dst, c.ExtraData...) // Field 13: Transactions - if len(c.Transactions) > 1048576 { - return nil, ssz.ErrListTooBig - } { offset = 4 * len(c.Transactions) for _, o := range c.Transactions { @@ -2099,16 +2096,10 @@ func (c *ExecutionPayloadGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } } for _, o := range c.Transactions { - if len(o) > 1073741824 { - return nil, ssz.ErrListTooBig - } dst = append(dst, o...) } // Field 14: Withdrawals - if len(c.Withdrawals) > 4 { - return nil, ssz.ErrListTooBig - } for _, o := range c.Withdrawals { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("Withdrawals: %w", err) @@ -2116,9 +2107,6 @@ func (c *ExecutionPayloadGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 17: BlockAccessList - if len(c.BlockAccessList) > 1073741824 { - return nil, ssz.ErrListTooBig - } dst = append(dst, c.BlockAccessList...) return dst, err } @@ -2230,9 +2218,6 @@ func (c *ExecutionPayloadGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned list bytes: when decoding c.Transactions, end-of-list offset is %d, which is not a multiple of 4 (offset size)", startOffset) } listLen := startOffset / 4 - if listLen > 1048576 { - return fmt.Errorf("ssz-max exceeded: c.Transactions has %d elements, ssz-max is 1048576: %w", listLen, ssz.ErrListTooBig) - } totalVarBytes := uint64(len(sszSlice13)) if totalVarBytes < startOffset { return fmt.Errorf("list bytes too short to contain an offset when decoding c.Transactions") @@ -2271,9 +2256,6 @@ func (c *ExecutionPayloadGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.Withdrawals length is %d, which is not a multiple of 44: %w", len(sszSlice14), ssz.ErrIncorrectListSize) } numElem := len(sszSlice14) / 44 - if numElem > 4 { - return fmt.Errorf("ssz-max exceeded: c.Withdrawals has %d elements, ssz-max is 4: %w", numElem, ssz.ErrListTooBig) - } c.Withdrawals = make([]*Withdrawal, numElem) for i := 0; i < numElem; i++ { var tmp *Withdrawal @@ -2303,8 +2285,18 @@ func (c *ExecutionPayloadGloas) UnmarshalSSZ(buf []byte) error { } func (c *ExecutionPayloadGloas) HashTreeRoot() ([32]byte, error) { + return c.ProgressiveHashTreeRoot() +} + +func (c *ExecutionPayloadGloas) HashTreeRootWith(hh *ssz.Hasher) error { + return c.ProgressiveHashTreeRootWith(hh) +} + +var activeFieldsExecutionPayloadGloas = []byte{0b11111111, 0b11111111, 0b00000111} + +func (c *ExecutionPayloadGloas) ProgressiveHashTreeRoot() ([32]byte, error) { hh := ssz.DefaultHasherPool.Get() - if err := c.HashTreeRootWith(hh); err != nil { + if err := c.ProgressiveHashTreeRootWith(hh); err != nil { ssz.DefaultHasherPool.Put(hh) return [32]byte{}, err } @@ -2313,7 +2305,7 @@ func (c *ExecutionPayloadGloas) HashTreeRoot() ([32]byte, error) { return root, err } -func (c *ExecutionPayloadGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { +func (c *ExecutionPayloadGloas) ProgressiveHashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() // Field 0: ParentHash if len(c.ParentHash) != 32 { @@ -2377,59 +2369,41 @@ func (c *ExecutionPayloadGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { hh.PutBytes(c.BlockHash) // Field 13: Transactions { - if len(c.Transactions) > 1048576 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.Transactions { - { - if len(o) > 1073741824 { - return ssz.ErrBytesLength - } subIndx := hh.Index() hh.AppendBytes32(o) - numItems := uint64(len(o)) - hh.MerkleizeWithMixin(subIndx, numItems, (1073741824*1+31)/32) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(o))) } - } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.Transactions)), 1048576) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.Transactions))) } // Field 14: Withdrawals { - if len(c.Withdrawals) > 4 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.Withdrawals { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("Withdrawals: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.Withdrawals)), 4) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.Withdrawals))) } // Field 15: BlobGasUsed hh.PutUint64(c.BlobGasUsed) // Field 16: ExcessBlobGas hh.PutUint64(c.ExcessBlobGas) // Field 17: BlockAccessList - { - if len(c.BlockAccessList) > 1073741824 { - return ssz.ErrBytesLength - } subIndx := hh.Index() hh.AppendBytes32(c.BlockAccessList) - numItems := uint64(len(c.BlockAccessList)) - hh.MerkleizeWithMixin(subIndx, numItems, (1073741824*1+31)/32) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.BlockAccessList))) } - // Field 18: SlotNumber if err := c.SlotNumber.HashTreeRootWith(hh); err != nil { return fmt.Errorf("SlotNumber: %w", err) } - hh.Merkleize(indx) + hh.MerkleizeProgressiveWithActiveFields(indx, activeFieldsExecutionPayloadGloas) return nil } @@ -3721,9 +3695,6 @@ func (c *ExecutionRequestsGloas) MarshalSSZTo(dst []byte) ([]byte, error) { offset += len(c.BuilderExits) * 68 // Field 0: Deposits - if len(c.Deposits) > 8192 { - return nil, ssz.ErrListTooBig - } for _, o := range c.Deposits { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("Deposits: %w", err) @@ -3731,9 +3702,6 @@ func (c *ExecutionRequestsGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 1: Withdrawals - if len(c.Withdrawals) > 16 { - return nil, ssz.ErrListTooBig - } for _, o := range c.Withdrawals { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("Withdrawals: %w", err) @@ -3741,9 +3709,6 @@ func (c *ExecutionRequestsGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 2: Consolidations - if len(c.Consolidations) > 2 { - return nil, ssz.ErrListTooBig - } for _, o := range c.Consolidations { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("Consolidations: %w", err) @@ -3751,9 +3716,6 @@ func (c *ExecutionRequestsGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 3: BuilderDeposits - if len(c.BuilderDeposits) > 256 { - return nil, ssz.ErrListTooBig - } for _, o := range c.BuilderDeposits { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("BuilderDeposits: %w", err) @@ -3761,9 +3723,6 @@ func (c *ExecutionRequestsGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 4: BuilderExits - if len(c.BuilderExits) > 16 { - return nil, ssz.ErrListTooBig - } for _, o := range c.BuilderExits { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("BuilderExits: %w", err) @@ -3814,9 +3773,6 @@ func (c *ExecutionRequestsGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.Deposits length is %d, which is not a multiple of 192: %w", len(sszSlice0), ssz.ErrIncorrectListSize) } numElem := len(sszSlice0) / 192 - if numElem > 8192 { - return fmt.Errorf("ssz-max exceeded: c.Deposits has %d elements, ssz-max is 8192: %w", numElem, ssz.ErrListTooBig) - } c.Deposits = make([]*DepositRequest, numElem) for i := 0; i < numElem; i++ { var tmp *DepositRequest @@ -3835,9 +3791,6 @@ func (c *ExecutionRequestsGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.Withdrawals length is %d, which is not a multiple of 76: %w", len(sszSlice1), ssz.ErrIncorrectListSize) } numElem := len(sszSlice1) / 76 - if numElem > 16 { - return fmt.Errorf("ssz-max exceeded: c.Withdrawals has %d elements, ssz-max is 16: %w", numElem, ssz.ErrListTooBig) - } c.Withdrawals = make([]*WithdrawalRequest, numElem) for i := 0; i < numElem; i++ { var tmp *WithdrawalRequest @@ -3856,9 +3809,6 @@ func (c *ExecutionRequestsGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.Consolidations length is %d, which is not a multiple of 116: %w", len(sszSlice2), ssz.ErrIncorrectListSize) } numElem := len(sszSlice2) / 116 - if numElem > 2 { - return fmt.Errorf("ssz-max exceeded: c.Consolidations has %d elements, ssz-max is 2: %w", numElem, ssz.ErrListTooBig) - } c.Consolidations = make([]*ConsolidationRequest, numElem) for i := 0; i < numElem; i++ { var tmp *ConsolidationRequest @@ -3877,9 +3827,6 @@ func (c *ExecutionRequestsGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.BuilderDeposits length is %d, which is not a multiple of 184: %w", len(sszSlice3), ssz.ErrIncorrectListSize) } numElem := len(sszSlice3) / 184 - if numElem > 256 { - return fmt.Errorf("ssz-max exceeded: c.BuilderDeposits has %d elements, ssz-max is 256: %w", numElem, ssz.ErrListTooBig) - } c.BuilderDeposits = make([]*BuilderDepositRequest, numElem) for i := 0; i < numElem; i++ { var tmp *BuilderDepositRequest @@ -3898,9 +3845,6 @@ func (c *ExecutionRequestsGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.BuilderExits length is %d, which is not a multiple of 68: %w", len(sszSlice4), ssz.ErrIncorrectListSize) } numElem := len(sszSlice4) / 68 - if numElem > 16 { - return fmt.Errorf("ssz-max exceeded: c.BuilderExits has %d elements, ssz-max is 16: %w", numElem, ssz.ErrListTooBig) - } c.BuilderExits = make([]*BuilderExitRequest, numElem) for i := 0; i < numElem; i++ { var tmp *BuilderExitRequest @@ -3916,8 +3860,18 @@ func (c *ExecutionRequestsGloas) UnmarshalSSZ(buf []byte) error { } func (c *ExecutionRequestsGloas) HashTreeRoot() ([32]byte, error) { + return c.ProgressiveHashTreeRoot() +} + +func (c *ExecutionRequestsGloas) HashTreeRootWith(hh *ssz.Hasher) error { + return c.ProgressiveHashTreeRootWith(hh) +} + +var activeFieldsExecutionRequestsGloas = []byte{0b00011111} + +func (c *ExecutionRequestsGloas) ProgressiveHashTreeRoot() ([32]byte, error) { hh := ssz.DefaultHasherPool.Get() - if err := c.HashTreeRootWith(hh); err != nil { + if err := c.ProgressiveHashTreeRootWith(hh); err != nil { ssz.DefaultHasherPool.Put(hh) return [32]byte{}, err } @@ -3926,74 +3880,59 @@ func (c *ExecutionRequestsGloas) HashTreeRoot() ([32]byte, error) { return root, err } -func (c *ExecutionRequestsGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { +func (c *ExecutionRequestsGloas) ProgressiveHashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() // Field 0: Deposits { - if len(c.Deposits) > 8192 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.Deposits { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("Deposits: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.Deposits)), 8192) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.Deposits))) } // Field 1: Withdrawals { - if len(c.Withdrawals) > 16 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.Withdrawals { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("Withdrawals: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.Withdrawals)), 16) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.Withdrawals))) } // Field 2: Consolidations { - if len(c.Consolidations) > 2 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.Consolidations { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("Consolidations: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.Consolidations)), 2) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.Consolidations))) } // Field 3: BuilderDeposits { - if len(c.BuilderDeposits) > 256 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.BuilderDeposits { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("BuilderDeposits: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.BuilderDeposits)), 256) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.BuilderDeposits))) } // Field 4: BuilderExits { - if len(c.BuilderExits) > 16 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.BuilderExits { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("BuilderExits: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.BuilderExits)), 16) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.BuilderExits))) } - hh.Merkleize(indx) + hh.MerkleizeProgressiveWithActiveFields(indx, activeFieldsExecutionRequestsGloas) return nil } diff --git a/proto/engine/v1/engine.ssz.go b/proto/engine/v1/engine.ssz.go index e4d601fda6a8..f0a158b3c4e6 100644 --- a/proto/engine/v1/engine.ssz.go +++ b/proto/engine/v1/engine.ssz.go @@ -2088,9 +2088,6 @@ func (c *ExecutionPayloadGloas) MarshalSSZTo(dst []byte) ([]byte, error) { dst = append(dst, c.ExtraData...) // Field 13: Transactions - if len(c.Transactions) > 1048576 { - return nil, ssz.ErrListTooBig - } { offset = 4 * len(c.Transactions) for _, o := range c.Transactions { @@ -2099,16 +2096,10 @@ func (c *ExecutionPayloadGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } } for _, o := range c.Transactions { - if len(o) > 1073741824 { - return nil, ssz.ErrListTooBig - } dst = append(dst, o...) } // Field 14: Withdrawals - if len(c.Withdrawals) > 16 { - return nil, ssz.ErrListTooBig - } for _, o := range c.Withdrawals { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("Withdrawals: %w", err) @@ -2116,9 +2107,6 @@ func (c *ExecutionPayloadGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 17: BlockAccessList - if len(c.BlockAccessList) > 1073741824 { - return nil, ssz.ErrListTooBig - } dst = append(dst, c.BlockAccessList...) return dst, err } @@ -2230,9 +2218,6 @@ func (c *ExecutionPayloadGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned list bytes: when decoding c.Transactions, end-of-list offset is %d, which is not a multiple of 4 (offset size)", startOffset) } listLen := startOffset / 4 - if listLen > 1048576 { - return fmt.Errorf("ssz-max exceeded: c.Transactions has %d elements, ssz-max is 1048576: %w", listLen, ssz.ErrListTooBig) - } totalVarBytes := uint64(len(sszSlice13)) if totalVarBytes < startOffset { return fmt.Errorf("list bytes too short to contain an offset when decoding c.Transactions") @@ -2271,9 +2256,6 @@ func (c *ExecutionPayloadGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.Withdrawals length is %d, which is not a multiple of 44: %w", len(sszSlice14), ssz.ErrIncorrectListSize) } numElem := len(sszSlice14) / 44 - if numElem > 16 { - return fmt.Errorf("ssz-max exceeded: c.Withdrawals has %d elements, ssz-max is 16: %w", numElem, ssz.ErrListTooBig) - } c.Withdrawals = make([]*Withdrawal, numElem) for i := 0; i < numElem; i++ { var tmp *Withdrawal @@ -2303,8 +2285,18 @@ func (c *ExecutionPayloadGloas) UnmarshalSSZ(buf []byte) error { } func (c *ExecutionPayloadGloas) HashTreeRoot() ([32]byte, error) { + return c.ProgressiveHashTreeRoot() +} + +func (c *ExecutionPayloadGloas) HashTreeRootWith(hh *ssz.Hasher) error { + return c.ProgressiveHashTreeRootWith(hh) +} + +var activeFieldsExecutionPayloadGloas = []byte{0b11111111, 0b11111111, 0b00000111} + +func (c *ExecutionPayloadGloas) ProgressiveHashTreeRoot() ([32]byte, error) { hh := ssz.DefaultHasherPool.Get() - if err := c.HashTreeRootWith(hh); err != nil { + if err := c.ProgressiveHashTreeRootWith(hh); err != nil { ssz.DefaultHasherPool.Put(hh) return [32]byte{}, err } @@ -2313,7 +2305,7 @@ func (c *ExecutionPayloadGloas) HashTreeRoot() ([32]byte, error) { return root, err } -func (c *ExecutionPayloadGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { +func (c *ExecutionPayloadGloas) ProgressiveHashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() // Field 0: ParentHash if len(c.ParentHash) != 32 { @@ -2377,59 +2369,41 @@ func (c *ExecutionPayloadGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { hh.PutBytes(c.BlockHash) // Field 13: Transactions { - if len(c.Transactions) > 1048576 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.Transactions { - { - if len(o) > 1073741824 { - return ssz.ErrBytesLength - } subIndx := hh.Index() hh.AppendBytes32(o) - numItems := uint64(len(o)) - hh.MerkleizeWithMixin(subIndx, numItems, (1073741824*1+31)/32) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(o))) } - } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.Transactions)), 1048576) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.Transactions))) } // Field 14: Withdrawals { - if len(c.Withdrawals) > 16 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.Withdrawals { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("Withdrawals: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.Withdrawals)), 16) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.Withdrawals))) } // Field 15: BlobGasUsed hh.PutUint64(c.BlobGasUsed) // Field 16: ExcessBlobGas hh.PutUint64(c.ExcessBlobGas) // Field 17: BlockAccessList - { - if len(c.BlockAccessList) > 1073741824 { - return ssz.ErrBytesLength - } subIndx := hh.Index() hh.AppendBytes32(c.BlockAccessList) - numItems := uint64(len(c.BlockAccessList)) - hh.MerkleizeWithMixin(subIndx, numItems, (1073741824*1+31)/32) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.BlockAccessList))) } - // Field 18: SlotNumber if err := c.SlotNumber.HashTreeRootWith(hh); err != nil { return fmt.Errorf("SlotNumber: %w", err) } - hh.Merkleize(indx) + hh.MerkleizeProgressiveWithActiveFields(indx, activeFieldsExecutionPayloadGloas) return nil } @@ -3721,9 +3695,6 @@ func (c *ExecutionRequestsGloas) MarshalSSZTo(dst []byte) ([]byte, error) { offset += len(c.BuilderExits) * 68 // Field 0: Deposits - if len(c.Deposits) > 8192 { - return nil, ssz.ErrListTooBig - } for _, o := range c.Deposits { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("Deposits: %w", err) @@ -3731,9 +3702,6 @@ func (c *ExecutionRequestsGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 1: Withdrawals - if len(c.Withdrawals) > 16 { - return nil, ssz.ErrListTooBig - } for _, o := range c.Withdrawals { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("Withdrawals: %w", err) @@ -3741,9 +3709,6 @@ func (c *ExecutionRequestsGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 2: Consolidations - if len(c.Consolidations) > 2 { - return nil, ssz.ErrListTooBig - } for _, o := range c.Consolidations { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("Consolidations: %w", err) @@ -3751,9 +3716,6 @@ func (c *ExecutionRequestsGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 3: BuilderDeposits - if len(c.BuilderDeposits) > 256 { - return nil, ssz.ErrListTooBig - } for _, o := range c.BuilderDeposits { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("BuilderDeposits: %w", err) @@ -3761,9 +3723,6 @@ func (c *ExecutionRequestsGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 4: BuilderExits - if len(c.BuilderExits) > 16 { - return nil, ssz.ErrListTooBig - } for _, o := range c.BuilderExits { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("BuilderExits: %w", err) @@ -3814,9 +3773,6 @@ func (c *ExecutionRequestsGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.Deposits length is %d, which is not a multiple of 192: %w", len(sszSlice0), ssz.ErrIncorrectListSize) } numElem := len(sszSlice0) / 192 - if numElem > 8192 { - return fmt.Errorf("ssz-max exceeded: c.Deposits has %d elements, ssz-max is 8192: %w", numElem, ssz.ErrListTooBig) - } c.Deposits = make([]*DepositRequest, numElem) for i := 0; i < numElem; i++ { var tmp *DepositRequest @@ -3835,9 +3791,6 @@ func (c *ExecutionRequestsGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.Withdrawals length is %d, which is not a multiple of 76: %w", len(sszSlice1), ssz.ErrIncorrectListSize) } numElem := len(sszSlice1) / 76 - if numElem > 16 { - return fmt.Errorf("ssz-max exceeded: c.Withdrawals has %d elements, ssz-max is 16: %w", numElem, ssz.ErrListTooBig) - } c.Withdrawals = make([]*WithdrawalRequest, numElem) for i := 0; i < numElem; i++ { var tmp *WithdrawalRequest @@ -3856,9 +3809,6 @@ func (c *ExecutionRequestsGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.Consolidations length is %d, which is not a multiple of 116: %w", len(sszSlice2), ssz.ErrIncorrectListSize) } numElem := len(sszSlice2) / 116 - if numElem > 2 { - return fmt.Errorf("ssz-max exceeded: c.Consolidations has %d elements, ssz-max is 2: %w", numElem, ssz.ErrListTooBig) - } c.Consolidations = make([]*ConsolidationRequest, numElem) for i := 0; i < numElem; i++ { var tmp *ConsolidationRequest @@ -3877,9 +3827,6 @@ func (c *ExecutionRequestsGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.BuilderDeposits length is %d, which is not a multiple of 184: %w", len(sszSlice3), ssz.ErrIncorrectListSize) } numElem := len(sszSlice3) / 184 - if numElem > 256 { - return fmt.Errorf("ssz-max exceeded: c.BuilderDeposits has %d elements, ssz-max is 256: %w", numElem, ssz.ErrListTooBig) - } c.BuilderDeposits = make([]*BuilderDepositRequest, numElem) for i := 0; i < numElem; i++ { var tmp *BuilderDepositRequest @@ -3898,9 +3845,6 @@ func (c *ExecutionRequestsGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.BuilderExits length is %d, which is not a multiple of 68: %w", len(sszSlice4), ssz.ErrIncorrectListSize) } numElem := len(sszSlice4) / 68 - if numElem > 16 { - return fmt.Errorf("ssz-max exceeded: c.BuilderExits has %d elements, ssz-max is 16: %w", numElem, ssz.ErrListTooBig) - } c.BuilderExits = make([]*BuilderExitRequest, numElem) for i := 0; i < numElem; i++ { var tmp *BuilderExitRequest @@ -3916,8 +3860,18 @@ func (c *ExecutionRequestsGloas) UnmarshalSSZ(buf []byte) error { } func (c *ExecutionRequestsGloas) HashTreeRoot() ([32]byte, error) { + return c.ProgressiveHashTreeRoot() +} + +func (c *ExecutionRequestsGloas) HashTreeRootWith(hh *ssz.Hasher) error { + return c.ProgressiveHashTreeRootWith(hh) +} + +var activeFieldsExecutionRequestsGloas = []byte{0b00011111} + +func (c *ExecutionRequestsGloas) ProgressiveHashTreeRoot() ([32]byte, error) { hh := ssz.DefaultHasherPool.Get() - if err := c.HashTreeRootWith(hh); err != nil { + if err := c.ProgressiveHashTreeRootWith(hh); err != nil { ssz.DefaultHasherPool.Put(hh) return [32]byte{}, err } @@ -3926,74 +3880,59 @@ func (c *ExecutionRequestsGloas) HashTreeRoot() ([32]byte, error) { return root, err } -func (c *ExecutionRequestsGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { +func (c *ExecutionRequestsGloas) ProgressiveHashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() // Field 0: Deposits { - if len(c.Deposits) > 8192 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.Deposits { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("Deposits: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.Deposits)), 8192) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.Deposits))) } // Field 1: Withdrawals { - if len(c.Withdrawals) > 16 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.Withdrawals { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("Withdrawals: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.Withdrawals)), 16) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.Withdrawals))) } // Field 2: Consolidations { - if len(c.Consolidations) > 2 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.Consolidations { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("Consolidations: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.Consolidations)), 2) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.Consolidations))) } // Field 3: BuilderDeposits { - if len(c.BuilderDeposits) > 256 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.BuilderDeposits { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("BuilderDeposits: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.BuilderDeposits)), 256) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.BuilderDeposits))) } // Field 4: BuilderExits { - if len(c.BuilderExits) > 16 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.BuilderExits { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("BuilderExits: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.BuilderExits)), 16) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.BuilderExits))) } - hh.Merkleize(indx) + hh.MerkleizeProgressiveWithActiveFields(indx, activeFieldsExecutionRequestsGloas) return nil } diff --git a/proto/engine/v1/engine.yaml b/proto/engine/v1/engine.yaml index 10406a3433dc..28f72d362000 100644 --- a/proto/engine/v1/engine.yaml +++ b/proto/engine/v1/engine.yaml @@ -10,12 +10,29 @@ types: - name: "ExecutionPayloadCapella" - name: "ExecutionPayloadDeneb" - name: "ExecutionPayloadGloas" + progressive: {} + fields: + Transactions: {type: "ProgressiveList", element: {type: "ProgressiveByteList"}} + Withdrawals: {type: "ProgressiveList"} + BlockAccessList: {type: "ProgressiveList"} - name: "ExecutionPayloadDenebAndBlobsBundle" - name: "ExecutionPayloadDenebAndBlobsBundleV2" - name: "ExecutionPayloadHeader" - name: "ExecutionPayloadHeaderCapella" - name: "ExecutionPayloadHeaderDeneb" + # Base ExecutionRequests is the electra/fulu (pre-gloas) type: bounded lists, + # NOT progressive. Progressive merkleization is introduced only at gloas + # (EIP-7688), and gloas uses the distinct ExecutionRequestsGloas message + # below. Annotating this base type progressive leaks into electra/fulu and + # breaks pre-gloas containment. - name: "ExecutionRequests" - name: "ExecutionRequestsGloas" + progressive: {} + fields: + Deposits: {type: "ProgressiveList"} + Withdrawals: {type: "ProgressiveList"} + Consolidations: {type: "ProgressiveList"} + BuilderDeposits: {type: "ProgressiveList"} + BuilderExits: {type: "ProgressiveList"} - name: "Withdrawal" - name: "WithdrawalRequest" diff --git a/proto/prysm/v1alpha1/gloas.minimal.ssz.go b/proto/prysm/v1alpha1/gloas.minimal.ssz.go index bf90aff351e5..5ecf78d38816 100644 --- a/proto/prysm/v1alpha1/gloas.minimal.ssz.go +++ b/proto/prysm/v1alpha1/gloas.minimal.ssz.go @@ -51,9 +51,6 @@ func (c *AttestationGloas) MarshalSSZTo(dst []byte) ([]byte, error) { dst = append(dst, []byte(c.CommitteeBits)...) // Field 0: AggregationBits - if len(c.AggregationBits) > 8192 { - return nil, ssz.ErrListTooBig - } dst = append(dst, c.AggregationBits...) return dst, err } @@ -79,7 +76,7 @@ func (c *AttestationGloas) UnmarshalSSZ(buf []byte) error { sszSlice0 := buf[sszVarOffset0:] // c.AggregationBits // Field 0: AggregationBits - if err = ssz.ValidateBitlist(sszSlice0, 8192); err != nil { + if err = ssz.ValidateProgressiveBitlist(sszSlice0); err != nil { return fmt.Errorf("AggregationBits: %w", err) } c.AggregationBits = append([]byte{}, go_bitfield.Bitlist(sszSlice0)...) @@ -101,8 +98,18 @@ func (c *AttestationGloas) UnmarshalSSZ(buf []byte) error { } func (c *AttestationGloas) HashTreeRoot() ([32]byte, error) { + return c.ProgressiveHashTreeRoot() +} + +func (c *AttestationGloas) HashTreeRootWith(hh *ssz.Hasher) error { + return c.ProgressiveHashTreeRootWith(hh) +} + +var activeFieldsAttestationGloas = []byte{0b00001111} + +func (c *AttestationGloas) ProgressiveHashTreeRoot() ([32]byte, error) { hh := ssz.DefaultHasherPool.Get() - if err := c.HashTreeRootWith(hh); err != nil { + if err := c.ProgressiveHashTreeRootWith(hh); err != nil { ssz.DefaultHasherPool.Put(hh) return [32]byte{}, err } @@ -111,13 +118,13 @@ func (c *AttestationGloas) HashTreeRoot() ([32]byte, error) { return root, err } -func (c *AttestationGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { +func (c *AttestationGloas) ProgressiveHashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() // Field 0: AggregationBits if len(c.AggregationBits) == 0 { return ssz.ErrEmptyBitlist } - hh.PutBitlist(c.AggregationBits, 8192) + hh.PutProgressiveBitlist(c.AggregationBits) // Field 1: Data if err := c.Data.HashTreeRootWith(hh); err != nil { return fmt.Errorf("Data: %w", err) @@ -132,7 +139,7 @@ func (c *AttestationGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { return ssz.ErrBytesLength } hh.PutBytes([]byte(c.CommitteeBits)) - hh.Merkleize(indx) + hh.MerkleizeProgressiveWithActiveFields(indx, activeFieldsAttestationGloas) return nil } @@ -559,9 +566,6 @@ func (c *BeaconBlockBodyGloas) MarshalSSZTo(dst []byte) ([]byte, error) { offset += c.ParentExecutionRequests.SizeSSZ() // Field 3: ProposerSlashings - if len(c.ProposerSlashings) > 16 { - return nil, ssz.ErrListTooBig - } for _, o := range c.ProposerSlashings { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("ProposerSlashings: %w", err) @@ -569,9 +573,6 @@ func (c *BeaconBlockBodyGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 4: AttesterSlashings - if len(c.AttesterSlashings) > 1 { - return nil, ssz.ErrListTooBig - } { offset = 4 * len(c.AttesterSlashings) for _, o := range c.AttesterSlashings { @@ -586,9 +587,6 @@ func (c *BeaconBlockBodyGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 5: Attestations - if len(c.Attestations) > 8 { - return nil, ssz.ErrListTooBig - } { offset = 4 * len(c.Attestations) for _, o := range c.Attestations { @@ -603,9 +601,6 @@ func (c *BeaconBlockBodyGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 6: Deposits - if len(c.Deposits) > 16 { - return nil, ssz.ErrListTooBig - } for _, o := range c.Deposits { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("Deposits: %w", err) @@ -613,9 +608,6 @@ func (c *BeaconBlockBodyGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 7: VoluntaryExits - if len(c.VoluntaryExits) > 16 { - return nil, ssz.ErrListTooBig - } for _, o := range c.VoluntaryExits { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("VoluntaryExits: %w", err) @@ -623,9 +615,6 @@ func (c *BeaconBlockBodyGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 9: BlsToExecutionChanges - if len(c.BlsToExecutionChanges) > 16 { - return nil, ssz.ErrListTooBig - } for _, o := range c.BlsToExecutionChanges { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("BlsToExecutionChanges: %w", err) @@ -638,9 +627,6 @@ func (c *BeaconBlockBodyGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 11: PayloadAttestations - if len(c.PayloadAttestations) > 4 { - return nil, ssz.ErrListTooBig - } for _, o := range c.PayloadAttestations { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("PayloadAttestations: %w", err) @@ -735,9 +721,6 @@ func (c *BeaconBlockBodyGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.ProposerSlashings length is %d, which is not a multiple of 416: %w", len(sszSlice3), ssz.ErrIncorrectListSize) } numElem := len(sszSlice3) / 416 - if numElem > 16 { - return fmt.Errorf("ssz-max exceeded: c.ProposerSlashings has %d elements, ssz-max is 16: %w", numElem, ssz.ErrListTooBig) - } c.ProposerSlashings = make([]*ProposerSlashing, numElem) for i := 0; i < numElem; i++ { var tmp *ProposerSlashing @@ -763,9 +746,6 @@ func (c *BeaconBlockBodyGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned list bytes: when decoding c.AttesterSlashings, end-of-list offset is %d, which is not a multiple of 4 (offset size)", startOffset) } listLen := startOffset / 4 - if listLen > 1 { - return fmt.Errorf("ssz-max exceeded: c.AttesterSlashings has %d elements, ssz-max is 1: %w", listLen, ssz.ErrListTooBig) - } totalVarBytes := uint64(len(sszSlice4)) if totalVarBytes < startOffset { return fmt.Errorf("list bytes too short to contain an offset when decoding c.AttesterSlashings") @@ -813,9 +793,6 @@ func (c *BeaconBlockBodyGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned list bytes: when decoding c.Attestations, end-of-list offset is %d, which is not a multiple of 4 (offset size)", startOffset) } listLen := startOffset / 4 - if listLen > 8 { - return fmt.Errorf("ssz-max exceeded: c.Attestations has %d elements, ssz-max is 8: %w", listLen, ssz.ErrListTooBig) - } totalVarBytes := uint64(len(sszSlice5)) if totalVarBytes < startOffset { return fmt.Errorf("list bytes too short to contain an offset when decoding c.Attestations") @@ -856,9 +833,6 @@ func (c *BeaconBlockBodyGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.Deposits length is %d, which is not a multiple of 1240: %w", len(sszSlice6), ssz.ErrIncorrectListSize) } numElem := len(sszSlice6) / 1240 - if numElem > 16 { - return fmt.Errorf("ssz-max exceeded: c.Deposits has %d elements, ssz-max is 16: %w", numElem, ssz.ErrListTooBig) - } c.Deposits = make([]*Deposit, numElem) for i := 0; i < numElem; i++ { var tmp *Deposit @@ -877,9 +851,6 @@ func (c *BeaconBlockBodyGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.VoluntaryExits length is %d, which is not a multiple of 112: %w", len(sszSlice7), ssz.ErrIncorrectListSize) } numElem := len(sszSlice7) / 112 - if numElem > 16 { - return fmt.Errorf("ssz-max exceeded: c.VoluntaryExits has %d elements, ssz-max is 16: %w", numElem, ssz.ErrListTooBig) - } c.VoluntaryExits = make([]*SignedVoluntaryExit, numElem) for i := 0; i < numElem; i++ { var tmp *SignedVoluntaryExit @@ -904,9 +875,6 @@ func (c *BeaconBlockBodyGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.BlsToExecutionChanges length is %d, which is not a multiple of 172: %w", len(sszSlice9), ssz.ErrIncorrectListSize) } numElem := len(sszSlice9) / 172 - if numElem > 16 { - return fmt.Errorf("ssz-max exceeded: c.BlsToExecutionChanges has %d elements, ssz-max is 16: %w", numElem, ssz.ErrListTooBig) - } c.BlsToExecutionChanges = make([]*SignedBLSToExecutionChange, numElem) for i := 0; i < numElem; i++ { var tmp *SignedBLSToExecutionChange @@ -931,9 +899,6 @@ func (c *BeaconBlockBodyGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.PayloadAttestations length is %d, which is not a multiple of 140: %w", len(sszSlice11), ssz.ErrIncorrectListSize) } numElem := len(sszSlice11) / 140 - if numElem > 4 { - return fmt.Errorf("ssz-max exceeded: c.PayloadAttestations has %d elements, ssz-max is 4: %w", numElem, ssz.ErrListTooBig) - } c.PayloadAttestations = make([]*PayloadAttestation, numElem) for i := 0; i < numElem; i++ { var tmp *PayloadAttestation @@ -955,8 +920,18 @@ func (c *BeaconBlockBodyGloas) UnmarshalSSZ(buf []byte) error { } func (c *BeaconBlockBodyGloas) HashTreeRoot() ([32]byte, error) { + return c.ProgressiveHashTreeRoot() +} + +func (c *BeaconBlockBodyGloas) HashTreeRootWith(hh *ssz.Hasher) error { + return c.ProgressiveHashTreeRootWith(hh) +} + +var activeFieldsBeaconBlockBodyGloas = []byte{0b11111111, 0b00011111} + +func (c *BeaconBlockBodyGloas) ProgressiveHashTreeRoot() ([32]byte, error) { hh := ssz.DefaultHasherPool.Get() - if err := c.HashTreeRootWith(hh); err != nil { + if err := c.ProgressiveHashTreeRootWith(hh); err != nil { ssz.DefaultHasherPool.Put(hh) return [32]byte{}, err } @@ -965,7 +940,7 @@ func (c *BeaconBlockBodyGloas) HashTreeRoot() ([32]byte, error) { return root, err } -func (c *BeaconBlockBodyGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { +func (c *BeaconBlockBodyGloas) ProgressiveHashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() // Field 0: RandaoReveal if len(c.RandaoReveal) != 96 { @@ -983,68 +958,53 @@ func (c *BeaconBlockBodyGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { hh.PutBytes(c.Graffiti) // Field 3: ProposerSlashings { - if len(c.ProposerSlashings) > 16 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.ProposerSlashings { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("ProposerSlashings: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.ProposerSlashings)), 16) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.ProposerSlashings))) } // Field 4: AttesterSlashings { - if len(c.AttesterSlashings) > 1 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.AttesterSlashings { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("AttesterSlashings: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.AttesterSlashings)), 1) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.AttesterSlashings))) } // Field 5: Attestations { - if len(c.Attestations) > 8 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.Attestations { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("Attestations: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.Attestations)), 8) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.Attestations))) } // Field 6: Deposits { - if len(c.Deposits) > 16 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.Deposits { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("Deposits: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.Deposits)), 16) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.Deposits))) } // Field 7: VoluntaryExits { - if len(c.VoluntaryExits) > 16 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.VoluntaryExits { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("VoluntaryExits: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.VoluntaryExits)), 16) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.VoluntaryExits))) } // Field 8: SyncAggregate if err := c.SyncAggregate.HashTreeRootWith(hh); err != nil { @@ -1052,16 +1012,13 @@ func (c *BeaconBlockBodyGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { } // Field 9: BlsToExecutionChanges { - if len(c.BlsToExecutionChanges) > 16 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.BlsToExecutionChanges { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("BlsToExecutionChanges: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.BlsToExecutionChanges)), 16) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.BlsToExecutionChanges))) } // Field 10: SignedExecutionPayloadBid if err := c.SignedExecutionPayloadBid.HashTreeRootWith(hh); err != nil { @@ -1069,22 +1026,19 @@ func (c *BeaconBlockBodyGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { } // Field 11: PayloadAttestations { - if len(c.PayloadAttestations) > 4 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.PayloadAttestations { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("PayloadAttestations: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.PayloadAttestations)), 4) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.PayloadAttestations))) } // Field 12: ParentExecutionRequests if err := c.ParentExecutionRequests.HashTreeRootWith(hh); err != nil { return fmt.Errorf("ParentExecutionRequests: %w", err) } - hh.Merkleize(indx) + hh.MerkleizeProgressiveWithActiveFields(indx, activeFieldsBeaconBlockBodyGloas) return nil } @@ -1774,9 +1728,6 @@ func (c *BeaconStateGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 11: Validators - if len(c.Validators) > 1099511627776 { - return nil, ssz.ErrListTooBig - } for _, o := range c.Validators { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("Validators: %w", err) @@ -1784,29 +1735,17 @@ func (c *BeaconStateGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 12: Balances - if len(c.Balances) > 1099511627776 { - return nil, ssz.ErrListTooBig - } for _, o := range c.Balances { dst = binary.LittleEndian.AppendUint64(dst, o) } // Field 15: PreviousEpochParticipation - if len(c.PreviousEpochParticipation) > 1099511627776 { - return nil, ssz.ErrListTooBig - } dst = append(dst, c.PreviousEpochParticipation...) // Field 16: CurrentEpochParticipation - if len(c.CurrentEpochParticipation) > 1099511627776 { - return nil, ssz.ErrListTooBig - } dst = append(dst, c.CurrentEpochParticipation...) // Field 21: InactivityScores - if len(c.InactivityScores) > 1099511627776 { - return nil, ssz.ErrListTooBig - } for _, o := range c.InactivityScores { dst = binary.LittleEndian.AppendUint64(dst, o) } @@ -1822,9 +1761,6 @@ func (c *BeaconStateGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 34: PendingDeposits - if len(c.PendingDeposits) > 134217728 { - return nil, ssz.ErrListTooBig - } for _, o := range c.PendingDeposits { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("PendingDeposits: %w", err) @@ -1832,9 +1768,6 @@ func (c *BeaconStateGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 35: PendingPartialWithdrawals - if len(c.PendingPartialWithdrawals) > 64 { - return nil, ssz.ErrListTooBig - } for _, o := range c.PendingPartialWithdrawals { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("PendingPartialWithdrawals: %w", err) @@ -1842,9 +1775,6 @@ func (c *BeaconStateGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 36: PendingConsolidations - if len(c.PendingConsolidations) > 64 { - return nil, ssz.ErrListTooBig - } for _, o := range c.PendingConsolidations { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("PendingConsolidations: %w", err) @@ -1852,9 +1782,6 @@ func (c *BeaconStateGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 38: Builders - if len(c.Builders) > 1099511627776 { - return nil, ssz.ErrListTooBig - } for _, o := range c.Builders { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("Builders: %w", err) @@ -1862,9 +1789,6 @@ func (c *BeaconStateGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 42: BuilderPendingWithdrawals - if len(c.BuilderPendingWithdrawals) > 1048576 { - return nil, ssz.ErrListTooBig - } for _, o := range c.BuilderPendingWithdrawals { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("BuilderPendingWithdrawals: %w", err) @@ -1877,9 +1801,6 @@ func (c *BeaconStateGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 44: PayloadExpectedWithdrawals - if len(c.PayloadExpectedWithdrawals) > 4 { - return nil, ssz.ErrListTooBig - } for _, o := range c.PayloadExpectedWithdrawals { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("PayloadExpectedWithdrawals: %w", err) @@ -2112,9 +2033,6 @@ func (c *BeaconStateGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.Validators length is %d, which is not a multiple of 121: %w", len(sszSlice11), ssz.ErrIncorrectListSize) } numElem := len(sszSlice11) / 121 - if numElem > 1099511627776 { - return fmt.Errorf("ssz-max exceeded: c.Validators has %d elements, ssz-max is 1099511627776: %w", numElem, ssz.ErrListTooBig) - } c.Validators = make([]*Validator, numElem) for i := 0; i < numElem; i++ { var tmp *Validator @@ -2133,9 +2051,6 @@ func (c *BeaconStateGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.Balances length is %d, which is not a multiple of 8: %w", len(sszSlice12), ssz.ErrIncorrectListSize) } numElem := len(sszSlice12) / 8 - if numElem > 1099511627776 { - return fmt.Errorf("ssz-max exceeded: c.Balances has %d elements, ssz-max is 1099511627776: %w", numElem, ssz.ErrListTooBig) - } c.Balances = make([]uint64, numElem) for i := 0; i < numElem; i++ { var tmp uint64 @@ -2205,9 +2120,6 @@ func (c *BeaconStateGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.InactivityScores length is %d, which is not a multiple of 8: %w", len(sszSlice21), ssz.ErrIncorrectListSize) } numElem := len(sszSlice21) / 8 - if numElem > 1099511627776 { - return fmt.Errorf("ssz-max exceeded: c.InactivityScores has %d elements, ssz-max is 1099511627776: %w", numElem, ssz.ErrListTooBig) - } c.InactivityScores = make([]uint64, numElem) for i := 0; i < numElem; i++ { var tmp uint64 @@ -2297,9 +2209,6 @@ func (c *BeaconStateGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.PendingDeposits length is %d, which is not a multiple of 192: %w", len(sszSlice34), ssz.ErrIncorrectListSize) } numElem := len(sszSlice34) / 192 - if numElem > 134217728 { - return fmt.Errorf("ssz-max exceeded: c.PendingDeposits has %d elements, ssz-max is 134217728: %w", numElem, ssz.ErrListTooBig) - } c.PendingDeposits = make([]*PendingDeposit, numElem) for i := 0; i < numElem; i++ { var tmp *PendingDeposit @@ -2318,9 +2227,6 @@ func (c *BeaconStateGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.PendingPartialWithdrawals length is %d, which is not a multiple of 24: %w", len(sszSlice35), ssz.ErrIncorrectListSize) } numElem := len(sszSlice35) / 24 - if numElem > 64 { - return fmt.Errorf("ssz-max exceeded: c.PendingPartialWithdrawals has %d elements, ssz-max is 64: %w", numElem, ssz.ErrListTooBig) - } c.PendingPartialWithdrawals = make([]*PendingPartialWithdrawal, numElem) for i := 0; i < numElem; i++ { var tmp *PendingPartialWithdrawal @@ -2339,9 +2245,6 @@ func (c *BeaconStateGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.PendingConsolidations length is %d, which is not a multiple of 16: %w", len(sszSlice36), ssz.ErrIncorrectListSize) } numElem := len(sszSlice36) / 16 - if numElem > 64 { - return fmt.Errorf("ssz-max exceeded: c.PendingConsolidations has %d elements, ssz-max is 64: %w", numElem, ssz.ErrListTooBig) - } c.PendingConsolidations = make([]*PendingConsolidation, numElem) for i := 0; i < numElem; i++ { var tmp *PendingConsolidation @@ -2374,9 +2277,6 @@ func (c *BeaconStateGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.Builders length is %d, which is not a multiple of 93: %w", len(sszSlice38), ssz.ErrIncorrectListSize) } numElem := len(sszSlice38) / 93 - if numElem > 1099511627776 { - return fmt.Errorf("ssz-max exceeded: c.Builders has %d elements, ssz-max is 1099511627776: %w", numElem, ssz.ErrListTooBig) - } c.Builders = make([]*Builder, numElem) for i := 0; i < numElem; i++ { var tmp *Builder @@ -2418,9 +2318,6 @@ func (c *BeaconStateGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.BuilderPendingWithdrawals length is %d, which is not a multiple of 36: %w", len(sszSlice42), ssz.ErrIncorrectListSize) } numElem := len(sszSlice42) / 36 - if numElem > 1048576 { - return fmt.Errorf("ssz-max exceeded: c.BuilderPendingWithdrawals has %d elements, ssz-max is 1048576: %w", numElem, ssz.ErrListTooBig) - } c.BuilderPendingWithdrawals = make([]*BuilderPendingWithdrawal, numElem) for i := 0; i < numElem; i++ { var tmp *BuilderPendingWithdrawal @@ -2445,9 +2342,6 @@ func (c *BeaconStateGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.PayloadExpectedWithdrawals length is %d, which is not a multiple of 44: %w", len(sszSlice44), ssz.ErrIncorrectListSize) } numElem := len(sszSlice44) / 44 - if numElem > 4 { - return fmt.Errorf("ssz-max exceeded: c.PayloadExpectedWithdrawals has %d elements, ssz-max is 4: %w", numElem, ssz.ErrListTooBig) - } c.PayloadExpectedWithdrawals = make([]*v1.Withdrawal, numElem) for i := 0; i < numElem; i++ { var tmp *v1.Withdrawal @@ -2477,8 +2371,18 @@ func (c *BeaconStateGloas) UnmarshalSSZ(buf []byte) error { } func (c *BeaconStateGloas) HashTreeRoot() ([32]byte, error) { + return c.ProgressiveHashTreeRoot() +} + +func (c *BeaconStateGloas) HashTreeRootWith(hh *ssz.Hasher) error { + return c.ProgressiveHashTreeRootWith(hh) +} + +var activeFieldsBeaconStateGloas = []byte{0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b00111111} + +func (c *BeaconStateGloas) ProgressiveHashTreeRoot() ([32]byte, error) { hh := ssz.DefaultHasherPool.Get() - if err := c.HashTreeRootWith(hh); err != nil { + if err := c.ProgressiveHashTreeRootWith(hh); err != nil { ssz.DefaultHasherPool.Put(hh) return [32]byte{}, err } @@ -2487,7 +2391,7 @@ func (c *BeaconStateGloas) HashTreeRoot() ([32]byte, error) { return root, err } -func (c *BeaconStateGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { +func (c *BeaconStateGloas) ProgressiveHashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() // Field 0: GenesisTime hh.PutUint64(c.GenesisTime) @@ -2571,29 +2475,22 @@ func (c *BeaconStateGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { hh.PutUint64(c.Eth1DepositIndex) // Field 11: Validators { - if len(c.Validators) > 1099511627776 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.Validators { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("Validators: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.Validators)), 1099511627776) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.Validators))) } // Field 12: Balances { - if len(c.Balances) > 1099511627776 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.Balances { hh.AppendUint64(o) } hh.FillUpTo32() - numItems := uint64(len(c.Balances)) - hh.MerkleizeWithMixin(subIndx, numItems, ssz.CalculateLimit(1099511627776, numItems, 8)) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.Balances))) } // Field 13: RandaoMixes { @@ -2621,29 +2518,17 @@ func (c *BeaconStateGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { hh.Merkleize(subIndx) } // Field 15: PreviousEpochParticipation - { - if len(c.PreviousEpochParticipation) > 1099511627776 { - return ssz.ErrBytesLength - } subIndx := hh.Index() hh.AppendBytes32(c.PreviousEpochParticipation) - numItems := uint64(len(c.PreviousEpochParticipation)) - hh.MerkleizeWithMixin(subIndx, numItems, (1099511627776*1+31)/32) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.PreviousEpochParticipation))) } - // Field 16: CurrentEpochParticipation - { - if len(c.CurrentEpochParticipation) > 1099511627776 { - return ssz.ErrBytesLength - } subIndx := hh.Index() hh.AppendBytes32(c.CurrentEpochParticipation) - numItems := uint64(len(c.CurrentEpochParticipation)) - hh.MerkleizeWithMixin(subIndx, numItems, (1099511627776*1+31)/32) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.CurrentEpochParticipation))) } - // Field 17: JustificationBits if len([]byte(c.JustificationBits)) != 1 { return ssz.ErrBytesLength @@ -2663,16 +2548,12 @@ func (c *BeaconStateGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { } // Field 21: InactivityScores { - if len(c.InactivityScores) > 1099511627776 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.InactivityScores { hh.AppendUint64(o) } hh.FillUpTo32() - numItems := uint64(len(c.InactivityScores)) - hh.MerkleizeWithMixin(subIndx, numItems, ssz.CalculateLimit(1099511627776, numItems, 8)) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.InactivityScores))) } // Field 22: CurrentSyncCommittee if err := c.CurrentSyncCommittee.HashTreeRootWith(hh); err != nil { @@ -2730,42 +2611,33 @@ func (c *BeaconStateGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { } // Field 34: PendingDeposits { - if len(c.PendingDeposits) > 134217728 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.PendingDeposits { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("PendingDeposits: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.PendingDeposits)), 134217728) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.PendingDeposits))) } // Field 35: PendingPartialWithdrawals { - if len(c.PendingPartialWithdrawals) > 64 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.PendingPartialWithdrawals { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("PendingPartialWithdrawals: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.PendingPartialWithdrawals)), 64) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.PendingPartialWithdrawals))) } // Field 36: PendingConsolidations { - if len(c.PendingConsolidations) > 64 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.PendingConsolidations { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("PendingConsolidations: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.PendingConsolidations)), 64) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.PendingConsolidations))) } // Field 37: ProposerLookahead { @@ -2780,16 +2652,13 @@ func (c *BeaconStateGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { } // Field 38: Builders { - if len(c.Builders) > 1099511627776 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.Builders { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("Builders: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.Builders)), 1099511627776) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.Builders))) } // Field 39: NextWithdrawalBuilderIndex if err := c.NextWithdrawalBuilderIndex.HashTreeRootWith(hh); err != nil { @@ -2815,16 +2684,13 @@ func (c *BeaconStateGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { } // Field 42: BuilderPendingWithdrawals { - if len(c.BuilderPendingWithdrawals) > 1048576 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.BuilderPendingWithdrawals { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("BuilderPendingWithdrawals: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.BuilderPendingWithdrawals)), 1048576) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.BuilderPendingWithdrawals))) } // Field 43: LatestExecutionPayloadBid if err := c.LatestExecutionPayloadBid.HashTreeRootWith(hh); err != nil { @@ -2832,16 +2698,13 @@ func (c *BeaconStateGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { } // Field 44: PayloadExpectedWithdrawals { - if len(c.PayloadExpectedWithdrawals) > 4 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.PayloadExpectedWithdrawals { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("PayloadExpectedWithdrawals: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.PayloadExpectedWithdrawals)), 4) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.PayloadExpectedWithdrawals))) } // Field 45: PtcWindow { @@ -2856,7 +2719,7 @@ func (c *BeaconStateGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { } hh.Merkleize(subIndx) } - hh.Merkleize(indx) + hh.MerkleizeProgressiveWithActiveFields(indx, activeFieldsBeaconStateGloas) return nil } @@ -3547,9 +3410,6 @@ func (c *DataColumnSidecarGloas) MarshalSSZTo(dst []byte) ([]byte, error) { dst = append(dst, c.BeaconBlockRoot...) // Field 1: Column - if len(c.Column) > 4096 { - return nil, ssz.ErrListTooBig - } for _, o := range c.Column { if len(o) != 2048 { return nil, ssz.ErrBytesLength @@ -3558,9 +3418,6 @@ func (c *DataColumnSidecarGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 2: KzgProofs - if len(c.KzgProofs) > 4096 { - return nil, ssz.ErrListTooBig - } for _, o := range c.KzgProofs { if len(o) != 48 { return nil, ssz.ErrBytesLength @@ -3604,9 +3461,6 @@ func (c *DataColumnSidecarGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.Column length is %d, which is not a multiple of 2048: %w", len(sszSlice1), ssz.ErrIncorrectListSize) } numElem := len(sszSlice1) / 2048 - if numElem > 4096 { - return fmt.Errorf("ssz-max exceeded: c.Column has %d elements, ssz-max is 4096: %w", numElem, ssz.ErrListTooBig) - } c.Column = make([][]byte, numElem) for i := 0; i < numElem; i++ { var tmp []byte @@ -3624,9 +3478,6 @@ func (c *DataColumnSidecarGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.KzgProofs length is %d, which is not a multiple of 48: %w", len(sszSlice2), ssz.ErrIncorrectListSize) } numElem := len(sszSlice2) / 48 - if numElem > 4096 { - return fmt.Errorf("ssz-max exceeded: c.KzgProofs has %d elements, ssz-max is 4096: %w", numElem, ssz.ErrListTooBig) - } c.KzgProofs = make([][]byte, numElem) for i := 0; i < numElem; i++ { var tmp []byte @@ -3666,9 +3517,6 @@ func (c *DataColumnSidecarGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { hh.PutUint64(c.Index) // Field 1: Column { - if len(c.Column) > 4096 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.Column { if len(o) != 2048 { @@ -3676,13 +3524,10 @@ func (c *DataColumnSidecarGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { } hh.PutBytes(o) } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.Column)), 4096) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.Column))) } // Field 2: KzgProofs { - if len(c.KzgProofs) > 4096 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.KzgProofs { if len(o) != 48 { @@ -3690,7 +3535,7 @@ func (c *DataColumnSidecarGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { } hh.PutBytes(o) } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.KzgProofs)), 4096) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.KzgProofs))) } // Field 3: Slot if err := c.Slot.HashTreeRootWith(hh); err != nil { @@ -3784,9 +3629,6 @@ func (c *ExecutionPayloadBid) MarshalSSZTo(dst []byte) ([]byte, error) { dst = append(dst, c.ExecutionRequestsRoot...) // Field 10: BlobKzgCommitments - if len(c.BlobKzgCommitments) > 4096 { - return nil, ssz.ErrListTooBig - } for _, o := range c.BlobKzgCommitments { if len(o) != 48 { return nil, ssz.ErrBytesLength @@ -3873,9 +3715,6 @@ func (c *ExecutionPayloadBid) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.BlobKzgCommitments length is %d, which is not a multiple of 48: %w", len(sszSlice10), ssz.ErrIncorrectListSize) } numElem := len(sszSlice10) / 48 - if numElem > 4096 { - return fmt.Errorf("ssz-max exceeded: c.BlobKzgCommitments has %d elements, ssz-max is 4096: %w", numElem, ssz.ErrListTooBig) - } c.BlobKzgCommitments = make([][]byte, numElem) for i := 0; i < numElem; i++ { var tmp []byte @@ -3894,8 +3733,18 @@ func (c *ExecutionPayloadBid) UnmarshalSSZ(buf []byte) error { } func (c *ExecutionPayloadBid) HashTreeRoot() ([32]byte, error) { + return c.ProgressiveHashTreeRoot() +} + +func (c *ExecutionPayloadBid) HashTreeRootWith(hh *ssz.Hasher) error { + return c.ProgressiveHashTreeRootWith(hh) +} + +var activeFieldsExecutionPayloadBid = []byte{0b11111111, 0b00001111} + +func (c *ExecutionPayloadBid) ProgressiveHashTreeRoot() ([32]byte, error) { hh := ssz.DefaultHasherPool.Get() - if err := c.HashTreeRootWith(hh); err != nil { + if err := c.ProgressiveHashTreeRootWith(hh); err != nil { ssz.DefaultHasherPool.Put(hh) return [32]byte{}, err } @@ -3904,7 +3753,7 @@ func (c *ExecutionPayloadBid) HashTreeRoot() ([32]byte, error) { return root, err } -func (c *ExecutionPayloadBid) HashTreeRootWith(hh *ssz.Hasher) (err error) { +func (c *ExecutionPayloadBid) ProgressiveHashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() // Field 0: ParentBlockHash if len(c.ParentBlockHash) != 32 { @@ -3951,9 +3800,6 @@ func (c *ExecutionPayloadBid) HashTreeRootWith(hh *ssz.Hasher) (err error) { } // Field 10: BlobKzgCommitments { - if len(c.BlobKzgCommitments) > 4096 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.BlobKzgCommitments { if len(o) != 48 { @@ -3961,14 +3807,14 @@ func (c *ExecutionPayloadBid) HashTreeRootWith(hh *ssz.Hasher) (err error) { } hh.PutBytes(o) } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.BlobKzgCommitments)), 4096) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.BlobKzgCommitments))) } // Field 11: ExecutionRequestsRoot if len(c.ExecutionRequestsRoot) != 32 { return ssz.ErrBytesLength } hh.PutBytes(c.ExecutionRequestsRoot) - hh.Merkleize(indx) + hh.MerkleizeProgressiveWithActiveFields(indx, activeFieldsExecutionPayloadBid) return nil } @@ -4090,8 +3936,18 @@ func (c *ExecutionPayloadEnvelope) UnmarshalSSZ(buf []byte) error { } func (c *ExecutionPayloadEnvelope) HashTreeRoot() ([32]byte, error) { + return c.ProgressiveHashTreeRoot() +} + +func (c *ExecutionPayloadEnvelope) HashTreeRootWith(hh *ssz.Hasher) error { + return c.ProgressiveHashTreeRootWith(hh) +} + +var activeFieldsExecutionPayloadEnvelope = []byte{0b00011111} + +func (c *ExecutionPayloadEnvelope) ProgressiveHashTreeRoot() ([32]byte, error) { hh := ssz.DefaultHasherPool.Get() - if err := c.HashTreeRootWith(hh); err != nil { + if err := c.ProgressiveHashTreeRootWith(hh); err != nil { ssz.DefaultHasherPool.Put(hh) return [32]byte{}, err } @@ -4100,7 +3956,7 @@ func (c *ExecutionPayloadEnvelope) HashTreeRoot() ([32]byte, error) { return root, err } -func (c *ExecutionPayloadEnvelope) HashTreeRootWith(hh *ssz.Hasher) (err error) { +func (c *ExecutionPayloadEnvelope) ProgressiveHashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() // Field 0: Payload if err := c.Payload.HashTreeRootWith(hh); err != nil { @@ -4124,7 +3980,7 @@ func (c *ExecutionPayloadEnvelope) HashTreeRootWith(hh *ssz.Hasher) (err error) return ssz.ErrBytesLength } hh.PutBytes(c.ParentBeaconBlockRoot) - hh.Merkleize(indx) + hh.MerkleizeProgressiveWithActiveFields(indx, activeFieldsExecutionPayloadEnvelope) return nil } @@ -4162,9 +4018,6 @@ func (c *IndexedAttestationGloas) MarshalSSZTo(dst []byte) ([]byte, error) { dst = append(dst, c.Signature...) // Field 0: AttestingIndices - if len(c.AttestingIndices) > 8192 { - return nil, ssz.ErrListTooBig - } for _, o := range c.AttestingIndices { dst = binary.LittleEndian.AppendUint64(dst, o) } @@ -4196,9 +4049,6 @@ func (c *IndexedAttestationGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.AttestingIndices length is %d, which is not a multiple of 8: %w", len(sszSlice0), ssz.ErrIncorrectListSize) } numElem := len(sszSlice0) / 8 - if numElem > 8192 { - return fmt.Errorf("ssz-max exceeded: c.AttestingIndices has %d elements, ssz-max is 8192: %w", numElem, ssz.ErrListTooBig) - } c.AttestingIndices = make([]uint64, numElem) for i := 0; i < numElem; i++ { var tmp uint64 @@ -4222,8 +4072,18 @@ func (c *IndexedAttestationGloas) UnmarshalSSZ(buf []byte) error { } func (c *IndexedAttestationGloas) HashTreeRoot() ([32]byte, error) { + return c.ProgressiveHashTreeRoot() +} + +func (c *IndexedAttestationGloas) HashTreeRootWith(hh *ssz.Hasher) error { + return c.ProgressiveHashTreeRootWith(hh) +} + +var activeFieldsIndexedAttestationGloas = []byte{0b00000111} + +func (c *IndexedAttestationGloas) ProgressiveHashTreeRoot() ([32]byte, error) { hh := ssz.DefaultHasherPool.Get() - if err := c.HashTreeRootWith(hh); err != nil { + if err := c.ProgressiveHashTreeRootWith(hh); err != nil { ssz.DefaultHasherPool.Put(hh) return [32]byte{}, err } @@ -4232,20 +4092,16 @@ func (c *IndexedAttestationGloas) HashTreeRoot() ([32]byte, error) { return root, err } -func (c *IndexedAttestationGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { +func (c *IndexedAttestationGloas) ProgressiveHashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() // Field 0: AttestingIndices { - if len(c.AttestingIndices) > 8192 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.AttestingIndices { hh.AppendUint64(o) } hh.FillUpTo32() - numItems := uint64(len(c.AttestingIndices)) - hh.MerkleizeWithMixin(subIndx, numItems, ssz.CalculateLimit(8192, numItems, 8)) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.AttestingIndices))) } // Field 1: Data if err := c.Data.HashTreeRootWith(hh); err != nil { @@ -4256,7 +4112,7 @@ func (c *IndexedAttestationGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { return ssz.ErrBytesLength } hh.PutBytes(c.Signature) - hh.Merkleize(indx) + hh.MerkleizeProgressiveWithActiveFields(indx, activeFieldsIndexedAttestationGloas) return nil } @@ -4325,8 +4181,18 @@ func (c *PayloadAttestation) UnmarshalSSZ(buf []byte) error { } func (c *PayloadAttestation) HashTreeRoot() ([32]byte, error) { + return c.ProgressiveHashTreeRoot() +} + +func (c *PayloadAttestation) HashTreeRootWith(hh *ssz.Hasher) error { + return c.ProgressiveHashTreeRootWith(hh) +} + +var activeFieldsPayloadAttestation = []byte{0b00000111} + +func (c *PayloadAttestation) ProgressiveHashTreeRoot() ([32]byte, error) { hh := ssz.DefaultHasherPool.Get() - if err := c.HashTreeRootWith(hh); err != nil { + if err := c.ProgressiveHashTreeRootWith(hh); err != nil { ssz.DefaultHasherPool.Put(hh) return [32]byte{}, err } @@ -4335,7 +4201,7 @@ func (c *PayloadAttestation) HashTreeRoot() ([32]byte, error) { return root, err } -func (c *PayloadAttestation) HashTreeRootWith(hh *ssz.Hasher) (err error) { +func (c *PayloadAttestation) ProgressiveHashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() // Field 0: AggregationBits if len([]byte(c.AggregationBits)) != 2 { @@ -4351,7 +4217,7 @@ func (c *PayloadAttestation) HashTreeRootWith(hh *ssz.Hasher) (err error) { return ssz.ErrBytesLength } hh.PutBytes(c.Signature) - hh.Merkleize(indx) + hh.MerkleizeProgressiveWithActiveFields(indx, activeFieldsPayloadAttestation) return nil } diff --git a/proto/prysm/v1alpha1/gloas.ssz.go b/proto/prysm/v1alpha1/gloas.ssz.go index 86f53777b99c..d8250648d20f 100644 --- a/proto/prysm/v1alpha1/gloas.ssz.go +++ b/proto/prysm/v1alpha1/gloas.ssz.go @@ -51,9 +51,6 @@ func (c *AttestationGloas) MarshalSSZTo(dst []byte) ([]byte, error) { dst = append(dst, []byte(c.CommitteeBits)...) // Field 0: AggregationBits - if len(c.AggregationBits) > 131072 { - return nil, ssz.ErrListTooBig - } dst = append(dst, c.AggregationBits...) return dst, err } @@ -79,7 +76,7 @@ func (c *AttestationGloas) UnmarshalSSZ(buf []byte) error { sszSlice0 := buf[sszVarOffset0:] // c.AggregationBits // Field 0: AggregationBits - if err = ssz.ValidateBitlist(sszSlice0, 131072); err != nil { + if err = ssz.ValidateProgressiveBitlist(sszSlice0); err != nil { return fmt.Errorf("AggregationBits: %w", err) } c.AggregationBits = append([]byte{}, go_bitfield.Bitlist(sszSlice0)...) @@ -101,8 +98,18 @@ func (c *AttestationGloas) UnmarshalSSZ(buf []byte) error { } func (c *AttestationGloas) HashTreeRoot() ([32]byte, error) { + return c.ProgressiveHashTreeRoot() +} + +func (c *AttestationGloas) HashTreeRootWith(hh *ssz.Hasher) error { + return c.ProgressiveHashTreeRootWith(hh) +} + +var activeFieldsAttestationGloas = []byte{0b00001111} + +func (c *AttestationGloas) ProgressiveHashTreeRoot() ([32]byte, error) { hh := ssz.DefaultHasherPool.Get() - if err := c.HashTreeRootWith(hh); err != nil { + if err := c.ProgressiveHashTreeRootWith(hh); err != nil { ssz.DefaultHasherPool.Put(hh) return [32]byte{}, err } @@ -111,13 +118,13 @@ func (c *AttestationGloas) HashTreeRoot() ([32]byte, error) { return root, err } -func (c *AttestationGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { +func (c *AttestationGloas) ProgressiveHashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() // Field 0: AggregationBits if len(c.AggregationBits) == 0 { return ssz.ErrEmptyBitlist } - hh.PutBitlist(c.AggregationBits, 131072) + hh.PutProgressiveBitlist(c.AggregationBits) // Field 1: Data if err := c.Data.HashTreeRootWith(hh); err != nil { return fmt.Errorf("Data: %w", err) @@ -132,7 +139,7 @@ func (c *AttestationGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { return ssz.ErrBytesLength } hh.PutBytes([]byte(c.CommitteeBits)) - hh.Merkleize(indx) + hh.MerkleizeProgressiveWithActiveFields(indx, activeFieldsAttestationGloas) return nil } @@ -559,9 +566,6 @@ func (c *BeaconBlockBodyGloas) MarshalSSZTo(dst []byte) ([]byte, error) { offset += c.ParentExecutionRequests.SizeSSZ() // Field 3: ProposerSlashings - if len(c.ProposerSlashings) > 16 { - return nil, ssz.ErrListTooBig - } for _, o := range c.ProposerSlashings { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("ProposerSlashings: %w", err) @@ -569,9 +573,6 @@ func (c *BeaconBlockBodyGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 4: AttesterSlashings - if len(c.AttesterSlashings) > 1 { - return nil, ssz.ErrListTooBig - } { offset = 4 * len(c.AttesterSlashings) for _, o := range c.AttesterSlashings { @@ -586,9 +587,6 @@ func (c *BeaconBlockBodyGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 5: Attestations - if len(c.Attestations) > 8 { - return nil, ssz.ErrListTooBig - } { offset = 4 * len(c.Attestations) for _, o := range c.Attestations { @@ -603,9 +601,6 @@ func (c *BeaconBlockBodyGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 6: Deposits - if len(c.Deposits) > 16 { - return nil, ssz.ErrListTooBig - } for _, o := range c.Deposits { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("Deposits: %w", err) @@ -613,9 +608,6 @@ func (c *BeaconBlockBodyGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 7: VoluntaryExits - if len(c.VoluntaryExits) > 16 { - return nil, ssz.ErrListTooBig - } for _, o := range c.VoluntaryExits { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("VoluntaryExits: %w", err) @@ -623,9 +615,6 @@ func (c *BeaconBlockBodyGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 9: BlsToExecutionChanges - if len(c.BlsToExecutionChanges) > 16 { - return nil, ssz.ErrListTooBig - } for _, o := range c.BlsToExecutionChanges { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("BlsToExecutionChanges: %w", err) @@ -638,9 +627,6 @@ func (c *BeaconBlockBodyGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 11: PayloadAttestations - if len(c.PayloadAttestations) > 4 { - return nil, ssz.ErrListTooBig - } for _, o := range c.PayloadAttestations { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("PayloadAttestations: %w", err) @@ -735,9 +721,6 @@ func (c *BeaconBlockBodyGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.ProposerSlashings length is %d, which is not a multiple of 416: %w", len(sszSlice3), ssz.ErrIncorrectListSize) } numElem := len(sszSlice3) / 416 - if numElem > 16 { - return fmt.Errorf("ssz-max exceeded: c.ProposerSlashings has %d elements, ssz-max is 16: %w", numElem, ssz.ErrListTooBig) - } c.ProposerSlashings = make([]*ProposerSlashing, numElem) for i := 0; i < numElem; i++ { var tmp *ProposerSlashing @@ -763,9 +746,6 @@ func (c *BeaconBlockBodyGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned list bytes: when decoding c.AttesterSlashings, end-of-list offset is %d, which is not a multiple of 4 (offset size)", startOffset) } listLen := startOffset / 4 - if listLen > 1 { - return fmt.Errorf("ssz-max exceeded: c.AttesterSlashings has %d elements, ssz-max is 1: %w", listLen, ssz.ErrListTooBig) - } totalVarBytes := uint64(len(sszSlice4)) if totalVarBytes < startOffset { return fmt.Errorf("list bytes too short to contain an offset when decoding c.AttesterSlashings") @@ -813,9 +793,6 @@ func (c *BeaconBlockBodyGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned list bytes: when decoding c.Attestations, end-of-list offset is %d, which is not a multiple of 4 (offset size)", startOffset) } listLen := startOffset / 4 - if listLen > 8 { - return fmt.Errorf("ssz-max exceeded: c.Attestations has %d elements, ssz-max is 8: %w", listLen, ssz.ErrListTooBig) - } totalVarBytes := uint64(len(sszSlice5)) if totalVarBytes < startOffset { return fmt.Errorf("list bytes too short to contain an offset when decoding c.Attestations") @@ -856,9 +833,6 @@ func (c *BeaconBlockBodyGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.Deposits length is %d, which is not a multiple of 1240: %w", len(sszSlice6), ssz.ErrIncorrectListSize) } numElem := len(sszSlice6) / 1240 - if numElem > 16 { - return fmt.Errorf("ssz-max exceeded: c.Deposits has %d elements, ssz-max is 16: %w", numElem, ssz.ErrListTooBig) - } c.Deposits = make([]*Deposit, numElem) for i := 0; i < numElem; i++ { var tmp *Deposit @@ -877,9 +851,6 @@ func (c *BeaconBlockBodyGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.VoluntaryExits length is %d, which is not a multiple of 112: %w", len(sszSlice7), ssz.ErrIncorrectListSize) } numElem := len(sszSlice7) / 112 - if numElem > 16 { - return fmt.Errorf("ssz-max exceeded: c.VoluntaryExits has %d elements, ssz-max is 16: %w", numElem, ssz.ErrListTooBig) - } c.VoluntaryExits = make([]*SignedVoluntaryExit, numElem) for i := 0; i < numElem; i++ { var tmp *SignedVoluntaryExit @@ -904,9 +875,6 @@ func (c *BeaconBlockBodyGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.BlsToExecutionChanges length is %d, which is not a multiple of 172: %w", len(sszSlice9), ssz.ErrIncorrectListSize) } numElem := len(sszSlice9) / 172 - if numElem > 16 { - return fmt.Errorf("ssz-max exceeded: c.BlsToExecutionChanges has %d elements, ssz-max is 16: %w", numElem, ssz.ErrListTooBig) - } c.BlsToExecutionChanges = make([]*SignedBLSToExecutionChange, numElem) for i := 0; i < numElem; i++ { var tmp *SignedBLSToExecutionChange @@ -931,9 +899,6 @@ func (c *BeaconBlockBodyGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.PayloadAttestations length is %d, which is not a multiple of 202: %w", len(sszSlice11), ssz.ErrIncorrectListSize) } numElem := len(sszSlice11) / 202 - if numElem > 4 { - return fmt.Errorf("ssz-max exceeded: c.PayloadAttestations has %d elements, ssz-max is 4: %w", numElem, ssz.ErrListTooBig) - } c.PayloadAttestations = make([]*PayloadAttestation, numElem) for i := 0; i < numElem; i++ { var tmp *PayloadAttestation @@ -955,8 +920,18 @@ func (c *BeaconBlockBodyGloas) UnmarshalSSZ(buf []byte) error { } func (c *BeaconBlockBodyGloas) HashTreeRoot() ([32]byte, error) { + return c.ProgressiveHashTreeRoot() +} + +func (c *BeaconBlockBodyGloas) HashTreeRootWith(hh *ssz.Hasher) error { + return c.ProgressiveHashTreeRootWith(hh) +} + +var activeFieldsBeaconBlockBodyGloas = []byte{0b11111111, 0b00011111} + +func (c *BeaconBlockBodyGloas) ProgressiveHashTreeRoot() ([32]byte, error) { hh := ssz.DefaultHasherPool.Get() - if err := c.HashTreeRootWith(hh); err != nil { + if err := c.ProgressiveHashTreeRootWith(hh); err != nil { ssz.DefaultHasherPool.Put(hh) return [32]byte{}, err } @@ -965,7 +940,7 @@ func (c *BeaconBlockBodyGloas) HashTreeRoot() ([32]byte, error) { return root, err } -func (c *BeaconBlockBodyGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { +func (c *BeaconBlockBodyGloas) ProgressiveHashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() // Field 0: RandaoReveal if len(c.RandaoReveal) != 96 { @@ -983,68 +958,53 @@ func (c *BeaconBlockBodyGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { hh.PutBytes(c.Graffiti) // Field 3: ProposerSlashings { - if len(c.ProposerSlashings) > 16 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.ProposerSlashings { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("ProposerSlashings: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.ProposerSlashings)), 16) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.ProposerSlashings))) } // Field 4: AttesterSlashings { - if len(c.AttesterSlashings) > 1 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.AttesterSlashings { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("AttesterSlashings: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.AttesterSlashings)), 1) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.AttesterSlashings))) } // Field 5: Attestations { - if len(c.Attestations) > 8 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.Attestations { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("Attestations: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.Attestations)), 8) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.Attestations))) } // Field 6: Deposits { - if len(c.Deposits) > 16 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.Deposits { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("Deposits: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.Deposits)), 16) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.Deposits))) } // Field 7: VoluntaryExits { - if len(c.VoluntaryExits) > 16 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.VoluntaryExits { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("VoluntaryExits: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.VoluntaryExits)), 16) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.VoluntaryExits))) } // Field 8: SyncAggregate if err := c.SyncAggregate.HashTreeRootWith(hh); err != nil { @@ -1052,16 +1012,13 @@ func (c *BeaconBlockBodyGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { } // Field 9: BlsToExecutionChanges { - if len(c.BlsToExecutionChanges) > 16 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.BlsToExecutionChanges { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("BlsToExecutionChanges: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.BlsToExecutionChanges)), 16) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.BlsToExecutionChanges))) } // Field 10: SignedExecutionPayloadBid if err := c.SignedExecutionPayloadBid.HashTreeRootWith(hh); err != nil { @@ -1069,22 +1026,19 @@ func (c *BeaconBlockBodyGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { } // Field 11: PayloadAttestations { - if len(c.PayloadAttestations) > 4 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.PayloadAttestations { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("PayloadAttestations: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.PayloadAttestations)), 4) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.PayloadAttestations))) } // Field 12: ParentExecutionRequests if err := c.ParentExecutionRequests.HashTreeRootWith(hh); err != nil { return fmt.Errorf("ParentExecutionRequests: %w", err) } - hh.Merkleize(indx) + hh.MerkleizeProgressiveWithActiveFields(indx, activeFieldsBeaconBlockBodyGloas) return nil } @@ -1774,9 +1728,6 @@ func (c *BeaconStateGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 11: Validators - if len(c.Validators) > 1099511627776 { - return nil, ssz.ErrListTooBig - } for _, o := range c.Validators { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("Validators: %w", err) @@ -1784,29 +1735,17 @@ func (c *BeaconStateGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 12: Balances - if len(c.Balances) > 1099511627776 { - return nil, ssz.ErrListTooBig - } for _, o := range c.Balances { dst = binary.LittleEndian.AppendUint64(dst, o) } // Field 15: PreviousEpochParticipation - if len(c.PreviousEpochParticipation) > 1099511627776 { - return nil, ssz.ErrListTooBig - } dst = append(dst, c.PreviousEpochParticipation...) // Field 16: CurrentEpochParticipation - if len(c.CurrentEpochParticipation) > 1099511627776 { - return nil, ssz.ErrListTooBig - } dst = append(dst, c.CurrentEpochParticipation...) // Field 21: InactivityScores - if len(c.InactivityScores) > 1099511627776 { - return nil, ssz.ErrListTooBig - } for _, o := range c.InactivityScores { dst = binary.LittleEndian.AppendUint64(dst, o) } @@ -1822,9 +1761,6 @@ func (c *BeaconStateGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 34: PendingDeposits - if len(c.PendingDeposits) > 134217728 { - return nil, ssz.ErrListTooBig - } for _, o := range c.PendingDeposits { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("PendingDeposits: %w", err) @@ -1832,9 +1768,6 @@ func (c *BeaconStateGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 35: PendingPartialWithdrawals - if len(c.PendingPartialWithdrawals) > 134217728 { - return nil, ssz.ErrListTooBig - } for _, o := range c.PendingPartialWithdrawals { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("PendingPartialWithdrawals: %w", err) @@ -1842,9 +1775,6 @@ func (c *BeaconStateGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 36: PendingConsolidations - if len(c.PendingConsolidations) > 262144 { - return nil, ssz.ErrListTooBig - } for _, o := range c.PendingConsolidations { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("PendingConsolidations: %w", err) @@ -1852,9 +1782,6 @@ func (c *BeaconStateGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 38: Builders - if len(c.Builders) > 1099511627776 { - return nil, ssz.ErrListTooBig - } for _, o := range c.Builders { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("Builders: %w", err) @@ -1862,9 +1789,6 @@ func (c *BeaconStateGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 42: BuilderPendingWithdrawals - if len(c.BuilderPendingWithdrawals) > 1048576 { - return nil, ssz.ErrListTooBig - } for _, o := range c.BuilderPendingWithdrawals { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("BuilderPendingWithdrawals: %w", err) @@ -1877,9 +1801,6 @@ func (c *BeaconStateGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 44: PayloadExpectedWithdrawals - if len(c.PayloadExpectedWithdrawals) > 16 { - return nil, ssz.ErrListTooBig - } for _, o := range c.PayloadExpectedWithdrawals { if dst, err = o.MarshalSSZTo(dst); err != nil { return nil, fmt.Errorf("PayloadExpectedWithdrawals: %w", err) @@ -2112,9 +2033,6 @@ func (c *BeaconStateGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.Validators length is %d, which is not a multiple of 121: %w", len(sszSlice11), ssz.ErrIncorrectListSize) } numElem := len(sszSlice11) / 121 - if numElem > 1099511627776 { - return fmt.Errorf("ssz-max exceeded: c.Validators has %d elements, ssz-max is 1099511627776: %w", numElem, ssz.ErrListTooBig) - } c.Validators = make([]*Validator, numElem) for i := 0; i < numElem; i++ { var tmp *Validator @@ -2133,9 +2051,6 @@ func (c *BeaconStateGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.Balances length is %d, which is not a multiple of 8: %w", len(sszSlice12), ssz.ErrIncorrectListSize) } numElem := len(sszSlice12) / 8 - if numElem > 1099511627776 { - return fmt.Errorf("ssz-max exceeded: c.Balances has %d elements, ssz-max is 1099511627776: %w", numElem, ssz.ErrListTooBig) - } c.Balances = make([]uint64, numElem) for i := 0; i < numElem; i++ { var tmp uint64 @@ -2205,9 +2120,6 @@ func (c *BeaconStateGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.InactivityScores length is %d, which is not a multiple of 8: %w", len(sszSlice21), ssz.ErrIncorrectListSize) } numElem := len(sszSlice21) / 8 - if numElem > 1099511627776 { - return fmt.Errorf("ssz-max exceeded: c.InactivityScores has %d elements, ssz-max is 1099511627776: %w", numElem, ssz.ErrListTooBig) - } c.InactivityScores = make([]uint64, numElem) for i := 0; i < numElem; i++ { var tmp uint64 @@ -2297,9 +2209,6 @@ func (c *BeaconStateGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.PendingDeposits length is %d, which is not a multiple of 192: %w", len(sszSlice34), ssz.ErrIncorrectListSize) } numElem := len(sszSlice34) / 192 - if numElem > 134217728 { - return fmt.Errorf("ssz-max exceeded: c.PendingDeposits has %d elements, ssz-max is 134217728: %w", numElem, ssz.ErrListTooBig) - } c.PendingDeposits = make([]*PendingDeposit, numElem) for i := 0; i < numElem; i++ { var tmp *PendingDeposit @@ -2318,9 +2227,6 @@ func (c *BeaconStateGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.PendingPartialWithdrawals length is %d, which is not a multiple of 24: %w", len(sszSlice35), ssz.ErrIncorrectListSize) } numElem := len(sszSlice35) / 24 - if numElem > 134217728 { - return fmt.Errorf("ssz-max exceeded: c.PendingPartialWithdrawals has %d elements, ssz-max is 134217728: %w", numElem, ssz.ErrListTooBig) - } c.PendingPartialWithdrawals = make([]*PendingPartialWithdrawal, numElem) for i := 0; i < numElem; i++ { var tmp *PendingPartialWithdrawal @@ -2339,9 +2245,6 @@ func (c *BeaconStateGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.PendingConsolidations length is %d, which is not a multiple of 16: %w", len(sszSlice36), ssz.ErrIncorrectListSize) } numElem := len(sszSlice36) / 16 - if numElem > 262144 { - return fmt.Errorf("ssz-max exceeded: c.PendingConsolidations has %d elements, ssz-max is 262144: %w", numElem, ssz.ErrListTooBig) - } c.PendingConsolidations = make([]*PendingConsolidation, numElem) for i := 0; i < numElem; i++ { var tmp *PendingConsolidation @@ -2374,9 +2277,6 @@ func (c *BeaconStateGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.Builders length is %d, which is not a multiple of 93: %w", len(sszSlice38), ssz.ErrIncorrectListSize) } numElem := len(sszSlice38) / 93 - if numElem > 1099511627776 { - return fmt.Errorf("ssz-max exceeded: c.Builders has %d elements, ssz-max is 1099511627776: %w", numElem, ssz.ErrListTooBig) - } c.Builders = make([]*Builder, numElem) for i := 0; i < numElem; i++ { var tmp *Builder @@ -2418,9 +2318,6 @@ func (c *BeaconStateGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.BuilderPendingWithdrawals length is %d, which is not a multiple of 36: %w", len(sszSlice42), ssz.ErrIncorrectListSize) } numElem := len(sszSlice42) / 36 - if numElem > 1048576 { - return fmt.Errorf("ssz-max exceeded: c.BuilderPendingWithdrawals has %d elements, ssz-max is 1048576: %w", numElem, ssz.ErrListTooBig) - } c.BuilderPendingWithdrawals = make([]*BuilderPendingWithdrawal, numElem) for i := 0; i < numElem; i++ { var tmp *BuilderPendingWithdrawal @@ -2445,9 +2342,6 @@ func (c *BeaconStateGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.PayloadExpectedWithdrawals length is %d, which is not a multiple of 44: %w", len(sszSlice44), ssz.ErrIncorrectListSize) } numElem := len(sszSlice44) / 44 - if numElem > 16 { - return fmt.Errorf("ssz-max exceeded: c.PayloadExpectedWithdrawals has %d elements, ssz-max is 16: %w", numElem, ssz.ErrListTooBig) - } c.PayloadExpectedWithdrawals = make([]*v1.Withdrawal, numElem) for i := 0; i < numElem; i++ { var tmp *v1.Withdrawal @@ -2477,8 +2371,18 @@ func (c *BeaconStateGloas) UnmarshalSSZ(buf []byte) error { } func (c *BeaconStateGloas) HashTreeRoot() ([32]byte, error) { + return c.ProgressiveHashTreeRoot() +} + +func (c *BeaconStateGloas) HashTreeRootWith(hh *ssz.Hasher) error { + return c.ProgressiveHashTreeRootWith(hh) +} + +var activeFieldsBeaconStateGloas = []byte{0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b00111111} + +func (c *BeaconStateGloas) ProgressiveHashTreeRoot() ([32]byte, error) { hh := ssz.DefaultHasherPool.Get() - if err := c.HashTreeRootWith(hh); err != nil { + if err := c.ProgressiveHashTreeRootWith(hh); err != nil { ssz.DefaultHasherPool.Put(hh) return [32]byte{}, err } @@ -2487,7 +2391,7 @@ func (c *BeaconStateGloas) HashTreeRoot() ([32]byte, error) { return root, err } -func (c *BeaconStateGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { +func (c *BeaconStateGloas) ProgressiveHashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() // Field 0: GenesisTime hh.PutUint64(c.GenesisTime) @@ -2571,29 +2475,22 @@ func (c *BeaconStateGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { hh.PutUint64(c.Eth1DepositIndex) // Field 11: Validators { - if len(c.Validators) > 1099511627776 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.Validators { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("Validators: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.Validators)), 1099511627776) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.Validators))) } // Field 12: Balances { - if len(c.Balances) > 1099511627776 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.Balances { hh.AppendUint64(o) } hh.FillUpTo32() - numItems := uint64(len(c.Balances)) - hh.MerkleizeWithMixin(subIndx, numItems, ssz.CalculateLimit(1099511627776, numItems, 8)) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.Balances))) } // Field 13: RandaoMixes { @@ -2621,29 +2518,17 @@ func (c *BeaconStateGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { hh.Merkleize(subIndx) } // Field 15: PreviousEpochParticipation - { - if len(c.PreviousEpochParticipation) > 1099511627776 { - return ssz.ErrBytesLength - } subIndx := hh.Index() hh.AppendBytes32(c.PreviousEpochParticipation) - numItems := uint64(len(c.PreviousEpochParticipation)) - hh.MerkleizeWithMixin(subIndx, numItems, (1099511627776*1+31)/32) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.PreviousEpochParticipation))) } - // Field 16: CurrentEpochParticipation - { - if len(c.CurrentEpochParticipation) > 1099511627776 { - return ssz.ErrBytesLength - } subIndx := hh.Index() hh.AppendBytes32(c.CurrentEpochParticipation) - numItems := uint64(len(c.CurrentEpochParticipation)) - hh.MerkleizeWithMixin(subIndx, numItems, (1099511627776*1+31)/32) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.CurrentEpochParticipation))) } - // Field 17: JustificationBits if len([]byte(c.JustificationBits)) != 1 { return ssz.ErrBytesLength @@ -2663,16 +2548,12 @@ func (c *BeaconStateGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { } // Field 21: InactivityScores { - if len(c.InactivityScores) > 1099511627776 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.InactivityScores { hh.AppendUint64(o) } hh.FillUpTo32() - numItems := uint64(len(c.InactivityScores)) - hh.MerkleizeWithMixin(subIndx, numItems, ssz.CalculateLimit(1099511627776, numItems, 8)) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.InactivityScores))) } // Field 22: CurrentSyncCommittee if err := c.CurrentSyncCommittee.HashTreeRootWith(hh); err != nil { @@ -2730,42 +2611,33 @@ func (c *BeaconStateGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { } // Field 34: PendingDeposits { - if len(c.PendingDeposits) > 134217728 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.PendingDeposits { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("PendingDeposits: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.PendingDeposits)), 134217728) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.PendingDeposits))) } // Field 35: PendingPartialWithdrawals { - if len(c.PendingPartialWithdrawals) > 134217728 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.PendingPartialWithdrawals { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("PendingPartialWithdrawals: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.PendingPartialWithdrawals)), 134217728) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.PendingPartialWithdrawals))) } // Field 36: PendingConsolidations { - if len(c.PendingConsolidations) > 262144 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.PendingConsolidations { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("PendingConsolidations: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.PendingConsolidations)), 262144) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.PendingConsolidations))) } // Field 37: ProposerLookahead { @@ -2780,16 +2652,13 @@ func (c *BeaconStateGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { } // Field 38: Builders { - if len(c.Builders) > 1099511627776 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.Builders { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("Builders: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.Builders)), 1099511627776) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.Builders))) } // Field 39: NextWithdrawalBuilderIndex if err := c.NextWithdrawalBuilderIndex.HashTreeRootWith(hh); err != nil { @@ -2815,16 +2684,13 @@ func (c *BeaconStateGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { } // Field 42: BuilderPendingWithdrawals { - if len(c.BuilderPendingWithdrawals) > 1048576 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.BuilderPendingWithdrawals { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("BuilderPendingWithdrawals: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.BuilderPendingWithdrawals)), 1048576) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.BuilderPendingWithdrawals))) } // Field 43: LatestExecutionPayloadBid if err := c.LatestExecutionPayloadBid.HashTreeRootWith(hh); err != nil { @@ -2832,16 +2698,13 @@ func (c *BeaconStateGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { } // Field 44: PayloadExpectedWithdrawals { - if len(c.PayloadExpectedWithdrawals) > 16 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.PayloadExpectedWithdrawals { if err := o.HashTreeRootWith(hh); err != nil { return fmt.Errorf("PayloadExpectedWithdrawals: %w", err) } } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.PayloadExpectedWithdrawals)), 16) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.PayloadExpectedWithdrawals))) } // Field 45: PtcWindow { @@ -2856,7 +2719,7 @@ func (c *BeaconStateGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { } hh.Merkleize(subIndx) } - hh.Merkleize(indx) + hh.MerkleizeProgressiveWithActiveFields(indx, activeFieldsBeaconStateGloas) return nil } @@ -3547,9 +3410,6 @@ func (c *DataColumnSidecarGloas) MarshalSSZTo(dst []byte) ([]byte, error) { dst = append(dst, c.BeaconBlockRoot...) // Field 1: Column - if len(c.Column) > 4096 { - return nil, ssz.ErrListTooBig - } for _, o := range c.Column { if len(o) != 2048 { return nil, ssz.ErrBytesLength @@ -3558,9 +3418,6 @@ func (c *DataColumnSidecarGloas) MarshalSSZTo(dst []byte) ([]byte, error) { } // Field 2: KzgProofs - if len(c.KzgProofs) > 4096 { - return nil, ssz.ErrListTooBig - } for _, o := range c.KzgProofs { if len(o) != 48 { return nil, ssz.ErrBytesLength @@ -3604,9 +3461,6 @@ func (c *DataColumnSidecarGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.Column length is %d, which is not a multiple of 2048: %w", len(sszSlice1), ssz.ErrIncorrectListSize) } numElem := len(sszSlice1) / 2048 - if numElem > 4096 { - return fmt.Errorf("ssz-max exceeded: c.Column has %d elements, ssz-max is 4096: %w", numElem, ssz.ErrListTooBig) - } c.Column = make([][]byte, numElem) for i := 0; i < numElem; i++ { var tmp []byte @@ -3624,9 +3478,6 @@ func (c *DataColumnSidecarGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.KzgProofs length is %d, which is not a multiple of 48: %w", len(sszSlice2), ssz.ErrIncorrectListSize) } numElem := len(sszSlice2) / 48 - if numElem > 4096 { - return fmt.Errorf("ssz-max exceeded: c.KzgProofs has %d elements, ssz-max is 4096: %w", numElem, ssz.ErrListTooBig) - } c.KzgProofs = make([][]byte, numElem) for i := 0; i < numElem; i++ { var tmp []byte @@ -3666,9 +3517,6 @@ func (c *DataColumnSidecarGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { hh.PutUint64(c.Index) // Field 1: Column { - if len(c.Column) > 4096 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.Column { if len(o) != 2048 { @@ -3676,13 +3524,10 @@ func (c *DataColumnSidecarGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { } hh.PutBytes(o) } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.Column)), 4096) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.Column))) } // Field 2: KzgProofs { - if len(c.KzgProofs) > 4096 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.KzgProofs { if len(o) != 48 { @@ -3690,7 +3535,7 @@ func (c *DataColumnSidecarGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { } hh.PutBytes(o) } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.KzgProofs)), 4096) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.KzgProofs))) } // Field 3: Slot if err := c.Slot.HashTreeRootWith(hh); err != nil { @@ -3784,9 +3629,6 @@ func (c *ExecutionPayloadBid) MarshalSSZTo(dst []byte) ([]byte, error) { dst = append(dst, c.ExecutionRequestsRoot...) // Field 10: BlobKzgCommitments - if len(c.BlobKzgCommitments) > 4096 { - return nil, ssz.ErrListTooBig - } for _, o := range c.BlobKzgCommitments { if len(o) != 48 { return nil, ssz.ErrBytesLength @@ -3873,9 +3715,6 @@ func (c *ExecutionPayloadBid) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.BlobKzgCommitments length is %d, which is not a multiple of 48: %w", len(sszSlice10), ssz.ErrIncorrectListSize) } numElem := len(sszSlice10) / 48 - if numElem > 4096 { - return fmt.Errorf("ssz-max exceeded: c.BlobKzgCommitments has %d elements, ssz-max is 4096: %w", numElem, ssz.ErrListTooBig) - } c.BlobKzgCommitments = make([][]byte, numElem) for i := 0; i < numElem; i++ { var tmp []byte @@ -3894,8 +3733,18 @@ func (c *ExecutionPayloadBid) UnmarshalSSZ(buf []byte) error { } func (c *ExecutionPayloadBid) HashTreeRoot() ([32]byte, error) { + return c.ProgressiveHashTreeRoot() +} + +func (c *ExecutionPayloadBid) HashTreeRootWith(hh *ssz.Hasher) error { + return c.ProgressiveHashTreeRootWith(hh) +} + +var activeFieldsExecutionPayloadBid = []byte{0b11111111, 0b00001111} + +func (c *ExecutionPayloadBid) ProgressiveHashTreeRoot() ([32]byte, error) { hh := ssz.DefaultHasherPool.Get() - if err := c.HashTreeRootWith(hh); err != nil { + if err := c.ProgressiveHashTreeRootWith(hh); err != nil { ssz.DefaultHasherPool.Put(hh) return [32]byte{}, err } @@ -3904,7 +3753,7 @@ func (c *ExecutionPayloadBid) HashTreeRoot() ([32]byte, error) { return root, err } -func (c *ExecutionPayloadBid) HashTreeRootWith(hh *ssz.Hasher) (err error) { +func (c *ExecutionPayloadBid) ProgressiveHashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() // Field 0: ParentBlockHash if len(c.ParentBlockHash) != 32 { @@ -3951,9 +3800,6 @@ func (c *ExecutionPayloadBid) HashTreeRootWith(hh *ssz.Hasher) (err error) { } // Field 10: BlobKzgCommitments { - if len(c.BlobKzgCommitments) > 4096 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.BlobKzgCommitments { if len(o) != 48 { @@ -3961,14 +3807,14 @@ func (c *ExecutionPayloadBid) HashTreeRootWith(hh *ssz.Hasher) (err error) { } hh.PutBytes(o) } - hh.MerkleizeWithMixin(subIndx, uint64(len(c.BlobKzgCommitments)), 4096) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.BlobKzgCommitments))) } // Field 11: ExecutionRequestsRoot if len(c.ExecutionRequestsRoot) != 32 { return ssz.ErrBytesLength } hh.PutBytes(c.ExecutionRequestsRoot) - hh.Merkleize(indx) + hh.MerkleizeProgressiveWithActiveFields(indx, activeFieldsExecutionPayloadBid) return nil } @@ -4090,8 +3936,18 @@ func (c *ExecutionPayloadEnvelope) UnmarshalSSZ(buf []byte) error { } func (c *ExecutionPayloadEnvelope) HashTreeRoot() ([32]byte, error) { + return c.ProgressiveHashTreeRoot() +} + +func (c *ExecutionPayloadEnvelope) HashTreeRootWith(hh *ssz.Hasher) error { + return c.ProgressiveHashTreeRootWith(hh) +} + +var activeFieldsExecutionPayloadEnvelope = []byte{0b00011111} + +func (c *ExecutionPayloadEnvelope) ProgressiveHashTreeRoot() ([32]byte, error) { hh := ssz.DefaultHasherPool.Get() - if err := c.HashTreeRootWith(hh); err != nil { + if err := c.ProgressiveHashTreeRootWith(hh); err != nil { ssz.DefaultHasherPool.Put(hh) return [32]byte{}, err } @@ -4100,7 +3956,7 @@ func (c *ExecutionPayloadEnvelope) HashTreeRoot() ([32]byte, error) { return root, err } -func (c *ExecutionPayloadEnvelope) HashTreeRootWith(hh *ssz.Hasher) (err error) { +func (c *ExecutionPayloadEnvelope) ProgressiveHashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() // Field 0: Payload if err := c.Payload.HashTreeRootWith(hh); err != nil { @@ -4124,7 +3980,7 @@ func (c *ExecutionPayloadEnvelope) HashTreeRootWith(hh *ssz.Hasher) (err error) return ssz.ErrBytesLength } hh.PutBytes(c.ParentBeaconBlockRoot) - hh.Merkleize(indx) + hh.MerkleizeProgressiveWithActiveFields(indx, activeFieldsExecutionPayloadEnvelope) return nil } @@ -4162,9 +4018,6 @@ func (c *IndexedAttestationGloas) MarshalSSZTo(dst []byte) ([]byte, error) { dst = append(dst, c.Signature...) // Field 0: AttestingIndices - if len(c.AttestingIndices) > 131072 { - return nil, ssz.ErrListTooBig - } for _, o := range c.AttestingIndices { dst = binary.LittleEndian.AppendUint64(dst, o) } @@ -4196,9 +4049,6 @@ func (c *IndexedAttestationGloas) UnmarshalSSZ(buf []byte) error { return fmt.Errorf("misaligned bytes: c.AttestingIndices length is %d, which is not a multiple of 8: %w", len(sszSlice0), ssz.ErrIncorrectListSize) } numElem := len(sszSlice0) / 8 - if numElem > 131072 { - return fmt.Errorf("ssz-max exceeded: c.AttestingIndices has %d elements, ssz-max is 131072: %w", numElem, ssz.ErrListTooBig) - } c.AttestingIndices = make([]uint64, numElem) for i := 0; i < numElem; i++ { var tmp uint64 @@ -4222,8 +4072,18 @@ func (c *IndexedAttestationGloas) UnmarshalSSZ(buf []byte) error { } func (c *IndexedAttestationGloas) HashTreeRoot() ([32]byte, error) { + return c.ProgressiveHashTreeRoot() +} + +func (c *IndexedAttestationGloas) HashTreeRootWith(hh *ssz.Hasher) error { + return c.ProgressiveHashTreeRootWith(hh) +} + +var activeFieldsIndexedAttestationGloas = []byte{0b00000111} + +func (c *IndexedAttestationGloas) ProgressiveHashTreeRoot() ([32]byte, error) { hh := ssz.DefaultHasherPool.Get() - if err := c.HashTreeRootWith(hh); err != nil { + if err := c.ProgressiveHashTreeRootWith(hh); err != nil { ssz.DefaultHasherPool.Put(hh) return [32]byte{}, err } @@ -4232,20 +4092,16 @@ func (c *IndexedAttestationGloas) HashTreeRoot() ([32]byte, error) { return root, err } -func (c *IndexedAttestationGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { +func (c *IndexedAttestationGloas) ProgressiveHashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() // Field 0: AttestingIndices { - if len(c.AttestingIndices) > 131072 { - return ssz.ErrListTooBig - } subIndx := hh.Index() for _, o := range c.AttestingIndices { hh.AppendUint64(o) } hh.FillUpTo32() - numItems := uint64(len(c.AttestingIndices)) - hh.MerkleizeWithMixin(subIndx, numItems, ssz.CalculateLimit(131072, numItems, 8)) + hh.MerkleizeProgressiveWithMixin(subIndx, uint64(len(c.AttestingIndices))) } // Field 1: Data if err := c.Data.HashTreeRootWith(hh); err != nil { @@ -4256,7 +4112,7 @@ func (c *IndexedAttestationGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) { return ssz.ErrBytesLength } hh.PutBytes(c.Signature) - hh.Merkleize(indx) + hh.MerkleizeProgressiveWithActiveFields(indx, activeFieldsIndexedAttestationGloas) return nil } @@ -4325,8 +4181,18 @@ func (c *PayloadAttestation) UnmarshalSSZ(buf []byte) error { } func (c *PayloadAttestation) HashTreeRoot() ([32]byte, error) { + return c.ProgressiveHashTreeRoot() +} + +func (c *PayloadAttestation) HashTreeRootWith(hh *ssz.Hasher) error { + return c.ProgressiveHashTreeRootWith(hh) +} + +var activeFieldsPayloadAttestation = []byte{0b00000111} + +func (c *PayloadAttestation) ProgressiveHashTreeRoot() ([32]byte, error) { hh := ssz.DefaultHasherPool.Get() - if err := c.HashTreeRootWith(hh); err != nil { + if err := c.ProgressiveHashTreeRootWith(hh); err != nil { ssz.DefaultHasherPool.Put(hh) return [32]byte{}, err } @@ -4335,7 +4201,7 @@ func (c *PayloadAttestation) HashTreeRoot() ([32]byte, error) { return root, err } -func (c *PayloadAttestation) HashTreeRootWith(hh *ssz.Hasher) (err error) { +func (c *PayloadAttestation) ProgressiveHashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() // Field 0: AggregationBits if len([]byte(c.AggregationBits)) != 64 { @@ -4351,7 +4217,7 @@ func (c *PayloadAttestation) HashTreeRootWith(hh *ssz.Hasher) (err error) { return ssz.ErrBytesLength } hh.PutBytes(c.Signature) - hh.Merkleize(indx) + hh.MerkleizeProgressiveWithActiveFields(indx, activeFieldsPayloadAttestation) return nil } From a669f2ff1eaf0cef0cbd27da0e098a20f499a789 Mon Sep 17 00:00:00 2001 From: Terence Tsao Date: Fri, 31 Jul 2026 19:55:02 -0500 Subject: [PATCH 05/23] Enforce BUILDER_WITHDRAWAL_PREFIX on builder deposit requests Ignore builder deposit requests whose withdrawal credentials do not carry BUILDER_WITHDRAWAL_PREFIX, both when batching new registrations and when processing an individual request. Such deposits are dropped and the funds are lost, matching the spec. Register new builders with PAYLOAD_BUILDER_VERSION rather than echoing the first credential byte, so the stored version cannot be influenced by the depositor. --- .../core/gloas/builder_deposit_request.go | 7 ++- .../gloas/builder_deposit_request_test.go | 46 ++++++++++++++++++- .../state/state-native/setters_gloas.go | 3 +- .../state/state-native/setters_gloas_test.go | 4 +- changelog/terence_builder-deposit-prefix.md | 3 ++ 5 files changed, 57 insertions(+), 6 deletions(-) create mode 100644 changelog/terence_builder-deposit-prefix.md diff --git a/beacon-chain/core/gloas/builder_deposit_request.go b/beacon-chain/core/gloas/builder_deposit_request.go index 0c6f1cd13112..fb02aa5e5fe5 100644 --- a/beacon-chain/core/gloas/builder_deposit_request.go +++ b/beacon-chain/core/gloas/builder_deposit_request.go @@ -27,7 +27,7 @@ func ProcessBuilderDepositRequests(ctx context.Context, st state.BeaconState, re newDeposits := make([]*enginev1.BuilderDepositRequest, 0, len(requests)) newIdx := make([]int, 0, len(requests)) for i, request := range requests { - if request == nil { + if request == nil || !helpers.IsBuilderWithdrawalCredential(request.WithdrawalCredentials) { continue } if _, isBuilder := st.BuilderIndexByPubkey(bytesutil.ToBytes48(request.Pubkey)); !isBuilder { @@ -86,6 +86,11 @@ func processBuilderDepositRequest(ctx context.Context, st state.BeaconState, req return errors.New("nil builder deposit request") } + // Deposits without BUILDER_WITHDRAWAL_PREFIX are dropped and the funds are lost. + if !helpers.IsBuilderWithdrawalCredential(request.WithdrawalCredentials) { + return nil + } + pubkey := bytesutil.ToBytes48(request.Pubkey) if idx, isBuilder := st.BuilderIndexByPubkey(pubkey); isBuilder { if err := st.IncreaseBuilderBalance(idx, request.Amount); err != nil { diff --git a/beacon-chain/core/gloas/builder_deposit_request_test.go b/beacon-chain/core/gloas/builder_deposit_request_test.go index 25fd1d198b24..57fe0c3cdbeb 100644 --- a/beacon-chain/core/gloas/builder_deposit_request_test.go +++ b/beacon-chain/core/gloas/builder_deposit_request_test.go @@ -46,7 +46,7 @@ func TestProcessBuilderDepositRequest_NewBuilderValidSignature(t *testing.T) { builder, err := st.Builder(idx) require.NoError(t, err) require.DeepEqual(t, req.Pubkey, builder.Pubkey) - require.DeepEqual(t, []byte{cred[0]}, builder.Version) + require.DeepEqual(t, []byte{params.BeaconConfig().PayloadBuilderVersion}, builder.Version) require.DeepEqual(t, cred[12:], builder.ExecutionAddress) require.Equal(t, uint64(1234), uint64(builder.Balance)) require.Equal(t, params.BeaconConfig().FarFutureEpoch, builder.WithdrawableEpoch) @@ -65,6 +65,50 @@ func TestProcessBuilderDepositRequest_NewBuilderInvalidSignatureIgnored(t *testi require.Equal(t, false, ok) } +func TestProcessBuilderDepositRequest_NewBuilderNonBuilderPrefixIgnored(t *testing.T) { + sk, err := bls.RandKey() + require.NoError(t, err) + cred := builderWithdrawalCredentials() + cred[0] = 0x01 + req := signedBuilderDepositRequest(t, sk, cred, 1234) + + st := newGloasState(t, nil, nil) + require.NoError(t, processBuilderDepositRequest(t.Context(), st, req, sigKnownValid)) + + _, ok := st.BuilderIndexByPubkey(toBytes48(req.Pubkey)) + require.Equal(t, false, ok) +} + +func TestProcessBuilderDepositRequest_TopUpNonBuilderPrefixIgnored(t *testing.T) { + sk, err := bls.RandKey() + require.NoError(t, err) + pubkey := sk.PublicKey().Marshal() + builders := []*ethpb.Builder{{ + Pubkey: pubkey, + Version: []byte{params.BeaconConfig().PayloadBuilderVersion}, + ExecutionAddress: bytes.Repeat([]byte{0x11}, 20), + Balance: 5, + WithdrawableEpoch: params.BeaconConfig().FarFutureEpoch, + }} + st := newGloasState(t, nil, builders) + + cred := builderWithdrawalCredentials() + cred[0] = 0x01 + req := &enginev1.BuilderDepositRequest{ + Pubkey: pubkey, + WithdrawalCredentials: cred[:], + Amount: 200, + Signature: make([]byte, 96), + } + require.NoError(t, processBuilderDepositRequest(t.Context(), st, req, sigKnownValid)) + + idx, ok := st.BuilderIndexByPubkey(toBytes48(pubkey)) + require.Equal(t, true, ok) + builder, err := st.Builder(idx) + require.NoError(t, err) + require.Equal(t, uint64(5), uint64(builder.Balance)) +} + func TestProcessBuilderDepositRequest_ExistingBuilderTopsUpNoSignatureCheck(t *testing.T) { sk, err := bls.RandKey() require.NoError(t, err) diff --git a/beacon-chain/state/state-native/setters_gloas.go b/beacon-chain/state/state-native/setters_gloas.go index b6cd146d12a4..066ea730c878 100644 --- a/beacon-chain/state/state-native/setters_gloas.go +++ b/beacon-chain/state/state-native/setters_gloas.go @@ -368,8 +368,7 @@ func (b *BeaconState) AddBuilderFromDeposit(pubkey [fieldparams.BLSPubkeyLength] b.lock.Lock() defer b.lock.Unlock() - // process_builder_deposit_request sets version to withdrawal_credentials[0]. - return b.addBuilderFromDepositAtEpoch(pubkey, withdrawalCredentials[0], withdrawalCredentials, amount, slots.ToEpoch(b.slot)) + return b.addBuilderFromDepositAtEpoch(pubkey, params.BeaconConfig().PayloadBuilderVersion, withdrawalCredentials, amount, slots.ToEpoch(b.slot)) } func (b *BeaconState) addBuilderFromDepositAtEpoch(pubkey [fieldparams.BLSPubkeyLength]byte, builderVersion byte, withdrawalCredentials [fieldparams.RootLength]byte, amount uint64, depositEpoch primitives.Epoch) error { diff --git a/beacon-chain/state/state-native/setters_gloas_test.go b/beacon-chain/state/state-native/setters_gloas_test.go index f480635b35ef..8c2d5a22d9e8 100644 --- a/beacon-chain/state/state-native/setters_gloas_test.go +++ b/beacon-chain/state/state-native/setters_gloas_test.go @@ -910,7 +910,7 @@ func TestAddBuilderFromDeposit(t *testing.T) { copy(pubkey[:], bytes.Repeat([]byte{0xAA}, 48)) var wc [32]byte copy(wc[:], bytes.Repeat([]byte{0xBB}, 32)) - wc[0] = 0x42 // version byte + wc[0] = 0x42 // registered version must ignore the credential prefix st := &BeaconState{ version: version.Gloas, @@ -933,7 +933,7 @@ func TestAddBuilderFromDeposit(t *testing.T) { got := st.builders[0] require.NotNil(t, got) require.DeepEqual(t, pubkey[:], got.Pubkey) - require.DeepEqual(t, []byte{0x42}, got.Version) + require.DeepEqual(t, []byte{params.BeaconConfig().PayloadBuilderVersion}, got.Version) require.DeepEqual(t, wc[12:], got.ExecutionAddress) require.Equal(t, primitives.Gwei(123), got.Balance) require.Equal(t, primitives.Epoch(0), got.DepositEpoch) diff --git a/changelog/terence_builder-deposit-prefix.md b/changelog/terence_builder-deposit-prefix.md new file mode 100644 index 000000000000..ba9b5111657a --- /dev/null +++ b/changelog/terence_builder-deposit-prefix.md @@ -0,0 +1,3 @@ +### Changed + +- Ignore builder deposit requests without `BUILDER_WITHDRAWAL_PREFIX` and register new builders with `PAYLOAD_BUILDER_VERSION`. From a0932831e26f811118f02287b8f8199fea9581c1 Mon Sep 17 00:00:00 2001 From: Terence Tsao Date: Fri, 31 Jul 2026 20:08:24 -0500 Subject: [PATCH 06/23] Reset builder withdrawable epoch on top-up only once swept An exited builder's withdrawable epoch was pushed out on every top-up, which let a builder with a pending balance defer its own withdrawal indefinitely. Only reset when the builder has actually been swept, and evaluate that before crediting the top-up so the new deposit does not mask a zero balance. Also guard against a nil builder at a known index rather than dereferencing it. --- .../core/gloas/builder_deposit_request.go | 12 ++-- .../gloas/builder_deposit_request_test.go | 63 +++++++++++++++++++ .../terence_builder-topup-swept-reset.md | 3 + 3 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 changelog/terence_builder-topup-swept-reset.md diff --git a/beacon-chain/core/gloas/builder_deposit_request.go b/beacon-chain/core/gloas/builder_deposit_request.go index fb02aa5e5fe5..935f02926069 100644 --- a/beacon-chain/core/gloas/builder_deposit_request.go +++ b/beacon-chain/core/gloas/builder_deposit_request.go @@ -93,19 +93,23 @@ func processBuilderDepositRequest(ctx context.Context, st state.BeaconState, req pubkey := bytesutil.ToBytes48(request.Pubkey) if idx, isBuilder := st.BuilderIndexByPubkey(pubkey); isBuilder { - if err := st.IncreaseBuilderBalance(idx, request.Amount); err != nil { - return err - } builder, err := st.Builder(idx) if err != nil { return err } - if builder.WithdrawableEpoch != params.BeaconConfig().FarFutureEpoch { + if builder == nil { + return errors.Errorf("builder at index %d is nil", idx) + } + // Reset only when exited and fully swept, checked before the top-up is credited. + if builder.WithdrawableEpoch != params.BeaconConfig().FarFutureEpoch && builder.Balance == 0 { builder.WithdrawableEpoch = slots.ToEpoch(st.Slot()) + params.BeaconConfig().MinBuilderWithdrawabilityDelay if err := st.UpdateBuilderAtIndex(idx, builder); err != nil { return err } } + if err := st.IncreaseBuilderBalance(idx, request.Amount); err != nil { + return err + } builderDepositsProcessedTotal.Inc() return nil } diff --git a/beacon-chain/core/gloas/builder_deposit_request_test.go b/beacon-chain/core/gloas/builder_deposit_request_test.go index 57fe0c3cdbeb..dddcea3655f8 100644 --- a/beacon-chain/core/gloas/builder_deposit_request_test.go +++ b/beacon-chain/core/gloas/builder_deposit_request_test.go @@ -11,6 +11,7 @@ import ( enginev1 "github.com/OffchainLabs/prysm/v7/proto/engine/v1" ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1" "github.com/OffchainLabs/prysm/v7/testing/require" + "github.com/OffchainLabs/prysm/v7/time/slots" ) func signedBuilderDepositRequest(t *testing.T, sk bls.SecretKey, cred [32]byte, amount uint64) *enginev1.BuilderDepositRequest { @@ -137,6 +138,68 @@ func TestProcessBuilderDepositRequest_ExistingBuilderTopsUpNoSignatureCheck(t *t require.Equal(t, uint64(205), uint64(builder.Balance)) } +func TestProcessBuilderDepositRequest_ExitedSweptBuilderTopUpResetsWithdrawableEpoch(t *testing.T) { + sk, err := bls.RandKey() + require.NoError(t, err) + pubkey := sk.PublicKey().Marshal() + builders := []*ethpb.Builder{{ + Pubkey: pubkey, + Version: []byte{params.BeaconConfig().BuilderWithdrawalPrefixByte}, + ExecutionAddress: bytes.Repeat([]byte{0x11}, 20), + Balance: 0, + WithdrawableEpoch: 0, + }} + st := newGloasState(t, nil, builders) + + cred := builderWithdrawalCredentials() + req := &enginev1.BuilderDepositRequest{ + Pubkey: pubkey, + WithdrawalCredentials: cred[:], + Amount: 200, + Signature: make([]byte, 96), + } + require.NoError(t, processBuilderDepositRequest(t.Context(), st, req, sigUnverified)) + + idx, ok := st.BuilderIndexByPubkey(toBytes48(pubkey)) + require.Equal(t, true, ok) + builder, err := st.Builder(idx) + require.NoError(t, err) + require.Equal(t, uint64(200), uint64(builder.Balance)) + expected := slots.ToEpoch(st.Slot()) + params.BeaconConfig().MinBuilderWithdrawabilityDelay + require.Equal(t, expected, builder.WithdrawableEpoch) +} + +func TestProcessBuilderDepositRequest_ExitedUnsweptBuilderTopUpKeepsWithdrawableEpoch(t *testing.T) { + sk, err := bls.RandKey() + require.NoError(t, err) + pubkey := sk.PublicKey().Marshal() + exitedEpoch := primitives.Epoch(1) + builders := []*ethpb.Builder{{ + Pubkey: pubkey, + Version: []byte{params.BeaconConfig().BuilderWithdrawalPrefixByte}, + ExecutionAddress: bytes.Repeat([]byte{0x11}, 20), + Balance: 5, + WithdrawableEpoch: exitedEpoch, + }} + st := newGloasState(t, nil, builders) + + cred := builderWithdrawalCredentials() + req := &enginev1.BuilderDepositRequest{ + Pubkey: pubkey, + WithdrawalCredentials: cred[:], + Amount: 200, + Signature: make([]byte, 96), + } + require.NoError(t, processBuilderDepositRequest(t.Context(), st, req, sigUnverified)) + + idx, ok := st.BuilderIndexByPubkey(toBytes48(pubkey)) + require.Equal(t, true, ok) + builder, err := st.Builder(idx) + require.NoError(t, err) + require.Equal(t, uint64(205), uint64(builder.Balance)) + require.Equal(t, exitedEpoch, builder.WithdrawableEpoch) +} + func TestProcessBuilderDepositRequests_BatchMixedValidInvalidAndTopUp(t *testing.T) { cred := builderWithdrawalCredentials() skValid, err := bls.RandKey() diff --git a/changelog/terence_builder-topup-swept-reset.md b/changelog/terence_builder-topup-swept-reset.md new file mode 100644 index 000000000000..d13a35b50952 --- /dev/null +++ b/changelog/terence_builder-topup-swept-reset.md @@ -0,0 +1,3 @@ +### Changed + +- Reset an exited builder's withdrawable epoch on top-up only when its balance has been swept. From 0226e6986b99c02798a31bd389dd37bc8e11f2c2 Mon Sep 17 00:00:00 2001 From: Terence Tsao Date: Fri, 31 Jul 2026 21:10:36 -0500 Subject: [PATCH 07/23] Remove the deposit request bound on Gloas request decoding Gloas drops MAX_DEPOSIT_REQUESTS_PER_PAYLOAD; the execution layer bounds deposit requests through the block gas limit instead. Lift the cap in the Gloas request list decoder. The remaining per-payload maxima (withdrawals, consolidations, builder deposits and builder exits) are still consensus checks, so assert them explicitly in ApplyParentExecutionPayload rather than relying on the SSZ list limits, which no longer bound the progressive types. --- beacon-chain/core/gloas/BUILD.bazel | 1 + beacon-chain/core/gloas/parent_payload.go | 30 ++++++++++++++++++- .../core/gloas/parent_payload_test.go | 27 +++++++++++++++++ .../terence_gloas-remove-deposit-limit.md | 3 ++ proto/engine/v1/electra.go | 3 ++ proto/engine/v1/electra_test.go | 20 +++++++++++++ 6 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 beacon-chain/core/gloas/parent_payload_test.go create mode 100644 changelog/terence_gloas-remove-deposit-limit.md diff --git a/beacon-chain/core/gloas/BUILD.bazel b/beacon-chain/core/gloas/BUILD.bazel index c0f8e93d99f6..3362eaecb8c2 100644 --- a/beacon-chain/core/gloas/BUILD.bazel +++ b/beacon-chain/core/gloas/BUILD.bazel @@ -58,6 +58,7 @@ go_test( "builder_deposit_request_test.go", "builder_exit_request_test.go", "deposit_request_test.go", + "parent_payload_test.go", "payload_attestation_test.go", "payload_test.go", "pending_payment_test.go", diff --git a/beacon-chain/core/gloas/parent_payload.go b/beacon-chain/core/gloas/parent_payload.go index 48c56d91795e..c96048f15bd3 100644 --- a/beacon-chain/core/gloas/parent_payload.go +++ b/beacon-chain/core/gloas/parent_payload.go @@ -6,6 +6,7 @@ import ( requests "github.com/OffchainLabs/prysm/v7/beacon-chain/core/requests" "github.com/OffchainLabs/prysm/v7/beacon-chain/state" + "github.com/OffchainLabs/prysm/v7/config/params" "github.com/OffchainLabs/prysm/v7/consensus-types/interfaces" "github.com/OffchainLabs/prysm/v7/monitoring/tracing/trace" enginev1 "github.com/OffchainLabs/prysm/v7/proto/engine/v1" @@ -63,7 +64,11 @@ func ProcessParentExecutionPayload(ctx context.Context, st state.BeaconState, bl // and mutates st. Called by ProcessParentExecutionPayload and by the validator during // block production before computing withdrawals. // -// +// +// assert len(requests.withdrawals) <= MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD +// assert len(requests.consolidations) <= MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD +// assert len(requests.builder_deposits) <= MAX_BUILDER_DEPOSIT_REQUESTS_PER_PAYLOAD +// assert len(requests.builder_exits) <= MAX_BUILDER_EXIT_REQUESTS_PER_PAYLOAD func ApplyParentExecutionPayload( ctx context.Context, st state.BeaconState, @@ -75,6 +80,10 @@ func ApplyParentExecutionPayload( } parentSlot := parentBid.Slot() + if err := validateExecutionRequestLengths(reqs); err != nil { + return err + } + if err := processExecutionRequests(ctx, st, reqs); err != nil { return errors.Wrap(err, "could not process parent execution requests") } @@ -95,6 +104,25 @@ func ApplyParentExecutionPayload( return nil } +// validateExecutionRequestLengths enforces the per-payload maxima that remain +// consensus-layer checks now that EIP-7688 uses ProgressiveList SSZ types. +func validateExecutionRequestLengths(reqs *enginev1.ExecutionRequestsGloas) error { + cfg := params.BeaconConfig() + if uint64(len(reqs.GetWithdrawals())) > cfg.MaxWithdrawalRequestsPerPayload { + return errors.Errorf("too many withdrawal requests: %d > %d", len(reqs.GetWithdrawals()), cfg.MaxWithdrawalRequestsPerPayload) + } + if uint64(len(reqs.GetConsolidations())) > cfg.MaxConsolidationsRequestsPerPayload { + return errors.Errorf("too many consolidation requests: %d > %d", len(reqs.GetConsolidations()), cfg.MaxConsolidationsRequestsPerPayload) + } + if uint64(len(reqs.GetBuilderDeposits())) > cfg.MaxBuilderDepositRequestsPerPayload { + return errors.Errorf("too many builder deposit requests: %d > %d", len(reqs.GetBuilderDeposits()), cfg.MaxBuilderDepositRequestsPerPayload) + } + if uint64(len(reqs.GetBuilderExits())) > cfg.MaxBuilderExitRequestsPerPayload { + return errors.Errorf("too many builder exit requests: %d > %d", len(reqs.GetBuilderExits()), cfg.MaxBuilderExitRequestsPerPayload) + } + return nil +} + func processExecutionRequests(ctx context.Context, st state.BeaconState, rqs *enginev1.ExecutionRequestsGloas) error { if err := ProcessDepositRequests(ctx, st, rqs.Deposits); err != nil { return errors.Wrap(err, "could not process deposit requests") diff --git a/beacon-chain/core/gloas/parent_payload_test.go b/beacon-chain/core/gloas/parent_payload_test.go new file mode 100644 index 000000000000..be8766457892 --- /dev/null +++ b/beacon-chain/core/gloas/parent_payload_test.go @@ -0,0 +1,27 @@ +package gloas + +import ( + "testing" + + "github.com/OffchainLabs/prysm/v7/config/params" + enginev1 "github.com/OffchainLabs/prysm/v7/proto/engine/v1" + "github.com/OffchainLabs/prysm/v7/testing/require" +) + +func TestValidateExecutionRequestLengths_DepositsUnbounded(t *testing.T) { + cfg := params.BeaconConfig() + reqs := &enginev1.ExecutionRequestsGloas{ + Deposits: make([]*enginev1.DepositRequest, int(cfg.MaxDepositRequestsPerPayload)+1), + } + + require.NoError(t, validateExecutionRequestLengths(reqs)) +} + +func TestValidateExecutionRequestLengths_WithdrawalsBounded(t *testing.T) { + cfg := params.BeaconConfig() + reqs := &enginev1.ExecutionRequestsGloas{ + Withdrawals: make([]*enginev1.WithdrawalRequest, int(cfg.MaxWithdrawalRequestsPerPayload)+1), + } + + require.ErrorContains(t, "too many withdrawal requests", validateExecutionRequestLengths(reqs)) +} diff --git a/changelog/terence_gloas-remove-deposit-limit.md b/changelog/terence_gloas-remove-deposit-limit.md new file mode 100644 index 000000000000..c18a6dd59c46 --- /dev/null +++ b/changelog/terence_gloas-remove-deposit-limit.md @@ -0,0 +1,3 @@ +### Changed + +- Remove the `MAX_DEPOSIT_REQUESTS_PER_PAYLOAD` bound on Gloas execution request decoding. diff --git a/proto/engine/v1/electra.go b/proto/engine/v1/electra.go index 5b57ef86026d..2ec557b6c268 100644 --- a/proto/engine/v1/electra.go +++ b/proto/engine/v1/electra.go @@ -2,6 +2,7 @@ package enginev1 import ( "fmt" + "math" "sync" "github.com/ethereum/go-ethereum/common/hexutil" @@ -93,6 +94,8 @@ func decodeExecutionRequestList(raw [][]byte, limits ExecutionRequestLimits) (*E // decodeExecutionRequestListGloas decodes the EIP-7685 flat request list into a // gloas ExecutionRequests, including builder deposit/exit requests (EIP-8282). func decodeExecutionRequestListGloas(raw [][]byte, limits ExecutionRequestLimits) (*ExecutionRequestsGloas, error) { + // Gloas removes MAX_DEPOSIT_REQUESTS_PER_PAYLOAD, the EL bounds deposit requests via the gas limit. + limits.Deposits = math.MaxUint64 / uint64(drSize) requests := &ExecutionRequestsGloas{} var prevTypeNum *uint8 for i := range raw { diff --git a/proto/engine/v1/electra_test.go b/proto/engine/v1/electra_test.go index 3f1e43254835..d0e124d3495a 100644 --- a/proto/engine/v1/electra_test.go +++ b/proto/engine/v1/electra_test.go @@ -276,3 +276,23 @@ func TestEmptyExecutionRequestsHashTreeRoot(t *testing.T) { require.NoError(t, err) require.Equal(t, want, got) } + +func TestEmptyExecutionRequestsGloasHashTreeRoot(t *testing.T) { + want, err := (&enginev1.ExecutionRequestsGloas{}).HashTreeRoot() + require.NoError(t, err) + got, err := enginev1.EmptyExecutionRequestsHashTreeRoot() + require.NoError(t, err) + require.Equal(t, want, got) +} + +func TestGetDecodedExecutionRequestsGloas_NoDepositLimit(t *testing.T) { + cfg := params.BeaconConfig() + count := int(cfg.MaxDepositRequestsPerPayload) + 1 + depositRequestBytes := make([]byte, count*(&enginev1.DepositRequest{}).SizeSSZ()) + ebg := &enginev1.ExecutionBundleGloas{ + ExecutionRequests: [][]byte{append([]byte{uint8(enginev1.DepositRequestType)}, depositRequestBytes...)}, + } + requests, err := ebg.GetDecodedExecutionRequests(cfg.ExecutionRequestLimits()) + require.NoError(t, err) + require.Equal(t, count, len(requests.Deposits)) +} From eeab910fa6804a4fcf89ab200ec0f7e8be2c97a4 Mon Sep 17 00:00:00 2001 From: Jun Song Date: Fri, 31 Jul 2026 19:28:56 -0500 Subject: [PATCH 08/23] Set BUILDER_WITHDRAWAL_PREFIX to 0xB0 Align the builder withdrawal credential prefix with the Gloas spec value of 0xB0 in both the mainnet and minimal configs. It was previously 0x03, which collided with the range reserved for future credential types. --- changelog/syjn99_fix-builder-withdrawal-prefix.md | 3 +++ config/params/mainnet_config.go | 2 +- config/params/minimal_config.go | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 changelog/syjn99_fix-builder-withdrawal-prefix.md diff --git a/changelog/syjn99_fix-builder-withdrawal-prefix.md b/changelog/syjn99_fix-builder-withdrawal-prefix.md new file mode 100644 index 000000000000..fa473e0b0d91 --- /dev/null +++ b/changelog/syjn99_fix-builder-withdrawal-prefix.md @@ -0,0 +1,3 @@ +### Fixed + +- Set `BUILDER_WITHDRAWAL_PREFIX` to `0xB0`. diff --git a/config/params/mainnet_config.go b/config/params/mainnet_config.go index 9f7f5414e688..08cc26a92406 100644 --- a/config/params/mainnet_config.go +++ b/config/params/mainnet_config.go @@ -96,7 +96,7 @@ var mainnetBeaconConfig = &BeaconChainConfig{ BLSWithdrawalPrefixByte: byte(0), ETH1AddressWithdrawalPrefixByte: byte(1), CompoundingWithdrawalPrefixByte: byte(2), - BuilderWithdrawalPrefixByte: byte(3), + BuilderWithdrawalPrefixByte: byte(0xB0), PayloadBuilderVersion: byte(0), BuilderIndexSelfBuild: primitives.BuilderIndex(math.MaxUint64), ZeroHash: [32]byte{}, diff --git a/config/params/minimal_config.go b/config/params/minimal_config.go index 70dff04339d9..e18afdbbeb5d 100644 --- a/config/params/minimal_config.go +++ b/config/params/minimal_config.go @@ -31,7 +31,7 @@ func MinimalSpecConfig() *BeaconChainConfig { // Initial values minimalConfig.BLSWithdrawalPrefixByte = byte(0) minimalConfig.ETH1AddressWithdrawalPrefixByte = byte(1) - minimalConfig.BuilderWithdrawalPrefixByte = byte(3) + minimalConfig.BuilderWithdrawalPrefixByte = byte(0xB0) // Time parameters minimalConfig.SecondsPerSlot = 6 From df9d00da83923d7c67056f2ab447dae760562fe8 Mon Sep 17 00:00:00 2001 From: Terence Tsao Date: Fri, 31 Jul 2026 19:30:17 -0500 Subject: [PATCH 09/23] Reduce Gloas builder config bounds Lower MIN_BUILDER_WITHDRAWABILITY_DELAY from 8192 to 64 epochs so an exiting builder's funds are not locked for an impractically long window, and lower MAX_BUILDER_DEPOSIT_REQUESTS_PER_PAYLOAD from 2**8 to 2**6 to match the current Gloas spec. --- changelog/terence_builder-withdrawability-delay-64.md | 3 +++ config/params/mainnet_config.go | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 changelog/terence_builder-withdrawability-delay-64.md diff --git a/changelog/terence_builder-withdrawability-delay-64.md b/changelog/terence_builder-withdrawability-delay-64.md new file mode 100644 index 000000000000..5f58ef1d7cb2 --- /dev/null +++ b/changelog/terence_builder-withdrawability-delay-64.md @@ -0,0 +1,3 @@ +### Changed + +- Reduce `MIN_BUILDER_WITHDRAWABILITY_DELAY` to 64 epochs. diff --git a/config/params/mainnet_config.go b/config/params/mainnet_config.go index 08cc26a92406..bcd6c3087ec7 100644 --- a/config/params/mainnet_config.go +++ b/config/params/mainnet_config.go @@ -112,7 +112,7 @@ var mainnetBeaconConfig = &BeaconChainConfig{ EpochsPerEth1VotingPeriod: 64, SlotsPerHistoricalRoot: 8192, MinValidatorWithdrawabilityDelay: 256, - MinBuilderWithdrawabilityDelay: 8192, + MinBuilderWithdrawabilityDelay: 64, ShardCommitteePeriod: 256, MinEpochsToInactivityPenalty: 4, Eth1FollowDistance: 2048, @@ -369,8 +369,8 @@ var mainnetBeaconConfig = &BeaconChainConfig{ ChurnLimitQuotientGloas: 32_768, ConsolidationChurnLimitQuotient: 65_536, MaxPerEpochActivationChurnLimitGloas: 256_000_000_000, - MaxBuilderDepositRequestsPerPayload: 256, // 2**8 (= 256) - MaxBuilderExitRequestsPerPayload: 16, // 2**4 (= 16) + MaxBuilderDepositRequestsPerPayload: 64, // 2**6 (= 64) + MaxBuilderExitRequestsPerPayload: 16, // 2**4 (= 16) // Values related to networking parameters. MaxPayloadSize: 10 * 1 << 20, // 10 MiB From 48973e38c2bd371c63b4505fd6e48660492de981 Mon Sep 17 00:00:00 2001 From: Terence Tsao Date: Fri, 31 Jul 2026 19:43:14 -0500 Subject: [PATCH 10/23] Set PAYLOAD_DUE_BPS to 5000 Move the payload deadline to the midpoint of the slot so builders have to reveal earlier, giving the PTC more time to attest to timeliness. Note: config/params TestLoadConfigFile now diverges from the pinned consensus-spec fixture, which still carries PAYLOAD_DUE_BPS 7500. This needs the spec test pin to advance before it can merge to develop. --- changelog/terence_payload-due-bps-5000.md | 3 +++ config/params/mainnet_config.go | 2 +- config/params/minimal_config.go | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 changelog/terence_payload-due-bps-5000.md diff --git a/changelog/terence_payload-due-bps-5000.md b/changelog/terence_payload-due-bps-5000.md new file mode 100644 index 000000000000..ee7fc3b4dc7f --- /dev/null +++ b/changelog/terence_payload-due-bps-5000.md @@ -0,0 +1,3 @@ +### Changed + +- Set `PAYLOAD_DUE_BPS` to 5000. diff --git a/config/params/mainnet_config.go b/config/params/mainnet_config.go index bcd6c3087ec7..ec0e26fd2046 100644 --- a/config/params/mainnet_config.go +++ b/config/params/mainnet_config.go @@ -135,7 +135,7 @@ var mainnetBeaconConfig = &BeaconChainConfig{ SyncMessageDueBPSGloas: primitives.BP(2500), ContributionDueBPSGloas: primitives.BP(5000), PayloadAttestationDueBPS: primitives.BP(7500), - PayloadDueBPS: primitives.BP(7500), + PayloadDueBPS: primitives.BP(5000), EquivocationEarlyDueBPS: primitives.BP(7500), // Ethereum PoW parameters. diff --git a/config/params/minimal_config.go b/config/params/minimal_config.go index e18afdbbeb5d..308ec46711ae 100644 --- a/config/params/minimal_config.go +++ b/config/params/minimal_config.go @@ -41,7 +41,7 @@ func MinimalSpecConfig() *BeaconChainConfig { minimalConfig.SyncMessageDueBPSGloas = 2500 minimalConfig.ContributionDueBPSGloas = 5000 minimalConfig.PayloadAttestationDueBPS = 7500 - minimalConfig.PayloadDueBPS = 7500 + minimalConfig.PayloadDueBPS = 5000 minimalConfig.EquivocationEarlyDueBPS = 7500 minimalConfig.MinAttestationInclusionDelay = 1 minimalConfig.SlotsPerEpoch = 8 From 79fdaaa63a7023bbdf6bcdd86f2ffea48ad0f52f Mon Sep 17 00:00:00 2001 From: Kasey Kirkham Date: Thu, 6 Aug 2026 00:52:58 -0500 Subject: [PATCH 11/23] bump ethspecify version to match --- .ethspecify.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ethspecify.yml b/.ethspecify.yml index b04bd210c853..2b4ab97a42e9 100644 --- a/.ethspecify.yml +++ b/.ethspecify.yml @@ -1,4 +1,4 @@ -version: v1.7.0-alpha.11 +version: v1.7.0-alpha.12 style: full specrefs: From 5d13d8dcf546cc2f25bbb291487a84fe2a6dc5c1 Mon Sep 17 00:00:00 2001 From: Kasey Kirkham Date: Thu, 6 Aug 2026 01:11:34 -0500 Subject: [PATCH 12/23] satisfy ethspecify --- .ethspecify.yml | 25 +- .../core/gloas/builder_deposit_request.go | 18 +- beacon-chain/core/gloas/upgrade.go | 34 +- beacon-chain/core/gloas/withdrawals.go | 46 +- beacon-chain/core/transition/gloas.go | 10 +- specrefs/configs.yml | 28 +- specrefs/constants.yml | 16 +- specrefs/containers.yml | 261 +++++----- specrefs/functions.yml | 456 ++++++++++++------ specrefs/presets.yml | 119 +++-- 10 files changed, 629 insertions(+), 384 deletions(-) diff --git a/.ethspecify.yml b/.ethspecify.yml index 2b4ab97a42e9..8451be8cb029 100644 --- a/.ethspecify.yml +++ b/.ethspecify.yml @@ -18,7 +18,6 @@ specrefs: exceptions: presets: # gloas - - BUILDER_PENDING_WITHDRAWALS_LIMIT#gloas - MAX_PAYLOAD_ATTESTATIONS#gloas - PTC_SIZE#gloas @@ -100,6 +99,7 @@ exceptions: # phase0 - Eth1Block#phase0 # fulu + - PartialDataColumnGroupID#fulu - PartialDataColumnHeader#fulu - PartialDataColumnPartsMetadata#fulu - PartialDataColumnSidecar#fulu @@ -253,7 +253,7 @@ exceptions: - get_current_balance_source#phase0 - get_current_target#phase0 - get_current_target_score#phase0 - - get_dependent_root#phase0 + - get_shuffling_dependent_root#phase0 - get_equivocation_score#phase0 - get_fast_confirmation_store#phase0 - get_latest_confirmed#phase0 @@ -478,7 +478,7 @@ exceptions: - get_forkchoice_store#gloas - get_head#gloas - get_indexed_payload_attestation#gloas - - get_dependent_root#gloas + - get_shuffling_dependent_root#gloas - get_next_sync_committee_indices#gloas - get_node_children#gloas - get_node_for_root#gloas @@ -536,7 +536,7 @@ exceptions: - get_builder_withdrawals#gloas - get_builders_sweep_withdrawals#gloas - get_index_for_new_builder#gloas - - get_proposer_preferences_signature#gloas + - get_signed_proposer_preferences#gloas - get_upcoming_proposal_slots#gloas - is_active_builder#gloas - is_builder_index#gloas @@ -559,11 +559,13 @@ exceptions: - block_to_light_client_header#gloas - compute_exit_epoch_and_update_churn#gloas - compute_weak_subjectivity_period#gloas + - current_sync_committee_gindex_at_slot#gloas + - finalized_root_gindex_at_slot#gloas + - next_sync_committee_gindex_at_slot#gloas - get_activation_churn_limit#gloas - get_consolidation_churn_limit#gloas - get_exit_churn_limit#gloas - get_lc_execution_root#gloas - - get_proposer_dependent_root#gloas - is_valid_light_client_header#gloas - process_pending_deposits#gloas - upgrade_lc_bootstrap_to_gloas#gloas @@ -577,8 +579,10 @@ exceptions: - compute_fork_version#heze - get_forkchoice_store#heze - get_inclusion_list_committee_assignment#heze + - get_inclusion_list_bits#heze - get_inclusion_list_committee#heze - get_inclusion_list_signature#heze + - is_inclusion_list_bits_inclusive#heze - get_inclusion_list_store#heze - get_inclusion_list_transactions#heze - is_payload_inclusion_list_satisfied#heze @@ -599,16 +603,21 @@ exceptions: - process_builder_deposit_request#gloas - process_builder_exit_request#gloas # phase0 - - is_epoch_boundary#phase0 + - is_not_epoch_boundary#phase0 presets: # gloas - - BUILDER_PENDING_WITHDRAWALS_LIMIT#gloas - - BUILDER_REGISTRY_LIMIT#gloas + - MAX_ATTESTER_SLASHING_SIZE#gloas - MAX_BUILDERS_PER_WITHDRAWALS_SWEEP#gloas + - MAX_DATA_COLUMN_SIDECAR_SIZE#gloas + - MAX_PARTIAL_DATA_COLUMN_SIDECAR_SIZE#gloas - MAX_PAYLOAD_ATTESTATIONS#gloas + - MAX_SIGNED_AGGREGATE_AND_PROOF_SIZE#gloas + - MAX_SIGNED_EXECUTION_PAYLOAD_BID_SIZE#gloas - PTC_SIZE#gloas # heze - INCLUSION_LIST_COMMITTEE_SIZE#heze + - MAX_SIGNED_EXECUTION_PAYLOAD_BID_SIZE_HEZE#heze + - MAX_SIGNED_INCLUSION_LIST_SIZE#heze # gloas (EIP-8282) - MAX_BUILDER_DEPOSIT_REQUESTS_PER_PAYLOAD#gloas - MAX_BUILDER_EXIT_REQUESTS_PER_PAYLOAD#gloas diff --git a/beacon-chain/core/gloas/builder_deposit_request.go b/beacon-chain/core/gloas/builder_deposit_request.go index 935f02926069..733f26b7c5c9 100644 --- a/beacon-chain/core/gloas/builder_deposit_request.go +++ b/beacon-chain/core/gloas/builder_deposit_request.go @@ -56,15 +56,19 @@ func ProcessBuilderDepositRequests(ctx context.Context, st state.BeaconState, re // processBuilderDepositRequest registers a new builder or tops up an existing one. // -// +// // def process_builder_deposit_request(state: BeaconState, request: BuilderDepositRequest) -> None: +// # Ignore deposits with unexpected withdrawal credential prefixes +// if not is_builder_withdrawal_credential(request.withdrawal_credentials): +// return +// // builder_pubkeys = [b.pubkey for b in state.builders] // if request.pubkey not in builder_pubkeys: // if is_valid_builder_deposit_signature(request): // add_builder_to_registry( // state, // request.pubkey, -// uint8(request.withdrawal_credentials[0]), +// PAYLOAD_BUILDER_VERSION, // ExecutionAddress(request.withdrawal_credentials[12:]), // request.amount, // state.slot, @@ -73,13 +77,13 @@ func ProcessBuilderDepositRequests(ctx context.Context, st state.BeaconState, re // builder_index = BuilderIndex(builder_pubkeys.index(request.pubkey)) // builder = state.builders[builder_index] // -// # Increase balance by deposit amount -// builder.balance += request.amount -// -// # If exited, reset the withdrawable epoch -// if builder.withdrawable_epoch != FAR_FUTURE_EPOCH: +// # If exited and swept, reset the withdrawable epoch +// if builder.withdrawable_epoch != FAR_FUTURE_EPOCH and builder.balance == 0: // epoch = get_current_epoch(state) // builder.withdrawable_epoch = epoch + MIN_BUILDER_WITHDRAWABILITY_DELAY +// +// # Increase balance by deposit amount +// builder.balance += request.amount // func processBuilderDepositRequest(ctx context.Context, st state.BeaconState, request *enginev1.BuilderDepositRequest, status sigStatus) error { if request == nil { diff --git a/beacon-chain/core/gloas/upgrade.go b/beacon-chain/core/gloas/upgrade.go index 4a51e562a693..ba0a33e58cdc 100644 --- a/beacon-chain/core/gloas/upgrade.go +++ b/beacon-chain/core/gloas/upgrade.go @@ -17,7 +17,7 @@ import ( // UpgradeToGloas updates inputs a generic state to return the version Gloas state. // -// +// // def upgrade_to_gloas(pre: fulu.BeaconState) -> BeaconState: // epoch = fulu.get_current_epoch(pre) // @@ -38,17 +38,26 @@ import ( // eth1_data=pre.eth1_data, // eth1_data_votes=pre.eth1_data_votes, // eth1_deposit_index=pre.eth1_deposit_index, -// validators=pre.validators, -// balances=pre.balances, +// # [Modified in Gloas:EIP7688] +// validators=ProgressiveList[Validator](list(pre.validators)), +// # [Modified in Gloas:EIP7688] +// balances=ProgressiveList[Gwei](list(pre.balances)), // randao_mixes=pre.randao_mixes, // slashings=pre.slashings, -// previous_epoch_participation=pre.previous_epoch_participation, -// current_epoch_participation=pre.current_epoch_participation, +// # [Modified in Gloas:EIP7688] +// previous_epoch_participation=ProgressiveList[ParticipationFlags]( +// list(pre.previous_epoch_participation) +// ), +// # [Modified in Gloas:EIP7688] +// current_epoch_participation=ProgressiveList[ParticipationFlags]( +// list(pre.current_epoch_participation) +// ), // justification_bits=pre.justification_bits, // previous_justified_checkpoint=pre.previous_justified_checkpoint, // current_justified_checkpoint=pre.current_justified_checkpoint, // finalized_checkpoint=pre.finalized_checkpoint, -// inactivity_scores=pre.inactivity_scores, +// # [Modified in Gloas:EIP7688] +// inactivity_scores=ProgressiveList[uint64](list(pre.inactivity_scores)), // current_sync_committee=pre.current_sync_committee, // next_sync_committee=pre.next_sync_committee, // # [Modified in Gloas:EIP7732] @@ -64,9 +73,16 @@ import ( // earliest_exit_epoch=pre.earliest_exit_epoch, // consolidation_balance_to_consume=pre.consolidation_balance_to_consume, // earliest_consolidation_epoch=pre.earliest_consolidation_epoch, -// pending_deposits=pre.pending_deposits, -// pending_partial_withdrawals=pre.pending_partial_withdrawals, -// pending_consolidations=pre.pending_consolidations, +// # [Modified in Gloas:EIP7688] +// pending_deposits=ProgressiveList[PendingDeposit](list(pre.pending_deposits)), +// # [Modified in Gloas:EIP7688] +// pending_partial_withdrawals=ProgressiveList[PendingPartialWithdrawal]( +// list(pre.pending_partial_withdrawals) +// ), +// # [Modified in Gloas:EIP7688] +// pending_consolidations=ProgressiveList[PendingConsolidation]( +// list(pre.pending_consolidations) +// ), // proposer_lookahead=pre.proposer_lookahead, // # [New in Gloas:EIP7732] // builders=[], diff --git a/beacon-chain/core/gloas/withdrawals.go b/beacon-chain/core/gloas/withdrawals.go index 13f56ad82ea6..6cabdfc6e8e9 100644 --- a/beacon-chain/core/gloas/withdrawals.go +++ b/beacon-chain/core/gloas/withdrawals.go @@ -11,35 +11,31 @@ import ( // // // def process_withdrawals( -// -// state: BeaconState, -// # [Modified in Gloas:EIP7732] -// # Removed `payload` -// +// state: BeaconState, +// # [Modified in Gloas:EIP7732] +// # Removed `payload` // ) -> None: +// # [New in Gloas:EIP7732] +// # Return early if the parent block is empty +// if state.latest_block_hash != state.latest_execution_payload_bid.block_hash: +// return // -// # [New in Gloas:EIP7732] -// # Return early if the parent block is empty -// if state.latest_block_hash != state.latest_execution_payload_bid.block_hash: -// return -// -// # Get expected withdrawals -// expected = get_expected_withdrawals(state) -// -// # Apply expected withdrawals -// apply_withdrawals(state, expected.withdrawals) +// # Get expected withdrawals +// expected = get_expected_withdrawals(state) // -// # Update withdrawals fields in the state -// update_next_withdrawal_index(state, expected.withdrawals) -// # [New in Gloas:EIP7732] -// update_payload_expected_withdrawals(state, expected.withdrawals) -// # [New in Gloas:EIP7732] -// update_builder_pending_withdrawals(state, expected.processed_builder_withdrawals_count) -// update_pending_partial_withdrawals(state, expected.processed_partial_withdrawals_count) -// # [New in Gloas:EIP7732] -// update_next_withdrawal_builder_index(state, expected.processed_builders_sweep_count) -// update_next_withdrawal_validator_index(state, expected.withdrawals) +// # Apply expected withdrawals +// apply_withdrawals(state, expected.withdrawals) // +// # Update withdrawals fields in the state +// update_next_withdrawal_index(state, expected.withdrawals) +// # [New in Gloas:EIP7732] +// update_payload_expected_withdrawals(state, expected.withdrawals) +// # [New in Gloas:EIP7732] +// update_builder_pending_withdrawals(state, expected.processed_builder_withdrawals_count) +// update_pending_partial_withdrawals(state, expected.processed_partial_withdrawals_count) +// # [New in Gloas:EIP7732] +// update_next_withdrawal_builder_index(state, expected.processed_builders_sweep_count) +// update_next_withdrawal_validator_index(state, expected.withdrawals) // func ProcessWithdrawals(st state.BeaconState) error { // Must be called before ProcessExecutionPayloadBid for the current block. diff --git a/beacon-chain/core/transition/gloas.go b/beacon-chain/core/transition/gloas.go index 675e8cba84cb..514fdffc4e9c 100644 --- a/beacon-chain/core/transition/gloas.go +++ b/beacon-chain/core/transition/gloas.go @@ -20,7 +20,7 @@ import ( // // Spec definition: // -// +// // def process_operations(state: BeaconState, body: BeaconBlockBody) -> None: // assert len(body.deposits) == 0 // @@ -28,6 +28,14 @@ import ( // for operation in operations: // fn(state, operation) // +// # [New in Gloas:EIP7688] +// assert len(body.proposer_slashings) <= MAX_PROPOSER_SLASHINGS +// assert len(body.attester_slashings) <= MAX_ATTESTER_SLASHINGS_ELECTRA +// assert len(body.attestations) <= MAX_ATTESTATIONS_ELECTRA +// assert len(body.voluntary_exits) <= MAX_VOLUNTARY_EXITS +// assert len(body.bls_to_execution_changes) <= MAX_BLS_TO_EXECUTION_CHANGES +// assert len(body.payload_attestations) <= MAX_PAYLOAD_ATTESTATIONS +// // # [Modified in Gloas:EIP7732] // for_ops(body.proposer_slashings, process_proposer_slashing) // for_ops(body.attester_slashings, process_attester_slashing) diff --git a/specrefs/configs.yml b/specrefs/configs.yml index 42e0f7f432d3..93ea6a590211 100644 --- a/specrefs/configs.yml +++ b/specrefs/configs.yml @@ -225,8 +225,8 @@ search: CustodyRequirement\s+uint64.*yaml:"CUSTODY_REQUIREMENT" regex: true spec: | - - CUSTODY_REQUIREMENT = 4 + + CUSTODY_REQUIREMENT: uint64 = 4 - name: DATA_COLUMN_SIDECAR_SUBNET_COUNT#fulu @@ -235,8 +235,8 @@ search: DataColumnSidecarSubnetCount\s+uint64 regex: true spec: | - - DATA_COLUMN_SIDECAR_SUBNET_COUNT = 128 + + DATA_COLUMN_SIDECAR_SUBNET_COUNT: uint64 = 128 - name: DENEB_FORK_EPOCH#deneb @@ -540,8 +540,8 @@ - file: config/params/mainnet_config.go search: MinBuilderWithdrawabilityDelay spec: | - - MIN_BUILDER_WITHDRAWABILITY_DELAY: uint64 = 8192 + + MIN_BUILDER_WITHDRAWABILITY_DELAY: uint64 = 64 - name: MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS#deneb @@ -560,8 +560,8 @@ search: MinEpochsForDataColumnSidecarsRequest\s+primitives.Epoch regex: true spec: | - - MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS = 4096 + + MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS: uint64 = 4096 - name: MIN_GENESIS_ACTIVE_VALIDATOR_COUNT#phase0 @@ -620,8 +620,8 @@ search: NumberOfCustodyGroups\s+uint64 regex: true spec: | - - NUMBER_OF_CUSTODY_GROUPS = 128 + + NUMBER_OF_CUSTODY_GROUPS: uint64 = 128 - name: PAYLOAD_ATTESTATION_DUE_BPS#gloas @@ -640,8 +640,8 @@ search: PayloadDueBPS\s+primitives.BP regex: true spec: | - - PAYLOAD_DUE_BPS: uint64 = 7500 + + PAYLOAD_DUE_BPS: uint64 = 5000 - name: PROPOSER_REORG_CUTOFF_BPS#phase0 @@ -700,8 +700,8 @@ search: SamplesPerSlot\s+uint64 regex: true spec: | - - SAMPLES_PER_SLOT = 8 + + SAMPLES_PER_SLOT: uint64 = 8 - name: SECONDS_PER_ETH1_BLOCK#phase0 diff --git a/specrefs/constants.yml b/specrefs/constants.yml index 6e0313904d2c..e12f36948d0f 100644 --- a/specrefs/constants.yml +++ b/specrefs/constants.yml @@ -84,8 +84,8 @@ - name: BUILDER_WITHDRAWAL_PREFIX#gloas sources: [] spec: | - - BUILDER_WITHDRAWAL_PREFIX: Bytes1 = '0x03' + + BUILDER_WITHDRAWAL_PREFIX: Bytes1 = '0xB0' - name: BYTES_PER_COMMITMENT#deneb @@ -432,8 +432,8 @@ - name: KZG_SETUP_G2_LENGTH#deneb sources: [] spec: | - - KZG_SETUP_G2_LENGTH = 65 + + KZG_SETUP_G2_LENGTH: uint64 = 65 - name: KZG_SETUP_G2_MONOMIAL#deneb @@ -594,8 +594,8 @@ search: SyncCommitteeSubnetCount\s+.*yaml:"SYNC_COMMITTEE_SUBNET_COUNT" regex: true spec: | - - SYNC_COMMITTEE_SUBNET_COUNT = 4 + + SYNC_COMMITTEE_SUBNET_COUNT: uint64 = 2**2 - name: SYNC_REWARD_WEIGHT#altair @@ -624,8 +624,8 @@ search: TargetAggregatorsPerSyncSubcommittee\s+.*yaml:"TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE" regex: true spec: | - - TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE = 2**4 + + TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE: uint64 = 2**4 - name: TIMELY_HEAD_FLAG_INDEX#altair diff --git a/specrefs/containers.yml b/specrefs/containers.yml index 66b57ec341f5..15af0d5bf1d8 100644 --- a/specrefs/containers.yml +++ b/specrefs/containers.yml @@ -40,16 +40,29 @@ - file: proto/prysm/v1alpha1/attestation.proto search: message AttestationElectra { spec: | - + class Attestation(Container): # [Modified in Electra:EIP7549] - aggregation_bits: Bitlist[MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT] + aggregation_bits: AggregationBits data: AttestationData signature: BLSSignature # [New in Electra:EIP7549] committee_bits: Bitvector[MAX_COMMITTEES_PER_SLOT] +- name: Attestation#gloas + sources: + - file: proto/prysm/v1alpha1/attestation.proto + search: message AttestationGloas { + spec: | + + class Attestation(ProgressiveContainer(active_fields=[1] * 4)): # type: ignore + aggregation_bits: AggregationBits + data: AttestationData + signature: BLSSignature + committee_bits: Bitvector[MAX_COMMITTEES_PER_SLOT] + + - name: AttestationData#phase0 sources: - file: proto/eth/v1/attestation.proto @@ -242,20 +255,26 @@ - name: BeaconBlockBody#gloas sources: [] spec: | - - class BeaconBlockBody(Container): + + class BeaconBlockBody(ProgressiveContainer(active_fields=[1] * 13)): # type: ignore randao_reveal: BLSSignature eth1_data: Eth1Data graffiti: Bytes32 - proposer_slashings: List[ProposerSlashing, MAX_PROPOSER_SLASHINGS] - attester_slashings: List[AttesterSlashing, MAX_ATTESTER_SLASHINGS_ELECTRA] - attestations: List[Attestation, MAX_ATTESTATIONS_ELECTRA] - deposits: List[Deposit, MAX_DEPOSITS] - voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS] + # [Modified in Gloas:EIP7688] + proposer_slashings: ProgressiveList[ProposerSlashing] + # [Modified in Gloas:EIP7688] + attester_slashings: ProgressiveList[AttesterSlashing] + # [Modified in Gloas:EIP7688] + attestations: ProgressiveList[Attestation] + # [Modified in Gloas:EIP7688] + deposits: ProgressiveList[Deposit] + # [Modified in Gloas:EIP7688] + voluntary_exits: ProgressiveList[SignedVoluntaryExit] sync_aggregate: SyncAggregate # [Modified in Gloas:EIP7732] # Removed `execution_payload` - bls_to_execution_changes: List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES] + # [Modified in Gloas:EIP7688] + bls_to_execution_changes: ProgressiveList[SignedBLSToExecutionChange] # [Modified in Gloas:EIP7732] # Removed `blob_kzg_commitments` # [Modified in Gloas:EIP7732] @@ -263,7 +282,7 @@ # [New in Gloas:EIP7732] signed_execution_payload_bid: SignedExecutionPayloadBid # [New in Gloas:EIP7732] - payload_attestations: List[PayloadAttestation, MAX_PAYLOAD_ATTESTATIONS] + payload_attestations: ProgressiveList[PayloadAttestation] # [New in Gloas:EIP7732] parent_execution_requests: ExecutionRequests @@ -570,8 +589,8 @@ - name: BeaconState#gloas sources: [] spec: | - - class BeaconState(Container): + + class BeaconState(ProgressiveContainer(active_fields=[1] * 46)): # type: ignore genesis_time: uint64 genesis_validators_root: Root slot: Slot @@ -583,17 +602,22 @@ eth1_data: Eth1Data eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH] eth1_deposit_index: uint64 - validators: List[Validator, VALIDATOR_REGISTRY_LIMIT] - balances: List[Gwei, VALIDATOR_REGISTRY_LIMIT] + # [Modified in Gloas:EIP7688] + validators: ProgressiveList[Validator] + # [Modified in Gloas:EIP7688] + balances: ProgressiveList[Gwei] randao_mixes: Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR] slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] - previous_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] - current_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] + # [Modified in Gloas:EIP7688] + previous_epoch_participation: ProgressiveList[ParticipationFlags] + # [Modified in Gloas:EIP7688] + current_epoch_participation: ProgressiveList[ParticipationFlags] justification_bits: Bitvector[JUSTIFICATION_BITS_LENGTH] previous_justified_checkpoint: Checkpoint current_justified_checkpoint: Checkpoint finalized_checkpoint: Checkpoint - inactivity_scores: List[uint64, VALIDATOR_REGISTRY_LIMIT] + # [Modified in Gloas:EIP7688] + inactivity_scores: ProgressiveList[uint64] current_sync_committee: SyncCommittee next_sync_committee: SyncCommittee # [Modified in Gloas:EIP7732] @@ -609,12 +633,15 @@ earliest_exit_epoch: Epoch consolidation_balance_to_consume: Gwei earliest_consolidation_epoch: Epoch - pending_deposits: List[PendingDeposit, PENDING_DEPOSITS_LIMIT] - pending_partial_withdrawals: List[PendingPartialWithdrawal, PENDING_PARTIAL_WITHDRAWALS_LIMIT] - pending_consolidations: List[PendingConsolidation, PENDING_CONSOLIDATIONS_LIMIT] + # [Modified in Gloas:EIP7688] + pending_deposits: ProgressiveList[PendingDeposit] + # [Modified in Gloas:EIP7688] + pending_partial_withdrawals: ProgressiveList[PendingPartialWithdrawal] + # [Modified in Gloas:EIP7688] + pending_consolidations: ProgressiveList[PendingConsolidation] proposer_lookahead: Vector[ValidatorIndex, (MIN_SEED_LOOKAHEAD + 1) * SLOTS_PER_EPOCH] # [New in Gloas:EIP7732] - builders: List[Builder, BUILDER_REGISTRY_LIMIT] + builders: ProgressiveList[Builder] # [New in Gloas:EIP7732] next_withdrawal_builder_index: BuilderIndex # [New in Gloas:EIP7732] @@ -622,11 +649,11 @@ # [New in Gloas:EIP7732] builder_pending_payments: Vector[BuilderPendingPayment, 2 * SLOTS_PER_EPOCH] # [New in Gloas:EIP7732] - builder_pending_withdrawals: List[BuilderPendingWithdrawal, BUILDER_PENDING_WITHDRAWALS_LIMIT] + builder_pending_withdrawals: ProgressiveList[BuilderPendingWithdrawal] # [New in Gloas:EIP7732] latest_execution_payload_bid: ExecutionPayloadBid # [New in Gloas:EIP7732] - payload_expected_withdrawals: List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD] + payload_expected_withdrawals: ProgressiveList[Withdrawal] # [New in Gloas:EIP7732] ptc_window: Vector[Vector[ValidatorIndex, PTC_SIZE], (2 + MIN_SEED_LOOKAHEAD) * SLOTS_PER_EPOCH] @@ -634,8 +661,8 @@ - name: BeaconState#heze sources: [] spec: | - - class BeaconState(Container): + + class BeaconState(ProgressiveContainer(active_fields=[1] * 46)): # type: ignore genesis_time: uint64 genesis_validators_root: Root slot: Slot @@ -647,22 +674,19 @@ eth1_data: Eth1Data eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH] eth1_deposit_index: uint64 - validators: List[Validator, VALIDATOR_REGISTRY_LIMIT] - balances: List[Gwei, VALIDATOR_REGISTRY_LIMIT] + validators: ProgressiveList[Validator] + balances: ProgressiveList[Gwei] randao_mixes: Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR] slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] - previous_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] - current_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] + previous_epoch_participation: ProgressiveList[ParticipationFlags] + current_epoch_participation: ProgressiveList[ParticipationFlags] justification_bits: Bitvector[JUSTIFICATION_BITS_LENGTH] previous_justified_checkpoint: Checkpoint current_justified_checkpoint: Checkpoint finalized_checkpoint: Checkpoint - inactivity_scores: List[uint64, VALIDATOR_REGISTRY_LIMIT] + inactivity_scores: ProgressiveList[uint64] current_sync_committee: SyncCommittee next_sync_committee: SyncCommittee - # [Modified in Gloas:EIP7732] - # Removed `latest_execution_payload_header` - # [New in Gloas:EIP7732] latest_block_hash: Hash32 next_withdrawal_index: WithdrawalIndex next_withdrawal_validator_index: ValidatorIndex @@ -673,33 +697,26 @@ earliest_exit_epoch: Epoch consolidation_balance_to_consume: Gwei earliest_consolidation_epoch: Epoch - pending_deposits: List[PendingDeposit, PENDING_DEPOSITS_LIMIT] - pending_partial_withdrawals: List[PendingPartialWithdrawal, PENDING_PARTIAL_WITHDRAWALS_LIMIT] - pending_consolidations: List[PendingConsolidation, PENDING_CONSOLIDATIONS_LIMIT] + pending_deposits: ProgressiveList[PendingDeposit] + pending_partial_withdrawals: ProgressiveList[PendingPartialWithdrawal] + pending_consolidations: ProgressiveList[PendingConsolidation] proposer_lookahead: Vector[ValidatorIndex, (MIN_SEED_LOOKAHEAD + 1) * SLOTS_PER_EPOCH] - # [New in Gloas:EIP7732] - builders: List[Builder, BUILDER_REGISTRY_LIMIT] - # [New in Gloas:EIP7732] + builders: ProgressiveList[Builder] next_withdrawal_builder_index: BuilderIndex - # [New in Gloas:EIP7732] execution_payload_availability: Bitvector[SLOTS_PER_HISTORICAL_ROOT] - # [New in Gloas:EIP7732] builder_pending_payments: Vector[BuilderPendingPayment, 2 * SLOTS_PER_EPOCH] - # [New in Gloas:EIP7732] - builder_pending_withdrawals: List[BuilderPendingWithdrawal, BUILDER_PENDING_WITHDRAWALS_LIMIT] - # [New in Gloas:EIP7732] + builder_pending_withdrawals: ProgressiveList[BuilderPendingWithdrawal] + # [Modified in Heze:EIP7805] latest_execution_payload_bid: ExecutionPayloadBid - # [New in Gloas:EIP7732] - payload_expected_withdrawals: List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD] - # [New in Gloas:EIP7732] + payload_expected_withdrawals: ProgressiveList[Withdrawal] ptc_window: Vector[Vector[ValidatorIndex, PTC_SIZE], (2 + MIN_SEED_LOOKAHEAD) * SLOTS_PER_EPOCH] - name: BeaconState#heze sources: [] spec: | - - class BeaconState(Container): + + class BeaconState(ProgressiveContainer(active_fields=[1] * 46)): # type: ignore genesis_time: uint64 genesis_validators_root: Root slot: Slot @@ -711,22 +728,19 @@ eth1_data: Eth1Data eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH] eth1_deposit_index: uint64 - validators: List[Validator, VALIDATOR_REGISTRY_LIMIT] - balances: List[Gwei, VALIDATOR_REGISTRY_LIMIT] + validators: ProgressiveList[Validator] + balances: ProgressiveList[Gwei] randao_mixes: Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR] slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] - previous_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] - current_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] + previous_epoch_participation: ProgressiveList[ParticipationFlags] + current_epoch_participation: ProgressiveList[ParticipationFlags] justification_bits: Bitvector[JUSTIFICATION_BITS_LENGTH] previous_justified_checkpoint: Checkpoint current_justified_checkpoint: Checkpoint finalized_checkpoint: Checkpoint - inactivity_scores: List[uint64, VALIDATOR_REGISTRY_LIMIT] + inactivity_scores: ProgressiveList[uint64] current_sync_committee: SyncCommittee next_sync_committee: SyncCommittee - # [Modified in Gloas:EIP7732] - # Removed `latest_execution_payload_header` - # [New in Gloas:EIP7732] latest_block_hash: Hash32 next_withdrawal_index: WithdrawalIndex next_withdrawal_validator_index: ValidatorIndex @@ -737,25 +751,18 @@ earliest_exit_epoch: Epoch consolidation_balance_to_consume: Gwei earliest_consolidation_epoch: Epoch - pending_deposits: List[PendingDeposit, PENDING_DEPOSITS_LIMIT] - pending_partial_withdrawals: List[PendingPartialWithdrawal, PENDING_PARTIAL_WITHDRAWALS_LIMIT] - pending_consolidations: List[PendingConsolidation, PENDING_CONSOLIDATIONS_LIMIT] + pending_deposits: ProgressiveList[PendingDeposit] + pending_partial_withdrawals: ProgressiveList[PendingPartialWithdrawal] + pending_consolidations: ProgressiveList[PendingConsolidation] proposer_lookahead: Vector[ValidatorIndex, (MIN_SEED_LOOKAHEAD + 1) * SLOTS_PER_EPOCH] - # [New in Gloas:EIP7732] - builders: List[Builder, BUILDER_REGISTRY_LIMIT] - # [New in Gloas:EIP7732] + builders: ProgressiveList[Builder] next_withdrawal_builder_index: BuilderIndex - # [New in Gloas:EIP7732] execution_payload_availability: Bitvector[SLOTS_PER_HISTORICAL_ROOT] - # [New in Gloas:EIP7732] builder_pending_payments: Vector[BuilderPendingPayment, 2 * SLOTS_PER_EPOCH] - # [New in Gloas:EIP7732] - builder_pending_withdrawals: List[BuilderPendingWithdrawal, BUILDER_PENDING_WITHDRAWALS_LIMIT] - # [New in Gloas:EIP7732] + builder_pending_withdrawals: ProgressiveList[BuilderPendingWithdrawal] + # [Modified in Heze:EIP7805] latest_execution_payload_bid: ExecutionPayloadBid - # [New in Gloas:EIP7732] - payload_expected_withdrawals: List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD] - # [New in Gloas:EIP7732] + payload_expected_withdrawals: ProgressiveList[Withdrawal] ptc_window: Vector[Vector[ValidatorIndex, PTC_SIZE], (2 + MIN_SEED_LOOKAHEAD) * SLOTS_PER_EPOCH] @@ -891,13 +898,15 @@ - name: DataColumnSidecar#gloas sources: [] spec: | - + class DataColumnSidecar(Container): index: ColumnIndex - column: List[Cell, MAX_BLOB_COMMITMENTS_PER_BLOCK] + # [Modified in Gloas:EIP7688] + column: ProgressiveList[Cell] # [Modified in Gloas:EIP7732] # Removed `kzg_commitments` - kzg_proofs: List[KZGProof, MAX_BLOB_COMMITMENTS_PER_BLOCK] + # [Modified in Gloas:EIP7688] + kzg_proofs: ProgressiveList[KZGProof] # [Modified in Gloas:EIP7732] # Removed `signed_block_header` # [Modified in Gloas:EIP7732] @@ -1070,8 +1079,8 @@ - name: ExecutionPayload#gloas sources: [] spec: | - - class ExecutionPayload(Container): + + class ExecutionPayload(ProgressiveContainer(active_fields=[1] * 19)): # type: ignore parent_hash: Hash32 fee_recipient: ExecutionAddress state_root: Bytes32 @@ -1085,8 +1094,10 @@ extra_data: ByteList[MAX_EXTRA_DATA_BYTES] base_fee_per_gas: uint256 block_hash: Hash32 - transactions: List[Transaction, MAX_TRANSACTIONS_PER_PAYLOAD] - withdrawals: List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD] + # [Modified in Gloas:EIP7688] + transactions: ProgressiveList[Transaction] + # [Modified in Gloas:EIP7688] + withdrawals: ProgressiveList[Withdrawal] blob_gas_used: uint64 excess_blob_gas: uint64 # [New in Gloas:EIP7928] @@ -1098,8 +1109,8 @@ - name: ExecutionPayloadBid#gloas sources: [] spec: | - - class ExecutionPayloadBid(Container): + + class ExecutionPayloadBid(ProgressiveContainer(active_fields=[1] * 12)): # type: ignore parent_block_hash: Hash32 parent_block_root: Root block_hash: Hash32 @@ -1110,15 +1121,15 @@ slot: Slot value: Gwei execution_payment: Gwei - blob_kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK] + blob_kzg_commitments: ProgressiveList[KZGCommitment] execution_requests_root: Root - name: ExecutionPayloadBid#heze sources: [] spec: | - - class ExecutionPayloadBid(Container): + + class ExecutionPayloadBid(ProgressiveContainer(active_fields=[1] * 13)): # type: ignore parent_block_hash: Hash32 parent_block_root: Root block_hash: Hash32 @@ -1129,15 +1140,17 @@ slot: Slot value: Gwei execution_payment: Gwei - blob_kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK] + blob_kzg_commitments: ProgressiveList[KZGCommitment] execution_requests_root: Root + # [New in Heze:EIP7805] + inclusion_list_bits: Bitvector[INCLUSION_LIST_COMMITTEE_SIZE] - name: ExecutionPayloadEnvelope#gloas sources: [] spec: | - - class ExecutionPayloadEnvelope(Container): + + class ExecutionPayloadEnvelope(ProgressiveContainer(active_fields=[1] * 5)): # type: ignore payload: ExecutionPayload execution_requests: ExecutionRequests builder_index: BuilderIndex @@ -1226,28 +1239,28 @@ - file: proto/engine/v1/electra.proto search: message ExecutionRequests { spec: | - + class ExecutionRequests(Container): # [New in Electra:EIP6110] - deposits: List[DepositRequest, MAX_DEPOSIT_REQUESTS_PER_PAYLOAD] + deposits: DepositRequests # [New in Electra:EIP7002:EIP7251] - withdrawals: List[WithdrawalRequest, MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD] + withdrawals: WithdrawalRequests # [New in Electra:EIP7251] - consolidations: List[ConsolidationRequest, MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD] + consolidations: ConsolidationRequests - name: ExecutionRequests#gloas sources: [] spec: | - - class ExecutionRequests(Container): - deposits: List[DepositRequest, MAX_DEPOSIT_REQUESTS_PER_PAYLOAD] - withdrawals: List[WithdrawalRequest, MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD] - consolidations: List[ConsolidationRequest, MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD] + + class ExecutionRequests(ProgressiveContainer(active_fields=[1] * 5)): # type: ignore + deposits: DepositRequests + withdrawals: WithdrawalRequests + consolidations: ConsolidationRequests # [New in Gloas:EIP8282] - builder_deposits: List[BuilderDepositRequest, MAX_BUILDER_DEPOSIT_REQUESTS_PER_PAYLOAD] + builder_deposits: BuilderDepositRequests # [New in Gloas:EIP8282] - builder_exits: List[BuilderExitRequest, MAX_BUILDER_EXIT_REQUESTS_PER_PAYLOAD] + builder_exits: BuilderExitRequests - name: Fork#phase0 @@ -1298,12 +1311,12 @@ - name: InclusionList#heze sources: [] spec: | - + class InclusionList(Container): slot: Slot validator_index: ValidatorIndex inclusion_list_committee_root: Root - transactions: List[Transaction, MAX_TRANSACTIONS_PER_PAYLOAD] + transactions: ProgressiveList[Transaction] - name: IndexedAttestation#phase0 @@ -1323,10 +1336,22 @@ - file: proto/prysm/v1alpha1/beacon_core_types.proto search: message IndexedAttestationElectra { spec: | - + class IndexedAttestation(Container): # [Modified in Electra:EIP7549] - attesting_indices: List[ValidatorIndex, MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT] + attesting_indices: AttestingIndices + data: AttestationData + signature: BLSSignature + + +- name: IndexedAttestation#gloas + sources: + - file: proto/prysm/v1alpha1/beacon_core_types.proto + search: message IndexedAttestationGloas { + spec: | + + class IndexedAttestation(ProgressiveContainer(active_fields=[1] * 3)): # type: ignore + attesting_indices: AttestingIndices data: AttestationData signature: BLSSignature @@ -1334,8 +1359,8 @@ - name: IndexedPayloadAttestation#gloas sources: [] spec: | - - class IndexedPayloadAttestation(Container): + + class IndexedPayloadAttestation(ProgressiveContainer(active_fields=[1] * 3)): # type: ignore attesting_indices: List[ValidatorIndex, PTC_SIZE] data: PayloadAttestationData signature: BLSSignature @@ -1510,13 +1535,22 @@ row_index: RowIndex +- name: PartialDataColumnGroupID#fulu + sources: [] + spec: | + + class PartialDataColumnGroupID(Container): + beacon_block_root: Root + + - name: PartialDataColumnGroupID#gloas sources: [] spec: | - + class PartialDataColumnGroupID(Container): - slot: Slot beacon_block_root: Root + # [New in Gloas:EIP7732] + slot: Slot - name: PartialDataColumnHeader#fulu @@ -1563,18 +1597,18 @@ - name: PartialDataColumnSidecar#gloas sources: [] spec: | - + class PartialDataColumnSidecar(Container): - cells_present_bitmap: Bitlist[MAX_BLOB_COMMITMENTS_PER_BLOCK] - partial_column: List[Cell, MAX_BLOB_COMMITMENTS_PER_BLOCK] - kzg_proofs: List[KZGProof, MAX_BLOB_COMMITMENTS_PER_BLOCK] + cells_present_bitmap: ProgressiveBitlist + partial_column: ProgressiveList[Cell] + kzg_proofs: ProgressiveList[KZGProof] - name: PayloadAttestation#gloas sources: [] spec: | - - class PayloadAttestation(Container): + + class PayloadAttestation(ProgressiveContainer(active_fields=[1] * 3)): # type: ignore aggregation_bits: Bitvector[PTC_SIZE] data: PayloadAttestationData signature: BLSSignature @@ -1765,8 +1799,9 @@ - name: SignedExecutionPayloadBid#heze sources: [] spec: | - + class SignedExecutionPayloadBid(Container): + # [Modified in Heze:EIP7805] message: ExecutionPayloadBid signature: BLSSignature diff --git a/specrefs/functions.yml b/specrefs/functions.yml index efc7bd7241f6..abc04f28a7ce 100644 --- a/specrefs/functions.yml +++ b/specrefs/functions.yml @@ -199,7 +199,7 @@ - file: beacon-chain/core/gloas/parent_payload.go search: func ApplyParentExecutionPayload( spec: | - + def apply_parent_execution_payload( state: BeaconState, requests: ExecutionRequests, @@ -208,6 +208,11 @@ parent_slot = parent_bid.slot parent_epoch = compute_epoch_at_slot(parent_slot) + assert len(requests.withdrawals) <= MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD + assert len(requests.consolidations) <= MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD + assert len(requests.builder_deposits) <= MAX_BUILDER_DEPOSIT_REQUESTS_PER_PAYLOAD + assert len(requests.builder_exits) <= MAX_BUILDER_EXIT_REQUESTS_PER_PAYLOAD + # Process execution requests from parent's payload. The execution # requests are processed at state.slot (child's slot), not the parent's slot. def for_ops(operations: Sequence[Any], fn: Callable[[BeaconState, Any], None]) -> None: @@ -217,9 +222,7 @@ for_ops(requests.deposits, process_deposit_request) for_ops(requests.withdrawals, process_withdrawal_request) for_ops(requests.consolidations, process_consolidation_request) - # [New in Gloas:EIP8282] for_ops(requests.builder_deposits, process_builder_deposit_request) - # [New in Gloas:EIP8282] for_ops(requests.builder_exits, process_builder_exit_request) # Settle the builder payment @@ -1243,14 +1246,14 @@ - file: beacon-chain/rpc/prysm/v1alpha1/validator/proposer_attestations_electra.go search: func computeOnChainAggregate( spec: | - + def compute_on_chain_aggregate(network_aggregates: Sequence[Attestation]) -> Attestation: aggregates = sorted( network_aggregates, key=lambda a: get_committee_indices(a.committee_bits)[0] ) data = aggregates[0].data - aggregation_bits = Bitlist[MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT]() + aggregation_bits = AggregationBits() for a in aggregates: for b in a.aggregation_bits: aggregation_bits.append(b) @@ -1932,6 +1935,21 @@ return CURRENT_SYNC_COMMITTEE_GINDEX +- name: current_sync_committee_gindex_at_slot#gloas + sources: [] + spec: | + + def current_sync_committee_gindex_at_slot(slot: Slot) -> GeneralizedIndex: + epoch = compute_epoch_at_slot(slot) + + # [Modified in Gloas:EIP7688] + if epoch >= GLOAS_FORK_EPOCH: + return CURRENT_SYNC_COMMITTEE_GINDEX_GLOAS + if epoch >= ELECTRA_FORK_EPOCH: + return CURRENT_SYNC_COMMITTEE_GINDEX_ELECTRA + return CURRENT_SYNC_COMMITTEE_GINDEX + + - name: decrease_balance#phase0 sources: - file: beacon-chain/core/helpers/rewards_penalties.go @@ -2106,6 +2124,21 @@ return FINALIZED_ROOT_GINDEX +- name: finalized_root_gindex_at_slot#gloas + sources: [] + spec: | + + def finalized_root_gindex_at_slot(slot: Slot) -> GeneralizedIndex: + epoch = compute_epoch_at_slot(slot) + + # [Modified in Gloas:EIP7688] + if epoch >= GLOAS_FORK_EPOCH: + return FINALIZED_ROOT_GINDEX_GLOAS + if epoch >= ELECTRA_FORK_EPOCH: + return FINALIZED_ROOT_GINDEX_ELECTRA + return FINALIZED_ROOT_GINDEX + + - name: find_latest_confirmed_descendant#phase0 sources: [] spec: | @@ -3585,40 +3618,6 @@ ) -- name: get_dependent_root#phase0 - sources: [] - spec: | - - def get_dependent_root(store: Store, root: Root) -> Root: - epoch = get_current_store_epoch(store) - if epoch <= MIN_SEED_LOOKAHEAD: - # Genesis block parent - return Root() - - node = ForkChoiceNode(root=root) - dependent_slot = Slot(compute_start_slot_at_epoch(epoch - MIN_SEED_LOOKAHEAD) - 1) - return get_ancestor(store, node, dependent_slot).root - - -- name: get_dependent_root#gloas - sources: [] - spec: | - - def get_dependent_root(store: Store, root: Root) -> Root: - epoch = get_current_store_epoch(store) - if epoch <= MIN_SEED_LOOKAHEAD: - # Genesis block parent - return Root() - - # [Modified in Gloas:EIP7732] - node = ForkChoiceNode( - root=root, - payload_status=PAYLOAD_STATUS_PENDING, - ) - dependent_slot = Slot(compute_start_slot_at_epoch(epoch - MIN_SEED_LOOKAHEAD) - 1) - return get_ancestor(store, node, dependent_slot).root - - - name: get_domain#phase0 sources: - file: beacon-chain/core/signing/domain.go @@ -3832,7 +3831,7 @@ - file: proto/engine/v1/electra.go search: func (ebe *ExecutionBundleElectra) GetDecodedExecutionRequests( spec: | - + def get_execution_requests(execution_requests_list: Sequence[bytes]) -> ExecutionRequests: deposits = [] withdrawals = [] @@ -3858,17 +3857,11 @@ prev_request_type = request_type if request_type == DEPOSIT_REQUEST_TYPE: - deposits = ssz_deserialize( - List[DepositRequest, MAX_DEPOSIT_REQUESTS_PER_PAYLOAD], request_data - ) + deposits = ssz_deserialize(DepositRequests, request_data) elif request_type == WITHDRAWAL_REQUEST_TYPE: - withdrawals = ssz_deserialize( - List[WithdrawalRequest, MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD], request_data - ) + withdrawals = ssz_deserialize(WithdrawalRequests, request_data) elif request_type == CONSOLIDATION_REQUEST_TYPE: - consolidations = ssz_deserialize( - List[ConsolidationRequest, MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD], request_data - ) + consolidations = ssz_deserialize(ConsolidationRequests, request_data) return ExecutionRequests( deposits=deposits, @@ -3880,7 +3873,7 @@ - name: get_execution_requests#gloas sources: [] spec: | - + def get_execution_requests(execution_requests_list: Sequence[bytes]) -> ExecutionRequests: deposits = [] withdrawals = [] @@ -3914,28 +3907,17 @@ prev_request_type = request_type if request_type == DEPOSIT_REQUEST_TYPE: - deposits = ssz_deserialize( - List[DepositRequest, MAX_DEPOSIT_REQUESTS_PER_PAYLOAD], request_data - ) + deposits = ssz_deserialize(DepositRequests, request_data) elif request_type == WITHDRAWAL_REQUEST_TYPE: - withdrawals = ssz_deserialize( - List[WithdrawalRequest, MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD], request_data - ) + withdrawals = ssz_deserialize(WithdrawalRequests, request_data) elif request_type == CONSOLIDATION_REQUEST_TYPE: - consolidations = ssz_deserialize( - List[ConsolidationRequest, MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD], request_data - ) + consolidations = ssz_deserialize(ConsolidationRequests, request_data) # [New in Gloas:EIP8282] elif request_type == BUILDER_DEPOSIT_REQUEST_TYPE: - builder_deposits = ssz_deserialize( - List[BuilderDepositRequest, MAX_BUILDER_DEPOSIT_REQUESTS_PER_PAYLOAD], - request_data, - ) + builder_deposits = ssz_deserialize(BuilderDepositRequests, request_data) # [New in Gloas:EIP8282] elif request_type == BUILDER_EXIT_REQUEST_TYPE: - builder_exits = ssz_deserialize( - List[BuilderExitRequest, MAX_BUILDER_EXIT_REQUESTS_PER_PAYLOAD], request_data - ) + builder_exits = ssz_deserialize(BuilderExitRequests, request_data) return ExecutionRequests( deposits=deposits, @@ -3953,9 +3935,9 @@ - file: proto/engine/v1/electra.go search: func EncodeExecutionRequests( spec: | - + def get_execution_requests_list(execution_requests: ExecutionRequests) -> Sequence[bytes]: - requests = [ + requests: Sequence[Tuple[Bytes1, List]] = [ (DEPOSIT_REQUEST_TYPE, execution_requests.deposits), (WITHDRAWAL_REQUEST_TYPE, execution_requests.withdrawals), (CONSOLIDATION_REQUEST_TYPE, execution_requests.consolidations), @@ -3971,9 +3953,9 @@ - name: get_execution_requests_list#gloas sources: [] spec: | - + def get_execution_requests_list(execution_requests: ExecutionRequests) -> Sequence[bytes]: - requests = [ + requests: Sequence[Tuple[Bytes1, ProgressiveList]] = [ (DEPOSIT_REQUEST_TYPE, execution_requests.deposits), (WITHDRAWAL_REQUEST_TYPE, execution_requests.withdrawals), (CONSOLIDATION_REQUEST_TYPE, execution_requests.consolidations), @@ -4457,6 +4439,36 @@ return rewards, penalties +- name: get_inclusion_list_bits#heze + sources: [] + spec: | + + def get_inclusion_list_bits( + store: InclusionListStore, state: BeaconState, slot: Slot, only_timely: bool = True + ) -> Bitvector[INCLUSION_LIST_COMMITTEE_SIZE]: + """ + Return a ``Bitvector`` over inclusion list committee indices with bits set + for those who provided valid, non-equivocating inclusion lists for the given ``slot``. + """ + committee = get_inclusion_list_committee(state, slot) + key = hash_tree_root(committee) + + inclusion_lists = store.inclusion_lists[key] + equivocators = store.equivocators[key] + timeliness = store.inclusion_list_timeliness + + validator_indices = [ + inclusion_lists[inclusion_list_root].validator_index + for inclusion_list_root in inclusion_lists + if inclusion_lists[inclusion_list_root].validator_index not in equivocators + if not only_timely or timeliness[inclusion_list_root] + ] + + return Bitvector[INCLUSION_LIST_COMMITTEE_SIZE]( + validator_index in validator_indices for validator_index in committee + ) + + - name: get_inclusion_list_committee#heze sources: [] spec: | @@ -5213,23 +5225,10 @@ return GENESIS_EPOCH if current_epoch == GENESIS_EPOCH else Epoch(current_epoch - 1) -- name: get_proposer_dependent_root#gloas - sources: [] - spec: | - - def get_proposer_dependent_root(state: BeaconState, epoch: Epoch) -> Root: - """ - Return the dependent root for the proposer lookahead at ``epoch``. - """ - return get_block_root_at_slot( - state, Slot(compute_start_slot_at_epoch(Epoch(epoch - MIN_SEED_LOOKAHEAD)) - 1) - ) - - - name: get_proposer_head#phase0 sources: [] spec: | - + def get_proposer_head(store: Store, head_node: ForkChoiceNode, slot: Slot) -> ForkChoiceNode: head_block = store.blocks[head_node.root] parent_root = head_block.parent_root @@ -5240,7 +5239,7 @@ head_late = is_head_late(store, head_node.root) # Do not re-org on an epoch boundary. - epoch_boundary = is_epoch_boundary(slot) + not_epoch_boundary = is_not_epoch_boundary(slot) # Ensure that the FFG information of the new head will be competitive with the current head. ffg_competitive = is_ffg_competitive(store, head_node.root, parent_root) @@ -5268,7 +5267,7 @@ if all([ head_late, - epoch_boundary, + not_epoch_boundary, ffg_competitive, finalization_ok, proposing_on_time, @@ -5287,7 +5286,7 @@ - name: get_proposer_head#gloas sources: [] spec: | - + def get_proposer_head(store: Store, head_node: ForkChoiceNode, slot: Slot) -> ForkChoiceNode: head_block = store.blocks[head_node.root] parent_root = head_block.parent_root @@ -5300,7 +5299,7 @@ head_late = is_head_late(store, head_node.root) # Do not re-org on an epoch boundary. - epoch_boundary = is_epoch_boundary(slot) + not_epoch_boundary = is_not_epoch_boundary(slot) # Ensure that the FFG information of the new head will be competitive with the current head. ffg_competitive = is_ffg_competitive(store, head_node.root, parent_root) @@ -5328,7 +5327,7 @@ if all([ head_late, - epoch_boundary, + not_epoch_boundary, ffg_competitive, finalization_ok, proposing_on_time, @@ -5344,20 +5343,6 @@ return head_node -- name: get_proposer_preferences_signature#gloas - sources: [] - spec: | - - def get_proposer_preferences_signature( - state: BeaconState, preferences: ProposerPreferences, privkey: int - ) -> BLSSignature: - domain = get_domain( - state, DOMAIN_PROPOSER_PREFERENCES, compute_epoch_at_slot(preferences.proposal_slot) - ) - signing_root = compute_signing_root(preferences, domain) - return bls.Sign(privkey, signing_root) - - - name: get_proposer_reorg_cutoff_ms#phase0 sources: [] spec: | @@ -6750,14 +6735,6 @@ ) -- name: is_epoch_boundary#phase0 - sources: [] - spec: | - - def is_epoch_boundary(slot: Slot) -> bool: - return slot % SLOTS_PER_EPOCH != 0 - - - name: is_execution_block#bellatrix sources: - file: beacon-chain/core/blocks/payload.go @@ -6942,6 +6919,31 @@ return get_finality_delay(state) > MIN_EPOCHS_TO_INACTIVITY_PENALTY +- name: is_inclusion_list_bits_inclusive#heze + sources: [] + spec: | + + def is_inclusion_list_bits_inclusive( + store: InclusionListStore, + state: BeaconState, + slot: Slot, + inclusion_list_bits: Bitvector[INCLUSION_LIST_COMMITTEE_SIZE], + only_timely: bool = True, + ) -> bool: + """ + Return ``True`` if and only if ``inclusion_list_bits`` has a bit set for + every bit set in the local inclusion list bits for the given ``slot``. + """ + local_inclusion_list_bits = get_inclusion_list_bits(store, state, slot, only_timely) + + return not any( + local_inclusion_bit and not inclusion_bit + for inclusion_bit, local_inclusion_bit in zip( + inclusion_list_bits, local_inclusion_list_bits, strict=True + ) + ) + + - name: is_merge_transition_block#bellatrix sources: [] spec: | @@ -7391,6 +7393,34 @@ return bls.FastAggregateVerify(pubkeys, signing_root, indexed_attestation.signature) +- name: is_valid_indexed_attestation#gloas + sources: + - file: beacon-chain/core/blocks/attestation.go + search: func VerifyIndexedAttestation( + spec: | + + def is_valid_indexed_attestation( + state: BeaconState, indexed_attestation: IndexedAttestation + ) -> bool: + """ + Check if ``indexed_attestation`` is not empty, has sorted and unique indices and has a valid aggregate signature. + """ + # Verify indices are sorted and unique + indices = indexed_attestation.attesting_indices + if ( + len(indices) == 0 + # [New in Gloas:EIP7688] + or len(indices) > MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT + or indices != sorted(set(indices)) + ): + return False + # Verify aggregate signature + pubkeys = [state.validators[i].pubkey for i in indices] + domain = get_domain(state, DOMAIN_BEACON_ATTESTER, indexed_attestation.data.target.epoch) + signing_root = compute_signing_root(indexed_attestation.data, domain) + return bls.FastAggregateVerify(pubkeys, signing_root, indexed_attestation.signature) + + - name: is_valid_indexed_payload_attestation#gloas sources: [] spec: | @@ -7744,6 +7774,21 @@ return NEXT_SYNC_COMMITTEE_GINDEX +- name: next_sync_committee_gindex_at_slot#gloas + sources: [] + spec: | + + def next_sync_committee_gindex_at_slot(slot: Slot) -> GeneralizedIndex: + epoch = compute_epoch_at_slot(slot) + + # [Modified in Gloas:EIP7688] + if epoch >= GLOAS_FORK_EPOCH: + return NEXT_SYNC_COMMITTEE_GINDEX_GLOAS + if epoch >= ELECTRA_FORK_EPOCH: + return NEXT_SYNC_COMMITTEE_GINDEX_ELECTRA + return NEXT_SYNC_COMMITTEE_GINDEX + + - name: normalize_merkle_branch#electra sources: [] spec: | @@ -9057,15 +9102,19 @@ - name: process_builder_deposit_request#gloas sources: [] spec: | - + def process_builder_deposit_request(state: BeaconState, request: BuilderDepositRequest) -> None: + # Ignore deposits with unexpected withdrawal credential prefixes + if not is_builder_withdrawal_credential(request.withdrawal_credentials): + return + builder_pubkeys = [b.pubkey for b in state.builders] if request.pubkey not in builder_pubkeys: if is_valid_builder_deposit_signature(request): add_builder_to_registry( state, request.pubkey, - uint8(request.withdrawal_credentials[0]), + PAYLOAD_BUILDER_VERSION, ExecutionAddress(request.withdrawal_credentials[12:]), request.amount, state.slot, @@ -9074,13 +9123,13 @@ builder_index = BuilderIndex(builder_pubkeys.index(request.pubkey)) builder = state.builders[builder_index] - # Increase balance by deposit amount - builder.balance += request.amount - - # If exited, reset the withdrawable epoch - if builder.withdrawable_epoch != FAR_FUTURE_EPOCH: + # If exited and swept, reset the withdrawable epoch + if builder.withdrawable_epoch != FAR_FUTURE_EPOCH and builder.balance == 0: epoch = get_current_epoch(state) builder.withdrawable_epoch = epoch + MIN_BUILDER_WITHDRAWABILITY_DELAY + + # Increase balance by deposit amount + builder.balance += request.amount - name: process_builder_exit_request#gloas @@ -10304,7 +10353,7 @@ - name: process_operations#gloas sources: [] spec: | - + def process_operations(state: BeaconState, body: BeaconBlockBody) -> None: assert len(body.deposits) == 0 @@ -10312,6 +10361,14 @@ for operation in operations: fn(state, operation) + # [New in Gloas:EIP7688] + assert len(body.proposer_slashings) <= MAX_PROPOSER_SLASHINGS + assert len(body.attester_slashings) <= MAX_ATTESTER_SLASHINGS_ELECTRA + assert len(body.attestations) <= MAX_ATTESTATIONS_ELECTRA + assert len(body.voluntary_exits) <= MAX_VOLUNTARY_EXITS + assert len(body.bls_to_execution_changes) <= MAX_BLS_TO_EXECUTION_CHANGES + assert len(body.payload_attestations) <= MAX_PAYLOAD_ATTESTATIONS + # [Modified in Gloas:EIP7732] for_ops(body.proposer_slashings, process_proposer_slashing) for_ops(body.attester_slashings, process_attester_slashing) @@ -12044,11 +12101,11 @@ - name: update_payload_expected_withdrawals#gloas sources: [] spec: | - + def update_payload_expected_withdrawals( state: BeaconState, withdrawals: Sequence[Withdrawal] ) -> None: - state.payload_expected_withdrawals = List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD](withdrawals) + state.payload_expected_withdrawals = ProgressiveList[Withdrawal](withdrawals) - name: update_pending_partial_withdrawals#electra @@ -12066,11 +12123,14 @@ - name: update_proposer_boost_root#phase0 sources: [] spec: | - + def update_proposer_boost_root(store: Store, head: Root, root: Root) -> None: is_first_block = store.proposer_boost_root == Root() is_timely = store.block_timeliness[root] - is_same_dependent_root = get_dependent_root(store, root) == get_dependent_root(store, head) + epoch = get_current_store_epoch(store) + head_dependent_root = get_shuffling_dependent_root(store, head, epoch) + block_dependent_root = get_shuffling_dependent_root(store, root, epoch) + is_same_dependent_root = head_dependent_root == block_dependent_root # Add proposer score boost if the block is timely, not conflicting with an # existing block, with the same dependent root as the canonical chain head. @@ -12081,12 +12141,15 @@ - name: update_proposer_boost_root#gloas sources: [] spec: | - + def update_proposer_boost_root(store: Store, head: Root, root: Root) -> None: is_first_block = store.proposer_boost_root == Root() # [Modified in Gloas:EIP7732] is_timely = store.block_timeliness[root][ATTESTATION_TIMELINESS_INDEX] - is_same_dependent_root = get_dependent_root(store, root) == get_dependent_root(store, head) + epoch = get_current_store_epoch(store) + head_dependent_root = get_shuffling_dependent_root(store, head, epoch) + block_dependent_root = get_shuffling_dependent_root(store, root, epoch) + is_same_dependent_root = head_dependent_root == block_dependent_root # Add proposer score boost if the block is timely, not conflicting with an # existing block, with the same dependent root as the canonical chain head. @@ -12117,6 +12180,48 @@ store.unrealized_finalized_checkpoint = unrealized_finalized_checkpoint +- name: upgrade_attestation_to_gloas#gloas + sources: + - file: proto/prysm/v1alpha1/attestation.go + search: func AttestationElectraToGloas( + spec: | + + def upgrade_attestation_to_gloas(pre: fulu.Attestation) -> Attestation: + return Attestation( + aggregation_bits=AggregationBits(list(pre.aggregation_bits)), + data=pre.data, + signature=pre.signature, + committee_bits=pre.committee_bits, + ) + + +- name: upgrade_attester_slashing_to_gloas#gloas + sources: + - file: proto/prysm/v1alpha1/attestation.go + search: func AttesterSlashingElectraToGloas( + spec: | + + def upgrade_attester_slashing_to_gloas(pre: fulu.AttesterSlashing) -> AttesterSlashing: + return AttesterSlashing( + attestation_1=upgrade_indexed_attestation_to_gloas(pre.attestation_1), + attestation_2=upgrade_indexed_attestation_to_gloas(pre.attestation_2), + ) + + +- name: upgrade_indexed_attestation_to_gloas#gloas + sources: + - file: proto/prysm/v1alpha1/attestation.go + search: func IndexedAttestationElectraToGloas( + spec: | + + def upgrade_indexed_attestation_to_gloas(pre: fulu.IndexedAttestation) -> IndexedAttestation: + return IndexedAttestation( + attesting_indices=AttestingIndices(list(pre.attesting_indices)), + data=pre.data, + signature=pre.signature, + ) + + - name: upgrade_lc_bootstrap_to_capella#capella sources: [] spec: | @@ -12158,12 +12263,14 @@ - name: upgrade_lc_bootstrap_to_gloas#gloas sources: [] spec: | - + def upgrade_lc_bootstrap_to_gloas(pre: electra.LightClientBootstrap) -> LightClientBootstrap: return LightClientBootstrap( header=upgrade_lc_header_to_gloas(pre.header), current_sync_committee=pre.current_sync_committee, - current_sync_committee_branch=pre.current_sync_committee_branch, + current_sync_committee_branch=normalize_merkle_branch( + pre.current_sync_committee_branch, CURRENT_SYNC_COMMITTEE_GINDEX_GLOAS + ), ) @@ -12218,14 +12325,14 @@ - name: upgrade_lc_finality_update_to_gloas#gloas sources: [] spec: | - + def upgrade_lc_finality_update_to_gloas( pre: electra.LightClientFinalityUpdate, ) -> LightClientFinalityUpdate: return LightClientFinalityUpdate( attested_header=upgrade_lc_header_to_gloas(pre.attested_header), finalized_header=upgrade_lc_header_to_gloas(pre.finalized_header), - finality_branch=pre.finality_branch, + finality_branch=normalize_merkle_branch(pre.finality_branch, FINALIZED_ROOT_GINDEX_GLOAS), sync_aggregate=pre.sync_aggregate, signature_slot=pre.signature_slot, ) @@ -12534,14 +12641,16 @@ - name: upgrade_lc_update_to_gloas#gloas sources: [] spec: | - + def upgrade_lc_update_to_gloas(pre: electra.LightClientUpdate) -> LightClientUpdate: return LightClientUpdate( attested_header=upgrade_lc_header_to_gloas(pre.attested_header), next_sync_committee=pre.next_sync_committee, - next_sync_committee_branch=pre.next_sync_committee_branch, + next_sync_committee_branch=normalize_merkle_branch( + pre.next_sync_committee_branch, NEXT_SYNC_COMMITTEE_GINDEX_GLOAS + ), finalized_header=upgrade_lc_header_to_gloas(pre.finalized_header), - finality_branch=pre.finality_branch, + finality_branch=normalize_merkle_branch(pre.finality_branch, FINALIZED_ROOT_GINDEX_GLOAS), sync_aggregate=pre.sync_aggregate, signature_slot=pre.signature_slot, ) @@ -12950,7 +13059,7 @@ - name: upgrade_to_gloas#gloas sources: [] spec: | - + def upgrade_to_gloas(pre: fulu.BeaconState) -> BeaconState: epoch = fulu.get_current_epoch(pre) @@ -12971,17 +13080,26 @@ eth1_data=pre.eth1_data, eth1_data_votes=pre.eth1_data_votes, eth1_deposit_index=pre.eth1_deposit_index, - validators=pre.validators, - balances=pre.balances, + # [Modified in Gloas:EIP7688] + validators=ProgressiveList[Validator](list(pre.validators)), + # [Modified in Gloas:EIP7688] + balances=ProgressiveList[Gwei](list(pre.balances)), randao_mixes=pre.randao_mixes, slashings=pre.slashings, - previous_epoch_participation=pre.previous_epoch_participation, - current_epoch_participation=pre.current_epoch_participation, + # [Modified in Gloas:EIP7688] + previous_epoch_participation=ProgressiveList[ParticipationFlags]( + list(pre.previous_epoch_participation) + ), + # [Modified in Gloas:EIP7688] + current_epoch_participation=ProgressiveList[ParticipationFlags]( + list(pre.current_epoch_participation) + ), justification_bits=pre.justification_bits, previous_justified_checkpoint=pre.previous_justified_checkpoint, current_justified_checkpoint=pre.current_justified_checkpoint, finalized_checkpoint=pre.finalized_checkpoint, - inactivity_scores=pre.inactivity_scores, + # [Modified in Gloas:EIP7688] + inactivity_scores=ProgressiveList[uint64](list(pre.inactivity_scores)), current_sync_committee=pre.current_sync_committee, next_sync_committee=pre.next_sync_committee, # [Modified in Gloas:EIP7732] @@ -12997,9 +13115,16 @@ earliest_exit_epoch=pre.earliest_exit_epoch, consolidation_balance_to_consume=pre.consolidation_balance_to_consume, earliest_consolidation_epoch=pre.earliest_consolidation_epoch, - pending_deposits=pre.pending_deposits, - pending_partial_withdrawals=pre.pending_partial_withdrawals, - pending_consolidations=pre.pending_consolidations, + # [Modified in Gloas:EIP7688] + pending_deposits=ProgressiveList[PendingDeposit](list(pre.pending_deposits)), + # [Modified in Gloas:EIP7688] + pending_partial_withdrawals=ProgressiveList[PendingPartialWithdrawal]( + list(pre.pending_partial_withdrawals) + ), + # [Modified in Gloas:EIP7688] + pending_consolidations=ProgressiveList[PendingConsolidation]( + list(pre.pending_consolidations) + ), proposer_lookahead=pre.proposer_lookahead, # [New in Gloas:EIP7732] builders=[], @@ -13032,9 +13157,25 @@ - name: upgrade_to_heze#heze sources: [] spec: | - + def upgrade_to_heze(pre: gloas.BeaconState) -> BeaconState: epoch = gloas.get_current_epoch(pre) + latest_execution_payload_bid = ExecutionPayloadBid( + parent_block_hash=pre.latest_execution_payload_bid.parent_block_hash, + parent_block_root=pre.latest_execution_payload_bid.parent_block_root, + block_hash=pre.latest_execution_payload_bid.block_hash, + prev_randao=pre.latest_execution_payload_bid.prev_randao, + fee_recipient=pre.latest_execution_payload_bid.fee_recipient, + gas_limit=pre.latest_execution_payload_bid.gas_limit, + builder_index=pre.latest_execution_payload_bid.builder_index, + slot=pre.latest_execution_payload_bid.slot, + value=pre.latest_execution_payload_bid.value, + execution_payment=pre.latest_execution_payload_bid.execution_payment, + blob_kzg_commitments=pre.latest_execution_payload_bid.blob_kzg_commitments, + execution_requests_root=pre.latest_execution_payload_bid.execution_requests_root, + # [New in Heze:EIP7805] + inclusion_list_bits=Bitvector[INCLUSION_LIST_COMMITTEE_SIZE](), + ) post = BeaconState( genesis_time=pre.genesis_time, @@ -13085,7 +13226,8 @@ execution_payload_availability=pre.execution_payload_availability, builder_pending_payments=pre.builder_pending_payments, builder_pending_withdrawals=pre.builder_pending_withdrawals, - latest_execution_payload_bid=pre.latest_execution_payload_bid, + # [Modified in Heze:EIP7805] + latest_execution_payload_bid=latest_execution_payload_bid, payload_expected_withdrawals=pre.payload_expected_withdrawals, ptc_window=pre.ptc_window, ) @@ -14962,15 +15104,15 @@ - name: validate_partial_data_column_sidecar_gossip#fulu sources: [] spec: | - + def validate_partial_data_column_sidecar_gossip( seen: Seen, store: Store, state: BeaconState, sidecar: PartialDataColumnSidecar, - block_root: Root, - column_index: ColumnIndex, current_time_ms: uint64, + group_id: PartialDataColumnGroupID, + column_index: ColumnIndex, ) -> None: """ Validate a PartialDataColumnSidecar for gossip propagation on a subnet. @@ -14984,11 +15126,11 @@ if not (has_header or has_cells): raise GossipReject("partial message is semantically empty") - # [REJECT] The cell count equals the number of bits set in cells_present_bitmap + # [REJECT] The cell count equals the number of set bits in the bitmap if len(sidecar.partial_column) != num_cells_present: raise GossipReject("number of cells does not match number of set bits") - # [REJECT] The proof count equals the number of bits set in cells_present_bitmap + # [REJECT] The proof count equals the number of set bits in the bitmap if len(sidecar.kzg_proofs) != num_cells_present: raise GossipReject("number of proofs does not match number of set bits") @@ -14997,13 +15139,13 @@ block_header = header.signed_block_header.message # [REJECT] The received header MUST equal any previously validated header for this block - prior_header = seen.partial_data_column_headers.get(block_root) + prior_header = seen.partial_data_column_headers.get(group_id.beacon_block_root) if prior_header is not None and prior_header != header: raise GossipReject("header differs from previously validated header") # [REJECT] The signed_block_header hash matches the partial message's group id - if hash_tree_root(block_header) != block_root: - raise GossipReject("header's block root does not match partial message group id") + if hash_tree_root(block_header) != group_id.beacon_block_root: + raise GossipReject("header's block root does not match group id's block root") # [REJECT] The header's kzg_commitments list is non-empty if len(header.kzg_commitments) == 0: @@ -15063,11 +15205,11 @@ raise GossipReject("header proposer_index does not match expected proposer") # Mark this header as seen - seen.partial_data_column_headers[block_root] = header + seen.partial_data_column_headers[group_id.beacon_block_root] = header if has_cells: # [IGNORE] A valid corresponding PartialDataColumnHeader has been seen - header = seen.partial_data_column_headers.get(block_root) + header = seen.partial_data_column_headers.get(group_id.beacon_block_root) if header is None: raise GossipIgnore("valid corresponding header has not been seen") @@ -15085,11 +15227,11 @@ "corresponding header is not from a slot greater than the latest finalized slot" ) - # [REJECT] The cells_present_bitmap length equals the number of header kzg_commitments + # [REJECT] The cells present bitmap length equals the number of header commitments if len(sidecar.cells_present_bitmap) != len(header.kzg_commitments): raise GossipReject("bitmap length does not match commitments length") - # [REJECT] The sidecar's cell and proof data is valid + # [REJECT] The sidecar's cell and proof data passes KZG verification if not verify_partial_data_column_sidecar_kzg_proofs( sidecar, header.kzg_commitments, column_index ): @@ -15505,11 +15647,11 @@ - name: verify_data_column_sidecar#gloas sources: [] spec: | - + def verify_data_column_sidecar( sidecar: DataColumnSidecar, # [New in Gloas:EIP7732] - kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK], + kzg_commitments: ProgressiveList[KZGCommitment], ) -> bool: """ Verify if the data column sidecar is valid. diff --git a/specrefs/presets.yml b/specrefs/presets.yml index c26f025218eb..c29f90bbfefb 100644 --- a/specrefs/presets.yml +++ b/specrefs/presets.yml @@ -8,20 +8,6 @@ BASE_REWARD_FACTOR: uint64 = 64 -- name: BUILDER_PENDING_WITHDRAWALS_LIMIT#gloas - sources: [] - spec: | - - BUILDER_PENDING_WITHDRAWALS_LIMIT: uint64 = 1048576 - - -- name: BUILDER_REGISTRY_LIMIT#gloas - sources: [] - spec: | - - BUILDER_REGISTRY_LIMIT: uint64 = 1099511627776 - - - name: BYTES_PER_LOGS_BLOOM#bellatrix sources: - file: config/params/config.go @@ -225,8 +211,8 @@ search: MaxAttestations\s+.*yaml:"MAX_ATTESTATIONS" regex: true spec: | - - MAX_ATTESTATIONS = 128 + + MAX_ATTESTATIONS: uint64 = 128 - name: MAX_ATTESTATIONS_ELECTRA#electra @@ -235,8 +221,8 @@ search: MaxAttestationsElectra\s+.*yaml:"MAX_ATTESTATIONS_ELECTRA" regex: true spec: | - - MAX_ATTESTATIONS_ELECTRA = 8 + + MAX_ATTESTATIONS_ELECTRA: uint64 = 8 - name: MAX_ATTESTER_SLASHINGS#phase0 @@ -245,8 +231,8 @@ search: MaxAttesterSlashings\s+.*yaml:"MAX_ATTESTER_SLASHINGS" regex: true spec: | - - MAX_ATTESTER_SLASHINGS = 2 + + MAX_ATTESTER_SLASHINGS: uint64 = 2 - name: MAX_ATTESTER_SLASHINGS_ELECTRA#electra @@ -255,8 +241,15 @@ search: MaxAttesterSlashingsElectra\s+.*yaml:"MAX_ATTESTER_SLASHINGS_ELECTRA" regex: true spec: | - - MAX_ATTESTER_SLASHINGS_ELECTRA = 1 + + MAX_ATTESTER_SLASHINGS_ELECTRA: uint64 = 1 + + +- name: MAX_ATTESTER_SLASHING_SIZE#gloas + sources: [] + spec: | + + MAX_ATTESTER_SLASHING_SIZE: uint64 = 2097616 - name: MAX_BLOB_COMMITMENTS_PER_BLOCK#deneb @@ -275,22 +268,22 @@ search: MaxBlsToExecutionChanges\s+.*yaml:"MAX_BLS_TO_EXECUTION_CHANGES" regex: true spec: | - - MAX_BLS_TO_EXECUTION_CHANGES = 16 + + MAX_BLS_TO_EXECUTION_CHANGES: uint64 = 16 - name: MAX_BUILDERS_PER_WITHDRAWALS_SWEEP#gloas sources: [] spec: | - - MAX_BUILDERS_PER_WITHDRAWALS_SWEEP = 16384 + + MAX_BUILDERS_PER_WITHDRAWALS_SWEEP: uint64 = 16384 - name: MAX_BUILDER_DEPOSIT_REQUESTS_PER_PAYLOAD#gloas sources: [] spec: | - - MAX_BUILDER_DEPOSIT_REQUESTS_PER_PAYLOAD: uint64 = 256 + + MAX_BUILDER_DEPOSIT_REQUESTS_PER_PAYLOAD: uint64 = 64 - name: MAX_BUILDER_EXIT_REQUESTS_PER_PAYLOAD#gloas @@ -340,14 +333,21 @@ MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD: uint64 = 2 +- name: MAX_DATA_COLUMN_SIDECAR_SIZE#gloas + sources: [] + spec: | + + MAX_DATA_COLUMN_SIDECAR_SIZE: uint64 = 8585272 + + - name: MAX_DEPOSITS#phase0 sources: - file: config/params/config.go search: MaxDeposits\s+.*yaml:"MAX_DEPOSITS" regex: true spec: | - - MAX_DEPOSITS = 16 + + MAX_DEPOSITS: uint64 = 16 - name: MAX_DEPOSIT_REQUESTS_PER_PAYLOAD#electra @@ -386,15 +386,22 @@ search: MaxExtraDataBytes\s+.*yaml:"MAX_EXTRA_DATA_BYTES" regex: true spec: | - - MAX_EXTRA_DATA_BYTES = 32 + + MAX_EXTRA_DATA_BYTES: uint64 = 32 + + +- name: MAX_PARTIAL_DATA_COLUMN_SIDECAR_SIZE#gloas + sources: [] + spec: | + + MAX_PARTIAL_DATA_COLUMN_SIDECAR_SIZE: uint64 = 8585741 - name: MAX_PAYLOAD_ATTESTATIONS#gloas sources: [] spec: | - - MAX_PAYLOAD_ATTESTATIONS = 4 + + MAX_PAYLOAD_ATTESTATIONS: uint64 = 4 - name: MAX_PENDING_DEPOSITS_PER_EPOCH#electra @@ -423,8 +430,8 @@ search: MaxProposerSlashings\s+.*yaml:"MAX_PROPOSER_SLASHINGS" regex: true spec: | - - MAX_PROPOSER_SLASHINGS = 16 + + MAX_PROPOSER_SLASHINGS: uint64 = 16 - name: MAX_SEED_LOOKAHEAD#phase0 @@ -437,6 +444,34 @@ MAX_SEED_LOOKAHEAD: uint64 = 4 +- name: MAX_SIGNED_AGGREGATE_AND_PROOF_SIZE#gloas + sources: [] + spec: | + + MAX_SIGNED_AGGREGATE_AND_PROOF_SIZE: uint64 = 16829 + + +- name: MAX_SIGNED_EXECUTION_PAYLOAD_BID_SIZE#gloas + sources: [] + spec: | + + MAX_SIGNED_EXECUTION_PAYLOAD_BID_SIZE: uint64 = 196932 + + +- name: MAX_SIGNED_EXECUTION_PAYLOAD_BID_SIZE_HEZE#heze + sources: [] + spec: | + + MAX_SIGNED_EXECUTION_PAYLOAD_BID_SIZE_HEZE: uint64 = 196934 + + +- name: MAX_SIGNED_INCLUSION_LIST_SIZE#heze + sources: [] + spec: | + + MAX_SIGNED_INCLUSION_LIST_SIZE: uint64 = 8348 + + - name: MAX_TRANSACTIONS_PER_PAYLOAD#bellatrix sources: - file: config/params/config.go @@ -473,8 +508,8 @@ search: MaxValidatorsPerWithdrawalsSweep\s+.*yaml:"MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP" regex: true spec: | - - MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP = 16384 + + MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP: uint64 = 16384 - name: MAX_VOLUNTARY_EXITS#phase0 @@ -483,8 +518,8 @@ search: MaxVoluntaryExits\s+.*yaml:"MAX_VOLUNTARY_EXITS" regex: true spec: | - - MAX_VOLUNTARY_EXITS = 16 + + MAX_VOLUNTARY_EXITS: uint64 = 16 - name: MAX_WITHDRAWALS_PER_PAYLOAD#capella @@ -613,8 +648,8 @@ search: NumberOfColumns\s*= regex: true spec: | - - NUMBER_OF_COLUMNS: uint64 = 128 + + NUMBER_OF_COLUMNS = 128 - name: PENDING_CONSOLIDATIONS_LIMIT#electra From 6c6680ca4442ae6e0eed04a6b848b9d1e2992936 Mon Sep 17 00:00:00 2001 From: Kasey Kirkham Date: Thu, 6 Aug 2026 02:41:09 -0500 Subject: [PATCH 13/23] gofmt --- beacon-chain/core/gloas/withdrawals.go | 46 ++++++++++++++------------ 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/beacon-chain/core/gloas/withdrawals.go b/beacon-chain/core/gloas/withdrawals.go index 6cabdfc6e8e9..13f56ad82ea6 100644 --- a/beacon-chain/core/gloas/withdrawals.go +++ b/beacon-chain/core/gloas/withdrawals.go @@ -11,31 +11,35 @@ import ( // // // def process_withdrawals( -// state: BeaconState, -// # [Modified in Gloas:EIP7732] -// # Removed `payload` +// +// state: BeaconState, +// # [Modified in Gloas:EIP7732] +// # Removed `payload` +// // ) -> None: -// # [New in Gloas:EIP7732] -// # Return early if the parent block is empty -// if state.latest_block_hash != state.latest_execution_payload_bid.block_hash: -// return // -// # Get expected withdrawals -// expected = get_expected_withdrawals(state) +// # [New in Gloas:EIP7732] +// # Return early if the parent block is empty +// if state.latest_block_hash != state.latest_execution_payload_bid.block_hash: +// return +// +// # Get expected withdrawals +// expected = get_expected_withdrawals(state) +// +// # Apply expected withdrawals +// apply_withdrawals(state, expected.withdrawals) // -// # Apply expected withdrawals -// apply_withdrawals(state, expected.withdrawals) +// # Update withdrawals fields in the state +// update_next_withdrawal_index(state, expected.withdrawals) +// # [New in Gloas:EIP7732] +// update_payload_expected_withdrawals(state, expected.withdrawals) +// # [New in Gloas:EIP7732] +// update_builder_pending_withdrawals(state, expected.processed_builder_withdrawals_count) +// update_pending_partial_withdrawals(state, expected.processed_partial_withdrawals_count) +// # [New in Gloas:EIP7732] +// update_next_withdrawal_builder_index(state, expected.processed_builders_sweep_count) +// update_next_withdrawal_validator_index(state, expected.withdrawals) // -// # Update withdrawals fields in the state -// update_next_withdrawal_index(state, expected.withdrawals) -// # [New in Gloas:EIP7732] -// update_payload_expected_withdrawals(state, expected.withdrawals) -// # [New in Gloas:EIP7732] -// update_builder_pending_withdrawals(state, expected.processed_builder_withdrawals_count) -// update_pending_partial_withdrawals(state, expected.processed_partial_withdrawals_count) -// # [New in Gloas:EIP7732] -// update_next_withdrawal_builder_index(state, expected.processed_builders_sweep_count) -// update_next_withdrawal_validator_index(state, expected.withdrawals) // func ProcessWithdrawals(st state.BeaconState) error { // Must be called before ProcessExecutionPayloadBid for the current block. From 9a17e27cdafa0518b1d6b2a42af7161f564781e8 Mon Sep 17 00:00:00 2001 From: Kasey Kirkham Date: Thu, 6 Aug 2026 03:14:28 -0500 Subject: [PATCH 14/23] skip unused PartialDataColumnGroupID type in spectests --- testing/spectest/shared/fulu/ssz_static/ssz_static.go | 7 +------ testing/spectest/shared/gloas/ssz_static/ssz_static.go | 4 ++-- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/testing/spectest/shared/fulu/ssz_static/ssz_static.go b/testing/spectest/shared/fulu/ssz_static/ssz_static.go index 8c2297ac1ee3..9bb91aec2463 100644 --- a/testing/spectest/shared/fulu/ssz_static/ssz_static.go +++ b/testing/spectest/shared/fulu/ssz_static/ssz_static.go @@ -67,9 +67,6 @@ func UnmarshalledSSZ(t *testing.T, serializedBytes []byte, folderName string) (a obj = ðpb.Deposit_Data{} case "Eth1Data": obj = ðpb.Eth1Data{} - case "Eth1Block": - t.Skip("Unused type") - return nil, nil case "Fork": obj = ðpb.Fork{} case "ForkData": @@ -154,10 +151,8 @@ func UnmarshalledSSZ(t *testing.T, serializedBytes []byte, folderName string) (a obj = ðpb.DataColumnSidecar{} case "DataColumnsByRootIdentifier": obj = ðpb.DataColumnsByRootIdentifier{} - case "MatrixEntry": + case "MatrixEntry", "Eth1Block", "PartialDataColumnHeader", "PartialDataColumnPartsMetadata", "PartialDataColumnSidecar", "PartialDataColumnGroupID": t.Skip("Unused type") - case "PartialDataColumnHeader", "PartialDataColumnPartsMetadata", "PartialDataColumnSidecar": - t.Skip("Not yet implemented") default: return nil, errors.New("type not found") } diff --git a/testing/spectest/shared/gloas/ssz_static/ssz_static.go b/testing/spectest/shared/gloas/ssz_static/ssz_static.go index 1940107af20b..34acae1baaf2 100644 --- a/testing/spectest/shared/gloas/ssz_static/ssz_static.go +++ b/testing/spectest/shared/gloas/ssz_static/ssz_static.go @@ -89,7 +89,7 @@ func unmarshalledSSZ(t *testing.T, serializedBytes []byte, folderName string) (a t.Skip("Not a consensus type") case "DataColumnSidecar": obj = ðpb.DataColumnSidecarGloas{} - case "SignedProposerPreferences", "ProposerPreferences": + case "SignedProposerPreferences", "ProposerPreferences", "PartialDataColumnGroupID": t.Skip("p2p-only type; not part of the consensus state transition") // Standard types that also exist in gloas @@ -199,7 +199,7 @@ func unmarshalledSSZ(t *testing.T, serializedBytes []byte, folderName string) (a obj = ðpb.DataColumnsByRootIdentifier{} case "MatrixEntry": t.Skip("Unused type") - case "PartialDataColumnHeader", "PartialDataColumnPartsMetadata", "PartialDataColumnSidecar", "PartialDataColumnGroupID": + case "PartialDataColumnHeader", "PartialDataColumnPartsMetadata", "PartialDataColumnSidecar": t.Skip("Not yet implemented") default: return nil, errors.New("type not found") From 3bca32cbe0730bbf4d8f52d64e9341722bfcc0d7 Mon Sep 17 00:00:00 2001 From: terence Date: Wed, 29 Jul 2026 20:38:17 -0700 Subject: [PATCH 15/23] Look up payload availability at the parent block's slot The Gloas payload matching check read execution_payload_availability at data.slot, which is not the slot of the attested block when slots are skipped. Attestations to a skipped slot with data.index == 1 therefore never earned the timely head flag. --- beacon-chain/core/altair/attestation.go | 25 +++- beacon-chain/core/altair/attestation_test.go | 36 +++++- beacon-chain/core/altair/upgrade.go | 3 +- beacon-chain/core/electra/BUILD.bazel | 1 + beacon-chain/core/electra/attestation.go | 8 +- beacon-chain/core/gloas/attestation.go | 27 +++- beacon-chain/core/gloas/attestation_test.go | 119 +++++++++++++----- beacon-chain/core/transition/gloas.go | 5 +- .../core/transition/gloas_operations_test.go | 4 +- .../core/transition/transition_fuzz_test.go | 2 +- .../transition/transition_no_verify_sig.go | 14 ++- .../transition_no_verify_sig_test.go | 6 +- ...ce_att-payload-availability-parent-slot.md | 3 + 13 files changed, 199 insertions(+), 54 deletions(-) create mode 100644 changelog/terence_att-payload-availability-parent-slot.md diff --git a/beacon-chain/core/altair/attestation.go b/beacon-chain/core/altair/attestation.go index ae200ff7ddf9..40dec8fe1d0e 100644 --- a/beacon-chain/core/altair/attestation.go +++ b/beacon-chain/core/altair/attestation.go @@ -22,10 +22,27 @@ import ( // ProcessAttestationsNoVerifySignature applies processing operations to a block's inner attestation // records. The only difference would be that the attestation signature would not be verified. +// +// Callers inside Gloas block processing must use ProcessAttestationsNoVerifySignatureWithParentSlot instead. func ProcessAttestationsNoVerifySignature( ctx context.Context, beaconState state.BeaconState, b interfaces.ReadOnlyBeaconBlock, +) (state.BeaconState, error) { + parentSlot, err := gloas.ParentSlotFromBid(beaconState) + if err != nil { + return nil, err + } + return ProcessAttestationsNoVerifySignatureWithParentSlot(ctx, beaconState, b, parentSlot) +} + +// ProcessAttestationsNoVerifySignatureWithParentSlot takes the parent block's slot explicitly, for +// Gloas block processing where the bid in state has already been replaced by the current block's. +func ProcessAttestationsNoVerifySignatureWithParentSlot( + ctx context.Context, + beaconState state.BeaconState, + b interfaces.ReadOnlyBeaconBlock, + parentSlot primitives.Slot, ) (state.BeaconState, error) { ctx, span := trace.StartSpan(ctx, "altair.ProcessAttestationsNoVerifySignature") defer span.End() @@ -42,7 +59,7 @@ func ProcessAttestationsNoVerifySignature( return nil, err } for idx, att := range body.Attestations() { - beaconState, err = ProcessAttestationNoVerifySignature(ctx, beaconState, att, totalBalance) + beaconState, err = ProcessAttestationNoVerifySignature(ctx, beaconState, att, totalBalance, parentSlot) if err != nil { return nil, errors.Wrapf(err, "could not verify attestation at index %d in block", idx) } @@ -57,6 +74,7 @@ func ProcessAttestationNoVerifySignature( beaconState state.BeaconState, att ethpb.Att, totalBalance uint64, + parentSlot primitives.Slot, ) (state.BeaconState, error) { ctx, span := trace.StartSpan(ctx, "altair.ProcessAttestationNoVerifySignature") defer span.End() @@ -69,7 +87,7 @@ func ProcessAttestationNoVerifySignature( if err != nil { return nil, fmt.Errorf("att slot %d can't be greater than state slot %d", att.GetData().Slot, beaconState.Slot()) } - participatedFlags, err := AttestationParticipationFlagIndices(beaconState, att.GetData(), delay) + participatedFlags, err := AttestationParticipationFlagIndices(beaconState, att.GetData(), delay, parentSlot) if err != nil { return nil, err } @@ -280,7 +298,7 @@ func RewardProposer(ctx context.Context, beaconState state.BeaconState, proposer // participation_flag_indices.append(TIMELY_HEAD_FLAG_INDEX) // // return participation_flag_indices -func AttestationParticipationFlagIndices(beaconState state.ReadOnlyBeaconState, data *ethpb.AttestationData, delay primitives.Slot) (map[uint8]bool, error) { +func AttestationParticipationFlagIndices(beaconState state.ReadOnlyBeaconState, data *ethpb.AttestationData, delay primitives.Slot, parentSlot primitives.Slot) (map[uint8]bool, error) { currEpoch := time.CurrentEpoch(beaconState) var justifiedCheckpt *ethpb.Checkpoint if data.Target.Epoch == currEpoch { @@ -319,6 +337,7 @@ func AttestationParticipationFlagIndices(beaconState state.ReadOnlyBeaconState, beaconState, beaconBlockRoot, data.Slot, + parentSlot, uint64(data.CommitteeIndex), ) if err != nil { diff --git a/beacon-chain/core/altair/attestation_test.go b/beacon-chain/core/altair/attestation_test.go index 95a2397e7574..fa81041a424f 100644 --- a/beacon-chain/core/altair/attestation_test.go +++ b/beacon-chain/core/altair/attestation_test.go @@ -315,7 +315,7 @@ func TestProcessAttestationNoVerify_SourceTargetHead(t *testing.T) { b, err := helpers.TotalActiveBalance(t.Context(), beaconState) require.NoError(t, err) - beaconState, err = altair.ProcessAttestationNoVerifySignature(t.Context(), beaconState, att, b) + beaconState, err = altair.ProcessAttestationNoVerifySignature(t.Context(), beaconState, att, b, 0) require.NoError(t, err) p, err := beaconState.CurrentEpochParticipation() @@ -689,6 +689,7 @@ func TestAttestationParticipationFlagIndices(t *testing.T) { inputState state.BeaconState inputData *ethpb.AttestationData inputDelay primitives.Slot + inputParentSlot primitives.Slot participationIndices map[uint8]bool }{ { @@ -820,7 +821,36 @@ func TestAttestationParticipationFlagIndices(t *testing.T) { Root: bytes.Repeat([]byte{0xAA}, 32), }, }, - inputDelay: 1, + inputDelay: 1, + inputParentSlot: 3, + participationIndices: map[uint8]bool{ + sourceFlagIndex: true, + targetFlagIndex: true, + headFlagIndex: true, + }, + }, + { + name: "gloas skipped data slot uses parent slot availability", + inputState: func() state.BeaconState { + stateSlot := primitives.Slot(5) + slot := primitives.Slot(4) + targetRoot := bytes.Repeat([]byte{0xAA}, 32) + headRoot := bytes.Repeat([]byte{0xBB}, 32) + // Slot 4 was skipped so it inherits slot 3's root, and slot 3 is where the revealed payload is recorded. + return buildGloasStateForFlags(t, stateSlot, slot, targetRoot, headRoot, headRoot, 1, 3) + }(), + inputData: ðpb.AttestationData{ + Slot: 4, + CommitteeIndex: 1, + BeaconBlockRoot: bytes.Repeat([]byte{0xBB}, 32), + Source: ðpb.Checkpoint{Root: bytes.Repeat([]byte{0xDD}, 32)}, + Target: ðpb.Checkpoint{ + Epoch: 0, + Root: bytes.Repeat([]byte{0xAA}, 32), + }, + }, + inputDelay: 1, + inputParentSlot: 3, participationIndices: map[uint8]bool{ sourceFlagIndex: true, targetFlagIndex: true, @@ -829,7 +859,7 @@ func TestAttestationParticipationFlagIndices(t *testing.T) { }, } for _, test := range tests { - flagIndices, err := altair.AttestationParticipationFlagIndices(test.inputState, test.inputData, test.inputDelay) + flagIndices, err := altair.AttestationParticipationFlagIndices(test.inputState, test.inputData, test.inputDelay, test.inputParentSlot) if test.participationIndices == nil { require.ErrorContains(t, "committee index", err) continue diff --git a/beacon-chain/core/altair/upgrade.go b/beacon-chain/core/altair/upgrade.go index 39f64b099d05..5e3679624005 100644 --- a/beacon-chain/core/altair/upgrade.go +++ b/beacon-chain/core/altair/upgrade.go @@ -154,7 +154,8 @@ func TranslateParticipation(ctx context.Context, state state.BeaconState, atts [ } for _, att := range atts { - participatedFlags, err := AttestationParticipationFlagIndices(state, att.Data, att.InclusionDelay) + // The parent slot is unused, the phase0 state being upgraded has no payload availability. + participatedFlags, err := AttestationParticipationFlagIndices(state, att.Data, att.InclusionDelay, 0) if err != nil { return nil, err } diff --git a/beacon-chain/core/electra/BUILD.bazel b/beacon-chain/core/electra/BUILD.bazel index 86ddece76b3d..71d43d203172 100644 --- a/beacon-chain/core/electra/BUILD.bazel +++ b/beacon-chain/core/electra/BUILD.bazel @@ -21,6 +21,7 @@ go_library( "//beacon-chain/core/altair:go_default_library", "//beacon-chain/core/epoch:go_default_library", "//beacon-chain/core/epoch/precompute:go_default_library", + "//beacon-chain/core/gloas:go_default_library", "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/core/signing:go_default_library", "//beacon-chain/core/time:go_default_library", diff --git a/beacon-chain/core/electra/attestation.go b/beacon-chain/core/electra/attestation.go index d09baf7af3c1..9e37162c9189 100644 --- a/beacon-chain/core/electra/attestation.go +++ b/beacon-chain/core/electra/attestation.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/OffchainLabs/prysm/v7/beacon-chain/core/altair" + "github.com/OffchainLabs/prysm/v7/beacon-chain/core/gloas" "github.com/OffchainLabs/prysm/v7/beacon-chain/core/helpers" "github.com/OffchainLabs/prysm/v7/beacon-chain/core/time" "github.com/OffchainLabs/prysm/v7/beacon-chain/state" @@ -33,7 +34,12 @@ func GetProposerRewardNumerator( return 0, fmt.Errorf("attestation slot %d exceeds state slot %d", data.Slot, st.Slot()) } - flags, err := altair.AttestationParticipationFlagIndices(st, data, delay) + parentSlot, err := gloas.ParentSlotFromBid(st) + if err != nil { + return 0, err + } + + flags, err := altair.AttestationParticipationFlagIndices(st, data, delay, parentSlot) if err != nil { return 0, err } diff --git a/beacon-chain/core/gloas/attestation.go b/beacon-chain/core/gloas/attestation.go index ba83e105d856..3f3f0ae91ba3 100644 --- a/beacon-chain/core/gloas/attestation.go +++ b/beacon-chain/core/gloas/attestation.go @@ -20,20 +20,21 @@ import ( // assert data.index == 0 // payload_matches = True // else: -// slot_index = data.slot % SLOTS_PER_HISTORICAL_ROOT +// slot_index = parent_slot % SLOTS_PER_HISTORICAL_ROOT // payload_index = state.execution_payload_availability[slot_index] // payload_matches = data.index == payload_index func MatchingPayload( beaconState state.ReadOnlyBeaconState, beaconBlockRoot [32]byte, - slot primitives.Slot, + dataSlot primitives.Slot, + parentSlot primitives.Slot, committeeIndex uint64, ) (bool, error) { if beaconState.Version() < version.Gloas { return true, nil } - sameSlot, err := beaconState.IsAttestationSameSlot(beaconBlockRoot, slot) + sameSlot, err := beaconState.IsAttestationSameSlot(beaconBlockRoot, dataSlot) if err != nil { return false, errors.Wrap(err, "failed to get same slot attestation status") } @@ -44,9 +45,27 @@ func MatchingPayload( return true, nil } - executionPayloadAvail, err := beaconState.ExecutionPayloadAvailability(slot) + // The attested block is the parent whenever the head flag can apply, so its availability bit lives at parentSlot, not at a skipped dataSlot. + executionPayloadAvail, err := beaconState.ExecutionPayloadAvailability(parentSlot) if err != nil { return false, errors.Wrap(err, "failed to get execution payload availability status") } return executionPayloadAvail == committeeIndex, nil } + +// ParentSlotFromBid returns the parent block's slot from the bid cached in state. +// Not valid inside block processing, ProcessExecutionPayloadBid replaces the bid with the current block's. +func ParentSlotFromBid(beaconState state.ReadOnlyBeaconState) (primitives.Slot, error) { + if beaconState.Version() < version.Gloas { + return 0, nil + } + + bid, err := beaconState.LatestExecutionPayloadBid() + if err != nil { + return 0, errors.Wrap(err, "failed to get latest execution payload bid") + } + if bid == nil { + return 0, nil + } + return bid.Slot(), nil +} diff --git a/beacon-chain/core/gloas/attestation_test.go b/beacon-chain/core/gloas/attestation_test.go index c3d52480d444..08748e4ba06f 100644 --- a/beacon-chain/core/gloas/attestation_test.go +++ b/beacon-chain/core/gloas/attestation_test.go @@ -31,12 +31,43 @@ func buildStateWithBlockRoots(t *testing.T, stateSlot primitives.Slot, roots map return state.(*state_native.BeaconState) } +func buildStateWithAvailability(t *testing.T, stateSlot primitives.Slot, roots map[primitives.Slot][]byte, availableSlots ...primitives.Slot) *state_native.BeaconState { + t.Helper() + + cfg := params.BeaconConfig() + blockRoots := make([][]byte, cfg.SlotsPerHistoricalRoot) + for slot, root := range roots { + blockRoots[slot%cfg.SlotsPerHistoricalRoot] = root + } + + availability := make([]byte, cfg.SlotsPerHistoricalRoot/8) + for _, slot := range availableSlots { + idx := uint64(slot % cfg.SlotsPerHistoricalRoot) + availability[idx/8] |= byte(1 << (idx % 8)) + } + + stIface, err := state_native.InitializeFromProtoGloas(ðpb.BeaconStateGloas{ + Slot: stateSlot, + BlockRoots: blockRoots, + ExecutionPayloadAvailability: availability, + Fork: ðpb.Fork{ + CurrentVersion: bytes.Repeat([]byte{0x66}, 4), + PreviousVersion: bytes.Repeat([]byte{0x66}, 4), + Epoch: 0, + }, + }) + require.NoError(t, err) + st := stIface.(*state_native.BeaconState) + require.Equal(t, version.Gloas, st.Version()) + return st +} + func TestMatchingPayload(t *testing.T) { t.Run("pre-gloas always true", func(t *testing.T) { stIface, err := state_native.InitializeFromProtoElectra(ðpb.BeaconStateElectra{}) require.NoError(t, err) - ok, err := MatchingPayload(stIface, [32]byte{}, 0, 123) + ok, err := MatchingPayload(stIface, [32]byte{}, 0, 0, 123) require.NoError(t, err) require.Equal(t, true, ok) }) @@ -51,7 +82,7 @@ func TestMatchingPayload(t *testing.T) { var rootArr [32]byte copy(rootArr[:], root) - ok, err := MatchingPayload(state, rootArr, 4, 1) + ok, err := MatchingPayload(state, rootArr, 4, 3, 1) require.ErrorContains(t, "committee index", err) require.Equal(t, false, ok) }) @@ -66,45 +97,71 @@ func TestMatchingPayload(t *testing.T) { var rootArr [32]byte copy(rootArr[:], root) - ok, err := MatchingPayload(state, rootArr, 4, 0) + ok, err := MatchingPayload(state, rootArr, 4, 3, 0) require.NoError(t, err) require.Equal(t, true, ok) }) - t.Run("non same slot checks payload availability", func(t *testing.T) { - cfg := params.BeaconConfig() - root := bytes.Repeat([]byte{0xAA}, 32) - blockRoots := make([][]byte, cfg.SlotsPerHistoricalRoot) - blockRoots[4%cfg.SlotsPerHistoricalRoot] = bytes.Repeat([]byte{0xCC}, 32) - blockRoots[3%cfg.SlotsPerHistoricalRoot] = bytes.Repeat([]byte{0xBB}, 32) - - availability := make([]byte, cfg.SlotsPerHistoricalRoot/8) - slotIndex := uint64(4) - availability[slotIndex/8] = byte(1 << (slotIndex % 8)) - - stIface, err := state_native.InitializeFromProtoGloas(ðpb.BeaconStateGloas{ - Slot: 6, - BlockRoots: blockRoots, - ExecutionPayloadAvailability: availability, - Fork: ðpb.Fork{ - CurrentVersion: bytes.Repeat([]byte{0x66}, 4), - PreviousVersion: bytes.Repeat([]byte{0x66}, 4), - Epoch: 0, - }, - }) - require.NoError(t, err) - state := stIface.(*state_native.BeaconState) - require.Equal(t, version.Gloas, state.Version()) + roots := map[primitives.Slot][]byte{ + 4: bytes.Repeat([]byte{0xCC}, 32), + 3: bytes.Repeat([]byte{0xBB}, 32), + } + var attestedRoot [32]byte + copy(attestedRoot[:], bytes.Repeat([]byte{0xAA}, 32)) - var rootArr [32]byte - copy(rootArr[:], root) + t.Run("non same slot checks availability at the parent slot", func(t *testing.T) { + // Slot 4 was skipped, the attested block at slot 3 revealed its payload. + st := buildStateWithAvailability(t, 6, roots, 3) - ok, err := MatchingPayload(state, rootArr, 4, 1) + ok, err := MatchingPayload(st, attestedRoot, 4, 3, 1) require.NoError(t, err) require.Equal(t, true, ok) - ok, err = MatchingPayload(state, rootArr, 4, 0) + ok, err = MatchingPayload(st, attestedRoot, 4, 3, 0) require.NoError(t, err) require.Equal(t, false, ok) }) + + t.Run("non same slot ignores availability at the data slot", func(t *testing.T) { + // Only the skipped slot 4 is marked available, the attested block at slot 3 withheld its payload. + st := buildStateWithAvailability(t, 6, roots, 4) + + ok, err := MatchingPayload(st, attestedRoot, 4, 3, 1) + require.NoError(t, err) + require.Equal(t, false, ok) + + ok, err = MatchingPayload(st, attestedRoot, 4, 3, 0) + require.NoError(t, err) + require.Equal(t, true, ok) + }) +} + +func TestParentSlotFromBid(t *testing.T) { + t.Run("pre-gloas returns zero", func(t *testing.T) { + st, err := state_native.InitializeFromProtoElectra(ðpb.BeaconStateElectra{}) + require.NoError(t, err) + + parentSlot, err := ParentSlotFromBid(st) + require.NoError(t, err) + require.Equal(t, primitives.Slot(0), parentSlot) + }) + + t.Run("returns the cached bid slot", func(t *testing.T) { + st, err := state_native.InitializeFromProtoGloas(ðpb.BeaconStateGloas{ + Slot: 6, + LatestExecutionPayloadBid: ðpb.ExecutionPayloadBid{ + Slot: 3, + ParentBlockHash: make([]byte, 32), + ParentBlockRoot: make([]byte, 32), + BlockHash: make([]byte, 32), + PrevRandao: make([]byte, 32), + FeeRecipient: make([]byte, 20), + }, + }) + require.NoError(t, err) + + parentSlot, err := ParentSlotFromBid(st) + require.NoError(t, err) + require.Equal(t, primitives.Slot(3), parentSlot) + }) } diff --git a/beacon-chain/core/transition/gloas.go b/beacon-chain/core/transition/gloas.go index 514fdffc4e9c..b654e49fdde4 100644 --- a/beacon-chain/core/transition/gloas.go +++ b/beacon-chain/core/transition/gloas.go @@ -3,6 +3,7 @@ package transition import ( "context" + "github.com/OffchainLabs/prysm/v7/beacon-chain/core/altair" "github.com/OffchainLabs/prysm/v7/beacon-chain/core/blocks" "github.com/OffchainLabs/prysm/v7/beacon-chain/core/electra" "github.com/OffchainLabs/prysm/v7/beacon-chain/core/epoch/precompute" @@ -52,7 +53,7 @@ import ( // # [New in Gloas:EIP7732] // for_ops(body.payload_attestations, process_payload_attestation) // -func gloasOperations(ctx context.Context, st state.BeaconState, block interfaces.ReadOnlyBeaconBlock) (state.BeaconState, error) { +func gloasOperations(ctx context.Context, st state.BeaconState, block interfaces.ReadOnlyBeaconBlock, parentSlot primitives.Slot) (state.BeaconState, error) { ctx, span := trace.StartSpan(ctx, "core.state.gloasOperations") defer span.End() @@ -77,7 +78,7 @@ func gloasOperations(ctx context.Context, st state.BeaconState, block interfaces if err != nil { return nil, errors.Wrap(ErrProcessAttesterSlashingsFailed, err.Error()) } - st, err = electra.ProcessAttestationsNoVerifySignature(ctx, st, block) + st, err = altair.ProcessAttestationsNoVerifySignatureWithParentSlot(ctx, st, block, parentSlot) if err != nil { return nil, errors.Wrap(ErrProcessAttestationsFailed, err.Error()) } diff --git a/beacon-chain/core/transition/gloas_operations_test.go b/beacon-chain/core/transition/gloas_operations_test.go index bba5a2d8bb01..2c09b2583e28 100644 --- a/beacon-chain/core/transition/gloas_operations_test.go +++ b/beacon-chain/core/transition/gloas_operations_test.go @@ -33,7 +33,7 @@ func TestGloasOperations_HappyPath(t *testing.T) { // A plain Electra state is fine here because we exercise zero operations. blk := newGloasBlock(t, emptyGloasBody()) - _, err := transition.GloasOperations(context.Background(), st, blk) + _, err := transition.GloasOperations(context.Background(), st, blk, 0) require.NoError(t, err) } @@ -226,7 +226,7 @@ func TestGloasOperations_ProcessingErrors(t *testing.T) { gloasBlk := newGloasBlock(t, body) - _, err := transition.GloasOperations(ctx, st, gloasBlk) + _, err := transition.GloasOperations(ctx, st, gloasBlk, 0) require.NotNil(t, err, "expected an error but got nil") require.ErrorContains(t, tc.errSubstr, err) require.Equal(t, true, errors.Is(err, tc.errSentinel)) diff --git a/beacon-chain/core/transition/transition_fuzz_test.go b/beacon-chain/core/transition/transition_fuzz_test.go index 652c90e01bb0..a6dbc42190a8 100644 --- a/beacon-chain/core/transition/transition_fuzz_test.go +++ b/beacon-chain/core/transition/transition_fuzz_test.go @@ -113,7 +113,7 @@ func TestFuzzprocessOperationsNoVerify_1000(t *testing.T) { } wb, err := blocks.NewBeaconBlock(bb) require.NoError(t, err) - s, err := ProcessOperationsNoVerifyAttsSigs(ctx, state, wb) + s, err := ProcessOperationsNoVerifyAttsSigs(ctx, state, wb, 0) if err != nil && s != nil { t.Fatalf("state should be nil on err. found: %v on error: %v for block body: %v", s, err, bb) } diff --git a/beacon-chain/core/transition/transition_no_verify_sig.go b/beacon-chain/core/transition/transition_no_verify_sig.go index 3597835fd41c..d6f94f4b31ca 100644 --- a/beacon-chain/core/transition/transition_no_verify_sig.go +++ b/beacon-chain/core/transition/transition_no_verify_sig.go @@ -14,6 +14,7 @@ import ( "github.com/OffchainLabs/prysm/v7/config/features" "github.com/OffchainLabs/prysm/v7/consensus-types/blocks" "github.com/OffchainLabs/prysm/v7/consensus-types/interfaces" + "github.com/OffchainLabs/prysm/v7/consensus-types/primitives" "github.com/OffchainLabs/prysm/v7/crypto/bls" "github.com/OffchainLabs/prysm/v7/monitoring/tracing" "github.com/OffchainLabs/prysm/v7/monitoring/tracing/trace" @@ -346,7 +347,8 @@ func ProcessBlockNoVerifyAnySig( func ProcessOperationsNoVerifyAttsSigs( ctx context.Context, state state.BeaconState, - beaconBlock interfaces.ReadOnlyBeaconBlock) (state.BeaconState, error) { + beaconBlock interfaces.ReadOnlyBeaconBlock, + parentSlot primitives.Slot) (state.BeaconState, error) { ctx, span := trace.StartSpan(ctx, "core.state.ProcessOperationsNoVerifyAttsSigs") defer span.End() if beaconBlock == nil || beaconBlock.IsNil() { @@ -359,7 +361,7 @@ func ProcessOperationsNoVerifyAttsSigs( blockVersion := beaconBlock.Version() if blockVersion >= version.Gloas { - state, err := gloasOperations(ctx, state, beaconBlock) + state, err := gloasOperations(ctx, state, beaconBlock, parentSlot) if err != nil { return nil, fmt.Errorf("gloas operations: %w", err) } @@ -437,6 +439,7 @@ func ProcessBlockForStateRoot( return nil, errors.Wrap(err, "could not process block header") } + var parentSlot primitives.Slot if state.Version() >= version.Gloas { // // def process_block(state: BeaconState, block: BeaconBlock) -> None: @@ -458,6 +461,11 @@ func ProcessBlockForStateRoot( if err := gloas.ProcessWithdrawals(state); err != nil { return nil, errors.Wrap(ErrProcessWithdrawalsFailed, err.Error()) } + // Read before the bid is replaced by this block's, process_attestation needs the parent's slot. + parentSlot, err = gloas.ParentSlotFromBid(state) + if err != nil { + return nil, errors.Wrap(err, "could not get parent slot from bid") + } if err := gloas.ProcessExecutionPayloadBid(state, blk); err != nil { return nil, errors.Wrap(err, "could not process execution payload bid") } @@ -496,7 +504,7 @@ func ProcessBlockForStateRoot( return nil, errors.Wrap(ErrProcessEth1DataFailed, err.Error()) } - state, err = ProcessOperationsNoVerifyAttsSigs(ctx, state, signed.Block()) + state, err = ProcessOperationsNoVerifyAttsSigs(ctx, state, signed.Block(), parentSlot) if err != nil { tracing.AnnotateError(span, err) return nil, errors.Wrap(err, "could not process block operation") diff --git a/beacon-chain/core/transition/transition_no_verify_sig_test.go b/beacon-chain/core/transition/transition_no_verify_sig_test.go index 7eeecc0690ae..0858456d4273 100644 --- a/beacon-chain/core/transition/transition_no_verify_sig_test.go +++ b/beacon-chain/core/transition/transition_no_verify_sig_test.go @@ -170,7 +170,7 @@ func TestProcessOperationsNoVerifyAttsSigs_OK(t *testing.T) { require.NoError(t, err) beaconState, err = transition.ProcessSlots(t.Context(), beaconState, wsb.Block().Slot()) require.NoError(t, err) - _, err = transition.ProcessOperationsNoVerifyAttsSigs(t.Context(), beaconState, wsb.Block()) + _, err = transition.ProcessOperationsNoVerifyAttsSigs(t.Context(), beaconState, wsb.Block(), 0) require.NoError(t, err) } @@ -180,7 +180,7 @@ func TestProcessOperationsNoVerifyAttsSigsBellatrix_OK(t *testing.T) { require.NoError(t, err) beaconState, err = transition.ProcessSlots(t.Context(), beaconState, wsb.Block().Slot()) require.NoError(t, err) - _, err = transition.ProcessOperationsNoVerifyAttsSigs(t.Context(), beaconState, wsb.Block()) + _, err = transition.ProcessOperationsNoVerifyAttsSigs(t.Context(), beaconState, wsb.Block(), 0) require.NoError(t, err) } @@ -190,7 +190,7 @@ func TestProcessOperationsNoVerifyAttsSigsCapella_OK(t *testing.T) { require.NoError(t, err) beaconState, err = transition.ProcessSlots(t.Context(), beaconState, wsb.Block().Slot()) require.NoError(t, err) - _, err = transition.ProcessOperationsNoVerifyAttsSigs(t.Context(), beaconState, wsb.Block()) + _, err = transition.ProcessOperationsNoVerifyAttsSigs(t.Context(), beaconState, wsb.Block(), 0) require.NoError(t, err) } diff --git a/changelog/terence_att-payload-availability-parent-slot.md b/changelog/terence_att-payload-availability-parent-slot.md new file mode 100644 index 000000000000..ffb6ba8b2d43 --- /dev/null +++ b/changelog/terence_att-payload-availability-parent-slot.md @@ -0,0 +1,3 @@ +### Fixed + +- Gloas: look up payload availability at the parent block's slot so attestations to skipped slots can earn the timely head flag. From 04fc6a02cbfe480acfd6b3bc9f304ff1bfaf6e0e Mon Sep 17 00:00:00 2001 From: terence Date: Fri, 7 Aug 2026 10:20:39 -0700 Subject: [PATCH 16/23] Bump consensus spec to v1.7.0-alpha.13 --- .ethspecify.yml | 71 +- WORKSPACE | 10 +- beacon-chain/core/gloas/bid.go | 9 +- .../core/gloas/payload_attestation.go | 8 +- beacon-chain/core/gloas/pending_payment.go | 6 +- beacon-chain/core/gloas/upgrade.go | 4 +- beacon-chain/core/transition/gloas.go | 16 +- .../transition/transition_no_verify_sig.go | 6 +- .../state/state-native/getters_gloas.go | 12 +- .../verification/execution_payload_bid.go | 4 +- config/params/loader_test.go | 1 + specrefs/configs.yml | 265 +++-- specrefs/constants.yml | 221 ++-- specrefs/containers.yml | 306 ++--- specrefs/dataclasses.yml | 188 +-- specrefs/functions.yml | 1035 +++++++++-------- specrefs/presets.yml | 316 ++--- 17 files changed, 1249 insertions(+), 1229 deletions(-) diff --git a/.ethspecify.yml b/.ethspecify.yml index 8451be8cb029..bf925c4d517d 100644 --- a/.ethspecify.yml +++ b/.ethspecify.yml @@ -1,4 +1,4 @@ -version: v1.7.0-alpha.12 +version: v1.7.0-alpha.13 style: full specrefs: @@ -40,19 +40,8 @@ exceptions: - PAYLOAD_STATUS_VALID#bellatrix - SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY#bellatrix # deneb - - BLS_MODULUS#deneb - - BYTES_PER_COMMITMENT#deneb - BYTES_PER_FIELD_ELEMENT#deneb - - BYTES_PER_PROOF#deneb - - FIAT_SHAMIR_PROTOCOL_DOMAIN#deneb - - G1_POINT_AT_INFINITY#deneb - G2_POINT_AT_INFINITY#deneb - - KZG_ENDIANNESS#deneb - - KZG_SETUP_G2_LENGTH#deneb - - KZG_SETUP_G2_MONOMIAL#deneb - - PRIMITIVE_ROOT_OF_UNITY#deneb - - RANDOM_CHALLENGE_KZG_BATCH_DOMAIN#deneb - - RANDOM_CHALLENGE_KZG_CELL_BATCH_DOMAIN#fulu # fulu - UINT256_MAX#fulu # gloas @@ -94,6 +83,7 @@ exceptions: - INCLUSION_LIST_DUE_BPS#heze - MAX_BYTES_PER_INCLUSION_LIST#heze - MAX_REQUEST_INCLUSION_LIST#heze + - MIN_SLOTS_FOR_INCLUSION_LISTS_REQUESTS#heze ssz_objects: # phase0 @@ -182,59 +172,6 @@ exceptions: - Store#heze functions: - # Functions implemented by KZG library for EIP-4844 - - bit_reversal_permutation#deneb - - blob_to_kzg_commitment#deneb - - blob_to_polynomial#deneb - - bls_field_to_bytes#deneb - - bytes_to_bls_field#deneb - - bytes_to_kzg_commitment#deneb - - bytes_to_kzg_proof#deneb - - compute_blob_kzg_proof#deneb - - compute_challenge#deneb - - compute_kzg_proof#deneb - - compute_kzg_proof_impl#deneb - - compute_powers#deneb - - compute_quotient_eval_within_domain#deneb - - compute_roots_of_unity#deneb - - evaluate_polynomial_in_evaluation_form#deneb - - g1_lincomb#deneb - - hash_to_bls_field#deneb - - is_power_of_two#deneb - - reverse_bits#deneb - - validate_kzg_g1#deneb - - verify_blob_kzg_proof#deneb - - verify_blob_kzg_proof_batch#deneb - - verify_kzg_proof#deneb - - verify_kzg_proof_batch#deneb - - verify_kzg_proof_impl#deneb - - # Functions implemented by KZG library for EIP-7594 - - _fft_field#fulu - - add_polynomialcoeff#fulu - - cell_to_coset_evals#fulu - - compute_cells#fulu - - compute_cells_and_kzg_proofs#fulu - - compute_cells_and_kzg_proofs_polynomialcoeff#fulu - - compute_kzg_proof_multi_impl#fulu - - compute_verify_cell_kzg_proof_batch_challenge#fulu - - construct_vanishing_polynomial#fulu - - coset_evals_to_cell#fulu - - coset_fft_field#fulu - - coset_for_cell#fulu - - coset_shift_for_cell#fulu - - divide_polynomialcoeff#fulu - - evaluate_polynomialcoeff#fulu - - fft_field#fulu - - interpolate_polynomialcoeff#fulu - - multiply_polynomialcoeff#fulu - - polynomial_eval_to_coeff#fulu - - recover_cells_and_kzg_proofs#fulu - - recover_polynomialcoeff#fulu - - vanishing_polynomialcoeff#fulu - - verify_cell_kzg_proof_batch#fulu - - verify_cell_kzg_proof_batch_impl#fulu - # phase0 - adjust_committee_weight_estimate_to_ensure_safety#phase0 - compute_adversarial_weight#phase0 @@ -390,7 +327,9 @@ exceptions: # deneb - compute_max_request_blob_sidecars#deneb - get_lc_execution_root#deneb + - is_current_or_previous_epoch#deneb - is_valid_light_client_header#deneb + - is_within_epoch#deneb - prepare_execution_payload#deneb - upgrade_lc_bootstrap_to_deneb#deneb - upgrade_lc_finality_update_to_deneb#deneb @@ -448,8 +387,10 @@ exceptions: # gloas - get_latest_message_epoch#gloas - get_payload_due_ms#gloas + - is_bid_compatible_with_head#gloas - is_gas_limit_target_compatible#gloas - is_payload_verified#gloas + - is_valid_dependent_root#gloas - on_execution_payload_envelope#gloas - payload_data_availability#gloas - payload_timeliness#gloas diff --git a/WORKSPACE b/WORKSPACE index 333592b19ead..fd899e8078f6 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -282,16 +282,16 @@ filegroup( url = "https://github.com/ethereum/EIPs/archive/5480440fe51742ed23342b68cf106cefd427e39d.tar.gz", ) -consensus_spec_version = "v1.7.0-alpha.12" +consensus_spec_version = "v1.7.0-alpha.13" load("@prysm//tools:download_spectests.bzl", "consensus_spec_tests") consensus_spec_tests( name = "consensus_spec_tests", flavors = { - "general": "sha256-Mp889Ykn3yYU7K+8546zxSWKE+hzHS9BC7Mdjkpbnq8=", - "minimal": "sha256-fXng6W/dZmqnDLdBNyk1xdMNStYHrjmYhSEulxSliwc=", - "mainnet": "sha256-8AV9Ks3qJzDsaMrCx5aq2JF04Q6bOKxorX2KocDL2Fw=", + "general": "sha256-uY5TKAN6hJkyVAhXALjZ6uMEvsqB0JRP4FJ0yjUj7Ys=", + "minimal": "sha256-lLr9c1FDhWRUBAB+bsi0eu0TykQ7jnViH0D85c4fR6I=", + "mainnet": "sha256-v2lwbJzCxCPju661rn61Op5a3974TjcxKWu2Rv4ugUk=", }, version = consensus_spec_version, ) @@ -307,7 +307,7 @@ filegroup( visibility = ["//visibility:public"], ) """, - integrity = "sha256-bd1ii7rnjYwiEun4br2U/E+zJ9lXZ72WxIditScOM/0=", + integrity = "sha256-2MTTrtDbvXqXOuZbxgIijr4v6X/2dLAoD/0Rb59SMYk=", strip_prefix = "consensus-specs-" + consensus_spec_version[1:], url = "https://github.com/ethereum/consensus-specs/archive/refs/tags/%s.tar.gz" % consensus_spec_version, ) diff --git a/beacon-chain/core/gloas/bid.go b/beacon-chain/core/gloas/bid.go index f6ab3377ba33..2d1c94903937 100644 --- a/beacon-chain/core/gloas/bid.go +++ b/beacon-chain/core/gloas/bid.go @@ -18,10 +18,10 @@ import ( // ProcessExecutionPayloadBid processes a signed execution payload bid in the Gloas fork. // -// +// // def process_execution_payload_bid( // state: BeaconState, signed_bid: SignedExecutionPayloadBid -// ) -> None: +// ) -> Slot: // bid = signed_bid.message // builder_index = bid.builder_index // amount = bid.value @@ -69,8 +69,13 @@ import ( // pending_payment // ) // +// # Cache the parent block's slot before overwriting the bid +// parent_slot = state.latest_execution_payload_bid.slot +// // # Cache the signed execution payload bid // state.latest_execution_payload_bid = bid +// +// return parent_slot // func ProcessExecutionPayloadBid(st state.BeaconState, block interfaces.ReadOnlyBeaconBlock) error { signedBid, err := block.Body().SignedExecutionPayloadBid() diff --git a/beacon-chain/core/gloas/payload_attestation.go b/beacon-chain/core/gloas/payload_attestation.go index bd086c8f27b2..38585bc49995 100644 --- a/beacon-chain/core/gloas/payload_attestation.go +++ b/beacon-chain/core/gloas/payload_attestation.go @@ -219,12 +219,12 @@ func ptcSeed(st state.ReadOnlyBeaconState, epoch primitives.Epoch, slot primitiv // selectByBalance selects a balance-weighted subset of input candidates. // -// +// // def compute_balance_weighted_selection( // state: BeaconState, // indices: Sequence[ValidatorIndex], // seed: Bytes32, -// size: uint64, +// size: Uint64, // shuffle_indices: bool, // ) -> Sequence[ValidatorIndex]: // """ @@ -234,11 +234,11 @@ func ptcSeed(st state.ReadOnlyBeaconState, epoch primitives.Epoch, slot primitiv // ``indices`` is traversed in order. The returned list can contain duplicates. // """ // MAX_RANDOM_VALUE = 2**16 - 1 -// total = uint64(len(indices)) +// total = Uint64(len(indices)) // assert total > 0 // effective_balances = [state.validators[index].effective_balance for index in indices] // selected: List[ValidatorIndex] = [] -// i = uint64(0) +// i = Uint64(0) // while len(selected) < size: // offset = i % 16 * 2 // if offset == 0: diff --git a/beacon-chain/core/gloas/pending_payment.go b/beacon-chain/core/gloas/pending_payment.go index e18d7e7ad30c..98e1b2a08853 100644 --- a/beacon-chain/core/gloas/pending_payment.go +++ b/beacon-chain/core/gloas/pending_payment.go @@ -61,14 +61,14 @@ func ProcessBuilderPendingPayments(ctx context.Context, state state.BeaconState) // builderQuorumThreshold calculates the quorum threshold for builder payments. // -// -// def get_builder_payment_quorum_threshold(state: BeaconState) -> uint64: +// +// def get_builder_payment_quorum_threshold(state: BeaconState) -> Uint64: // """ // Calculate the quorum threshold for builder payments. // """ // per_slot_balance = get_total_active_balance(state) // SLOTS_PER_EPOCH // quorum = per_slot_balance * BUILDER_PAYMENT_THRESHOLD_NUMERATOR -// return uint64(quorum // BUILDER_PAYMENT_THRESHOLD_DENOMINATOR) +// return Uint64(quorum // BUILDER_PAYMENT_THRESHOLD_DENOMINATOR) // func builderQuorumThreshold(ctx context.Context, state state.ReadOnlyBeaconState) (primitives.Gwei, error) { activeBalance, err := helpers.TotalActiveBalance(ctx, state) diff --git a/beacon-chain/core/gloas/upgrade.go b/beacon-chain/core/gloas/upgrade.go index ba0a33e58cdc..3c292fd093af 100644 --- a/beacon-chain/core/gloas/upgrade.go +++ b/beacon-chain/core/gloas/upgrade.go @@ -17,7 +17,7 @@ import ( // UpgradeToGloas updates inputs a generic state to return the version Gloas state. // -// +// // def upgrade_to_gloas(pre: fulu.BeaconState) -> BeaconState: // epoch = fulu.get_current_epoch(pre) // @@ -57,7 +57,7 @@ import ( // current_justified_checkpoint=pre.current_justified_checkpoint, // finalized_checkpoint=pre.finalized_checkpoint, // # [Modified in Gloas:EIP7688] -// inactivity_scores=ProgressiveList[uint64](list(pre.inactivity_scores)), +// inactivity_scores=ProgressiveList[Uint64](list(pre.inactivity_scores)), // current_sync_committee=pre.current_sync_committee, // next_sync_committee=pre.next_sync_committee, // # [Modified in Gloas:EIP7732] diff --git a/beacon-chain/core/transition/gloas.go b/beacon-chain/core/transition/gloas.go index b654e49fdde4..588ac4d7f8bc 100644 --- a/beacon-chain/core/transition/gloas.go +++ b/beacon-chain/core/transition/gloas.go @@ -21,13 +21,19 @@ import ( // // Spec definition: // -// -// def process_operations(state: BeaconState, body: BeaconBlockBody) -> None: +// +// def process_operations( +// state: BeaconState, +// body: BeaconBlockBody, +// # [New in Gloas:EIP7732] +// parent_slot: Slot, +// ) -> None: // assert len(body.deposits) == 0 // -// def for_ops(operations: Sequence[Any], fn: Callable[[BeaconState, Any], None]) -> None: +// # [Modified in Gloas:EIP7732] +// def for_ops(operations: Sequence[Any], fn: Callable[..., None], *args: Any) -> None: // for operation in operations: -// fn(state, operation) +// fn(state, operation, *args) // // # [New in Gloas:EIP7688] // assert len(body.proposer_slashings) <= MAX_PROPOSER_SLASHINGS @@ -41,7 +47,7 @@ import ( // for_ops(body.proposer_slashings, process_proposer_slashing) // for_ops(body.attester_slashings, process_attester_slashing) // # [Modified in Gloas:EIP7732] -// for_ops(body.attestations, process_attestation) +// for_ops(body.attestations, process_attestation, parent_slot) // for_ops(body.voluntary_exits, process_voluntary_exit) // for_ops(body.bls_to_execution_changes, process_bls_to_execution_change) // # [Modified in Gloas:EIP7732] diff --git a/beacon-chain/core/transition/transition_no_verify_sig.go b/beacon-chain/core/transition/transition_no_verify_sig.go index d6f94f4b31ca..d0e37c146d53 100644 --- a/beacon-chain/core/transition/transition_no_verify_sig.go +++ b/beacon-chain/core/transition/transition_no_verify_sig.go @@ -441,7 +441,7 @@ func ProcessBlockForStateRoot( var parentSlot primitives.Slot if state.Version() >= version.Gloas { - // + // // def process_block(state: BeaconState, block: BeaconBlock) -> None: // # [New in Gloas:EIP7732] // process_parent_execution_payload(state, block) @@ -451,11 +451,11 @@ func ProcessBlockForStateRoot( // # [Modified in Gloas:EIP7732] // # Removed `process_execution_payload` // # [New in Gloas:EIP7732] - // process_execution_payload_bid(state, block.body.signed_execution_payload_bid) + // parent_slot = process_execution_payload_bid(state, block.body.signed_execution_payload_bid) // process_randao(state, block.body) // process_eth1_data(state, block.body) // # [Modified in Gloas:EIP7732] - // process_operations(state, block.body) + // process_operations(state, block.body, parent_slot) // process_sync_aggregate(state, block.body.sync_aggregate) // if err := gloas.ProcessWithdrawals(state); err != nil { diff --git a/beacon-chain/state/state-native/getters_gloas.go b/beacon-chain/state/state-native/getters_gloas.go index bf781de1e6f8..e9930669e218 100644 --- a/beacon-chain/state/state-native/getters_gloas.go +++ b/beacon-chain/state/state-native/getters_gloas.go @@ -459,16 +459,16 @@ func (b *BeaconState) ExpectedWithdrawalsGloas() (state.ExpectedWithdrawalsGloas // appendBuilderWithdrawals returns builder pending withdrawals, the updated withdrawal index, // and the processed count. // -// +// // def get_builder_withdrawals( // state: BeaconState, // withdrawal_index: WithdrawalIndex, // prior_withdrawals: Sequence[Withdrawal], -// ) -> Tuple[Sequence[Withdrawal], WithdrawalIndex, uint64]: +// ) -> Tuple[Sequence[Withdrawal], WithdrawalIndex, Uint64]: // withdrawals_limit = MAX_WITHDRAWALS_PER_PAYLOAD - 1 // assert len(prior_withdrawals) <= withdrawals_limit // -// processed_count: uint64 = 0 +// processed_count: Uint64 = 0 // withdrawals: List[Withdrawal] = [] // for withdrawal in state.builder_pending_withdrawals: // all_withdrawals = prior_withdrawals + withdrawals @@ -521,18 +521,18 @@ func (b *BeaconState) appendBuilderWithdrawals(withdrawalIndex uint64, withdrawa // appendBuildersSweepWithdrawals returns builder sweep withdrawals, the updated withdrawal index, // and the processed count. // -// +// // def get_builders_sweep_withdrawals( // state: BeaconState, // withdrawal_index: WithdrawalIndex, // prior_withdrawals: Sequence[Withdrawal], -// ) -> Tuple[Sequence[Withdrawal], WithdrawalIndex, uint64]: +// ) -> Tuple[Sequence[Withdrawal], WithdrawalIndex, Uint64]: // epoch = get_current_epoch(state) // builders_limit = min(len(state.builders), MAX_BUILDERS_PER_WITHDRAWALS_SWEEP) // withdrawals_limit = MAX_WITHDRAWALS_PER_PAYLOAD - 1 // assert len(prior_withdrawals) <= withdrawals_limit // -// processed_count: uint64 = 0 +// processed_count: Uint64 = 0 // withdrawals: List[Withdrawal] = [] // builder_index = state.next_withdrawal_builder_index // for _ in range(builders_limit): diff --git a/beacon-chain/verification/execution_payload_bid.go b/beacon-chain/verification/execution_payload_bid.go index 972db12a9a39..654df2f73980 100644 --- a/beacon-chain/verification/execution_payload_bid.go +++ b/beacon-chain/verification/execution_payload_bid.go @@ -232,9 +232,9 @@ func (v *BidVerifier) VerifyGasLimitTargetCompatible(parentGasLimit, targetGasLi // isGasLimitTargetCompatible reports whether gasLimit is compatible with // targetGasLimit under the EIP-1559 transition rule from parentGasLimit. // -// +// // def is_gas_limit_target_compatible( -// parent_gas_limit: uint64, gas_limit: uint64, target_gas_limit: uint64 +// parent_gas_limit: Uint64, gas_limit: Uint64, target_gas_limit: Uint64 // ) -> bool: // """ // Check if ``gas_limit`` is compatible with ``target_gas_limit`` under the diff --git a/config/params/loader_test.go b/config/params/loader_test.go index 327a95df6903..cefb2189589f 100644 --- a/config/params/loader_test.go +++ b/config/params/loader_test.go @@ -49,6 +49,7 @@ var placeholderFields = []string{ "KZG_COMMITMENTS_INCLUSION_PROOF_DEPTH", // Configured in proto/ssz_proto_library.bzl "MAX_BYTES_PER_INCLUSION_LIST", "MAX_REQUEST_INCLUSION_LIST", + "MIN_SLOTS_FOR_INCLUSION_LISTS_REQUESTS", "NUMBER_OF_COLUMNS", // Configured as a constant in config/fieldparams/mainnet.go "TARGET_NUMBER_OF_PEERS", "UPDATE_TIMEOUT", diff --git a/specrefs/configs.yml b/specrefs/configs.yml index 93ea6a590211..17301c490db1 100644 --- a/specrefs/configs.yml +++ b/specrefs/configs.yml @@ -4,15 +4,15 @@ search: AggregateDueBPS\s+primitives.BP regex: true spec: | - - AGGREGATE_DUE_BPS: uint64 = 6667 + + AGGREGATE_DUE_BPS: Uint64 = 6667 - name: AGGREGATE_DUE_BPS_GLOAS#gloas sources: [] spec: | - - AGGREGATE_DUE_BPS_GLOAS: uint64 = 5000 + + AGGREGATE_DUE_BPS_GLOAS: Uint64 = 5000 - name: ALTAIR_FORK_EPOCH#altair @@ -41,15 +41,15 @@ search: ^\tAttestationDueBPS\s regex: true spec: | - - ATTESTATION_DUE_BPS: uint64 = 3333 + + ATTESTATION_DUE_BPS: Uint64 = 3333 - name: ATTESTATION_DUE_BPS_GLOAS#gloas sources: [] spec: | - - ATTESTATION_DUE_BPS_GLOAS: uint64 = 2500 + + ATTESTATION_DUE_BPS_GLOAS: Uint64 = 2500 - name: ATTESTATION_PROPAGATION_SLOT_RANGE#phase0 @@ -58,8 +58,8 @@ search: AttestationPropagationSlotRange\s+primitives.Slot regex: true spec: | - - ATTESTATION_PROPAGATION_SLOT_RANGE = 32 + + ATTESTATION_PROPAGATION_SLOT_RANGE: Slot = 32 - name: ATTESTATION_SUBNET_COUNT#phase0 @@ -68,8 +68,8 @@ search: AttestationSubnetCount\s+uint64 regex: true spec: | - - ATTESTATION_SUBNET_COUNT = 64 + + ATTESTATION_SUBNET_COUNT: Uint64 = 64 - name: ATTESTATION_SUBNET_EXTRA_BITS#phase0 @@ -78,8 +78,8 @@ search: AttestationSubnetExtraBits\s+uint64 regex: true spec: | - - ATTESTATION_SUBNET_EXTRA_BITS = 0 + + ATTESTATION_SUBNET_EXTRA_BITS: Uint64 = 0 - name: BALANCE_PER_ADDITIONAL_CUSTODY_GROUP#fulu @@ -137,8 +137,8 @@ search: BlobsidecarSubnetCount\s+uint64 regex: true spec: | - - BLOB_SIDECAR_SUBNET_COUNT = 6 + + BLOB_SIDECAR_SUBNET_COUNT: Uint64 = 6 - name: BLOB_SIDECAR_SUBNET_COUNT_ELECTRA#electra @@ -147,8 +147,8 @@ search: BlobsidecarSubnetCountElectra\s+uint64 regex: true spec: | - - BLOB_SIDECAR_SUBNET_COUNT_ELECTRA = 9 + + BLOB_SIDECAR_SUBNET_COUNT_ELECTRA: Uint64 = 9 - name: CAPELLA_FORK_EPOCH#capella @@ -177,29 +177,29 @@ search: \bChurnLimitQuotient\s+uint64 regex: true spec: | - - CHURN_LIMIT_QUOTIENT: uint64 = 65536 + + CHURN_LIMIT_QUOTIENT: Uint64 = 65536 - name: CHURN_LIMIT_QUOTIENT_GLOAS#gloas sources: [] spec: | - - CHURN_LIMIT_QUOTIENT_GLOAS: uint64 = 32768 + + CHURN_LIMIT_QUOTIENT_GLOAS: Uint64 = 32768 - name: CONFIRMATION_BYZANTINE_THRESHOLD#phase0 sources: [] spec: | - - CONFIRMATION_BYZANTINE_THRESHOLD: uint64 = 25 + + CONFIRMATION_BYZANTINE_THRESHOLD: Uint64 = 25 - name: CONSOLIDATION_CHURN_LIMIT_QUOTIENT#gloas sources: [] spec: | - - CONSOLIDATION_CHURN_LIMIT_QUOTIENT: uint64 = 65536 + + CONSOLIDATION_CHURN_LIMIT_QUOTIENT: Uint64 = 65536 - name: CONTRIBUTION_DUE_BPS#altair @@ -208,15 +208,15 @@ search: ContributionDueBPS\s+primitives.BP regex: true spec: | - - CONTRIBUTION_DUE_BPS: uint64 = 6667 + + CONTRIBUTION_DUE_BPS: Uint64 = 6667 - name: CONTRIBUTION_DUE_BPS_GLOAS#gloas sources: [] spec: | - - CONTRIBUTION_DUE_BPS_GLOAS: uint64 = 5000 + + CONTRIBUTION_DUE_BPS_GLOAS: Uint64 = 5000 - name: CUSTODY_REQUIREMENT#fulu @@ -225,8 +225,8 @@ search: CustodyRequirement\s+uint64.*yaml:"CUSTODY_REQUIREMENT" regex: true spec: | - - CUSTODY_REQUIREMENT: uint64 = 4 + + CUSTODY_REQUIREMENT: Uint64 = 4 - name: DATA_COLUMN_SIDECAR_SUBNET_COUNT#fulu @@ -235,8 +235,8 @@ search: DataColumnSidecarSubnetCount\s+uint64 regex: true spec: | - - DATA_COLUMN_SIDECAR_SUBNET_COUNT: uint64 = 128 + + DATA_COLUMN_SIDECAR_SUBNET_COUNT: Uint64 = 128 - name: DENEB_FORK_EPOCH#deneb @@ -259,6 +259,36 @@ DENEB_FORK_VERSION: Version = '0x04000000' +- name: DEPOSIT_CHAIN_ID#phase0 + sources: + - file: config/params/config.go + search: DepositChainID\s+uint64 + regex: true + spec: | + + DEPOSIT_CHAIN_ID: Uint64 = 1 + + +- name: DEPOSIT_CONTRACT_ADDRESS#phase0 + sources: + - file: config/params/config.go + search: DepositContractAddress\s+string + regex: true + spec: | + + DEPOSIT_CONTRACT_ADDRESS: ExecutionAddress = '0x00000000219ab540356cBB839Cbe05303d7705Fa' + + +- name: DEPOSIT_NETWORK_ID#phase0 + sources: + - file: config/params/config.go + search: DepositNetworkID\s+uint64 + regex: true + spec: | + + DEPOSIT_NETWORK_ID: Uint64 = 1 + + - name: EJECTION_BALANCE#phase0 sources: - file: config/params/config.go @@ -295,8 +325,8 @@ search: EpochsPerSubnetSubscription\s+uint64 regex: true spec: | - - EPOCHS_PER_SUBNET_SUBSCRIPTION = 256 + + EPOCHS_PER_SUBNET_SUBSCRIPTION: Epoch = 256 - name: ETH1_FOLLOW_DISTANCE#phase0 @@ -305,8 +335,8 @@ search: Eth1FollowDistance\s+uint64 regex: true spec: | - - ETH1_FOLLOW_DISTANCE: uint64 = 2048 + + ETH1_FOLLOW_DISTANCE: Uint64 = 2048 - name: FULU_FORK_EPOCH#fulu @@ -335,8 +365,8 @@ search: GenesisDelay\s+uint64 regex: true spec: | - - GENESIS_DELAY: uint64 = 604800 + + GENESIS_DELAY: Uint64 = 604800 - name: GENESIS_FORK_VERSION#phase0 @@ -383,8 +413,8 @@ search: InactivityScoreBias\s+uint64 regex: true spec: | - - INACTIVITY_SCORE_BIAS: uint64 = 4 + + INACTIVITY_SCORE_BIAS: Uint64 = 4 - name: INACTIVITY_SCORE_RECOVERY_RATE#altair @@ -393,15 +423,15 @@ search: InactivityScoreRecoveryRate\s+uint64 regex: true spec: | - - INACTIVITY_SCORE_RECOVERY_RATE: uint64 = 16 + + INACTIVITY_SCORE_RECOVERY_RATE: Uint64 = 16 - name: INCLUSION_LIST_DUE_BPS#heze sources: [] spec: | - - INCLUSION_LIST_DUE_BPS: uint64 = 6667 + + INCLUSION_LIST_DUE_BPS: Uint64 = 6667 - name: MAXIMUM_GOSSIP_CLOCK_DISPARITY#phase0 @@ -410,8 +440,8 @@ search: MaximumGossipClockDisparity\s+uint64 regex: true spec: | - - MAXIMUM_GOSSIP_CLOCK_DISPARITY = 500 + + MAXIMUM_GOSSIP_CLOCK_DISPARITY: Uint64 = 500 - name: MAX_BLOBS_PER_BLOCK#deneb @@ -420,8 +450,8 @@ search: DeprecatedMaxBlobsPerBlock\s+int regex: true spec: | - - MAX_BLOBS_PER_BLOCK: uint64 = 6 + + MAX_BLOBS_PER_BLOCK: Uint64 = 6 - name: MAX_BLOBS_PER_BLOCK_ELECTRA#electra @@ -430,15 +460,15 @@ search: DeprecatedMaxBlobsPerBlockElectra\s+int regex: true spec: | - - MAX_BLOBS_PER_BLOCK_ELECTRA: uint64 = 9 + + MAX_BLOBS_PER_BLOCK_ELECTRA: Uint64 = 9 - name: MAX_BYTES_PER_INCLUSION_LIST#heze sources: [] spec: | - - MAX_BYTES_PER_INCLUSION_LIST = 8192 + + MAX_BYTES_PER_INCLUSION_LIST: Uint64 = 8192 - name: MAX_PAYLOAD_SIZE#phase0 @@ -447,8 +477,8 @@ search: MaxPayloadSize\s+uint64 regex: true spec: | - - MAX_PAYLOAD_SIZE = 10485760 + + MAX_PAYLOAD_SIZE: Uint64 = 10485760 - name: MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT#deneb @@ -457,8 +487,8 @@ search: MaxPerEpochActivationChurnLimit\s+uint64 regex: true spec: | - - MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT: uint64 = 8 + + MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT: Uint64 = 8 - name: MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT_GLOAS#gloas @@ -484,8 +514,8 @@ search: MaxRequestBlocks\s+uint64 regex: true spec: | - - MAX_REQUEST_BLOCKS = 1024 + + MAX_REQUEST_BLOCKS: Uint64 = 1024 - name: MAX_REQUEST_BLOCKS_DENEB#deneb @@ -494,15 +524,15 @@ search: MaxRequestBlocksDeneb\s+uint64 regex: true spec: | - - MAX_REQUEST_BLOCKS_DENEB = 128 + + MAX_REQUEST_BLOCKS_DENEB: Uint64 = 128 - name: MAX_REQUEST_INCLUSION_LIST#heze sources: [] spec: | - - MAX_REQUEST_INCLUSION_LIST = 16 + + MAX_REQUEST_INCLUSION_LIST: Uint64 = 16 - name: MAX_REQUEST_PAYLOADS#gloas @@ -511,8 +541,8 @@ search: MaxRequestPayloads\s+uint64 regex: true spec: | - - MAX_REQUEST_PAYLOADS = 128 + + MAX_REQUEST_PAYLOADS: Uint64 = 128 - name: MESSAGE_DOMAIN_INVALID_SNAPPY#phase0 @@ -540,8 +570,8 @@ - file: config/params/mainnet_config.go search: MinBuilderWithdrawabilityDelay spec: | - - MIN_BUILDER_WITHDRAWABILITY_DELAY: uint64 = 64 + + MIN_BUILDER_WITHDRAWABILITY_DELAY: Epoch = 64 - name: MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS#deneb @@ -550,8 +580,8 @@ search: MinEpochsForBlobsSidecarsRequest\s+primitives.Epoch regex: true spec: | - - MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS = 4096 + + MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS: Epoch = 4096 - name: MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS#fulu @@ -560,8 +590,8 @@ search: MinEpochsForDataColumnSidecarsRequest\s+primitives.Epoch regex: true spec: | - - MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS: uint64 = 4096 + + MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS: Epoch = 4096 - name: MIN_GENESIS_ACTIVE_VALIDATOR_COUNT#phase0 @@ -570,8 +600,8 @@ search: MinGenesisActiveValidatorCount\s+uint64 regex: true spec: | - - MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: uint64 = 16384 + + MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: Uint64 = 16384 - name: MIN_GENESIS_TIME#phase0 @@ -580,8 +610,8 @@ search: MinGenesisTime\s+uint64 regex: true spec: | - - MIN_GENESIS_TIME: uint64 = 1606824000 + + MIN_GENESIS_TIME: Uint64 = 1606824000 - name: MIN_PER_EPOCH_CHURN_LIMIT#phase0 @@ -590,8 +620,8 @@ search: MinPerEpochChurnLimit\s+uint64 regex: true spec: | - - MIN_PER_EPOCH_CHURN_LIMIT: uint64 = 4 + + MIN_PER_EPOCH_CHURN_LIMIT: Uint64 = 4 - name: MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA#electra @@ -604,14 +634,21 @@ MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA: Gwei = 128000000000 +- name: MIN_SLOTS_FOR_INCLUSION_LISTS_REQUESTS#heze + sources: [] + spec: | + + MIN_SLOTS_FOR_INCLUSION_LISTS_REQUESTS: Slot = 1 + + - name: MIN_VALIDATOR_WITHDRAWABILITY_DELAY#phase0 sources: - file: config/params/config.go search: MinValidatorWithdrawabilityDelay\s+primitives.Epoch regex: true spec: | - - MIN_VALIDATOR_WITHDRAWABILITY_DELAY: uint64 = 256 + + MIN_VALIDATOR_WITHDRAWABILITY_DELAY: Epoch = 256 - name: NUMBER_OF_CUSTODY_GROUPS#fulu @@ -620,8 +657,8 @@ search: NumberOfCustodyGroups\s+uint64 regex: true spec: | - - NUMBER_OF_CUSTODY_GROUPS: uint64 = 128 + + NUMBER_OF_CUSTODY_GROUPS: Uint64 = 128 - name: PAYLOAD_ATTESTATION_DUE_BPS#gloas @@ -630,8 +667,8 @@ search: PayloadAttestationDueBPS\s+primitives.BP regex: true spec: | - - PAYLOAD_ATTESTATION_DUE_BPS: uint64 = 7500 + + PAYLOAD_ATTESTATION_DUE_BPS: Uint64 = 7500 - name: PAYLOAD_DUE_BPS#gloas @@ -640,8 +677,8 @@ search: PayloadDueBPS\s+primitives.BP regex: true spec: | - - PAYLOAD_DUE_BPS: uint64 = 5000 + + PAYLOAD_DUE_BPS: Uint64 = 5000 - name: PROPOSER_REORG_CUTOFF_BPS#phase0 @@ -650,8 +687,8 @@ search: ProposerReorgCutoffBPS\s+primitives.BP regex: true spec: | - - PROPOSER_REORG_CUTOFF_BPS: uint64 = 1667 + + PROPOSER_REORG_CUTOFF_BPS: Uint64 = 1667 - name: PROPOSER_SCORE_BOOST#phase0 @@ -660,8 +697,8 @@ search: ProposerScoreBoost\s+uint64 regex: true spec: | - - PROPOSER_SCORE_BOOST: uint64 = 40 + + PROPOSER_SCORE_BOOST: Uint64 = 40 - name: REORG_HEAD_WEIGHT_THRESHOLD#phase0 @@ -670,8 +707,8 @@ search: ReorgHeadWeightThreshold\s+uint64 regex: true spec: | - - REORG_HEAD_WEIGHT_THRESHOLD: uint64 = 20 + + REORG_HEAD_WEIGHT_THRESHOLD: Uint64 = 20 - name: REORG_MAX_EPOCHS_SINCE_FINALIZATION#phase0 @@ -690,8 +727,8 @@ search: ReorgParentWeightThreshold\s+uint64 regex: true spec: | - - REORG_PARENT_WEIGHT_THRESHOLD: uint64 = 160 + + REORG_PARENT_WEIGHT_THRESHOLD: Uint64 = 160 - name: SAMPLES_PER_SLOT#fulu @@ -700,8 +737,8 @@ search: SamplesPerSlot\s+uint64 regex: true spec: | - - SAMPLES_PER_SLOT: uint64 = 8 + + SAMPLES_PER_SLOT: Uint64 = 8 - name: SECONDS_PER_ETH1_BLOCK#phase0 @@ -710,8 +747,8 @@ search: SecondsPerETH1Block\s+uint64 regex: true spec: | - - SECONDS_PER_ETH1_BLOCK: uint64 = 14 + + SECONDS_PER_ETH1_BLOCK: Uint64 = 14 - name: SHARD_COMMITTEE_PERIOD#phase0 @@ -720,8 +757,8 @@ search: ShardCommitteePeriod\s+primitives.Epoch regex: true spec: | - - SHARD_COMMITTEE_PERIOD: uint64 = 256 + + SHARD_COMMITTEE_PERIOD: Epoch = 256 - name: SLOT_DURATION_MS#phase0 @@ -730,8 +767,8 @@ search: SlotDurationMilliseconds\s+uint64 regex: true spec: | - - SLOT_DURATION_MS: uint64 = 12000 + + SLOT_DURATION_MS: Uint64 = 12000 - name: SUBNETS_PER_NODE#phase0 @@ -740,8 +777,8 @@ search: SubnetsPerNode\s+uint64 regex: true spec: | - - SUBNETS_PER_NODE = 2 + + SUBNETS_PER_NODE: Uint64 = 2 - name: SYNC_MESSAGE_DUE_BPS#altair @@ -750,15 +787,15 @@ search: SyncMessageDueBPS\s+primitives.BP regex: true spec: | - - SYNC_MESSAGE_DUE_BPS: uint64 = 3333 + + SYNC_MESSAGE_DUE_BPS: Uint64 = 3333 - name: SYNC_MESSAGE_DUE_BPS_GLOAS#gloas sources: [] spec: | - - SYNC_MESSAGE_DUE_BPS_GLOAS: uint64 = 2500 + + SYNC_MESSAGE_DUE_BPS_GLOAS: Uint64 = 2500 - name: TERMINAL_BLOCK_HASH#bellatrix @@ -777,8 +814,8 @@ search: TerminalBlockHashActivationEpoch\s+primitives.Epoch regex: true spec: | - - TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH = 18446744073709551615 + + TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH: Epoch = 18446744073709551615 - name: TERMINAL_TOTAL_DIFFICULTY#bellatrix @@ -787,8 +824,8 @@ search: TerminalTotalDifficulty\s+string regex: true spec: | - - TERMINAL_TOTAL_DIFFICULTY = 58750000000000000000000 + + TERMINAL_TOTAL_DIFFICULTY: Uint256 = 58750000000000000000000 - name: VALIDATOR_CUSTODY_REQUIREMENT#fulu @@ -797,6 +834,6 @@ search: ValidatorCustodyRequirement\s+uint64 regex: true spec: | - - VALIDATOR_CUSTODY_REQUIREMENT = 8 + + VALIDATOR_CUSTODY_REQUIREMENT: Uint64 = 8 diff --git a/specrefs/constants.yml b/specrefs/constants.yml index e12f36948d0f..c644172b546a 100644 --- a/specrefs/constants.yml +++ b/specrefs/constants.yml @@ -1,8 +1,8 @@ - name: ATTESTATION_TIMELINESS_INDEX#gloas sources: [] spec: | - - ATTESTATION_TIMELINESS_INDEX = 0 + + ATTESTATION_TIMELINESS_INDEX: Uint64 = 0 - name: BASE_REWARDS_PER_EPOCH#phase0 @@ -11,22 +11,15 @@ search: BaseRewardsPerEpoch\s+.*yaml:"BASE_REWARDS_PER_EPOCH" regex: true spec: | - - BASE_REWARDS_PER_EPOCH: uint64 = 4 + + BASE_REWARDS_PER_EPOCH: Uint64 = 4 - name: BASIS_POINTS#phase0 sources: [] spec: | - - BASIS_POINTS: uint64 = 10000 - - -- name: BLS_MODULUS#deneb - sources: [] - spec: | - - BLS_MODULUS = 52435875175126190479447740508185965837690552500527637822603658699938581184513 + + BASIS_POINTS: Uint64 = 10000 - name: BLS_WITHDRAWAL_PREFIX#phase0 @@ -56,8 +49,8 @@ - name: BUILDER_INDEX_FLAG#gloas sources: [] spec: | - - BUILDER_INDEX_FLAG: uint64 = 2**40 + + BUILDER_INDEX_FLAG: Uint64 = 2**40 - name: BUILDER_INDEX_SELF_BUILD#gloas @@ -70,15 +63,15 @@ - name: BUILDER_PAYMENT_THRESHOLD_DENOMINATOR#gloas sources: [] spec: | - - BUILDER_PAYMENT_THRESHOLD_DENOMINATOR: uint64 = 10 + + BUILDER_PAYMENT_THRESHOLD_DENOMINATOR: Uint64 = 10 - name: BUILDER_PAYMENT_THRESHOLD_NUMERATOR#gloas sources: [] spec: | - - BUILDER_PAYMENT_THRESHOLD_NUMERATOR: uint64 = 6 + + BUILDER_PAYMENT_THRESHOLD_NUMERATOR: Uint64 = 6 - name: BUILDER_WITHDRAWAL_PREFIX#gloas @@ -88,32 +81,18 @@ BUILDER_WITHDRAWAL_PREFIX: Bytes1 = '0xB0' -- name: BYTES_PER_COMMITMENT#deneb - sources: [] - spec: | - - BYTES_PER_COMMITMENT: uint64 = 48 - - - name: BYTES_PER_FIELD_ELEMENT#deneb sources: [] spec: | - - BYTES_PER_FIELD_ELEMENT: uint64 = 32 - - -- name: BYTES_PER_PROOF#deneb - sources: [] - spec: | - - BYTES_PER_PROOF: uint64 = 48 + + BYTES_PER_FIELD_ELEMENT: Uint64 = 32 - name: COMMITTEE_WEIGHT_ESTIMATION_ADJUSTMENT_FACTOR#phase0 sources: [] spec: | - - COMMITTEE_WEIGHT_ESTIMATION_ADJUSTMENT_FACTOR: uint64 = 5 + + COMMITTEE_WEIGHT_ESTIMATION_ADJUSTMENT_FACTOR: Uint64 = 5 - name: COMPOUNDING_WITHDRAWAL_PREFIX#electra @@ -142,8 +121,8 @@ search: DepositContractTreeDepth\s+.*yaml:"DEPOSIT_CONTRACT_TREE_DEPTH" regex: true spec: | - - DEPOSIT_CONTRACT_TREE_DEPTH: uint64 = 2**5 + + DEPOSIT_CONTRACT_TREE_DEPTH: Uint64 = 2**5 - name: DEPOSIT_REQUEST_TYPE#electra @@ -344,8 +323,8 @@ search: GweiPerEth\s+uint64 regex: true spec: | - - ETH_TO_GWEI: uint64 = 10**9 + + ETH_TO_GWEI: Uint64 = 10**9 - name: FAR_FUTURE_EPOCH#phase0 @@ -358,28 +337,14 @@ FAR_FUTURE_EPOCH: Epoch = 2**64 - 1 -- name: FIAT_SHAMIR_PROTOCOL_DOMAIN#deneb - sources: [] - spec: | - - FIAT_SHAMIR_PROTOCOL_DOMAIN = b'FSBLOBVERIFY_V1_' - - - name: FULL_EXIT_REQUEST_AMOUNT#electra sources: - file: config/params/config.go search: FullExitRequestAmount\s+.*yaml:"FULL_EXIT_REQUEST_AMOUNT" regex: true spec: | - - FULL_EXIT_REQUEST_AMOUNT: uint64 = 0 - - -- name: G1_POINT_AT_INFINITY#deneb - sources: [] - spec: | - - G1_POINT_AT_INFINITY: Bytes48 = b'\xc0' + b'\x00' * 47 + + FULL_EXIT_REQUEST_AMOUNT: Gwei = 0 - name: G2_POINT_AT_INFINITY#altair @@ -418,36 +383,15 @@ search: JustificationBitsLength\s+.*yaml:"JUSTIFICATION_BITS_LENGTH" regex: true spec: | - - JUSTIFICATION_BITS_LENGTH: uint64 = 4 - - -- name: KZG_ENDIANNESS#deneb - sources: [] - spec: | - - KZG_ENDIANNESS = 'big' - - -- name: KZG_SETUP_G2_LENGTH#deneb - sources: [] - spec: | - - KZG_SETUP_G2_LENGTH: uint64 = 65 - - -- name: KZG_SETUP_G2_MONOMIAL#deneb - sources: [] - spec: | - - KZG_SETUP_G2_MONOMIAL: Vector[G2Point, KZG_SETUP_G2_LENGTH] = ['0x93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8', '0xb5bfd7dd8cdeb128843bc287230af38926187075cbfbefa81009a2ce615ac53d2914e5870cb452d2afaaab24f3499f72185cbfee53492714734429b7b38608e23926c911cceceac9a36851477ba4c60b087041de621000edc98edada20c1def2', '0xb5337ba0ce5d37224290916e268e2060e5c14f3f9fc9e1ec3af5a958e7a0303122500ce18f1a4640bf66525bd10e763501fe986d86649d8d45143c08c3209db3411802c226e9fe9a55716ac4a0c14f9dcef9e70b2bb309553880dc5025eab3cc', '0xb3c1dcdc1f62046c786f0b82242ef283e7ed8f5626f72542aa2c7a40f14d9094dd1ebdbd7457ffdcdac45fd7da7e16c51200b06d791e5e43e257e45efdf0bd5b06cd2333beca2a3a84354eb48662d83aef5ecf4e67658c851c10b13d8d87c874', '0x954d91c7688983382609fca9e211e461f488a5971fd4e40d7e2892037268eacdfd495cfa0a7ed6eb0eb11ac3ae6f651716757e7526abe1e06c64649d80996fd3105c20c4c94bc2b22d97045356fe9d791f21ea6428ac48db6f9e68e30d875280', '0x88a6b6bb26c51cf9812260795523973bb90ce80f6820b6c9048ab366f0fb96e48437a7f7cb62aedf64b11eb4dfefebb0147608793133d32003cb1f2dc47b13b5ff45f1bb1b2408ea45770a08dbfaec60961acb8119c47b139a13b8641e2c9487', '0x85cd7be9728bd925d12f47fb04b32d9fad7cab88788b559f053e69ca18e463113ecc8bbb6dbfb024835f901b3a957d3108d6770fb26d4c8be0a9a619f6e3a4bf15cbfd48e61593490885f6cee30e4300c5f9cf5e1c08e60a2d5b023ee94fcad0', '0x80477dba360f04399821a48ca388c0fa81102dd15687fea792ee8c1114e00d1bc4839ad37ac58900a118d863723acfbe08126ea883be87f50e4eabe3b5e72f5d9e041db8d9b186409fd4df4a7dde38c0e0a3b1ae29b098e5697e7f110b6b27e4', '0xb7a6aec08715a9f8672a2b8c367e407be37e59514ac19dd4f0942a68007bba3923df22da48702c63c0d6b3efd3c2d04e0fe042d8b5a54d562f9f33afc4865dcbcc16e99029e25925580e87920c399e710d438ac1ce3a6dc9b0d76c064a01f6f7', '0xac1b001edcea02c8258aeffbf9203114c1c874ad88dae1184fadd7d94cd09053649efd0ca413400e6e9b5fa4eac33261000af88b6bd0d2abf877a4f0355d2fb4d6007adb181695201c5432e50b850b51b3969f893bddf82126c5a71b042b7686', '0x90043fda4de53fb364fab2c04be5296c215599105ecff0c12e4917c549257125775c29f2507124d15f56e30447f367db0596c33237242c02d83dfd058735f1e3c1ff99069af55773b6d51d32a68bf75763f59ec4ee7267932ae426522b8aaab6', '0xa8660ce853e9dc08271bf882e29cd53397d63b739584dda5263da4c7cc1878d0cf6f3e403557885f557e184700575fee016ee8542dec22c97befe1d10f414d22e84560741cdb3e74c30dda9b42eeaaf53e27822de2ee06e24e912bf764a9a533', '0x8fe3921a96d0d065e8aa8fce9aa42c8e1461ca0470688c137be89396dd05103606dab6cdd2a4591efd6addf72026c12e065da7be276dee27a7e30afa2bd81c18f1516e7f068f324d0bad9570b95f6bd02c727cd2343e26db0887c3e4e26dceda', '0x8ae1ad97dcb9c192c9a3933541b40447d1dc4eebf380151440bbaae1e120cc5cdf1bcea55180b128d8e180e3af623815191d063cc0d7a47d55fb7687b9d87040bf7bc1a7546b07c61db5ccf1841372d7c2fe4a5431ffff829f3c2eb590b0b710', '0x8c2fa96870a88150f7876c931e2d3cc2adeaaaf5c73ef5fa1cf9dfa0991ae4819f9321af7e916e5057d87338e630a2f21242c29d76963cf26035b548d2a63d8ad7bd6efefa01c1df502cbdfdfe0334fb21ceb9f686887440f713bf17a89b8081', '0xb9aa98e2f02bb616e22ee5dd74c7d1049321ac9214d093a738159850a1dbcc7138cb8d26ce09d8296368fd5b291d74fa17ac7cc1b80840fdd4ee35e111501e3fa8485b508baecda7c1ab7bd703872b7d64a2a40b3210b6a70e8a6ffe0e5127e3', '0x9292db67f8771cdc86854a3f614a73805bf3012b48f1541e704ea4015d2b6b9c9aaed36419769c87c49f9e3165f03edb159c23b3a49c4390951f78e1d9b0ad997129b17cdb57ea1a6638794c0cca7d239f229e589c5ae4f9fe6979f7f8cba1d7', '0x91cd9e86550f230d128664f7312591fee6a84c34f5fc7aed557bcf986a409a6de722c4330453a305f06911d2728626e611acfdf81284f77f60a3a1595053a9479964fd713117e27c0222cc679674b03bc8001501aaf9b506196c56de29429b46', '0xa9516b73f605cc31b89c68b7675dc451e6364595243d235339437f556cf22d745d4250c1376182273be2d99e02c10eee047410a43eff634d051aeb784e76cb3605d8e079b9eb6ad1957dfdf77e1cd32ce4a573c9dfcc207ca65af6eb187f6c3d', '0xa9667271f7d191935cc8ad59ef3ec50229945faea85bfdfb0d582090f524436b348aaa0183b16a6231c00332fdac2826125b8c857a2ed9ec66821cfe02b3a2279be2412441bc2e369b255eb98614e4be8490799c4df22f18d47d24ec70bba5f7', '0xa4371144d2aa44d70d3cb9789096d3aa411149a6f800cb46f506461ee8363c8724667974252f28aea61b6030c05930ac039c1ee64bb4bd56532a685cae182bf2ab935eee34718cffcb46cae214c77aaca11dbb1320faf23c47247db1da04d8dc', '0x89a7eb441892260b7e81168c386899cd84ffc4a2c5cad2eae0d1ab9e8b5524662e6f660fe3f8bfe4c92f60b060811bc605b14c5631d16709266886d7885a5eb5930097127ec6fb2ebbaf2df65909cf48f253b3d5e22ae48d3e9a2fd2b01f447e', '0x9648c42ca97665b5eccb49580d8532df05eb5a68db07f391a2340769b55119eaf4c52fe4f650c09250fa78a76c3a1e271799b8333cc2628e3d4b4a6a3e03da1f771ecf6516dd63236574a7864ff07e319a6f11f153406280d63af9e2b5713283', '0x9663bf6dd446ea7a90658ee458578d4196dc0b175ef7fcfa75f44d41670850774c2e46c5a6be132a2c072a3c0180a24f0305d1acac49d2d79878e5cda80c57feda3d01a6af12e78b5874e2a4b3717f11c97503b41a4474e2e95b179113726199', '0xb212aeb4814e0915b432711b317923ed2b09e076aaf558c3ae8ef83f9e15a83f9ea3f47805b2750ab9e8106cb4dc6ad003522c84b03dc02829978a097899c773f6fb31f7fe6b8f2d836d96580f216fec20158f1590c3e0d7850622e15194db05', '0x925f005059bf07e9ceccbe66c711b048e236ade775720d0fe479aebe6e23e8af281225ad18e62458dc1b03b42ad4ca290d4aa176260604a7aad0d9791337006fbdebe23746f8060d42876f45e4c83c3643931392fde1cd13ff8bddf8111ef974', '0x9553edb22b4330c568e156a59ef03b26f5c326424f830fe3e8c0b602f08c124730ffc40bc745bec1a22417adb22a1a960243a10565c2be3066bfdb841d1cd14c624cd06e0008f4beb83f972ce6182a303bee3fcbcabc6cfe48ec5ae4b7941bfc', '0x935f5a404f0a78bdcce709899eda0631169b366a669e9b58eacbbd86d7b5016d044b8dfc59ce7ed8de743ae16c2343b50e2f925e88ba6319e33c3fc76b314043abad7813677b4615c8a97eb83cc79de4fedf6ccbcfa4d4cbf759a5a84e4d9742', '0xa5b014ab936eb4be113204490e8b61cd38d71da0dec7215125bcd131bf3ab22d0a32ce645bca93e7b3637cf0c2db3d6601a0ddd330dc46f9fae82abe864ffc12d656c88eb50c20782e5bb6f75d18760666f43943abb644b881639083e122f557', '0x935b7298ae52862fa22bf03bfc1795b34c70b181679ae27de08a9f5b4b884f824ef1b276b7600efa0d2f1d79e4a470d51692fd565c5cf8343dd80e5d3336968fc21c09ba9348590f6206d4424eb229e767547daefa98bc3aa9f421158dee3f2a', '0x9830f92446e708a8f6b091cc3c38b653505414f8b6507504010a96ffda3bcf763d5331eb749301e2a1437f00e2415efb01b799ad4c03f4b02de077569626255ac1165f96ea408915d4cf7955047620da573e5c439671d1fa5c833fb11de7afe6', '0x840dcc44f673fff3e387af2bb41e89640f2a70bcd2b92544876daa92143f67c7512faf5f90a04b7191de01f3e2b1bde00622a20dc62ca23bbbfaa6ad220613deff43908382642d4d6a86999f662efd64b1df448b68c847cfa87630a3ffd2ec76', '0x92950c895ed54f7f876b2fda17ecc9c41b7accfbdd42c210cc5b475e0737a7279f558148531b5c916e310604a1de25a80940c94fe5389ae5d6a5e9c371be67bceea1877f5401725a6595bcf77ece60905151b6dfcb68b75ed2e708c73632f4fd', '0x8010246bf8e94c25fd029b346b5fbadb404ef6f44a58fd9dd75acf62433d8cc6db66974f139a76e0c26dddc1f329a88214dbb63276516cf325c7869e855d07e0852d622c332ac55609ba1ec9258c45746a2aeb1af0800141ee011da80af175d4', '0xb0f1bad257ebd187bdc3f37b23f33c6a5d6a8e1f2de586080d6ada19087b0e2bf23b79c1b6da1ee82271323f5bdf3e1b018586b54a5b92ab6a1a16bb3315190a3584a05e6c37d5ca1e05d702b9869e27f513472bcdd00f4d0502a107773097da', '0x9636d24f1ede773ce919f309448dd7ce023f424afd6b4b69cb98c2a988d849a283646dc3e469879daa1b1edae91ae41f009887518e7eb5578f88469321117303cd3ac2d7aee4d9cb5f82ab9ae3458e796dfe7c24284b05815acfcaa270ff22e2', '0xb373feb5d7012fd60578d7d00834c5c81df2a23d42794fed91aa9535a4771fde0341c4da882261785e0caca40bf83405143085e7f17e55b64f6c5c809680c20b050409bf3702c574769127c854d27388b144b05624a0e24a1cbcc4d08467005b', '0xb15680648949ce69f82526e9b67d9b55ce5c537dc6ab7f3089091a9a19a6b90df7656794f6edc87fb387d21573ffc847062623685931c2790a508cbc8c6b231dd2c34f4d37d4706237b1407673605a604bcf6a50cc0b1a2db20485e22b02c17e', '0x8817e46672d40c8f748081567b038a3165f87994788ec77ee8daea8587f5540df3422f9e120e94339be67f186f50952504cb44f61e30a5241f1827e501b2de53c4c64473bcc79ab887dd277f282fbfe47997a930dd140ac08b03efac88d81075', '0xa6e4ef6c1d1098f95aae119905f87eb49b909d17f9c41bcfe51127aa25fee20782ea884a7fdf7d5e9c245b5a5b32230b07e0dbf7c6743bf52ee20e2acc0b269422bd6cf3c07115df4aa85b11b2c16630a07c974492d9cdd0ec325a3fabd95044', '0x8634aa7c3d00e7f17150009698ce440d8e1b0f13042b624a722ace68ead870c3d2212fbee549a2c190e384d7d6ac37ce14ab962c299ea1218ef1b1489c98906c91323b94c587f1d205a6edd5e9d05b42d591c26494a6f6a029a2aadb5f8b6f67', '0x821a58092900bdb73decf48e13e7a5012a3f88b06288a97b855ef51306406e7d867d613d9ec738ebacfa6db344b677d21509d93f3b55c2ebf3a2f2a6356f875150554c6fff52e62e3e46f7859be971bf7dd9d5b3e1d799749c8a97c2e04325df', '0x8dba356577a3a388f782e90edb1a7f3619759f4de314ad5d95c7cc6e197211446819c4955f99c5fc67f79450d2934e3c09adefc91b724887e005c5190362245eec48ce117d0a94d6fa6db12eda4ba8dde608fbbd0051f54dcf3bb057adfb2493', '0xa32a690dc95c23ed9fb46443d9b7d4c2e27053a7fcc216d2b0020a8cf279729c46114d2cda5772fd60a97016a07d6c5a0a7eb085a18307d34194596f5b541cdf01b2ceb31d62d6b55515acfd2b9eec92b27d082fbc4dc59fc63b551eccdb8468', '0xa040f7f4be67eaf0a1d658a3175d65df21a7dbde99bfa893469b9b43b9d150fc2e333148b1cb88cfd0447d88fa1a501d126987e9fdccb2852ecf1ba907c2ca3d6f97b055e354a9789854a64ecc8c2e928382cf09dda9abde42bbdf92280cdd96', '0x864baff97fa60164f91f334e0c9be00a152a416556b462f96d7c43b59fe1ebaff42f0471d0bf264976f8aa6431176eb905bd875024cf4f76c13a70bede51dc3e47e10b9d5652d30d2663b3af3f08d5d11b9709a0321aba371d2ef13174dcfcaf', '0x95a46f32c994133ecc22db49bad2c36a281d6b574c83cfee6680b8c8100466ca034b815cfaedfbf54f4e75188e661df901abd089524e1e0eb0bf48d48caa9dd97482d2e8c1253e7e8ac250a32fd066d5b5cb08a8641bdd64ecfa48289dca83a3', '0xa2cce2be4d12144138cb91066e0cd0542c80b478bf467867ebef9ddaf3bd64e918294043500bf5a9f45ee089a8d6ace917108d9ce9e4f41e7e860cbce19ac52e791db3b6dde1c4b0367377b581f999f340e1d6814d724edc94cb07f9c4730774', '0xb145f203eee1ac0a1a1731113ffa7a8b0b694ef2312dabc4d431660f5e0645ef5838e3e624cfe1228cfa248d48b5760501f93e6ab13d3159fc241427116c4b90359599a4cb0a86d0bb9190aa7fabff482c812db966fd2ce0a1b48cb8ac8b3bca', '0xadabe5d215c608696e03861cbd5f7401869c756b3a5aadc55f41745ad9478145d44393fec8bb6dfc4ad9236dc62b9ada0f7ca57fe2bae1b71565dbf9536d33a68b8e2090b233422313cc96afc7f1f7e0907dc7787806671541d6de8ce47c4cd0', '0xae7845fa6b06db53201c1080e01e629781817f421f28956589c6df3091ec33754f8a4bd4647a6bb1c141ac22731e3c1014865d13f3ed538dcb0f7b7576435133d9d03be655f8fbb4c9f7d83e06d1210aedd45128c2b0c9bab45a9ddde1c862a5', '0x9159eaa826a24adfa7adf6e8d2832120ebb6eccbeb3d0459ffdc338548813a2d239d22b26451fda98cc0c204d8e1ac69150b5498e0be3045300e789bcb4e210d5cd431da4bdd915a21f407ea296c20c96608ded0b70d07188e96e6c1a7b9b86b', '0xa9fc6281e2d54b46458ef564ffaed6944bff71e389d0acc11fa35d3fcd8e10c1066e0dde5b9b6516f691bb478e81c6b20865281104dcb640e29dc116daae2e884f1fe6730d639dbe0e19a532be4fb337bf52ae8408446deb393d224eee7cfa50', '0x84291a42f991bfb36358eedead3699d9176a38f6f63757742fdbb7f631f2c70178b1aedef4912fed7b6cf27e88ddc7eb0e2a6aa4b999f3eb4b662b93f386c8d78e9ac9929e21f4c5e63b12991fcde93aa64a735b75b535e730ff8dd2abb16e04', '0xa1b7fcacae181495d91765dfddf26581e8e39421579c9cbd0dd27a40ea4c54af3444a36bf85a11dda2114246eaddbdd619397424bb1eb41b5a15004b902a590ede5742cd850cf312555be24d2df8becf48f5afba5a8cd087cb7be0a521728386', '0x92feaaf540dbd84719a4889a87cdd125b7e995a6782911931fef26da9afcfbe6f86aaf5328fe1f77631491ce6239c5470f44c7791506c6ef1626803a5794e76d2be0af92f7052c29ac6264b7b9b51f267ad820afc6f881460521428496c6a5f1', '0xa525c925bfae1b89320a5054acc1fa11820f73d0cf28d273092b305467b2831fab53b6daf75fb926f332782d50e2522a19edcd85be5eb72f1497193c952d8cd0bcc5d43b39363b206eae4cb1e61668bde28a3fb2fc1e0d3d113f6dfadb799717', '0x98752bb6f5a44213f40eda6aa4ff124057c1b13b6529ab42fe575b9afa66e59b9c0ed563fb20dff62130c436c3e905ee17dd8433ba02c445b1d67182ab6504a90bbe12c26a754bbf734665c622f76c62fe2e11dd43ce04fd2b91a8463679058b', '0xa9aa9a84729f7c44219ff9e00e651e50ddea3735ef2a73fdf8ed8cd271961d8ed7af5cd724b713a89a097a3fe65a3c0202f69458a8b4c157c62a85668b12fc0d3957774bc9b35f86c184dd03bfefd5c325da717d74192cc9751c2073fe9d170e', '0xb221c1fd335a4362eff504cd95145f122bf93ea02ae162a3fb39c75583fc13a932d26050e164da97cff3e91f9a7f6ff80302c19dd1916f24acf6b93b62f36e9665a8785413b0c7d930c7f1668549910f849bca319b00e59dd01e5dec8d2edacc', '0xa71e2b1e0b16d754b848f05eda90f67bedab37709550171551050c94efba0bfc282f72aeaaa1f0330041461f5e6aa4d11537237e955e1609a469d38ed17f5c2a35a1752f546db89bfeff9eab78ec944266f1cb94c1db3334ab48df716ce408ef', '0xb990ae72768779ba0b2e66df4dd29b3dbd00f901c23b2b4a53419226ef9232acedeb498b0d0687c463e3f1eead58b20b09efcefa566fbfdfe1c6e48d32367936142d0a734143e5e63cdf86be7457723535b787a9cfcfa32fe1d61ad5a2617220', '0x8d27e7fbff77d5b9b9bbc864d5231fecf817238a6433db668d5a62a2c1ee1e5694fdd90c3293c06cc0cb15f7cbeab44d0d42be632cb9ff41fc3f6628b4b62897797d7b56126d65b694dcf3e298e3561ac8813fbd7296593ced33850426df42db', '0xa92039a08b5502d5b211a7744099c9f93fa8c90cedcb1d05e92f01886219dd464eb5fb0337496ad96ed09c987da4e5f019035c5b01cc09b2a18b8a8dd419bc5895388a07e26958f6bd26751929c25f89b8eb4a299d822e2d26fec9ef350e0d3c', '0x92dcc5a1c8c3e1b28b1524e3dd6dbecd63017c9201da9dbe077f1b82adc08c50169f56fc7b5a3b28ec6b89254de3e2fd12838a761053437883c3e01ba616670cea843754548ef84bcc397de2369adcca2ab54cd73c55dc68d87aec3fc2fe4f10'] + + JUSTIFICATION_BITS_LENGTH: Uint64 = 4 - name: MAX_CONCURRENT_REQUESTS#phase0 sources: [] spec: | - - MAX_CONCURRENT_REQUESTS = 2 + + MAX_CONCURRENT_REQUESTS: Uint64 = 2 - name: MAX_REQUEST_LIGHT_CLIENT_UPDATES#altair @@ -456,8 +400,8 @@ search: MaxRequestLightClientUpdates\s+.*yaml:"MAX_REQUEST_LIGHT_CLIENT_UPDATES" regex: true spec: | - - MAX_REQUEST_LIGHT_CLIENT_UPDATES = 2**7 + + MAX_REQUEST_LIGHT_CLIENT_UPDATES: Uint64 = 2**7 - name: NODE_ID_BITS#phase0 @@ -466,15 +410,15 @@ search: NodeIdBits\s+.*yaml:"NODE_ID_BITS" regex: true spec: | - - NODE_ID_BITS = 256 + + NODE_ID_BITS: Uint64 = 256 - name: NUM_BLOCK_TIMELINESS_DEADLINES#gloas sources: [] spec: | - - NUM_BLOCK_TIMELINESS_DEADLINES = 2 + + NUM_BLOCK_TIMELINESS_DEADLINES: Uint64 = 2 - name: PARTICIPATION_FLAG_WEIGHTS#altair @@ -487,8 +431,8 @@ - name: PAYLOAD_BUILDER_VERSION#gloas sources: [] spec: | - - PAYLOAD_BUILDER_VERSION: uint8 = 0 + + PAYLOAD_BUILDER_VERSION: Uint8 = 0 - name: PAYLOAD_STATUS_EMPTY#gloas @@ -533,42 +477,21 @@ PAYLOAD_STATUS_VALID: PayloadValidationStatus = 0 -- name: PRIMITIVE_ROOT_OF_UNITY#deneb - sources: [] - spec: | - - PRIMITIVE_ROOT_OF_UNITY = 7 - - - name: PROPOSER_WEIGHT#altair sources: - file: config/params/config.go search: ProposerWeight\s+.*yaml:"PROPOSER_WEIGHT" regex: true spec: | - - PROPOSER_WEIGHT: uint64 = 8 + + PROPOSER_WEIGHT: Uint64 = 8 - name: PTC_TIMELINESS_INDEX#gloas sources: [] spec: | - - PTC_TIMELINESS_INDEX = 1 - - -- name: RANDOM_CHALLENGE_KZG_BATCH_DOMAIN#deneb - sources: [] - spec: | - - RANDOM_CHALLENGE_KZG_BATCH_DOMAIN = b'RCKZGBATCH___V1_' - - -- name: RANDOM_CHALLENGE_KZG_CELL_BATCH_DOMAIN#fulu - sources: [] - spec: | - - RANDOM_CHALLENGE_KZG_CELL_BATCH_DOMAIN = b'RCKZGCBATCH__V1_' + + PTC_TIMELINESS_INDEX: Uint64 = 1 - name: SAFETY_DECAY#phase0 @@ -577,15 +500,15 @@ search: SafetyDecay\s+uint64 regex: true spec: | - - SAFETY_DECAY: uint64 = 10 + + SAFETY_DECAY: Uint64 = 10 - name: SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY#bellatrix sources: [] spec: | - - SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY = 128 + + SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY: Slot = 128 - name: SYNC_COMMITTEE_SUBNET_COUNT#altair @@ -594,8 +517,8 @@ search: SyncCommitteeSubnetCount\s+.*yaml:"SYNC_COMMITTEE_SUBNET_COUNT" regex: true spec: | - - SYNC_COMMITTEE_SUBNET_COUNT: uint64 = 2**2 + + SYNC_COMMITTEE_SUBNET_COUNT: Uint64 = 2**2 - name: SYNC_REWARD_WEIGHT#altair @@ -604,8 +527,8 @@ search: SyncRewardWeight\s+.*yaml:"SYNC_REWARD_WEIGHT" regex: true spec: | - - SYNC_REWARD_WEIGHT: uint64 = 2 + + SYNC_REWARD_WEIGHT: Uint64 = 2 - name: TARGET_AGGREGATORS_PER_COMMITTEE#phase0 @@ -614,8 +537,8 @@ search: TargetAggregatorsPerCommittee\s+.*yaml:"TARGET_AGGREGATORS_PER_COMMITTEE" regex: true spec: | - - TARGET_AGGREGATORS_PER_COMMITTEE = 2**4 + + TARGET_AGGREGATORS_PER_COMMITTEE: Uint64 = 2**4 - name: TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE#altair @@ -624,8 +547,8 @@ search: TargetAggregatorsPerSyncSubcommittee\s+.*yaml:"TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE" regex: true spec: | - - TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE: uint64 = 2**4 + + TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE: Uint64 = 2**4 - name: TIMELY_HEAD_FLAG_INDEX#altair @@ -634,8 +557,8 @@ search: TimelyHeadFlagIndex\s+.*yaml:"TIMELY_HEAD_FLAG_INDEX" regex: true spec: | - - TIMELY_HEAD_FLAG_INDEX = 2 + + TIMELY_HEAD_FLAG_INDEX: Uint64 = 2 - name: TIMELY_HEAD_WEIGHT#altair @@ -644,8 +567,8 @@ search: TimelyHeadWeight\s+.*yaml:"TIMELY_HEAD_WEIGHT" regex: true spec: | - - TIMELY_HEAD_WEIGHT: uint64 = 14 + + TIMELY_HEAD_WEIGHT: Uint64 = 14 - name: TIMELY_SOURCE_FLAG_INDEX#altair @@ -654,8 +577,8 @@ search: TimelySourceFlagIndex\s+.*yaml:"TIMELY_SOURCE_FLAG_INDEX" regex: true spec: | - - TIMELY_SOURCE_FLAG_INDEX = 0 + + TIMELY_SOURCE_FLAG_INDEX: Uint64 = 0 - name: TIMELY_SOURCE_WEIGHT#altair @@ -664,8 +587,8 @@ search: TimelySourceWeight\s+.*yaml:"TIMELY_SOURCE_WEIGHT" regex: true spec: | - - TIMELY_SOURCE_WEIGHT: uint64 = 14 + + TIMELY_SOURCE_WEIGHT: Uint64 = 14 - name: TIMELY_TARGET_FLAG_INDEX#altair @@ -674,8 +597,8 @@ search: TimelyTargetFlagIndex\s+.*yaml:"TIMELY_TARGET_FLAG_INDEX" regex: true spec: | - - TIMELY_TARGET_FLAG_INDEX = 1 + + TIMELY_TARGET_FLAG_INDEX: Uint64 = 1 - name: TIMELY_TARGET_WEIGHT#altair @@ -684,29 +607,29 @@ search: TimelyTargetWeight\s+.*yaml:"TIMELY_TARGET_WEIGHT" regex: true spec: | - - TIMELY_TARGET_WEIGHT: uint64 = 26 + + TIMELY_TARGET_WEIGHT: Uint64 = 26 - name: UINT256_MAX#fulu sources: [] spec: | - - UINT256_MAX: uint256 = 2**256 - 1 + + UINT256_MAX: Uint256 = 2**256 - 1 - name: UINT64_MAX#phase0 sources: [] spec: | - - UINT64_MAX: uint64 = 2**64 - 1 + + UINT64_MAX: Uint64 = 2**64 - 1 - name: UINT64_MAX_SQRT#phase0 sources: [] spec: | - - UINT64_MAX_SQRT: uint64 = 4294967295 + + UINT64_MAX_SQRT: Uint64 = 4294967295 - name: UNSET_DEPOSIT_REQUESTS_START_INDEX#electra @@ -715,8 +638,8 @@ search: UnsetDepositRequestsStartIndex\s+.*yaml:"UNSET_DEPOSIT_REQUESTS_START_INDEX" regex: true spec: | - - UNSET_DEPOSIT_REQUESTS_START_INDEX: uint64 = 2**64 - 1 + + UNSET_DEPOSIT_REQUESTS_START_INDEX: Uint64 = 2**64 - 1 - name: VERSIONED_HASH_VERSION_KZG#deneb @@ -735,8 +658,8 @@ search: WeightDenominator\s+.*yaml:"WEIGHT_DENOMINATOR" regex: true spec: | - - WEIGHT_DENOMINATOR: uint64 = 64 + + WEIGHT_DENOMINATOR: Uint64 = 64 - name: WITHDRAWAL_REQUEST_TYPE#electra diff --git a/specrefs/containers.yml b/specrefs/containers.yml index 15af0d5bf1d8..187fcdd2f1c5 100644 --- a/specrefs/containers.yml +++ b/specrefs/containers.yml @@ -28,9 +28,9 @@ - file: proto/prysm/v1alpha1/attestation.proto search: message Attestation { spec: | - + class Attestation(Container): - aggregation_bits: Bitlist[MAX_VALIDATORS_PER_COMMITTEE] + aggregation_bits: BitList[MAX_VALIDATORS_PER_COMMITTEE] data: AttestationData signature: BLSSignature @@ -40,14 +40,14 @@ - file: proto/prysm/v1alpha1/attestation.proto search: message AttestationElectra { spec: | - + class Attestation(Container): # [Modified in Electra:EIP7549] aggregation_bits: AggregationBits data: AttestationData signature: BLSSignature # [New in Electra:EIP7549] - committee_bits: Bitvector[MAX_COMMITTEES_PER_SLOT] + committee_bits: BitVector[MAX_COMMITTEES_PER_SLOT] - name: Attestation#gloas @@ -55,12 +55,12 @@ - file: proto/prysm/v1alpha1/attestation.proto search: message AttestationGloas { spec: | - + class Attestation(ProgressiveContainer(active_fields=[1] * 4)): # type: ignore aggregation_bits: AggregationBits data: AttestationData signature: BLSSignature - committee_bits: Bitvector[MAX_COMMITTEES_PER_SLOT] + committee_bits: BitVector[MAX_COMMITTEES_PER_SLOT] - name: AttestationData#phase0 @@ -306,9 +306,9 @@ - file: proto/prysm/v1alpha1/beacon_state.proto search: message BeaconState { spec: | - + class BeaconState(Container): - genesis_time: uint64 + genesis_time: Uint64 genesis_validators_root: Root slot: Slot fork: Fork @@ -318,14 +318,14 @@ historical_roots: List[Root, HISTORICAL_ROOTS_LIMIT] eth1_data: Eth1Data eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH] - eth1_deposit_index: uint64 + eth1_deposit_index: Uint64 validators: List[Validator, VALIDATOR_REGISTRY_LIMIT] balances: List[Gwei, VALIDATOR_REGISTRY_LIMIT] randao_mixes: Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR] slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] previous_epoch_attestations: List[PendingAttestation, MAX_ATTESTATIONS * SLOTS_PER_EPOCH] current_epoch_attestations: List[PendingAttestation, MAX_ATTESTATIONS * SLOTS_PER_EPOCH] - justification_bits: Bitvector[JUSTIFICATION_BITS_LENGTH] + justification_bits: BitVector[JUSTIFICATION_BITS_LENGTH] previous_justified_checkpoint: Checkpoint current_justified_checkpoint: Checkpoint finalized_checkpoint: Checkpoint @@ -336,9 +336,9 @@ - file: proto/prysm/v1alpha1/beacon_state.proto search: message BeaconStateAltair { spec: | - + class BeaconState(Container): - genesis_time: uint64 + genesis_time: Uint64 genesis_validators_root: Root slot: Slot fork: Fork @@ -348,7 +348,7 @@ historical_roots: List[Root, HISTORICAL_ROOTS_LIMIT] eth1_data: Eth1Data eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH] - eth1_deposit_index: uint64 + eth1_deposit_index: Uint64 validators: List[Validator, VALIDATOR_REGISTRY_LIMIT] balances: List[Gwei, VALIDATOR_REGISTRY_LIMIT] randao_mixes: Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR] @@ -357,12 +357,12 @@ previous_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] # [Modified in Altair] current_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] - justification_bits: Bitvector[JUSTIFICATION_BITS_LENGTH] + justification_bits: BitVector[JUSTIFICATION_BITS_LENGTH] previous_justified_checkpoint: Checkpoint current_justified_checkpoint: Checkpoint finalized_checkpoint: Checkpoint # [New in Altair] - inactivity_scores: List[uint64, VALIDATOR_REGISTRY_LIMIT] + inactivity_scores: List[Uint64, VALIDATOR_REGISTRY_LIMIT] # [New in Altair] current_sync_committee: SyncCommittee # [New in Altair] @@ -374,9 +374,9 @@ - file: proto/prysm/v1alpha1/beacon_state.proto search: message BeaconStateBellatrix { spec: | - + class BeaconState(Container): - genesis_time: uint64 + genesis_time: Uint64 genesis_validators_root: Root slot: Slot fork: Fork @@ -386,18 +386,18 @@ historical_roots: List[Root, HISTORICAL_ROOTS_LIMIT] eth1_data: Eth1Data eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH] - eth1_deposit_index: uint64 + eth1_deposit_index: Uint64 validators: List[Validator, VALIDATOR_REGISTRY_LIMIT] balances: List[Gwei, VALIDATOR_REGISTRY_LIMIT] randao_mixes: Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR] slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] previous_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] current_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] - justification_bits: Bitvector[JUSTIFICATION_BITS_LENGTH] + justification_bits: BitVector[JUSTIFICATION_BITS_LENGTH] previous_justified_checkpoint: Checkpoint current_justified_checkpoint: Checkpoint finalized_checkpoint: Checkpoint - inactivity_scores: List[uint64, VALIDATOR_REGISTRY_LIMIT] + inactivity_scores: List[Uint64, VALIDATOR_REGISTRY_LIMIT] current_sync_committee: SyncCommittee next_sync_committee: SyncCommittee # [New in Bellatrix] @@ -409,9 +409,9 @@ - file: proto/prysm/v1alpha1/beacon_state.proto search: message BeaconStateCapella { spec: | - + class BeaconState(Container): - genesis_time: uint64 + genesis_time: Uint64 genesis_validators_root: Root slot: Slot fork: Fork @@ -421,18 +421,18 @@ historical_roots: List[Root, HISTORICAL_ROOTS_LIMIT] eth1_data: Eth1Data eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH] - eth1_deposit_index: uint64 + eth1_deposit_index: Uint64 validators: List[Validator, VALIDATOR_REGISTRY_LIMIT] balances: List[Gwei, VALIDATOR_REGISTRY_LIMIT] randao_mixes: Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR] slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] previous_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] current_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] - justification_bits: Bitvector[JUSTIFICATION_BITS_LENGTH] + justification_bits: BitVector[JUSTIFICATION_BITS_LENGTH] previous_justified_checkpoint: Checkpoint current_justified_checkpoint: Checkpoint finalized_checkpoint: Checkpoint - inactivity_scores: List[uint64, VALIDATOR_REGISTRY_LIMIT] + inactivity_scores: List[Uint64, VALIDATOR_REGISTRY_LIMIT] current_sync_committee: SyncCommittee next_sync_committee: SyncCommittee # [Modified in Capella] @@ -450,9 +450,9 @@ - file: proto/prysm/v1alpha1/beacon_state.proto search: message BeaconStateDeneb { spec: | - + class BeaconState(Container): - genesis_time: uint64 + genesis_time: Uint64 genesis_validators_root: Root slot: Slot fork: Fork @@ -462,18 +462,18 @@ historical_roots: List[Root, HISTORICAL_ROOTS_LIMIT] eth1_data: Eth1Data eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH] - eth1_deposit_index: uint64 + eth1_deposit_index: Uint64 validators: List[Validator, VALIDATOR_REGISTRY_LIMIT] balances: List[Gwei, VALIDATOR_REGISTRY_LIMIT] randao_mixes: Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR] slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] previous_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] current_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] - justification_bits: Bitvector[JUSTIFICATION_BITS_LENGTH] + justification_bits: BitVector[JUSTIFICATION_BITS_LENGTH] previous_justified_checkpoint: Checkpoint current_justified_checkpoint: Checkpoint finalized_checkpoint: Checkpoint - inactivity_scores: List[uint64, VALIDATOR_REGISTRY_LIMIT] + inactivity_scores: List[Uint64, VALIDATOR_REGISTRY_LIMIT] current_sync_committee: SyncCommittee next_sync_committee: SyncCommittee # [Modified in Deneb:EIP4844] @@ -488,9 +488,9 @@ - file: proto/prysm/v1alpha1/beacon_state.proto search: message BeaconStateElectra { spec: | - + class BeaconState(Container): - genesis_time: uint64 + genesis_time: Uint64 genesis_validators_root: Root slot: Slot fork: Fork @@ -500,18 +500,18 @@ historical_roots: List[Root, HISTORICAL_ROOTS_LIMIT] eth1_data: Eth1Data eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH] - eth1_deposit_index: uint64 + eth1_deposit_index: Uint64 validators: List[Validator, VALIDATOR_REGISTRY_LIMIT] balances: List[Gwei, VALIDATOR_REGISTRY_LIMIT] randao_mixes: Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR] slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] previous_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] current_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] - justification_bits: Bitvector[JUSTIFICATION_BITS_LENGTH] + justification_bits: BitVector[JUSTIFICATION_BITS_LENGTH] previous_justified_checkpoint: Checkpoint current_justified_checkpoint: Checkpoint finalized_checkpoint: Checkpoint - inactivity_scores: List[uint64, VALIDATOR_REGISTRY_LIMIT] + inactivity_scores: List[Uint64, VALIDATOR_REGISTRY_LIMIT] current_sync_committee: SyncCommittee next_sync_committee: SyncCommittee latest_execution_payload_header: ExecutionPayloadHeader @@ -519,7 +519,7 @@ next_withdrawal_validator_index: ValidatorIndex historical_summaries: List[HistoricalSummary, HISTORICAL_ROOTS_LIMIT] # [New in Electra:EIP6110] - deposit_requests_start_index: uint64 + deposit_requests_start_index: Uint64 # [New in Electra:EIP7251] deposit_balance_to_consume: Gwei # [New in Electra:EIP7251] @@ -543,9 +543,9 @@ - file: proto/prysm/v1alpha1/beacon_state.proto search: message BeaconStateFulu { spec: | - + class BeaconState(Container): - genesis_time: uint64 + genesis_time: Uint64 genesis_validators_root: Root slot: Slot fork: Fork @@ -555,25 +555,25 @@ historical_roots: List[Root, HISTORICAL_ROOTS_LIMIT] eth1_data: Eth1Data eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH] - eth1_deposit_index: uint64 + eth1_deposit_index: Uint64 validators: List[Validator, VALIDATOR_REGISTRY_LIMIT] balances: List[Gwei, VALIDATOR_REGISTRY_LIMIT] randao_mixes: Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR] slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] previous_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] current_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] - justification_bits: Bitvector[JUSTIFICATION_BITS_LENGTH] + justification_bits: BitVector[JUSTIFICATION_BITS_LENGTH] previous_justified_checkpoint: Checkpoint current_justified_checkpoint: Checkpoint finalized_checkpoint: Checkpoint - inactivity_scores: List[uint64, VALIDATOR_REGISTRY_LIMIT] + inactivity_scores: List[Uint64, VALIDATOR_REGISTRY_LIMIT] current_sync_committee: SyncCommittee next_sync_committee: SyncCommittee latest_execution_payload_header: ExecutionPayloadHeader next_withdrawal_index: WithdrawalIndex next_withdrawal_validator_index: ValidatorIndex historical_summaries: List[HistoricalSummary, HISTORICAL_ROOTS_LIMIT] - deposit_requests_start_index: uint64 + deposit_requests_start_index: Uint64 deposit_balance_to_consume: Gwei exit_balance_to_consume: Gwei earliest_exit_epoch: Epoch @@ -589,9 +589,9 @@ - name: BeaconState#gloas sources: [] spec: | - + class BeaconState(ProgressiveContainer(active_fields=[1] * 46)): # type: ignore - genesis_time: uint64 + genesis_time: Uint64 genesis_validators_root: Root slot: Slot fork: Fork @@ -601,7 +601,7 @@ historical_roots: List[Root, HISTORICAL_ROOTS_LIMIT] eth1_data: Eth1Data eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH] - eth1_deposit_index: uint64 + eth1_deposit_index: Uint64 # [Modified in Gloas:EIP7688] validators: ProgressiveList[Validator] # [Modified in Gloas:EIP7688] @@ -612,12 +612,12 @@ previous_epoch_participation: ProgressiveList[ParticipationFlags] # [Modified in Gloas:EIP7688] current_epoch_participation: ProgressiveList[ParticipationFlags] - justification_bits: Bitvector[JUSTIFICATION_BITS_LENGTH] + justification_bits: BitVector[JUSTIFICATION_BITS_LENGTH] previous_justified_checkpoint: Checkpoint current_justified_checkpoint: Checkpoint finalized_checkpoint: Checkpoint # [Modified in Gloas:EIP7688] - inactivity_scores: ProgressiveList[uint64] + inactivity_scores: ProgressiveList[Uint64] current_sync_committee: SyncCommittee next_sync_committee: SyncCommittee # [Modified in Gloas:EIP7732] @@ -627,7 +627,7 @@ next_withdrawal_index: WithdrawalIndex next_withdrawal_validator_index: ValidatorIndex historical_summaries: List[HistoricalSummary, HISTORICAL_ROOTS_LIMIT] - deposit_requests_start_index: uint64 + deposit_requests_start_index: Uint64 deposit_balance_to_consume: Gwei exit_balance_to_consume: Gwei earliest_exit_epoch: Epoch @@ -645,7 +645,7 @@ # [New in Gloas:EIP7732] next_withdrawal_builder_index: BuilderIndex # [New in Gloas:EIP7732] - execution_payload_availability: Bitvector[SLOTS_PER_HISTORICAL_ROOT] + execution_payload_availability: BitVector[SLOTS_PER_HISTORICAL_ROOT] # [New in Gloas:EIP7732] builder_pending_payments: Vector[BuilderPendingPayment, 2 * SLOTS_PER_EPOCH] # [New in Gloas:EIP7732] @@ -661,9 +661,9 @@ - name: BeaconState#heze sources: [] spec: | - + class BeaconState(ProgressiveContainer(active_fields=[1] * 46)): # type: ignore - genesis_time: uint64 + genesis_time: Uint64 genesis_validators_root: Root slot: Slot fork: Fork @@ -673,25 +673,25 @@ historical_roots: List[Root, HISTORICAL_ROOTS_LIMIT] eth1_data: Eth1Data eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH] - eth1_deposit_index: uint64 + eth1_deposit_index: Uint64 validators: ProgressiveList[Validator] balances: ProgressiveList[Gwei] randao_mixes: Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR] slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] previous_epoch_participation: ProgressiveList[ParticipationFlags] current_epoch_participation: ProgressiveList[ParticipationFlags] - justification_bits: Bitvector[JUSTIFICATION_BITS_LENGTH] + justification_bits: BitVector[JUSTIFICATION_BITS_LENGTH] previous_justified_checkpoint: Checkpoint current_justified_checkpoint: Checkpoint finalized_checkpoint: Checkpoint - inactivity_scores: ProgressiveList[uint64] + inactivity_scores: ProgressiveList[Uint64] current_sync_committee: SyncCommittee next_sync_committee: SyncCommittee latest_block_hash: Hash32 next_withdrawal_index: WithdrawalIndex next_withdrawal_validator_index: ValidatorIndex historical_summaries: List[HistoricalSummary, HISTORICAL_ROOTS_LIMIT] - deposit_requests_start_index: uint64 + deposit_requests_start_index: Uint64 deposit_balance_to_consume: Gwei exit_balance_to_consume: Gwei earliest_exit_epoch: Epoch @@ -703,7 +703,7 @@ proposer_lookahead: Vector[ValidatorIndex, (MIN_SEED_LOOKAHEAD + 1) * SLOTS_PER_EPOCH] builders: ProgressiveList[Builder] next_withdrawal_builder_index: BuilderIndex - execution_payload_availability: Bitvector[SLOTS_PER_HISTORICAL_ROOT] + execution_payload_availability: BitVector[SLOTS_PER_HISTORICAL_ROOT] builder_pending_payments: Vector[BuilderPendingPayment, 2 * SLOTS_PER_EPOCH] builder_pending_withdrawals: ProgressiveList[BuilderPendingWithdrawal] # [Modified in Heze:EIP7805] @@ -715,9 +715,9 @@ - name: BeaconState#heze sources: [] spec: | - + class BeaconState(ProgressiveContainer(active_fields=[1] * 46)): # type: ignore - genesis_time: uint64 + genesis_time: Uint64 genesis_validators_root: Root slot: Slot fork: Fork @@ -727,25 +727,25 @@ historical_roots: List[Root, HISTORICAL_ROOTS_LIMIT] eth1_data: Eth1Data eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH] - eth1_deposit_index: uint64 + eth1_deposit_index: Uint64 validators: ProgressiveList[Validator] balances: ProgressiveList[Gwei] randao_mixes: Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR] slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] previous_epoch_participation: ProgressiveList[ParticipationFlags] current_epoch_participation: ProgressiveList[ParticipationFlags] - justification_bits: Bitvector[JUSTIFICATION_BITS_LENGTH] + justification_bits: BitVector[JUSTIFICATION_BITS_LENGTH] previous_justified_checkpoint: Checkpoint current_justified_checkpoint: Checkpoint finalized_checkpoint: Checkpoint - inactivity_scores: ProgressiveList[uint64] + inactivity_scores: ProgressiveList[Uint64] current_sync_committee: SyncCommittee next_sync_committee: SyncCommittee latest_block_hash: Hash32 next_withdrawal_index: WithdrawalIndex next_withdrawal_validator_index: ValidatorIndex historical_summaries: List[HistoricalSummary, HISTORICAL_ROOTS_LIMIT] - deposit_requests_start_index: uint64 + deposit_requests_start_index: Uint64 deposit_balance_to_consume: Gwei exit_balance_to_consume: Gwei earliest_exit_epoch: Epoch @@ -757,7 +757,7 @@ proposer_lookahead: Vector[ValidatorIndex, (MIN_SEED_LOOKAHEAD + 1) * SLOTS_PER_EPOCH] builders: ProgressiveList[Builder] next_withdrawal_builder_index: BuilderIndex - execution_payload_availability: Bitvector[SLOTS_PER_HISTORICAL_ROOT] + execution_payload_availability: BitVector[SLOTS_PER_HISTORICAL_ROOT] builder_pending_payments: Vector[BuilderPendingPayment, 2 * SLOTS_PER_EPOCH] builder_pending_withdrawals: ProgressiveList[BuilderPendingWithdrawal] # [Modified in Heze:EIP7805] @@ -795,10 +795,10 @@ - name: Builder#gloas sources: [] spec: | - + class Builder(Container): pubkey: BLSPubkey - version: uint8 + version: Uint8 execution_address: ExecutionAddress balance: Gwei deposit_epoch: Epoch @@ -969,23 +969,23 @@ - file: proto/engine/v1/electra.proto search: message DepositRequest { spec: | - + class DepositRequest(Container): pubkey: BLSPubkey withdrawal_credentials: Bytes32 amount: Gwei signature: BLSSignature - index: uint64 + index: Uint64 - name: Eth1Block#phase0 sources: [] spec: | - + class Eth1Block(Container): - timestamp: uint64 + timestamp: Uint64 deposit_root: Root - deposit_count: uint64 + deposit_count: Uint64 - name: Eth1Data#phase0 @@ -993,10 +993,10 @@ - file: proto/prysm/v1alpha1/beacon_core_types.proto search: message Eth1Data { spec: | - + class Eth1Data(Container): deposit_root: Root - deposit_count: uint64 + deposit_count: Uint64 block_hash: Hash32 @@ -1005,7 +1005,7 @@ - file: proto/engine/v1/execution_engine.proto search: message ExecutionPayload { spec: | - + class ExecutionPayload(Container): parent_hash: Hash32 fee_recipient: ExecutionAddress @@ -1013,12 +1013,12 @@ receipts_root: Bytes32 logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM] prev_randao: Bytes32 - block_number: uint64 - gas_limit: uint64 - gas_used: uint64 - timestamp: uint64 + block_number: Uint64 + gas_limit: Uint64 + gas_used: Uint64 + timestamp: Uint64 extra_data: ByteList[MAX_EXTRA_DATA_BYTES] - base_fee_per_gas: uint256 + base_fee_per_gas: Uint256 block_hash: Hash32 transactions: List[Transaction, MAX_TRANSACTIONS_PER_PAYLOAD] @@ -1028,7 +1028,7 @@ - file: proto/engine/v1/execution_engine.proto search: message ExecutionPayloadCapella { spec: | - + class ExecutionPayload(Container): parent_hash: Hash32 fee_recipient: ExecutionAddress @@ -1036,12 +1036,12 @@ receipts_root: Bytes32 logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM] prev_randao: Bytes32 - block_number: uint64 - gas_limit: uint64 - gas_used: uint64 - timestamp: uint64 + block_number: Uint64 + gas_limit: Uint64 + gas_used: Uint64 + timestamp: Uint64 extra_data: ByteList[MAX_EXTRA_DATA_BYTES] - base_fee_per_gas: uint256 + base_fee_per_gas: Uint256 block_hash: Hash32 transactions: List[Transaction, MAX_TRANSACTIONS_PER_PAYLOAD] # [New in Capella] @@ -1053,7 +1053,7 @@ - file: proto/engine/v1/execution_engine.proto search: message ExecutionPayloadDeneb { spec: | - + class ExecutionPayload(Container): parent_hash: Hash32 fee_recipient: ExecutionAddress @@ -1061,25 +1061,25 @@ receipts_root: Bytes32 logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM] prev_randao: Bytes32 - block_number: uint64 - gas_limit: uint64 - gas_used: uint64 - timestamp: uint64 + block_number: Uint64 + gas_limit: Uint64 + gas_used: Uint64 + timestamp: Uint64 extra_data: ByteList[MAX_EXTRA_DATA_BYTES] - base_fee_per_gas: uint256 + base_fee_per_gas: Uint256 block_hash: Hash32 transactions: List[Transaction, MAX_TRANSACTIONS_PER_PAYLOAD] withdrawals: List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD] # [New in Deneb:EIP4844] - blob_gas_used: uint64 + blob_gas_used: Uint64 # [New in Deneb:EIP4844] - excess_blob_gas: uint64 + excess_blob_gas: Uint64 - name: ExecutionPayload#gloas sources: [] spec: | - + class ExecutionPayload(ProgressiveContainer(active_fields=[1] * 19)): # type: ignore parent_hash: Hash32 fee_recipient: ExecutionAddress @@ -1087,36 +1087,36 @@ receipts_root: Bytes32 logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM] prev_randao: Bytes32 - block_number: uint64 - gas_limit: uint64 - gas_used: uint64 - timestamp: uint64 + block_number: Uint64 + gas_limit: Uint64 + gas_used: Uint64 + timestamp: Uint64 extra_data: ByteList[MAX_EXTRA_DATA_BYTES] - base_fee_per_gas: uint256 + base_fee_per_gas: Uint256 block_hash: Hash32 # [Modified in Gloas:EIP7688] transactions: ProgressiveList[Transaction] # [Modified in Gloas:EIP7688] withdrawals: ProgressiveList[Withdrawal] - blob_gas_used: uint64 - excess_blob_gas: uint64 + blob_gas_used: Uint64 + excess_blob_gas: Uint64 # [New in Gloas:EIP7928] block_access_list: BlockAccessList # [New in Gloas:EIP7843] - slot_number: uint64 + slot_number: Uint64 - name: ExecutionPayloadBid#gloas sources: [] spec: | - + class ExecutionPayloadBid(ProgressiveContainer(active_fields=[1] * 12)): # type: ignore parent_block_hash: Hash32 parent_block_root: Root block_hash: Hash32 prev_randao: Bytes32 fee_recipient: ExecutionAddress - gas_limit: uint64 + gas_limit: Uint64 builder_index: BuilderIndex slot: Slot value: Gwei @@ -1128,14 +1128,14 @@ - name: ExecutionPayloadBid#heze sources: [] spec: | - + class ExecutionPayloadBid(ProgressiveContainer(active_fields=[1] * 13)): # type: ignore parent_block_hash: Hash32 parent_block_root: Root block_hash: Hash32 prev_randao: Bytes32 fee_recipient: ExecutionAddress - gas_limit: uint64 + gas_limit: Uint64 builder_index: BuilderIndex slot: Slot value: Gwei @@ -1143,7 +1143,7 @@ blob_kzg_commitments: ProgressiveList[KZGCommitment] execution_requests_root: Root # [New in Heze:EIP7805] - inclusion_list_bits: Bitvector[INCLUSION_LIST_COMMITTEE_SIZE] + inclusion_list_bits: BitVector[INCLUSION_LIST_COMMITTEE_SIZE] - name: ExecutionPayloadEnvelope#gloas @@ -1163,7 +1163,7 @@ - file: proto/engine/v1/execution_engine.proto search: message ExecutionPayloadHeader { spec: | - + class ExecutionPayloadHeader(Container): parent_hash: Hash32 fee_recipient: ExecutionAddress @@ -1171,12 +1171,12 @@ receipts_root: Bytes32 logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM] prev_randao: Bytes32 - block_number: uint64 - gas_limit: uint64 - gas_used: uint64 - timestamp: uint64 + block_number: Uint64 + gas_limit: Uint64 + gas_used: Uint64 + timestamp: Uint64 extra_data: ByteList[MAX_EXTRA_DATA_BYTES] - base_fee_per_gas: uint256 + base_fee_per_gas: Uint256 block_hash: Hash32 transactions_root: Root @@ -1186,7 +1186,7 @@ - file: proto/engine/v1/execution_engine.proto search: message ExecutionPayloadHeaderCapella { spec: | - + class ExecutionPayloadHeader(Container): parent_hash: Hash32 fee_recipient: ExecutionAddress @@ -1194,12 +1194,12 @@ receipts_root: Bytes32 logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM] prev_randao: Bytes32 - block_number: uint64 - gas_limit: uint64 - gas_used: uint64 - timestamp: uint64 + block_number: Uint64 + gas_limit: Uint64 + gas_used: Uint64 + timestamp: Uint64 extra_data: ByteList[MAX_EXTRA_DATA_BYTES] - base_fee_per_gas: uint256 + base_fee_per_gas: Uint256 block_hash: Hash32 transactions_root: Root # [New in Capella] @@ -1211,7 +1211,7 @@ - file: proto/engine/v1/execution_engine.proto search: message ExecutionPayloadHeaderDeneb { spec: | - + class ExecutionPayloadHeader(Container): parent_hash: Hash32 fee_recipient: ExecutionAddress @@ -1219,19 +1219,19 @@ receipts_root: Bytes32 logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM] prev_randao: Bytes32 - block_number: uint64 - gas_limit: uint64 - gas_used: uint64 - timestamp: uint64 + block_number: Uint64 + gas_limit: Uint64 + gas_used: Uint64 + timestamp: Uint64 extra_data: ByteList[MAX_EXTRA_DATA_BYTES] - base_fee_per_gas: uint256 + base_fee_per_gas: Uint256 block_hash: Hash32 transactions_root: Root withdrawals_root: Root # [New in Deneb:EIP4844] - blob_gas_used: uint64 + blob_gas_used: Uint64 # [New in Deneb:EIP4844] - excess_blob_gas: uint64 + excess_blob_gas: Uint64 - name: ExecutionRequests#electra @@ -1576,18 +1576,18 @@ - name: PartialDataColumnPartsMetadata#fulu sources: [] spec: | - + class PartialDataColumnPartsMetadata(Container): - available: Bitlist[MAX_BLOB_COMMITMENTS_PER_BLOCK] - requests: Bitlist[MAX_BLOB_COMMITMENTS_PER_BLOCK] + available: BitList[MAX_BLOB_COMMITMENTS_PER_BLOCK] + requests: BitList[MAX_BLOB_COMMITMENTS_PER_BLOCK] - name: PartialDataColumnSidecar#fulu sources: [] spec: | - + class PartialDataColumnSidecar(Container): - cells_present_bitmap: Bitlist[MAX_BLOB_COMMITMENTS_PER_BLOCK] + cells_present_bitmap: BitList[MAX_BLOB_COMMITMENTS_PER_BLOCK] partial_column: List[Cell, MAX_BLOB_COMMITMENTS_PER_BLOCK] kzg_proofs: List[KZGProof, MAX_BLOB_COMMITMENTS_PER_BLOCK] # Optional header, only sent on eager pushes @@ -1597,9 +1597,9 @@ - name: PartialDataColumnSidecar#gloas sources: [] spec: | - + class PartialDataColumnSidecar(Container): - cells_present_bitmap: ProgressiveBitlist + cells_present_bitmap: ProgressiveBitList partial_column: ProgressiveList[Cell] kzg_proofs: ProgressiveList[KZGProof] @@ -1607,9 +1607,9 @@ - name: PayloadAttestation#gloas sources: [] spec: | - + class PayloadAttestation(ProgressiveContainer(active_fields=[1] * 3)): # type: ignore - aggregation_bits: Bitvector[PTC_SIZE] + aggregation_bits: BitVector[PTC_SIZE] data: PayloadAttestationData signature: BLSSignature @@ -1617,12 +1617,12 @@ - name: PayloadAttestationData#gloas sources: [] spec: | - + class PayloadAttestationData(Container): beacon_block_root: Root slot: Slot - payload_present: boolean - blob_data_available: boolean + payload_present: Boolean + blob_data_available: Boolean - name: PayloadAttestationMessage#gloas @@ -1640,9 +1640,9 @@ - file: proto/prysm/v1alpha1/beacon_state.proto search: message PendingAttestation { spec: | - + class PendingAttestation(Container): - aggregation_bits: Bitlist[MAX_VALIDATORS_PER_COMMITTEE] + aggregation_bits: BitList[MAX_VALIDATORS_PER_COMMITTEE] data: AttestationData inclusion_delay: Slot proposer_index: ValidatorIndex @@ -1690,23 +1690,23 @@ - file: proto/prysm/v1alpha1/beacon_state.proto search: message PowBlock { spec: | - + class PowBlock(Container): block_hash: Hash32 parent_hash: Hash32 - total_difficulty: uint256 + total_difficulty: Uint256 - name: ProposerPreferences#gloas sources: [] spec: | - + class ProposerPreferences(Container): dependent_root: Root proposal_slot: Slot validator_index: ValidatorIndex fee_recipient: ExecutionAddress - target_gas_limit: uint64 + target_gas_limit: Uint64 - name: ProposerSlashing#phase0 @@ -1873,9 +1873,9 @@ - file: proto/prysm/v1alpha1/beacon_core_types.proto search: message SyncAggregate { spec: | - + class SyncAggregate(Container): - sync_committee_bits: Bitvector[SYNC_COMMITTEE_SIZE] + sync_committee_bits: BitVector[SYNC_COMMITTEE_SIZE] sync_committee_signature: BLSSignature @@ -1884,10 +1884,10 @@ - file: proto/prysm/v1alpha1/beacon_state.proto search: message SyncAggregatorSelectionData { spec: | - + class SyncAggregatorSelectionData(Container): slot: Slot - subcommittee_index: uint64 + subcommittee_index: Uint64 - name: SyncCommittee#altair @@ -1906,12 +1906,12 @@ - file: proto/prysm/v1alpha1/sync_committee.proto search: message SyncCommitteeContribution { spec: | - + class SyncCommitteeContribution(Container): slot: Slot beacon_block_root: Root - subcommittee_index: uint64 - aggregation_bits: Bitvector[SYNC_COMMITTEE_SIZE // SYNC_COMMITTEE_SUBNET_COUNT] + subcommittee_index: Uint64 + aggregation_bits: BitVector[SYNC_COMMITTEE_SIZE // SYNC_COMMITTEE_SUBNET_COUNT] signature: BLSSignature @@ -1933,12 +1933,12 @@ - file: proto/prysm/v1alpha1/beacon_core_types.proto search: message Validator { spec: | - + class Validator(Container): pubkey: BLSPubkey withdrawal_credentials: Bytes32 effective_balance: Gwei - slashed: boolean + slashed: Boolean activation_eligibility_epoch: Epoch activation_epoch: Epoch exit_epoch: Epoch diff --git a/specrefs/dataclasses.yml b/specrefs/dataclasses.yml index 668ea2b39f16..faf1ce8e9d7f 100644 --- a/specrefs/dataclasses.yml +++ b/specrefs/dataclasses.yml @@ -1,10 +1,10 @@ - name: BlobParameters#fulu sources: [] spec: | - + class BlobParameters: epoch: Epoch - max_blobs_per_block: uint64 + max_blobs_per_block: Uint64 - name: BlobsBundle#deneb @@ -37,35 +37,35 @@ - name: ExpectedWithdrawals#capella sources: [] spec: | - + class ExpectedWithdrawals: withdrawals: Sequence[Withdrawal] - processed_sweep_withdrawals_count: uint64 + processed_sweep_withdrawals_count: Uint64 - name: ExpectedWithdrawals#electra sources: [] spec: | - + class ExpectedWithdrawals: withdrawals: Sequence[Withdrawal] # [New in Electra:EIP7251] - processed_partial_withdrawals_count: uint64 - processed_sweep_withdrawals_count: uint64 + processed_partial_withdrawals_count: Uint64 + processed_sweep_withdrawals_count: Uint64 - name: ExpectedWithdrawals#gloas sources: [] spec: | - + class ExpectedWithdrawals: withdrawals: Sequence[Withdrawal] # [New in Gloas:EIP7732] - processed_builder_withdrawals_count: uint64 - processed_partial_withdrawals_count: uint64 + processed_builder_withdrawals_count: Uint64 + processed_partial_withdrawals_count: Uint64 # [New in Gloas:EIP7732] - processed_builders_sweep_count: uint64 - processed_sweep_withdrawals_count: uint64 + processed_builders_sweep_count: Uint64 + processed_sweep_withdrawals_count: Uint64 - name: FastConfirmationStore#phase0 @@ -129,10 +129,10 @@ - file: consensus-types/blocks/get_payload.go search: GetPayloadResponseV(1|2 spec: | - + class GetPayloadResponse: execution_payload: ExecutionPayload - block_value: uint256 + block_value: Uint256 - name: GetPayloadResponse#deneb @@ -142,10 +142,10 @@ - file: consensus-types/blocks/get_payload.go search: GetPayloadResponseV(1|2|3 spec: | - + class GetPayloadResponse: execution_payload: ExecutionPayload - block_value: uint256 + block_value: Uint256 # [New in Deneb:EIP4844] blobs_bundle: BlobsBundle @@ -157,10 +157,10 @@ - file: consensus-types/blocks/get_payload.go search: GetPayloadResponseV(1|2|3|4 spec: | - + class GetPayloadResponse: execution_payload: ExecutionPayload - block_value: uint256 + block_value: Uint256 blobs_bundle: BlobsBundle # [New in Electra] execution_requests: Sequence[bytes] @@ -173,10 +173,10 @@ - file: consensus-types/blocks/get_payload.go search: GetPayloadResponseV(1|2|3|4|5 spec: | - + class GetPayloadResponse: execution_payload: ExecutionPayload - block_value: uint256 + block_value: Uint256 # [Modified in Fulu:EIP7594] blobs_bundle: BlobsBundle execution_requests: Sequence[bytes] @@ -185,12 +185,12 @@ - name: InclusionListStore#heze sources: [] spec: | - + class InclusionListStore: - inclusion_lists: DefaultDict[Root, Dict[Root, InclusionList]] = field( + inclusion_lists: DefaultDict[Root, Dict[Root, SignedInclusionList]] = field( default_factory=lambda: defaultdict(dict) ) - inclusion_list_timeliness: Dict[Root, boolean] = field(default_factory=dict) + inclusion_list_timeliness: Dict[Root, Boolean] = field(default_factory=dict) equivocators: DefaultDict[Root, Set[ValidatorIndex]] = field( default_factory=lambda: defaultdict(set) ) @@ -209,18 +209,18 @@ - name: LatestMessage#gloas sources: [] spec: | - + @dataclass(eq=True, frozen=True) class LatestMessage: slot: Slot root: Root - payload_present: boolean + payload_present: Boolean - name: LightClientStore#altair sources: [] spec: | - + class LightClientStore: # Header that is finalized finalized_header: LightClientHeader @@ -232,14 +232,14 @@ # Most recent available reasonably-safe header optimistic_header: LightClientHeader # Max number of active participants in a sync committee (used to calculate safety threshold) - previous_max_active_participants: uint64 - current_max_active_participants: uint64 + previous_max_active_participants: Uint64 + current_max_active_participants: Uint64 - name: LightClientStore#capella sources: [] spec: | - + class LightClientStore: # [Modified in Capella] finalized_header: LightClientHeader @@ -249,8 +249,8 @@ best_valid_update: Optional[LightClientUpdate] # [Modified in Capella] optimistic_header: LightClientHeader - previous_max_active_participants: uint64 - current_max_active_participants: uint64 + previous_max_active_participants: Uint64 + current_max_active_participants: Uint64 - name: NewPayloadRequest#bellatrix @@ -306,9 +306,9 @@ search: ^message PayloadAttributes\s*\{ regex: true spec: | - + class PayloadAttributes: - timestamp: uint64 + timestamp: Uint64 prev_randao: Bytes32 suggested_fee_recipient: ExecutionAddress @@ -319,9 +319,9 @@ search: ^message PayloadAttributesV2 regex: true spec: | - + class PayloadAttributes: - timestamp: uint64 + timestamp: Uint64 prev_randao: Bytes32 suggested_fee_recipient: ExecutionAddress # [New in Capella] @@ -334,9 +334,9 @@ search: ^message PayloadAttributesV3 regex: true spec: | - + class PayloadAttributes: - timestamp: uint64 + timestamp: Uint64 prev_randao: Bytes32 suggested_fee_recipient: ExecutionAddress withdrawals: Sequence[Withdrawal] @@ -347,31 +347,31 @@ - name: PayloadAttributes#gloas sources: [] spec: | - + class PayloadAttributes: - timestamp: uint64 + timestamp: Uint64 prev_randao: Bytes32 suggested_fee_recipient: ExecutionAddress withdrawals: Sequence[Withdrawal] parent_beacon_block_root: Root # [New in Gloas:EIP7843] - slot_number: uint64 + slot_number: Uint64 # [New in Gloas] - target_gas_limit: uint64 + target_gas_limit: Uint64 - name: PayloadAttributes#heze sources: [] spec: | - + class PayloadAttributes: - timestamp: uint64 + timestamp: Uint64 prev_randao: Bytes32 suggested_fee_recipient: ExecutionAddress withdrawals: Sequence[Withdrawal] parent_beacon_block_root: Root - slot_number: uint64 - target_gas_limit: uint64 + slot_number: Uint64 + target_gas_limit: Uint64 # [New in Heze:EIP7805] inclusion_list_transactions: Sequence[Transaction] @@ -379,11 +379,11 @@ - name: Seen#phase0 sources: [] spec: | - + class Seen: proposer_slots: Set[Tuple[ValidatorIndex, Slot]] aggregator_epochs: Set[Tuple[ValidatorIndex, Epoch]] - aggregate_data_roots: Dict[Root, Set[Tuple[boolean, ...]]] + aggregate_data_roots: Dict[Root, Set[Tuple[Boolean, ...]]] voluntary_exit_indices: Set[ValidatorIndex] proposer_slashing_indices: Set[ValidatorIndex] attester_slashing_indices: Set[ValidatorIndex] @@ -393,38 +393,38 @@ - name: Seen#altair sources: [] spec: | - + class Seen: proposer_slots: Set[Tuple[ValidatorIndex, Slot]] aggregator_epochs: Set[Tuple[ValidatorIndex, Epoch]] - aggregate_data_roots: Dict[Root, Set[Tuple[boolean, ...]]] + aggregate_data_roots: Dict[Root, Set[Tuple[Boolean, ...]]] voluntary_exit_indices: Set[ValidatorIndex] proposer_slashing_indices: Set[ValidatorIndex] attester_slashing_indices: Set[ValidatorIndex] attestation_validator_epochs: Set[Tuple[ValidatorIndex, Epoch]] # [New in Altair] - sync_contribution_aggregator_slots: Set[Tuple[ValidatorIndex, Slot, uint64]] + sync_contribution_aggregator_slots: Set[Tuple[ValidatorIndex, Slot, Uint64]] # [New in Altair] - sync_contribution_data: Dict[Tuple[Slot, Root, uint64], Set[Tuple[boolean, ...]]] + sync_contribution_data: Dict[Tuple[Slot, Root, Uint64], Set[Tuple[Boolean, ...]]] # [New in Altair] - sync_message_validator_slots: Set[Tuple[Slot, ValidatorIndex, uint64]] + sync_message_validator_slots: Set[Tuple[Slot, ValidatorIndex, Uint64]] - name: Seen#capella sources: [] spec: | - + class Seen: proposer_slots: Set[Tuple[ValidatorIndex, Slot]] aggregator_epochs: Set[Tuple[ValidatorIndex, Epoch]] - aggregate_data_roots: Dict[Root, Set[Tuple[boolean, ...]]] + aggregate_data_roots: Dict[Root, Set[Tuple[Boolean, ...]]] voluntary_exit_indices: Set[ValidatorIndex] proposer_slashing_indices: Set[ValidatorIndex] attester_slashing_indices: Set[ValidatorIndex] attestation_validator_epochs: Set[Tuple[ValidatorIndex, Epoch]] - sync_contribution_aggregator_slots: Set[Tuple[ValidatorIndex, Slot, uint64]] - sync_contribution_data: Dict[Tuple[Slot, Root, uint64], Set[Tuple[boolean, ...]]] - sync_message_validator_slots: Set[Tuple[Slot, ValidatorIndex, uint64]] + sync_contribution_aggregator_slots: Set[Tuple[ValidatorIndex, Slot, Uint64]] + sync_contribution_data: Dict[Tuple[Slot, Root, Uint64], Set[Tuple[Boolean, ...]]] + sync_message_validator_slots: Set[Tuple[Slot, ValidatorIndex, Uint64]] # [New in Capella] bls_to_execution_change_indices: Set[ValidatorIndex] @@ -432,18 +432,18 @@ - name: Seen#deneb sources: [] spec: | - + class Seen: proposer_slots: Set[Tuple[ValidatorIndex, Slot]] aggregator_epochs: Set[Tuple[ValidatorIndex, Epoch]] - aggregate_data_roots: Dict[Root, Set[Tuple[boolean, ...]]] + aggregate_data_roots: Dict[Root, Set[Tuple[Boolean, ...]]] voluntary_exit_indices: Set[ValidatorIndex] proposer_slashing_indices: Set[ValidatorIndex] attester_slashing_indices: Set[ValidatorIndex] attestation_validator_epochs: Set[Tuple[ValidatorIndex, Epoch]] - sync_contribution_aggregator_slots: Set[Tuple[ValidatorIndex, Slot, uint64]] - sync_contribution_data: Dict[Tuple[Slot, Root, uint64], Set[Tuple[boolean, ...]]] - sync_message_validator_slots: Set[Tuple[Slot, ValidatorIndex, uint64]] + sync_contribution_aggregator_slots: Set[Tuple[ValidatorIndex, Slot, Uint64]] + sync_contribution_data: Dict[Tuple[Slot, Root, Uint64], Set[Tuple[Boolean, ...]]] + sync_message_validator_slots: Set[Tuple[Slot, ValidatorIndex, Uint64]] bls_to_execution_change_indices: Set[ValidatorIndex] # [New in Deneb] blob_sidecar_tuples: Set[Tuple[Slot, ValidatorIndex, BlobIndex]] @@ -452,19 +452,19 @@ - name: Seen#electra sources: [] spec: | - + class Seen: proposer_slots: Set[Tuple[ValidatorIndex, Slot]] aggregator_epochs: Set[Tuple[ValidatorIndex, Epoch]] # [Modified in Electra:EIP7549] - aggregate_data_roots: Dict[Tuple[Root, CommitteeIndex], Set[Tuple[boolean, ...]]] + aggregate_data_roots: Dict[Tuple[Root, CommitteeIndex], Set[Tuple[Boolean, ...]]] voluntary_exit_indices: Set[ValidatorIndex] proposer_slashing_indices: Set[ValidatorIndex] attester_slashing_indices: Set[ValidatorIndex] attestation_validator_epochs: Set[Tuple[ValidatorIndex, Epoch]] - sync_contribution_aggregator_slots: Set[Tuple[ValidatorIndex, Slot, uint64]] - sync_contribution_data: Dict[Tuple[Slot, Root, uint64], Set[Tuple[boolean, ...]]] - sync_message_validator_slots: Set[Tuple[Slot, ValidatorIndex, uint64]] + sync_contribution_aggregator_slots: Set[Tuple[ValidatorIndex, Slot, Uint64]] + sync_contribution_data: Dict[Tuple[Slot, Root, Uint64], Set[Tuple[Boolean, ...]]] + sync_message_validator_slots: Set[Tuple[Slot, ValidatorIndex, Uint64]] bls_to_execution_change_indices: Set[ValidatorIndex] blob_sidecar_tuples: Set[Tuple[Slot, ValidatorIndex, BlobIndex]] @@ -472,18 +472,18 @@ - name: Seen#fulu sources: [] spec: | - + class Seen: proposer_slots: Set[Tuple[ValidatorIndex, Slot]] aggregator_epochs: Set[Tuple[ValidatorIndex, Epoch]] - aggregate_data_roots: Dict[Tuple[Root, CommitteeIndex], Set[Tuple[boolean, ...]]] + aggregate_data_roots: Dict[Tuple[Root, CommitteeIndex], Set[Tuple[Boolean, ...]]] voluntary_exit_indices: Set[ValidatorIndex] proposer_slashing_indices: Set[ValidatorIndex] attester_slashing_indices: Set[ValidatorIndex] attestation_validator_epochs: Set[Tuple[ValidatorIndex, Epoch]] - sync_contribution_aggregator_slots: Set[Tuple[ValidatorIndex, Slot, uint64]] - sync_contribution_data: Dict[Tuple[Slot, Root, uint64], Set[Tuple[boolean, ...]]] - sync_message_validator_slots: Set[Tuple[Slot, ValidatorIndex, uint64]] + sync_contribution_aggregator_slots: Set[Tuple[ValidatorIndex, Slot, Uint64]] + sync_contribution_data: Dict[Tuple[Slot, Root, Uint64], Set[Tuple[Boolean, ...]]] + sync_message_validator_slots: Set[Tuple[Slot, ValidatorIndex, Uint64]] bls_to_execution_change_indices: Set[ValidatorIndex] # [Modified in Fulu:EIP7594] # Removed `blob_sidecar_tuples` @@ -496,18 +496,18 @@ - name: Seen#gloas sources: [] spec: | - + class Seen: proposer_slots: Set[Tuple[ValidatorIndex, Slot]] aggregator_epochs: Set[Tuple[ValidatorIndex, Epoch]] - aggregate_data_roots: Dict[Tuple[Root, CommitteeIndex], Set[Tuple[boolean, ...]]] + aggregate_data_roots: Dict[Tuple[Root, CommitteeIndex], Set[Tuple[Boolean, ...]]] voluntary_exit_indices: Set[ValidatorIndex] proposer_slashing_indices: Set[ValidatorIndex] attester_slashing_indices: Set[ValidatorIndex] attestation_validator_epochs: Set[Tuple[ValidatorIndex, Epoch]] - sync_contribution_aggregator_slots: Set[Tuple[ValidatorIndex, Slot, uint64]] - sync_contribution_data: Dict[Tuple[Slot, Root, uint64], Set[Tuple[boolean, ...]]] - sync_message_validator_slots: Set[Tuple[Slot, ValidatorIndex, uint64]] + sync_contribution_aggregator_slots: Set[Tuple[ValidatorIndex, Slot, Uint64]] + sync_contribution_data: Dict[Tuple[Slot, Root, Uint64], Set[Tuple[Boolean, ...]]] + sync_message_validator_slots: Set[Tuple[Slot, ValidatorIndex, Uint64]] bls_to_execution_change_indices: Set[ValidatorIndex] data_column_sidecar_tuples: Set[Tuple[Slot, ValidatorIndex, ColumnIndex]] @@ -515,10 +515,10 @@ - name: Store#phase0 sources: [] spec: | - + class Store: - time: uint64 - genesis_time: uint64 + time: Uint64 + genesis_time: Uint64 justified_checkpoint: Checkpoint finalized_checkpoint: Checkpoint unrealized_justified_checkpoint: Checkpoint @@ -527,7 +527,7 @@ equivocating_indices: Set[ValidatorIndex] blocks: Dict[Root, BeaconBlock] = field(default_factory=dict) block_states: Dict[Root, BeaconState] = field(default_factory=dict) - block_timeliness: Dict[Root, boolean] = field(default_factory=dict) + block_timeliness: Dict[Root, Boolean] = field(default_factory=dict) checkpoint_states: Dict[Checkpoint, BeaconState] = field(default_factory=dict) latest_messages: Dict[ValidatorIndex, LatestMessage] = field(default_factory=dict) unrealized_justifications: Dict[Root, Checkpoint] = field(default_factory=dict) @@ -536,10 +536,10 @@ - name: Store#gloas sources: [] spec: | - + class Store: - time: uint64 - genesis_time: uint64 + time: Uint64 + genesis_time: Uint64 justified_checkpoint: Checkpoint finalized_checkpoint: Checkpoint unrealized_justified_checkpoint: Checkpoint @@ -549,16 +549,16 @@ blocks: Dict[Root, BeaconBlock] = field(default_factory=dict) block_states: Dict[Root, BeaconState] = field(default_factory=dict) # [Modified in Gloas:EIP7732] - block_timeliness: Dict[Root, list[boolean]] = field(default_factory=dict) + block_timeliness: Dict[Root, list[Boolean]] = field(default_factory=dict) checkpoint_states: Dict[Checkpoint, BeaconState] = field(default_factory=dict) latest_messages: Dict[ValidatorIndex, LatestMessage] = field(default_factory=dict) unrealized_justifications: Dict[Root, Checkpoint] = field(default_factory=dict) # [New in Gloas:EIP7732] payloads: Dict[Root, ExecutionPayloadEnvelope] = field(default_factory=dict) # [New in Gloas:EIP7732] - payload_timeliness_vote: Dict[Root, list[Optional[boolean]]] = field(default_factory=dict) + payload_timeliness_vote: Dict[Root, list[Optional[Boolean]]] = field(default_factory=dict) # [New in Gloas:EIP7732] - payload_data_availability_vote: Dict[Root, list[Optional[boolean]]] = field( + payload_data_availability_vote: Dict[Root, list[Optional[Boolean]]] = field( default_factory=dict ) @@ -566,10 +566,10 @@ - name: Store#heze sources: [] spec: | - + class Store: - time: uint64 - genesis_time: uint64 + time: Uint64 + genesis_time: Uint64 justified_checkpoint: Checkpoint finalized_checkpoint: Checkpoint unrealized_justified_checkpoint: Checkpoint @@ -578,15 +578,15 @@ equivocating_indices: Set[ValidatorIndex] blocks: Dict[Root, BeaconBlock] = field(default_factory=dict) block_states: Dict[Root, BeaconState] = field(default_factory=dict) - block_timeliness: Dict[Root, list[boolean]] = field(default_factory=dict) + block_timeliness: Dict[Root, list[Boolean]] = field(default_factory=dict) checkpoint_states: Dict[Checkpoint, BeaconState] = field(default_factory=dict) latest_messages: Dict[ValidatorIndex, LatestMessage] = field(default_factory=dict) unrealized_justifications: Dict[Root, Checkpoint] = field(default_factory=dict) payloads: Dict[Root, ExecutionPayloadEnvelope] = field(default_factory=dict) - payload_timeliness_vote: Dict[Root, list[Optional[boolean]]] = field(default_factory=dict) - payload_data_availability_vote: Dict[Root, list[Optional[boolean]]] = field( + payload_timeliness_vote: Dict[Root, list[Optional[Boolean]]] = field(default_factory=dict) + payload_data_availability_vote: Dict[Root, list[Optional[Boolean]]] = field( default_factory=dict ) # [New in Heze:EIP7805] - payload_inclusion_list_satisfaction: Dict[Root, boolean] = field(default_factory=dict) + payload_inclusion_list_satisfaction: Dict[Root, Boolean] = field(default_factory=dict) diff --git a/specrefs/functions.yml b/specrefs/functions.yml index abc04f28a7ce..32438fb9c70a 100644 --- a/specrefs/functions.yml +++ b/specrefs/functions.yml @@ -1,13 +1,13 @@ - name: add_builder_to_registry#gloas sources: [] spec: | - + def add_builder_to_registry( state: BeaconState, pubkey: BLSPubkey, - version: uint8, + version: Uint8, execution_address: ExecutionAddress, - amount: uint64, + amount: Uint64, slot: Slot, ) -> None: set_or_append_list( @@ -43,9 +43,9 @@ - file: beacon-chain/core/altair/deposit.go search: func AddValidatorToRegistry( spec: | - + def add_validator_to_registry( - state: BeaconState, pubkey: BLSPubkey, withdrawal_credentials: Bytes32, amount: uint64 + state: BeaconState, pubkey: BLSPubkey, withdrawal_credentials: Bytes32, amount: Uint64 ) -> None: state.validators.append(get_validator_from_deposit(pubkey, withdrawal_credentials, amount)) state.balances.append(amount) @@ -56,9 +56,9 @@ - file: beacon-chain/core/altair/deposit.go search: func AddValidatorToRegistry( spec: | - + def add_validator_to_registry( - state: BeaconState, pubkey: BLSPubkey, withdrawal_credentials: Bytes32, amount: uint64 + state: BeaconState, pubkey: BLSPubkey, withdrawal_credentials: Bytes32, amount: Uint64 ) -> None: index = get_index_for_new_validator(state) validator = get_validator_from_deposit(pubkey, withdrawal_credentials, amount) @@ -67,7 +67,7 @@ # [New in Altair] set_or_append_list(state.previous_epoch_participation, index, ParticipationFlags(0b0000_0000)) set_or_append_list(state.current_epoch_participation, index, ParticipationFlags(0b0000_0000)) - set_or_append_list(state.inactivity_scores, index, uint64(0)) + set_or_append_list(state.inactivity_scores, index, Uint64(0)) - name: add_validator_to_registry#electra @@ -75,9 +75,9 @@ - file: beacon-chain/core/electra/deposits.go search: func AddValidatorToRegistry( spec: | - + def add_validator_to_registry( - state: BeaconState, pubkey: BLSPubkey, withdrawal_credentials: Bytes32, amount: uint64 + state: BeaconState, pubkey: BLSPubkey, withdrawal_credentials: Bytes32, amount: Uint64 ) -> None: index = get_index_for_new_validator(state) # [Modified in Electra:EIP7251] @@ -86,7 +86,7 @@ set_or_append_list(state.balances, index, amount) set_or_append_list(state.previous_epoch_participation, index, ParticipationFlags(0b0000_0000)) set_or_append_list(state.current_epoch_participation, index, ParticipationFlags(0b0000_0000)) - set_or_append_list(state.inactivity_scores, index, uint64(0)) + set_or_append_list(state.inactivity_scores, index, Uint64(0)) - name: adjust_committee_weight_estimate_to_ensure_safety#phase0 @@ -107,12 +107,12 @@ - file: beacon-chain/core/altair/deposit.go search: func ApplyDeposit( spec: | - + def apply_deposit( state: BeaconState, pubkey: BLSPubkey, withdrawal_credentials: Bytes32, - amount: uint64, + amount: Uint64, signature: BLSSignature, ) -> None: validator_pubkeys = [v.pubkey for v in state.validators] @@ -139,12 +139,12 @@ - file: beacon-chain/core/electra/deposits.go search: func ApplyDeposit( spec: | - + def apply_deposit( state: BeaconState, pubkey: BLSPubkey, withdrawal_credentials: Bytes32, - amount: uint64, + amount: Uint64, signature: BLSSignature, ) -> None: validator_pubkeys = [v.pubkey for v in state.validators] @@ -481,19 +481,19 @@ - file: encoding/bytesutil/integers.go search: func FromBytes8( spec: | - - def bytes_to_uint64(data: bytes) -> uint64: + + def bytes_to_uint64(data: bytes) -> Uint64: """ Return the integer deserialization of ``data`` interpreted as ``ENDIANNESS``-endian. """ - return uint64(int.from_bytes(data, ENDIANNESS)) + return Uint64(int.from_bytes(data, ENDIANNESS)) - name: calculate_committee_fraction#phase0 sources: [] spec: | - - def calculate_committee_fraction(state: BeaconState, committee_percent: uint64) -> Gwei: + + def calculate_committee_fraction(state: BeaconState, committee_percent: Uint64) -> Gwei: committee_weight = get_total_active_balance(state) // SLOTS_PER_EPOCH return Gwei((committee_weight * committee_percent) // 100) @@ -568,23 +568,23 @@ - name: compute_attestation_subnet_prefix_bits#phase0 sources: [] spec: | - - def compute_attestation_subnet_prefix_bits() -> uint64: + + def compute_attestation_subnet_prefix_bits() -> Uint64: """ Return the number of NodeId bits to use when mapping to a subscribed subnet. """ - return uint64(ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS) + return Uint64(ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS) - name: compute_balance_weighted_selection#gloas sources: [] spec: | - + def compute_balance_weighted_selection( state: BeaconState, indices: Sequence[ValidatorIndex], seed: Bytes32, - size: uint64, + size: Uint64, shuffle_indices: bool, ) -> Sequence[ValidatorIndex]: """ @@ -594,11 +594,11 @@ ``indices`` is traversed in order. The returned list can contain duplicates. """ MAX_RANDOM_VALUE = 2**16 - 1 - total = uint64(len(indices)) + total = Uint64(len(indices)) assert total > 0 effective_balances = [state.validators[index].effective_balance for index in indices] selected: List[ValidatorIndex] = [] - i = uint64(0) + i = Uint64(0) while len(selected) < size: offset = i % 16 * 2 if offset == 0: @@ -634,17 +634,17 @@ - file: beacon-chain/core/helpers/beacon_committee.go search: func ComputeCommittee( spec: | - + def compute_committee( - indices: Sequence[ValidatorIndex], seed: Bytes32, index: uint64, count: uint64 + indices: Sequence[ValidatorIndex], seed: Bytes32, index: Uint64, count: Uint64 ) -> Sequence[ValidatorIndex]: """ Return the committee corresponding to ``indices``, ``seed``, ``index``, and committee ``count``. """ start = (len(indices) * index) // count - end = (len(indices) * uint64(index + 1)) // count + end = (len(indices) * Uint64(index + 1)) // count return [ - indices[compute_shuffled_index(uint64(i), uint64(len(indices)), seed)] + indices[compute_shuffled_index(Uint64(i), Uint64(len(indices)), seed)] for i in range(start, end) ] @@ -862,7 +862,7 @@ - file: config/params/config.go search: func entryWithForkDigest( spec: | - + def compute_fork_digest( genesis_validators_root: Root, epoch: Epoch, @@ -888,8 +888,8 @@ xor( base_digest, hash( - uint_to_bytes(uint64(blob_parameters.epoch)) - + uint_to_bytes(uint64(blob_parameters.max_blobs_per_block)) + uint_to_bytes(Uint64(blob_parameters.epoch)) + + uint_to_bytes(Uint64(blob_parameters.max_blobs_per_block)) ), ) )[:4] @@ -1134,7 +1134,7 @@ - name: compute_matrix#fulu sources: [] spec: | - + def compute_matrix(blobs: Sequence[Blob]) -> Sequence[MatrixEntry]: """ Return the full, flattened sequence of matrix entries. @@ -1144,7 +1144,7 @@ """ matrix = [] for blob_index, blob in enumerate(blobs): - cells, proofs = compute_cells_and_kzg_proofs(blob) + cells, proofs = kzg.compute_cells_and_kzg_proofs(blob) for cell_index, (cell, proof) in enumerate(zip(cells, proofs, strict=True)): matrix.append( MatrixEntry( @@ -1160,43 +1160,43 @@ - name: compute_max_request_blob_sidecars#deneb sources: [] spec: | - - def compute_max_request_blob_sidecars() -> uint64: + + def compute_max_request_blob_sidecars() -> Uint64: """ Return the maximum number of blob sidecars in a single request. """ - return uint64(MAX_REQUEST_BLOCKS_DENEB * MAX_BLOBS_PER_BLOCK) + return Uint64(MAX_REQUEST_BLOCKS_DENEB * MAX_BLOBS_PER_BLOCK) - name: compute_max_request_blob_sidecars#electra sources: [] spec: | - - def compute_max_request_blob_sidecars() -> uint64: + + def compute_max_request_blob_sidecars() -> Uint64: """ Return the maximum number of blob sidecars in a single request. """ # [Modified in Electra:EIP7691] - return uint64(MAX_REQUEST_BLOCKS_DENEB * MAX_BLOBS_PER_BLOCK_ELECTRA) + return Uint64(MAX_REQUEST_BLOCKS_DENEB * MAX_BLOBS_PER_BLOCK_ELECTRA) - name: compute_max_request_data_column_sidecars#fulu sources: [] spec: | - - def compute_max_request_data_column_sidecars() -> uint64: + + def compute_max_request_data_column_sidecars() -> Uint64: """ Return the maximum number of data column sidecars in a single request. """ - return uint64(MAX_REQUEST_BLOCKS_DENEB * NUMBER_OF_COLUMNS) + return Uint64(MAX_REQUEST_BLOCKS_DENEB * NUMBER_OF_COLUMNS) - name: compute_merkle_branch_root#phase0 sources: [] spec: | - + def compute_merkle_branch_root( - leaf: Bytes32, branch: Sequence[Bytes32], depth: uint64, index: uint64 + leaf: Bytes32, branch: Sequence[Bytes32], depth: Uint64, index: Uint64 ) -> Root: """ Return the Merkle root obtained by hashing ``leaf`` at ``index`` with ``branch``. @@ -1220,12 +1220,12 @@ - name: compute_min_epochs_for_block_requests#phase0 sources: [] spec: | - - def compute_min_epochs_for_block_requests() -> uint64: + + def compute_min_epochs_for_block_requests() -> Uint64: """ Return the minimum epoch range over which a node must serve blocks. """ - return uint64(MIN_VALIDATOR_WITHDRAWABILITY_DELAY + CHURN_LIMIT_QUOTIENT // 2) + return Uint64(MIN_VALIDATOR_WITHDRAWABILITY_DELAY + CHURN_LIMIT_QUOTIENT // 2) - name: compute_new_state_root#phase0 @@ -1246,7 +1246,7 @@ - file: beacon-chain/rpc/prysm/v1alpha1/validator/proposer_attestations_electra.go search: func computeOnChainAggregate( spec: | - + def compute_on_chain_aggregate(network_aggregates: Sequence[Attestation]) -> Attestation: aggregates = sorted( network_aggregates, key=lambda a: get_committee_indices(a.committee_bits)[0] @@ -1262,7 +1262,7 @@ committee_indices = [get_committee_indices(a.committee_bits)[0] for a in aggregates] committee_flags = [(index in committee_indices) for index in range(MAX_COMMITTEES_PER_SLOT)] - committee_bits = Bitvector[MAX_COMMITTEES_PER_SLOT](committee_flags) + committee_bits = BitVector[MAX_COMMITTEES_PER_SLOT](committee_flags) return Attestation( aggregation_bits=aggregation_bits, @@ -1277,7 +1277,7 @@ - file: beacon-chain/core/helpers/validators.go search: func ComputeProposerIndex( spec: | - + def compute_proposer_index( state: BeaconState, indices: Sequence[ValidatorIndex], seed: Bytes32 ) -> ValidatorIndex: @@ -1286,11 +1286,11 @@ """ assert len(indices) > 0 MAX_RANDOM_BYTE = 2**8 - 1 - i = uint64(0) - total = uint64(len(indices)) + i = Uint64(0) + total = Uint64(len(indices)) while True: candidate_index = indices[compute_shuffled_index(i % total, total, seed)] - random_byte = hash(seed + uint_to_bytes(uint64(i // 32)))[i % 32] + random_byte = hash(seed + uint_to_bytes(Uint64(i // 32)))[i % 32] effective_balance = state.validators[candidate_index].effective_balance if effective_balance * MAX_RANDOM_BYTE >= MAX_EFFECTIVE_BALANCE * random_byte: return candidate_index @@ -1304,7 +1304,7 @@ - file: beacon-chain/core/helpers/validators.go search: if bState.Version() >= version.Electra { spec: | - + def compute_proposer_index( state: BeaconState, indices: Sequence[ValidatorIndex], seed: Bytes32 ) -> ValidatorIndex: @@ -1314,8 +1314,8 @@ assert len(indices) > 0 # [Modified in Electra] MAX_RANDOM_VALUE = 2**16 - 1 - i = uint64(0) - total = uint64(len(indices)) + i = Uint64(0) + total = Uint64(len(indices)) while True: candidate_index = indices[compute_shuffled_index(i % total, total, seed)] # [Modified in Electra] @@ -1449,8 +1449,8 @@ - file: beacon-chain/core/helpers/shuffle.go search: func ComputeShuffledIndex( spec: | - - def compute_shuffled_index(index: uint64, index_count: uint64, seed: Bytes32) -> uint64: + + def compute_shuffled_index(index: Uint64, index_count: Uint64, seed: Bytes32) -> Uint64: """ Return the shuffled index corresponding to ``seed`` (and ``index_count``). """ @@ -1461,18 +1461,18 @@ - name: compute_shuffled_permutation#phase0 sources: [] spec: | - - def compute_shuffled_permutation(index_count: uint64, seed: Bytes32) -> Sequence[uint64]: + + def compute_shuffled_permutation(index_count: Uint64, seed: Bytes32) -> Sequence[Uint64]: """ Return the full shuffled permutation corresponding to ``seed`` (and ``index_count``). """ # Swap or not (https://link.springer.com/content/pdf/10.1007%2F978-3-642-32009-5_1.pdf) # See the 'generalized domain' algorithm on page 3 - indices = [uint64(i) for i in range(index_count)] + indices = [Uint64(i) for i in range(index_count)] for current_round in range(SHUFFLE_ROUND_COUNT): round_bytes = current_round.to_bytes(1, "little") pivot = int.from_bytes(hash(seed + round_bytes)[0:8], "little") % index_count - source_by_bucket: Dict[uint64, Bytes32] = {} + source_by_bucket: Dict[Uint64, Bytes32] = {} for i in range(index_count): flip = (pivot + index_count - indices[i]) % index_count position = max(indices[i], flip) @@ -1552,15 +1552,15 @@ - file: beacon-chain/core/helpers/attestation.go search: func ComputeSubnetForAttestation( spec: | - + def compute_subnet_for_attestation( - committees_per_slot: uint64, slot: Slot, committee_index: CommitteeIndex + committees_per_slot: Uint64, slot: Slot, committee_index: CommitteeIndex ) -> SubnetID: """ Compute the correct subnet for an attestation for Phase 0. Note, this mimics expected future behavior where attestations will be mapped to their shard subnet. """ - slots_since_epoch_start = uint64(slot % SLOTS_PER_EPOCH) + slots_since_epoch_start = Uint64(slot % SLOTS_PER_EPOCH) committees_since_epoch_start = committees_per_slot * slots_since_epoch_start return SubnetID((committees_since_epoch_start + committee_index) % ATTESTATION_SUBNET_COUNT) @@ -1630,13 +1630,13 @@ - file: beacon-chain/p2p/subnets.go search: func computeSubscribedSubnet( spec: | - + def compute_subscribed_subnet(node_id: NodeID, epoch: Epoch, index: int) -> SubnetID: prefix_bits = int(compute_attestation_subnet_prefix_bits()) - node_id_prefix = node_id >> (NODE_ID_BITS - prefix_bits) - node_offset = node_id % EPOCHS_PER_SUBNET_SUBSCRIPTION + node_id_prefix = node_id >> int(NODE_ID_BITS - prefix_bits) + node_offset = Uint64(node_id % Uint256(EPOCHS_PER_SUBNET_SUBSCRIPTION)) permutation_seed = hash( - uint_to_bytes(uint64((epoch + node_offset) // EPOCHS_PER_SUBNET_SUBSCRIPTION)) + uint_to_bytes(Uint64((epoch + node_offset) // EPOCHS_PER_SUBNET_SUBSCRIPTION)) ) permutated_prefix = compute_shuffled_index( node_id_prefix, @@ -1661,16 +1661,16 @@ - file: time/slots/slottime.go search: func SyncCommitteePeriod( spec: | - - def compute_sync_committee_period(epoch: Epoch) -> uint64: + + def compute_sync_committee_period(epoch: Epoch) -> Uint64: return epoch // EPOCHS_PER_SYNC_COMMITTEE_PERIOD - name: compute_sync_committee_period_at_slot#altair sources: [] spec: | - - def compute_sync_committee_period_at_slot(slot: Slot) -> uint64: + + def compute_sync_committee_period_at_slot(slot: Slot) -> Uint64: return compute_sync_committee_period(compute_epoch_at_slot(slot)) @@ -1679,22 +1679,22 @@ - file: time/slots/slottime.go search: func StartTime( spec: | - - def compute_time_at_slot(state: BeaconState, slot: Slot) -> uint64: + + def compute_time_at_slot(state: BeaconState, slot: Slot) -> Uint64: slots_since_genesis = slot - GENESIS_SLOT - return uint64(state.genesis_time + slots_since_genesis * SLOT_DURATION_MS // 1000) + return Uint64(state.genesis_time + slots_since_genesis * SLOT_DURATION_MS // 1000) - name: compute_time_at_slot_ms#phase0 sources: [] spec: | - - def compute_time_at_slot_ms(state: BeaconState, slot: Slot) -> uint64: + + def compute_time_at_slot_ms(state: BeaconState, slot: Slot) -> Uint64: """ Return the time in milliseconds at the start of the given slot. """ slots_since_genesis = slot - GENESIS_SLOT - return uint64(state.genesis_time * 1000 + slots_since_genesis * SLOT_DURATION_MS) + return Uint64(state.genesis_time * 1000 + slots_since_genesis * SLOT_DURATION_MS) - name: compute_weak_subjectivity_period#phase0 @@ -1702,8 +1702,8 @@ - file: beacon-chain/core/helpers/weak_subjectivity.go search: func ComputeWeakSubjectivityPeriod( spec: | - - def compute_weak_subjectivity_period(state: BeaconState) -> uint64: + + def compute_weak_subjectivity_period(state: BeaconState) -> Uint64: """ Returns the weak subjectivity period for the current ``state``. This computation takes into account the effect of: @@ -1735,8 +1735,8 @@ - name: compute_weak_subjectivity_period#electra sources: [] spec: | - - def compute_weak_subjectivity_period(state: BeaconState) -> uint64: + + def compute_weak_subjectivity_period(state: BeaconState) -> Uint64: """ Returns the weak subjectivity period for the current ``state``. This computation takes into account the effect of: @@ -1753,8 +1753,8 @@ - name: compute_weak_subjectivity_period#gloas sources: [] spec: | - - def compute_weak_subjectivity_period(state: BeaconState) -> uint64: + + def compute_weak_subjectivity_period(state: BeaconState) -> Uint64: """ Returns the weak subjectivity period for the current ``state``. This computation takes into account the effect of: @@ -2335,16 +2335,16 @@ - name: get_aggregate_due_ms#phase0 sources: [] spec: | - - def get_aggregate_due_ms() -> uint64: + + def get_aggregate_due_ms() -> Uint64: return get_slot_component_duration_ms(AGGREGATE_DUE_BPS) - name: get_aggregate_due_ms#gloas sources: [] spec: | - - def get_aggregate_due_ms() -> uint64: + + def get_aggregate_due_ms() -> Uint64: # [Modified in Gloas] return get_slot_component_duration_ms(AGGREGATE_DUE_BPS_GLOAS) @@ -2415,7 +2415,7 @@ - name: get_attestation_component_deltas#phase0 sources: [] spec: | - + def get_attestation_component_deltas( state: BeaconState, attestations: Sequence[PendingAttestation] ) -> Tuple[Sequence[Gwei], Sequence[Gwei]]: @@ -2429,7 +2429,7 @@ attesting_balance = get_total_balance(state, unslashed_attesting_indices) for index in get_eligible_validator_indices(state): if index in unslashed_attesting_indices: - increment = EFFECTIVE_BALANCE_INCREMENT # Factored out from balance totals to avoid uint64 overflow + increment = EFFECTIVE_BALANCE_INCREMENT # Factored out from balance totals to avoid Uint64 overflow if is_in_inactivity_leak(state): # Since full base reward will be canceled out by inactivity penalty deltas, # optimal participation receives full base reward compensation here. @@ -2474,16 +2474,16 @@ - name: get_attestation_due_ms#phase0 sources: [] spec: | - - def get_attestation_due_ms() -> uint64: + + def get_attestation_due_ms() -> Uint64: return get_slot_component_duration_ms(ATTESTATION_DUE_BPS) - name: get_attestation_due_ms#gloas sources: [] spec: | - - def get_attestation_due_ms() -> uint64: + + def get_attestation_due_ms() -> Uint64: # [Modified in Gloas] return get_slot_component_duration_ms(ATTESTATION_DUE_BPS_GLOAS) @@ -2493,9 +2493,9 @@ - file: beacon-chain/core/altair/attestation.go search: func AttestationParticipationFlagIndices( spec: | - + def get_attestation_participation_flag_indices( - state: BeaconState, data: AttestationData, inclusion_delay: uint64 + state: BeaconState, data: AttestationData, inclusion_delay: Uint64 ) -> Sequence[int]: """ Return the flag indices that are satisfied by an attestation. @@ -2535,9 +2535,9 @@ - file: beacon-chain/core/altair/attestation.go search: func AttestationParticipationFlagIndices( spec: | - + def get_attestation_participation_flag_indices( - state: BeaconState, data: AttestationData, inclusion_delay: uint64 + state: BeaconState, data: AttestationData, inclusion_delay: Uint64 ) -> Sequence[int]: """ Return the flag indices that are satisfied by an attestation. @@ -2576,9 +2576,13 @@ - name: get_attestation_participation_flag_indices#gloas sources: [] spec: | - + def get_attestation_participation_flag_indices( - state: BeaconState, data: AttestationData, inclusion_delay: uint64 + state: BeaconState, + data: AttestationData, + inclusion_delay: Uint64, + # [New in Gloas:EIP7732] + parent_slot: Slot, ) -> Sequence[int]: """ Return the flag indices that are satisfied by an attestation. @@ -2600,7 +2604,7 @@ assert data.index == 0 payload_matches = True else: - slot_index = data.slot % SLOTS_PER_HISTORICAL_ROOT + slot_index = parent_slot % SLOTS_PER_HISTORICAL_ROOT payload_index = state.execution_payload_availability[slot_index] payload_matches = data.index == payload_index @@ -3056,29 +3060,29 @@ - name: get_builder_payment_quorum_threshold#gloas sources: [] spec: | - - def get_builder_payment_quorum_threshold(state: BeaconState) -> uint64: + + def get_builder_payment_quorum_threshold(state: BeaconState) -> Uint64: """ Calculate the quorum threshold for builder payments. """ per_slot_balance = get_total_active_balance(state) // SLOTS_PER_EPOCH quorum = per_slot_balance * BUILDER_PAYMENT_THRESHOLD_NUMERATOR - return uint64(quorum // BUILDER_PAYMENT_THRESHOLD_DENOMINATOR) + return Uint64(quorum // BUILDER_PAYMENT_THRESHOLD_DENOMINATOR) - name: get_builder_withdrawals#gloas sources: [] spec: | - + def get_builder_withdrawals( state: BeaconState, withdrawal_index: WithdrawalIndex, prior_withdrawals: Sequence[Withdrawal], - ) -> Tuple[Sequence[Withdrawal], WithdrawalIndex, uint64]: + ) -> Tuple[Sequence[Withdrawal], WithdrawalIndex, Uint64]: withdrawals_limit = MAX_WITHDRAWALS_PER_PAYLOAD - 1 assert len(prior_withdrawals) <= withdrawals_limit - processed_count: uint64 = 0 + processed_count: Uint64 = 0 withdrawals: List[Withdrawal] = [] for withdrawal in state.builder_pending_withdrawals: all_withdrawals = prior_withdrawals + withdrawals @@ -3104,18 +3108,18 @@ - name: get_builders_sweep_withdrawals#gloas sources: [] spec: | - + def get_builders_sweep_withdrawals( state: BeaconState, withdrawal_index: WithdrawalIndex, prior_withdrawals: Sequence[Withdrawal], - ) -> Tuple[Sequence[Withdrawal], WithdrawalIndex, uint64]: + ) -> Tuple[Sequence[Withdrawal], WithdrawalIndex, Uint64]: epoch = get_current_epoch(state) builders_limit = min(len(state.builders), MAX_BUILDERS_PER_WITHDRAWALS_SWEEP) withdrawals_limit = MAX_WITHDRAWALS_PER_PAYLOAD - 1 assert len(prior_withdrawals) <= withdrawals_limit - processed_count: uint64 = 0 + processed_count: Uint64 = 0 withdrawals: List[Withdrawal] = [] builder_index = state.next_withdrawal_builder_index for _ in range(builders_limit): @@ -3215,16 +3219,16 @@ - file: beacon-chain/core/helpers/beacon_committee.go search: func SlotCommitteeCount( spec: | - - def get_committee_count_per_slot(state: BeaconState, epoch: Epoch) -> uint64: + + def get_committee_count_per_slot(state: BeaconState, epoch: Epoch) -> Uint64: """ Return the number of committees in each slot for the given ``epoch``. """ return max( - uint64(1), + Uint64(1), min( MAX_COMMITTEES_PER_SLOT, - uint64(len(get_active_validator_indices(state, epoch))) + Uint64(len(get_active_validator_indices(state, epoch))) // SLOTS_PER_EPOCH // TARGET_COMMITTEE_SIZE, ), @@ -3236,8 +3240,8 @@ - file: beacon-chain/core/helpers/beacon_committee.go search: func CommitteeIndices( spec: | - - def get_committee_indices(committee_bits: Bitvector) -> Sequence[CommitteeIndex]: + + def get_committee_indices(committee_bits: BitVector) -> Sequence[CommitteeIndex]: return [CommitteeIndex(index) for index, bit in enumerate(committee_bits) if bit] @@ -3308,16 +3312,16 @@ - name: get_contribution_due_ms#altair sources: [] spec: | - - def get_contribution_due_ms() -> uint64: + + def get_contribution_due_ms() -> Uint64: return get_slot_component_duration_ms(CONTRIBUTION_DUE_BPS) - name: get_contribution_due_ms#gloas sources: [] spec: | - - def get_contribution_due_ms() -> uint64: + + def get_contribution_due_ms() -> Uint64: # [Modified in Gloas] return get_slot_component_duration_ms(CONTRIBUTION_DUE_BPS_GLOAS) @@ -3413,15 +3417,15 @@ - file: beacon-chain/core/peerdas/das_core.go search: func CustodyGroups( spec: | - - def get_custody_groups(node_id: NodeID, custody_group_count: uint64) -> Sequence[CustodyIndex]: + + def get_custody_groups(node_id: NodeID, custody_group_count: Uint64) -> Sequence[CustodyIndex]: assert custody_group_count <= NUMBER_OF_CUSTODY_GROUPS # Skip computation if all groups are custodied if custody_group_count == NUMBER_OF_CUSTODY_GROUPS: return [CustodyIndex(i) for i in range(NUMBER_OF_CUSTODY_GROUPS)] - current_id = uint256(node_id) + current_id = Uint256(node_id) custody_groups: List[CustodyIndex] = [] while len(custody_groups) < custody_group_count: custody_group = CustodyIndex( @@ -3431,7 +3435,7 @@ custody_groups.append(custody_group) if current_id == UINT256_MAX: # Overflow prevention - current_id = uint256(0) + current_id = Uint256(0) else: current_id += 1 @@ -3697,15 +3701,15 @@ - file: beacon-chain/rpc/prysm/v1alpha1/validator/proposer_deposits.go search: func (vs *Server) deposits( spec: | - - def get_eth1_pending_deposit_count(state: BeaconState) -> uint64: + + def get_eth1_pending_deposit_count(state: BeaconState) -> Uint64: eth1_deposit_index_limit = min( state.eth1_data.deposit_count, state.deposit_requests_start_index ) if state.eth1_deposit_index < eth1_deposit_index_limit: return min(MAX_DEPOSITS, eth1_deposit_index_limit - state.eth1_deposit_index) else: - return uint64(0) + return Uint64(0) - name: get_eth1_vote#phase0 @@ -4122,8 +4126,8 @@ - file: beacon-chain/core/helpers/rewards_penalties.go search: func FinalityDelay( spec: | - - def get_finality_delay(state: BeaconState) -> uint64: + + def get_finality_delay(state: BeaconState) -> Uint64: return get_previous_epoch(state) - state.finalized_checkpoint.epoch @@ -4165,7 +4169,7 @@ - name: get_forkchoice_store#phase0 sources: [] spec: | - + def get_forkchoice_store(anchor_state: BeaconState, anchor_block: BeaconBlock) -> Store: assert anchor_block.state_root == hash_tree_root(anchor_state) anchor_root = hash_tree_root(anchor_block) @@ -4174,7 +4178,7 @@ finalized_checkpoint = Checkpoint(epoch=anchor_epoch, root=anchor_root) proposer_boost_root = Root() return Store( - time=uint64(anchor_state.genesis_time + SLOT_DURATION_MS * anchor_state.slot // 1000), + time=Uint64(anchor_state.genesis_time + SLOT_DURATION_MS * anchor_state.slot // 1000), genesis_time=anchor_state.genesis_time, justified_checkpoint=justified_checkpoint, finalized_checkpoint=finalized_checkpoint, @@ -4192,7 +4196,7 @@ - name: get_forkchoice_store#gloas sources: [] spec: | - + def get_forkchoice_store(anchor_state: BeaconState, anchor_block: BeaconBlock) -> Store: assert anchor_block.state_root == hash_tree_root(anchor_state) anchor_root = hash_tree_root(anchor_block) @@ -4201,7 +4205,7 @@ finalized_checkpoint = Checkpoint(epoch=anchor_epoch, root=anchor_root) proposer_boost_root = Root() return Store( - time=uint64(anchor_state.genesis_time + SLOT_DURATION_MS * anchor_state.slot // 1000), + time=Uint64(anchor_state.genesis_time + SLOT_DURATION_MS * anchor_state.slot // 1000), genesis_time=anchor_state.genesis_time, justified_checkpoint=justified_checkpoint, finalized_checkpoint=finalized_checkpoint, @@ -4227,7 +4231,7 @@ - name: get_forkchoice_store#heze sources: [] spec: | - + def get_forkchoice_store(anchor_state: BeaconState, anchor_block: BeaconBlock) -> Store: assert anchor_block.state_root == hash_tree_root(anchor_state) anchor_root = hash_tree_root(anchor_block) @@ -4236,7 +4240,7 @@ finalized_checkpoint = Checkpoint(epoch=anchor_epoch, root=anchor_root) proposer_boost_root = Root() return Store( - time=uint64(anchor_state.genesis_time + SLOT_DURATION_MS * anchor_state.slot // 1000), + time=Uint64(anchor_state.genesis_time + SLOT_DURATION_MS * anchor_state.slot // 1000), genesis_time=anchor_state.genesis_time, justified_checkpoint=justified_checkpoint, finalized_checkpoint=finalized_checkpoint, @@ -4442,12 +4446,12 @@ - name: get_inclusion_list_bits#heze sources: [] spec: | - + def get_inclusion_list_bits( store: InclusionListStore, state: BeaconState, slot: Slot, only_timely: bool = True - ) -> Bitvector[INCLUSION_LIST_COMMITTEE_SIZE]: + ) -> BitVector[INCLUSION_LIST_COMMITTEE_SIZE]: """ - Return a ``Bitvector`` over inclusion list committee indices with bits set + Return a ``BitVector`` over inclusion list committee indices with bits set for those who provided valid, non-equivocating inclusion lists for the given ``slot``. """ committee = get_inclusion_list_committee(state, slot) @@ -4458,13 +4462,13 @@ timeliness = store.inclusion_list_timeliness validator_indices = [ - inclusion_lists[inclusion_list_root].validator_index + inclusion_lists[inclusion_list_root].message.validator_index for inclusion_list_root in inclusion_lists - if inclusion_lists[inclusion_list_root].validator_index not in equivocators + if inclusion_lists[inclusion_list_root].message.validator_index not in equivocators if not only_timely or timeliness[inclusion_list_root] ] - return Bitvector[INCLUSION_LIST_COMMITTEE_SIZE]( + return BitVector[INCLUSION_LIST_COMMITTEE_SIZE]( validator_index in validator_indices for validator_index in committee ) @@ -4516,8 +4520,8 @@ - name: get_inclusion_list_due_ms#heze sources: [] spec: | - - def get_inclusion_list_due_ms() -> uint64: + + def get_inclusion_list_due_ms() -> Uint64: return get_slot_component_duration_ms(INCLUSION_LIST_DUE_BPS) @@ -4551,7 +4555,7 @@ - name: get_inclusion_list_transactions#heze sources: [] spec: | - + def get_inclusion_list_transactions( store: InclusionListStore, state: BeaconState, slot: Slot, only_timely: bool = True ) -> Sequence[Transaction]: @@ -4565,9 +4569,9 @@ transactions = [ transaction for inclusion_list_root in inclusion_lists - if inclusion_lists[inclusion_list_root].validator_index not in equivocators + if inclusion_lists[inclusion_list_root].message.validator_index not in equivocators if not only_timely or timeliness[inclusion_list_root] - for transaction in inclusion_lists[inclusion_list_root].transactions + for transaction in inclusion_lists[inclusion_list_root].message.transactions ] # Deduplicate inclusion list transactions. Order does not need to be preserved. @@ -4911,7 +4915,7 @@ - file: beacon-chain/core/altair/sync_committee.go search: func NextSyncCommitteeIndices( spec: | - + def get_next_sync_committee_indices(state: BeaconState) -> Sequence[ValidatorIndex]: """ Return the sync committee indices, with possible duplicates, for the next sync committee. @@ -4920,16 +4924,16 @@ MAX_RANDOM_BYTE = 2**8 - 1 active_validator_indices = get_active_validator_indices(state, epoch) - active_validator_count = uint64(len(active_validator_indices)) + active_validator_count = Uint64(len(active_validator_indices)) seed = get_seed(state, epoch, DOMAIN_SYNC_COMMITTEE) i = 0 sync_committee_indices: List[ValidatorIndex] = [] while len(sync_committee_indices) < SYNC_COMMITTEE_SIZE: shuffled_index = compute_shuffled_index( - uint64(i % active_validator_count), active_validator_count, seed + Uint64(i % active_validator_count), active_validator_count, seed ) candidate_index = active_validator_indices[shuffled_index] - random_byte = hash(seed + uint_to_bytes(uint64(i // 32)))[i % 32] + random_byte = hash(seed + uint_to_bytes(Uint64(i // 32)))[i % 32] effective_balance = state.validators[candidate_index].effective_balance if effective_balance * MAX_RANDOM_BYTE >= MAX_EFFECTIVE_BALANCE * random_byte: sync_committee_indices.append(candidate_index) @@ -4944,7 +4948,7 @@ - file: beacon-chain/core/altair/sync_committee.go search: if s.Version() >= version.Electra { spec: | - + def get_next_sync_committee_indices(state: BeaconState) -> Sequence[ValidatorIndex]: """ Return the sync committee indices, with possible duplicates, for the next sync committee. @@ -4954,13 +4958,13 @@ # [Modified in Electra] MAX_RANDOM_VALUE = 2**16 - 1 active_validator_indices = get_active_validator_indices(state, epoch) - active_validator_count = uint64(len(active_validator_indices)) + active_validator_count = Uint64(len(active_validator_indices)) seed = get_seed(state, epoch, DOMAIN_SYNC_COMMITTEE) - i = uint64(0) + i = Uint64(0) sync_committee_indices: List[ValidatorIndex] = [] while len(sync_committee_indices) < SYNC_COMMITTEE_SIZE: shuffled_index = compute_shuffled_index( - uint64(i % active_validator_count), active_validator_count, seed + Uint64(i % active_validator_count), active_validator_count, seed ) candidate_index = active_validator_indices[shuffled_index] # [Modified in Electra] @@ -5057,8 +5061,8 @@ - name: get_payload_attestation_due_ms#gloas sources: [] spec: | - - def get_payload_attestation_due_ms() -> uint64: + + def get_payload_attestation_due_ms() -> Uint64: return get_slot_component_duration_ms(PAYLOAD_ATTESTATION_DUE_BPS) @@ -5077,16 +5081,16 @@ - name: get_payload_due_ms#gloas sources: [] spec: | - - def get_payload_due_ms() -> uint64: + + def get_payload_due_ms() -> Uint64: return get_slot_component_duration_ms(PAYLOAD_DUE_BPS) - name: get_payload_status_tiebreaker#gloas sources: [] spec: | - - def get_payload_status_tiebreaker(store: Store, node: ForkChoiceNode) -> uint8: + + def get_payload_status_tiebreaker(store: Store, node: ForkChoiceNode) -> Uint8: if is_previous_slot_payload_decision(store, node): # To decide on a payload from the previous slot, choose # between FULL and EMPTY based on `should_extend_payload` @@ -5136,12 +5140,12 @@ - name: get_pending_partial_withdrawals#electra sources: [] spec: | - + def get_pending_partial_withdrawals( state: BeaconState, withdrawal_index: WithdrawalIndex, prior_withdrawals: Sequence[Withdrawal], - ) -> Tuple[Sequence[Withdrawal], WithdrawalIndex, uint64]: + ) -> Tuple[Sequence[Withdrawal], WithdrawalIndex, Uint64]: epoch = get_current_epoch(state) withdrawals_limit = min( len(prior_withdrawals) + MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP, @@ -5149,7 +5153,7 @@ ) assert len(prior_withdrawals) <= withdrawals_limit - processed_count: uint64 = 0 + processed_count: Uint64 = 0 withdrawals: List[Withdrawal] = [] for withdrawal in state.pending_partial_withdrawals: all_withdrawals = prior_withdrawals + withdrawals @@ -5346,8 +5350,8 @@ - name: get_proposer_reorg_cutoff_ms#phase0 sources: [] spec: | - - def get_proposer_reorg_cutoff_ms() -> uint64: + + def get_proposer_reorg_cutoff_ms() -> Uint64: return get_slot_component_duration_ms(PROPOSER_REORG_CUTOFF_BPS) @@ -5463,8 +5467,8 @@ - name: get_safety_threshold#altair sources: [] spec: | - - def get_safety_threshold(store: LightClientStore) -> uint64: + + def get_safety_threshold(store: LightClientStore) -> Uint64: return ( max( store.previous_max_active_participants, @@ -5510,8 +5514,8 @@ - name: get_slot_component_duration_ms#phase0 sources: [] spec: | - - def get_slot_component_duration_ms(basis_points: uint64) -> uint64: + + def get_slot_component_duration_ms(basis_points: Uint64) -> Uint64: """ Calculate the duration of a slot component in milliseconds. """ @@ -5557,9 +5561,9 @@ - name: get_subtree_index#altair sources: [] spec: | - - def get_subtree_index(generalized_index: GeneralizedIndex) -> uint64: - return uint64(generalized_index % 2 ** (floorlog2(generalized_index))) + + def get_subtree_index(generalized_index: GeneralizedIndex) -> Uint64: + return Uint64(generalized_index % 2 ** (floorlog2(generalized_index))) - name: get_support_discount#phase0 @@ -5632,9 +5636,9 @@ - name: get_sync_committee_selection_proof#altair sources: [] spec: | - + def get_sync_committee_selection_proof( - state: BeaconState, slot: Slot, subcommittee_index: uint64, privkey: int + state: BeaconState, slot: Slot, subcommittee_index: Uint64, privkey: int ) -> BLSSignature: domain = get_domain(state, DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF, compute_epoch_at_slot(slot)) signing_data = SyncAggregatorSelectionData( @@ -5648,16 +5652,16 @@ - name: get_sync_message_due_ms#altair sources: [] spec: | - - def get_sync_message_due_ms() -> uint64: + + def get_sync_message_due_ms() -> Uint64: return get_slot_component_duration_ms(SYNC_MESSAGE_DUE_BPS) - name: get_sync_message_due_ms#gloas sources: [] spec: | - - def get_sync_message_due_ms() -> uint64: + + def get_sync_message_due_ms() -> Uint64: # [Modified in Gloas] return get_slot_component_duration_ms(SYNC_MESSAGE_DUE_BPS_GLOAS) @@ -5667,9 +5671,9 @@ - file: beacon-chain/core/altair/sync_committee.go search: func SyncSubCommitteePubkeys( spec: | - + def get_sync_subcommittee_pubkeys( - state: BeaconState, subcommittee_index: uint64 + state: BeaconState, subcommittee_index: Uint64 ) -> Sequence[BLSPubkey]: # Committees assigned to `slot` sign for `slot - 1` # This creates the exceptional logic below when transitioning between sync committee periods @@ -5741,12 +5745,12 @@ - file: beacon-chain/core/helpers/rewards_penalties.go search: func TotalBalance( spec: | - + def get_total_balance(state: BeaconState, indices: Set[ValidatorIndex]) -> Gwei: """ Return the combined effective balance of the ``indices``. ``EFFECTIVE_BALANCE_INCREMENT`` Gwei minimum to avoid divisions by zero. - Math safe up to ~10B ETH, after which this overflows uint64. + Math safe up to ~10B ETH, after which this overflows Uint64. """ return Gwei( max( @@ -5818,8 +5822,8 @@ - file: beacon-chain/core/helpers/validators.go search: func ValidatorActivationChurnLimitDeneb( spec: | - - def get_validator_activation_churn_limit(state: BeaconState) -> uint64: + + def get_validator_activation_churn_limit(state: BeaconState) -> Uint64: """ Return the validator activation churn limit for the current epoch. """ @@ -5831,14 +5835,14 @@ - file: beacon-chain/core/helpers/validators.go search: func ValidatorExitChurnLimit( spec: | - - def get_validator_churn_limit(state: BeaconState) -> uint64: + + def get_validator_churn_limit(state: BeaconState) -> Uint64: """ Return the validator churn limit for the current epoch. """ active_validator_indices = get_active_validator_indices(state, get_current_epoch(state)) return max( - MIN_PER_EPOCH_CHURN_LIMIT, uint64(len(active_validator_indices)) // CHURN_LIMIT_QUOTIENT + MIN_PER_EPOCH_CHURN_LIMIT, Uint64(len(active_validator_indices)) // CHURN_LIMIT_QUOTIENT ) @@ -5847,9 +5851,9 @@ - file: beacon-chain/core/altair/deposit.go search: func GetValidatorFromDeposit( spec: | - + def get_validator_from_deposit( - pubkey: BLSPubkey, withdrawal_credentials: Bytes32, amount: uint64 + pubkey: BLSPubkey, withdrawal_credentials: Bytes32, amount: Uint64 ) -> Validator: effective_balance = min(amount - amount % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE) @@ -5870,9 +5874,9 @@ - file: beacon-chain/core/electra/deposits.go search: func GetValidatorFromDeposit( spec: | - + def get_validator_from_deposit( - pubkey: BLSPubkey, withdrawal_credentials: Bytes32, amount: uint64 + pubkey: BLSPubkey, withdrawal_credentials: Bytes32, amount: Uint64 ) -> Validator: validator = Validator( pubkey=pubkey, @@ -5899,10 +5903,10 @@ - file: beacon-chain/core/peerdas/validator.go search: func ValidatorsCustodyRequirement( spec: | - + def get_validators_custody_requirement( state: BeaconState, validator_indices: Sequence[ValidatorIndex] - ) -> uint64: + ) -> Uint64: total_node_balance = sum( state.validators[index].effective_balance for index in validator_indices ) @@ -5913,19 +5917,19 @@ - name: get_validators_sweep_withdrawals#capella sources: [] spec: | - + def get_validators_sweep_withdrawals( state: BeaconState, withdrawal_index: WithdrawalIndex, prior_withdrawals: Sequence[Withdrawal], - ) -> Tuple[Sequence[Withdrawal], WithdrawalIndex, uint64]: + ) -> Tuple[Sequence[Withdrawal], WithdrawalIndex, Uint64]: epoch = get_current_epoch(state) validators_limit = min(len(state.validators), MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP) withdrawals_limit = MAX_WITHDRAWALS_PER_PAYLOAD # There must be at least one space reserved for validator sweep withdrawals assert len(prior_withdrawals) < withdrawals_limit - processed_count: uint64 = 0 + processed_count: Uint64 = 0 withdrawals: List[Withdrawal] = [] validator_index = state.next_withdrawal_validator_index for _ in range(validators_limit): @@ -5966,19 +5970,19 @@ - name: get_validators_sweep_withdrawals#electra sources: [] spec: | - + def get_validators_sweep_withdrawals( state: BeaconState, withdrawal_index: WithdrawalIndex, prior_withdrawals: Sequence[Withdrawal], - ) -> Tuple[Sequence[Withdrawal], WithdrawalIndex, uint64]: + ) -> Tuple[Sequence[Withdrawal], WithdrawalIndex, Uint64]: epoch = get_current_epoch(state) validators_limit = min(len(state.validators), MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP) withdrawals_limit = MAX_WITHDRAWALS_PER_PAYLOAD # There must be at least one space reserved for validator sweep withdrawals assert len(prior_withdrawals) < withdrawals_limit - processed_count: uint64 = 0 + processed_count: Uint64 = 0 withdrawals: List[Withdrawal] = [] validator_index = state.next_withdrawal_validator_index for _ in range(validators_limit): @@ -6163,9 +6167,9 @@ - file: beacon-chain/core/transition/state.go search: func GenesisBeaconState( spec: | - + def initialize_beacon_state_from_eth1( - eth1_block_hash: Hash32, eth1_timestamp: uint64, deposits: Sequence[Deposit] + eth1_block_hash: Hash32, eth1_timestamp: Uint64, deposits: Sequence[Deposit] ) -> BeaconState: fork = Fork( previous_version=GENESIS_FORK_VERSION, @@ -6175,7 +6179,7 @@ state = BeaconState( genesis_time=eth1_timestamp + GENESIS_DELAY, fork=fork, - eth1_data=Eth1Data(deposit_count=uint64(len(deposits)), block_hash=eth1_block_hash), + eth1_data=Eth1Data(deposit_count=Uint64(len(deposits)), block_hash=eth1_block_hash), latest_block_header=BeaconBlockHeader(body_root=hash_tree_root(BeaconBlockBody())), randao_mixes=[eth1_block_hash] * EPOCHS_PER_HISTORICAL_VECTOR, # Seed RANDAO with Eth1 entropy @@ -6350,8 +6354,8 @@ - file: math/math_helper.go search: func IntegerSquareRoot( spec: | - - def integer_squareroot(n: uint64) -> uint64: + + def integer_squareroot(n: Uint64) -> Uint64: """ Return the largest integer ``x`` such that ``x**2 <= n``. """ @@ -6530,6 +6534,35 @@ return new_update.signature_slot < old_update.signature_slot +- name: is_bid_compatible_with_head#gloas + sources: [] + spec: | + + def is_bid_compatible_with_head(store: Store, bid: ExecutionPayloadBid) -> bool: + """ + Check if ``bid`` is compatible with the head branch. + """ + head_node = get_head(store) + head_block = store.blocks[head_node.root] + head_bid = head_block.body.signed_execution_payload_bid.message + + builds_on_parent_block = bid.parent_block_root == head_block.parent_root + builds_on_parent_payload = bid.parent_block_hash == head_bid.parent_block_hash + + if builds_on_parent_block and builds_on_parent_payload: + return True + + if bid.parent_block_root != head_node.root: + return False + + builds_on_head_payload = bid.parent_block_hash == head_bid.block_hash + + if should_build_on_full(store, head_node, bid.slot): + return builds_on_head_payload + + return builds_on_parent_payload + + - name: is_builder_index#gloas sources: [] spec: | @@ -6549,8 +6582,8 @@ - name: is_candidate_block#phase0 sources: [] spec: | - - def is_candidate_block(block: Eth1Block, period_start: uint64) -> bool: + + def is_candidate_block(block: Eth1Block, period_start: Uint64) -> bool: return ( block.timestamp + SECONDS_PER_ETH1_BLOCK * ETH1_FOLLOW_DISTANCE <= period_start and block.timestamp + SECONDS_PER_ETH1_BLOCK * ETH1_FOLLOW_DISTANCE * 2 >= period_start @@ -6609,14 +6642,32 @@ ) +- name: is_current_or_previous_epoch#deneb + sources: [] + spec: | + + def is_current_or_previous_epoch( + state: BeaconState, + epoch: Epoch, + current_time_ms: Uint64, + ) -> bool: + """ + Check if the given epoch is the current or previous epoch + (with MAXIMUM_GOSSIP_CLOCK_DISPARITY allowance). + """ + is_current = is_within_epoch(state, epoch, current_time_ms) + is_previous = is_within_epoch(state, Epoch(epoch + 1), current_time_ms) + return is_current or is_previous + + - name: is_current_slot#altair sources: [] spec: | - + def is_current_slot( state: BeaconState, slot: Slot, - current_time_ms: uint64, + current_time_ms: Uint64, ) -> bool: """ Check if the given slot is the current slot @@ -6632,7 +6683,7 @@ - file: beacon-chain/blockchain/process_block.go search: func (s *Service) areBlobsAvailable( spec: | - + def is_data_available( beacon_block_root: Root, blob_kzg_commitments: Sequence[KZGCommitment] ) -> bool: @@ -6642,7 +6693,7 @@ # `MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS` blobs, proofs = retrieve_blobs_and_proofs(beacon_block_root) - return verify_blob_kzg_proof_batch(blobs, blob_kzg_commitments, proofs) + return kzg.verify_blob_kzg_proof_batch(blobs, blob_kzg_commitments, proofs) - name: is_data_available#fulu @@ -6785,13 +6836,13 @@ - name: is_full_validator_set_covered#phase0 sources: [] spec: | - + def is_full_validator_set_covered(start_slot: Slot, end_slot: Slot) -> bool: """ Return ``True`` if the range between ``start_slot`` and ``end_slot`` (inclusive of both) includes an entire epoch. """ - start_full_epoch = compute_epoch_at_slot(start_slot + (SLOTS_PER_EPOCH - 1)) - end_full_epoch = compute_epoch_at_slot(Slot(end_slot + 1)) + start_full_epoch = compute_epoch_at_slot(start_slot + SLOTS_PER_EPOCH - Slot(1)) + end_full_epoch = compute_epoch_at_slot(end_slot + Slot(1)) return start_full_epoch < end_full_epoch @@ -6835,9 +6886,9 @@ - name: is_gas_limit_target_compatible#gloas sources: [] spec: | - + def is_gas_limit_target_compatible( - parent_gas_limit: uint64, gas_limit: uint64, target_gas_limit: uint64 + parent_gas_limit: Uint64, gas_limit: Uint64, target_gas_limit: Uint64 ) -> bool: """ Check if ``gas_limit`` is compatible with ``target_gas_limit`` under the @@ -6873,18 +6924,35 @@ - name: is_head_weak#phase0 sources: [] spec: | - + def is_head_weak(store: Store, head_root: Root) -> bool: + # Calculate weight threshold for weak head justified_state = store.checkpoint_states[store.justified_checkpoint] reorg_threshold = calculate_committee_fraction(justified_state, REORG_HEAD_WEIGHT_THRESHOLD) - head_weight = get_weight(store, ForkChoiceNode(root=head_root)) + + # Compute head weight including equivocations + head_state = store.block_states[head_root] + head_block = store.blocks[head_root] + epoch = compute_epoch_at_slot(head_block.slot) + head_node = ForkChoiceNode(root=head_root) + head_weight = get_attestation_score(store, head_node, justified_state) + for index in range(get_committee_count_per_slot(head_state, epoch)): + committee = get_beacon_committee(head_state, head_block.slot, CommitteeIndex(index)) + head_weight += Gwei( + sum( + justified_state.validators[i].effective_balance + for i in committee + if i in store.equivocating_indices + ) + ) + return head_weight < reorg_threshold - name: is_head_weak#gloas sources: [] spec: | - + def is_head_weak(store: Store, head_root: Root) -> bool: # Calculate weight threshold for weak head justified_state = store.checkpoint_states[store.justified_checkpoint] @@ -6894,6 +6962,7 @@ head_state = store.block_states[head_root] head_block = store.blocks[head_root] epoch = compute_epoch_at_slot(head_block.slot) + # [Modified in Gloas:EIP7732] head_node = ForkChoiceNode(root=head_root, payload_status=PAYLOAD_STATUS_PENDING) head_weight = get_attestation_score(store, head_node, justified_state) for index in range(get_committee_count_per_slot(head_state, epoch)): @@ -6922,12 +6991,12 @@ - name: is_inclusion_list_bits_inclusive#heze sources: [] spec: | - + def is_inclusion_list_bits_inclusive( store: InclusionListStore, state: BeaconState, slot: Slot, - inclusion_list_bits: Bitvector[INCLUSION_LIST_COMMITTEE_SIZE], + inclusion_list_bits: BitVector[INCLUSION_LIST_COMMITTEE_SIZE], only_timely: bool = True, ) -> bool: """ @@ -6973,10 +7042,10 @@ - name: is_non_strict_superset#phase0 sources: [] spec: | - + def is_non_strict_superset( - seen_bits_set: Set[Tuple[boolean, ...]], - new_bits: Tuple[boolean, ...], + seen_bits_set: Set[Tuple[Boolean, ...]], + new_bits: Tuple[Boolean, ...], ) -> bool: """ Return True if any prior bitset in ``seen_bits_set`` is a non-strict @@ -6996,11 +7065,11 @@ - name: is_not_from_future_slot#phase0 sources: [] spec: | - + def is_not_from_future_slot( state: BeaconState, slot: Slot, - current_time_ms: uint64, + current_time_ms: Uint64, ) -> bool: """ Check if the given slot is not from the future @@ -7060,13 +7129,13 @@ - name: is_parent_strong#phase0 sources: [] spec: | - + def is_parent_strong(store: Store, root: Root) -> bool: justified_state = store.checkpoint_states[store.justified_checkpoint] parent_threshold = calculate_committee_fraction(justified_state, REORG_PARENT_WEIGHT_THRESHOLD) parent_root = store.blocks[root].parent_root parent_node = ForkChoiceNode(root=parent_root) - parent_weight = get_weight(store, parent_node) + parent_weight = get_attestation_score(store, parent_node, justified_state) return parent_weight > parent_threshold @@ -7316,6 +7385,25 @@ return bls.Verify(request.pubkey, signing_root, request.signature) +- name: is_valid_dependent_root#gloas + sources: [] + spec: | + + def is_valid_dependent_root(store: Store, root: Root, epoch: Epoch) -> bool: + """ + Check if the block with the given ``root`` is a possible dependent block + for the given ``epoch``, meaning that on some branch it is, or could + become, the latest block prior to the start of the epoch. + """ + epoch_start_slot = compute_start_slot_at_epoch(epoch) + if store.blocks[root].slot >= epoch_start_slot: + return False + for block in store.blocks.values(): + if block.parent_root == root and block.slot >= epoch_start_slot: + return True + return root == get_head(store).root + + - name: is_valid_deposit_signature#electra sources: - file: beacon-chain/core/electra/deposits.go @@ -7323,9 +7411,9 @@ - file: beacon-chain/core/helpers/deposit.go search: func IsValidDepositSignature( spec: | - + def is_valid_deposit_signature( - pubkey: BLSPubkey, withdrawal_credentials: Bytes32, amount: uint64, signature: BLSSignature + pubkey: BLSPubkey, withdrawal_credentials: Bytes32, amount: Uint64, signature: BLSSignature ) -> bool: deposit_message = DepositMessage( pubkey=pubkey, @@ -7477,15 +7565,15 @@ - name: is_valid_light_client_header#deneb sources: [] spec: | - + def is_valid_light_client_header(header: LightClientHeader) -> bool: epoch = compute_epoch_at_slot(header.beacon.slot) # [New in Deneb:EIP4844] if epoch < DENEB_FORK_EPOCH: - if header.execution.blob_gas_used != uint64(0): + if header.execution.blob_gas_used != Uint64(0): return False - if header.execution.excess_blob_gas != uint64(0): + if header.execution.excess_blob_gas != Uint64(0): return False if epoch < CAPELLA_FORK_EPOCH: @@ -7544,9 +7632,9 @@ - name: is_valid_merkle_branch#phase0 sources: [] spec: | - + def is_valid_merkle_branch( - leaf: Bytes32, branch: Sequence[Bytes32], depth: uint64, index: uint64, root: Root + leaf: Bytes32, branch: Sequence[Bytes32], depth: Uint64, index: Uint64, root: Root ) -> bool: """ Check if ``leaf`` at ``index`` verifies against the Merkle ``root`` and ``branch``. @@ -7646,15 +7734,36 @@ return is_total_difficulty_reached and is_parent_total_difficulty_valid +- name: is_within_epoch#deneb + sources: [] + spec: | + + def is_within_epoch( + state: BeaconState, + epoch: Epoch, + current_time_ms: Uint64, + ) -> bool: + """ + Check if the current time is within the given epoch + (with MAXIMUM_GOSSIP_CLOCK_DISPARITY allowance on both ends). + """ + return is_within_slot_range( + state, + compute_start_slot_at_epoch(epoch), + SLOTS_PER_EPOCH - 1, + current_time_ms, + ) + + - name: is_within_slot_range#phase0 sources: [] spec: | - + def is_within_slot_range( state: BeaconState, slot: Slot, - slot_range: uint64, - current_time_ms: uint64, + slot_range: Uint64, + current_time_ms: Uint64, ) -> bool: """ Check if the current time is within the inclusive slot range ``[slot, slot + slot_range]`` @@ -7733,11 +7842,11 @@ - file: beacon-chain/p2p/encoder/ssz.go search: func MaxCompressedLen( spec: | - - def max_compressed_len(n: uint64) -> uint64: + + def max_compressed_len(n: Uint64) -> Uint64: # Worst-case compressed length for a given payload of size n when using snappy: # https://github.com/google/snappy/blob/32ded457c0b1fe78ceb8397632c416568d6714a0/snappy.cc#L218C1-L218C47 - return uint64(32 + n + n / 6) + return Uint64(32 + n + n / 6) - name: max_message_size#phase0 @@ -7745,8 +7854,8 @@ - file: beacon-chain/p2p/pubsub.go search: func MaxMessageSize( spec: | - - def max_message_size() -> uint64: + + def max_message_size() -> Uint64: # Allow 1024 bytes for framing and encoding overhead but at least 1MiB in case MAX_PAYLOAD_SIZE is small. return max(max_compressed_len(MAX_PAYLOAD_SIZE) + 1024, 1024 * 1024) @@ -7882,9 +7991,15 @@ - file: beacon-chain/blockchain/receive_block.go search: func (s *Service) ReceiveBlock( spec: | - + def on_block(store: Store, signed_block: SignedBeaconBlock) -> None: block = signed_block.message + block_root = hash_tree_root(block) + + # Return early if the block is already known + if block_root in store.blocks: + return + # Parent block must be known assert block.parent_root in store.block_states # Make a copy of the state to avoid mutability issues @@ -7905,7 +8020,6 @@ # Check the block is valid and compute the post-state state = pre_state.copy() - block_root = hash_tree_root(block) state_transition(state, signed_block, validate_result=True) # Compute head before applying the block @@ -7930,7 +8044,7 @@ - file: beacon-chain/blockchain/receive_block.go search: func (s *Service) ReceiveBlock( spec: | - + def on_block(store: Store, signed_block: SignedBeaconBlock) -> None: """ Run ``on_block`` upon receiving a new block. @@ -7939,6 +8053,12 @@ consider scheduling it for later processing in such case. """ block = signed_block.message + block_root = hash_tree_root(block) + + # Return early if the block is already known + if block_root in store.blocks: + return + # Parent block must be known assert block.parent_root in store.block_states # Make a copy of the state to avoid mutability issues @@ -7959,7 +8079,6 @@ # Check the block is valid and compute the post-state state = pre_state.copy() - block_root = hash_tree_root(block) state_transition(state, signed_block, validate_result=True) # [New in Bellatrix] @@ -7988,12 +8107,18 @@ - file: beacon-chain/blockchain/receive_block.go search: func (s *Service) ReceiveBlock( spec: | - + def on_block(store: Store, signed_block: SignedBeaconBlock) -> None: """ Run ``on_block`` upon receiving a new block. """ block = signed_block.message + block_root = hash_tree_root(block) + + # Return early if the block is already known + if block_root in store.blocks: + return + # Parent block must be known assert block.parent_root in store.block_states # Blocks cannot be in the future. If they are, their consideration must be delayed until they are in the past. @@ -8013,7 +8138,6 @@ # Check the block is valid and compute the post-state # Make a copy of the state to avoid mutability issues state = copy(store.block_states[block.parent_root]) - block_root = hash_tree_root(block) state_transition(state, signed_block, validate_result=True) # Compute head before applying the block @@ -8038,12 +8162,18 @@ - file: beacon-chain/blockchain/receive_block.go search: func (s *Service) ReceiveBlock( spec: | - + def on_block(store: Store, signed_block: SignedBeaconBlock) -> None: """ Run ``on_block`` upon receiving a new block. """ block = signed_block.message + block_root = hash_tree_root(block) + + # Return early if the block is already known + if block_root in store.blocks: + return + # Parent block must be known assert block.parent_root in store.block_states # Blocks cannot be in the future. If they are, their consideration must be delayed until they are in the past. @@ -8063,12 +8193,11 @@ # [New in Deneb:EIP4844] # Check if blob data is available # If not, this payload MAY be queued and subsequently considered when blob data becomes available - assert is_data_available(hash_tree_root(block), block.body.blob_kzg_commitments) + assert is_data_available(block_root, block.body.blob_kzg_commitments) # Check the block is valid and compute the post-state # Make a copy of the state to avoid mutability issues state = copy(store.block_states[block.parent_root]) - block_root = hash_tree_root(block) state_transition(state, signed_block, validate_result=True) # Compute head before applying the block @@ -8093,12 +8222,18 @@ - file: beacon-chain/blockchain/receive_block.go search: func (s *Service) ReceiveBlock( spec: | - + def on_block(store: Store, signed_block: SignedBeaconBlock) -> None: """ Run ``on_block`` upon receiving a new block. """ block = signed_block.message + block_root = hash_tree_root(block) + + # Return early if the block is already known + if block_root in store.blocks: + return + # Parent block must be known assert block.parent_root in store.block_states # Make a copy of the state to avoid mutability issues @@ -8120,10 +8255,9 @@ # [Modified in Fulu:EIP7594] # Check if blob data is available # If not, this payload MAY be queued and subsequently considered when blob data becomes available - assert is_data_available(hash_tree_root(block)) + assert is_data_available(block_root) # Check the block is valid and compute the post-state - block_root = hash_tree_root(block) state_transition(state, signed_block, validate_result=True) # Compute head before applying the block @@ -8146,12 +8280,18 @@ - name: on_block#gloas sources: [] spec: | - + def on_block(store: Store, signed_block: SignedBeaconBlock) -> None: """ Run ``on_block`` upon receiving a new block. """ block = signed_block.message + block_root = hash_tree_root(block) + + # Return early if the block is already known + if block_root in store.blocks: + return + # Parent block must be known assert block.parent_root in store.block_states @@ -8179,7 +8319,6 @@ state = copy(store.block_states[block.parent_root]) # Check the block is valid and compute the post-state - block_root = hash_tree_root(block) state_transition(state, signed_block, validate_result=True) # Compute head before applying the block @@ -8278,19 +8417,17 @@ - name: on_inclusion_list#heze sources: [] spec: | - + def on_inclusion_list(store: Store, signed_inclusion_list: SignedInclusionList) -> None: """ Run ``on_inclusion_list`` upon receiving a new inclusion list. """ - inclusion_list = signed_inclusion_list.message - seconds_since_genesis = store.time - store.genesis_time time_into_slot_ms = seconds_to_milliseconds(seconds_since_genesis) % SLOT_DURATION_MS inclusion_list_due_ms = get_inclusion_list_due_ms() is_timely = time_into_slot_ms < inclusion_list_due_ms - process_inclusion_list(get_inclusion_list_store(), inclusion_list, is_timely) + process_inclusion_list(get_inclusion_list_store(), signed_inclusion_list, is_timely) - name: on_payload_attestation_message#gloas @@ -8349,8 +8486,8 @@ - name: on_tick#phase0 sources: [] spec: | - - def on_tick(store: Store, time: uint64) -> None: + + def on_tick(store: Store, time: Uint64) -> None: # If the ``store.time`` falls behind, while loop catches up slot by slot # to ensure that every previous slot is processed with ``on_tick_per_slot`` tick_slot = (time - store.genesis_time) * 1000 // SLOT_DURATION_MS @@ -8365,8 +8502,8 @@ - name: on_tick_per_slot#phase0 sources: [] spec: | - - def on_tick_per_slot(store: Store, time: uint64) -> None: + + def on_tick_per_slot(store: Store, time: Uint64) -> None: previous_slot = get_current_slot(store) # Update store time @@ -8573,7 +8710,7 @@ - name: prepare_execution_payload#heze sources: [] spec: | - + def prepare_execution_payload( store: Store, head: ForkChoiceNode, @@ -8581,11 +8718,11 @@ safe_block_hash: Hash32, finalized_block_hash: Hash32, suggested_fee_recipient: ExecutionAddress, - target_gas_limit: uint64, + target_gas_limit: Uint64, execution_engine: ExecutionEngine, ) -> Optional[PayloadId]: parent_bid = state.latest_execution_payload_bid - if should_build_on_full(store, head): + if should_build_on_full(store, head, get_current_slot(store)): envelope = store.payloads[head.root] # Make a copy of the state to avoid mutability issues state = copy(state) @@ -8812,8 +8949,13 @@ - name: process_attestation#gloas sources: [] spec: | - - def process_attestation(state: BeaconState, attestation: Attestation) -> None: + + def process_attestation( + state: BeaconState, + attestation: Attestation, + # [New in Gloas:EIP7732] + parent_slot: Slot, + ) -> None: data = attestation.data assert data.target.epoch in (get_previous_epoch(state), get_current_epoch(state)) assert data.target.epoch == compute_epoch_at_slot(data.slot) @@ -8838,8 +8980,9 @@ assert len(attestation.aggregation_bits) == committee_offset # Participation flag indices + # [Modified in Gloas:EIP7732] participation_flag_indices = get_attestation_participation_flag_indices( - state, data, state.slot - data.slot + state, data, state.slot - data.slot, parent_slot ) # Verify signature @@ -9022,7 +9165,7 @@ - name: process_block#gloas sources: [] spec: | - + def process_block(state: BeaconState, block: BeaconBlock) -> None: # [New in Gloas:EIP7732] process_parent_execution_payload(state, block) @@ -9032,11 +9175,11 @@ # [Modified in Gloas:EIP7732] # Removed `process_execution_payload` # [New in Gloas:EIP7732] - process_execution_payload_bid(state, block.body.signed_execution_payload_bid) + parent_slot = process_execution_payload_bid(state, block.body.signed_execution_payload_bid) process_randao(state, block.body) process_eth1_data(state, block.body) # [Modified in Gloas:EIP7732] - process_operations(state, block.body) + process_operations(state, block.body, parent_slot) process_sync_aggregate(state, block.body.sync_aggregate) @@ -9371,12 +9514,12 @@ - file: beacon-chain/core/epoch/epoch_processing.go search: func ProcessEffectiveBalanceUpdates( spec: | - + def process_effective_balance_updates(state: BeaconState) -> None: # Update effective balances with hysteresis for index, validator in enumerate(state.validators): balance = state.balances[index] - HYSTERESIS_INCREMENT = uint64(EFFECTIVE_BALANCE_INCREMENT // HYSTERESIS_QUOTIENT) + HYSTERESIS_INCREMENT = Uint64(EFFECTIVE_BALANCE_INCREMENT // HYSTERESIS_QUOTIENT) DOWNWARD_THRESHOLD = HYSTERESIS_INCREMENT * HYSTERESIS_DOWNWARD_MULTIPLIER UPWARD_THRESHOLD = HYSTERESIS_INCREMENT * HYSTERESIS_UPWARD_MULTIPLIER if ( @@ -9393,12 +9536,12 @@ - file: beacon-chain/core/electra/effective_balance_updates.go search: func ProcessEffectiveBalanceUpdates( spec: | - + def process_effective_balance_updates(state: BeaconState) -> None: # Update effective balances with hysteresis for index, validator in enumerate(state.validators): balance = state.balances[index] - HYSTERESIS_INCREMENT = uint64(EFFECTIVE_BALANCE_INCREMENT // HYSTERESIS_QUOTIENT) + HYSTERESIS_INCREMENT = Uint64(EFFECTIVE_BALANCE_INCREMENT // HYSTERESIS_QUOTIENT) DOWNWARD_THRESHOLD = HYSTERESIS_INCREMENT * HYSTERESIS_DOWNWARD_MULTIPLIER UPWARD_THRESHOLD = HYSTERESIS_INCREMENT * HYSTERESIS_UPWARD_MULTIPLIER # [Modified in Electra:EIP7251] @@ -9927,10 +10070,10 @@ - name: process_execution_payload_bid#gloas sources: [] spec: | - + def process_execution_payload_bid( state: BeaconState, signed_bid: SignedExecutionPayloadBid - ) -> None: + ) -> Slot: bid = signed_bid.message builder_index = bid.builder_index amount = bid.value @@ -9978,8 +10121,13 @@ pending_payment ) + # Cache the parent block's slot before overwriting the bid + parent_slot = state.latest_execution_payload_bid.slot + # Cache the signed execution payload bid state.latest_execution_payload_bid = bid + + return parent_slot - name: process_historical_roots_update#phase0 @@ -10044,12 +10192,13 @@ - name: process_inclusion_list#heze sources: [] spec: | - + def process_inclusion_list( store: InclusionListStore, - inclusion_list: InclusionList, + signed_inclusion_list: SignedInclusionList, is_timely: bool, ) -> None: + inclusion_list = signed_inclusion_list.message key = inclusion_list.inclusion_list_committee_root # Ignore `inclusion_list` from equivocators. @@ -10057,7 +10206,7 @@ return for stored_root in store.inclusion_lists[key]: - stored_inclusion_list = store.inclusion_lists[key][stored_root] + stored_inclusion_list = store.inclusion_lists[key][stored_root].message if stored_inclusion_list.validator_index != inclusion_list.validator_index: continue @@ -10067,9 +10216,9 @@ # Whether it was an equivocation or not, we have processed this `inclusion_list`. return - # Store `inclusion_list` and its timeliness. + # Store `signed_inclusion_list` and its timeliness. inclusion_list_root = hash_tree_root(inclusion_list) - store.inclusion_lists[key][inclusion_list_root] = inclusion_list + store.inclusion_lists[key][inclusion_list_root] = signed_inclusion_list store.inclusion_list_timeliness[inclusion_list_root] = is_timely @@ -10353,13 +10502,19 @@ - name: process_operations#gloas sources: [] spec: | - - def process_operations(state: BeaconState, body: BeaconBlockBody) -> None: + + def process_operations( + state: BeaconState, + body: BeaconBlockBody, + # [New in Gloas:EIP7732] + parent_slot: Slot, + ) -> None: assert len(body.deposits) == 0 - def for_ops(operations: Sequence[Any], fn: Callable[[BeaconState, Any], None]) -> None: + # [Modified in Gloas:EIP7732] + def for_ops(operations: Sequence[Any], fn: Callable[..., None], *args: Any) -> None: for operation in operations: - fn(state, operation) + fn(state, operation, *args) # [New in Gloas:EIP7688] assert len(body.proposer_slashings) <= MAX_PROPOSER_SLASHINGS @@ -10373,7 +10528,7 @@ for_ops(body.proposer_slashings, process_proposer_slashing) for_ops(body.attester_slashings, process_attester_slashing) # [Modified in Gloas:EIP7732] - for_ops(body.attestations, process_attestation) + for_ops(body.attestations, process_attestation, parent_slot) for_ops(body.voluntary_exits, process_voluntary_exit) for_ops(body.bls_to_execution_changes, process_bls_to_execution_change) # [Modified in Gloas:EIP7732] @@ -10956,7 +11111,7 @@ - file: beacon-chain/core/epoch/epoch_processing.go search: func ProcessSlashings( spec: | - + def process_slashings(state: BeaconState) -> None: epoch = get_current_epoch(state) total_balance = get_total_active_balance(state) @@ -10968,7 +11123,7 @@ validator.slashed and epoch + EPOCHS_PER_SLASHINGS_VECTOR // 2 == validator.withdrawable_epoch ): - increment = EFFECTIVE_BALANCE_INCREMENT # Factored out from penalty numerator to avoid uint64 overflow + increment = EFFECTIVE_BALANCE_INCREMENT # Factored out from penalty numerator to avoid Uint64 overflow penalty_numerator = ( validator.effective_balance // increment * adjusted_total_slashing_balance ) @@ -10981,7 +11136,7 @@ - file: beacon-chain/core/epoch/epoch_processing.go search: func ProcessSlashings( spec: | - + def process_slashings(state: BeaconState) -> None: epoch = get_current_epoch(state) total_balance = get_total_active_balance(state) @@ -10993,7 +11148,7 @@ validator.slashed and epoch + EPOCHS_PER_SLASHINGS_VECTOR // 2 == validator.withdrawable_epoch ): - increment = EFFECTIVE_BALANCE_INCREMENT # Factored out from penalty numerator to avoid uint64 overflow + increment = EFFECTIVE_BALANCE_INCREMENT # Factored out from penalty numerator to avoid Uint64 overflow penalty_numerator = ( validator.effective_balance // increment * adjusted_total_slashing_balance ) @@ -11006,7 +11161,7 @@ - file: beacon-chain/core/epoch/epoch_processing.go search: func ProcessSlashings( spec: | - + def process_slashings(state: BeaconState) -> None: epoch = get_current_epoch(state) total_balance = get_total_active_balance(state) @@ -11021,7 +11176,7 @@ validator.slashed and epoch + EPOCHS_PER_SLASHINGS_VECTOR // 2 == validator.withdrawable_epoch ): - increment = EFFECTIVE_BALANCE_INCREMENT # Factored out from penalty numerator to avoid uint64 overflow + increment = EFFECTIVE_BALANCE_INCREMENT # Factored out from penalty numerator to avoid Uint64 overflow penalty_numerator = ( validator.effective_balance // increment * adjusted_total_slashing_balance ) @@ -11034,7 +11189,7 @@ - file: beacon-chain/core/epoch/epoch_processing.go search: func ProcessSlashings( spec: | - + def process_slashings(state: BeaconState) -> None: epoch = get_current_epoch(state) total_balance = get_total_active_balance(state) @@ -11042,7 +11197,7 @@ sum(state.slashings) * PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX, total_balance ) increment = ( - EFFECTIVE_BALANCE_INCREMENT # Factored out from total balance to avoid uint64 overflow + EFFECTIVE_BALANCE_INCREMENT # Factored out from total balance to avoid Uint64 overflow ) penalty_per_effective_balance_increment = adjusted_total_slashing_balance // ( total_balance // increment @@ -11552,7 +11707,7 @@ - name: record_payload_inclusion_list_satisfaction#heze sources: [] spec: | - + def record_payload_inclusion_list_satisfaction( store: Store, state: BeaconState, @@ -11561,7 +11716,7 @@ execution_engine: ExecutionEngine, ) -> None: inclusion_list_transactions = get_inclusion_list_transactions( - get_inclusion_list_store(), state, Slot(state.slot - 1) + get_inclusion_list_store(), state, Slot(state.slot - 1), only_timely=True ) is_inclusion_list_satisfied = execution_engine.is_inclusion_list_satisfied( payload, inclusion_list_transactions @@ -11572,21 +11727,21 @@ - name: recover_matrix#fulu sources: [] spec: | - + def recover_matrix( - partial_matrix: Sequence[MatrixEntry], blob_count: uint64 + partial_matrix: Sequence[MatrixEntry], blob_count: Uint64 ) -> Sequence[MatrixEntry]: """ Recover the full, flattened sequence of matrix entries. - This helper demonstrates how to apply ``recover_cells_and_kzg_proofs``. + This helper demonstrates how to apply ``kzg.recover_cells_and_kzg_proofs``. The data structure for storing cells/proofs is implementation-dependent. """ matrix = [] for blob_index in range(blob_count): cell_indices = [e.column_index for e in partial_matrix if e.row_index == blob_index] cells = [e.cell for e in partial_matrix if e.row_index == blob_index] - recovered_cells, recovered_proofs = recover_cells_and_kzg_proofs(cell_indices, cells) + recovered_cells, recovered_proofs = kzg.recover_cells_and_kzg_proofs(cell_indices, cells) for cell_index, (cell, proof) in enumerate( zip(recovered_cells, recovered_proofs, strict=True) ): @@ -11604,8 +11759,8 @@ - name: seconds_to_milliseconds#phase0 sources: [] spec: | - - def seconds_to_milliseconds(seconds: uint64) -> uint64: + + def seconds_to_milliseconds(seconds: Uint64) -> Uint64: """ Convert seconds to milliseconds with overflow protection. Returns ``UINT64_MAX`` if the result would overflow. @@ -11629,8 +11784,8 @@ - name: settle_builder_payment#gloas sources: [] spec: | - - def settle_builder_payment(state: BeaconState, payment_index: uint64) -> None: + + def settle_builder_payment(state: BeaconState, payment_index: Uint64) -> None: assert payment_index < len(state.builder_pending_payments) payment = state.builder_pending_payments[payment_index] if payment.withdrawal.amount > 0: @@ -11678,10 +11833,10 @@ - name: should_build_on_full#gloas sources: [] spec: | - - def should_build_on_full(store: Store, head: ForkChoiceNode) -> bool: + + def should_build_on_full(store: Store, head: ForkChoiceNode, slot: Slot) -> bool: assert head.payload_status != PAYLOAD_STATUS_PENDING - if store.blocks[head.root].slot + 1 != get_current_slot(store): + if store.blocks[head.root].slot + 1 != slot: return head.payload_status == PAYLOAD_STATUS_FULL if head.payload_status == PAYLOAD_STATUS_EMPTY: return False @@ -11956,9 +12111,9 @@ - name: update_builder_pending_withdrawals#gloas sources: [] spec: | - + def update_builder_pending_withdrawals( - state: BeaconState, processed_builder_withdrawals_count: uint64 + state: BeaconState, processed_builder_withdrawals_count: Uint64 ) -> None: state.builder_pending_withdrawals = state.builder_pending_withdrawals[ processed_builder_withdrawals_count: @@ -12055,9 +12210,9 @@ - name: update_next_withdrawal_builder_index#gloas sources: [] spec: | - + def update_next_withdrawal_builder_index( - state: BeaconState, processed_builders_sweep_count: uint64 + state: BeaconState, processed_builders_sweep_count: Uint64 ) -> None: if len(state.builders) > 0: # Update the next builder index to start the next withdrawal sweep @@ -12111,9 +12266,9 @@ - name: update_pending_partial_withdrawals#electra sources: [] spec: | - + def update_pending_partial_withdrawals( - state: BeaconState, processed_partial_withdrawals_count: uint64 + state: BeaconState, processed_partial_withdrawals_count: Uint64 ) -> None: state.pending_partial_withdrawals = state.pending_partial_withdrawals[ processed_partial_withdrawals_count: @@ -12353,7 +12508,7 @@ - name: upgrade_lc_header_to_deneb#deneb sources: [] spec: | - + def upgrade_lc_header_to_deneb(pre: capella.LightClientHeader) -> LightClientHeader: return LightClientHeader( beacon=pre.beacon, @@ -12374,9 +12529,9 @@ transactions_root=pre.execution.transactions_root, withdrawals_root=pre.execution.withdrawals_root, # [New in Deneb:EIP4844] - blob_gas_used=uint64(0), + blob_gas_used=Uint64(0), # [New in Deneb:EIP4844] - excess_blob_gas=uint64(0), + excess_blob_gas=Uint64(0), ), execution_branch=pre.execution_branch, ) @@ -12661,7 +12816,7 @@ - file: beacon-chain/core/altair/upgrade.go search: func UpgradeToAltair( spec: | - + def upgrade_to_altair(pre: phase0.BeaconState) -> BeaconState: epoch = phase0.get_current_epoch(pre) post = BeaconState( @@ -12695,7 +12850,7 @@ previous_justified_checkpoint=pre.previous_justified_checkpoint, current_justified_checkpoint=pre.current_justified_checkpoint, finalized_checkpoint=pre.finalized_checkpoint, - inactivity_scores=[uint64(0) for _ in range(len(pre.validators))], + inactivity_scores=[Uint64(0) for _ in range(len(pre.validators))], ) # Fill in previous epoch participation from the pre state's pending attestations translate_participation(post, pre.previous_epoch_attestations) @@ -12825,7 +12980,7 @@ - file: beacon-chain/core/deneb/upgrade.go search: func UpgradeToDeneb( spec: | - + def upgrade_to_deneb(pre: capella.BeaconState) -> BeaconState: epoch = capella.get_current_epoch(pre) latest_execution_payload_header = ExecutionPayloadHeader( @@ -12845,9 +13000,9 @@ transactions_root=pre.latest_execution_payload_header.transactions_root, withdrawals_root=pre.latest_execution_payload_header.withdrawals_root, # [New in Deneb:EIP4844] - blob_gas_used=uint64(0), + blob_gas_used=Uint64(0), # [New in Deneb:EIP4844] - excess_blob_gas=uint64(0), + excess_blob_gas=Uint64(0), ) post = BeaconState( genesis_time=pre.genesis_time, @@ -13059,7 +13214,7 @@ - name: upgrade_to_gloas#gloas sources: [] spec: | - + def upgrade_to_gloas(pre: fulu.BeaconState) -> BeaconState: epoch = fulu.get_current_epoch(pre) @@ -13099,7 +13254,7 @@ current_justified_checkpoint=pre.current_justified_checkpoint, finalized_checkpoint=pre.finalized_checkpoint, # [Modified in Gloas:EIP7688] - inactivity_scores=ProgressiveList[uint64](list(pre.inactivity_scores)), + inactivity_scores=ProgressiveList[Uint64](list(pre.inactivity_scores)), current_sync_committee=pre.current_sync_committee, next_sync_committee=pre.next_sync_committee, # [Modified in Gloas:EIP7732] @@ -13157,7 +13312,7 @@ - name: upgrade_to_heze#heze sources: [] spec: | - + def upgrade_to_heze(pre: gloas.BeaconState) -> BeaconState: epoch = gloas.get_current_epoch(pre) latest_execution_payload_bid = ExecutionPayloadBid( @@ -13174,7 +13329,7 @@ blob_kzg_commitments=pre.latest_execution_payload_bid.blob_kzg_commitments, execution_requests_root=pre.latest_execution_payload_bid.execution_requests_root, # [New in Heze:EIP7805] - inclusion_list_bits=Bitvector[INCLUSION_LIST_COMMITTEE_SIZE](), + inclusion_list_bits=BitVector[INCLUSION_LIST_COMMITTEE_SIZE](), ) post = BeaconState( @@ -13297,13 +13452,13 @@ - name: validate_beacon_aggregate_and_proof_gossip#phase0 sources: [] spec: | - + def validate_beacon_aggregate_and_proof_gossip( seen: Seen, store: Store, state: BeaconState, signed_aggregate_and_proof: SignedAggregateAndProof, - current_time_ms: uint64, + current_time_ms: Uint64, ) -> None: """ Validate a SignedAggregateAndProof for gossip propagation. @@ -13411,13 +13566,13 @@ - name: validate_beacon_aggregate_and_proof_gossip#deneb sources: [] spec: | - + def validate_beacon_aggregate_and_proof_gossip( seen: Seen, store: Store, state: BeaconState, signed_aggregate_and_proof: SignedAggregateAndProof, - current_time_ms: uint64, + current_time_ms: Uint64, ) -> None: """ Validate a SignedAggregateAndProof for gossip propagation. @@ -13442,20 +13597,8 @@ # [Modified in Deneb:EIP7045] # [IGNORE] The aggregate attestation's epoch is either the current or previous epoch attestation_epoch = compute_epoch_at_slot(aggregate.data.slot) - is_previous_epoch_attestation = is_within_slot_range( - state, - compute_start_slot_at_epoch(Epoch(attestation_epoch + 1)), - SLOTS_PER_EPOCH - 1, - current_time_ms, - ) - is_current_epoch_attestation = is_within_slot_range( - state, - compute_start_slot_at_epoch(attestation_epoch), - SLOTS_PER_EPOCH - 1, - current_time_ms, - ) - if not (is_previous_epoch_attestation or is_current_epoch_attestation): - raise GossipIgnore("aggregate epoch is not previous or current epoch") + if not is_current_or_previous_epoch(state, attestation_epoch, current_time_ms): + raise GossipIgnore("aggregate epoch is not current or previous epoch") # [REJECT] The aggregate attestation's epoch matches its target if aggregate.data.target.epoch != compute_epoch_at_slot(aggregate.data.slot): @@ -13542,13 +13685,13 @@ - name: validate_beacon_aggregate_and_proof_gossip#electra sources: [] spec: | - + def validate_beacon_aggregate_and_proof_gossip( seen: Seen, store: Store, state: BeaconState, signed_aggregate_and_proof: SignedAggregateAndProof, - current_time_ms: uint64, + current_time_ms: Uint64, ) -> None: """ Validate a SignedAggregateAndProof for gossip propagation. @@ -13582,20 +13725,8 @@ # [IGNORE] The aggregate attestation's epoch is either the current or previous epoch attestation_epoch = compute_epoch_at_slot(aggregate.data.slot) - is_previous_epoch_attestation = is_within_slot_range( - state, - compute_start_slot_at_epoch(Epoch(attestation_epoch + 1)), - SLOTS_PER_EPOCH - 1, - current_time_ms, - ) - is_current_epoch_attestation = is_within_slot_range( - state, - compute_start_slot_at_epoch(attestation_epoch), - SLOTS_PER_EPOCH - 1, - current_time_ms, - ) - if not (is_previous_epoch_attestation or is_current_epoch_attestation): - raise GossipIgnore("aggregate epoch is not previous or current epoch") + if not is_current_or_previous_epoch(state, attestation_epoch, current_time_ms): + raise GossipIgnore("aggregate epoch is not current or previous epoch") # [REJECT] The aggregate attestation's epoch matches its target if aggregate.data.target.epoch != compute_epoch_at_slot(aggregate.data.slot): @@ -13684,13 +13815,13 @@ - name: validate_beacon_attestation_gossip#phase0 sources: [] spec: | - + def validate_beacon_attestation_gossip( seen: Seen, store: Store, state: BeaconState, attestation: Attestation, - current_time_ms: uint64, + current_time_ms: Uint64, subnet_id: SubnetID, ) -> None: """ @@ -13774,13 +13905,13 @@ - name: validate_beacon_attestation_gossip#deneb sources: [] spec: | - + def validate_beacon_attestation_gossip( seen: Seen, store: Store, state: BeaconState, attestation: Attestation, - current_time_ms: uint64, + current_time_ms: Uint64, subnet_id: SubnetID, ) -> None: """ @@ -13813,20 +13944,8 @@ # [Modified in Deneb:EIP7045] # [IGNORE] The attestation's epoch is either the current or previous epoch attestation_epoch = compute_epoch_at_slot(data.slot) - is_previous_epoch_attestation = is_within_slot_range( - state, - compute_start_slot_at_epoch(Epoch(attestation_epoch + 1)), - SLOTS_PER_EPOCH - 1, - current_time_ms, - ) - is_current_epoch_attestation = is_within_slot_range( - state, - compute_start_slot_at_epoch(attestation_epoch), - SLOTS_PER_EPOCH - 1, - current_time_ms, - ) - if not (is_previous_epoch_attestation or is_current_epoch_attestation): - raise GossipIgnore("attestation epoch is not previous or current epoch") + if not is_current_or_previous_epoch(state, attestation_epoch, current_time_ms): + raise GossipIgnore("attestation epoch is not current or previous epoch") # [REJECT] The attestation's epoch matches its target if target_epoch != compute_epoch_at_slot(data.slot): @@ -13881,14 +14000,14 @@ - name: validate_beacon_attestation_gossip#electra sources: [] spec: | - + def validate_beacon_attestation_gossip( seen: Seen, store: Store, state: BeaconState, # [Modified in Electra:EIP7549] attestation: SingleAttestation, - current_time_ms: uint64, + current_time_ms: Uint64, subnet_id: SubnetID, ) -> None: """ @@ -13925,20 +14044,8 @@ # [IGNORE] The attestation's epoch is either the current or previous epoch attestation_epoch = compute_epoch_at_slot(data.slot) - is_previous_epoch_attestation = is_within_slot_range( - state, - compute_start_slot_at_epoch(Epoch(attestation_epoch + 1)), - SLOTS_PER_EPOCH - 1, - current_time_ms, - ) - is_current_epoch_attestation = is_within_slot_range( - state, - compute_start_slot_at_epoch(attestation_epoch), - SLOTS_PER_EPOCH - 1, - current_time_ms, - ) - if not (is_previous_epoch_attestation or is_current_epoch_attestation): - raise GossipIgnore("attestation epoch is not previous or current epoch") + if not is_current_or_previous_epoch(state, attestation_epoch, current_time_ms): + raise GossipIgnore("attestation epoch is not current or previous epoch") # [REJECT] The attestation's epoch matches its target if target_epoch != compute_epoch_at_slot(data.slot): @@ -13992,13 +14099,13 @@ - name: validate_beacon_block_gossip#phase0 sources: [] spec: | - + def validate_beacon_block_gossip( seen: Seen, store: Store, state: BeaconState, signed_beacon_block: SignedBeaconBlock, - current_time_ms: uint64, + current_time_ms: Uint64, ) -> None: """ Validate a SignedBeaconBlock for gossip propagation. @@ -14068,13 +14175,13 @@ - name: validate_beacon_block_gossip#bellatrix sources: [] spec: | - + def validate_beacon_block_gossip( seen: Seen, store: Store, state: BeaconState, signed_beacon_block: SignedBeaconBlock, - current_time_ms: uint64, + current_time_ms: Uint64, # [New in Bellatrix] block_payload_statuses: Dict[Root, PayloadValidationStatus], ) -> None: @@ -14129,15 +14236,15 @@ if block.parent_root not in store.block_states: if parent_payload_status == PAYLOAD_STATUS_NOT_VALIDATED: - # [REJECT] The block's parent passes validation - raise GossipReject("block's parent is invalid and EL result is unknown") + # [REJECT] The block's parent failed validation and its execution payload is optimistic + raise GossipReject("block's parent is invalid and its payload is optimistic") - # [IGNORE] The block's parent passes validation - raise GossipIgnore("block's parent is invalid and EL result is known") + # [IGNORE] The block's parent failed validation and its execution payload is processed + raise GossipIgnore("block's parent is invalid and its payload is processed") - # [IGNORE] The block's parent's execution payload passes validation + # [IGNORE] The block's parent passed validation but its execution payload is invalid if parent_payload_status == PAYLOAD_STATUS_INVALIDATED: - raise GossipIgnore("block's parent is valid and EL result is invalid") + raise GossipIgnore("block's parent is valid and its payload is invalid") # [REJECT] The block's parent passes validation elif block.parent_root not in store.block_states: @@ -14170,13 +14277,13 @@ - name: validate_beacon_block_gossip#capella sources: [] spec: | - + def validate_beacon_block_gossip( seen: Seen, store: Store, state: BeaconState, signed_beacon_block: SignedBeaconBlock, - current_time_ms: uint64, + current_time_ms: Uint64, block_payload_statuses: Dict[Root, PayloadValidationStatus], ) -> None: """ @@ -14228,15 +14335,15 @@ if block.parent_root not in store.block_states: if parent_payload_status == PAYLOAD_STATUS_NOT_VALIDATED: - # [REJECT] The block's parent passes validation - raise GossipReject("block's parent is invalid and EL result is unknown") + # [REJECT] The block's parent failed validation and its execution payload is optimistic + raise GossipReject("block's parent is invalid and its payload is optimistic") - # [IGNORE] The block's parent passes validation - raise GossipIgnore("block's parent is invalid and EL result is known") + # [IGNORE] The block's parent failed validation and its execution payload is processed + raise GossipIgnore("block's parent is invalid and its payload is processed") - # [IGNORE] The block's parent's execution payload passes validation + # [IGNORE] The block's parent passed validation but its execution payload is invalid if parent_payload_status == PAYLOAD_STATUS_INVALIDATED: - raise GossipIgnore("block's parent is valid and EL result is invalid") + raise GossipIgnore("block's parent is valid and its payload is invalid") # [REJECT] The block is from a higher slot than its parent if block.slot <= store.blocks[block.parent_root].slot: @@ -14264,13 +14371,13 @@ - name: validate_beacon_block_gossip#deneb sources: [] spec: | - + def validate_beacon_block_gossip( seen: Seen, store: Store, state: BeaconState, signed_beacon_block: SignedBeaconBlock, - current_time_ms: uint64, + current_time_ms: Uint64, block_payload_statuses: Dict[Root, PayloadValidationStatus], ) -> None: """ @@ -14322,15 +14429,15 @@ if block.parent_root not in store.block_states: if parent_payload_status == PAYLOAD_STATUS_NOT_VALIDATED: - # [REJECT] The block's parent passes validation - raise GossipReject("block's parent is invalid and EL result is unknown") + # [REJECT] The block's parent failed validation and its execution payload is optimistic + raise GossipReject("block's parent is invalid and its payload is optimistic") - # [IGNORE] The block's parent passes validation - raise GossipIgnore("block's parent is invalid and EL result is known") + # [IGNORE] The block's parent failed validation and its execution payload is processed + raise GossipIgnore("block's parent is invalid and its payload is processed") - # [IGNORE] The block's parent's execution payload passes validation + # [IGNORE] The block's parent passed validation but its execution payload is invalid if parent_payload_status == PAYLOAD_STATUS_INVALIDATED: - raise GossipIgnore("block's parent is valid and EL result is invalid") + raise GossipIgnore("block's parent is valid and its payload is invalid") # [REJECT] The block is from a higher slot than its parent if block.slot <= store.blocks[block.parent_root].slot: @@ -14363,13 +14470,13 @@ - name: validate_beacon_block_gossip#electra sources: [] spec: | - + def validate_beacon_block_gossip( seen: Seen, store: Store, state: BeaconState, signed_beacon_block: SignedBeaconBlock, - current_time_ms: uint64, + current_time_ms: Uint64, block_payload_statuses: Dict[Root, PayloadValidationStatus], ) -> None: """ @@ -14421,15 +14528,15 @@ if block.parent_root not in store.block_states: if parent_payload_status == PAYLOAD_STATUS_NOT_VALIDATED: - # [REJECT] The block's parent passes validation - raise GossipReject("block's parent is invalid and EL result is unknown") + # [REJECT] The block's parent failed validation and its execution payload is optimistic + raise GossipReject("block's parent is invalid and its payload is optimistic") - # [IGNORE] The block's parent passes validation - raise GossipIgnore("block's parent is invalid and EL result is known") + # [IGNORE] The block's parent failed validation and its execution payload is processed + raise GossipIgnore("block's parent is invalid and its payload is processed") - # [IGNORE] The block's parent's execution payload passes validation + # [IGNORE] The block's parent passed validation but its execution payload is invalid if parent_payload_status == PAYLOAD_STATUS_INVALIDATED: - raise GossipIgnore("block's parent is valid and EL result is invalid") + raise GossipIgnore("block's parent is valid and its payload is invalid") # [REJECT] The block is from a higher slot than its parent if block.slot <= store.blocks[block.parent_root].slot: @@ -14462,13 +14569,13 @@ - name: validate_beacon_block_gossip#fulu sources: [] spec: | - + def validate_beacon_block_gossip( seen: Seen, store: Store, state: BeaconState, signed_beacon_block: SignedBeaconBlock, - current_time_ms: uint64, + current_time_ms: Uint64, block_payload_statuses: Optional[Dict[Root, PayloadValidationStatus]] = None, ) -> None: """ @@ -14522,15 +14629,15 @@ if block.parent_root not in store.block_states: if parent_payload_status == PAYLOAD_STATUS_NOT_VALIDATED: - # [REJECT] The block's parent passes validation - raise GossipReject("block's parent is invalid and EL result is unknown") + # [REJECT] The block's parent failed validation and its execution payload is optimistic + raise GossipReject("block's parent is invalid and its payload is optimistic") - # [IGNORE] The block's parent passes validation - raise GossipIgnore("block's parent is invalid and EL result is known") + # [IGNORE] The block's parent failed validation and its execution payload is processed + raise GossipIgnore("block's parent is invalid and its payload is processed") - # [IGNORE] The block's parent's execution payload passes validation + # [IGNORE] The block's parent passed validation but its execution payload is invalid if parent_payload_status == PAYLOAD_STATUS_INVALIDATED: - raise GossipIgnore("block's parent is valid and EL result is invalid") + raise GossipIgnore("block's parent is valid and its payload is invalid") # [REJECT] The block is from a higher slot than its parent if block.slot <= store.blocks[block.parent_root].slot: @@ -14564,13 +14671,13 @@ - name: validate_blob_sidecar_gossip#deneb sources: [] spec: | - + def validate_blob_sidecar_gossip( seen: Seen, store: Store, state: BeaconState, blob_sidecar: BlobSidecar, - current_time_ms: uint64, + current_time_ms: Uint64, subnet_id: SubnetID, ) -> None: """ @@ -14633,7 +14740,7 @@ raise GossipReject("invalid blob sidecar inclusion proof") # [REJECT] The sidecar's blob is valid as verified by verify_blob_kzg_proof - if not verify_blob_kzg_proof( + if not kzg.verify_blob_kzg_proof( blob_sidecar.blob, blob_sidecar.kzg_commitment, blob_sidecar.kzg_proof ): raise GossipReject("invalid blob kzg proof") @@ -14659,13 +14766,13 @@ - name: validate_blob_sidecar_gossip#electra sources: [] spec: | - + def validate_blob_sidecar_gossip( seen: Seen, store: Store, state: BeaconState, blob_sidecar: BlobSidecar, - current_time_ms: uint64, + current_time_ms: Uint64, subnet_id: SubnetID, ) -> None: """ @@ -14729,7 +14836,7 @@ raise GossipReject("invalid blob sidecar inclusion proof") # [REJECT] The sidecar's blob is valid as verified by verify_blob_kzg_proof - if not verify_blob_kzg_proof( + if not kzg.verify_blob_kzg_proof( blob_sidecar.blob, blob_sidecar.kzg_commitment, blob_sidecar.kzg_proof ): raise GossipReject("invalid blob kzg proof") @@ -14755,12 +14862,12 @@ - name: validate_bls_to_execution_change_gossip#capella sources: [] spec: | - + def validate_bls_to_execution_change_gossip( seen: Seen, state: BeaconState, signed_bls_to_execution_change: SignedBLSToExecutionChange, - current_time_ms: uint64, + current_time_ms: Uint64, ) -> None: """ Validate a SignedBLSToExecutionChange for gossip propagation. @@ -14814,13 +14921,13 @@ - name: validate_data_column_sidecar_gossip#fulu sources: [] spec: | - + def validate_data_column_sidecar_gossip( seen: Seen, store: Store, state: BeaconState, sidecar: DataColumnSidecar, - current_time_ms: uint64, + current_time_ms: Uint64, subnet_id: SubnetID, ) -> None: """ @@ -15104,13 +15211,13 @@ - name: validate_partial_data_column_sidecar_gossip#fulu sources: [] spec: | - + def validate_partial_data_column_sidecar_gossip( seen: Seen, store: Store, state: BeaconState, sidecar: PartialDataColumnSidecar, - current_time_ms: uint64, + current_time_ms: Uint64, group_id: PartialDataColumnGroupID, column_index: ColumnIndex, ) -> None: @@ -15296,12 +15403,12 @@ - name: validate_sync_committee_contribution_and_proof_gossip#altair sources: [] spec: | - + def validate_sync_committee_contribution_and_proof_gossip( seen: Seen, state: BeaconState, signed_contribution_and_proof: SignedContributionAndProof, - current_time_ms: uint64, + current_time_ms: Uint64, ) -> None: """ Validate a SignedContributionAndProof for gossip propagation. @@ -15404,12 +15511,12 @@ - name: validate_sync_committee_message_gossip#altair sources: [] spec: | - + def validate_sync_committee_message_gossip( seen: Seen, state: BeaconState, sync_committee_message: SyncCommitteeMessage, - current_time_ms: uint64, + current_time_ms: Uint64, subnet_id: SubnetID, ) -> None: """ @@ -15699,7 +15806,7 @@ - file: beacon-chain/core/peerdas/p2p_interface.go search: func VerifyDataColumnsCellsKZGProofs( spec: | - + def verify_data_column_sidecar_kzg_proofs(sidecar: DataColumnSidecar) -> bool: """ Verify if the KZG proofs are correct. @@ -15708,7 +15815,7 @@ cell_indices = [CellIndex(sidecar.index)] * len(sidecar.column) # Batch verify that the cells match the corresponding commitments and proofs - return verify_cell_kzg_proof_batch( + return kzg.verify_cell_kzg_proof_batch( commitments_bytes=sidecar.kzg_commitments, cell_indices=cell_indices, cells=sidecar.column, @@ -15819,7 +15926,7 @@ - name: verify_partial_data_column_sidecar_kzg_proofs#fulu sources: [] spec: | - + def verify_partial_data_column_sidecar_kzg_proofs( sidecar: PartialDataColumnSidecar, all_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK], @@ -15835,7 +15942,7 @@ cell_indices = [CellIndex(column_index)] * len(blob_indices) # Batch verify that the cells match the corresponding commitments and proofs - return verify_cell_kzg_proof_batch( + return kzg.verify_cell_kzg_proof_batch( commitments_bytes=[all_commitments[i] for i in blob_indices], cell_indices=cell_indices, cells=sidecar.partial_column, @@ -15848,8 +15955,8 @@ - file: time/slots/slottime.go search: func VotingPeriodStartTime( spec: | - - def voting_period_start_time(state: BeaconState) -> uint64: + + def voting_period_start_time(state: BeaconState) -> Uint64: eth1_voting_period_start_slot = Slot( state.slot - state.slot % (EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH) ) diff --git a/specrefs/presets.yml b/specrefs/presets.yml index c29f90bbfefb..5a768246cd11 100644 --- a/specrefs/presets.yml +++ b/specrefs/presets.yml @@ -4,8 +4,8 @@ search: BaseRewardFactor\s+.*yaml:"BASE_REWARD_FACTOR" regex: true spec: | - - BASE_REWARD_FACTOR: uint64 = 64 + + BASE_REWARD_FACTOR: Uint64 = 64 - name: BYTES_PER_LOGS_BLOOM#bellatrix @@ -14,8 +14,8 @@ search: BytesPerLogsBloom\s+.*yaml:"BYTES_PER_LOGS_BLOOM" regex: true spec: | - - BYTES_PER_LOGS_BLOOM: uint64 = 256 + + BYTES_PER_LOGS_BLOOM: Uint64 = 256 - name: CELLS_PER_EXT_BLOB#fulu @@ -44,8 +44,8 @@ search: EpochsPerEth1VotingPeriod\s+.*yaml:"EPOCHS_PER_ETH1_VOTING_PERIOD" regex: true spec: | - - EPOCHS_PER_ETH1_VOTING_PERIOD: uint64 = 64 + + EPOCHS_PER_ETH1_VOTING_PERIOD: Epoch = 64 - name: EPOCHS_PER_HISTORICAL_VECTOR#phase0 @@ -54,8 +54,8 @@ search: RandaoMixesLength\s*= regex: true spec: | - - EPOCHS_PER_HISTORICAL_VECTOR: uint64 = 65536 + + EPOCHS_PER_HISTORICAL_VECTOR: Epoch = 65536 - name: EPOCHS_PER_SLASHINGS_VECTOR#phase0 @@ -64,8 +64,8 @@ search: SlashingsLength\s*= regex: true spec: | - - EPOCHS_PER_SLASHINGS_VECTOR: uint64 = 8192 + + EPOCHS_PER_SLASHINGS_VECTOR: Epoch = 8192 - name: EPOCHS_PER_SYNC_COMMITTEE_PERIOD#altair @@ -74,8 +74,8 @@ search: EpochsPerSyncCommitteePeriod\s+.*yaml:"EPOCHS_PER_SYNC_COMMITTEE_PERIOD" regex: true spec: | - - EPOCHS_PER_SYNC_COMMITTEE_PERIOD: uint64 = 256 + + EPOCHS_PER_SYNC_COMMITTEE_PERIOD: Epoch = 256 - name: FIELD_ELEMENTS_PER_BLOB#deneb @@ -84,8 +84,8 @@ search: FieldElementsPerBlob\s+.*yaml:"FIELD_ELEMENTS_PER_BLOB" regex: true spec: | - - FIELD_ELEMENTS_PER_BLOB: uint64 = 4096 + + FIELD_ELEMENTS_PER_BLOB: Uint64 = 4096 - name: FIELD_ELEMENTS_PER_CELL#fulu @@ -94,8 +94,8 @@ search: CellsPerBlob\s*= regex: true spec: | - - FIELD_ELEMENTS_PER_CELL: uint64 = 64 + + FIELD_ELEMENTS_PER_CELL: Uint64 = 64 - name: FIELD_ELEMENTS_PER_EXT_BLOB#fulu @@ -114,8 +114,8 @@ search: HistoricalRootsLength\s*= regex: true spec: | - - HISTORICAL_ROOTS_LIMIT: uint64 = 16777216 + + HISTORICAL_ROOTS_LIMIT: Uint64 = 16777216 - name: HYSTERESIS_DOWNWARD_MULTIPLIER#phase0 @@ -124,8 +124,8 @@ search: HysteresisDownwardMultiplier\s+.*yaml:"HYSTERESIS_DOWNWARD_MULTIPLIER" regex: true spec: | - - HYSTERESIS_DOWNWARD_MULTIPLIER: uint64 = 1 + + HYSTERESIS_DOWNWARD_MULTIPLIER: Uint64 = 1 - name: HYSTERESIS_QUOTIENT#phase0 @@ -134,8 +134,8 @@ search: HysteresisQuotient\s+.*yaml:"HYSTERESIS_QUOTIENT" regex: true spec: | - - HYSTERESIS_QUOTIENT: uint64 = 4 + + HYSTERESIS_QUOTIENT: Uint64 = 4 - name: HYSTERESIS_UPWARD_MULTIPLIER#phase0 @@ -144,8 +144,8 @@ search: HysteresisUpwardMultiplier\s+.*yaml:"HYSTERESIS_UPWARD_MULTIPLIER" regex: true spec: | - - HYSTERESIS_UPWARD_MULTIPLIER: uint64 = 5 + + HYSTERESIS_UPWARD_MULTIPLIER: Uint64 = 5 - name: INACTIVITY_PENALTY_QUOTIENT#phase0 @@ -154,8 +154,8 @@ search: InactivityPenaltyQuotient\s+.*yaml:"INACTIVITY_PENALTY_QUOTIENT" regex: true spec: | - - INACTIVITY_PENALTY_QUOTIENT: uint64 = 67108864 + + INACTIVITY_PENALTY_QUOTIENT: Uint64 = 67108864 - name: INACTIVITY_PENALTY_QUOTIENT_ALTAIR#altair @@ -164,8 +164,8 @@ search: InactivityPenaltyQuotientAltair\s+.*yaml:"INACTIVITY_PENALTY_QUOTIENT_ALTAIR" regex: true spec: | - - INACTIVITY_PENALTY_QUOTIENT_ALTAIR: uint64 = 50331648 + + INACTIVITY_PENALTY_QUOTIENT_ALTAIR: Uint64 = 50331648 - name: INACTIVITY_PENALTY_QUOTIENT_BELLATRIX#bellatrix @@ -174,15 +174,15 @@ search: InactivityPenaltyQuotientBellatrix\s+.*yaml:"INACTIVITY_PENALTY_QUOTIENT_BELLATRIX" regex: true spec: | - - INACTIVITY_PENALTY_QUOTIENT_BELLATRIX: uint64 = 16777216 + + INACTIVITY_PENALTY_QUOTIENT_BELLATRIX: Uint64 = 16777216 - name: INCLUSION_LIST_COMMITTEE_SIZE#heze sources: [] spec: | - - INCLUSION_LIST_COMMITTEE_SIZE: uint64 = 16 + + INCLUSION_LIST_COMMITTEE_SIZE: Uint64 = 16 - name: KZG_COMMITMENTS_INCLUSION_PROOF_DEPTH#fulu @@ -191,8 +191,8 @@ search: mainnet\s*=\s*\{[^}]*"kzg_commitments_inclusion_proof_depth\.size":.*[^}]*\} regex: true spec: | - - KZG_COMMITMENTS_INCLUSION_PROOF_DEPTH: uint64 = 4 + + KZG_COMMITMENTS_INCLUSION_PROOF_DEPTH: Uint64 = 4 - name: KZG_COMMITMENT_INCLUSION_PROOF_DEPTH#deneb @@ -201,8 +201,8 @@ search: KzgCommitmentInclusionProofDepth\s*= regex: true spec: | - - KZG_COMMITMENT_INCLUSION_PROOF_DEPTH: uint64 = 17 + + KZG_COMMITMENT_INCLUSION_PROOF_DEPTH: Uint64 = 17 - name: MAX_ATTESTATIONS#phase0 @@ -211,8 +211,8 @@ search: MaxAttestations\s+.*yaml:"MAX_ATTESTATIONS" regex: true spec: | - - MAX_ATTESTATIONS: uint64 = 128 + + MAX_ATTESTATIONS: Uint64 = 128 - name: MAX_ATTESTATIONS_ELECTRA#electra @@ -221,8 +221,8 @@ search: MaxAttestationsElectra\s+.*yaml:"MAX_ATTESTATIONS_ELECTRA" regex: true spec: | - - MAX_ATTESTATIONS_ELECTRA: uint64 = 8 + + MAX_ATTESTATIONS_ELECTRA: Uint64 = 8 - name: MAX_ATTESTER_SLASHINGS#phase0 @@ -231,8 +231,8 @@ search: MaxAttesterSlashings\s+.*yaml:"MAX_ATTESTER_SLASHINGS" regex: true spec: | - - MAX_ATTESTER_SLASHINGS: uint64 = 2 + + MAX_ATTESTER_SLASHINGS: Uint64 = 2 - name: MAX_ATTESTER_SLASHINGS_ELECTRA#electra @@ -241,15 +241,15 @@ search: MaxAttesterSlashingsElectra\s+.*yaml:"MAX_ATTESTER_SLASHINGS_ELECTRA" regex: true spec: | - - MAX_ATTESTER_SLASHINGS_ELECTRA: uint64 = 1 + + MAX_ATTESTER_SLASHINGS_ELECTRA: Uint64 = 1 - name: MAX_ATTESTER_SLASHING_SIZE#gloas sources: [] spec: | - - MAX_ATTESTER_SLASHING_SIZE: uint64 = 2097616 + + MAX_ATTESTER_SLASHING_SIZE: Uint64 = 2097616 - name: MAX_BLOB_COMMITMENTS_PER_BLOCK#deneb @@ -258,8 +258,8 @@ search: MaxBlobCommitmentsPerBlock\s*= regex: true spec: | - - MAX_BLOB_COMMITMENTS_PER_BLOCK: uint64 = 4096 + + MAX_BLOB_COMMITMENTS_PER_BLOCK: Uint64 = 4096 - name: MAX_BLS_TO_EXECUTION_CHANGES#capella @@ -268,29 +268,29 @@ search: MaxBlsToExecutionChanges\s+.*yaml:"MAX_BLS_TO_EXECUTION_CHANGES" regex: true spec: | - - MAX_BLS_TO_EXECUTION_CHANGES: uint64 = 16 + + MAX_BLS_TO_EXECUTION_CHANGES: Uint64 = 16 - name: MAX_BUILDERS_PER_WITHDRAWALS_SWEEP#gloas sources: [] spec: | - - MAX_BUILDERS_PER_WITHDRAWALS_SWEEP: uint64 = 16384 + + MAX_BUILDERS_PER_WITHDRAWALS_SWEEP: Uint64 = 16384 - name: MAX_BUILDER_DEPOSIT_REQUESTS_PER_PAYLOAD#gloas sources: [] spec: | - - MAX_BUILDER_DEPOSIT_REQUESTS_PER_PAYLOAD: uint64 = 64 + + MAX_BUILDER_DEPOSIT_REQUESTS_PER_PAYLOAD: Uint64 = 64 - name: MAX_BUILDER_EXIT_REQUESTS_PER_PAYLOAD#gloas sources: [] spec: | - - MAX_BUILDER_EXIT_REQUESTS_PER_PAYLOAD: uint64 = 16 + + MAX_BUILDER_EXIT_REQUESTS_PER_PAYLOAD: Uint64 = 16 - name: MAX_BYTES_PER_TRANSACTION#bellatrix @@ -299,8 +299,8 @@ search: MaxBytesPerTransaction\s+.*yaml:"MAX_BYTES_PER_TRANSACTION" regex: true spec: | - - MAX_BYTES_PER_TRANSACTION: uint64 = 1073741824 + + MAX_BYTES_PER_TRANSACTION: Uint64 = 1073741824 - name: MAX_COMMITTEES_PER_SLOT#phase0 @@ -309,8 +309,8 @@ search: MaxCommitteesPerSlot\s+.*yaml:"MAX_COMMITTEES_PER_SLOT" regex: true spec: | - - MAX_COMMITTEES_PER_SLOT: uint64 = 64 + + MAX_COMMITTEES_PER_SLOT: Uint64 = 64 - name: MAX_COMMITTEES_PER_SLOT#electra @@ -319,8 +319,8 @@ search: MaxCommitteesPerSlot\s+.*yaml:"MAX_COMMITTEES_PER_SLOT" regex: true spec: | - - MAX_COMMITTEES_PER_SLOT: uint64 = 64 + + MAX_COMMITTEES_PER_SLOT: Uint64 = 64 - name: MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD#electra @@ -329,15 +329,15 @@ search: MaxConsolidationsRequestsPerPayload\s+.*yaml:"MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD" regex: true spec: | - - MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD: uint64 = 2 + + MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD: Uint64 = 2 - name: MAX_DATA_COLUMN_SIDECAR_SIZE#gloas sources: [] spec: | - - MAX_DATA_COLUMN_SIDECAR_SIZE: uint64 = 8585272 + + MAX_DATA_COLUMN_SIDECAR_SIZE: Uint64 = 8585272 - name: MAX_DEPOSITS#phase0 @@ -346,8 +346,8 @@ search: MaxDeposits\s+.*yaml:"MAX_DEPOSITS" regex: true spec: | - - MAX_DEPOSITS: uint64 = 16 + + MAX_DEPOSITS: Uint64 = 16 - name: MAX_DEPOSIT_REQUESTS_PER_PAYLOAD#electra @@ -356,8 +356,8 @@ search: MaxDepositRequestsPerPayload\s+.*yaml:"MAX_DEPOSIT_REQUESTS_PER_PAYLOAD" regex: true spec: | - - MAX_DEPOSIT_REQUESTS_PER_PAYLOAD: uint64 = 8192 + + MAX_DEPOSIT_REQUESTS_PER_PAYLOAD: Uint64 = 8192 - name: MAX_EFFECTIVE_BALANCE#phase0 @@ -386,22 +386,22 @@ search: MaxExtraDataBytes\s+.*yaml:"MAX_EXTRA_DATA_BYTES" regex: true spec: | - - MAX_EXTRA_DATA_BYTES: uint64 = 32 + + MAX_EXTRA_DATA_BYTES: Uint64 = 32 - name: MAX_PARTIAL_DATA_COLUMN_SIDECAR_SIZE#gloas sources: [] spec: | - - MAX_PARTIAL_DATA_COLUMN_SIDECAR_SIZE: uint64 = 8585741 + + MAX_PARTIAL_DATA_COLUMN_SIDECAR_SIZE: Uint64 = 8585741 - name: MAX_PAYLOAD_ATTESTATIONS#gloas sources: [] spec: | - - MAX_PAYLOAD_ATTESTATIONS: uint64 = 4 + + MAX_PAYLOAD_ATTESTATIONS: Uint64 = 4 - name: MAX_PENDING_DEPOSITS_PER_EPOCH#electra @@ -410,8 +410,8 @@ search: MaxPendingDepositsPerEpoch\s+.*yaml:"MAX_PENDING_DEPOSITS_PER_EPOCH" regex: true spec: | - - MAX_PENDING_DEPOSITS_PER_EPOCH: uint64 = 16 + + MAX_PENDING_DEPOSITS_PER_EPOCH: Uint64 = 16 - name: MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP#electra @@ -420,8 +420,8 @@ search: MaxPendingPartialsPerWithdrawalsSweep\s+.*yaml:"MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP" regex: true spec: | - - MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP: uint64 = 8 + + MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP: Uint64 = 8 - name: MAX_PROPOSER_SLASHINGS#phase0 @@ -430,8 +430,8 @@ search: MaxProposerSlashings\s+.*yaml:"MAX_PROPOSER_SLASHINGS" regex: true spec: | - - MAX_PROPOSER_SLASHINGS: uint64 = 16 + + MAX_PROPOSER_SLASHINGS: Uint64 = 16 - name: MAX_SEED_LOOKAHEAD#phase0 @@ -440,36 +440,36 @@ search: MaxSeedLookahead\s+.*yaml:"MAX_SEED_LOOKAHEAD" regex: true spec: | - - MAX_SEED_LOOKAHEAD: uint64 = 4 + + MAX_SEED_LOOKAHEAD: Epoch = 4 - name: MAX_SIGNED_AGGREGATE_AND_PROOF_SIZE#gloas sources: [] spec: | - - MAX_SIGNED_AGGREGATE_AND_PROOF_SIZE: uint64 = 16829 + + MAX_SIGNED_AGGREGATE_AND_PROOF_SIZE: Uint64 = 16829 - name: MAX_SIGNED_EXECUTION_PAYLOAD_BID_SIZE#gloas sources: [] spec: | - - MAX_SIGNED_EXECUTION_PAYLOAD_BID_SIZE: uint64 = 196932 + + MAX_SIGNED_EXECUTION_PAYLOAD_BID_SIZE: Uint64 = 196932 - name: MAX_SIGNED_EXECUTION_PAYLOAD_BID_SIZE_HEZE#heze sources: [] spec: | - - MAX_SIGNED_EXECUTION_PAYLOAD_BID_SIZE_HEZE: uint64 = 196934 + + MAX_SIGNED_EXECUTION_PAYLOAD_BID_SIZE_HEZE: Uint64 = 196934 - name: MAX_SIGNED_INCLUSION_LIST_SIZE#heze sources: [] spec: | - - MAX_SIGNED_INCLUSION_LIST_SIZE: uint64 = 8348 + + MAX_SIGNED_INCLUSION_LIST_SIZE: Uint64 = 8348 - name: MAX_TRANSACTIONS_PER_PAYLOAD#bellatrix @@ -478,8 +478,8 @@ search: MaxTransactionsPerPayload\s+.*yaml:"MAX_TRANSACTIONS_PER_PAYLOAD" regex: true spec: | - - MAX_TRANSACTIONS_PER_PAYLOAD: uint64 = 1048576 + + MAX_TRANSACTIONS_PER_PAYLOAD: Uint64 = 1048576 - name: MAX_VALIDATORS_PER_COMMITTEE#phase0 @@ -488,8 +488,8 @@ search: MaxValidatorsPerCommittee\s+.*yaml:"MAX_VALIDATORS_PER_COMMITTEE" regex: true spec: | - - MAX_VALIDATORS_PER_COMMITTEE: uint64 = 2048 + + MAX_VALIDATORS_PER_COMMITTEE: Uint64 = 2048 - name: MAX_VALIDATORS_PER_COMMITTEE#electra @@ -498,8 +498,8 @@ search: MaxValidatorsPerCommittee\s+.*yaml:"MAX_VALIDATORS_PER_COMMITTEE" regex: true spec: | - - MAX_VALIDATORS_PER_COMMITTEE: uint64 = 2048 + + MAX_VALIDATORS_PER_COMMITTEE: Uint64 = 2048 - name: MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP#capella @@ -508,8 +508,8 @@ search: MaxValidatorsPerWithdrawalsSweep\s+.*yaml:"MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP" regex: true spec: | - - MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP: uint64 = 16384 + + MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP: Uint64 = 16384 - name: MAX_VOLUNTARY_EXITS#phase0 @@ -518,8 +518,8 @@ search: MaxVoluntaryExits\s+.*yaml:"MAX_VOLUNTARY_EXITS" regex: true spec: | - - MAX_VOLUNTARY_EXITS: uint64 = 16 + + MAX_VOLUNTARY_EXITS: Uint64 = 16 - name: MAX_WITHDRAWALS_PER_PAYLOAD#capella @@ -528,8 +528,8 @@ search: MaxWithdrawalsPerPayload\s*= regex: true spec: | - - MAX_WITHDRAWALS_PER_PAYLOAD: uint64 = 16 + + MAX_WITHDRAWALS_PER_PAYLOAD: Uint64 = 16 - name: MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD#electra @@ -538,8 +538,8 @@ search: MaxWithdrawalRequestsPerPayload\s+.*yaml:"MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD" regex: true spec: | - - MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD: uint64 = 16 + + MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD: Uint64 = 16 - name: MIN_ACTIVATION_BALANCE#electra @@ -558,8 +558,8 @@ search: MinAttestationInclusionDelay\s+.*yaml:"MIN_ATTESTATION_INCLUSION_DELAY" regex: true spec: | - - MIN_ATTESTATION_INCLUSION_DELAY: uint64 = 1 + + MIN_ATTESTATION_INCLUSION_DELAY: Slot = 1 - name: MIN_DEPOSIT_AMOUNT#phase0 @@ -578,8 +578,8 @@ search: MinEpochsToInactivityPenalty\s+.*yaml:"MIN_EPOCHS_TO_INACTIVITY_PENALTY" regex: true spec: | - - MIN_EPOCHS_TO_INACTIVITY_PENALTY: uint64 = 4 + + MIN_EPOCHS_TO_INACTIVITY_PENALTY: Epoch = 4 - name: MIN_SEED_LOOKAHEAD#phase0 @@ -588,8 +588,8 @@ search: MinSeedLookahead\s+.*yaml:"MIN_SEED_LOOKAHEAD" regex: true spec: | - - MIN_SEED_LOOKAHEAD: uint64 = 1 + + MIN_SEED_LOOKAHEAD: Epoch = 1 - name: MIN_SLASHING_PENALTY_QUOTIENT#phase0 @@ -598,8 +598,8 @@ search: MinSlashingPenaltyQuotient\s+.*yaml:"MIN_SLASHING_PENALTY_QUOTIENT" regex: true spec: | - - MIN_SLASHING_PENALTY_QUOTIENT: uint64 = 128 + + MIN_SLASHING_PENALTY_QUOTIENT: Uint64 = 128 - name: MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR#altair @@ -608,8 +608,8 @@ search: MinSlashingPenaltyQuotientAltair\s+.*yaml:"MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR" regex: true spec: | - - MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR: uint64 = 64 + + MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR: Uint64 = 64 - name: MIN_SLASHING_PENALTY_QUOTIENT_BELLATRIX#bellatrix @@ -618,8 +618,8 @@ search: MinSlashingPenaltyQuotientBellatrix\s+.*yaml:"MIN_SLASHING_PENALTY_QUOTIENT_BELLATRIX" regex: true spec: | - - MIN_SLASHING_PENALTY_QUOTIENT_BELLATRIX: uint64 = 32 + + MIN_SLASHING_PENALTY_QUOTIENT_BELLATRIX: Uint64 = 32 - name: MIN_SLASHING_PENALTY_QUOTIENT_ELECTRA#electra @@ -628,8 +628,8 @@ search: MinSlashingPenaltyQuotientElectra\s+.*yaml:"MIN_SLASHING_PENALTY_QUOTIENT_ELECTRA" regex: true spec: | - - MIN_SLASHING_PENALTY_QUOTIENT_ELECTRA: uint64 = 4096 + + MIN_SLASHING_PENALTY_QUOTIENT_ELECTRA: Uint64 = 4096 - name: MIN_SYNC_COMMITTEE_PARTICIPANTS#altair @@ -638,8 +638,8 @@ search: MinSyncCommitteeParticipants\s+.*yaml:"MIN_SYNC_COMMITTEE_PARTICIPANTS" regex: true spec: | - - MIN_SYNC_COMMITTEE_PARTICIPANTS = 1 + + MIN_SYNC_COMMITTEE_PARTICIPANTS: Uint64 = 1 - name: NUMBER_OF_COLUMNS#fulu @@ -648,8 +648,8 @@ search: NumberOfColumns\s*= regex: true spec: | - - NUMBER_OF_COLUMNS = 128 + + NUMBER_OF_COLUMNS: Uint64 = 128 - name: PENDING_CONSOLIDATIONS_LIMIT#electra @@ -658,8 +658,8 @@ search: PendingConsolidationsLimit\s*= regex: true spec: | - - PENDING_CONSOLIDATIONS_LIMIT: uint64 = 262144 + + PENDING_CONSOLIDATIONS_LIMIT: Uint64 = 262144 - name: PENDING_DEPOSITS_LIMIT#electra @@ -668,8 +668,8 @@ search: PendingDepositsLimit\s*= regex: true spec: | - - PENDING_DEPOSITS_LIMIT: uint64 = 134217728 + + PENDING_DEPOSITS_LIMIT: Uint64 = 134217728 - name: PENDING_PARTIAL_WITHDRAWALS_LIMIT#electra @@ -678,8 +678,8 @@ search: PendingPartialWithdrawalsLimit\s*= regex: true spec: | - - PENDING_PARTIAL_WITHDRAWALS_LIMIT: uint64 = 134217728 + + PENDING_PARTIAL_WITHDRAWALS_LIMIT: Uint64 = 134217728 - name: PROPORTIONAL_SLASHING_MULTIPLIER#phase0 @@ -688,8 +688,8 @@ search: ProportionalSlashingMultiplier\s+.*yaml:"PROPORTIONAL_SLASHING_MULTIPLIER" regex: true spec: | - - PROPORTIONAL_SLASHING_MULTIPLIER: uint64 = 1 + + PROPORTIONAL_SLASHING_MULTIPLIER: Uint64 = 1 - name: PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR#altair @@ -698,8 +698,8 @@ search: ProportionalSlashingMultiplierAltair\s+.*yaml:"PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR" regex: true spec: | - - PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR: uint64 = 2 + + PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR: Uint64 = 2 - name: PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX#bellatrix @@ -708,8 +708,8 @@ search: ProportionalSlashingMultiplierBellatrix\s+.*yaml:"PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX" regex: true spec: | - - PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX: uint64 = 3 + + PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX: Uint64 = 3 - name: PROPOSER_REWARD_QUOTIENT#phase0 @@ -718,15 +718,15 @@ search: ProposerRewardQuotient\s+.*yaml:"PROPOSER_REWARD_QUOTIENT" regex: true spec: | - - PROPOSER_REWARD_QUOTIENT: uint64 = 8 + + PROPOSER_REWARD_QUOTIENT: Uint64 = 8 - name: PTC_SIZE#gloas sources: [] spec: | - - PTC_SIZE: uint64 = 512 + + PTC_SIZE: Uint64 = 512 - name: SHUFFLE_ROUND_COUNT#phase0 @@ -735,8 +735,8 @@ search: ShuffleRoundCount\s+.*yaml:"SHUFFLE_ROUND_COUNT" regex: true spec: | - - SHUFFLE_ROUND_COUNT: uint64 = 90 + + SHUFFLE_ROUND_COUNT: Uint64 = 90 - name: SLOTS_PER_EPOCH#phase0 @@ -745,8 +745,8 @@ search: SlotsPerEpoch\s*= regex: true spec: | - - SLOTS_PER_EPOCH: uint64 = 32 + + SLOTS_PER_EPOCH: Slot = 32 - name: SLOTS_PER_HISTORICAL_ROOT#phase0 @@ -755,8 +755,8 @@ search: BlockRootsLength\s*= regex: true spec: | - - SLOTS_PER_HISTORICAL_ROOT: uint64 = 8192 + + SLOTS_PER_HISTORICAL_ROOT: Slot = 8192 - name: SYNC_COMMITTEE_SIZE#altair @@ -765,8 +765,8 @@ search: SyncCommitteeLength\s*= regex: true spec: | - - SYNC_COMMITTEE_SIZE: uint64 = 512 + + SYNC_COMMITTEE_SIZE: Uint64 = 512 - name: TARGET_COMMITTEE_SIZE#phase0 @@ -775,8 +775,8 @@ search: TargetCommitteeSize\s+.*yaml:"TARGET_COMMITTEE_SIZE" regex: true spec: | - - TARGET_COMMITTEE_SIZE: uint64 = 128 + + TARGET_COMMITTEE_SIZE: Uint64 = 128 - name: UPDATE_TIMEOUT#altair @@ -785,8 +785,8 @@ search: data\["UPDATE_TIMEOUT"\] regex: true spec: | - - UPDATE_TIMEOUT = 8192 + + UPDATE_TIMEOUT: Slot = 8192 - name: VALIDATOR_REGISTRY_LIMIT#phase0 @@ -795,8 +795,8 @@ search: ValidatorRegistryLimit\s*= regex: true spec: | - - VALIDATOR_REGISTRY_LIMIT: uint64 = 1099511627776 + + VALIDATOR_REGISTRY_LIMIT: Uint64 = 1099511627776 - name: WHISTLEBLOWER_REWARD_QUOTIENT#phase0 @@ -805,8 +805,8 @@ search: WhistleBlowerRewardQuotient\s+.*yaml:"WHISTLEBLOWER_REWARD_QUOTIENT" regex: true spec: | - - WHISTLEBLOWER_REWARD_QUOTIENT: uint64 = 512 + + WHISTLEBLOWER_REWARD_QUOTIENT: Uint64 = 512 - name: WHISTLEBLOWER_REWARD_QUOTIENT_ELECTRA#electra @@ -815,6 +815,6 @@ search: WhistleBlowerRewardQuotientElectra\s+.*yaml:"WHISTLEBLOWER_REWARD_QUOTIENT_ELECTRA" regex: true spec: | - - WHISTLEBLOWER_REWARD_QUOTIENT_ELECTRA: uint64 = 4096 + + WHISTLEBLOWER_REWARD_QUOTIENT_ELECTRA: Uint64 = 4096 From 898faf49f071fa89ae6085eb1f9c2190e3f9b763 Mon Sep 17 00:00:00 2001 From: terence Date: Fri, 7 Aug 2026 12:50:00 -0700 Subject: [PATCH 17/23] Enable equivocation tracking by default --- .../forkchoice/doubly-linked-tree/BUILD.bazel | 1 + .../forkchoice/doubly-linked-tree/forkchoice.go | 4 +++- .../doubly-linked-tree/forkchoice_test.go | 3 +++ config/features/config.go | 8 ++++---- config/features/deprecated_flags.go | 6 ++++++ config/features/flags.go | 8 ++++---- .../spectest/shared/common/forkchoice/builder.go | 14 ++++++++++++++ 7 files changed, 35 insertions(+), 9 deletions(-) diff --git a/beacon-chain/forkchoice/doubly-linked-tree/BUILD.bazel b/beacon-chain/forkchoice/doubly-linked-tree/BUILD.bazel index 333fdfb1c433..0a001e143cb2 100644 --- a/beacon-chain/forkchoice/doubly-linked-tree/BUILD.bazel +++ b/beacon-chain/forkchoice/doubly-linked-tree/BUILD.bazel @@ -70,6 +70,7 @@ go_test( "//beacon-chain/forkchoice/types:go_default_library", "//beacon-chain/state:go_default_library", "//beacon-chain/state/state-native:go_default_library", + "//config/features:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//consensus-types/blocks:go_default_library", diff --git a/beacon-chain/forkchoice/doubly-linked-tree/forkchoice.go b/beacon-chain/forkchoice/doubly-linked-tree/forkchoice.go index b4608f1c8ed9..18a82a8e6357 100644 --- a/beacon-chain/forkchoice/doubly-linked-tree/forkchoice.go +++ b/beacon-chain/forkchoice/doubly-linked-tree/forkchoice.go @@ -138,7 +138,9 @@ func (f *ForkChoice) InsertNode(ctx context.Context, state state.BeaconState, ro if err != nil { return err } - f.RecordBlockForEquivocation(roblock.Block().Slot(), roblock.Block().ProposerIndex(), roblock.Root()) + if features.Get().TrackEquivocations { + f.RecordBlockForEquivocation(roblock.Block().Slot(), roblock.Block().ProposerIndex(), roblock.Root()) + } jc, fc = f.store.pullTips(state, pn.node, jc, fc) if err := f.updateCheckpoints(ctx, jc, fc); err != nil { _, remErr := f.store.removeNode(ctx, pn) diff --git a/beacon-chain/forkchoice/doubly-linked-tree/forkchoice_test.go b/beacon-chain/forkchoice/doubly-linked-tree/forkchoice_test.go index 8a8d3c3cfd18..a7809bb886a4 100644 --- a/beacon-chain/forkchoice/doubly-linked-tree/forkchoice_test.go +++ b/beacon-chain/forkchoice/doubly-linked-tree/forkchoice_test.go @@ -9,6 +9,7 @@ import ( forkchoicetypes "github.com/OffchainLabs/prysm/v7/beacon-chain/forkchoice/types" "github.com/OffchainLabs/prysm/v7/beacon-chain/state" state_native "github.com/OffchainLabs/prysm/v7/beacon-chain/state/state-native" + "github.com/OffchainLabs/prysm/v7/config/features" "github.com/OffchainLabs/prysm/v7/config/params" "github.com/OffchainLabs/prysm/v7/consensus-types/blocks" "github.com/OffchainLabs/prysm/v7/consensus-types/primitives" @@ -430,6 +431,8 @@ func TestForkChoice_RecordBlockForEquivocation_DedupesRoot(t *testing.T) { } func TestForkChoice_InsertNode_RecordsFirstSeen(t *testing.T) { + resetFn := features.InitWithReset(&features.Flags{TrackEquivocations: true}) + defer resetFn() f := setup(0, 0) blockRoot := indexToHash(1) st, roblock, err := prepareForkchoiceState(t.Context(), 1, blockRoot, params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 0, 0) diff --git a/config/features/config.go b/config/features/config.go index 8415d2e5b119..70382796a0d7 100644 --- a/config/features/config.go +++ b/config/features/config.go @@ -291,10 +291,10 @@ func ConfigureBeaconChain(ctx *cli.Context) error { logEnabled(ignoreUnviableAttestations) cfg.IgnoreUnviableAttestations = true } - cfg.TrackEquivocations = false - if ctx.IsSet(trackEquivocations.Name) && ctx.Bool(trackEquivocations.Name) { - logEnabled(trackEquivocations) - cfg.TrackEquivocations = true + cfg.TrackEquivocations = true + if ctx.IsSet(disableTrackEquivocations.Name) && ctx.Bool(disableTrackEquivocations.Name) { + logDisabled(disableTrackEquivocations) + cfg.TrackEquivocations = false } if ctx.IsSet(EnableStateDiff.Name) { logEnabled(EnableStateDiff) diff --git a/config/features/deprecated_flags.go b/config/features/deprecated_flags.go index 9399ca2b8dc2..5a0f0a4122fc 100644 --- a/config/features/deprecated_flags.go +++ b/config/features/deprecated_flags.go @@ -60,6 +60,11 @@ var ( Usage: deprecatedUsage, Hidden: true, } + deprecatedTrackEquivocations = &cli.BoolFlag{ + Name: "track-equivocations", + Usage: deprecatedUsage, + Hidden: true, + } ) // Deprecated flags for both the beacon node and validator client. @@ -72,6 +77,7 @@ var deprecatedFlags = []cli.Flag{ deprecatedInteropStartIndex, deprecatedInteropEth1DataVotes, deprecatedInteropWriteSSZStateTransitions, + deprecatedTrackEquivocations, } var upcomingDeprecation = []cli.Flag{ diff --git a/config/features/flags.go b/config/features/flags.go index 25788cf1eb3d..e4cb2279e246 100644 --- a/config/features/flags.go +++ b/config/features/flags.go @@ -228,9 +228,9 @@ var ( Name: "ignore-unviable-attestations", Usage: "Ignores attestations whose target state is not viable with respect to the current head (avoid expensive state replay from lagging attesters).", } - trackEquivocations = &cli.BoolFlag{ - Name: "track-equivocations", - Usage: "Records proposer equivocations observed on gossip and marks the slot in forkchoice if the equivocation arrives before the configured early deadline.", + disableTrackEquivocations = &cli.BoolFlag{ + Name: "disable-track-equivocations", + Usage: "Disables recording proposer equivocations observed on gossip into forkchoice.", } ) @@ -277,7 +277,7 @@ var BeaconChainFlags = combinedFlags([]cli.Flag{ SaveFullExecutionPayloads, enableStartupOptimistic, ignoreUnviableAttestations, - trackEquivocations, + disableTrackEquivocations, enableFullSSZDataLogging, disableVerboseSigVerification, enableProposerPreprocessing, diff --git a/testing/spectest/shared/common/forkchoice/builder.go b/testing/spectest/shared/common/forkchoice/builder.go index 3445650f653a..660d2c21746a 100644 --- a/testing/spectest/shared/common/forkchoice/builder.go +++ b/testing/spectest/shared/common/forkchoice/builder.go @@ -119,6 +119,20 @@ func (bb *Builder) ValidBlock(t testing.TB, b interfaces.ReadOnlySignedBeaconBlo ctx, cancel := context.WithTimeout(t.Context(), 3*time.Second) defer cancel() require.NoError(t, bb.service.ReceiveBlock(ctx, b, r, nil)) + bb.recordIfEarly(b, r) +} + +func (bb *Builder) recordIfEarly(b interfaces.ReadOnlySignedBeaconBlock, root [32]byte) { + cfg := params.BeaconConfig() + slot := b.Block().Slot() + if uint64(bb.lastTick)/cfg.SecondsPerSlot != uint64(slot) { + return + } + slotStart := int64(uint64(slot) * cfg.SecondsPerSlot) + if time.Duration(bb.lastTick-slotStart)*time.Second >= cfg.SlotComponentDuration(cfg.EquivocationEarlyDueBPS) { + return + } + bb.service.RecordBlockForEquivocation(slot, b.Block().ProposerIndex(), root) } // ExecutionPayloadEnvelope receives an envelope and notifies the chain service. From 13a5b3d85173ec9a58ef19575d6415d7d784b9be Mon Sep 17 00:00:00 2001 From: terence Date: Fri, 7 Aug 2026 15:37:13 -0700 Subject: [PATCH 18/23] Source KZG spec test vectors from ethereum/cryptography-specs --- WORKSPACE | 17 ++ build/bazel/testdata_fetch.go | 9 +- build/bazel/testdata_fetch_test.go | 1 + build/externaldata/bazelsource.go | 9 +- build/externaldata/externaldata.go | 147 +++++++++++++----- testing/spectest/general/BUILD.bazel | 2 +- ...__kzg__verify_blob_kzg_proof_batch_test.go | 4 +- ..._kzg__compute_cells_and_kzg_proofs_test.go | 4 +- .../general/fulu__kzg__compute_cells_test.go | 4 +- ..._kzg__recover_cells_and_kzg_proofs_test.go | 4 +- ...__kzg__verify_cell_kzg_proof_batch_test.go | 4 +- 11 files changed, 150 insertions(+), 55 deletions(-) diff --git a/WORKSPACE b/WORKSPACE index fd899e8078f6..8af0d42a66aa 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -312,6 +312,23 @@ filegroup( url = "https://github.com/ethereum/consensus-specs/archive/refs/tags/%s.tar.gz" % consensus_spec_version, ) +cryptography_spec_tests_version = "v0.1.0" + +http_archive( + name = "cryptography_spec_tests", + build_file_content = """ +filegroup( + name = "test_data", + srcs = glob([ + "**/*.yaml", + ]), + visibility = ["//visibility:public"], +) + """, + integrity = "sha256-7rSJPrVE93CBDZSZAH67C5MZQx6kEr1Uc24cJ02j0Dc=", + url = "https://github.com/ethereum/cryptography-specs/releases/download/%s/tests.zip" % cryptography_spec_tests_version, +) + bls_test_version = "v0.1.1" http_archive( diff --git a/build/bazel/testdata_fetch.go b/build/bazel/testdata_fetch.go index 74621923cc72..df881956966a 100644 --- a/build/bazel/testdata_fetch.go +++ b/build/bazel/testdata_fetch.go @@ -35,9 +35,9 @@ func archiveForPath(path string) (string, bool) { switch first { case "tests": - // Consensus spec tests: tests/{general,minimal,mainnet}/... + // Spec tests: tests/{general,minimal,mainnet,kzg}/... category, _, _ := strings.Cut(rest, "/") - if name, ok := consensusSpecTestArchives[category]; ok { + if name, ok := specTestArchives[category]; ok { return name, true } return "", false @@ -60,11 +60,12 @@ func archiveForPath(path string) (string, bool) { return "", false } -// consensusSpecTestArchives maps a consensus-spec test category. -var consensusSpecTestArchives = map[string]string{ +// specTestArchives maps a top-level spec test category to its archive. +var specTestArchives = map[string]string{ "general": externaldata.ConsensusSpecTestsGeneral, "minimal": externaldata.ConsensusSpecTestsMinimal, "mainnet": externaldata.ConsensusSpecTestsMainnet, + "kzg": externaldata.CryptographySpecTests, } // blsCategories are the top-level directories the bls12-381 test archive unpacks diff --git a/build/bazel/testdata_fetch_test.go b/build/bazel/testdata_fetch_test.go index fca9cf7b6a42..b0cdadf80d2c 100644 --- a/build/bazel/testdata_fetch_test.go +++ b/build/bazel/testdata_fetch_test.go @@ -23,6 +23,7 @@ func TestArchiveForPath(t *testing.T) { {"consensus general", "tests/general/phase0/foo.ssz", externaldata.ConsensusSpecTestsGeneral, true}, {"consensus minimal", "tests/minimal/altair/bar.yaml", externaldata.ConsensusSpecTestsMinimal, true}, {"consensus mainnet", "tests/mainnet/capella/baz.yaml", externaldata.ConsensusSpecTestsMainnet, true}, + {"cryptography kzg", "tests/kzg/compute_cells", externaldata.CryptographySpecTests, true}, {"consensus unknown category", "tests/devnet/foo.yaml", "", false}, {"consensus bare", "tests", "", false}, {"external repo", "external/my_repo/file.txt", "my_repo", true}, diff --git a/build/externaldata/bazelsource.go b/build/externaldata/bazelsource.go index 8b101862c131..b44c8afa3098 100644 --- a/build/externaldata/bazelsource.go +++ b/build/externaldata/bazelsource.go @@ -18,9 +18,12 @@ var ( workspaceContent = sync.OnceValue(func() string { return readBazelFile(workspaceFile) }) e2eDepsContent = sync.OnceValue(func() string { return readBazelFile(e2eDepsFile) }) - consensusSpecVersion = sync.OnceValue(func() string { return bazelVar(workspaceContent(), workspaceFile, "consensus_spec_version") }) - blsVersion = sync.OnceValue(func() string { return bazelVar(workspaceContent(), workspaceFile, "bls_test_version") }) - lighthouseVersion = sync.OnceValue(func() string { return bazelVar(e2eDepsContent(), e2eDepsFile, "lighthouse_version") }) + consensusSpecVersion = sync.OnceValue(func() string { return bazelVar(workspaceContent(), workspaceFile, "consensus_spec_version") }) + cryptographySpecTestsVersion = sync.OnceValue(func() string { + return bazelVar(workspaceContent(), workspaceFile, "cryptography_spec_tests_version") + }) + blsVersion = sync.OnceValue(func() string { return bazelVar(workspaceContent(), workspaceFile, "bls_test_version") }) + lighthouseVersion = sync.OnceValue(func() string { return bazelVar(e2eDepsContent(), e2eDepsFile, "lighthouse_version") }) ) // readBazelFile reads a Bazel build file relative to the module root. diff --git a/build/externaldata/externaldata.go b/build/externaldata/externaldata.go index ce23adfe0768..4bb37a2a188f 100644 --- a/build/externaldata/externaldata.go +++ b/build/externaldata/externaldata.go @@ -2,6 +2,7 @@ package externaldata import ( "archive/tar" + "archive/zip" "bytes" "compress/gzip" "crypto/sha256" @@ -33,6 +34,7 @@ const ( ConsensusSpecTestsMinimal = "consensus_spec_tests_minimal" ConsensusSpecTestsMainnet = "consensus_spec_tests_mainnet" ConsensusSpec = "consensus_spec" + CryptographySpecTests = "cryptography_spec_tests" Mainnet = "mainnet" HoleskyTestnet = "holesky_testnet" SepoliaTestnet = "sepolia_testnet" @@ -70,6 +72,7 @@ func buildManifest() []archive { {HoleskyTestnet, archiveURL(workspaceContent(), workspaceFile, HoleskyTestnet), archiveHash(workspaceContent(), workspaceFile, HoleskyTestnet), "external/holesky_testnet", 1, ""}, {SepoliaTestnet, archiveURL(workspaceContent(), workspaceFile, SepoliaTestnet), archiveHash(workspaceContent(), workspaceFile, SepoliaTestnet), "external/sepolia_testnet", 1, ""}, {HoodiTestnet, archiveURL(workspaceContent(), workspaceFile, HoodiTestnet), archiveHash(workspaceContent(), workspaceFile, HoodiTestnet), "external/hoodi_testnet", 1, ""}, + {CryptographySpecTests, "https://github.com/ethereum/cryptography-specs/releases/download/" + cryptographySpecTestsVersion() + "/tests.zip", archiveHash(workspaceContent(), workspaceFile, CryptographySpecTests), ".", 0, ""}, {BLSSpecTests, "https://github.com/ethereum/bls12-381-tests/releases/download/" + blsVersion() + "/bls_tests_yaml.tar.gz", archiveHash(workspaceContent(), workspaceFile, BLSSpecTests), ".", 0, ""}, {EIP3076SpecTests, archiveURL(workspaceContent(), workspaceFile, EIP3076SpecTests), archiveHash(workspaceContent(), workspaceFile, EIP3076SpecTests), "external/eip3076_spec_tests", 1, ""}, {EIP4881SpecTests, archiveURL(workspaceContent(), workspaceFile, EIP4881SpecTests), archiveHash(workspaceContent(), workspaceFile, EIP4881SpecTests), "external/eip4881_spec_tests", 1, "*/assets/eip-4881/*"}, @@ -354,15 +357,23 @@ func download(url string) ([]byte, error) { return nil, lastErr } -// extract unpacks a gzip'd tar into target, stripping `strip` leading path -// components and, if include != "", only entries whose (pre-strip) name matches -// that glob. -func extract(targz []byte, target string, strip int, include string) error { +// extract unpacks a gzip'd tar or a zip into target, stripping `strip` leading +// path components and, if include != "", only entries whose (pre-strip) name +// matches that glob. +func extract(data []byte, target string, strip int, include string) error { var includeRe *regexp.Regexp if include != "" { includeRe = globToRegexp(include) } + if bytes.HasPrefix(data, []byte("PK\x03\x04")) { + return extractZip(data, target, strip, includeRe) + } + + return extractTarGz(data, target, strip, includeRe) +} + +func extractTarGz(targz []byte, target string, strip int, includeRe *regexp.Regexp) error { gz, err := gzip.NewReader(bytes.NewReader(targz)) if err != nil { return fmt.Errorf("gzip new reader: %w", err) @@ -380,49 +391,22 @@ func extract(targz []byte, target string, strip int, include string) error { return fmt.Errorf("tar next: %w", err) } - if includeRe != nil && !includeRe.MatchString(hdr.Name) { - continue + dst, ok, err := entryDest(target, hdr.Name, strip, includeRe) + if err != nil { + return err } - - rel := stripComponents(hdr.Name, strip) - if rel == "" { + if !ok { continue } - cleanTarget := filepath.Clean(target) - dst := filepath.Join(cleanTarget, filepath.FromSlash(rel)) - if dst == cleanTarget { - continue - } - - if !strings.HasPrefix(dst, cleanTarget+string(os.PathSeparator)) { - return fmt.Errorf("externaldata: unsafe path %q in archive", hdr.Name) - } - switch hdr.Typeflag { case tar.TypeDir: if err := os.MkdirAll(dst, 0o750); err != nil { return fmt.Errorf("mkdir all: %w", err) } case tar.TypeReg: - if err := os.MkdirAll(filepath.Dir(dst), 0o750); err != nil { - return fmt.Errorf("mkdir all: %w", err) - } - - // #nosec G304 -- dst is verified above to stay within the target dir (HasPrefix check) - f, err := os.OpenFile(dst, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, os.FileMode(hdr.Mode)&0o777|0o600) - if err != nil { - return fmt.Errorf("open file: %w", err) - } - - // #nosec G110 -- archive bytes are sha256-verified against a pinned hash before extraction - if _, err := io.Copy(f, tr); err != nil { - _ = f.Close() - return fmt.Errorf("copy file: %w", err) - } - - if err := f.Close(); err != nil { - return fmt.Errorf("close file: %w", err) + if err := writeEntry(dst, tr, os.FileMode(hdr.Mode)); err != nil { + return err } case tar.TypeSymlink: @@ -437,6 +421,95 @@ func extract(targz []byte, target string, strip int, include string) error { return nil } +func extractZip(data []byte, target string, strip int, includeRe *regexp.Regexp) error { + zr, err := zip.NewReader(bytes.NewReader(data), int64(len(data))) + if err != nil { + return fmt.Errorf("zip new reader: %w", err) + } + + for _, f := range zr.File { + dst, ok, err := entryDest(target, f.Name, strip, includeRe) + if err != nil { + return err + } + if !ok { + continue + } + + if f.FileInfo().IsDir() { + if err := os.MkdirAll(dst, 0o750); err != nil { + return fmt.Errorf("mkdir all: %w", err) + } + continue + } + + rc, err := f.Open() + if err != nil { + return fmt.Errorf("open zip entry: %w", err) + } + + if err := writeEntry(dst, rc, f.Mode()); err != nil { + _ = rc.Close() + return err + } + + if err := rc.Close(); err != nil { + return fmt.Errorf("close zip entry: %w", err) + } + } + + return nil +} + +// entryDest resolves an archive entry to its destination path, reporting ok=false +// when the entry is filtered out or stripped away entirely. +func entryDest(target, name string, strip int, includeRe *regexp.Regexp) (string, bool, error) { + if includeRe != nil && !includeRe.MatchString(name) { + return "", false, nil + } + + rel := stripComponents(name, strip) + if rel == "" { + return "", false, nil + } + + cleanTarget := filepath.Clean(target) + dst := filepath.Join(cleanTarget, filepath.FromSlash(rel)) + if dst == cleanTarget { + return "", false, nil + } + + if !strings.HasPrefix(dst, cleanTarget+string(os.PathSeparator)) { + return "", false, fmt.Errorf("externaldata: unsafe path %q in archive", name) + } + + return dst, true, nil +} + +func writeEntry(dst string, r io.Reader, mode os.FileMode) error { + if err := os.MkdirAll(filepath.Dir(dst), 0o750); err != nil { + return fmt.Errorf("mkdir all: %w", err) + } + + // #nosec G304 -- dst is verified by entryDest to stay within the target dir + f, err := os.OpenFile(dst, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, mode&0o777|0o600) + if err != nil { + return fmt.Errorf("open file: %w", err) + } + + // #nosec G110 -- archive bytes are sha256-verified against a pinned hash before extraction + if _, err := io.Copy(f, r); err != nil { + _ = f.Close() + return fmt.Errorf("copy file: %w", err) + } + + if err := f.Close(); err != nil { + return fmt.Errorf("close file: %w", err) + } + + return nil +} + func stripComponents(name string, n int) string { parts := strings.Split(strings.TrimPrefix(name, "./"), "/") if len(parts) <= n { diff --git a/testing/spectest/general/BUILD.bazel b/testing/spectest/general/BUILD.bazel index 37106d8075b4..e4ab9aba2707 100644 --- a/testing/spectest/general/BUILD.bazel +++ b/testing/spectest/general/BUILD.bazel @@ -9,7 +9,7 @@ go_test( "fulu__kzg__recover_cells_and_kzg_proofs_test.go", "fulu__kzg__verify_cell_kzg_proof_batch_test.go", ], - data = ["@consensus_spec_tests//:test_data"], + data = ["@cryptography_spec_tests//:test_data"], tags = ["spectest"], deps = [ "//beacon-chain/blockchain/kzg:go_default_library", diff --git a/testing/spectest/general/deneb__kzg__verify_blob_kzg_proof_batch_test.go b/testing/spectest/general/deneb__kzg__verify_blob_kzg_proof_batch_test.go index a1a556881306..bb67d49e5f70 100644 --- a/testing/spectest/general/deneb__kzg__verify_blob_kzg_proof_batch_test.go +++ b/testing/spectest/general/deneb__kzg__verify_blob_kzg_proof_batch_test.go @@ -27,9 +27,9 @@ type KZGTestData struct { func TestVerifyBlobKZGProofBatch(t *testing.T) { require.NoError(t, kzgPrysm.Start()) - testFolders, testFolderPath := utils.TestFolders(t, "general", "deneb", "kzg/verify_blob_kzg_proof_batch/kzg-mainnet") + testFolders, testFolderPath := utils.TestFolders(t, "kzg", "verify_blob_kzg_proof_batch", "") if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", "general", "deneb", "kzg/verify_blob_kzg_proof_batch/kzg-mainnet") + t.Fatalf("No test folders found for kzg/verify_blob_kzg_proof_batch") } for _, folder := range testFolders { t.Run(folder.Name(), func(t *testing.T) { diff --git a/testing/spectest/general/fulu__kzg__compute_cells_and_kzg_proofs_test.go b/testing/spectest/general/fulu__kzg__compute_cells_and_kzg_proofs_test.go index 1cc1927706dd..53c0fd8a9470 100644 --- a/testing/spectest/general/fulu__kzg__compute_cells_and_kzg_proofs_test.go +++ b/testing/spectest/general/fulu__kzg__compute_cells_and_kzg_proofs_test.go @@ -23,9 +23,9 @@ func TestComputeCellsAndKzgProofs(t *testing.T) { Output [][]string `json:"output"` } require.NoError(t, kzgPrysm.Start()) - testFolders, testFolderPath := utils.TestFolders(t, "general", "fulu", "kzg/compute_cells_and_kzg_proofs/kzg-mainnet") + testFolders, testFolderPath := utils.TestFolders(t, "kzg", "compute_cells_and_kzg_proofs", "") if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", "general", "fulu", "kzg/compute_cells_and_kzg_proofs/kzg-mainnet") + t.Fatalf("No test folders found for kzg/compute_cells_and_kzg_proofs") } for _, folder := range testFolders { t.Run(folder.Name(), func(t *testing.T) { diff --git a/testing/spectest/general/fulu__kzg__compute_cells_test.go b/testing/spectest/general/fulu__kzg__compute_cells_test.go index 2a6a58fe3236..b6c0f64e08e5 100644 --- a/testing/spectest/general/fulu__kzg__compute_cells_test.go +++ b/testing/spectest/general/fulu__kzg__compute_cells_test.go @@ -24,9 +24,9 @@ func TestComputeCells(t *testing.T) { } require.NoError(t, kzgPrysm.Start()) - testFolders, testFolderPath := utils.TestFolders(t, "general", "fulu", "kzg/compute_cells/kzg-mainnet") + testFolders, testFolderPath := utils.TestFolders(t, "kzg", "compute_cells", "") if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", "general", "fulu", "kzg/compute_cells/kzg-mainnet") + t.Fatalf("No test folders found for kzg/compute_cells") } for _, folder := range testFolders { t.Run(folder.Name(), func(t *testing.T) { diff --git a/testing/spectest/general/fulu__kzg__recover_cells_and_kzg_proofs_test.go b/testing/spectest/general/fulu__kzg__recover_cells_and_kzg_proofs_test.go index 4d5da8ba15cc..9fe7a792094b 100644 --- a/testing/spectest/general/fulu__kzg__recover_cells_and_kzg_proofs_test.go +++ b/testing/spectest/general/fulu__kzg__recover_cells_and_kzg_proofs_test.go @@ -24,9 +24,9 @@ func TestRecoverCellsAndKzgProofs(t *testing.T) { Output [][]string `json:"output"` } require.NoError(t, kzgPrysm.Start()) - testFolders, testFolderPath := utils.TestFolders(t, "general", "fulu", "kzg/recover_cells_and_kzg_proofs/kzg-mainnet") + testFolders, testFolderPath := utils.TestFolders(t, "kzg", "recover_cells_and_kzg_proofs", "") if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", "general", "fulu", "kzg/recover_cells_and_kzg_proofs/kzg-mainnet") + t.Fatalf("No test folders found for kzg/recover_cells_and_kzg_proofs") } for _, folder := range testFolders { t.Run(folder.Name(), func(t *testing.T) { diff --git a/testing/spectest/general/fulu__kzg__verify_cell_kzg_proof_batch_test.go b/testing/spectest/general/fulu__kzg__verify_cell_kzg_proof_batch_test.go index e6362e937545..92b372ae238f 100644 --- a/testing/spectest/general/fulu__kzg__verify_cell_kzg_proof_batch_test.go +++ b/testing/spectest/general/fulu__kzg__verify_cell_kzg_proof_batch_test.go @@ -26,9 +26,9 @@ func TestVerifyCellKZGProofBatch(t *testing.T) { Output bool `json:"output"` } require.NoError(t, kzgPrysm.Start()) - testFolders, testFolderPath := utils.TestFolders(t, "general", "fulu", "kzg/verify_cell_kzg_proof_batch/kzg-mainnet") + testFolders, testFolderPath := utils.TestFolders(t, "kzg", "verify_cell_kzg_proof_batch", "") if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", "general", "fulu", "kzg/verify_cell_kzg_proof_batch/kzg-mainnet") + t.Fatalf("No test folders found for kzg/verify_cell_kzg_proof_batch") } for _, folder := range testFolders { t.Run(folder.Name(), func(t *testing.T) { From b058ebea68cc4cdaa3c8ecef135f942dddc9bc11 Mon Sep 17 00:00:00 2001 From: terence Date: Wed, 19 Aug 2026 08:43:08 -0700 Subject: [PATCH 19/23] Explicitly set bid fields when upgrading to Gloas --- beacon-chain/core/gloas/upgrade.go | 14 +++++++++----- beacon-chain/core/gloas/upgrade_test.go | 13 +++++++++---- changelog/terence_gloas-fork-bid-fields.md | 3 +++ 3 files changed, 21 insertions(+), 9 deletions(-) create mode 100644 changelog/terence_gloas-fork-bid-fields.md diff --git a/beacon-chain/core/gloas/upgrade.go b/beacon-chain/core/gloas/upgrade.go index 3c292fd093af..89f5d3536255 100644 --- a/beacon-chain/core/gloas/upgrade.go +++ b/beacon-chain/core/gloas/upgrade.go @@ -280,6 +280,8 @@ func upgradeToGloas(beaconState state.BeaconState) (state.BeaconState, error) { return nil, errors.Wrap(err, "could not compute empty execution requests root") } + latestBlockHeader := beaconState.LatestBlockHeader() + s := ðpb.BeaconStateGloas{ GenesisTime: uint64(beaconState.GenesisTime().Unix()), GenesisValidatorsRoot: beaconState.GenesisValidatorsRoot(), @@ -289,7 +291,7 @@ func upgradeToGloas(beaconState state.BeaconState) (state.BeaconState, error) { CurrentVersion: params.BeaconConfig().GloasForkVersion, Epoch: time.CurrentEpoch(beaconState), }, - LatestBlockHeader: beaconState.LatestBlockHeader(), + LatestBlockHeader: latestBlockHeader, BlockRoots: beaconState.BlockRoots(), StateRoots: beaconState.StateRoots(), HistoricalRoots: beaconState.HistoricalRoots(), @@ -310,12 +312,14 @@ func upgradeToGloas(beaconState state.BeaconState) (state.BeaconState, error) { CurrentSyncCommittee: currentSyncCommittee, NextSyncCommittee: nextSyncCommittee, LatestExecutionPayloadBid: ðpb.ExecutionPayloadBid{ + ParentBlockHash: payloadHeader.ParentHash(), + ParentBlockRoot: latestBlockHeader.ParentRoot, BlockHash: payloadHeader.BlockHash(), - GasLimit: payloadHeader.GasLimit(), + PrevRandao: payloadHeader.PrevRandao(), FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), - ParentBlockHash: make([]byte, fieldparams.RootLength), - ParentBlockRoot: make([]byte, fieldparams.RootLength), - PrevRandao: make([]byte, fieldparams.RootLength), + GasLimit: payloadHeader.GasLimit(), + BuilderIndex: params.BeaconConfig().BuilderIndexSelfBuild, + Slot: latestBlockHeader.Slot, ExecutionRequestsRoot: emptyExecutionRequestsRoot[:], }, NextWithdrawalIndex: wi, diff --git a/beacon-chain/core/gloas/upgrade_test.go b/beacon-chain/core/gloas/upgrade_test.go index 193d41f9b102..9dfd70982ef1 100644 --- a/beacon-chain/core/gloas/upgrade_test.go +++ b/beacon-chain/core/gloas/upgrade_test.go @@ -12,6 +12,7 @@ import ( consensusblocks "github.com/OffchainLabs/prysm/v7/consensus-types/blocks" "github.com/OffchainLabs/prysm/v7/consensus-types/primitives" "github.com/OffchainLabs/prysm/v7/crypto/bls" + "github.com/OffchainLabs/prysm/v7/encoding/bytesutil" enginev1 "github.com/OffchainLabs/prysm/v7/proto/engine/v1" ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1" "github.com/OffchainLabs/prysm/v7/testing/require" @@ -35,7 +36,9 @@ func TestUpgradeToGloas_Basic(t *testing.T) { require.NoError(t, st.SetPendingConsolidations([]*ethpb.PendingConsolidation{{SourceIndex: 3, TargetIndex: 4}})) blockHash := bytes.Repeat([]byte{0xAB}, 32) - header := &enginev1.ExecutionPayloadHeaderDeneb{BlockHash: blockHash} + parentHash := bytes.Repeat([]byte{0xCD}, 32) + prevRandao := bytes.Repeat([]byte{0xEF}, 32) + header := &enginev1.ExecutionPayloadHeaderDeneb{BlockHash: blockHash, ParentHash: parentHash, PrevRandao: prevRandao} wrappedHeader, err := consensusblocks.WrappedExecutionPayloadHeaderDeneb(header) require.NoError(t, err) require.NoError(t, st.SetLatestExecutionPayloadHeader(wrappedHeader)) @@ -60,9 +63,11 @@ func TestUpgradeToGloas_Basic(t *testing.T) { copy(wantBlockHash[:], blockHash) require.DeepSSZEqual(t, wantBlockHash, bid.BlockHash()) require.DeepSSZEqual(t, [20]byte{}, bid.FeeRecipient()) - require.DeepSSZEqual(t, [32]byte{}, bid.ParentBlockHash()) - require.DeepSSZEqual(t, [32]byte{}, bid.ParentBlockRoot()) - require.DeepSSZEqual(t, [32]byte{}, bid.PrevRandao()) + require.DeepSSZEqual(t, bytesutil.ToBytes32(parentHash), bid.ParentBlockHash()) + require.DeepSSZEqual(t, bytesutil.ToBytes32(preForkState.LatestBlockHeader().ParentRoot), bid.ParentBlockRoot()) + require.DeepSSZEqual(t, bytesutil.ToBytes32(prevRandao), bid.PrevRandao()) + require.Equal(t, params.BeaconConfig().BuilderIndexSelfBuild, bid.BuilderIndex()) + require.Equal(t, preForkState.LatestBlockHeader().Slot, bid.Slot()) latestBlockHash, err := mSt.LatestBlockHash() require.NoError(t, err) diff --git a/changelog/terence_gloas-fork-bid-fields.md b/changelog/terence_gloas-fork-bid-fields.md new file mode 100644 index 000000000000..aea729dc4ccd --- /dev/null +++ b/changelog/terence_gloas-fork-bid-fields.md @@ -0,0 +1,3 @@ +### Changed + +- Explicitly set execution payload bid fields when upgrading to Gloas per consensus-specs#5553. From 33e610aa8429e7bc3cd73336b016951c90726092 Mon Sep 17 00:00:00 2001 From: terence Date: Wed, 19 Aug 2026 13:14:51 -0700 Subject: [PATCH 20/23] Bump consensus spec to v1.7.0-alpha.14 --- .ethspecify.yml | 153 +- WORKSPACE | 10 +- .../core/gloas/payload_attestation.go | 16 +- beacon-chain/core/gloas/pending_payment.go | 4 +- beacon-chain/core/gloas/upgrade.go | 54 +- .../state/state-native/getters_gloas.go | 20 +- .../state/state-native/setters_gloas.go | 4 +- .../verification/execution_payload_bid.go | 8 +- changelog/terence_alpha14.md | 3 + specrefs/configs.yml | 15 +- specrefs/containers.yml | 1882 +++++++++++--- specrefs/dataclasses.yml | 190 +- specrefs/functions.yml | 2244 ++++++++++++----- 13 files changed, 3554 insertions(+), 1049 deletions(-) create mode 100644 changelog/terence_alpha14.md diff --git a/.ethspecify.yml b/.ethspecify.yml index bf925c4d517d..d0205f6b196a 100644 --- a/.ethspecify.yml +++ b/.ethspecify.yml @@ -1,4 +1,4 @@ -version: v1.7.0-alpha.13 +version: v1.7.0-alpha.14 style: full specrefs: @@ -81,10 +81,11 @@ exceptions: - HEZE_FORK_EPOCH#heze - HEZE_FORK_VERSION#heze - INCLUSION_LIST_DUE_BPS#heze - - MAX_BYTES_PER_INCLUSION_LIST#heze + - MAX_TRANSACTIONS_BYTES_PER_INCLUSION_LIST#heze - MAX_REQUEST_INCLUSION_LIST#heze - MIN_SLOTS_FOR_INCLUSION_LISTS_REQUESTS#heze + - GAS_LIMIT_SCHEDULE#gloas ssz_objects: # phase0 - Eth1Block#phase0 @@ -134,6 +135,128 @@ exceptions: - BuilderDepositRequest#gloas - BuilderExitRequest#gloas - ExecutionRequests#gloas + - AggregationBits#electra + - AggregationBits#gloas + - AggregationBits#phase0 + - Attestations#electra + - Attestations#gloas + - Attestations#phase0 + - AttesterSlashings#electra + - AttesterSlashings#gloas + - AttesterSlashings#phase0 + - AttestingIndices#electra + - AttestingIndices#gloas + - AttestingIndices#phase0 + - Attnets#phase0 + - BLSToExecutionChanges#capella + - BLSToExecutionChanges#gloas + - Balances#gloas + - Balances#phase0 + - BeaconBlockRoots#deneb + - BeaconBlockRoots#phase0 + - Blob#deneb + - BlobKZGCommitments#deneb + - BlobKZGCommitments#gloas + - Blobs#deneb + - BlockAccessList#gloas + - BlockRoots#phase0 + - BuilderDepositRequests#gloas + - BuilderExitRequests#gloas + - BuilderPendingPayments#gloas + - BuilderPendingWithdrawals#gloas + - Builders#gloas + - Cell#fulu + - CellKZGProofs#fulu + - Cells#fulu + - CellsBitList#fulu + - CellsBitList#gloas + - CommitteeBits#electra + - ConsolidationRequests#electra + - ConsolidationRequests#gloas + - CurrentSyncCommitteeBranch#altair + - CurrentSyncCommitteeBranch#electra + - CurrentSyncCommitteeBranch#gloas + - CustodyColumnBits#gloas + - DataColumn#fulu + - DataColumn#gloas + - DataColumnIndices#fulu + - DataColumnsByRootIdentifiers#fulu + - DepositDataList#phase0 + - DepositProof#phase0 + - DepositRequests#electra + - DepositRequests#gloas + - Deposits#gloas + - Deposits#phase0 + - EpochParticipation#altair + - EpochParticipation#gloas + - ErrorMessage#phase0 + - Eth1DataVotes#phase0 + - ExecutionBranch#capella + - ExecutionBranch#gloas + - ExecutionPayloadAvailability#gloas + - ExecutionPayloadEnvelopeRoots#gloas + - ExtraData#bellatrix + - FinalityBranch#altair + - FinalityBranch#electra + - FinalityBranch#gloas + - HistoricalRoots#phase0 + - HistoricalSummaries#capella + - InactivityScores#altair + - InactivityScores#gloas + - InclusionListBits#heze + - InclusionListCommittee#heze + - JustificationBits#phase0 + - KZGCommitmentInclusionProof#deneb + - KZGCommitmentsInclusionProof#fulu + - KZGProofs#deneb + - KZGProofs#gloas + - LightClientUpdates#altair + - LogsBloom#bellatrix + - NextSyncCommitteeBranch#altair + - NextSyncCommitteeBranch#electra + - NextSyncCommitteeBranch#gloas + - OptionalPartialDataColumnHeader#fulu + - PTC#gloas + - PTCAttestingIndices#gloas + - PTCBits#gloas + - PTCWindow#gloas + - PartialDataColumnPartsMetadata#gloas + - PayloadAttestations#gloas + - PendingAttestations#phase0 + - PendingConsolidations#electra + - PendingConsolidations#gloas + - PendingDeposits#electra + - PendingDeposits#gloas + - PendingPartialWithdrawals#electra + - PendingPartialWithdrawals#gloas + - Proofs#fulu + - ProposerIndices#fulu + - ProposerLookahead#fulu + - ProposerSlashings#gloas + - ProposerSlashings#phase0 + - RandaoMixes#phase0 + - SignedBeaconBlocks#deneb + - SignedBeaconBlocks#phase0 + - SignedExecutionPayloadEnvelopes#gloas + - SignedInclusionLists#heze + - Slashings#phase0 + - StateRoots#phase0 + - SyncCommitteeBits#altair + - SyncCommitteePubkeys#altair + - SyncSubcommitteeBits#altair + - Syncnets#altair + - Transaction#bellatrix + - Transaction#gloas + - Transactions#bellatrix + - Transactions#gloas + - Validators#gloas + - Validators#phase0 + - VoluntaryExits#gloas + - VoluntaryExits#phase0 + - WithdrawalRequests#electra + - WithdrawalRequests#gloas + - Withdrawals#capella + - Withdrawals#gloas dataclasses: # phase0 - FastConfirmationStore#phase0 @@ -171,6 +294,7 @@ exceptions: - PayloadAttributes#heze - Store#heze + - InclusionListEntry#heze functions: # phase0 - adjust_committee_weight_estimate_to_ensure_safety#phase0 @@ -214,7 +338,6 @@ exceptions: - compute_attestation_subnet_prefix_bits#phase0 - compute_min_epochs_for_block_requests#phase0 - compute_time_at_slot_ms#phase0 - - is_not_from_future_slot#phase0 - is_within_slot_range#phase0 - update_proposer_boost_root#phase0 - is_proposer_equivocation#phase0 @@ -486,7 +609,6 @@ exceptions: - is_head_late#gloas - is_head_weak#gloas - is_parent_strong#gloas - - is_valid_proposal_slot#gloas - onboard_builders_from_pending_deposits#gloas - process_deposit_request#gloas - record_block_timeliness#gloas @@ -544,7 +666,28 @@ exceptions: - process_builder_deposit_request#gloas - process_builder_exit_request#gloas # phase0 - - is_not_epoch_boundary#phase0 + - compute_shuffling_dependent_slot#phase0 + - get_custody_column_bits#gloas + - get_proposer_head#fulu + - get_scheduled_gas_limit#gloas + - get_set_bit_count#phase0 + - get_signed_inclusion_list#heze + - is_current_or_next_slot#gloas + - is_future_slot#phase0 + - is_past_slot#gloas + - is_shuffling_stable#phase0 + - validate_beacon_aggregate_and_proof_gossip#gloas + - validate_beacon_attestation_gossip#gloas + - validate_beacon_block_gossip#gloas + - validate_data_column_sidecar_gossip#gloas + - validate_execution_payload_bid_gossip#gloas + - validate_execution_payload_envelope_gossip#gloas + - validate_partial_data_column_sidecar_gossip#gloas + - validate_payload_attestation_message_gossip#gloas + - validate_proposer_preferences_gossip#gloas + - verify_attestation_payload_status#gloas + - verify_block_body_operation_limits#gloas + - verify_execution_requests_limits#gloas presets: # gloas - MAX_ATTESTER_SLASHING_SIZE#gloas diff --git a/WORKSPACE b/WORKSPACE index 8af0d42a66aa..1e602877267b 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -282,16 +282,16 @@ filegroup( url = "https://github.com/ethereum/EIPs/archive/5480440fe51742ed23342b68cf106cefd427e39d.tar.gz", ) -consensus_spec_version = "v1.7.0-alpha.13" +consensus_spec_version = "v1.7.0-alpha.14" load("@prysm//tools:download_spectests.bzl", "consensus_spec_tests") consensus_spec_tests( name = "consensus_spec_tests", flavors = { - "general": "sha256-uY5TKAN6hJkyVAhXALjZ6uMEvsqB0JRP4FJ0yjUj7Ys=", - "minimal": "sha256-lLr9c1FDhWRUBAB+bsi0eu0TykQ7jnViH0D85c4fR6I=", - "mainnet": "sha256-v2lwbJzCxCPju661rn61Op5a3974TjcxKWu2Rv4ugUk=", + "general": "sha256-xPOV9x9gbCgJNQDjIGeZDkMMxzoid75vO/UJCtzOP2c=", + "minimal": "sha256-LKQtMBStfkASQA5CjVEiAx6ROHO6v+0xxew6pd5x88g=", + "mainnet": "sha256-+YvTL01ohnaRuRC6HGLj1V3U6LalenhbPf2Sl7+YAPc=", }, version = consensus_spec_version, ) @@ -307,7 +307,7 @@ filegroup( visibility = ["//visibility:public"], ) """, - integrity = "sha256-2MTTrtDbvXqXOuZbxgIijr4v6X/2dLAoD/0Rb59SMYk=", + integrity = "sha256-us/WKo/xoYSNg7c9uv6MVYEYmGLc9v03c2XM3XXt6Gk=", strip_prefix = "consensus-specs-" + consensus_spec_version[1:], url = "https://github.com/ethereum/consensus-specs/archive/refs/tags/%s.tar.gz" % consensus_spec_version, ) diff --git a/beacon-chain/core/gloas/payload_attestation.go b/beacon-chain/core/gloas/payload_attestation.go index 38585bc49995..3a035d56ac04 100644 --- a/beacon-chain/core/gloas/payload_attestation.go +++ b/beacon-chain/core/gloas/payload_attestation.go @@ -109,21 +109,23 @@ func indexedPayloadAttestation(ctx context.Context, st state.ReadOnlyBeaconState // computePTC computes the payload timeliness committee for a given slot. // -// -// def compute_ptc(state: BeaconState, slot: Slot) -> Vector[ValidatorIndex, PTC_SIZE]: +// +// def compute_ptc(state: BeaconState, slot: Slot) -> PTC: // """ // Get the payload timeliness committee, with possible duplicates, for the given ``slot``. // """ // epoch = compute_epoch_at_slot(slot) // seed = hash(get_seed(state, epoch, DOMAIN_PTC_ATTESTER) + uint_to_bytes(slot)) -// indices: List[ValidatorIndex] = [] +// indices: list[ValidatorIndex] = [] // # Concatenate all committees for this slot in order // committees_per_slot = get_committee_count_per_slot(state, epoch) // for i in range(committees_per_slot): // committee = get_beacon_committee(state, slot, CommitteeIndex(i)) // indices.extend(committee) -// return compute_balance_weighted_selection( -// state, indices, seed, size=PTC_SIZE, shuffle_indices=False +// return PTC( +// compute_balance_weighted_selection( +// state, indices, seed, size=PTC_SIZE, shuffle_indices=False +// ) // ) // func computePTC(ctx context.Context, st state.ReadOnlyBeaconState, slot primitives.Slot) ([]primitives.ValidatorIndex, error) { @@ -219,7 +221,7 @@ func ptcSeed(st state.ReadOnlyBeaconState, epoch primitives.Epoch, slot primitiv // selectByBalance selects a balance-weighted subset of input candidates. // -// +// // def compute_balance_weighted_selection( // state: BeaconState, // indices: Sequence[ValidatorIndex], @@ -237,7 +239,7 @@ func ptcSeed(st state.ReadOnlyBeaconState, epoch primitives.Epoch, slot primitiv // total = Uint64(len(indices)) // assert total > 0 // effective_balances = [state.validators[index].effective_balance for index in indices] -// selected: List[ValidatorIndex] = [] +// selected: list[ValidatorIndex] = [] // i = Uint64(0) // while len(selected) < size: // offset = i % 16 * 2 diff --git a/beacon-chain/core/gloas/pending_payment.go b/beacon-chain/core/gloas/pending_payment.go index 98e1b2a08853..26084cb47488 100644 --- a/beacon-chain/core/gloas/pending_payment.go +++ b/beacon-chain/core/gloas/pending_payment.go @@ -13,7 +13,7 @@ import ( // ProcessBuilderPendingPayments processes the builder pending payments from the previous epoch. // -// +// // def process_builder_pending_payments(state: BeaconState) -> None: // """ // Processes the builder pending payments from the previous epoch. @@ -25,7 +25,7 @@ import ( // // old_payments = state.builder_pending_payments[SLOTS_PER_EPOCH:] // new_payments = [BuilderPendingPayment() for _ in range(SLOTS_PER_EPOCH)] -// state.builder_pending_payments = old_payments + new_payments +// state.builder_pending_payments = BuilderPendingPayments(old_payments + new_payments) // func ProcessBuilderPendingPayments(ctx context.Context, state state.BeaconState) error { quorum, err := builderQuorumThreshold(ctx, state) diff --git a/beacon-chain/core/gloas/upgrade.go b/beacon-chain/core/gloas/upgrade.go index 89f5d3536255..763635747639 100644 --- a/beacon-chain/core/gloas/upgrade.go +++ b/beacon-chain/core/gloas/upgrade.go @@ -17,7 +17,7 @@ import ( // UpgradeToGloas updates inputs a generic state to return the version Gloas state. // -// +// // def upgrade_to_gloas(pre: fulu.BeaconState) -> BeaconState: // epoch = fulu.get_current_epoch(pre) // @@ -39,25 +39,21 @@ import ( // eth1_data_votes=pre.eth1_data_votes, // eth1_deposit_index=pre.eth1_deposit_index, // # [Modified in Gloas:EIP7688] -// validators=ProgressiveList[Validator](list(pre.validators)), +// validators=Validators(list(pre.validators)), // # [Modified in Gloas:EIP7688] -// balances=ProgressiveList[Gwei](list(pre.balances)), +// balances=Balances(list(pre.balances)), // randao_mixes=pre.randao_mixes, // slashings=pre.slashings, // # [Modified in Gloas:EIP7688] -// previous_epoch_participation=ProgressiveList[ParticipationFlags]( -// list(pre.previous_epoch_participation) -// ), +// previous_epoch_participation=EpochParticipation(list(pre.previous_epoch_participation)), // # [Modified in Gloas:EIP7688] -// current_epoch_participation=ProgressiveList[ParticipationFlags]( -// list(pre.current_epoch_participation) -// ), +// current_epoch_participation=EpochParticipation(list(pre.current_epoch_participation)), // justification_bits=pre.justification_bits, // previous_justified_checkpoint=pre.previous_justified_checkpoint, // current_justified_checkpoint=pre.current_justified_checkpoint, // finalized_checkpoint=pre.finalized_checkpoint, // # [Modified in Gloas:EIP7688] -// inactivity_scores=ProgressiveList[Uint64](list(pre.inactivity_scores)), +// inactivity_scores=InactivityScores(list(pre.inactivity_scores)), // current_sync_committee=pre.current_sync_committee, // next_sync_committee=pre.next_sync_committee, // # [Modified in Gloas:EIP7732] @@ -74,34 +70,43 @@ import ( // consolidation_balance_to_consume=pre.consolidation_balance_to_consume, // earliest_consolidation_epoch=pre.earliest_consolidation_epoch, // # [Modified in Gloas:EIP7688] -// pending_deposits=ProgressiveList[PendingDeposit](list(pre.pending_deposits)), +// pending_deposits=PendingDeposits(list(pre.pending_deposits)), // # [Modified in Gloas:EIP7688] -// pending_partial_withdrawals=ProgressiveList[PendingPartialWithdrawal]( +// pending_partial_withdrawals=PendingPartialWithdrawals( // list(pre.pending_partial_withdrawals) // ), // # [Modified in Gloas:EIP7688] -// pending_consolidations=ProgressiveList[PendingConsolidation]( -// list(pre.pending_consolidations) -// ), +// pending_consolidations=PendingConsolidations(list(pre.pending_consolidations)), // proposer_lookahead=pre.proposer_lookahead, // # [New in Gloas:EIP7732] -// builders=[], +// builders=Builders(), // # [New in Gloas:EIP7732] // next_withdrawal_builder_index=BuilderIndex(0), // # [New in Gloas:EIP7732] -// execution_payload_availability=[0b1 for _ in range(SLOTS_PER_HISTORICAL_ROOT)], +// execution_payload_availability=ExecutionPayloadAvailability([ +// 0b1 for _ in range(SLOTS_PER_HISTORICAL_ROOT) +// ]), // # [New in Gloas:EIP7732] -// builder_pending_payments=[BuilderPendingPayment() for _ in range(2 * SLOTS_PER_EPOCH)], +// builder_pending_payments=BuilderPendingPayments(), // # [New in Gloas:EIP7732] -// builder_pending_withdrawals=[], +// builder_pending_withdrawals=BuilderPendingWithdrawals(), // # [New in Gloas:EIP7732] // latest_execution_payload_bid=ExecutionPayloadBid( +// parent_block_hash=pre.latest_execution_payload_header.parent_hash, +// parent_block_root=pre.latest_block_header.parent_root, // block_hash=pre.latest_execution_payload_header.block_hash, +// prev_randao=pre.latest_execution_payload_header.prev_randao, +// fee_recipient=ExecutionAddress(), // gas_limit=pre.latest_execution_payload_header.gas_limit, +// builder_index=BUILDER_INDEX_SELF_BUILD, +// slot=pre.latest_block_header.slot, +// value=Gwei(0), +// execution_payment=Gwei(0), +// blob_kzg_commitments=BlobKZGCommitments(), // execution_requests_root=hash_tree_root(ExecutionRequests()), // ), // # [New in Gloas:EIP7732] -// payload_expected_withdrawals=[], +// payload_expected_withdrawals=Withdrawals(), // # [New in Gloas:EIP7732] // ptc_window=initialize_ptc_window(pre), // ) @@ -131,17 +136,16 @@ func UpgradeToGloas(beaconState state.BeaconState) (state.BeaconState, error) { // initializePTCWindow builds the initial PTC window for the Gloas fork upgrade. // -// +// // def initialize_ptc_window( // state: BeaconState, -// ) -> Vector[Vector[ValidatorIndex, PTC_SIZE], (2 + MIN_SEED_LOOKAHEAD) * SLOTS_PER_EPOCH]: +// ) -> PTCWindow: // """ // Return the cached PTC window starting from the current epoch. // Used to initialize the ``ptc_window`` field in the beacon state at genesis and after forks. // """ // empty_previous_epoch = [ -// Vector[ValidatorIndex, PTC_SIZE]([ValidatorIndex(0) for _ in range(PTC_SIZE)]) -// for _ in range(SLOTS_PER_EPOCH) +// PTC([ValidatorIndex(0) for _ in range(PTC_SIZE)]) for _ in range(SLOTS_PER_EPOCH) // ] // // ptcs = [] @@ -151,7 +155,7 @@ func UpgradeToGloas(beaconState state.BeaconState) (state.BeaconState, error) { // start_slot = compute_start_slot_at_epoch(epoch) // ptcs += [compute_ptc(state, Slot(start_slot + i)) for i in range(SLOTS_PER_EPOCH)] // -// return empty_previous_epoch + ptcs +// return PTCWindow(empty_previous_epoch + ptcs) // func initializePTCWindow(ctx context.Context, st state.ReadOnlyBeaconState) ([]*ethpb.PTCs, error) { currentEpoch := slots.ToEpoch(st.Slot()) diff --git a/beacon-chain/state/state-native/getters_gloas.go b/beacon-chain/state/state-native/getters_gloas.go index e9930669e218..03590a9b1739 100644 --- a/beacon-chain/state/state-native/getters_gloas.go +++ b/beacon-chain/state/state-native/getters_gloas.go @@ -375,10 +375,10 @@ func (b *BeaconState) builderIndexByPubkey(pubkey [fieldparams.BLSPubkeyLength]b // applied to the current state. It is also used by validators to check that the execution payload carried // the right number of withdrawals. // -// +// // def get_expected_withdrawals(state: BeaconState) -> ExpectedWithdrawals: // withdrawal_index = state.next_withdrawal_index -// withdrawals: List[Withdrawal] = [] +// withdrawals: list[Withdrawal] = [] // // # [New in Gloas:EIP7732] // # Get builder withdrawals @@ -459,7 +459,7 @@ func (b *BeaconState) ExpectedWithdrawalsGloas() (state.ExpectedWithdrawalsGloas // appendBuilderWithdrawals returns builder pending withdrawals, the updated withdrawal index, // and the processed count. // -// +// // def get_builder_withdrawals( // state: BeaconState, // withdrawal_index: WithdrawalIndex, @@ -469,9 +469,9 @@ func (b *BeaconState) ExpectedWithdrawalsGloas() (state.ExpectedWithdrawalsGloas // assert len(prior_withdrawals) <= withdrawals_limit // // processed_count: Uint64 = 0 -// withdrawals: List[Withdrawal] = [] +// withdrawals: list[Withdrawal] = [] // for withdrawal in state.builder_pending_withdrawals: -// all_withdrawals = prior_withdrawals + withdrawals +// all_withdrawals = list(prior_withdrawals) + withdrawals // has_reached_limit = len(all_withdrawals) >= withdrawals_limit // if has_reached_limit: // break @@ -521,7 +521,7 @@ func (b *BeaconState) appendBuilderWithdrawals(withdrawalIndex uint64, withdrawa // appendBuildersSweepWithdrawals returns builder sweep withdrawals, the updated withdrawal index, // and the processed count. // -// +// // def get_builders_sweep_withdrawals( // state: BeaconState, // withdrawal_index: WithdrawalIndex, @@ -533,10 +533,10 @@ func (b *BeaconState) appendBuilderWithdrawals(withdrawalIndex uint64, withdrawa // assert len(prior_withdrawals) <= withdrawals_limit // // processed_count: Uint64 = 0 -// withdrawals: List[Withdrawal] = [] +// withdrawals: list[Withdrawal] = [] // builder_index = state.next_withdrawal_builder_index // for _ in range(builders_limit): -// all_withdrawals = prior_withdrawals + withdrawals +// all_withdrawals = list(prior_withdrawals) + withdrawals // has_reached_limit = len(all_withdrawals) >= withdrawals_limit // if has_reached_limit: // break @@ -693,8 +693,8 @@ func (b *BeaconState) NextWithdrawalBuilderIndex() (primitives.BuilderIndex, err // PayloadCommitteeReadOnly returns the payload timeliness committee for a given slot // by looking up the cached PTC window in state. // -// -// def get_ptc(state: BeaconState, slot: Slot) -> Vector[ValidatorIndex, PTC_SIZE]: +// +// def get_ptc(state: BeaconState, slot: Slot) -> PTC: // """ // Get the payload timeliness committee for the given ``slot``. // """ diff --git a/beacon-chain/state/state-native/setters_gloas.go b/beacon-chain/state/state-native/setters_gloas.go index 066ea730c878..c5cd26e8cd75 100644 --- a/beacon-chain/state/state-native/setters_gloas.go +++ b/beacon-chain/state/state-native/setters_gloas.go @@ -684,7 +684,7 @@ func decreaseBalanceWithVal(currBalance, delta primitives.Gwei) primitives.Gwei // OnboardBuildersFromPendingDeposits applies any pending builder deposits at the fork. // It mutates the state and prunes pending deposits accordingly. // -// +// // def onboard_builders_from_pending_deposits(state: BeaconState) -> None: // """ // Applies any pending deposit for builders, effectively @@ -692,7 +692,7 @@ func decreaseBalanceWithVal(currBalance, delta primitives.Gwei) primitives.Gwei // """ // validator_pubkeys = [v.pubkey for v in state.validators] // -// pending_deposits = [] +// pending_deposits = PendingDeposits() // for deposit in state.pending_deposits: // # Deposits for existing validators stay in the pending queue // if deposit.pubkey in validator_pubkeys: diff --git a/beacon-chain/verification/execution_payload_bid.go b/beacon-chain/verification/execution_payload_bid.go index 654df2f73980..a9a109ab4081 100644 --- a/beacon-chain/verification/execution_payload_bid.go +++ b/beacon-chain/verification/execution_payload_bid.go @@ -232,7 +232,7 @@ func (v *BidVerifier) VerifyGasLimitTargetCompatible(parentGasLimit, targetGasLi // isGasLimitTargetCompatible reports whether gasLimit is compatible with // targetGasLimit under the EIP-1559 transition rule from parentGasLimit. // -// +// // def is_gas_limit_target_compatible( // parent_gas_limit: Uint64, gas_limit: Uint64, target_gas_limit: Uint64 // ) -> bool: @@ -244,11 +244,11 @@ func (v *BidVerifier) VerifyGasLimitTargetCompatible(parentGasLimit, targetGasLi // min_gas_limit = parent_gas_limit - max_gas_limit_difference // max_gas_limit = parent_gas_limit + max_gas_limit_difference // -// if target_gas_limit >= min_gas_limit and target_gas_limit <= max_gas_limit: -// return gas_limit == target_gas_limit +// if target_gas_limit < min_gas_limit: +// return gas_limit == min_gas_limit // if target_gas_limit > max_gas_limit: // return gas_limit == max_gas_limit -// return gas_limit == min_gas_limit +// return gas_limit == target_gas_limit // func isGasLimitTargetCompatible(parentGasLimit, gasLimit, targetGasLimit uint64) bool { maxDiff := max(parentGasLimit/1024, 1) - 1 diff --git a/changelog/terence_alpha14.md b/changelog/terence_alpha14.md new file mode 100644 index 000000000000..674d8779a165 --- /dev/null +++ b/changelog/terence_alpha14.md @@ -0,0 +1,3 @@ +### Changed + +- Bump consensus spec to v1.7.0-alpha.14. diff --git a/specrefs/configs.yml b/specrefs/configs.yml index 17301c490db1..2472813fc566 100644 --- a/specrefs/configs.yml +++ b/specrefs/configs.yml @@ -359,6 +359,14 @@ FULU_FORK_VERSION: Version = '0x06000000' +- name: GAS_LIMIT_SCHEDULE#gloas + sources: [] + spec: | + + GAS_LIMIT_SCHEDULE: tuple[frozendict[str, Any], ...] = ( + ) + + - name: GENESIS_DELAY#phase0 sources: - file: config/params/config.go @@ -464,13 +472,6 @@ MAX_BLOBS_PER_BLOCK_ELECTRA: Uint64 = 9 -- name: MAX_BYTES_PER_INCLUSION_LIST#heze - sources: [] - spec: | - - MAX_BYTES_PER_INCLUSION_LIST: Uint64 = 8192 - - - name: MAX_PAYLOAD_SIZE#phase0 sources: - file: config/params/config.go diff --git a/specrefs/containers.yml b/specrefs/containers.yml index 187fcdd2f1c5..6e03060924f5 100644 --- a/specrefs/containers.yml +++ b/specrefs/containers.yml @@ -23,14 +23,47 @@ selection_proof: BLSSignature +- name: AggregationBits#phase0 + sources: [] + spec: | + + class AggregationBits(BitList[MAX_VALIDATORS_PER_COMMITTEE]): + """ + The participation bits of a single committee, one bit per member in + committee order. + """ + + +- name: AggregationBits#electra + sources: [] + spec: | + + class AggregationBits(BitList[MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT]): # type: ignore + """ + The participation bits of all committees participating in an attestation, + concatenated in committee order. + """ + + +- name: AggregationBits#gloas + sources: [] + spec: | + + class AggregationBits(ProgressiveBitList): + """ + The participation bits of all committees participating in an attestation, + concatenated in committee order. + """ + + - name: Attestation#phase0 sources: - file: proto/prysm/v1alpha1/attestation.proto search: message Attestation { spec: | - + class Attestation(Container): - aggregation_bits: BitList[MAX_VALIDATORS_PER_COMMITTEE] + aggregation_bits: AggregationBits data: AttestationData signature: BLSSignature @@ -40,14 +73,14 @@ - file: proto/prysm/v1alpha1/attestation.proto search: message AttestationElectra { spec: | - + class Attestation(Container): # [Modified in Electra:EIP7549] aggregation_bits: AggregationBits data: AttestationData signature: BLSSignature # [New in Electra:EIP7549] - committee_bits: BitVector[MAX_COMMITTEES_PER_SLOT] + committee_bits: CommitteeBits - name: Attestation#gloas @@ -55,12 +88,12 @@ - file: proto/prysm/v1alpha1/attestation.proto search: message AttestationGloas { spec: | - + class Attestation(ProgressiveContainer(active_fields=[1] * 4)): # type: ignore aggregation_bits: AggregationBits data: AttestationData signature: BLSSignature - committee_bits: BitVector[MAX_COMMITTEES_PER_SLOT] + committee_bits: CommitteeBits - name: AttestationData#phase0 @@ -77,6 +110,36 @@ target: Checkpoint +- name: Attestations#phase0 + sources: [] + spec: | + + class Attestations(List[Attestation, MAX_ATTESTATIONS]): + """ + The attestations included in a beacon block. + """ + + +- name: Attestations#electra + sources: [] + spec: | + + class Attestations(List[Attestation, MAX_ATTESTATIONS_ELECTRA]): + """ + The attestations included in a beacon block. + """ + + +- name: Attestations#gloas + sources: [] + spec: | + + class Attestations(ProgressiveList[Attestation]): + """ + The attestations included in a beacon block. + """ + + - name: AttesterSlashing#phase0 sources: - file: proto/eth/v1/beacon_block.proto @@ -101,6 +164,78 @@ attestation_2: IndexedAttestation +- name: AttesterSlashings#phase0 + sources: [] + spec: | + + class AttesterSlashings(List[AttesterSlashing, MAX_ATTESTER_SLASHINGS]): + """ + The attester slashings included in a beacon block. + """ + + +- name: AttesterSlashings#electra + sources: [] + spec: | + + class AttesterSlashings(List[AttesterSlashing, MAX_ATTESTER_SLASHINGS_ELECTRA]): + """ + The attester slashings included in a beacon block. + """ + + +- name: AttesterSlashings#gloas + sources: [] + spec: | + + class AttesterSlashings(ProgressiveList[AttesterSlashing]): + """ + The attester slashings included in a beacon block. + """ + + +- name: AttestingIndices#phase0 + sources: [] + spec: | + + class AttestingIndices(List[ValidatorIndex, MAX_VALIDATORS_PER_COMMITTEE]): + """ + The indices of the validators participating in an attestation. + """ + + +- name: AttestingIndices#electra + sources: [] + spec: | + + class AttestingIndices( + List[ValidatorIndex, MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT] # type: ignore + ): + """ + The indices of the validators participating in an attestation. + """ + + +- name: AttestingIndices#gloas + sources: [] + spec: | + + class AttestingIndices(ProgressiveList[ValidatorIndex]): + """ + The indices of the validators participating in an attestation. + """ + + +- name: Attnets#phase0 + sources: [] + spec: | + + class Attnets(BitVector[ATTESTATION_SUBNET_COUNT]): # type: ignore + """ + The attestation subnets a node is subscribed to, one bit per subnet. + """ + + - name: BLSToExecutionChange#capella sources: - file: proto/prysm/v1alpha1/withdrawals.proto @@ -113,6 +248,48 @@ to_execution_address: ExecutionAddress +- name: BLSToExecutionChanges#capella + sources: [] + spec: | + + class BLSToExecutionChanges(List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES]): + """ + The signed BLS-to-execution credential changes included in a beacon + block. + """ + + +- name: BLSToExecutionChanges#gloas + sources: [] + spec: | + + class BLSToExecutionChanges(ProgressiveList[SignedBLSToExecutionChange]): + """ + The signed BLS-to-execution credential changes included in a beacon + block. + """ + + +- name: Balances#phase0 + sources: [] + spec: | + + class Balances(List[Gwei, VALIDATOR_REGISTRY_LIMIT]): + """ + The balances of all validators. + """ + + +- name: Balances#gloas + sources: [] + spec: | + + class Balances(ProgressiveList[Gwei]): + """ + The balances of all validators. + """ + + - name: BeaconBlock#phase0 sources: - file: proto/eth/v1/beacon_block.proto @@ -132,16 +309,16 @@ - file: proto/eth/v1/beacon_block.proto search: message BeaconBlockBody { spec: | - + class BeaconBlockBody(Container): randao_reveal: BLSSignature eth1_data: Eth1Data graffiti: Bytes32 - proposer_slashings: List[ProposerSlashing, MAX_PROPOSER_SLASHINGS] - attester_slashings: List[AttesterSlashing, MAX_ATTESTER_SLASHINGS] - attestations: List[Attestation, MAX_ATTESTATIONS] - deposits: List[Deposit, MAX_DEPOSITS] - voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS] + proposer_slashings: ProposerSlashings + attester_slashings: AttesterSlashings + attestations: Attestations + deposits: Deposits + voluntary_exits: VoluntaryExits - name: BeaconBlockBody#altair @@ -149,16 +326,16 @@ - file: proto/prysm/v1alpha1/beacon_block.proto search: message BeaconBlockBodyAltair { spec: | - + class BeaconBlockBody(Container): randao_reveal: BLSSignature eth1_data: Eth1Data graffiti: Bytes32 - proposer_slashings: List[ProposerSlashing, MAX_PROPOSER_SLASHINGS] - attester_slashings: List[AttesterSlashing, MAX_ATTESTER_SLASHINGS] - attestations: List[Attestation, MAX_ATTESTATIONS] - deposits: List[Deposit, MAX_DEPOSITS] - voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS] + proposer_slashings: ProposerSlashings + attester_slashings: AttesterSlashings + attestations: Attestations + deposits: Deposits + voluntary_exits: VoluntaryExits # [New in Altair] sync_aggregate: SyncAggregate @@ -168,16 +345,16 @@ - file: proto/prysm/v1alpha1/beacon_block.proto search: message BeaconBlockBodyBellatrix { spec: | - + class BeaconBlockBody(Container): randao_reveal: BLSSignature eth1_data: Eth1Data graffiti: Bytes32 - proposer_slashings: List[ProposerSlashing, MAX_PROPOSER_SLASHINGS] - attester_slashings: List[AttesterSlashing, MAX_ATTESTER_SLASHINGS] - attestations: List[Attestation, MAX_ATTESTATIONS] - deposits: List[Deposit, MAX_DEPOSITS] - voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS] + proposer_slashings: ProposerSlashings + attester_slashings: AttesterSlashings + attestations: Attestations + deposits: Deposits + voluntary_exits: VoluntaryExits sync_aggregate: SyncAggregate # [New in Bellatrix] execution_payload: ExecutionPayload @@ -188,20 +365,20 @@ - file: proto/prysm/v1alpha1/beacon_block.proto search: message BeaconBlockBodyCapella { spec: | - + class BeaconBlockBody(Container): randao_reveal: BLSSignature eth1_data: Eth1Data graffiti: Bytes32 - proposer_slashings: List[ProposerSlashing, MAX_PROPOSER_SLASHINGS] - attester_slashings: List[AttesterSlashing, MAX_ATTESTER_SLASHINGS] - attestations: List[Attestation, MAX_ATTESTATIONS] - deposits: List[Deposit, MAX_DEPOSITS] - voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS] + proposer_slashings: ProposerSlashings + attester_slashings: AttesterSlashings + attestations: Attestations + deposits: Deposits + voluntary_exits: VoluntaryExits sync_aggregate: SyncAggregate execution_payload: ExecutionPayload # [New in Capella] - bls_to_execution_changes: List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES] + bls_to_execution_changes: BLSToExecutionChanges - name: BeaconBlockBody#deneb @@ -209,22 +386,22 @@ - file: proto/prysm/v1alpha1/beacon_block.proto search: message BeaconBlockBodyDeneb { spec: | - + class BeaconBlockBody(Container): randao_reveal: BLSSignature eth1_data: Eth1Data graffiti: Bytes32 - proposer_slashings: List[ProposerSlashing, MAX_PROPOSER_SLASHINGS] - attester_slashings: List[AttesterSlashing, MAX_ATTESTER_SLASHINGS] - attestations: List[Attestation, MAX_ATTESTATIONS] - deposits: List[Deposit, MAX_DEPOSITS] - voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS] + proposer_slashings: ProposerSlashings + attester_slashings: AttesterSlashings + attestations: Attestations + deposits: Deposits + voluntary_exits: VoluntaryExits sync_aggregate: SyncAggregate # [Modified in Deneb:EIP4844] execution_payload: ExecutionPayload - bls_to_execution_changes: List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES] + bls_to_execution_changes: BLSToExecutionChanges # [New in Deneb:EIP4844] - blob_kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK] + blob_kzg_commitments: BlobKZGCommitments - name: BeaconBlockBody#electra @@ -232,22 +409,22 @@ - file: proto/prysm/v1alpha1/beacon_block.proto search: message BeaconBlockBodyElectra { spec: | - + class BeaconBlockBody(Container): randao_reveal: BLSSignature eth1_data: Eth1Data graffiti: Bytes32 - proposer_slashings: List[ProposerSlashing, MAX_PROPOSER_SLASHINGS] + proposer_slashings: ProposerSlashings # [Modified in Electra:EIP7549] - attester_slashings: List[AttesterSlashing, MAX_ATTESTER_SLASHINGS_ELECTRA] + attester_slashings: AttesterSlashings # [Modified in Electra:EIP7549] - attestations: List[Attestation, MAX_ATTESTATIONS_ELECTRA] - deposits: List[Deposit, MAX_DEPOSITS] - voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS] + attestations: Attestations + deposits: Deposits + voluntary_exits: VoluntaryExits sync_aggregate: SyncAggregate execution_payload: ExecutionPayload - bls_to_execution_changes: List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES] - blob_kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK] + bls_to_execution_changes: BLSToExecutionChanges + blob_kzg_commitments: BlobKZGCommitments # [New in Electra] execution_requests: ExecutionRequests @@ -255,26 +432,26 @@ - name: BeaconBlockBody#gloas sources: [] spec: | - + class BeaconBlockBody(ProgressiveContainer(active_fields=[1] * 13)): # type: ignore randao_reveal: BLSSignature eth1_data: Eth1Data graffiti: Bytes32 # [Modified in Gloas:EIP7688] - proposer_slashings: ProgressiveList[ProposerSlashing] + proposer_slashings: ProposerSlashings # [Modified in Gloas:EIP7688] - attester_slashings: ProgressiveList[AttesterSlashing] + attester_slashings: AttesterSlashings # [Modified in Gloas:EIP7688] - attestations: ProgressiveList[Attestation] + attestations: Attestations # [Modified in Gloas:EIP7688] - deposits: ProgressiveList[Deposit] + deposits: Deposits # [Modified in Gloas:EIP7688] - voluntary_exits: ProgressiveList[SignedVoluntaryExit] + voluntary_exits: VoluntaryExits sync_aggregate: SyncAggregate # [Modified in Gloas:EIP7732] # Removed `execution_payload` # [Modified in Gloas:EIP7688] - bls_to_execution_changes: ProgressiveList[SignedBLSToExecutionChange] + bls_to_execution_changes: BLSToExecutionChanges # [Modified in Gloas:EIP7732] # Removed `blob_kzg_commitments` # [Modified in Gloas:EIP7732] @@ -282,7 +459,7 @@ # [New in Gloas:EIP7732] signed_execution_payload_bid: SignedExecutionPayloadBid # [New in Gloas:EIP7732] - payload_attestations: ProgressiveList[PayloadAttestation] + payload_attestations: PayloadAttestations # [New in Gloas:EIP7732] parent_execution_requests: ExecutionRequests @@ -301,31 +478,51 @@ body_root: Root +- name: BeaconBlockRoots#phase0 + sources: [] + spec: | + + class BeaconBlockRoots(List[Root, MAX_REQUEST_BLOCKS]): # type: ignore + """ + Beacon block roots requested in a ``BeaconBlocksByRoot`` request. + """ + + +- name: BeaconBlockRoots#deneb + sources: [] + spec: | + + class BeaconBlockRoots(List[Root, MAX_REQUEST_BLOCKS_DENEB]): # type: ignore + """ + Beacon block roots requested in a ``BeaconBlocksByRoot`` request. + """ + + - name: BeaconState#phase0 sources: - file: proto/prysm/v1alpha1/beacon_state.proto search: message BeaconState { spec: | - + class BeaconState(Container): genesis_time: Uint64 genesis_validators_root: Root slot: Slot fork: Fork latest_block_header: BeaconBlockHeader - block_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT] - state_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT] - historical_roots: List[Root, HISTORICAL_ROOTS_LIMIT] + block_roots: BlockRoots + state_roots: StateRoots + historical_roots: HistoricalRoots eth1_data: Eth1Data - eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH] + eth1_data_votes: Eth1DataVotes eth1_deposit_index: Uint64 - validators: List[Validator, VALIDATOR_REGISTRY_LIMIT] - balances: List[Gwei, VALIDATOR_REGISTRY_LIMIT] - randao_mixes: Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR] - slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] - previous_epoch_attestations: List[PendingAttestation, MAX_ATTESTATIONS * SLOTS_PER_EPOCH] - current_epoch_attestations: List[PendingAttestation, MAX_ATTESTATIONS * SLOTS_PER_EPOCH] - justification_bits: BitVector[JUSTIFICATION_BITS_LENGTH] + validators: Validators + balances: Balances + randao_mixes: RandaoMixes + slashings: Slashings + previous_epoch_attestations: PendingAttestations + current_epoch_attestations: PendingAttestations + justification_bits: JustificationBits previous_justified_checkpoint: Checkpoint current_justified_checkpoint: Checkpoint finalized_checkpoint: Checkpoint @@ -336,33 +533,33 @@ - file: proto/prysm/v1alpha1/beacon_state.proto search: message BeaconStateAltair { spec: | - + class BeaconState(Container): genesis_time: Uint64 genesis_validators_root: Root slot: Slot fork: Fork latest_block_header: BeaconBlockHeader - block_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT] - state_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT] - historical_roots: List[Root, HISTORICAL_ROOTS_LIMIT] + block_roots: BlockRoots + state_roots: StateRoots + historical_roots: HistoricalRoots eth1_data: Eth1Data - eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH] + eth1_data_votes: Eth1DataVotes eth1_deposit_index: Uint64 - validators: List[Validator, VALIDATOR_REGISTRY_LIMIT] - balances: List[Gwei, VALIDATOR_REGISTRY_LIMIT] - randao_mixes: Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR] - slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] + validators: Validators + balances: Balances + randao_mixes: RandaoMixes + slashings: Slashings # [Modified in Altair] - previous_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] + previous_epoch_participation: EpochParticipation # [Modified in Altair] - current_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] - justification_bits: BitVector[JUSTIFICATION_BITS_LENGTH] + current_epoch_participation: EpochParticipation + justification_bits: JustificationBits previous_justified_checkpoint: Checkpoint current_justified_checkpoint: Checkpoint finalized_checkpoint: Checkpoint # [New in Altair] - inactivity_scores: List[Uint64, VALIDATOR_REGISTRY_LIMIT] + inactivity_scores: InactivityScores # [New in Altair] current_sync_committee: SyncCommittee # [New in Altair] @@ -374,30 +571,30 @@ - file: proto/prysm/v1alpha1/beacon_state.proto search: message BeaconStateBellatrix { spec: | - + class BeaconState(Container): genesis_time: Uint64 genesis_validators_root: Root slot: Slot fork: Fork latest_block_header: BeaconBlockHeader - block_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT] - state_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT] - historical_roots: List[Root, HISTORICAL_ROOTS_LIMIT] + block_roots: BlockRoots + state_roots: StateRoots + historical_roots: HistoricalRoots eth1_data: Eth1Data - eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH] + eth1_data_votes: Eth1DataVotes eth1_deposit_index: Uint64 - validators: List[Validator, VALIDATOR_REGISTRY_LIMIT] - balances: List[Gwei, VALIDATOR_REGISTRY_LIMIT] - randao_mixes: Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR] - slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] - previous_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] - current_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] - justification_bits: BitVector[JUSTIFICATION_BITS_LENGTH] + validators: Validators + balances: Balances + randao_mixes: RandaoMixes + slashings: Slashings + previous_epoch_participation: EpochParticipation + current_epoch_participation: EpochParticipation + justification_bits: JustificationBits previous_justified_checkpoint: Checkpoint current_justified_checkpoint: Checkpoint finalized_checkpoint: Checkpoint - inactivity_scores: List[Uint64, VALIDATOR_REGISTRY_LIMIT] + inactivity_scores: InactivityScores current_sync_committee: SyncCommittee next_sync_committee: SyncCommittee # [New in Bellatrix] @@ -409,30 +606,30 @@ - file: proto/prysm/v1alpha1/beacon_state.proto search: message BeaconStateCapella { spec: | - + class BeaconState(Container): genesis_time: Uint64 genesis_validators_root: Root slot: Slot fork: Fork latest_block_header: BeaconBlockHeader - block_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT] - state_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT] - historical_roots: List[Root, HISTORICAL_ROOTS_LIMIT] + block_roots: BlockRoots + state_roots: StateRoots + historical_roots: HistoricalRoots eth1_data: Eth1Data - eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH] + eth1_data_votes: Eth1DataVotes eth1_deposit_index: Uint64 - validators: List[Validator, VALIDATOR_REGISTRY_LIMIT] - balances: List[Gwei, VALIDATOR_REGISTRY_LIMIT] - randao_mixes: Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR] - slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] - previous_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] - current_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] - justification_bits: BitVector[JUSTIFICATION_BITS_LENGTH] + validators: Validators + balances: Balances + randao_mixes: RandaoMixes + slashings: Slashings + previous_epoch_participation: EpochParticipation + current_epoch_participation: EpochParticipation + justification_bits: JustificationBits previous_justified_checkpoint: Checkpoint current_justified_checkpoint: Checkpoint finalized_checkpoint: Checkpoint - inactivity_scores: List[Uint64, VALIDATOR_REGISTRY_LIMIT] + inactivity_scores: InactivityScores current_sync_committee: SyncCommittee next_sync_committee: SyncCommittee # [Modified in Capella] @@ -442,7 +639,7 @@ # [New in Capella] next_withdrawal_validator_index: ValidatorIndex # [New in Capella] - historical_summaries: List[HistoricalSummary, HISTORICAL_ROOTS_LIMIT] + historical_summaries: HistoricalSummaries - name: BeaconState#deneb @@ -450,37 +647,37 @@ - file: proto/prysm/v1alpha1/beacon_state.proto search: message BeaconStateDeneb { spec: | - + class BeaconState(Container): genesis_time: Uint64 genesis_validators_root: Root slot: Slot fork: Fork latest_block_header: BeaconBlockHeader - block_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT] - state_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT] - historical_roots: List[Root, HISTORICAL_ROOTS_LIMIT] + block_roots: BlockRoots + state_roots: StateRoots + historical_roots: HistoricalRoots eth1_data: Eth1Data - eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH] + eth1_data_votes: Eth1DataVotes eth1_deposit_index: Uint64 - validators: List[Validator, VALIDATOR_REGISTRY_LIMIT] - balances: List[Gwei, VALIDATOR_REGISTRY_LIMIT] - randao_mixes: Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR] - slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] - previous_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] - current_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] - justification_bits: BitVector[JUSTIFICATION_BITS_LENGTH] + validators: Validators + balances: Balances + randao_mixes: RandaoMixes + slashings: Slashings + previous_epoch_participation: EpochParticipation + current_epoch_participation: EpochParticipation + justification_bits: JustificationBits previous_justified_checkpoint: Checkpoint current_justified_checkpoint: Checkpoint finalized_checkpoint: Checkpoint - inactivity_scores: List[Uint64, VALIDATOR_REGISTRY_LIMIT] + inactivity_scores: InactivityScores current_sync_committee: SyncCommittee next_sync_committee: SyncCommittee # [Modified in Deneb:EIP4844] latest_execution_payload_header: ExecutionPayloadHeader next_withdrawal_index: WithdrawalIndex next_withdrawal_validator_index: ValidatorIndex - historical_summaries: List[HistoricalSummary, HISTORICAL_ROOTS_LIMIT] + historical_summaries: HistoricalSummaries - name: BeaconState#electra @@ -488,36 +685,36 @@ - file: proto/prysm/v1alpha1/beacon_state.proto search: message BeaconStateElectra { spec: | - + class BeaconState(Container): genesis_time: Uint64 genesis_validators_root: Root slot: Slot fork: Fork latest_block_header: BeaconBlockHeader - block_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT] - state_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT] - historical_roots: List[Root, HISTORICAL_ROOTS_LIMIT] + block_roots: BlockRoots + state_roots: StateRoots + historical_roots: HistoricalRoots eth1_data: Eth1Data - eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH] + eth1_data_votes: Eth1DataVotes eth1_deposit_index: Uint64 - validators: List[Validator, VALIDATOR_REGISTRY_LIMIT] - balances: List[Gwei, VALIDATOR_REGISTRY_LIMIT] - randao_mixes: Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR] - slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] - previous_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] - current_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] - justification_bits: BitVector[JUSTIFICATION_BITS_LENGTH] + validators: Validators + balances: Balances + randao_mixes: RandaoMixes + slashings: Slashings + previous_epoch_participation: EpochParticipation + current_epoch_participation: EpochParticipation + justification_bits: JustificationBits previous_justified_checkpoint: Checkpoint current_justified_checkpoint: Checkpoint finalized_checkpoint: Checkpoint - inactivity_scores: List[Uint64, VALIDATOR_REGISTRY_LIMIT] + inactivity_scores: InactivityScores current_sync_committee: SyncCommittee next_sync_committee: SyncCommittee latest_execution_payload_header: ExecutionPayloadHeader next_withdrawal_index: WithdrawalIndex next_withdrawal_validator_index: ValidatorIndex - historical_summaries: List[HistoricalSummary, HISTORICAL_ROOTS_LIMIT] + historical_summaries: HistoricalSummaries # [New in Electra:EIP6110] deposit_requests_start_index: Uint64 # [New in Electra:EIP7251] @@ -531,11 +728,11 @@ # [New in Electra:EIP7251] earliest_consolidation_epoch: Epoch # [New in Electra:EIP7251] - pending_deposits: List[PendingDeposit, PENDING_DEPOSITS_LIMIT] + pending_deposits: PendingDeposits # [New in Electra:EIP7251] - pending_partial_withdrawals: List[PendingPartialWithdrawal, PENDING_PARTIAL_WITHDRAWALS_LIMIT] + pending_partial_withdrawals: PendingPartialWithdrawals # [New in Electra:EIP7251] - pending_consolidations: List[PendingConsolidation, PENDING_CONSOLIDATIONS_LIMIT] + pending_consolidations: PendingConsolidations - name: BeaconState#fulu @@ -543,81 +740,81 @@ - file: proto/prysm/v1alpha1/beacon_state.proto search: message BeaconStateFulu { spec: | - + class BeaconState(Container): genesis_time: Uint64 genesis_validators_root: Root slot: Slot fork: Fork latest_block_header: BeaconBlockHeader - block_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT] - state_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT] - historical_roots: List[Root, HISTORICAL_ROOTS_LIMIT] + block_roots: BlockRoots + state_roots: StateRoots + historical_roots: HistoricalRoots eth1_data: Eth1Data - eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH] + eth1_data_votes: Eth1DataVotes eth1_deposit_index: Uint64 - validators: List[Validator, VALIDATOR_REGISTRY_LIMIT] - balances: List[Gwei, VALIDATOR_REGISTRY_LIMIT] - randao_mixes: Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR] - slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] - previous_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] - current_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT] - justification_bits: BitVector[JUSTIFICATION_BITS_LENGTH] + validators: Validators + balances: Balances + randao_mixes: RandaoMixes + slashings: Slashings + previous_epoch_participation: EpochParticipation + current_epoch_participation: EpochParticipation + justification_bits: JustificationBits previous_justified_checkpoint: Checkpoint current_justified_checkpoint: Checkpoint finalized_checkpoint: Checkpoint - inactivity_scores: List[Uint64, VALIDATOR_REGISTRY_LIMIT] + inactivity_scores: InactivityScores current_sync_committee: SyncCommittee next_sync_committee: SyncCommittee latest_execution_payload_header: ExecutionPayloadHeader next_withdrawal_index: WithdrawalIndex next_withdrawal_validator_index: ValidatorIndex - historical_summaries: List[HistoricalSummary, HISTORICAL_ROOTS_LIMIT] + historical_summaries: HistoricalSummaries deposit_requests_start_index: Uint64 deposit_balance_to_consume: Gwei exit_balance_to_consume: Gwei earliest_exit_epoch: Epoch consolidation_balance_to_consume: Gwei earliest_consolidation_epoch: Epoch - pending_deposits: List[PendingDeposit, PENDING_DEPOSITS_LIMIT] - pending_partial_withdrawals: List[PendingPartialWithdrawal, PENDING_PARTIAL_WITHDRAWALS_LIMIT] - pending_consolidations: List[PendingConsolidation, PENDING_CONSOLIDATIONS_LIMIT] + pending_deposits: PendingDeposits + pending_partial_withdrawals: PendingPartialWithdrawals + pending_consolidations: PendingConsolidations # [New in Fulu:EIP7917] - proposer_lookahead: Vector[ValidatorIndex, (MIN_SEED_LOOKAHEAD + 1) * SLOTS_PER_EPOCH] + proposer_lookahead: ProposerLookahead - name: BeaconState#gloas sources: [] spec: | - + class BeaconState(ProgressiveContainer(active_fields=[1] * 46)): # type: ignore genesis_time: Uint64 genesis_validators_root: Root slot: Slot fork: Fork latest_block_header: BeaconBlockHeader - block_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT] - state_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT] - historical_roots: List[Root, HISTORICAL_ROOTS_LIMIT] + block_roots: BlockRoots + state_roots: StateRoots + historical_roots: HistoricalRoots eth1_data: Eth1Data - eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH] + eth1_data_votes: Eth1DataVotes eth1_deposit_index: Uint64 # [Modified in Gloas:EIP7688] - validators: ProgressiveList[Validator] + validators: Validators # [Modified in Gloas:EIP7688] - balances: ProgressiveList[Gwei] - randao_mixes: Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR] - slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] + balances: Balances + randao_mixes: RandaoMixes + slashings: Slashings # [Modified in Gloas:EIP7688] - previous_epoch_participation: ProgressiveList[ParticipationFlags] + previous_epoch_participation: EpochParticipation # [Modified in Gloas:EIP7688] - current_epoch_participation: ProgressiveList[ParticipationFlags] - justification_bits: BitVector[JUSTIFICATION_BITS_LENGTH] + current_epoch_participation: EpochParticipation + justification_bits: JustificationBits previous_justified_checkpoint: Checkpoint current_justified_checkpoint: Checkpoint finalized_checkpoint: Checkpoint # [Modified in Gloas:EIP7688] - inactivity_scores: ProgressiveList[Uint64] + inactivity_scores: InactivityScores current_sync_committee: SyncCommittee next_sync_committee: SyncCommittee # [Modified in Gloas:EIP7732] @@ -626,7 +823,7 @@ latest_block_hash: Hash32 next_withdrawal_index: WithdrawalIndex next_withdrawal_validator_index: ValidatorIndex - historical_summaries: List[HistoricalSummary, HISTORICAL_ROOTS_LIMIT] + historical_summaries: HistoricalSummaries deposit_requests_start_index: Uint64 deposit_balance_to_consume: Gwei exit_balance_to_consume: Gwei @@ -634,136 +831,146 @@ consolidation_balance_to_consume: Gwei earliest_consolidation_epoch: Epoch # [Modified in Gloas:EIP7688] - pending_deposits: ProgressiveList[PendingDeposit] + pending_deposits: PendingDeposits # [Modified in Gloas:EIP7688] - pending_partial_withdrawals: ProgressiveList[PendingPartialWithdrawal] + pending_partial_withdrawals: PendingPartialWithdrawals # [Modified in Gloas:EIP7688] - pending_consolidations: ProgressiveList[PendingConsolidation] - proposer_lookahead: Vector[ValidatorIndex, (MIN_SEED_LOOKAHEAD + 1) * SLOTS_PER_EPOCH] + pending_consolidations: PendingConsolidations + proposer_lookahead: ProposerLookahead # [New in Gloas:EIP7732] - builders: ProgressiveList[Builder] + builders: Builders # [New in Gloas:EIP7732] next_withdrawal_builder_index: BuilderIndex # [New in Gloas:EIP7732] - execution_payload_availability: BitVector[SLOTS_PER_HISTORICAL_ROOT] + execution_payload_availability: ExecutionPayloadAvailability # [New in Gloas:EIP7732] - builder_pending_payments: Vector[BuilderPendingPayment, 2 * SLOTS_PER_EPOCH] + builder_pending_payments: BuilderPendingPayments # [New in Gloas:EIP7732] - builder_pending_withdrawals: ProgressiveList[BuilderPendingWithdrawal] + builder_pending_withdrawals: BuilderPendingWithdrawals # [New in Gloas:EIP7732] latest_execution_payload_bid: ExecutionPayloadBid # [New in Gloas:EIP7732] - payload_expected_withdrawals: ProgressiveList[Withdrawal] + payload_expected_withdrawals: Withdrawals # [New in Gloas:EIP7732] - ptc_window: Vector[Vector[ValidatorIndex, PTC_SIZE], (2 + MIN_SEED_LOOKAHEAD) * SLOTS_PER_EPOCH] + ptc_window: PTCWindow - name: BeaconState#heze sources: [] spec: | - + class BeaconState(ProgressiveContainer(active_fields=[1] * 46)): # type: ignore genesis_time: Uint64 genesis_validators_root: Root slot: Slot fork: Fork latest_block_header: BeaconBlockHeader - block_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT] - state_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT] - historical_roots: List[Root, HISTORICAL_ROOTS_LIMIT] + block_roots: BlockRoots + state_roots: StateRoots + historical_roots: HistoricalRoots eth1_data: Eth1Data - eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH] + eth1_data_votes: Eth1DataVotes eth1_deposit_index: Uint64 - validators: ProgressiveList[Validator] - balances: ProgressiveList[Gwei] - randao_mixes: Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR] - slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] - previous_epoch_participation: ProgressiveList[ParticipationFlags] - current_epoch_participation: ProgressiveList[ParticipationFlags] - justification_bits: BitVector[JUSTIFICATION_BITS_LENGTH] + validators: Validators + balances: Balances + randao_mixes: RandaoMixes + slashings: Slashings + previous_epoch_participation: EpochParticipation + current_epoch_participation: EpochParticipation + justification_bits: JustificationBits previous_justified_checkpoint: Checkpoint current_justified_checkpoint: Checkpoint finalized_checkpoint: Checkpoint - inactivity_scores: ProgressiveList[Uint64] + inactivity_scores: InactivityScores current_sync_committee: SyncCommittee next_sync_committee: SyncCommittee latest_block_hash: Hash32 next_withdrawal_index: WithdrawalIndex next_withdrawal_validator_index: ValidatorIndex - historical_summaries: List[HistoricalSummary, HISTORICAL_ROOTS_LIMIT] + historical_summaries: HistoricalSummaries deposit_requests_start_index: Uint64 deposit_balance_to_consume: Gwei exit_balance_to_consume: Gwei earliest_exit_epoch: Epoch consolidation_balance_to_consume: Gwei earliest_consolidation_epoch: Epoch - pending_deposits: ProgressiveList[PendingDeposit] - pending_partial_withdrawals: ProgressiveList[PendingPartialWithdrawal] - pending_consolidations: ProgressiveList[PendingConsolidation] - proposer_lookahead: Vector[ValidatorIndex, (MIN_SEED_LOOKAHEAD + 1) * SLOTS_PER_EPOCH] - builders: ProgressiveList[Builder] + pending_deposits: PendingDeposits + pending_partial_withdrawals: PendingPartialWithdrawals + pending_consolidations: PendingConsolidations + proposer_lookahead: ProposerLookahead + builders: Builders next_withdrawal_builder_index: BuilderIndex - execution_payload_availability: BitVector[SLOTS_PER_HISTORICAL_ROOT] - builder_pending_payments: Vector[BuilderPendingPayment, 2 * SLOTS_PER_EPOCH] - builder_pending_withdrawals: ProgressiveList[BuilderPendingWithdrawal] + execution_payload_availability: ExecutionPayloadAvailability + builder_pending_payments: BuilderPendingPayments + builder_pending_withdrawals: BuilderPendingWithdrawals # [Modified in Heze:EIP7805] latest_execution_payload_bid: ExecutionPayloadBid - payload_expected_withdrawals: ProgressiveList[Withdrawal] - ptc_window: Vector[Vector[ValidatorIndex, PTC_SIZE], (2 + MIN_SEED_LOOKAHEAD) * SLOTS_PER_EPOCH] + payload_expected_withdrawals: Withdrawals + ptc_window: PTCWindow - name: BeaconState#heze sources: [] spec: | - + class BeaconState(ProgressiveContainer(active_fields=[1] * 46)): # type: ignore genesis_time: Uint64 genesis_validators_root: Root slot: Slot fork: Fork latest_block_header: BeaconBlockHeader - block_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT] - state_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT] - historical_roots: List[Root, HISTORICAL_ROOTS_LIMIT] + block_roots: BlockRoots + state_roots: StateRoots + historical_roots: HistoricalRoots eth1_data: Eth1Data - eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH] + eth1_data_votes: Eth1DataVotes eth1_deposit_index: Uint64 - validators: ProgressiveList[Validator] - balances: ProgressiveList[Gwei] - randao_mixes: Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR] - slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] - previous_epoch_participation: ProgressiveList[ParticipationFlags] - current_epoch_participation: ProgressiveList[ParticipationFlags] - justification_bits: BitVector[JUSTIFICATION_BITS_LENGTH] + validators: Validators + balances: Balances + randao_mixes: RandaoMixes + slashings: Slashings + previous_epoch_participation: EpochParticipation + current_epoch_participation: EpochParticipation + justification_bits: JustificationBits previous_justified_checkpoint: Checkpoint current_justified_checkpoint: Checkpoint finalized_checkpoint: Checkpoint - inactivity_scores: ProgressiveList[Uint64] + inactivity_scores: InactivityScores current_sync_committee: SyncCommittee next_sync_committee: SyncCommittee latest_block_hash: Hash32 next_withdrawal_index: WithdrawalIndex next_withdrawal_validator_index: ValidatorIndex - historical_summaries: List[HistoricalSummary, HISTORICAL_ROOTS_LIMIT] + historical_summaries: HistoricalSummaries deposit_requests_start_index: Uint64 deposit_balance_to_consume: Gwei exit_balance_to_consume: Gwei earliest_exit_epoch: Epoch consolidation_balance_to_consume: Gwei earliest_consolidation_epoch: Epoch - pending_deposits: ProgressiveList[PendingDeposit] - pending_partial_withdrawals: ProgressiveList[PendingPartialWithdrawal] - pending_consolidations: ProgressiveList[PendingConsolidation] - proposer_lookahead: Vector[ValidatorIndex, (MIN_SEED_LOOKAHEAD + 1) * SLOTS_PER_EPOCH] - builders: ProgressiveList[Builder] + pending_deposits: PendingDeposits + pending_partial_withdrawals: PendingPartialWithdrawals + pending_consolidations: PendingConsolidations + proposer_lookahead: ProposerLookahead + builders: Builders next_withdrawal_builder_index: BuilderIndex - execution_payload_availability: BitVector[SLOTS_PER_HISTORICAL_ROOT] - builder_pending_payments: Vector[BuilderPendingPayment, 2 * SLOTS_PER_EPOCH] - builder_pending_withdrawals: ProgressiveList[BuilderPendingWithdrawal] + execution_payload_availability: ExecutionPayloadAvailability + builder_pending_payments: BuilderPendingPayments + builder_pending_withdrawals: BuilderPendingWithdrawals # [Modified in Heze:EIP7805] latest_execution_payload_bid: ExecutionPayloadBid - payload_expected_withdrawals: ProgressiveList[Withdrawal] - ptc_window: Vector[Vector[ValidatorIndex, PTC_SIZE], (2 + MIN_SEED_LOOKAHEAD) * SLOTS_PER_EPOCH] + payload_expected_withdrawals: Withdrawals + ptc_window: PTCWindow + + +- name: Blob#deneb + sources: [] + spec: | + + class Blob(ByteVector[BYTES_PER_FIELD_ELEMENT * FIELD_ELEMENTS_PER_BLOB]): # type: ignore + """ + A blob of data, encoded as a sequence of BLS scalar field elements. + """ - name: BlobIdentifier#deneb @@ -777,19 +984,70 @@ index: BlobIndex +- name: BlobKZGCommitments#deneb + sources: [] + spec: | + + class BlobKZGCommitments(List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK]): + """ + The KZG commitments to the blobs of a beacon block. + """ + + +- name: BlobKZGCommitments#gloas + sources: [] + spec: | + + class BlobKZGCommitments(ProgressiveList[KZGCommitment]): + """ + The KZG commitments to the blobs of a beacon block. + """ + + - name: BlobSidecar#deneb sources: - file: proto/prysm/v1alpha1/beacon_block.proto search: message BlobSidecar { spec: | - + class BlobSidecar(Container): index: BlobIndex blob: Blob kzg_commitment: KZGCommitment kzg_proof: KZGProof signed_block_header: SignedBeaconBlockHeader - kzg_commitment_inclusion_proof: Vector[Bytes32, KZG_COMMITMENT_INCLUSION_PROOF_DEPTH] + kzg_commitment_inclusion_proof: KZGCommitmentInclusionProof + + +- name: Blobs#deneb + sources: [] + spec: | + + class Blobs(List[Blob, MAX_BLOB_COMMITMENTS_PER_BLOCK]): + """ + The blobs of a single beacon block. + """ + + +- name: BlockAccessList#gloas + sources: [] + spec: | + + class BlockAccessList(ProgressiveByteList): + """ + The serialized block access list of an execution payload. + """ + + +- name: BlockRoots#phase0 + sources: [] + spec: | + + class BlockRoots(Vector[Root, SLOTS_PER_HISTORICAL_ROOT]): + """ + A rolling window of recent block roots, indexed by slot modulo + ``SLOTS_PER_HISTORICAL_ROOT``. + """ - name: Builder#gloas @@ -816,6 +1074,16 @@ signature: BLSSignature +- name: BuilderDepositRequests#gloas + sources: [] + spec: | + + class BuilderDepositRequests(ProgressiveList[BuilderDepositRequest]): + """ + The builder deposit requests pertaining to a single execution payload. + """ + + - name: BuilderExitRequest#gloas sources: [] spec: | @@ -825,6 +1093,16 @@ pubkey: BLSPubkey +- name: BuilderExitRequests#gloas + sources: [] + spec: | + + class BuilderExitRequests(ProgressiveList[BuilderExitRequest]): + """ + The builder exit requests pertaining to a single execution payload. + """ + + - name: BuilderPendingPayment#gloas sources: [] spec: | @@ -835,6 +1113,16 @@ proposer_index: ValidatorIndex +- name: BuilderPendingPayments#gloas + sources: [] + spec: | + + class BuilderPendingPayments(Vector[BuilderPendingPayment, 2 * SLOTS_PER_EPOCH]): # type: ignore + """ + The pending builder payments of the previous and current epoch. + """ + + - name: BuilderPendingWithdrawal#gloas sources: [] spec: | @@ -845,6 +1133,76 @@ builder_index: BuilderIndex +- name: BuilderPendingWithdrawals#gloas + sources: [] + spec: | + + class BuilderPendingWithdrawals(ProgressiveList[BuilderPendingWithdrawal]): + """ + The queue of builder withdrawals awaiting processing. + """ + + +- name: Builders#gloas + sources: [] + spec: | + + class Builders(ProgressiveList[Builder]): + """ + The builder registry. + """ + + +- name: Cell#fulu + sources: [] + spec: | + + class Cell(ByteVector[BYTES_PER_FIELD_ELEMENT * FIELD_ELEMENTS_PER_CELL]): # type: ignore + """ + The unit of extended blob data that has its own ``KZGProof``. + """ + + +- name: CellKZGProofs#fulu + sources: [] + spec: | + + class CellKZGProofs(List[KZGProof, FIELD_ELEMENTS_PER_EXT_BLOB * MAX_BLOB_COMMITMENTS_PER_BLOCK]): # type: ignore + """ + The KZG cell proofs for every blob in a block, one proof per cell. + """ + + +- name: Cells#fulu + sources: [] + spec: | + + class Cells(Vector[Cell, CELLS_PER_EXT_BLOB]): + """ + The cells of a single extended blob. + """ + + +- name: CellsBitList#fulu + sources: [] + spec: | + + class CellsBitList(BitList[MAX_BLOB_COMMITMENTS_PER_BLOCK]): + """ + A bitfield over the cells of a column, one bit per blob. + """ + + +- name: CellsBitList#gloas + sources: [] + spec: | + + class CellsBitList(ProgressiveBitList): + """ + A bitfield over the cells of a column, one bit per blob. + """ + + - name: Checkpoint#phase0 sources: - file: proto/eth/v1/attestation.proto @@ -856,6 +1214,16 @@ root: Root +- name: CommitteeBits#electra + sources: [] + spec: | + + class CommitteeBits(BitVector[MAX_COMMITTEES_PER_SLOT]): + """ + Bits marking which committees of a slot participate in an attestation. + """ + + - name: ConsolidationRequest#electra sources: - file: proto/engine/v1/electra.proto @@ -868,6 +1236,26 @@ target_pubkey: BLSPubkey +- name: ConsolidationRequests#electra + sources: [] + spec: | + + class ConsolidationRequests(List[ConsolidationRequest, MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD]): + """ + The consolidation requests pertaining to a single execution payload. + """ + + +- name: ConsolidationRequests#gloas + sources: [] + spec: | + + class ConsolidationRequests(ProgressiveList[ConsolidationRequest]): + """ + The consolidation requests pertaining to a single execution payload. + """ + + - name: ContributionAndProof#altair sources: - file: proto/prysm/v1alpha1/sync_committee.proto @@ -880,33 +1268,103 @@ selection_proof: BLSSignature +- name: CurrentSyncCommitteeBranch#altair + sources: [] + spec: | + + class CurrentSyncCommitteeBranch(Vector[Bytes32, floorlog2(CURRENT_SYNC_COMMITTEE_GINDEX)]): # type: ignore + """ + A Merkle branch proving ``current_sync_committee`` within ``BeaconState``. + """ + + +- name: CurrentSyncCommitteeBranch#electra + sources: [] + spec: | + + class CurrentSyncCommitteeBranch(Vector[Bytes32, floorlog2(CURRENT_SYNC_COMMITTEE_GINDEX_ELECTRA)]): # type: ignore + """ + A Merkle branch proving ``current_sync_committee`` within ``BeaconState``. + """ + + +- name: CurrentSyncCommitteeBranch#gloas + sources: [] + spec: | + + class CurrentSyncCommitteeBranch(Vector[Bytes32, floorlog2(CURRENT_SYNC_COMMITTEE_GINDEX_GLOAS)]): # type: ignore + """ + A Merkle branch proving ``current_sync_committee`` within ``BeaconState``. + """ + + +- name: CustodyColumnBits#gloas + sources: [] + spec: | + + class CustodyColumnBits(BitVector[NUMBER_OF_COLUMNS]): + """ + Bits marking the data columns custodied by a node, one bit per column. + """ + + +- name: DataColumn#fulu + sources: [] + spec: | + + class DataColumn(List[Cell, MAX_BLOB_COMMITMENTS_PER_BLOCK]): + """ + A column of the extended blob data matrix, with at most one cell per blob. + """ + + +- name: DataColumn#gloas + sources: [] + spec: | + + class DataColumn(ProgressiveList[Cell]): + """ + A column of the extended blob data matrix, with at most one cell per blob. + """ + + +- name: DataColumnIndices#fulu + sources: [] + spec: | + + class DataColumnIndices(List[ColumnIndex, NUMBER_OF_COLUMNS]): + """ + The indices of the data columns being requested. + """ + + - name: DataColumnSidecar#fulu sources: - file: proto/prysm/v1alpha1/data_columns.proto search: message DataColumnSidecar { spec: | - + class DataColumnSidecar(Container): index: ColumnIndex - column: List[Cell, MAX_BLOB_COMMITMENTS_PER_BLOCK] - kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK] - kzg_proofs: List[KZGProof, MAX_BLOB_COMMITMENTS_PER_BLOCK] + column: DataColumn + kzg_commitments: BlobKZGCommitments + kzg_proofs: KZGProofs signed_block_header: SignedBeaconBlockHeader - kzg_commitments_inclusion_proof: Vector[Bytes32, KZG_COMMITMENTS_INCLUSION_PROOF_DEPTH] + kzg_commitments_inclusion_proof: KZGCommitmentsInclusionProof - name: DataColumnSidecar#gloas sources: [] spec: | - + class DataColumnSidecar(Container): index: ColumnIndex # [Modified in Gloas:EIP7688] - column: ProgressiveList[Cell] + column: DataColumn # [Modified in Gloas:EIP7732] # Removed `kzg_commitments` # [Modified in Gloas:EIP7688] - kzg_proofs: ProgressiveList[KZGProof] + kzg_proofs: KZGProofs # [Modified in Gloas:EIP7732] # Removed `signed_block_header` # [Modified in Gloas:EIP7732] @@ -922,10 +1380,21 @@ - file: proto/prysm/v1alpha1/data_columns.proto search: message DataColumnsByRootIdentifier { spec: | - + class DataColumnsByRootIdentifier(Container): block_root: Root - columns: List[ColumnIndex, NUMBER_OF_COLUMNS] + columns: DataColumnIndices + + +- name: DataColumnsByRootIdentifiers#fulu + sources: [] + spec: | + + class DataColumnsByRootIdentifiers(List[DataColumnsByRootIdentifier, MAX_REQUEST_BLOCKS_DENEB]): # type: ignore + """ + The identifiers of the data column sidecars requested in a + ``DataColumnSidecarsByRoot`` request. + """ - name: Deposit#phase0 @@ -933,9 +1402,9 @@ - file: proto/eth/v1/beacon_block.proto search: message Deposit { spec: | - + class Deposit(Container): - proof: Vector[Bytes32, DEPOSIT_CONTRACT_TREE_DEPTH + 1] + proof: DepositProof data: DepositData @@ -952,6 +1421,16 @@ signature: BLSSignature +- name: DepositDataList#phase0 + sources: [] + spec: | + + class DepositDataList(List[DepositData, 2**DEPOSIT_CONTRACT_TREE_DEPTH]): # type: ignore + """ + The ``DepositData`` of deposits made to the deposit contract. + """ + + - name: DepositMessage#phase0 sources: - file: proto/prysm/v1alpha1/beacon_state.proto @@ -964,6 +1443,17 @@ amount: Gwei +- name: DepositProof#phase0 + sources: [] + spec: | + + class DepositProof(Vector[Bytes32, DEPOSIT_CONTRACT_TREE_DEPTH + 1]): # type: ignore + """ + A Merkle proof of a deposit in the deposit contract's tree. The node + beyond the tree depth accounts for the deposit count mix-in. + """ + + - name: DepositRequest#electra sources: - file: proto/engine/v1/electra.proto @@ -978,6 +1468,76 @@ index: Uint64 +- name: DepositRequests#electra + sources: [] + spec: | + + class DepositRequests(List[DepositRequest, MAX_DEPOSIT_REQUESTS_PER_PAYLOAD]): + """ + The deposit requests pertaining to a single execution payload. + """ + + +- name: DepositRequests#gloas + sources: [] + spec: | + + class DepositRequests(ProgressiveList[DepositRequest]): + """ + The deposit requests pertaining to a single execution payload. + """ + + +- name: Deposits#phase0 + sources: [] + spec: | + + class Deposits(List[Deposit, MAX_DEPOSITS]): + """ + The deposits included in a beacon block. + """ + + +- name: Deposits#gloas + sources: [] + spec: | + + class Deposits(ProgressiveList[Deposit]): + """ + The deposits included in a beacon block. + """ + + +- name: EpochParticipation#altair + sources: [] + spec: | + + class EpochParticipation(List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT]): + """ + The participation flags of each validator for an epoch. + """ + + +- name: EpochParticipation#gloas + sources: [] + spec: | + + class EpochParticipation(ProgressiveList[ParticipationFlags]): + """ + The participation flags of each validator for an epoch. + """ + + +- name: ErrorMessage#phase0 + sources: [] + spec: | + + class ErrorMessage(List[Byte, 256]): + """ + The error message of an unsuccessful response chunk. + """ + + - name: Eth1Block#phase0 sources: [] spec: | @@ -1000,27 +1560,58 @@ block_hash: Hash32 +- name: Eth1DataVotes#phase0 + sources: [] + spec: | + + class Eth1DataVotes(List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH]): # type: ignore + """ + The ``Eth1Data`` votes of the current voting period. + """ + + +- name: ExecutionBranch#capella + sources: [] + spec: | + + class ExecutionBranch(Vector[Bytes32, floorlog2(EXECUTION_PAYLOAD_GINDEX)]): # type: ignore + """ + A Merkle branch proving ``execution_payload`` within ``BeaconBlockBody``. + """ + + +- name: ExecutionBranch#gloas + sources: [] + spec: | + + class ExecutionBranch(Vector[Bytes32, floorlog2(EXECUTION_BLOCK_HASH_GINDEX_GLOAS)]): # type: ignore + """ + A Merkle branch proving the execution block hash within + ``BeaconBlockBody``. + """ + + - name: ExecutionPayload#bellatrix sources: - file: proto/engine/v1/execution_engine.proto search: message ExecutionPayload { spec: | - + class ExecutionPayload(Container): parent_hash: Hash32 fee_recipient: ExecutionAddress state_root: Bytes32 receipts_root: Bytes32 - logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM] + logs_bloom: LogsBloom prev_randao: Bytes32 block_number: Uint64 gas_limit: Uint64 gas_used: Uint64 timestamp: Uint64 - extra_data: ByteList[MAX_EXTRA_DATA_BYTES] + extra_data: ExtraData base_fee_per_gas: Uint256 block_hash: Hash32 - transactions: List[Transaction, MAX_TRANSACTIONS_PER_PAYLOAD] + transactions: Transactions - name: ExecutionPayload#capella @@ -1028,24 +1619,24 @@ - file: proto/engine/v1/execution_engine.proto search: message ExecutionPayloadCapella { spec: | - + class ExecutionPayload(Container): parent_hash: Hash32 fee_recipient: ExecutionAddress state_root: Bytes32 receipts_root: Bytes32 - logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM] + logs_bloom: LogsBloom prev_randao: Bytes32 block_number: Uint64 gas_limit: Uint64 gas_used: Uint64 timestamp: Uint64 - extra_data: ByteList[MAX_EXTRA_DATA_BYTES] + extra_data: ExtraData base_fee_per_gas: Uint256 block_hash: Hash32 - transactions: List[Transaction, MAX_TRANSACTIONS_PER_PAYLOAD] + transactions: Transactions # [New in Capella] - withdrawals: List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD] + withdrawals: Withdrawals - name: ExecutionPayload#deneb @@ -1053,23 +1644,23 @@ - file: proto/engine/v1/execution_engine.proto search: message ExecutionPayloadDeneb { spec: | - + class ExecutionPayload(Container): parent_hash: Hash32 fee_recipient: ExecutionAddress state_root: Bytes32 receipts_root: Bytes32 - logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM] + logs_bloom: LogsBloom prev_randao: Bytes32 block_number: Uint64 gas_limit: Uint64 gas_used: Uint64 timestamp: Uint64 - extra_data: ByteList[MAX_EXTRA_DATA_BYTES] + extra_data: ExtraData base_fee_per_gas: Uint256 block_hash: Hash32 - transactions: List[Transaction, MAX_TRANSACTIONS_PER_PAYLOAD] - withdrawals: List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD] + transactions: Transactions + withdrawals: Withdrawals # [New in Deneb:EIP4844] blob_gas_used: Uint64 # [New in Deneb:EIP4844] @@ -1079,25 +1670,25 @@ - name: ExecutionPayload#gloas sources: [] spec: | - + class ExecutionPayload(ProgressiveContainer(active_fields=[1] * 19)): # type: ignore parent_hash: Hash32 fee_recipient: ExecutionAddress state_root: Bytes32 receipts_root: Bytes32 - logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM] + logs_bloom: LogsBloom prev_randao: Bytes32 block_number: Uint64 gas_limit: Uint64 gas_used: Uint64 timestamp: Uint64 - extra_data: ByteList[MAX_EXTRA_DATA_BYTES] + extra_data: ExtraData base_fee_per_gas: Uint256 block_hash: Hash32 # [Modified in Gloas:EIP7688] - transactions: ProgressiveList[Transaction] + transactions: Transactions # [Modified in Gloas:EIP7688] - withdrawals: ProgressiveList[Withdrawal] + withdrawals: Withdrawals blob_gas_used: Uint64 excess_blob_gas: Uint64 # [New in Gloas:EIP7928] @@ -1106,10 +1697,21 @@ slot_number: Uint64 +- name: ExecutionPayloadAvailability#gloas + sources: [] + spec: | + + class ExecutionPayloadAvailability(BitVector[SLOTS_PER_HISTORICAL_ROOT]): + """ + Bits tracking payload availability for recent slots, indexed by slot + modulo ``SLOTS_PER_HISTORICAL_ROOT``. + """ + + - name: ExecutionPayloadBid#gloas sources: [] spec: | - + class ExecutionPayloadBid(ProgressiveContainer(active_fields=[1] * 12)): # type: ignore parent_block_hash: Hash32 parent_block_root: Root @@ -1121,14 +1723,14 @@ slot: Slot value: Gwei execution_payment: Gwei - blob_kzg_commitments: ProgressiveList[KZGCommitment] + blob_kzg_commitments: BlobKZGCommitments execution_requests_root: Root - name: ExecutionPayloadBid#heze sources: [] spec: | - + class ExecutionPayloadBid(ProgressiveContainer(active_fields=[1] * 13)): # type: ignore parent_block_hash: Hash32 parent_block_root: Root @@ -1140,10 +1742,10 @@ slot: Slot value: Gwei execution_payment: Gwei - blob_kzg_commitments: ProgressiveList[KZGCommitment] + blob_kzg_commitments: BlobKZGCommitments execution_requests_root: Root # [New in Heze:EIP7805] - inclusion_list_bits: BitVector[INCLUSION_LIST_COMMITTEE_SIZE] + inclusion_list_bits: InclusionListBits - name: ExecutionPayloadEnvelope#gloas @@ -1158,24 +1760,35 @@ parent_beacon_block_root: Root +- name: ExecutionPayloadEnvelopeRoots#gloas + sources: [] + spec: | + + class ExecutionPayloadEnvelopeRoots(List[Root, MAX_REQUEST_PAYLOADS]): # type: ignore + """ + The beacon block roots of the payload envelopes requested in an + ``ExecutionPayloadEnvelopesByRoot`` request. + """ + + - name: ExecutionPayloadHeader#bellatrix sources: - file: proto/engine/v1/execution_engine.proto search: message ExecutionPayloadHeader { spec: | - + class ExecutionPayloadHeader(Container): parent_hash: Hash32 fee_recipient: ExecutionAddress state_root: Bytes32 receipts_root: Bytes32 - logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM] + logs_bloom: LogsBloom prev_randao: Bytes32 block_number: Uint64 gas_limit: Uint64 gas_used: Uint64 timestamp: Uint64 - extra_data: ByteList[MAX_EXTRA_DATA_BYTES] + extra_data: ExtraData base_fee_per_gas: Uint256 block_hash: Hash32 transactions_root: Root @@ -1186,19 +1799,19 @@ - file: proto/engine/v1/execution_engine.proto search: message ExecutionPayloadHeaderCapella { spec: | - + class ExecutionPayloadHeader(Container): parent_hash: Hash32 fee_recipient: ExecutionAddress state_root: Bytes32 receipts_root: Bytes32 - logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM] + logs_bloom: LogsBloom prev_randao: Bytes32 block_number: Uint64 gas_limit: Uint64 gas_used: Uint64 timestamp: Uint64 - extra_data: ByteList[MAX_EXTRA_DATA_BYTES] + extra_data: ExtraData base_fee_per_gas: Uint256 block_hash: Hash32 transactions_root: Root @@ -1211,19 +1824,19 @@ - file: proto/engine/v1/execution_engine.proto search: message ExecutionPayloadHeaderDeneb { spec: | - + class ExecutionPayloadHeader(Container): parent_hash: Hash32 fee_recipient: ExecutionAddress state_root: Bytes32 receipts_root: Bytes32 - logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM] + logs_bloom: LogsBloom prev_randao: Bytes32 block_number: Uint64 gas_limit: Uint64 gas_used: Uint64 timestamp: Uint64 - extra_data: ByteList[MAX_EXTRA_DATA_BYTES] + extra_data: ExtraData base_fee_per_gas: Uint256 block_hash: Hash32 transactions_root: Root @@ -1263,6 +1876,49 @@ builder_exits: BuilderExitRequests +- name: ExtraData#bellatrix + sources: [] + spec: | + + class ExtraData(ByteList[MAX_EXTRA_DATA_BYTES]): + """ + Arbitrary extra data included in an execution payload. + """ + + +- name: FinalityBranch#altair + sources: [] + spec: | + + class FinalityBranch(Vector[Bytes32, floorlog2(FINALIZED_ROOT_GINDEX)]): # type: ignore + """ + A Merkle branch proving ``finalized_checkpoint.root`` within + ``BeaconState``. + """ + + +- name: FinalityBranch#electra + sources: [] + spec: | + + class FinalityBranch(Vector[Bytes32, floorlog2(FINALIZED_ROOT_GINDEX_ELECTRA)]): # type: ignore + """ + A Merkle branch proving ``finalized_checkpoint.root`` within + ``BeaconState``. + """ + + +- name: FinalityBranch#gloas + sources: [] + spec: | + + class FinalityBranch(Vector[Bytes32, floorlog2(FINALIZED_ROOT_GINDEX_GLOAS)]): # type: ignore + """ + A Merkle branch proving ``finalized_checkpoint.root`` within + ``BeaconState``. + """ + + - name: Fork#phase0 sources: - file: proto/prysm/v1alpha1/beacon_core_types.proto @@ -1291,10 +1947,30 @@ - file: proto/prysm/v1alpha1/beacon_state.proto search: message HistoricalBatch { spec: | - + class HistoricalBatch(Container): - block_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT] - state_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT] + block_roots: BlockRoots + state_roots: StateRoots + + +- name: HistoricalRoots#phase0 + sources: [] + spec: | + + class HistoricalRoots(List[Root, HISTORICAL_ROOTS_LIMIT]): + """ + The roots of ``HistoricalBatch`` objects. + """ + + +- name: HistoricalSummaries#capella + sources: [] + spec: | + + class HistoricalSummaries(List[HistoricalSummary, HISTORICAL_ROOTS_LIMIT]): + """ + Summaries of the chain's block and state root history. + """ - name: HistoricalSummary#capella @@ -1308,15 +1984,56 @@ state_summary_root: Root +- name: InactivityScores#altair + sources: [] + spec: | + + class InactivityScores(List[Uint64, VALIDATOR_REGISTRY_LIMIT]): + """ + Each validator's inactivity score, tracking missed timely target votes. + """ + + +- name: InactivityScores#gloas + sources: [] + spec: | + + class InactivityScores(ProgressiveList[Uint64]): + """ + Each validator's inactivity score, tracking missed timely target votes. + """ + + - name: InclusionList#heze sources: [] spec: | - + class InclusionList(Container): slot: Slot validator_index: ValidatorIndex - inclusion_list_committee_root: Root - transactions: ProgressiveList[Transaction] + dependent_root: Root + transactions: Transactions + + +- name: InclusionListBits#heze + sources: [] + spec: | + + class InclusionListBits(BitVector[INCLUSION_LIST_COMMITTEE_SIZE]): + """ + A bitfield over the inclusion list committee, one bit per member in + committee order. + """ + + +- name: InclusionListCommittee#heze + sources: [] + spec: | + + class InclusionListCommittee(Vector[ValidatorIndex, INCLUSION_LIST_COMMITTEE_SIZE]): + """ + The inclusion list committee of a slot. + """ - name: IndexedAttestation#phase0 @@ -1324,9 +2041,9 @@ - file: proto/prysm/v1alpha1/beacon_block.proto search: message IndexedAttestation { spec: | - + class IndexedAttestation(Container): - attesting_indices: List[ValidatorIndex, MAX_VALIDATORS_PER_COMMITTEE] + attesting_indices: AttestingIndices data: AttestationData signature: BLSSignature @@ -1359,13 +2076,65 @@ - name: IndexedPayloadAttestation#gloas sources: [] spec: | - + class IndexedPayloadAttestation(ProgressiveContainer(active_fields=[1] * 3)): # type: ignore - attesting_indices: List[ValidatorIndex, PTC_SIZE] + attesting_indices: PTCAttestingIndices data: PayloadAttestationData signature: BLSSignature +- name: JustificationBits#phase0 + sources: [] + spec: | + + class JustificationBits(BitVector[JUSTIFICATION_BITS_LENGTH]): + """ + The justification status of the last ``JUSTIFICATION_BITS_LENGTH`` epochs. + """ + + +- name: KZGCommitmentInclusionProof#deneb + sources: [] + spec: | + + class KZGCommitmentInclusionProof(Vector[Bytes32, KZG_COMMITMENT_INCLUSION_PROOF_DEPTH]): + """ + A Merkle branch proving a blob's KZG commitment within + ``BeaconBlockBody``. + """ + + +- name: KZGCommitmentsInclusionProof#fulu + sources: [] + spec: | + + class KZGCommitmentsInclusionProof(Vector[Bytes32, KZG_COMMITMENTS_INCLUSION_PROOF_DEPTH]): + """ + A Merkle branch proving a block's blob KZG commitments within + ``BeaconBlockBody``. + """ + + +- name: KZGProofs#deneb + sources: [] + spec: | + + class KZGProofs(List[KZGProof, MAX_BLOB_COMMITMENTS_PER_BLOCK]): + """ + A list of KZG proofs, one for each blob or cell being proven. + """ + + +- name: KZGProofs#gloas + sources: [] + spec: | + + class KZGProofs(ProgressiveList[KZGProof]): + """ + The KZG cell proofs of the cells held by a data column. + """ + + - name: LightClientBootstrap#altair sources: - file: proto/prysm/v1alpha1/light_client.proto @@ -1524,6 +2293,26 @@ signature_slot: Slot +- name: LightClientUpdates#altair + sources: [] + spec: | + + class LightClientUpdates(List[LightClientUpdate, MAX_REQUEST_LIGHT_CLIENT_UPDATES]): + """ + Light client updates returned in a ``LightClientUpdatesByRange`` response. + """ + + +- name: LogsBloom#bellatrix + sources: [] + spec: | + + class LogsBloom(ByteVector[BYTES_PER_LOGS_BLOOM]): + """ + A Bloom filter aggregating the logs emitted by an execution payload. + """ + + - name: MatrixEntry#fulu sources: [] spec: | @@ -1535,6 +2324,89 @@ row_index: RowIndex +- name: NextSyncCommitteeBranch#altair + sources: [] + spec: | + + class NextSyncCommitteeBranch(Vector[Bytes32, floorlog2(NEXT_SYNC_COMMITTEE_GINDEX)]): # type: ignore + """ + A Merkle branch proving ``next_sync_committee`` within ``BeaconState``. + """ + + +- name: NextSyncCommitteeBranch#electra + sources: [] + spec: | + + class NextSyncCommitteeBranch(Vector[Bytes32, floorlog2(NEXT_SYNC_COMMITTEE_GINDEX_ELECTRA)]): # type: ignore + """ + A Merkle branch proving ``next_sync_committee`` within ``BeaconState``. + """ + + +- name: NextSyncCommitteeBranch#gloas + sources: [] + spec: | + + class NextSyncCommitteeBranch(Vector[Bytes32, floorlog2(NEXT_SYNC_COMMITTEE_GINDEX_GLOAS)]): # type: ignore + """ + A Merkle branch proving ``next_sync_committee`` within ``BeaconState``. + """ + + +- name: OptionalPartialDataColumnHeader#fulu + sources: [] + spec: | + + class OptionalPartialDataColumnHeader(List[PartialDataColumnHeader, 1]): + """ + A header that may or may not be present, encoded as a list of length zero + or one. + """ + + +- name: PTC#gloas + sources: [] + spec: | + + class PTC(Vector[ValidatorIndex, PTC_SIZE]): + """ + The payload timeliness committee of a slot. + """ + + +- name: PTCAttestingIndices#gloas + sources: [] + spec: | + + class PTCAttestingIndices(List[ValidatorIndex, PTC_SIZE]): + """ + The indices of the PTC members participating in a payload attestation. + """ + + +- name: PTCBits#gloas + sources: [] + spec: | + + class PTCBits(BitVector[PTC_SIZE]): + """ + The participation bits of the payload timeliness committee, one bit per + member in committee order. + """ + + +- name: PTCWindow#gloas + sources: [] + spec: | + + class PTCWindow(Vector[PTC, (2 + MIN_SEED_LOOKAHEAD) * SLOTS_PER_EPOCH]): # type: ignore + """ + A rolling window of payload timeliness committees for the previous, + current, and lookahead epochs. + """ + + - name: PartialDataColumnGroupID#fulu sources: [] spec: | @@ -1556,60 +2428,71 @@ - name: PartialDataColumnHeader#fulu sources: [] spec: | - + class PartialDataColumnHeader(Container): - kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK] + kzg_commitments: BlobKZGCommitments signed_block_header: SignedBeaconBlockHeader - kzg_commitments_inclusion_proof: Vector[Bytes32, KZG_COMMITMENTS_INCLUSION_PROOF_DEPTH] + kzg_commitments_inclusion_proof: KZGCommitmentsInclusionProof - name: PartialDataColumnHeader#gloas sources: [] spec: | - + class PartialDataColumnHeader(Container): - kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK] + kzg_commitments: BlobKZGCommitments signed_block_header: SignedBeaconBlockHeader - kzg_commitments_inclusion_proof: Vector[Bytes32, KZG_COMMITMENTS_INCLUSION_PROOF_DEPTH] + kzg_commitments_inclusion_proof: KZGCommitmentsInclusionProof - name: PartialDataColumnPartsMetadata#fulu sources: [] spec: | - + + class PartialDataColumnPartsMetadata(Container): + available: CellsBitList + requests: CellsBitList + + +- name: PartialDataColumnPartsMetadata#gloas + sources: [] + spec: | + class PartialDataColumnPartsMetadata(Container): - available: BitList[MAX_BLOB_COMMITMENTS_PER_BLOCK] - requests: BitList[MAX_BLOB_COMMITMENTS_PER_BLOCK] + # [Modified in Gloas:EIP7688] + available: CellsBitList + # [Modified in Gloas:EIP7688] + requests: CellsBitList - name: PartialDataColumnSidecar#fulu sources: [] spec: | - + class PartialDataColumnSidecar(Container): - cells_present_bitmap: BitList[MAX_BLOB_COMMITMENTS_PER_BLOCK] - partial_column: List[Cell, MAX_BLOB_COMMITMENTS_PER_BLOCK] - kzg_proofs: List[KZGProof, MAX_BLOB_COMMITMENTS_PER_BLOCK] + cells_present_bitmap: CellsBitList + partial_column: DataColumn + kzg_proofs: KZGProofs # Optional header, only sent on eager pushes - header: List[PartialDataColumnHeader, 1] + header: OptionalPartialDataColumnHeader - name: PartialDataColumnSidecar#gloas sources: [] spec: | - + class PartialDataColumnSidecar(Container): - cells_present_bitmap: ProgressiveBitList - partial_column: ProgressiveList[Cell] - kzg_proofs: ProgressiveList[KZGProof] + cells_present_bitmap: CellsBitList + partial_column: DataColumn + kzg_proofs: KZGProofs - name: PayloadAttestation#gloas sources: [] spec: | - + class PayloadAttestation(ProgressiveContainer(active_fields=[1] * 3)): # type: ignore - aggregation_bits: BitVector[PTC_SIZE] + aggregation_bits: PTCBits data: PayloadAttestationData signature: BLSSignature @@ -1635,19 +2518,39 @@ signature: BLSSignature +- name: PayloadAttestations#gloas + sources: [] + spec: | + + class PayloadAttestations(ProgressiveList[PayloadAttestation]): + """ + The payload attestations included in a beacon block. + """ + + - name: PendingAttestation#phase0 sources: - file: proto/prysm/v1alpha1/beacon_state.proto search: message PendingAttestation { spec: | - + class PendingAttestation(Container): - aggregation_bits: BitList[MAX_VALIDATORS_PER_COMMITTEE] + aggregation_bits: AggregationBits data: AttestationData inclusion_delay: Slot proposer_index: ValidatorIndex +- name: PendingAttestations#phase0 + sources: [] + spec: | + + class PendingAttestations(List[PendingAttestation, MAX_ATTESTATIONS * SLOTS_PER_EPOCH]): # type: ignore + """ + The attestations included in blocks during an epoch. + """ + + - name: PendingConsolidation#electra sources: - file: proto/prysm/v1alpha1/eip_7251.proto @@ -1659,6 +2562,26 @@ target_index: ValidatorIndex +- name: PendingConsolidations#electra + sources: [] + spec: | + + class PendingConsolidations(List[PendingConsolidation, PENDING_CONSOLIDATIONS_LIMIT]): + """ + The queue of consolidations awaiting processing. + """ + + +- name: PendingConsolidations#gloas + sources: [] + spec: | + + class PendingConsolidations(ProgressiveList[PendingConsolidation]): + """ + The queue of consolidations awaiting processing. + """ + + - name: PendingDeposit#electra sources: - file: proto/prysm/v1alpha1/eip_7251.proto @@ -1673,6 +2596,26 @@ slot: Slot +- name: PendingDeposits#electra + sources: [] + spec: | + + class PendingDeposits(List[PendingDeposit, PENDING_DEPOSITS_LIMIT]): + """ + The queue of deposits awaiting processing. + """ + + +- name: PendingDeposits#gloas + sources: [] + spec: | + + class PendingDeposits(ProgressiveList[PendingDeposit]): + """ + The queue of deposits awaiting processing. + """ + + - name: PendingPartialWithdrawal#electra sources: - file: proto/prysm/v1alpha1/eip_7251.proto @@ -1685,6 +2628,26 @@ withdrawable_epoch: Epoch +- name: PendingPartialWithdrawals#electra + sources: [] + spec: | + + class PendingPartialWithdrawals(List[PendingPartialWithdrawal, PENDING_PARTIAL_WITHDRAWALS_LIMIT]): + """ + The queue of partial withdrawals awaiting processing. + """ + + +- name: PendingPartialWithdrawals#gloas + sources: [] + spec: | + + class PendingPartialWithdrawals(ProgressiveList[PendingPartialWithdrawal]): + """ + The queue of partial withdrawals awaiting processing. + """ + + - name: PowBlock#bellatrix sources: - file: proto/prysm/v1alpha1/beacon_state.proto @@ -1697,6 +2660,37 @@ total_difficulty: Uint256 +- name: Proofs#fulu + sources: [] + spec: | + + class Proofs(Vector[KZGProof, CELLS_PER_EXT_BLOB]): + """ + The KZG proofs for the cells of a single extended blob. + """ + + +- name: ProposerIndices#fulu + sources: [] + spec: | + + class ProposerIndices(Vector[ValidatorIndex, SLOTS_PER_EPOCH]): + """ + The proposer indices for every slot of a single epoch. + """ + + +- name: ProposerLookahead#fulu + sources: [] + spec: | + + class ProposerLookahead(Vector[ValidatorIndex, (MIN_SEED_LOOKAHEAD + 1) * SLOTS_PER_EPOCH]): # type: ignore + """ + The precomputed proposer indices for the current and next + ``MIN_SEED_LOOKAHEAD`` epochs. + """ + + - name: ProposerPreferences#gloas sources: [] spec: | @@ -1720,6 +2714,37 @@ signed_header_2: SignedBeaconBlockHeader +- name: ProposerSlashings#phase0 + sources: [] + spec: | + + class ProposerSlashings(List[ProposerSlashing, MAX_PROPOSER_SLASHINGS]): + """ + The proposer slashings included in a beacon block. + """ + + +- name: ProposerSlashings#gloas + sources: [] + spec: | + + class ProposerSlashings(ProgressiveList[ProposerSlashing]): + """ + The proposer slashings included in a beacon block. + """ + + +- name: RandaoMixes#phase0 + sources: [] + spec: | + + class RandaoMixes(Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR]): + """ + A rolling window of accumulated RANDAO mixes, indexed by epoch modulo + ``EPOCHS_PER_HISTORICAL_VECTOR``. + """ + + - name: SignedAggregateAndProof#phase0 sources: - file: proto/prysm/v1alpha1/attestation.proto @@ -1776,6 +2801,28 @@ signature: BLSSignature +- name: SignedBeaconBlocks#phase0 + sources: [] + spec: | + + class SignedBeaconBlocks(List[SignedBeaconBlock, MAX_REQUEST_BLOCKS]): # type: ignore + """ + Signed beacon blocks returned in a ``BeaconBlocksByRange`` or + ``BeaconBlocksByRoot`` response. + """ + + +- name: SignedBeaconBlocks#deneb + sources: [] + spec: | + + class SignedBeaconBlocks(List[SignedBeaconBlock, MAX_REQUEST_BLOCKS_DENEB]): # type: ignore + """ + Signed beacon blocks returned in a ``BeaconBlocksByRange`` or + ``BeaconBlocksByRoot`` response. + """ + + - name: SignedContributionAndProof#altair sources: - file: proto/prysm/v1alpha1/sync_committee.proto @@ -1815,6 +2862,18 @@ signature: BLSSignature +- name: SignedExecutionPayloadEnvelopes#gloas + sources: [] + spec: | + + class SignedExecutionPayloadEnvelopes(List[SignedExecutionPayloadEnvelope, MAX_REQUEST_PAYLOADS]): # type: ignore + """ + Signed execution payload envelopes returned in an + ``ExecutionPayloadEnvelopesByRange`` or + ``ExecutionPayloadEnvelopesByRoot`` response. + """ + + - name: SignedInclusionList#heze sources: [] spec: | @@ -1824,6 +2883,17 @@ signature: BLSSignature +- name: SignedInclusionLists#heze + sources: [] + spec: | + + class SignedInclusionLists(List[SignedInclusionList, MAX_REQUEST_INCLUSION_LIST]): # type: ignore + """ + Signed inclusion lists returned in an ``InclusionListsByIndices`` + response. + """ + + - name: SignedProposerPreferences#gloas sources: [] spec: | @@ -1868,14 +2938,36 @@ signature: BLSSignature +- name: Slashings#phase0 + sources: [] + spec: | + + class Slashings(Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR]): + """ + Per-epoch sums of slashed effective balances, indexed by epoch modulo + ``EPOCHS_PER_SLASHINGS_VECTOR``. + """ + + +- name: StateRoots#phase0 + sources: [] + spec: | + + class StateRoots(Vector[Root, SLOTS_PER_HISTORICAL_ROOT]): + """ + A rolling window of recent state roots, indexed by slot modulo + ``SLOTS_PER_HISTORICAL_ROOT``. + """ + + - name: SyncAggregate#altair sources: - file: proto/prysm/v1alpha1/beacon_core_types.proto search: message SyncAggregate { spec: | - + class SyncAggregate(Container): - sync_committee_bits: BitVector[SYNC_COMMITTEE_SIZE] + sync_committee_bits: SyncCommitteeBits sync_committee_signature: BLSSignature @@ -1895,23 +2987,34 @@ - file: proto/prysm/v1alpha1/beacon_core_types.proto search: message SyncCommittee { spec: | - + class SyncCommittee(Container): - pubkeys: Vector[BLSPubkey, SYNC_COMMITTEE_SIZE] + pubkeys: SyncCommitteePubkeys aggregate_pubkey: BLSPubkey +- name: SyncCommitteeBits#altair + sources: [] + spec: | + + class SyncCommitteeBits(BitVector[SYNC_COMMITTEE_SIZE]): + """ + The participation bits of the sync committee, one bit per member in + committee order. + """ + + - name: SyncCommitteeContribution#altair sources: - file: proto/prysm/v1alpha1/sync_committee.proto search: message SyncCommitteeContribution { spec: | - + class SyncCommitteeContribution(Container): slot: Slot beacon_block_root: Root subcommittee_index: Uint64 - aggregation_bits: BitVector[SYNC_COMMITTEE_SIZE // SYNC_COMMITTEE_SUBNET_COUNT] + aggregation_bits: SyncSubcommitteeBits signature: BLSSignature @@ -1928,6 +3031,79 @@ signature: BLSSignature +- name: SyncCommitteePubkeys#altair + sources: [] + spec: | + + class SyncCommitteePubkeys(Vector[BLSPubkey, SYNC_COMMITTEE_SIZE]): + """ + The public keys of the sync committee members, in committee order. + """ + + +- name: SyncSubcommitteeBits#altair + sources: [] + spec: | + + class SyncSubcommitteeBits(BitVector[SYNC_COMMITTEE_SIZE // SYNC_COMMITTEE_SUBNET_COUNT]): # type: ignore + """ + The participation bits of a single sync subcommittee, one bit per member + in subcommittee order. + """ + + +- name: Syncnets#altair + sources: [] + spec: | + + class Syncnets(BitVector[SYNC_COMMITTEE_SUBNET_COUNT]): + """ + The sync committee subnets a node is subscribed to, one bit per subnet. + """ + + +- name: Transaction#bellatrix + sources: [] + spec: | + + class Transaction(ByteList[MAX_BYTES_PER_TRANSACTION]): + """ + An opaque execution-layer transaction, either a typed transaction + envelope or a legacy RLP-encoded transaction. + """ + + +- name: Transaction#gloas + sources: [] + spec: | + + class Transaction(ProgressiveByteList): + """ + An opaque execution-layer transaction, either a typed transaction + envelope or a legacy RLP-encoded transaction. + """ + + +- name: Transactions#bellatrix + sources: [] + spec: | + + class Transactions(List[Transaction, MAX_TRANSACTIONS_PER_PAYLOAD]): + """ + A list of execution-layer transactions. + """ + + +- name: Transactions#gloas + sources: [] + spec: | + + class Transactions(ProgressiveList[Transaction]): + """ + A list of execution-layer transactions. + """ + + - name: Validator#phase0 sources: - file: proto/prysm/v1alpha1/beacon_core_types.proto @@ -1945,6 +3121,26 @@ withdrawable_epoch: Epoch +- name: Validators#phase0 + sources: [] + spec: | + + class Validators(List[Validator, VALIDATOR_REGISTRY_LIMIT]): + """ + The validator registry. + """ + + +- name: Validators#gloas + sources: [] + spec: | + + class Validators(ProgressiveList[Validator]): + """ + The validator registry. + """ + + - name: VoluntaryExit#phase0 sources: - file: proto/eth/v1/beacon_block.proto @@ -1956,6 +3152,26 @@ validator_index: ValidatorIndex +- name: VoluntaryExits#phase0 + sources: [] + spec: | + + class VoluntaryExits(List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS]): + """ + The signed voluntary exits included in a beacon block. + """ + + +- name: VoluntaryExits#gloas + sources: [] + spec: | + + class VoluntaryExits(ProgressiveList[SignedVoluntaryExit]): + """ + The signed voluntary exits included in a beacon block. + """ + + - name: Withdrawal#capella sources: - file: proto/engine/v1/execution_engine.proto @@ -1980,3 +3196,43 @@ validator_pubkey: BLSPubkey amount: Gwei + +- name: WithdrawalRequests#electra + sources: [] + spec: | + + class WithdrawalRequests(List[WithdrawalRequest, MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD]): + """ + The withdrawal requests pertaining to a single execution payload. + """ + + +- name: WithdrawalRequests#gloas + sources: [] + spec: | + + class WithdrawalRequests(ProgressiveList[WithdrawalRequest]): + """ + The withdrawal requests pertaining to a single execution payload. + """ + + +- name: Withdrawals#capella + sources: [] + spec: | + + class Withdrawals(List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD]): + """ + A list of withdrawals. + """ + + +- name: Withdrawals#gloas + sources: [] + spec: | + + class Withdrawals(ProgressiveList[Withdrawal]): + """ + A list of withdrawals. + """ + diff --git a/specrefs/dataclasses.yml b/specrefs/dataclasses.yml index faf1ce8e9d7f..961b3bf100e0 100644 --- a/specrefs/dataclasses.yml +++ b/specrefs/dataclasses.yml @@ -13,11 +13,11 @@ search: ^message BlobsBundle\s*\{ regex: true spec: | - + class BlobsBundle: - commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK] - proofs: List[KZGProof, MAX_BLOB_COMMITMENTS_PER_BLOCK] - blobs: List[Blob, MAX_BLOB_COMMITMENTS_PER_BLOCK] + commitments: BlobKZGCommitments + proofs: KZGProofs + blobs: Blobs - name: BlobsBundle#fulu @@ -26,12 +26,12 @@ search: ^message BlobsBundleV2 regex: true spec: | - + class BlobsBundle: - commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK] + commitments: BlobKZGCommitments # [Modified in Fulu:EIP7594] - proofs: List[KZGProof, FIELD_ELEMENTS_PER_EXT_BLOB * MAX_BLOB_COMMITMENTS_PER_BLOCK] - blobs: List[Blob, MAX_BLOB_COMMITMENTS_PER_BLOCK] + proofs: CellKZGProofs + blobs: Blobs - name: ExpectedWithdrawals#capella @@ -182,18 +182,23 @@ execution_requests: Sequence[bytes] +- name: InclusionListEntry#heze + sources: [] + spec: | + + @dataclass(eq=True, frozen=True) + class InclusionListEntry: + signed_inclusion_list: SignedInclusionList + timely: Boolean + + - name: InclusionListStore#heze sources: [] spec: | - + class InclusionListStore: - inclusion_lists: DefaultDict[Root, Dict[Root, SignedInclusionList]] = field( - default_factory=lambda: defaultdict(dict) - ) - inclusion_list_timeliness: Dict[Root, Boolean] = field(default_factory=dict) - equivocators: DefaultDict[Root, Set[ValidatorIndex]] = field( - default_factory=lambda: defaultdict(set) - ) + inclusion_lists: DefaultDict[Tuple[Slot, Root], Dict[ValidatorIndex, InclusionListEntry]] + equivocators: DefaultDict[Tuple[Slot, Root], Set[ValidatorIndex]] - name: LatestMessage#phase0 @@ -292,12 +297,12 @@ - name: OptimisticStore#bellatrix sources: [] spec: | - - class OptimisticStore(object): + + class OptimisticStore: optimistic_roots: Set[Root] head_block_root: Root - blocks: Dict[Root, BeaconBlock] = field(default_factory=dict) - block_states: Dict[Root, BeaconState] = field(default_factory=dict) + blocks: Dict[Root, BeaconBlock] + block_states: Dict[Root, BeaconState] - name: PayloadAttributes#bellatrix @@ -379,31 +384,31 @@ - name: Seen#phase0 sources: [] spec: | - + class Seen: - proposer_slots: Set[Tuple[ValidatorIndex, Slot]] - aggregator_epochs: Set[Tuple[ValidatorIndex, Epoch]] + proposer_slots: Set[Tuple[Slot, ValidatorIndex]] + aggregator_epochs: Set[Tuple[Epoch, ValidatorIndex]] aggregate_data_roots: Dict[Root, Set[Tuple[Boolean, ...]]] voluntary_exit_indices: Set[ValidatorIndex] proposer_slashing_indices: Set[ValidatorIndex] attester_slashing_indices: Set[ValidatorIndex] - attestation_validator_epochs: Set[Tuple[ValidatorIndex, Epoch]] + attestation_validator_epochs: Set[Tuple[Epoch, ValidatorIndex]] - name: Seen#altair sources: [] spec: | - + class Seen: - proposer_slots: Set[Tuple[ValidatorIndex, Slot]] - aggregator_epochs: Set[Tuple[ValidatorIndex, Epoch]] + proposer_slots: Set[Tuple[Slot, ValidatorIndex]] + aggregator_epochs: Set[Tuple[Epoch, ValidatorIndex]] aggregate_data_roots: Dict[Root, Set[Tuple[Boolean, ...]]] voluntary_exit_indices: Set[ValidatorIndex] proposer_slashing_indices: Set[ValidatorIndex] attester_slashing_indices: Set[ValidatorIndex] - attestation_validator_epochs: Set[Tuple[ValidatorIndex, Epoch]] + attestation_validator_epochs: Set[Tuple[Epoch, ValidatorIndex]] # [New in Altair] - sync_contribution_aggregator_slots: Set[Tuple[ValidatorIndex, Slot, Uint64]] + sync_contribution_aggregator_slots: Set[Tuple[Slot, ValidatorIndex, Uint64]] # [New in Altair] sync_contribution_data: Dict[Tuple[Slot, Root, Uint64], Set[Tuple[Boolean, ...]]] # [New in Altair] @@ -413,16 +418,16 @@ - name: Seen#capella sources: [] spec: | - + class Seen: - proposer_slots: Set[Tuple[ValidatorIndex, Slot]] - aggregator_epochs: Set[Tuple[ValidatorIndex, Epoch]] + proposer_slots: Set[Tuple[Slot, ValidatorIndex]] + aggregator_epochs: Set[Tuple[Epoch, ValidatorIndex]] aggregate_data_roots: Dict[Root, Set[Tuple[Boolean, ...]]] voluntary_exit_indices: Set[ValidatorIndex] proposer_slashing_indices: Set[ValidatorIndex] attester_slashing_indices: Set[ValidatorIndex] - attestation_validator_epochs: Set[Tuple[ValidatorIndex, Epoch]] - sync_contribution_aggregator_slots: Set[Tuple[ValidatorIndex, Slot, Uint64]] + attestation_validator_epochs: Set[Tuple[Epoch, ValidatorIndex]] + sync_contribution_aggregator_slots: Set[Tuple[Slot, ValidatorIndex, Uint64]] sync_contribution_data: Dict[Tuple[Slot, Root, Uint64], Set[Tuple[Boolean, ...]]] sync_message_validator_slots: Set[Tuple[Slot, ValidatorIndex, Uint64]] # [New in Capella] @@ -432,16 +437,16 @@ - name: Seen#deneb sources: [] spec: | - + class Seen: - proposer_slots: Set[Tuple[ValidatorIndex, Slot]] - aggregator_epochs: Set[Tuple[ValidatorIndex, Epoch]] + proposer_slots: Set[Tuple[Slot, ValidatorIndex]] + aggregator_epochs: Set[Tuple[Epoch, ValidatorIndex]] aggregate_data_roots: Dict[Root, Set[Tuple[Boolean, ...]]] voluntary_exit_indices: Set[ValidatorIndex] proposer_slashing_indices: Set[ValidatorIndex] attester_slashing_indices: Set[ValidatorIndex] - attestation_validator_epochs: Set[Tuple[ValidatorIndex, Epoch]] - sync_contribution_aggregator_slots: Set[Tuple[ValidatorIndex, Slot, Uint64]] + attestation_validator_epochs: Set[Tuple[Epoch, ValidatorIndex]] + sync_contribution_aggregator_slots: Set[Tuple[Slot, ValidatorIndex, Uint64]] sync_contribution_data: Dict[Tuple[Slot, Root, Uint64], Set[Tuple[Boolean, ...]]] sync_message_validator_slots: Set[Tuple[Slot, ValidatorIndex, Uint64]] bls_to_execution_change_indices: Set[ValidatorIndex] @@ -452,17 +457,17 @@ - name: Seen#electra sources: [] spec: | - + class Seen: - proposer_slots: Set[Tuple[ValidatorIndex, Slot]] - aggregator_epochs: Set[Tuple[ValidatorIndex, Epoch]] + proposer_slots: Set[Tuple[Slot, ValidatorIndex]] + aggregator_epochs: Set[Tuple[Epoch, ValidatorIndex]] # [Modified in Electra:EIP7549] aggregate_data_roots: Dict[Tuple[Root, CommitteeIndex], Set[Tuple[Boolean, ...]]] voluntary_exit_indices: Set[ValidatorIndex] proposer_slashing_indices: Set[ValidatorIndex] attester_slashing_indices: Set[ValidatorIndex] - attestation_validator_epochs: Set[Tuple[ValidatorIndex, Epoch]] - sync_contribution_aggregator_slots: Set[Tuple[ValidatorIndex, Slot, Uint64]] + attestation_validator_epochs: Set[Tuple[Epoch, ValidatorIndex]] + sync_contribution_aggregator_slots: Set[Tuple[Slot, ValidatorIndex, Uint64]] sync_contribution_data: Dict[Tuple[Slot, Root, Uint64], Set[Tuple[Boolean, ...]]] sync_message_validator_slots: Set[Tuple[Slot, ValidatorIndex, Uint64]] bls_to_execution_change_indices: Set[ValidatorIndex] @@ -472,16 +477,16 @@ - name: Seen#fulu sources: [] spec: | - + class Seen: - proposer_slots: Set[Tuple[ValidatorIndex, Slot]] - aggregator_epochs: Set[Tuple[ValidatorIndex, Epoch]] + proposer_slots: Set[Tuple[Slot, ValidatorIndex]] + aggregator_epochs: Set[Tuple[Epoch, ValidatorIndex]] aggregate_data_roots: Dict[Tuple[Root, CommitteeIndex], Set[Tuple[Boolean, ...]]] voluntary_exit_indices: Set[ValidatorIndex] proposer_slashing_indices: Set[ValidatorIndex] attester_slashing_indices: Set[ValidatorIndex] - attestation_validator_epochs: Set[Tuple[ValidatorIndex, Epoch]] - sync_contribution_aggregator_slots: Set[Tuple[ValidatorIndex, Slot, Uint64]] + attestation_validator_epochs: Set[Tuple[Epoch, ValidatorIndex]] + sync_contribution_aggregator_slots: Set[Tuple[Slot, ValidatorIndex, Uint64]] sync_contribution_data: Dict[Tuple[Slot, Root, Uint64], Set[Tuple[Boolean, ...]]] sync_message_validator_slots: Set[Tuple[Slot, ValidatorIndex, Uint64]] bls_to_execution_change_indices: Set[ValidatorIndex] @@ -496,26 +501,41 @@ - name: Seen#gloas sources: [] spec: | - + class Seen: - proposer_slots: Set[Tuple[ValidatorIndex, Slot]] - aggregator_epochs: Set[Tuple[ValidatorIndex, Epoch]] + proposer_slots: Set[Tuple[Slot, ValidatorIndex]] + aggregator_epochs: Set[Tuple[Epoch, ValidatorIndex]] aggregate_data_roots: Dict[Tuple[Root, CommitteeIndex], Set[Tuple[Boolean, ...]]] voluntary_exit_indices: Set[ValidatorIndex] proposer_slashing_indices: Set[ValidatorIndex] attester_slashing_indices: Set[ValidatorIndex] - attestation_validator_epochs: Set[Tuple[ValidatorIndex, Epoch]] - sync_contribution_aggregator_slots: Set[Tuple[ValidatorIndex, Slot, Uint64]] + attestation_validator_epochs: Set[Tuple[Epoch, ValidatorIndex]] + sync_contribution_aggregator_slots: Set[Tuple[Slot, ValidatorIndex, Uint64]] sync_contribution_data: Dict[Tuple[Slot, Root, Uint64], Set[Tuple[Boolean, ...]]] sync_message_validator_slots: Set[Tuple[Slot, ValidatorIndex, Uint64]] bls_to_execution_change_indices: Set[ValidatorIndex] - data_column_sidecar_tuples: Set[Tuple[Slot, ValidatorIndex, ColumnIndex]] + # [Modified in Gloas:EIP7732] + data_column_sidecar_tuples: Set[Tuple[Root, ColumnIndex]] + # [Modified in Gloas:EIP7732] + # Removed `partial_data_column_headers` + # [New in Gloas:EIP7732] + execution_payloads: Dict[Hash32, ExecutionPayload] + # [New in Gloas:EIP7732] + execution_payload_envelopes: Set[Tuple[Root, BuilderIndex]] + # [New in Gloas:EIP7732] + payload_attestation_validators: Set[Tuple[Slot, ValidatorIndex]] + # [New in Gloas:EIP7732] + execution_payload_bids: Set[Tuple[Slot, Hash32, Root, BuilderIndex]] + # [New in Gloas:EIP7732] + best_execution_payload_bid: Dict[Tuple[Slot, Hash32, Root], Gwei] + # [New in Gloas:EIP7732] + proposer_preferences: Dict[Tuple[Root, Slot], ProposerPreferences] - name: Store#phase0 sources: [] spec: | - + class Store: time: Uint64 genesis_time: Uint64 @@ -525,18 +545,18 @@ unrealized_finalized_checkpoint: Checkpoint proposer_boost_root: Root equivocating_indices: Set[ValidatorIndex] - blocks: Dict[Root, BeaconBlock] = field(default_factory=dict) - block_states: Dict[Root, BeaconState] = field(default_factory=dict) - block_timeliness: Dict[Root, Boolean] = field(default_factory=dict) - checkpoint_states: Dict[Checkpoint, BeaconState] = field(default_factory=dict) - latest_messages: Dict[ValidatorIndex, LatestMessage] = field(default_factory=dict) - unrealized_justifications: Dict[Root, Checkpoint] = field(default_factory=dict) + blocks: Dict[Root, BeaconBlock] + block_states: Dict[Root, BeaconState] + block_timeliness: Dict[Root, Boolean] + checkpoint_states: Dict[Checkpoint, BeaconState] + latest_messages: Dict[ValidatorIndex, LatestMessage] + unrealized_justifications: Dict[Root, Checkpoint] - name: Store#gloas sources: [] spec: | - + class Store: time: Uint64 genesis_time: Uint64 @@ -546,27 +566,25 @@ unrealized_finalized_checkpoint: Checkpoint proposer_boost_root: Root equivocating_indices: Set[ValidatorIndex] - blocks: Dict[Root, BeaconBlock] = field(default_factory=dict) - block_states: Dict[Root, BeaconState] = field(default_factory=dict) + blocks: Dict[Root, BeaconBlock] + block_states: Dict[Root, BeaconState] # [Modified in Gloas:EIP7732] - block_timeliness: Dict[Root, list[Boolean]] = field(default_factory=dict) - checkpoint_states: Dict[Checkpoint, BeaconState] = field(default_factory=dict) - latest_messages: Dict[ValidatorIndex, LatestMessage] = field(default_factory=dict) - unrealized_justifications: Dict[Root, Checkpoint] = field(default_factory=dict) + block_timeliness: Dict[Root, list[Boolean]] + checkpoint_states: Dict[Checkpoint, BeaconState] + latest_messages: Dict[ValidatorIndex, LatestMessage] + unrealized_justifications: Dict[Root, Checkpoint] # [New in Gloas:EIP7732] - payloads: Dict[Root, ExecutionPayloadEnvelope] = field(default_factory=dict) + payloads: Dict[Root, ExecutionPayloadEnvelope] # [New in Gloas:EIP7732] - payload_timeliness_vote: Dict[Root, list[Optional[Boolean]]] = field(default_factory=dict) + payload_timeliness_vote: Dict[Root, list[Optional[Boolean]]] # [New in Gloas:EIP7732] - payload_data_availability_vote: Dict[Root, list[Optional[Boolean]]] = field( - default_factory=dict - ) + payload_data_availability_vote: Dict[Root, list[Optional[Boolean]]] - name: Store#heze sources: [] spec: | - + class Store: time: Uint64 genesis_time: Uint64 @@ -576,17 +594,15 @@ unrealized_finalized_checkpoint: Checkpoint proposer_boost_root: Root equivocating_indices: Set[ValidatorIndex] - blocks: Dict[Root, BeaconBlock] = field(default_factory=dict) - block_states: Dict[Root, BeaconState] = field(default_factory=dict) - block_timeliness: Dict[Root, list[Boolean]] = field(default_factory=dict) - checkpoint_states: Dict[Checkpoint, BeaconState] = field(default_factory=dict) - latest_messages: Dict[ValidatorIndex, LatestMessage] = field(default_factory=dict) - unrealized_justifications: Dict[Root, Checkpoint] = field(default_factory=dict) - payloads: Dict[Root, ExecutionPayloadEnvelope] = field(default_factory=dict) - payload_timeliness_vote: Dict[Root, list[Optional[Boolean]]] = field(default_factory=dict) - payload_data_availability_vote: Dict[Root, list[Optional[Boolean]]] = field( - default_factory=dict - ) + blocks: Dict[Root, BeaconBlock] + block_states: Dict[Root, BeaconState] + block_timeliness: Dict[Root, list[Boolean]] + checkpoint_states: Dict[Checkpoint, BeaconState] + latest_messages: Dict[ValidatorIndex, LatestMessage] + unrealized_justifications: Dict[Root, Checkpoint] + payloads: Dict[Root, ExecutionPayloadEnvelope] + payload_timeliness_vote: Dict[Root, list[Optional[Boolean]]] + payload_data_availability_vote: Dict[Root, list[Optional[Boolean]]] # [New in Heze:EIP7805] - payload_inclusion_list_satisfaction: Dict[Root, Boolean] = field(default_factory=dict) + payload_inclusion_list_satisfaction: Dict[Root, Boolean] diff --git a/specrefs/functions.yml b/specrefs/functions.yml index 32438fb9c70a..94d0c7b6f181 100644 --- a/specrefs/functions.yml +++ b/specrefs/functions.yml @@ -579,7 +579,7 @@ - name: compute_balance_weighted_selection#gloas sources: [] spec: | - + def compute_balance_weighted_selection( state: BeaconState, indices: Sequence[ValidatorIndex], @@ -597,7 +597,7 @@ total = Uint64(len(indices)) assert total > 0 effective_balances = [state.validators[index].effective_balance for index in indices] - selected: List[ValidatorIndex] = [] + selected: list[ValidatorIndex] = [] i = Uint64(0) while len(selected) < size: offset = i % 16 * 2 @@ -1246,7 +1246,7 @@ - file: beacon-chain/rpc/prysm/v1alpha1/validator/proposer_attestations_electra.go search: func computeOnChainAggregate( spec: | - + def compute_on_chain_aggregate(network_aggregates: Sequence[Attestation]) -> Attestation: aggregates = sorted( network_aggregates, key=lambda a: get_committee_indices(a.committee_bits)[0] @@ -1262,7 +1262,7 @@ committee_indices = [get_committee_indices(a.committee_bits)[0] for a in aggregates] committee_flags = [(index in committee_indices) for index in range(MAX_COMMITTEES_PER_SLOT)] - committee_bits = BitVector[MAX_COMMITTEES_PER_SLOT](committee_flags) + committee_bits = CommitteeBits(committee_flags) return Attestation( aggregation_bits=aggregation_bits, @@ -1334,35 +1334,35 @@ - file: beacon-chain/core/helpers/beacon_committee.go search: func PrecomputeProposerIndices( spec: | - + def compute_proposer_indices( state: BeaconState, epoch: Epoch, seed: Bytes32, indices: Sequence[ValidatorIndex] - ) -> Vector[ValidatorIndex, SLOTS_PER_EPOCH]: + ) -> ProposerIndices: """ Return the proposer indices for the given ``epoch``. """ start_slot = compute_start_slot_at_epoch(epoch) seeds = [hash(seed + uint_to_bytes(Slot(start_slot + i))) for i in range(SLOTS_PER_EPOCH)] - return [compute_proposer_index(state, indices, seed) for seed in seeds] + return ProposerIndices(compute_proposer_index(state, indices, seed) for seed in seeds) - name: compute_proposer_indices#gloas sources: [] spec: | - + def compute_proposer_indices( state: BeaconState, epoch: Epoch, seed: Bytes32, indices: Sequence[ValidatorIndex] - ) -> Vector[ValidatorIndex, SLOTS_PER_EPOCH]: + ) -> ProposerIndices: """ Return the proposer indices for the given ``epoch``. """ start_slot = compute_start_slot_at_epoch(epoch) seeds = [hash(seed + uint_to_bytes(Slot(start_slot + i))) for i in range(SLOTS_PER_EPOCH)] # [Modified in Gloas:EIP7732] - return [ + return ProposerIndices( compute_balance_weighted_selection(state, indices, seed, size=1, shuffle_indices=True)[0] for seed in seeds - ] + ) - name: compute_proposer_score#phase0 @@ -1377,21 +1377,23 @@ - name: compute_ptc#gloas sources: [] spec: | - - def compute_ptc(state: BeaconState, slot: Slot) -> Vector[ValidatorIndex, PTC_SIZE]: + + def compute_ptc(state: BeaconState, slot: Slot) -> PTC: """ Get the payload timeliness committee, with possible duplicates, for the given ``slot``. """ epoch = compute_epoch_at_slot(slot) seed = hash(get_seed(state, epoch, DOMAIN_PTC_ATTESTER) + uint_to_bytes(slot)) - indices: List[ValidatorIndex] = [] + indices: list[ValidatorIndex] = [] # Concatenate all committees for this slot in order committees_per_slot = get_committee_count_per_slot(state, epoch) for i in range(committees_per_slot): committee = get_beacon_committee(state, slot, CommitteeIndex(i)) indices.extend(committee) - return compute_balance_weighted_selection( - state, indices, seed, size=PTC_SIZE, shuffle_indices=False + return PTC( + compute_balance_weighted_selection( + state, indices, seed, size=PTC_SIZE, shuffle_indices=False + ) ) @@ -1488,6 +1490,16 @@ return indices +- name: compute_shuffling_dependent_slot#phase0 + sources: [] + spec: | + + def compute_shuffling_dependent_slot(epoch: Epoch) -> Slot: + if epoch <= MIN_SEED_LOOKAHEAD: + return GENESIS_SLOT + return compute_start_slot_at_epoch(epoch - MIN_SEED_LOOKAHEAD) - Slot(1) + + - name: compute_signed_block_header#deneb sources: - file: consensus-types/interfaces/utils.go @@ -1688,13 +1700,13 @@ - name: compute_time_at_slot_ms#phase0 sources: [] spec: | - - def compute_time_at_slot_ms(state: BeaconState, slot: Slot) -> Uint64: + + def compute_time_at_slot_ms(store: Store, slot: Slot) -> Uint64: """ Return the time in milliseconds at the start of the given slot. """ slots_since_genesis = slot - GENESIS_SLOT - return Uint64(state.genesis_time * 1000 + slots_since_genesis * SLOT_DURATION_MS) + return Uint64(store.genesis_time * 1000 + slots_since_genesis * SLOT_DURATION_MS) - name: compute_weak_subjectivity_period#phase0 @@ -1849,7 +1861,7 @@ - file: beacon-chain/light-client/lightclient.go search: func NewLightClientUpdateFromBeaconState( spec: | - + def create_light_client_update( state: BeaconState, block: SignedBeaconBlock, @@ -1859,7 +1871,7 @@ ) -> LightClientUpdate: assert compute_epoch_at_slot(attested_state.slot) >= ALTAIR_FORK_EPOCH assert ( - sum(block.message.body.sync_aggregate.sync_committee_bits) + get_set_bit_count(block.message.body.sync_aggregate.sync_committee_bits) >= MIN_SYNC_COMMITTEE_PARTICIPANTS ) @@ -2874,10 +2886,8 @@ - file: beacon-chain/core/helpers/beacon_committee.go search: func PrecomputeProposerIndices( spec: | - - def get_beacon_proposer_indices( - state: BeaconState, epoch: Epoch - ) -> Vector[ValidatorIndex, SLOTS_PER_EPOCH]: + + def get_beacon_proposer_indices(state: BeaconState, epoch: Epoch) -> ProposerIndices: """ Return the proposer indices for the given ``epoch``. """ @@ -2893,10 +2903,8 @@ - file: beacon-chain/core/helpers/beacon_committee.go search: func PrecomputeProposerIndices( spec: | - - def get_beacon_proposer_indices( - state: BeaconState, epoch: Epoch - ) -> Vector[ValidatorIndex, SLOTS_PER_EPOCH]: + + def get_beacon_proposer_indices(state: BeaconState, epoch: Epoch) -> ProposerIndices: """ Return the proposer indices for the given ``epoch``. """ @@ -3073,7 +3081,7 @@ - name: get_builder_withdrawals#gloas sources: [] spec: | - + def get_builder_withdrawals( state: BeaconState, withdrawal_index: WithdrawalIndex, @@ -3083,9 +3091,9 @@ assert len(prior_withdrawals) <= withdrawals_limit processed_count: Uint64 = 0 - withdrawals: List[Withdrawal] = [] + withdrawals: list[Withdrawal] = [] for withdrawal in state.builder_pending_withdrawals: - all_withdrawals = prior_withdrawals + withdrawals + all_withdrawals = list(prior_withdrawals) + withdrawals has_reached_limit = len(all_withdrawals) >= withdrawals_limit if has_reached_limit: break @@ -3108,7 +3116,7 @@ - name: get_builders_sweep_withdrawals#gloas sources: [] spec: | - + def get_builders_sweep_withdrawals( state: BeaconState, withdrawal_index: WithdrawalIndex, @@ -3120,10 +3128,10 @@ assert len(prior_withdrawals) <= withdrawals_limit processed_count: Uint64 = 0 - withdrawals: List[Withdrawal] = [] + withdrawals: list[Withdrawal] = [] builder_index = state.next_withdrawal_builder_index for _ in range(builders_limit): - all_withdrawals = prior_withdrawals + withdrawals + all_withdrawals = list(prior_withdrawals) + withdrawals has_reached_limit = len(all_withdrawals) >= withdrawals_limit if has_reached_limit: break @@ -3412,12 +3420,27 @@ ) +- name: get_custody_column_bits#gloas + sources: [] + spec: | + + def get_custody_column_bits(node_id: NodeID, custody_group_count: Uint64) -> CustodyColumnBits: + """ + Compute the bitvector of column indices custodied by ``node_id``. + """ + bits = CustodyColumnBits() + for custody_group in get_custody_groups(node_id, custody_group_count): + for column in compute_columns_for_custody_group(custody_group): + bits[column] = True + return bits + + - name: get_custody_groups#fulu sources: - file: beacon-chain/core/peerdas/das_core.go search: func CustodyGroups( spec: | - + def get_custody_groups(node_id: NodeID, custody_group_count: Uint64) -> Sequence[CustodyIndex]: assert custody_group_count <= NUMBER_OF_CUSTODY_GROUPS @@ -3426,7 +3449,7 @@ return [CustodyIndex(i) for i in range(NUMBER_OF_CUSTODY_GROUPS)] current_id = Uint256(node_id) - custody_groups: List[CustodyIndex] = [] + custody_groups: list[CustodyIndex] = [] while len(custody_groups) < custody_group_count: custody_group = CustodyIndex( bytes_to_uint64(hash(uint_to_bytes(current_id))[0:8]) % NUMBER_OF_CUSTODY_GROUPS @@ -3448,14 +3471,12 @@ - file: beacon-chain/core/peerdas/validator.go search: func DataColumnSidecars( spec: | - + def get_data_column_sidecars( signed_block_header: SignedBeaconBlockHeader, - kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK], - kzg_commitments_inclusion_proof: Vector[Bytes32, KZG_COMMITMENTS_INCLUSION_PROOF_DEPTH], - cells_and_kzg_proofs: Sequence[ - Tuple[Vector[Cell, CELLS_PER_EXT_BLOB], Vector[KZGProof, CELLS_PER_EXT_BLOB]] - ], + kzg_commitments: BlobKZGCommitments, + kzg_commitments_inclusion_proof: KZGCommitmentsInclusionProof, + cells_and_kzg_proofs: Sequence[Tuple[Cells, Proofs]], ) -> Sequence[DataColumnSidecar]: """ Given a signed block header and the commitments, inclusion proof, cells/proofs associated with @@ -3465,7 +3486,8 @@ sidecars = [] for column_index in range(NUMBER_OF_COLUMNS): - column_cells, column_proofs = [], [] + column_cells = DataColumn() + column_proofs = KZGProofs() for cells, proofs in cells_and_kzg_proofs: column_cells.append(cells[column_index]) column_proofs.append(proofs[column_index]) @@ -3485,7 +3507,7 @@ - name: get_data_column_sidecars#gloas sources: [] spec: | - + def get_data_column_sidecars( # [Modified in Gloas:EIP7732] # Removed `signed_block_header` @@ -3497,9 +3519,7 @@ # Removed `kzg_commitments` # [Modified in Gloas:EIP7732] # Removed `kzg_commitments_inclusion_proof` - cells_and_kzg_proofs: Sequence[ - Tuple[Vector[Cell, CELLS_PER_EXT_BLOB], Vector[KZGProof, CELLS_PER_EXT_BLOB]] - ], + cells_and_kzg_proofs: Sequence[Tuple[Cells, Proofs]], ) -> Sequence[DataColumnSidecar]: """ Given a beacon block root and the cells/proofs associated with each blob @@ -3508,7 +3528,8 @@ """ sidecars = [] for column_index in range(NUMBER_OF_COLUMNS): - column_cells, column_proofs = [], [] + column_cells = DataColumn() + column_proofs = KZGProofs() for cells, proofs in cells_and_kzg_proofs: column_cells.append(cells[column_index]) column_proofs.append(proofs[column_index]) @@ -3528,12 +3549,10 @@ - name: get_data_column_sidecars_from_block#fulu sources: [] spec: | - + def get_data_column_sidecars_from_block( signed_block: SignedBeaconBlock, - cells_and_kzg_proofs: Sequence[ - Tuple[Vector[Cell, CELLS_PER_EXT_BLOB], Vector[KZGProof, CELLS_PER_EXT_BLOB]] - ], + cells_and_kzg_proofs: Sequence[Tuple[Cells, Proofs]], ) -> Sequence[DataColumnSidecar]: """ Given a signed block and the cells/proofs associated with each blob in the @@ -3541,9 +3560,11 @@ """ blob_kzg_commitments = signed_block.message.body.blob_kzg_commitments signed_block_header = compute_signed_block_header(signed_block) - kzg_commitments_inclusion_proof = compute_merkle_proof( - signed_block.message.body, - get_generalized_index(BeaconBlockBody, "blob_kzg_commitments"), + kzg_commitments_inclusion_proof = KZGCommitmentsInclusionProof( + compute_merkle_proof( + signed_block.message.body, + get_generalized_index(BeaconBlockBody, "blob_kzg_commitments"), + ) ) return get_data_column_sidecars( signed_block_header, @@ -3556,12 +3577,10 @@ - name: get_data_column_sidecars_from_block#gloas sources: [] spec: | - + def get_data_column_sidecars_from_block( signed_block: SignedBeaconBlock, - cells_and_kzg_proofs: Sequence[ - Tuple[Vector[Cell, CELLS_PER_EXT_BLOB], Vector[KZGProof, CELLS_PER_EXT_BLOB]] - ], + cells_and_kzg_proofs: Sequence[Tuple[Cells, Proofs]], ) -> Sequence[DataColumnSidecar]: """ Given a signed block and the cells/proofs associated with each blob in the @@ -3578,12 +3597,10 @@ - name: get_data_column_sidecars_from_column_sidecar#fulu sources: [] spec: | - + def get_data_column_sidecars_from_column_sidecar( sidecar: DataColumnSidecar, - cells_and_kzg_proofs: Sequence[ - Tuple[Vector[Cell, CELLS_PER_EXT_BLOB], Vector[KZGProof, CELLS_PER_EXT_BLOB]] - ], + cells_and_kzg_proofs: Sequence[Tuple[Cells, Proofs]], ) -> Sequence[DataColumnSidecar]: """ Given a data column sidecar and the cells/proofs associated with each blob corresponding @@ -3602,12 +3619,10 @@ - name: get_data_column_sidecars_from_column_sidecar#gloas sources: [] spec: | - + def get_data_column_sidecars_from_column_sidecar( sidecar: DataColumnSidecar, - cells_and_kzg_proofs: Sequence[ - Tuple[Vector[Cell, CELLS_PER_EXT_BLOB], Vector[KZGProof, CELLS_PER_EXT_BLOB]] - ], + cells_and_kzg_proofs: Sequence[Tuple[Cells, Proofs]], ) -> Sequence[DataColumnSidecar]: """ Given a data column sidecar and the cells/proofs associated with each blob @@ -3835,11 +3850,11 @@ - file: proto/engine/v1/electra.go search: func (ebe *ExecutionBundleElectra) GetDecodedExecutionRequests( spec: | - + def get_execution_requests(execution_requests_list: Sequence[bytes]) -> ExecutionRequests: - deposits = [] - withdrawals = [] - consolidations = [] + deposits = DepositRequests() + withdrawals = WithdrawalRequests() + consolidations = ConsolidationRequests() request_types = [ DEPOSIT_REQUEST_TYPE, @@ -3877,15 +3892,15 @@ - name: get_execution_requests#gloas sources: [] spec: | - + def get_execution_requests(execution_requests_list: Sequence[bytes]) -> ExecutionRequests: - deposits = [] - withdrawals = [] - consolidations = [] + deposits = DepositRequests() + withdrawals = WithdrawalRequests() + consolidations = ConsolidationRequests() # [New in Gloas:EIP8282] - builder_deposits = [] + builder_deposits = BuilderDepositRequests() # [New in Gloas:EIP8282] - builder_exits = [] + builder_exits = BuilderExitRequests() request_types = [ DEPOSIT_REQUEST_TYPE, @@ -3997,10 +4012,10 @@ - file: beacon-chain/state/state-native/getters_withdrawal.go search: func (b *BeaconState) ExpectedWithdrawals( spec: | - + def get_expected_withdrawals(state: BeaconState) -> ExpectedWithdrawals: withdrawal_index = state.next_withdrawal_index - withdrawals: List[Withdrawal] = [] + withdrawals: list[Withdrawal] = [] # Get validators sweep withdrawals validators_sweep_withdrawals, withdrawal_index, processed_validators_sweep_count = ( @@ -4019,10 +4034,10 @@ - file: beacon-chain/state/state-native/getters_withdrawal.go search: func (b *BeaconState) ExpectedWithdrawals( spec: | - + def get_expected_withdrawals(state: BeaconState) -> ExpectedWithdrawals: withdrawal_index = state.next_withdrawal_index - withdrawals: List[Withdrawal] = [] + withdrawals: list[Withdrawal] = [] # [New in Electra:EIP7251] # Get partial withdrawals @@ -4048,10 +4063,10 @@ - name: get_expected_withdrawals#gloas sources: [] spec: | - + def get_expected_withdrawals(state: BeaconState) -> ExpectedWithdrawals: withdrawal_index = state.next_withdrawal_index - withdrawals: List[Withdrawal] = [] + withdrawals: list[Withdrawal] = [] # [New in Gloas:EIP7732] # Get builder withdrawals @@ -4169,7 +4184,7 @@ - name: get_forkchoice_store#phase0 sources: [] spec: | - + def get_forkchoice_store(anchor_state: BeaconState, anchor_block: BeaconBlock) -> Store: assert anchor_block.state_root == hash_tree_root(anchor_state) anchor_root = hash_tree_root(anchor_block) @@ -4188,7 +4203,9 @@ equivocating_indices=set(), blocks={anchor_root: copy(anchor_block)}, block_states={anchor_root: copy(anchor_state)}, + block_timeliness={}, checkpoint_states={justified_checkpoint: copy(anchor_state)}, + latest_messages={}, unrealized_justifications={anchor_root: justified_checkpoint}, ) @@ -4196,7 +4213,7 @@ - name: get_forkchoice_store#gloas sources: [] spec: | - + def get_forkchoice_store(anchor_state: BeaconState, anchor_block: BeaconBlock) -> Store: assert anchor_block.state_root == hash_tree_root(anchor_state) anchor_root = hash_tree_root(anchor_block) @@ -4218,6 +4235,7 @@ # [New in Gloas:EIP7732] block_timeliness={anchor_root: [True, True]}, checkpoint_states={justified_checkpoint: copy(anchor_state)}, + latest_messages={}, unrealized_justifications={anchor_root: justified_checkpoint}, # [New in Gloas:EIP7732] payloads={}, @@ -4231,7 +4249,7 @@ - name: get_forkchoice_store#heze sources: [] spec: | - + def get_forkchoice_store(anchor_state: BeaconState, anchor_block: BeaconBlock) -> Store: assert anchor_block.state_root == hash_tree_root(anchor_state) anchor_root = hash_tree_root(anchor_block) @@ -4252,6 +4270,7 @@ block_states={anchor_root: copy(anchor_state)}, block_timeliness={anchor_root: [True, True]}, checkpoint_states={justified_checkpoint: copy(anchor_state)}, + latest_messages={}, unrealized_justifications={anchor_root: justified_checkpoint}, payloads={}, payload_timeliness_vote={}, @@ -4446,53 +4465,51 @@ - name: get_inclusion_list_bits#heze sources: [] spec: | - + def get_inclusion_list_bits( - store: InclusionListStore, state: BeaconState, slot: Slot, only_timely: bool = True - ) -> BitVector[INCLUSION_LIST_COMMITTEE_SIZE]: - """ - Return a ``BitVector`` over inclusion list committee indices with bits set - for those who provided valid, non-equivocating inclusion lists for the given ``slot``. - """ - committee = get_inclusion_list_committee(state, slot) - key = hash_tree_root(committee) - + store: InclusionListStore, + committee: InclusionListCommittee, + slot: Slot, + dependent_root: Root, + only_timely: bool = True, + ) -> InclusionListBits: + key = (slot, dependent_root) inclusion_lists = store.inclusion_lists[key] equivocators = store.equivocators[key] - timeliness = store.inclusion_list_timeliness - validator_indices = [ - inclusion_lists[inclusion_list_root].message.validator_index - for inclusion_list_root in inclusion_lists - if inclusion_lists[inclusion_list_root].message.validator_index not in equivocators - if not only_timely or timeliness[inclusion_list_root] - ] + validator_indices = [] + for validator_index, inclusion_list in inclusion_lists.items(): + # Ignore inclusion lists from equivocators + if validator_index in equivocators: + continue - return BitVector[INCLUSION_LIST_COMMITTEE_SIZE]( - validator_index in validator_indices for validator_index in committee - ) + # Ignore untimely inclusion lists if only timely ones are requested + if only_timely and not inclusion_list.timely: + continue + + validator_indices.append(validator_index) + + return InclusionListBits(validator_index in validator_indices for validator_index in committee) - name: get_inclusion_list_committee#heze sources: [] spec: | - - def get_inclusion_list_committee( - state: BeaconState, slot: Slot - ) -> Vector[ValidatorIndex, INCLUSION_LIST_COMMITTEE_SIZE]: + + def get_inclusion_list_committee(state: BeaconState, slot: Slot) -> InclusionListCommittee: """ Get the inclusion list committee for the given ``slot``. """ epoch = compute_epoch_at_slot(slot) - indices: List[ValidatorIndex] = [] + indices: list[ValidatorIndex] = [] # Concatenate all committees for this slot in order committees_per_slot = get_committee_count_per_slot(state, epoch) for i in range(committees_per_slot): committee = get_beacon_committee(state, slot, CommitteeIndex(i)) indices.extend(committee) - return Vector[ValidatorIndex, INCLUSION_LIST_COMMITTEE_SIZE]([ + return InclusionListCommittee( indices[i % len(indices)] for i in range(INCLUSION_LIST_COMMITTEE_SIZE) - ]) + ) - name: get_inclusion_list_committee_assignment#heze @@ -4555,24 +4572,25 @@ - name: get_inclusion_list_transactions#heze sources: [] spec: | - + def get_inclusion_list_transactions( - store: InclusionListStore, state: BeaconState, slot: Slot, only_timely: bool = True + store: InclusionListStore, slot: Slot, dependent_root: Root, only_timely: bool = True ) -> Sequence[Transaction]: - committee = get_inclusion_list_committee(state, slot) - key = hash_tree_root(committee) - + key = (slot, dependent_root) inclusion_lists = store.inclusion_lists[key] equivocators = store.equivocators[key] - timeliness = store.inclusion_list_timeliness - - transactions = [ - transaction - for inclusion_list_root in inclusion_lists - if inclusion_lists[inclusion_list_root].message.validator_index not in equivocators - if not only_timely or timeliness[inclusion_list_root] - for transaction in inclusion_lists[inclusion_list_root].message.transactions - ] + + transactions: list[Transaction] = [] + for validator_index, inclusion_list in inclusion_lists.items(): + # Ignore inclusion lists from equivocators + if validator_index in equivocators: + continue + + # Ignore untimely inclusion lists if only timely ones are requested + if only_timely and not inclusion_list.timely: + continue + + transactions.extend(inclusion_list.signed_inclusion_list.message.transactions) # Deduplicate inclusion list transactions. Order does not need to be preserved. return list(set(transactions)) @@ -4602,7 +4620,7 @@ - file: proto/prysm/v1alpha1/attestation/attestation_utils.go search: func ConvertToIndexed( spec: | - + def get_indexed_attestation(state: BeaconState, attestation: Attestation) -> IndexedAttestation: """ Return the indexed attestation corresponding to ``attestation``. @@ -4610,7 +4628,7 @@ attesting_indices = get_attesting_indices(state, attestation) return IndexedAttestation( - attesting_indices=sorted(attesting_indices), + attesting_indices=AttestingIndices(sorted(attesting_indices)), data=attestation.data, signature=attestation.signature, ) @@ -4619,7 +4637,7 @@ - name: get_indexed_payload_attestation#gloas sources: [] spec: | - + def get_indexed_payload_attestation( state: BeaconState, payload_attestation: PayloadAttestation ) -> IndexedPayloadAttestation: @@ -4632,7 +4650,7 @@ attesting_indices = [index for i, index in enumerate(ptc) if bits[i]] return IndexedPayloadAttestation( - attesting_indices=sorted(attesting_indices), + attesting_indices=PTCAttestingIndices(sorted(attesting_indices)), data=payload_attestation.data, signature=payload_attestation.signature, ) @@ -4915,7 +4933,7 @@ - file: beacon-chain/core/altair/sync_committee.go search: func NextSyncCommitteeIndices( spec: | - + def get_next_sync_committee_indices(state: BeaconState) -> Sequence[ValidatorIndex]: """ Return the sync committee indices, with possible duplicates, for the next sync committee. @@ -4927,7 +4945,7 @@ active_validator_count = Uint64(len(active_validator_indices)) seed = get_seed(state, epoch, DOMAIN_SYNC_COMMITTEE) i = 0 - sync_committee_indices: List[ValidatorIndex] = [] + sync_committee_indices: list[ValidatorIndex] = [] while len(sync_committee_indices) < SYNC_COMMITTEE_SIZE: shuffled_index = compute_shuffled_index( Uint64(i % active_validator_count), active_validator_count, seed @@ -4948,7 +4966,7 @@ - file: beacon-chain/core/altair/sync_committee.go search: if s.Version() >= version.Electra { spec: | - + def get_next_sync_committee_indices(state: BeaconState) -> Sequence[ValidatorIndex]: """ Return the sync committee indices, with possible duplicates, for the next sync committee. @@ -4961,7 +4979,7 @@ active_validator_count = Uint64(len(active_validator_indices)) seed = get_seed(state, epoch, DOMAIN_SYNC_COMMITTEE) i = Uint64(0) - sync_committee_indices: List[ValidatorIndex] = [] + sync_committee_indices: list[ValidatorIndex] = [] while len(sync_committee_indices) < SYNC_COMMITTEE_SIZE: shuffled_index = compute_shuffled_index( Uint64(i % active_validator_count), active_validator_count, seed @@ -5140,7 +5158,7 @@ - name: get_pending_partial_withdrawals#electra sources: [] spec: | - + def get_pending_partial_withdrawals( state: BeaconState, withdrawal_index: WithdrawalIndex, @@ -5154,9 +5172,9 @@ assert len(prior_withdrawals) <= withdrawals_limit processed_count: Uint64 = 0 - withdrawals: List[Withdrawal] = [] + withdrawals: list[Withdrawal] = [] for withdrawal in state.pending_partial_withdrawals: - all_withdrawals = prior_withdrawals + withdrawals + all_withdrawals = list(prior_withdrawals) + withdrawals is_withdrawable = withdrawal.withdrawable_epoch <= epoch has_reached_limit = len(all_withdrawals) >= withdrawals_limit if not is_withdrawable or has_reached_limit: @@ -5232,7 +5250,65 @@ - name: get_proposer_head#phase0 sources: [] spec: | - + + def get_proposer_head(store: Store, head_node: ForkChoiceNode, slot: Slot) -> ForkChoiceNode: + head_block = store.blocks[head_node.root] + parent_root = head_block.parent_root + parent_block = store.blocks[parent_root] + parent_node = ForkChoiceNode(root=parent_root) + + # Only re-org the head block if it arrived later than the attestation deadline. + head_late = is_head_late(store, head_node.root) + + # Do not re-org on an epoch boundary where the proposer shuffling could change. + shuffling_stable = is_shuffling_stable(slot) + + # Ensure that the FFG information of the new head will be competitive with the current head. + ffg_competitive = is_ffg_competitive(store, head_node.root, parent_root) + + # Do not re-org if the chain is not finalizing with acceptable frequency. + finalization_ok = is_finalization_ok(store, slot) + + # Only re-org if we are proposing on-time. + proposing_on_time = is_proposing_on_time(store) + + # Only re-org a single slot at most. + parent_slot_ok = parent_block.slot + 1 == head_block.slot + current_time_ok = head_block.slot + 1 == slot + single_slot_reorg = parent_slot_ok and current_time_ok + + # Check that the head has few enough votes to be overpowered by our proposer boost. + assert store.proposer_boost_root != head_node.root # ensure boost has worn off + head_weak = is_head_weak(store, head_node.root) + + # Check that the missing votes are assigned to the parent and not being hoarded. + parent_strong = is_parent_strong(store, head_node.root) + + # Re-org more aggressively if there is a proposer equivocation in the previous slot. + proposer_equivocation = is_proposer_equivocation(store, head_node.root) + + if all([ + head_late, + shuffling_stable, + ffg_competitive, + finalization_ok, + proposing_on_time, + single_slot_reorg, + head_weak, + parent_strong, + ]): + # We can re-org the current head by building upon its parent node. + return parent_node + elif all([head_weak, current_time_ok, proposer_equivocation]): + return parent_node + else: + return head_node + + +- name: get_proposer_head#fulu + sources: [] + spec: | + def get_proposer_head(store: Store, head_node: ForkChoiceNode, slot: Slot) -> ForkChoiceNode: head_block = store.blocks[head_node.root] parent_root = head_block.parent_root @@ -5242,8 +5318,8 @@ # Only re-org the head block if it arrived later than the attestation deadline. head_late = is_head_late(store, head_node.root) - # Do not re-org on an epoch boundary. - not_epoch_boundary = is_not_epoch_boundary(slot) + # [Modified in Fulu:EIP7917] + # Removed `shuffling_stable = is_shuffling_stable(slot)` # Ensure that the FFG information of the new head will be competitive with the current head. ffg_competitive = is_ffg_competitive(store, head_node.root, parent_root) @@ -5271,7 +5347,8 @@ if all([ head_late, - not_epoch_boundary, + # [Modified in Fulu:EIP7917] + # Removed `shuffling_stable` ffg_competitive, finalization_ok, proposing_on_time, @@ -5290,7 +5367,7 @@ - name: get_proposer_head#gloas sources: [] spec: | - + def get_proposer_head(store: Store, head_node: ForkChoiceNode, slot: Slot) -> ForkChoiceNode: head_block = store.blocks[head_node.root] parent_root = head_block.parent_root @@ -5302,9 +5379,6 @@ # Only re-org the head block if it arrived later than the attestation deadline. head_late = is_head_late(store, head_node.root) - # Do not re-org on an epoch boundary. - not_epoch_boundary = is_not_epoch_boundary(slot) - # Ensure that the FFG information of the new head will be competitive with the current head. ffg_competitive = is_ffg_competitive(store, head_node.root, parent_root) @@ -5331,7 +5405,6 @@ if all([ head_late, - not_epoch_boundary, ffg_competitive, finalization_ok, proposing_on_time, @@ -5377,8 +5450,8 @@ - name: get_ptc#gloas sources: [] spec: | - - def get_ptc(state: BeaconState, slot: Slot) -> Vector[ValidatorIndex, PTC_SIZE]: + + def get_ptc(state: BeaconState, slot: Slot) -> PTC: """ Get the payload timeliness committee for the given ``slot``. """ @@ -5478,6 +5551,20 @@ ) +- name: get_scheduled_gas_limit#gloas + sources: [] + spec: | + + def get_scheduled_gas_limit(epoch: Epoch) -> Optional[Uint64]: + """ + Return the scheduled gas limit at a given epoch, if any. + """ + for entry in sorted(GAS_LIMIT_SCHEDULE, key=lambda e: e["EPOCH"], reverse=True): + if epoch >= entry["EPOCH"]: + return entry["GAS_LIMIT"] + return None + + - name: get_seed#phase0 sources: - file: beacon-chain/core/helpers/randao.go @@ -5494,6 +5581,40 @@ return hash(domain_type + uint_to_bytes(epoch) + mix) +- name: get_set_bit_count#phase0 + sources: [] + spec: | + + def get_set_bit_count(bits: Sequence[Boolean]) -> Uint64: + """ + Return the number of bits that are set in ``bits``. + """ + return Uint64(sum(1 for bit in bits if bit)) + + +- name: get_signed_inclusion_list#heze + sources: [] + spec: | + + def get_signed_inclusion_list( + store: Store, + state: BeaconState, + head_root: Root, + slot: Slot, + validator_index: ValidatorIndex, + inclusion_list_transactions: Sequence[Transaction], + privkey: int, + ) -> SignedInclusionList: + inclusion_list = InclusionList( + slot=slot, + validator_index=validator_index, + dependent_root=get_shuffling_dependent_root(store, head_root, compute_epoch_at_slot(slot)), + transactions=inclusion_list_transactions, + ) + signature = get_inclusion_list_signature(state, inclusion_list, privkey) + return SignedInclusionList(message=inclusion_list, signature=signature) + + - name: get_slot_committee#phase0 sources: [] spec: | @@ -5917,7 +6038,7 @@ - name: get_validators_sweep_withdrawals#capella sources: [] spec: | - + def get_validators_sweep_withdrawals( state: BeaconState, withdrawal_index: WithdrawalIndex, @@ -5930,10 +6051,10 @@ assert len(prior_withdrawals) < withdrawals_limit processed_count: Uint64 = 0 - withdrawals: List[Withdrawal] = [] + withdrawals: list[Withdrawal] = [] validator_index = state.next_withdrawal_validator_index for _ in range(validators_limit): - all_withdrawals = prior_withdrawals + withdrawals + all_withdrawals = list(prior_withdrawals) + withdrawals has_reached_limit = len(all_withdrawals) >= withdrawals_limit if has_reached_limit: break @@ -5970,7 +6091,7 @@ - name: get_validators_sweep_withdrawals#electra sources: [] spec: | - + def get_validators_sweep_withdrawals( state: BeaconState, withdrawal_index: WithdrawalIndex, @@ -5983,10 +6104,10 @@ assert len(prior_withdrawals) < withdrawals_limit processed_count: Uint64 = 0 - withdrawals: List[Withdrawal] = [] + withdrawals: list[Withdrawal] = [] validator_index = state.next_withdrawal_validator_index for _ in range(validators_limit): - all_withdrawals = prior_withdrawals + withdrawals + all_withdrawals = list(prior_withdrawals) + withdrawals has_reached_limit = len(all_withdrawals) >= withdrawals_limit if has_reached_limit: break @@ -6167,7 +6288,7 @@ - file: beacon-chain/core/transition/state.go search: func GenesisBeaconState( spec: | - + def initialize_beacon_state_from_eth1( eth1_block_hash: Hash32, eth1_timestamp: Uint64, deposits: Sequence[Deposit] ) -> BeaconState: @@ -6188,7 +6309,7 @@ # Process deposits leaves = [deposit.data for deposit in deposits] for index, deposit in enumerate(deposits): - deposit_data_list = List[DepositData, 2**DEPOSIT_CONTRACT_TREE_DEPTH](*leaves[: index + 1]) + deposit_data_list = DepositDataList(*leaves[: index + 1]) state.eth1_data.deposit_root = hash_tree_root(deposit_data_list) process_deposit(state, deposit) @@ -6243,35 +6364,34 @@ - file: beacon-chain/core/helpers/beacon_committee.go search: func InitializeProposerLookahead( spec: | - + def initialize_proposer_lookahead( state: electra.BeaconState, - ) -> Vector[ValidatorIndex, (MIN_SEED_LOOKAHEAD + 1) * SLOTS_PER_EPOCH]: + ) -> ProposerLookahead: """ Return the proposer indices for the full available lookahead starting from current epoch. Used to initialize the ``proposer_lookahead`` field in the beacon state at genesis and after forks. """ current_epoch = get_current_epoch(state) - lookahead = [] + lookahead: list[ValidatorIndex] = [] for i in range(MIN_SEED_LOOKAHEAD + 1): lookahead.extend(get_beacon_proposer_indices(state, Epoch(current_epoch + i))) - return lookahead + return ProposerLookahead(lookahead) - name: initialize_ptc_window#gloas sources: [] spec: | - + def initialize_ptc_window( state: BeaconState, - ) -> Vector[Vector[ValidatorIndex, PTC_SIZE], (2 + MIN_SEED_LOOKAHEAD) * SLOTS_PER_EPOCH]: + ) -> PTCWindow: """ Return the cached PTC window starting from the current epoch. Used to initialize the ``ptc_window`` field in the beacon state at genesis and after forks. """ empty_previous_epoch = [ - Vector[ValidatorIndex, PTC_SIZE]([ValidatorIndex(0) for _ in range(PTC_SIZE)]) - for _ in range(SLOTS_PER_EPOCH) + PTC([ValidatorIndex(0) for _ in range(PTC_SIZE)]) for _ in range(SLOTS_PER_EPOCH) ] ptcs = [] @@ -6281,7 +6401,7 @@ start_slot = compute_start_slot_at_epoch(epoch) ptcs += [compute_ptc(state, Slot(start_slot + i)) for i in range(SLOTS_PER_EPOCH)] - return empty_previous_epoch + ptcs + return PTCWindow(empty_previous_epoch + ptcs) - name: initiate_builder_exit#gloas @@ -6480,12 +6600,12 @@ - file: beacon-chain/light-client/lightclient.go search: func IsBetterUpdate( spec: | - + def is_better_update(new_update: LightClientUpdate, old_update: LightClientUpdate) -> bool: # Compare supermajority (> 2/3) sync committee participation max_active_participants = len(new_update.sync_aggregate.sync_committee_bits) - new_num_active_participants = sum(new_update.sync_aggregate.sync_committee_bits) - old_num_active_participants = sum(old_update.sync_aggregate.sync_committee_bits) + new_num_active_participants = get_set_bit_count(new_update.sync_aggregate.sync_committee_bits) + old_num_active_participants = get_set_bit_count(old_update.sync_aggregate.sync_committee_bits) new_has_supermajority = new_num_active_participants * 3 >= max_active_participants * 2 old_has_supermajority = old_num_active_participants * 3 >= max_active_participants * 2 if new_has_supermajority != old_has_supermajority: @@ -6642,12 +6762,30 @@ ) +- name: is_current_or_next_slot#gloas + sources: [] + spec: | + + def is_current_or_next_slot( + store: Store, + slot: Slot, + current_time_ms: Uint64, + ) -> bool: + """ + Check if the given slot is the current slot or the next slot + (with MAXIMUM_GOSSIP_CLOCK_DISPARITY allowance). + """ + is_current = is_current_slot(store, slot, current_time_ms) + is_next = is_current_slot(store, Slot(slot - 1), current_time_ms) + return is_current or is_next + + - name: is_current_or_previous_epoch#deneb sources: [] spec: | - + def is_current_or_previous_epoch( - state: BeaconState, + store: Store, epoch: Epoch, current_time_ms: Uint64, ) -> bool: @@ -6655,17 +6793,17 @@ Check if the given epoch is the current or previous epoch (with MAXIMUM_GOSSIP_CLOCK_DISPARITY allowance). """ - is_current = is_within_epoch(state, epoch, current_time_ms) - is_previous = is_within_epoch(state, Epoch(epoch + 1), current_time_ms) + is_current = is_within_epoch(store, epoch, current_time_ms) + is_previous = is_within_epoch(store, Epoch(epoch + 1), current_time_ms) return is_current or is_previous - name: is_current_slot#altair sources: [] spec: | - + def is_current_slot( - state: BeaconState, + store: Store, slot: Slot, current_time_ms: Uint64, ) -> bool: @@ -6673,7 +6811,7 @@ Check if the given slot is the current slot (with MAXIMUM_GOSSIP_CLOCK_DISPARITY allowance). """ - return is_within_slot_range(state, slot, 0, current_time_ms) + return is_within_slot_range(store, slot, 0, current_time_ms) - name: is_data_available#deneb @@ -6883,10 +7021,27 @@ ) +- name: is_future_slot#phase0 + sources: [] + spec: | + + def is_future_slot( + store: Store, + slot: Slot, + current_time_ms: Uint64, + ) -> bool: + """ + Check if the given slot is in the future + (with MAXIMUM_GOSSIP_CLOCK_DISPARITY allowance). + """ + slot_time_ms = compute_time_at_slot_ms(store, slot) + return current_time_ms + MAXIMUM_GOSSIP_CLOCK_DISPARITY < slot_time_ms + + - name: is_gas_limit_target_compatible#gloas sources: [] spec: | - + def is_gas_limit_target_compatible( parent_gas_limit: Uint64, gas_limit: Uint64, target_gas_limit: Uint64 ) -> bool: @@ -6898,11 +7053,11 @@ min_gas_limit = parent_gas_limit - max_gas_limit_difference max_gas_limit = parent_gas_limit + max_gas_limit_difference - if target_gas_limit >= min_gas_limit and target_gas_limit <= max_gas_limit: - return gas_limit == target_gas_limit + if target_gas_limit < min_gas_limit: + return gas_limit == min_gas_limit if target_gas_limit > max_gas_limit: return gas_limit == max_gas_limit - return gas_limit == min_gas_limit + return gas_limit == target_gas_limit - name: is_head_late#phase0 @@ -6991,26 +7146,23 @@ - name: is_inclusion_list_bits_inclusive#heze sources: [] spec: | - + def is_inclusion_list_bits_inclusive( store: InclusionListStore, - state: BeaconState, + committee: InclusionListCommittee, slot: Slot, - inclusion_list_bits: BitVector[INCLUSION_LIST_COMMITTEE_SIZE], + dependent_root: Root, + inclusion_list_bits: InclusionListBits, only_timely: bool = True, ) -> bool: - """ - Return ``True`` if and only if ``inclusion_list_bits`` has a bit set for - every bit set in the local inclusion list bits for the given ``slot``. - """ - local_inclusion_list_bits = get_inclusion_list_bits(store, state, slot, only_timely) - - return not any( - local_inclusion_bit and not inclusion_bit - for inclusion_bit, local_inclusion_bit in zip( - inclusion_list_bits, local_inclusion_list_bits, strict=True - ) + local_inclusion_list_bits = get_inclusion_list_bits( + store, committee, slot, dependent_root, only_timely ) + + for i in range(INCLUSION_LIST_COMMITTEE_SIZE): + if local_inclusion_list_bits[i] and not inclusion_list_bits[i]: + return False + return True - name: is_merge_transition_block#bellatrix @@ -7062,23 +7214,6 @@ return False -- name: is_not_from_future_slot#phase0 - sources: [] - spec: | - - def is_not_from_future_slot( - state: BeaconState, - slot: Slot, - current_time_ms: Uint64, - ) -> bool: - """ - Check if the given slot is not from the future - (with MAXIMUM_GOSSIP_CLOCK_DISPARITY allowance). - """ - slot_time_ms = compute_time_at_slot_ms(state, slot) - return current_time_ms + MAXIMUM_GOSSIP_CLOCK_DISPARITY >= slot_time_ms - - - name: is_one_confirmed#phase0 sources: [] spec: | @@ -7199,6 +7334,23 @@ ) +- name: is_past_slot#gloas + sources: [] + spec: | + + def is_past_slot( + store: Store, + slot: Slot, + current_time_ms: Uint64, + ) -> bool: + """ + Check if the given slot is in the past + (with MAXIMUM_GOSSIP_CLOCK_DISPARITY allowance). + """ + slot_time_ms = compute_time_at_slot_ms(store, slot) + return current_time_ms > slot_time_ms + MAXIMUM_GOSSIP_CLOCK_DISPARITY + + - name: is_payload_inclusion_list_satisfied#heze sources: [] spec: | @@ -7299,6 +7451,14 @@ return time_into_slot_ms <= proposer_reorg_cutoff_ms +- name: is_shuffling_stable#phase0 + sources: [] + spec: | + + def is_shuffling_stable(slot: Slot) -> bool: + return slot % SLOTS_PER_EPOCH != 0 + + - name: is_slashable_attestation_data#phase0 sources: - file: beacon-chain/core/blocks/attester_slashing.go @@ -7388,7 +7548,7 @@ - name: is_valid_dependent_root#gloas sources: [] spec: | - + def is_valid_dependent_root(store: Store, root: Root, epoch: Epoch) -> bool: """ Check if the block with the given ``root`` is a possible dependent block @@ -7396,12 +7556,13 @@ become, the latest block prior to the start of the epoch. """ epoch_start_slot = compute_start_slot_at_epoch(epoch) - if store.blocks[root].slot >= epoch_start_slot: - return False for block in store.blocks.values(): - if block.parent_root == root and block.slot >= epoch_start_slot: - return True - return root == get_head(store).root + if block.parent_root == root: + if block.slot >= epoch_start_slot: + return True + if root == get_head(store).root: + return True + return False - name: is_valid_deposit_signature#electra @@ -7660,27 +7821,6 @@ return is_valid_merkle_branch(leaf, branch[num_extra:], depth, index, root) -- name: is_valid_proposal_slot#gloas - sources: [] - spec: | - - def is_valid_proposal_slot(state: BeaconState, preferences: ProposerPreferences) -> bool: - """ - Check if the validator is the proposer for the given slot within the - proposer lookahead. - """ - current_epoch = get_current_epoch(state) - proposal_epoch = compute_epoch_at_slot(preferences.proposal_slot) - if proposal_epoch < current_epoch: - return False - if proposal_epoch > current_epoch + Epoch(MIN_SEED_LOOKAHEAD): - return False - - index = (proposal_epoch - current_epoch) * SLOTS_PER_EPOCH - index += preferences.proposal_slot % SLOTS_PER_EPOCH - return state.proposer_lookahead[index] == preferences.validator_index - - - name: is_valid_switch_to_compounding_request#electra sources: - file: beacon-chain/core/electra/consolidations.go @@ -7737,9 +7877,9 @@ - name: is_within_epoch#deneb sources: [] spec: | - + def is_within_epoch( - state: BeaconState, + store: Store, epoch: Epoch, current_time_ms: Uint64, ) -> bool: @@ -7748,7 +7888,7 @@ (with MAXIMUM_GOSSIP_CLOCK_DISPARITY allowance on both ends). """ return is_within_slot_range( - state, + store, compute_start_slot_at_epoch(epoch), SLOTS_PER_EPOCH - 1, current_time_ms, @@ -7758,9 +7898,9 @@ - name: is_within_slot_range#phase0 sources: [] spec: | - + def is_within_slot_range( - state: BeaconState, + store: Store, slot: Slot, slot_range: Uint64, current_time_ms: Uint64, @@ -7769,10 +7909,10 @@ Check if the current time is within the inclusive slot range ``[slot, slot + slot_range]`` (with MAXIMUM_GOSSIP_CLOCK_DISPARITY allowance on both ends). """ - start_time_ms = compute_time_at_slot_ms(state, slot) + start_time_ms = compute_time_at_slot_ms(store, slot) if current_time_ms + MAXIMUM_GOSSIP_CLOCK_DISPARITY < start_time_ms: return False - end_time_ms = compute_time_at_slot_ms(state, Slot(slot + slot_range + 1)) + end_time_ms = compute_time_at_slot_ms(store, Slot(slot + slot_range + 1)) if end_time_ms + MAXIMUM_GOSSIP_CLOCK_DISPARITY < current_time_ms: return False return True @@ -7942,10 +8082,10 @@ - file: beacon-chain/blockchain/process_attestation.go search: func (s *Service) OnAttestation( spec: | - + def on_attestation(store: Store, attestation: Attestation, is_from_block: bool = False) -> None: """ - Run ``on_attestation`` upon receiving a new ``attestation`` from either within a block or directly on the wire. + Run ``on_attestation`` upon receiving a new attestation from either within a block or directly on the wire. An ``attestation`` that is asserted as invalid may be valid at a later time, consider scheduling it for later processing in such case. @@ -7968,10 +8108,10 @@ - file: beacon-chain/core/blocks/attester_slashing.go search: func ProcessAttesterSlashing( spec: | - + def on_attester_slashing(store: Store, attester_slashing: AttesterSlashing) -> None: """ - Run ``on_attester_slashing`` immediately upon receiving a new ``AttesterSlashing`` + Run ``on_attester_slashing`` immediately upon receiving a new attester slashing from either within a block or directly on the wire. """ attestation_1 = attester_slashing.attestation_1 @@ -7991,8 +8131,11 @@ - file: beacon-chain/blockchain/receive_block.go search: func (s *Service) ReceiveBlock( spec: | - + def on_block(store: Store, signed_block: SignedBeaconBlock) -> None: + """ + Run ``on_block`` upon receiving a new block. + """ block = signed_block.message block_root = hash_tree_root(block) @@ -8374,7 +8517,7 @@ - name: on_execution_payload_envelope#heze sources: [] spec: | - + def on_execution_payload_envelope( store: Store, signed_envelope: SignedExecutionPayloadEnvelope ) -> None: @@ -8398,7 +8541,7 @@ # Check if this payload satisfies the inclusion list constraints # If not, add this payload to the store as inclusion list constraints unsatisfied record_payload_inclusion_list_satisfaction( - store, state, envelope.beacon_block_root, envelope.payload, EXECUTION_ENGINE + store, envelope.beacon_block_root, envelope.payload, EXECUTION_ENGINE ) # Add execution payload envelope to the store @@ -8417,29 +8560,55 @@ - name: on_inclusion_list#heze sources: [] spec: | - + def on_inclusion_list(store: Store, signed_inclusion_list: SignedInclusionList) -> None: """ Run ``on_inclusion_list`` upon receiving a new inclusion list. """ + inclusion_list = signed_inclusion_list.message + current_slot = get_current_slot(store) + + # The transactions must not exceed the maximum size + transactions_size = sum(len(transaction) for transaction in inclusion_list.transactions) + assert transactions_size <= MAX_TRANSACTIONS_BYTES_PER_INCLUSION_LIST + + # The slot must be within the retention window + assert inclusion_list.slot <= current_slot + assert inclusion_list.slot + MIN_SLOTS_FOR_INCLUSION_LISTS_REQUESTS >= current_slot + + # The dependent block must be known + assert inclusion_list.dependent_root in store.block_states + + # Verify the validator is in the inclusion list committee + dependent_state = copy(store.block_states[inclusion_list.dependent_root]) + if dependent_state.slot < inclusion_list.slot: + process_slots(dependent_state, inclusion_list.slot) + committee = get_inclusion_list_committee(dependent_state, inclusion_list.slot) + assert inclusion_list.validator_index in committee + + # Verify the signature + assert is_valid_inclusion_list_signature(dependent_state, signed_inclusion_list) + + # The inclusion list is timely if it arrives in its slot before the deadline seconds_since_genesis = store.time - store.genesis_time time_into_slot_ms = seconds_to_milliseconds(seconds_since_genesis) % SLOT_DURATION_MS - inclusion_list_due_ms = get_inclusion_list_due_ms() - is_timely = time_into_slot_ms < inclusion_list_due_ms + is_current_slot = inclusion_list.slot == current_slot + is_timely = is_current_slot and time_into_slot_ms < get_inclusion_list_due_ms() + # Process the inclusion list process_inclusion_list(get_inclusion_list_store(), signed_inclusion_list, is_timely) - name: on_payload_attestation_message#gloas sources: [] spec: | - + def on_payload_attestation_message( store: Store, ptc_message: PayloadAttestationMessage, is_from_block: bool = False ) -> None: """ - Run ``on_payload_attestation_message`` upon receiving a new ``ptc_message`` from - either within a block or directly on the wire. + Run ``on_payload_attestation_message`` upon receiving a new payload attestation message + from either within a block or directly on the wire. """ data = ptc_message.data @@ -8710,7 +8879,7 @@ - name: prepare_execution_payload#heze sources: [] spec: | - + def prepare_execution_payload( store: Store, head: ForkChoiceNode, @@ -8745,7 +8914,12 @@ target_gas_limit=target_gas_limit, # [New in Heze:EIP7805] inclusion_list_transactions=get_inclusion_list_transactions( - get_inclusion_list_store(), state, Slot(state.slot - 1), only_timely=False + get_inclusion_list_store(), + state.slot - Slot(1), + get_shuffling_dependent_root( + store, head.root, compute_epoch_at_slot(state.slot - Slot(1)) + ), + only_timely=False, ), ) return execution_engine.notify_forkchoice_updated( @@ -8753,6 +8927,7 @@ safe_block_hash=safe_block_hash, finalized_block_hash=finalized_block_hash, payload_attributes=payload_attributes, + custody_columns=None, ) @@ -8949,7 +9124,7 @@ - name: process_attestation#gloas sources: [] spec: | - + def process_attestation( state: BeaconState, attestation: Attestation, @@ -9001,8 +9176,7 @@ proposer_reward_numerator = 0 for index in get_attesting_indices(state, attestation): # [New in Gloas:EIP7732] - # For same-slot attestations, check if we are setting any new flags. - # If we are, this validator has not contributed to this slot's quorum yet. + had_no_participation = epoch_participation[index] == ParticipationFlags(0b0000_0000) will_set_new_flag = False for flag_index, weight in enumerate(PARTICIPATION_FLAG_WEIGHTS): @@ -9015,10 +9189,9 @@ will_set_new_flag = True # [New in Gloas:EIP7732] - # Add weight for same-slot attestations when any new flag is set. - # This ensures each validator contributes exactly once per slot. if ( will_set_new_flag + and had_no_participation and is_attestation_same_slot(state, data) and payment.withdrawal.amount > 0 ): @@ -9300,7 +9473,7 @@ - name: process_builder_pending_payments#gloas sources: [] spec: | - + def process_builder_pending_payments(state: BeaconState) -> None: """ Processes the builder pending payments from the previous epoch. @@ -9312,7 +9485,7 @@ old_payments = state.builder_pending_payments[SLOTS_PER_EPOCH:] new_payments = [BuilderPendingPayment() for _ in range(SLOTS_PER_EPOCH)] - state.builder_pending_payments = old_payments + new_payments + state.builder_pending_payments = BuilderPendingPayments(old_payments + new_payments) - name: process_consolidation_request#electra @@ -9734,12 +9907,12 @@ - file: beacon-chain/core/epoch/epoch_processing.go search: func ProcessEth1DataReset( spec: | - + def process_eth1_data_reset(state: BeaconState) -> None: next_epoch = Epoch(get_current_epoch(state) + 1) # Reset eth1 data votes if next_epoch % EPOCHS_PER_ETH1_VOTING_PERIOD == 0: - state.eth1_data_votes = [] + state.eth1_data_votes = Eth1DataVotes() - name: process_execution_payload#bellatrix @@ -10192,34 +10365,29 @@ - name: process_inclusion_list#heze sources: [] spec: | - + def process_inclusion_list( - store: InclusionListStore, - signed_inclusion_list: SignedInclusionList, - is_timely: bool, + store: InclusionListStore, signed_inclusion_list: SignedInclusionList, timely: bool ) -> None: inclusion_list = signed_inclusion_list.message - key = inclusion_list.inclusion_list_committee_root - - # Ignore `inclusion_list` from equivocators. - if inclusion_list.validator_index in store.equivocators[key]: - return - - for stored_root in store.inclusion_lists[key]: - stored_inclusion_list = store.inclusion_lists[key][stored_root].message - if stored_inclusion_list.validator_index != inclusion_list.validator_index: - continue + validator_index = inclusion_list.validator_index + key = (inclusion_list.slot, inclusion_list.dependent_root) + if validator_index in store.inclusion_lists[key]: + # Mark the validator as an equivocator if it published a different inclusion list + stored_entry = store.inclusion_lists[key][validator_index] + stored_inclusion_list = stored_entry.signed_inclusion_list.message if stored_inclusion_list != inclusion_list: - store.equivocators[key].add(inclusion_list.validator_index) + store.equivocators[key].add(validator_index) - # Whether it was an equivocation or not, we have processed this `inclusion_list`. + # Ignore an inclusion list that has already been processed return - # Store `signed_inclusion_list` and its timeliness. - inclusion_list_root = hash_tree_root(inclusion_list) - store.inclusion_lists[key][inclusion_list_root] = signed_inclusion_list - store.inclusion_list_timeliness[inclusion_list_root] = is_timely + # Store the signed inclusion list and its timeliness + store.inclusion_lists[key][validator_index] = InclusionListEntry( + signed_inclusion_list=signed_inclusion_list, + timely=timely, + ) - name: process_justification_and_finalization#phase0 @@ -10341,7 +10509,7 @@ - name: process_light_client_update#altair sources: [] spec: | - + def process_light_client_update( store: LightClientStore, update: LightClientUpdate, @@ -10359,12 +10527,12 @@ # Track the maximum number of active participants in the committee signatures store.current_max_active_participants = max( store.current_max_active_participants, - sum(sync_committee_bits), + get_set_bit_count(sync_committee_bits), ) # Update the optimistic header if ( - sum(sync_committee_bits) > get_safety_threshold(store) + get_set_bit_count(sync_committee_bits) > get_safety_threshold(store) and update.attested_header.beacon.slot > store.optimistic_header.beacon.slot ): store.optimistic_header = update.attested_header @@ -10379,7 +10547,7 @@ == compute_sync_committee_period_at_slot(update.attested_header.beacon.slot) ) ) - if sum(sync_committee_bits) * 3 >= len(sync_committee_bits) * 2 and ( + if get_set_bit_count(sync_committee_bits) * 3 >= len(sync_committee_bits) * 2 and ( update.finalized_header.beacon.slot > store.finalized_header.beacon.slot or update_has_finalized_next_sync_committee ): @@ -10567,12 +10735,12 @@ - file: beacon-chain/core/altair/epoch_spec.go search: func ProcessParticipationFlagUpdates( spec: | - + def process_participation_flag_updates(state: BeaconState) -> None: state.previous_epoch_participation = state.current_epoch_participation - state.current_epoch_participation = [ + state.current_epoch_participation = EpochParticipation( ParticipationFlags(0b0000_0000) for _ in range(len(state.validators)) - ] + ) - name: process_participation_record_updates#phase0 @@ -10580,11 +10748,11 @@ - file: beacon-chain/core/epoch/epoch_processing.go search: func ProcessParticipationRecordUpdates( spec: | - + def process_participation_record_updates(state: BeaconState) -> None: # Rotate current/previous epoch attestations state.previous_epoch_attestations = state.current_epoch_attestations - state.current_epoch_attestations = [] + state.current_epoch_attestations = PendingAttestations() - name: process_payload_attestation#gloas @@ -10610,7 +10778,7 @@ - file: beacon-chain/core/electra/consolidations.go search: func ProcessPendingConsolidations( spec: | - + def process_pending_consolidations(state: BeaconState) -> None: next_epoch = Epoch(get_current_epoch(state) + 1) next_pending_consolidation = 0 @@ -10632,7 +10800,9 @@ increase_balance(state, pending_consolidation.target_index, source_effective_balance) next_pending_consolidation += 1 - state.pending_consolidations = state.pending_consolidations[next_pending_consolidation:] + state.pending_consolidations = PendingConsolidations( + state.pending_consolidations[next_pending_consolidation:] + ) - name: process_pending_deposits#electra @@ -10640,7 +10810,7 @@ - file: beacon-chain/core/electra/deposits.go search: func ProcessPendingDeposits( spec: | - + def process_pending_deposits(state: BeaconState) -> None: next_epoch = Epoch(get_current_epoch(state) + 1) available_for_processing = state.deposit_balance_to_consume + get_activation_exit_churn_limit( @@ -10699,7 +10869,9 @@ # Regardless of how the deposit was handled, we move on in the queue. next_deposit_index += 1 - state.pending_deposits = state.pending_deposits[next_deposit_index:] + deposits_to_postpone + state.pending_deposits = PendingDeposits( + state.pending_deposits[next_deposit_index:] + deposits_to_postpone + ) # Accumulate churn only if the churn limit has been hit. if is_churn_limit_reached: @@ -10711,7 +10883,7 @@ - name: process_pending_deposits#fulu sources: [] spec: | - + def process_pending_deposits(state: BeaconState) -> None: next_epoch = Epoch(get_current_epoch(state) + 1) available_for_processing = state.deposit_balance_to_consume + get_activation_exit_churn_limit( @@ -10760,7 +10932,9 @@ # Regardless of how the deposit was handled, we move on in the queue. next_deposit_index += 1 - state.pending_deposits = state.pending_deposits[next_deposit_index:] + deposits_to_postpone + state.pending_deposits = PendingDeposits( + state.pending_deposits[next_deposit_index:] + deposits_to_postpone + ) # Accumulate churn only if the churn limit has been hit. if is_churn_limit_reached: @@ -10772,7 +10946,7 @@ - name: process_pending_deposits#gloas sources: [] spec: | - + def process_pending_deposits(state: BeaconState) -> None: next_epoch = Epoch(get_current_epoch(state) + 1) # [Modified in Gloas:EIP8061] @@ -10821,7 +10995,9 @@ # Regardless of how the deposit was handled, we move on in the queue. next_deposit_index += 1 - state.pending_deposits = state.pending_deposits[next_deposit_index:] + deposits_to_postpone + state.pending_deposits = PendingDeposits( + state.pending_deposits[next_deposit_index:] + deposits_to_postpone + ) # Accumulate churn only if the churn limit has been hit. if is_churn_limit_reached: @@ -11283,15 +11459,15 @@ - file: beacon-chain/core/altair/block.go search: func ProcessSyncAggregate( spec: | - + def process_sync_aggregate(state: BeaconState, sync_aggregate: SyncAggregate) -> None: # Verify sync committee aggregate signature signing over the previous slot block root committee_pubkeys = state.current_sync_committee.pubkeys committee_bits = sync_aggregate.sync_committee_bits - if sum(committee_bits) == SYNC_COMMITTEE_SIZE: + if get_set_bit_count(committee_bits) == SYNC_COMMITTEE_SIZE: # All members participated - use precomputed aggregate key participant_pubkeys = [state.current_sync_committee.aggregate_pubkey] - elif sum(committee_bits) > SYNC_COMMITTEE_SIZE // 2: + elif get_set_bit_count(committee_bits) > SYNC_COMMITTEE_SIZE // 2: # More than half participated - subtract non-participant keys. # First determine nonparticipating members non_participant_pubkeys = [ @@ -11707,16 +11883,17 @@ - name: record_payload_inclusion_list_satisfaction#heze sources: [] spec: | - + def record_payload_inclusion_list_satisfaction( store: Store, - state: BeaconState, root: Root, payload: ExecutionPayload, execution_engine: ExecutionEngine, ) -> None: + slot = store.blocks[root].slot - Slot(1) + dependent_root = get_shuffling_dependent_root(store, root, compute_epoch_at_slot(slot)) inclusion_list_transactions = get_inclusion_list_transactions( - get_inclusion_list_store(), state, Slot(state.slot - 1), only_timely=True + get_inclusion_list_store(), slot, dependent_root, only_timely=True ) is_inclusion_list_satisfied = execution_engine.is_inclusion_list_satisfied( payload, inclusion_list_transactions @@ -12111,13 +12288,13 @@ - name: update_builder_pending_withdrawals#gloas sources: [] spec: | - + def update_builder_pending_withdrawals( state: BeaconState, processed_builder_withdrawals_count: Uint64 ) -> None: - state.builder_pending_withdrawals = state.builder_pending_withdrawals[ - processed_builder_withdrawals_count: - ] + state.builder_pending_withdrawals = BuilderPendingWithdrawals( + state.builder_pending_withdrawals[processed_builder_withdrawals_count:] + ) - name: update_checkpoints#phase0 @@ -12256,23 +12433,23 @@ - name: update_payload_expected_withdrawals#gloas sources: [] spec: | - + def update_payload_expected_withdrawals( state: BeaconState, withdrawals: Sequence[Withdrawal] ) -> None: - state.payload_expected_withdrawals = ProgressiveList[Withdrawal](withdrawals) + state.payload_expected_withdrawals = Withdrawals(withdrawals) - name: update_pending_partial_withdrawals#electra sources: [] spec: | - + def update_pending_partial_withdrawals( state: BeaconState, processed_partial_withdrawals_count: Uint64 ) -> None: - state.pending_partial_withdrawals = state.pending_partial_withdrawals[ - processed_partial_withdrawals_count: - ] + state.pending_partial_withdrawals = PendingPartialWithdrawals( + state.pending_partial_withdrawals[processed_partial_withdrawals_count:] + ) - name: update_proposer_boost_root#phase0 @@ -12816,7 +12993,7 @@ - file: beacon-chain/core/altair/upgrade.go search: func UpgradeToAltair( spec: | - + def upgrade_to_altair(pre: phase0.BeaconState) -> BeaconState: epoch = phase0.get_current_epoch(pre) post = BeaconState( @@ -12840,17 +13017,17 @@ balances=pre.balances, randao_mixes=pre.randao_mixes, slashings=pre.slashings, - previous_epoch_participation=[ + previous_epoch_participation=EpochParticipation([ ParticipationFlags(0b0000_0000) for _ in range(len(pre.validators)) - ], - current_epoch_participation=[ + ]), + current_epoch_participation=EpochParticipation([ ParticipationFlags(0b0000_0000) for _ in range(len(pre.validators)) - ], + ]), justification_bits=pre.justification_bits, previous_justified_checkpoint=pre.previous_justified_checkpoint, current_justified_checkpoint=pre.current_justified_checkpoint, finalized_checkpoint=pre.finalized_checkpoint, - inactivity_scores=[Uint64(0) for _ in range(len(pre.validators))], + inactivity_scores=InactivityScores([Uint64(0) for _ in range(len(pre.validators))]), ) # Fill in previous epoch participation from the pre state's pending attestations translate_participation(post, pre.previous_epoch_attestations) @@ -12912,7 +13089,7 @@ - file: beacon-chain/core/capella/upgrade.go search: func UpgradeToCapella( spec: | - + def upgrade_to_capella(pre: bellatrix.BeaconState) -> BeaconState: epoch = bellatrix.get_current_epoch(pre) latest_execution_payload_header = ExecutionPayloadHeader( @@ -12969,7 +13146,7 @@ # [New in Capella] next_withdrawal_validator_index=ValidatorIndex(0), # [New in Capella] - historical_summaries=List[HistoricalSummary, HISTORICAL_ROOTS_LIMIT]([]), + historical_summaries=HistoricalSummaries(), ) return post @@ -13049,7 +13226,7 @@ - file: beacon-chain/core/electra/upgrade.go search: func UpgradeToElectra( spec: | - + def upgrade_to_electra(pre: deneb.BeaconState) -> BeaconState: epoch = deneb.get_current_epoch(pre) @@ -13106,11 +13283,11 @@ # [New in Electra:EIP7251] earliest_consolidation_epoch=compute_activation_exit_epoch(get_current_epoch(pre)), # [New in Electra:EIP7251] - pending_deposits=[], + pending_deposits=PendingDeposits(), # [New in Electra:EIP7251] - pending_partial_withdrawals=[], + pending_partial_withdrawals=PendingPartialWithdrawals(), # [New in Electra:EIP7251] - pending_consolidations=[], + pending_consolidations=PendingConsolidations(), ) post.exit_balance_to_consume = get_activation_exit_churn_limit(post) @@ -13214,7 +13391,7 @@ - name: upgrade_to_gloas#gloas sources: [] spec: | - + def upgrade_to_gloas(pre: fulu.BeaconState) -> BeaconState: epoch = fulu.get_current_epoch(pre) @@ -13236,25 +13413,21 @@ eth1_data_votes=pre.eth1_data_votes, eth1_deposit_index=pre.eth1_deposit_index, # [Modified in Gloas:EIP7688] - validators=ProgressiveList[Validator](list(pre.validators)), + validators=Validators(list(pre.validators)), # [Modified in Gloas:EIP7688] - balances=ProgressiveList[Gwei](list(pre.balances)), + balances=Balances(list(pre.balances)), randao_mixes=pre.randao_mixes, slashings=pre.slashings, # [Modified in Gloas:EIP7688] - previous_epoch_participation=ProgressiveList[ParticipationFlags]( - list(pre.previous_epoch_participation) - ), + previous_epoch_participation=EpochParticipation(list(pre.previous_epoch_participation)), # [Modified in Gloas:EIP7688] - current_epoch_participation=ProgressiveList[ParticipationFlags]( - list(pre.current_epoch_participation) - ), + current_epoch_participation=EpochParticipation(list(pre.current_epoch_participation)), justification_bits=pre.justification_bits, previous_justified_checkpoint=pre.previous_justified_checkpoint, current_justified_checkpoint=pre.current_justified_checkpoint, finalized_checkpoint=pre.finalized_checkpoint, # [Modified in Gloas:EIP7688] - inactivity_scores=ProgressiveList[Uint64](list(pre.inactivity_scores)), + inactivity_scores=InactivityScores(list(pre.inactivity_scores)), current_sync_committee=pre.current_sync_committee, next_sync_committee=pre.next_sync_committee, # [Modified in Gloas:EIP7732] @@ -13271,34 +13444,43 @@ consolidation_balance_to_consume=pre.consolidation_balance_to_consume, earliest_consolidation_epoch=pre.earliest_consolidation_epoch, # [Modified in Gloas:EIP7688] - pending_deposits=ProgressiveList[PendingDeposit](list(pre.pending_deposits)), + pending_deposits=PendingDeposits(list(pre.pending_deposits)), # [Modified in Gloas:EIP7688] - pending_partial_withdrawals=ProgressiveList[PendingPartialWithdrawal]( + pending_partial_withdrawals=PendingPartialWithdrawals( list(pre.pending_partial_withdrawals) ), # [Modified in Gloas:EIP7688] - pending_consolidations=ProgressiveList[PendingConsolidation]( - list(pre.pending_consolidations) - ), + pending_consolidations=PendingConsolidations(list(pre.pending_consolidations)), proposer_lookahead=pre.proposer_lookahead, # [New in Gloas:EIP7732] - builders=[], + builders=Builders(), # [New in Gloas:EIP7732] next_withdrawal_builder_index=BuilderIndex(0), # [New in Gloas:EIP7732] - execution_payload_availability=[0b1 for _ in range(SLOTS_PER_HISTORICAL_ROOT)], + execution_payload_availability=ExecutionPayloadAvailability([ + 0b1 for _ in range(SLOTS_PER_HISTORICAL_ROOT) + ]), # [New in Gloas:EIP7732] - builder_pending_payments=[BuilderPendingPayment() for _ in range(2 * SLOTS_PER_EPOCH)], + builder_pending_payments=BuilderPendingPayments(), # [New in Gloas:EIP7732] - builder_pending_withdrawals=[], + builder_pending_withdrawals=BuilderPendingWithdrawals(), # [New in Gloas:EIP7732] latest_execution_payload_bid=ExecutionPayloadBid( + parent_block_hash=pre.latest_execution_payload_header.parent_hash, + parent_block_root=pre.latest_block_header.parent_root, block_hash=pre.latest_execution_payload_header.block_hash, + prev_randao=pre.latest_execution_payload_header.prev_randao, + fee_recipient=ExecutionAddress(), gas_limit=pre.latest_execution_payload_header.gas_limit, + builder_index=BUILDER_INDEX_SELF_BUILD, + slot=pre.latest_block_header.slot, + value=Gwei(0), + execution_payment=Gwei(0), + blob_kzg_commitments=BlobKZGCommitments(), execution_requests_root=hash_tree_root(ExecutionRequests()), ), # [New in Gloas:EIP7732] - payload_expected_withdrawals=[], + payload_expected_withdrawals=Withdrawals(), # [New in Gloas:EIP7732] ptc_window=initialize_ptc_window(pre), ) @@ -13312,7 +13494,7 @@ - name: upgrade_to_heze#heze sources: [] spec: | - + def upgrade_to_heze(pre: gloas.BeaconState) -> BeaconState: epoch = gloas.get_current_epoch(pre) latest_execution_payload_bid = ExecutionPayloadBid( @@ -13329,7 +13511,7 @@ blob_kzg_commitments=pre.latest_execution_payload_bid.blob_kzg_commitments, execution_requests_root=pre.latest_execution_payload_bid.execution_requests_root, # [New in Heze:EIP7805] - inclusion_list_bits=BitVector[INCLUSION_LIST_COMMITTEE_SIZE](), + inclusion_list_bits=InclusionListBits(), ) post = BeaconState( @@ -13452,7 +13634,7 @@ - name: validate_beacon_aggregate_and_proof_gossip#phase0 sources: [] spec: | - + def validate_beacon_aggregate_and_proof_gossip( seen: Seen, store: Store, @@ -13477,7 +13659,7 @@ # [IGNORE] The aggregate attestation's slot is within the propagation range # (MAY be queued for processing at the appropriate slot) if not is_within_slot_range( - state, aggregate.data.slot, ATTESTATION_PROPAGATION_SLOT_RANGE, current_time_ms + store, aggregate.data.slot, ATTESTATION_PROPAGATION_SLOT_RANGE, current_time_ms ): raise GossipIgnore("attestation slot not within propagation range") @@ -13502,11 +13684,12 @@ if is_non_strict_superset(seen_bits, aggregate_bits): raise GossipIgnore("already seen aggregate for this data") - # [IGNORE] This is the first valid aggregate for this aggregator in this epoch + # [IGNORE] This is the first valid aggregate for this epoch and aggregator aggregator_index = aggregate_and_proof.aggregator_index target_epoch = aggregate.data.target.epoch - if (aggregator_index, target_epoch) in seen.aggregator_epochs: - raise GossipIgnore("already seen aggregate from this aggregator for this epoch") + aggregator_epoch_key = (target_epoch, aggregator_index) + if aggregator_epoch_key in seen.aggregator_epochs: + raise GossipIgnore("already seen aggregate for this epoch and aggregator") # [REJECT] The selection proof selects the validator as an aggregator if not is_aggregator(state, aggregate.data.slot, index, aggregate_and_proof.selection_proof): @@ -13535,29 +13718,27 @@ # [IGNORE] The block being voted for has been seen (via gossip or non-gossip sources) # (MAY be queued until block is retrieved) - if aggregate.data.beacon_block_root not in store.blocks: + block_root = aggregate.data.beacon_block_root + if block_root not in store.blocks: raise GossipIgnore("block being voted for has not been seen") # [REJECT] The block being voted for passes validation - if aggregate.data.beacon_block_root not in store.block_states: + if block_root not in store.block_states: raise GossipReject("block being voted for failed validation") # [REJECT] The target block is an ancestor of the LMD vote block - checkpoint_block = get_checkpoint_block( - store, aggregate.data.beacon_block_root, aggregate.data.target.epoch - ) + checkpoint_block = get_checkpoint_block(store, block_root, aggregate.data.target.epoch) if checkpoint_block != aggregate.data.target.root: raise GossipReject("target block is not an ancestor of LMD vote block") # [IGNORE] The finalized checkpoint is an ancestor of the block - finalized_checkpoint_block = get_checkpoint_block( - store, aggregate.data.beacon_block_root, store.finalized_checkpoint.epoch - ) + finalized_epoch = store.finalized_checkpoint.epoch + finalized_checkpoint_block = get_checkpoint_block(store, block_root, finalized_epoch) if finalized_checkpoint_block != store.finalized_checkpoint.root: raise GossipIgnore("finalized checkpoint is not an ancestor of block") # Mark this aggregate as seen - seen.aggregator_epochs.add((aggregator_index, target_epoch)) + seen.aggregator_epochs.add(aggregator_epoch_key) if aggregate_data_root not in seen.aggregate_data_roots: seen.aggregate_data_roots[aggregate_data_root] = set() seen.aggregate_data_roots[aggregate_data_root].add(aggregate_bits) @@ -13566,7 +13747,7 @@ - name: validate_beacon_aggregate_and_proof_gossip#deneb sources: [] spec: | - + def validate_beacon_aggregate_and_proof_gossip( seen: Seen, store: Store, @@ -13591,13 +13772,13 @@ # [New in Deneb:EIP7045] # [IGNORE] The aggregate attestation's slot is not from a future slot # (MAY be queued for processing at the appropriate slot) - if not is_not_from_future_slot(state, aggregate.data.slot, current_time_ms): + if is_future_slot(store, aggregate.data.slot, current_time_ms): raise GossipIgnore("aggregate slot is from a future slot") # [Modified in Deneb:EIP7045] # [IGNORE] The aggregate attestation's epoch is either the current or previous epoch attestation_epoch = compute_epoch_at_slot(aggregate.data.slot) - if not is_current_or_previous_epoch(state, attestation_epoch, current_time_ms): + if not is_current_or_previous_epoch(store, attestation_epoch, current_time_ms): raise GossipIgnore("aggregate epoch is not current or previous epoch") # [REJECT] The aggregate attestation's epoch matches its target @@ -13621,11 +13802,12 @@ if is_non_strict_superset(seen_bits, aggregate_bits): raise GossipIgnore("already seen aggregate for this data") - # [IGNORE] This is the first valid aggregate for this aggregator in this epoch + # [IGNORE] This is the first valid aggregate for this epoch and aggregator aggregator_index = aggregate_and_proof.aggregator_index target_epoch = aggregate.data.target.epoch - if (aggregator_index, target_epoch) in seen.aggregator_epochs: - raise GossipIgnore("already seen aggregate from this aggregator for this epoch") + aggregator_epoch_key = (target_epoch, aggregator_index) + if aggregator_epoch_key in seen.aggregator_epochs: + raise GossipIgnore("already seen aggregate for this epoch and aggregator") # [REJECT] The selection proof selects the validator as an aggregator if not is_aggregator(state, aggregate.data.slot, index, aggregate_and_proof.selection_proof): @@ -13654,29 +13836,27 @@ # [IGNORE] The block being voted for has been seen (via gossip or non-gossip sources) # (MAY be queued until block is retrieved) - if aggregate.data.beacon_block_root not in store.blocks: + block_root = aggregate.data.beacon_block_root + if block_root not in store.blocks: raise GossipIgnore("block being voted for has not been seen") # [REJECT] The block being voted for passes validation - if aggregate.data.beacon_block_root not in store.block_states: + if block_root not in store.block_states: raise GossipReject("block being voted for failed validation") # [REJECT] The target block is an ancestor of the LMD vote block - checkpoint_block = get_checkpoint_block( - store, aggregate.data.beacon_block_root, aggregate.data.target.epoch - ) + checkpoint_block = get_checkpoint_block(store, block_root, aggregate.data.target.epoch) if checkpoint_block != aggregate.data.target.root: raise GossipReject("target block is not an ancestor of LMD vote block") # [IGNORE] The finalized checkpoint is an ancestor of the block - finalized_checkpoint_block = get_checkpoint_block( - store, aggregate.data.beacon_block_root, store.finalized_checkpoint.epoch - ) + finalized_epoch = store.finalized_checkpoint.epoch + finalized_checkpoint_block = get_checkpoint_block(store, block_root, finalized_epoch) if finalized_checkpoint_block != store.finalized_checkpoint.root: raise GossipIgnore("finalized checkpoint is not an ancestor of block") # Mark this aggregate as seen - seen.aggregator_epochs.add((aggregator_index, target_epoch)) + seen.aggregator_epochs.add(aggregator_epoch_key) if aggregate_data_root not in seen.aggregate_data_roots: seen.aggregate_data_roots[aggregate_data_root] = set() seen.aggregate_data_roots[aggregate_data_root].add(aggregate_bits) @@ -13685,7 +13865,7 @@ - name: validate_beacon_aggregate_and_proof_gossip#electra sources: [] spec: | - + def validate_beacon_aggregate_and_proof_gossip( seen: Seen, store: Store, @@ -13720,12 +13900,12 @@ # [IGNORE] The aggregate attestation's slot is not from a future slot # (MAY be queued for processing at the appropriate slot) - if not is_not_from_future_slot(state, aggregate.data.slot, current_time_ms): + if is_future_slot(store, aggregate.data.slot, current_time_ms): raise GossipIgnore("aggregate slot is from a future slot") # [IGNORE] The aggregate attestation's epoch is either the current or previous epoch attestation_epoch = compute_epoch_at_slot(aggregate.data.slot) - if not is_current_or_previous_epoch(state, attestation_epoch, current_time_ms): + if not is_current_or_previous_epoch(store, attestation_epoch, current_time_ms): raise GossipIgnore("aggregate epoch is not current or previous epoch") # [REJECT] The aggregate attestation's epoch matches its target @@ -13751,11 +13931,12 @@ if is_non_strict_superset(seen_bits, aggregate_bits): raise GossipIgnore("already seen aggregate for this data") - # [IGNORE] This is the first valid aggregate for this aggregator in this epoch + # [IGNORE] This is the first valid aggregate for this epoch and aggregator aggregator_index = aggregate_and_proof.aggregator_index target_epoch = aggregate.data.target.epoch - if (aggregator_index, target_epoch) in seen.aggregator_epochs: - raise GossipIgnore("already seen aggregate from this aggregator for this epoch") + aggregator_epoch_key = (target_epoch, aggregator_index) + if aggregator_epoch_key in seen.aggregator_epochs: + raise GossipIgnore("already seen aggregate for this epoch and aggregator") # [REJECT] The selection proof selects the validator as an aggregator if not is_aggregator(state, aggregate.data.slot, index, aggregate_and_proof.selection_proof): @@ -13784,53 +13965,184 @@ # [IGNORE] The block being voted for has been seen (via gossip or non-gossip sources) # (MAY be queued until block is retrieved) - if aggregate.data.beacon_block_root not in store.blocks: + block_root = aggregate.data.beacon_block_root + if block_root not in store.blocks: raise GossipIgnore("block being voted for has not been seen") # [REJECT] The block being voted for passes validation - if aggregate.data.beacon_block_root not in store.block_states: + if block_root not in store.block_states: raise GossipReject("block being voted for failed validation") # [REJECT] The target block is an ancestor of the LMD vote block - checkpoint_block = get_checkpoint_block( - store, aggregate.data.beacon_block_root, aggregate.data.target.epoch - ) + checkpoint_block = get_checkpoint_block(store, block_root, aggregate.data.target.epoch) if checkpoint_block != aggregate.data.target.root: raise GossipReject("target block is not an ancestor of LMD vote block") # [IGNORE] The finalized checkpoint is an ancestor of the block - finalized_checkpoint_block = get_checkpoint_block( - store, aggregate.data.beacon_block_root, store.finalized_checkpoint.epoch - ) + finalized_epoch = store.finalized_checkpoint.epoch + finalized_checkpoint_block = get_checkpoint_block(store, block_root, finalized_epoch) if finalized_checkpoint_block != store.finalized_checkpoint.root: raise GossipIgnore("finalized checkpoint is not an ancestor of block") # Mark this aggregate as seen - seen.aggregator_epochs.add((aggregator_index, target_epoch)) + seen.aggregator_epochs.add(aggregator_epoch_key) if aggregate_cache_key not in seen.aggregate_data_roots: seen.aggregate_data_roots[aggregate_cache_key] = set() seen.aggregate_data_roots[aggregate_cache_key].add(aggregate_bits) -- name: validate_beacon_attestation_gossip#phase0 +- name: validate_beacon_aggregate_and_proof_gossip#gloas sources: [] spec: | - - def validate_beacon_attestation_gossip( + + def validate_beacon_aggregate_and_proof_gossip( seen: Seen, store: Store, state: BeaconState, - attestation: Attestation, + signed_aggregate_and_proof: SignedAggregateAndProof, current_time_ms: Uint64, - subnet_id: SubnetID, + # [New in Gloas:EIP7732] + block_payload_statuses: Dict[Root, PayloadValidationStatus], ) -> None: """ - Validate an Attestation for gossip propagation on a subnet. + Validate a SignedAggregateAndProof for gossip propagation. Raises GossipIgnore or GossipReject on validation failure. """ - data = attestation.data - committee_index = data.index - target_epoch = data.target.epoch + aggregate_and_proof = signed_aggregate_and_proof.message + aggregate = aggregate_and_proof.aggregate + aggregation_bits = aggregate.aggregation_bits + + # [New in Gloas:EIP7732] + # [REJECT] The aggregate attestation's data index is 0 or 1 + if aggregate.data.index > 1: + raise GossipReject("aggregate data index must be 0 or 1") + + # [REJECT] Exactly one committee is specified by the committee bits + committee_indices = get_committee_indices(aggregate.committee_bits) + if len(committee_indices) != 1: + raise GossipReject("aggregate committee bits must specify exactly one committee") + index = committee_indices[0] + + # [REJECT] The committee index is within the expected range + committee_count = get_committee_count_per_slot(state, aggregate.data.target.epoch) + if index >= committee_count: + raise GossipReject("committee index out of range") + + # [IGNORE] The aggregate attestation's slot is not from a future slot + # (MAY be queued for processing at the appropriate slot) + if is_future_slot(store, aggregate.data.slot, current_time_ms): + raise GossipIgnore("aggregate slot is from a future slot") + + # [IGNORE] The aggregate attestation's epoch is either the current or previous epoch + attestation_epoch = compute_epoch_at_slot(aggregate.data.slot) + if not is_current_or_previous_epoch(store, attestation_epoch, current_time_ms): + raise GossipIgnore("aggregate epoch is not current or previous epoch") + + # [REJECT] The aggregate attestation's epoch matches its target + if aggregate.data.target.epoch != compute_epoch_at_slot(aggregate.data.slot): + raise GossipReject("attestation epoch does not match target epoch") + + # [REJECT] The number of aggregation bits matches the committee size + committee = get_beacon_committee(state, aggregate.data.slot, index) + if len(aggregation_bits) != len(committee): + raise GossipReject("aggregation bits length does not match committee size") + + # [REJECT] The aggregate attestation has participants + attesting_indices = get_attesting_indices(state, aggregate) + if len(attesting_indices) < 1: + raise GossipReject("aggregate has no participants") + + # [IGNORE] A valid aggregate with a superset of aggregation bits has not already been seen + aggregate_data_root = hash_tree_root(aggregate.data) + aggregate_cache_key = (aggregate_data_root, index) + aggregate_bits = tuple(bool(bit) for bit in aggregation_bits) + seen_bits = seen.aggregate_data_roots.get(aggregate_cache_key, set()) + if is_non_strict_superset(seen_bits, aggregate_bits): + raise GossipIgnore("already seen aggregate for this data") + + # [IGNORE] This is the first valid aggregate for this epoch and aggregator + aggregator_index = aggregate_and_proof.aggregator_index + target_epoch = aggregate.data.target.epoch + aggregator_epoch_key = (target_epoch, aggregator_index) + if aggregator_epoch_key in seen.aggregator_epochs: + raise GossipIgnore("already seen aggregate for this epoch and aggregator") + + # [REJECT] The selection proof selects the validator as an aggregator + if not is_aggregator(state, aggregate.data.slot, index, aggregate_and_proof.selection_proof): + raise GossipReject("validator is not selected as aggregator") + + # [REJECT] The aggregator's validator index is within the committee + if aggregator_index not in committee: + raise GossipReject("aggregator index not in committee") + + # [REJECT] The selection proof signature is valid + aggregator = state.validators[aggregator_index] + domain = get_domain(state, DOMAIN_SELECTION_PROOF, target_epoch) + signing_root = compute_signing_root(aggregate.data.slot, domain) + if not bls.Verify(aggregator.pubkey, signing_root, aggregate_and_proof.selection_proof): + raise GossipReject("invalid selection proof signature") + + # [REJECT] The aggregator signature is valid + domain = get_domain(state, DOMAIN_AGGREGATE_AND_PROOF, target_epoch) + signing_root = compute_signing_root(aggregate_and_proof, domain) + if not bls.Verify(aggregator.pubkey, signing_root, signed_aggregate_and_proof.signature): + raise GossipReject("invalid aggregator signature") + + # [REJECT] The aggregate signature is valid + if not is_valid_indexed_attestation(state, get_indexed_attestation(state, aggregate)): + raise GossipReject("invalid aggregate signature") + + # [IGNORE] The block being voted for has been seen (via gossip or non-gossip sources) + # (MAY be queued until block is retrieved) + block_root = aggregate.data.beacon_block_root + if block_root not in store.blocks: + raise GossipIgnore("block being voted for has not been seen") + + # [REJECT] The block being voted for passes validation + if block_root not in store.block_states: + raise GossipReject("block being voted for failed validation") + + # [REJECT] The target block is an ancestor of the LMD vote block + checkpoint_block = get_checkpoint_block(store, block_root, aggregate.data.target.epoch) + if checkpoint_block != aggregate.data.target.root: + raise GossipReject("target block is not an ancestor of LMD vote block") + + # [IGNORE] The finalized checkpoint is an ancestor of the block + finalized_epoch = store.finalized_checkpoint.epoch + finalized_checkpoint_block = get_checkpoint_block(store, block_root, finalized_epoch) + if finalized_checkpoint_block != store.finalized_checkpoint.root: + raise GossipIgnore("finalized checkpoint is not an ancestor of block") + + # [New in Gloas:EIP7732] + # The attested payload status is consistent with the block's execution payload + verify_attestation_payload_status(store, aggregate.data, block_payload_statuses) + + # Mark this aggregate as seen + seen.aggregator_epochs.add(aggregator_epoch_key) + if aggregate_cache_key not in seen.aggregate_data_roots: + seen.aggregate_data_roots[aggregate_cache_key] = set() + seen.aggregate_data_roots[aggregate_cache_key].add(aggregate_bits) + + +- name: validate_beacon_attestation_gossip#phase0 + sources: [] + spec: | + + def validate_beacon_attestation_gossip( + seen: Seen, + store: Store, + state: BeaconState, + attestation: Attestation, + current_time_ms: Uint64, + subnet_id: SubnetID, + ) -> None: + """ + Validate an Attestation for gossip propagation on a subnet. + Raises GossipIgnore or GossipReject on validation failure. + """ + data = attestation.data + committee_index = data.index + target_epoch = data.target.epoch aggregation_bits = attestation.aggregation_bits # [REJECT] The committee index is within the expected range @@ -13848,7 +14160,7 @@ # [IGNORE] The attestation slot is within the propagation range # (MAY be queued for processing at the appropriate slot) if not is_within_slot_range( - state, data.slot, ATTESTATION_PROPAGATION_SLOT_RANGE, current_time_ms + store, data.slot, ATTESTATION_PROPAGATION_SLOT_RANGE, current_time_ms ): raise GossipIgnore("attestation slot not within propagation range") @@ -13857,7 +14169,7 @@ raise GossipReject("attestation epoch does not match target epoch") # [REJECT] The attestation is unaggregated (exactly one bit set) - num_bits_set = sum(1 for bit in aggregation_bits if bit) + num_bits_set = get_set_bit_count(aggregation_bits) if num_bits_set != 1: raise GossipReject("attestation is not unaggregated") @@ -13866,10 +14178,11 @@ if len(aggregation_bits) != len(committee): raise GossipReject("aggregation bits length does not match committee size") - # [IGNORE] No other valid attestation seen for this validator and target epoch + # [IGNORE] No other valid attestation seen for this target epoch and validator participant_index = committee[aggregation_bits.index(True)] - if (participant_index, target_epoch) in seen.attestation_validator_epochs: - raise GossipIgnore("already seen attestation from this validator for this epoch") + attestation_epoch_key = (target_epoch, participant_index) + if attestation_epoch_key in seen.attestation_validator_epochs: + raise GossipIgnore("already seen attestation for this epoch and validator") # [REJECT] The attestation signature is valid indexed_attestation = get_indexed_attestation(state, attestation) @@ -13878,34 +14191,33 @@ # [IGNORE] The block being voted for has been seen (via gossip or non-gossip sources) # (MAY be queued until block is retrieved) - beacon_block_root = data.beacon_block_root - if beacon_block_root not in store.blocks: + block_root = data.beacon_block_root + if block_root not in store.blocks: raise GossipIgnore("block being voted for has not been seen") # [REJECT] The block being voted for passes validation - if beacon_block_root not in store.block_states: + if block_root not in store.block_states: raise GossipReject("block being voted for failed validation") # [REJECT] The attestation's target block is an ancestor of the LMD vote block - target_checkpoint_block = get_checkpoint_block(store, beacon_block_root, target_epoch) + target_checkpoint_block = get_checkpoint_block(store, block_root, target_epoch) if target_checkpoint_block != data.target.root: raise GossipReject("target block is not an ancestor of LMD vote block") # [IGNORE] The current finalized_checkpoint is an ancestor of the block - finalized_checkpoint_block = get_checkpoint_block( - store, beacon_block_root, store.finalized_checkpoint.epoch - ) + finalized_epoch = store.finalized_checkpoint.epoch + finalized_checkpoint_block = get_checkpoint_block(store, block_root, finalized_epoch) if finalized_checkpoint_block != store.finalized_checkpoint.root: raise GossipIgnore("finalized checkpoint is not an ancestor of block") # Mark this attestation as seen - seen.attestation_validator_epochs.add((participant_index, target_epoch)) + seen.attestation_validator_epochs.add(attestation_epoch_key) - name: validate_beacon_attestation_gossip#deneb sources: [] spec: | - + def validate_beacon_attestation_gossip( seen: Seen, store: Store, @@ -13938,13 +14250,13 @@ # [Modified in Deneb:EIP7045] # [IGNORE] The attestation's slot is not from a future slot # (MAY be queued for processing at the appropriate slot) - if not is_not_from_future_slot(state, data.slot, current_time_ms): + if is_future_slot(store, data.slot, current_time_ms): raise GossipIgnore("attestation slot is from a future slot") # [Modified in Deneb:EIP7045] # [IGNORE] The attestation's epoch is either the current or previous epoch attestation_epoch = compute_epoch_at_slot(data.slot) - if not is_current_or_previous_epoch(state, attestation_epoch, current_time_ms): + if not is_current_or_previous_epoch(store, attestation_epoch, current_time_ms): raise GossipIgnore("attestation epoch is not current or previous epoch") # [REJECT] The attestation's epoch matches its target @@ -13952,7 +14264,7 @@ raise GossipReject("attestation epoch does not match target epoch") # [REJECT] The attestation is unaggregated (exactly one bit set) - num_bits_set = sum(1 for bit in aggregation_bits if bit) + num_bits_set = get_set_bit_count(aggregation_bits) if num_bits_set != 1: raise GossipReject("attestation is not unaggregated") @@ -13961,10 +14273,11 @@ if len(aggregation_bits) != len(committee): raise GossipReject("aggregation bits length does not match committee size") - # [IGNORE] No other valid attestation seen for this validator and target epoch + # [IGNORE] No other valid attestation seen for this target epoch and validator participant_index = committee[aggregation_bits.index(True)] - if (participant_index, target_epoch) in seen.attestation_validator_epochs: - raise GossipIgnore("already seen attestation from this validator for this epoch") + attestation_epoch_key = (target_epoch, participant_index) + if attestation_epoch_key in seen.attestation_validator_epochs: + raise GossipIgnore("already seen attestation for this epoch and validator") # [REJECT] The attestation signature is valid indexed_attestation = get_indexed_attestation(state, attestation) @@ -13973,34 +14286,33 @@ # [IGNORE] The block being voted for has been seen (via gossip or non-gossip sources) # (MAY be queued until block is retrieved) - beacon_block_root = data.beacon_block_root - if beacon_block_root not in store.blocks: + block_root = data.beacon_block_root + if block_root not in store.blocks: raise GossipIgnore("block being voted for has not been seen") # [REJECT] The block being voted for passes validation - if beacon_block_root not in store.block_states: + if block_root not in store.block_states: raise GossipReject("block being voted for failed validation") # [REJECT] The attestation's target block is an ancestor of the LMD vote block - target_checkpoint_block = get_checkpoint_block(store, beacon_block_root, target_epoch) + target_checkpoint_block = get_checkpoint_block(store, block_root, target_epoch) if target_checkpoint_block != data.target.root: raise GossipReject("target block is not an ancestor of LMD vote block") # [IGNORE] The current finalized_checkpoint is an ancestor of the block - finalized_checkpoint_block = get_checkpoint_block( - store, beacon_block_root, store.finalized_checkpoint.epoch - ) + finalized_epoch = store.finalized_checkpoint.epoch + finalized_checkpoint_block = get_checkpoint_block(store, block_root, finalized_epoch) if finalized_checkpoint_block != store.finalized_checkpoint.root: raise GossipIgnore("finalized checkpoint is not an ancestor of block") # Mark this attestation as seen - seen.attestation_validator_epochs.add((participant_index, target_epoch)) + seen.attestation_validator_epochs.add(attestation_epoch_key) - name: validate_beacon_attestation_gossip#electra sources: [] spec: | - + def validate_beacon_attestation_gossip( seen: Seen, store: Store, @@ -14039,12 +14351,12 @@ # [IGNORE] The attestation's slot is not from a future slot # (MAY be queued for processing at the appropriate slot) - if not is_not_from_future_slot(state, data.slot, current_time_ms): + if is_future_slot(store, data.slot, current_time_ms): raise GossipIgnore("attestation slot is from a future slot") # [IGNORE] The attestation's epoch is either the current or previous epoch attestation_epoch = compute_epoch_at_slot(data.slot) - if not is_current_or_previous_epoch(state, attestation_epoch, current_time_ms): + if not is_current_or_previous_epoch(store, attestation_epoch, current_time_ms): raise GossipIgnore("attestation epoch is not current or previous epoch") # [REJECT] The attestation's epoch matches its target @@ -14058,9 +14370,10 @@ raise GossipReject("attester is not a member of the committee") # [Modified in Electra:EIP7549] - # [IGNORE] No other valid attestation seen for this validator and target epoch - if (attester_index, target_epoch) in seen.attestation_validator_epochs: - raise GossipIgnore("already seen attestation from this validator for this epoch") + # [IGNORE] No other valid attestation seen for this target epoch and validator + attestation_epoch_key = (target_epoch, attester_index) + if attestation_epoch_key in seen.attestation_validator_epochs: + raise GossipIgnore("already seen attestation for this epoch and validator") # [Modified in Electra:EIP7549] # [REJECT] The attestation signature is valid @@ -14072,34 +14385,133 @@ # [IGNORE] The block being voted for has been seen (via gossip or non-gossip sources) # (MAY be queued until block is retrieved) - beacon_block_root = data.beacon_block_root - if beacon_block_root not in store.blocks: + block_root = data.beacon_block_root + if block_root not in store.blocks: raise GossipIgnore("block being voted for has not been seen") # [REJECT] The block being voted for passes validation - if beacon_block_root not in store.block_states: + if block_root not in store.block_states: raise GossipReject("block being voted for failed validation") # [REJECT] The attestation's target block is an ancestor of the LMD vote block - target_checkpoint_block = get_checkpoint_block(store, beacon_block_root, target_epoch) + target_checkpoint_block = get_checkpoint_block(store, block_root, target_epoch) if target_checkpoint_block != data.target.root: raise GossipReject("target block is not an ancestor of LMD vote block") # [IGNORE] The current finalized_checkpoint is an ancestor of the block - finalized_checkpoint_block = get_checkpoint_block( - store, beacon_block_root, store.finalized_checkpoint.epoch + finalized_epoch = store.finalized_checkpoint.epoch + finalized_checkpoint_block = get_checkpoint_block(store, block_root, finalized_epoch) + if finalized_checkpoint_block != store.finalized_checkpoint.root: + raise GossipIgnore("finalized checkpoint is not an ancestor of block") + + # Mark this attestation as seen + seen.attestation_validator_epochs.add(attestation_epoch_key) + + +- name: validate_beacon_attestation_gossip#gloas + sources: [] + spec: | + + def validate_beacon_attestation_gossip( + seen: Seen, + store: Store, + state: BeaconState, + attestation: SingleAttestation, + current_time_ms: Uint64, + subnet_id: SubnetID, + # [New in Gloas:EIP7732] + block_payload_statuses: Dict[Root, PayloadValidationStatus], + ) -> None: + """ + Validate a SingleAttestation for gossip propagation on a subnet. + Raises GossipIgnore or GossipReject on validation failure. + """ + data = attestation.data + committee_index = attestation.committee_index + attester_index = attestation.attester_index + target_epoch = data.target.epoch + + # [New in Gloas:EIP7732] + # [REJECT] The attestation's data index is 0 or 1 + if data.index > 1: + raise GossipReject("attestation data index must be 0 or 1") + + # [REJECT] The committee index is within the expected range + committees_per_slot = get_committee_count_per_slot(state, target_epoch) + if committee_index >= committees_per_slot: + raise GossipReject("committee index out of range") + + # [REJECT] The attestation is for the correct subnet + expected_subnet = compute_subnet_for_attestation( + committees_per_slot, data.slot, committee_index ) + if expected_subnet != subnet_id: + raise GossipReject("attestation is for wrong subnet") + + # [IGNORE] The attestation's slot is not from a future slot + # (MAY be queued for processing at the appropriate slot) + if is_future_slot(store, data.slot, current_time_ms): + raise GossipIgnore("attestation slot is from a future slot") + + # [IGNORE] The attestation's epoch is either the current or previous epoch + attestation_epoch = compute_epoch_at_slot(data.slot) + if not is_current_or_previous_epoch(store, attestation_epoch, current_time_ms): + raise GossipIgnore("attestation epoch is not current or previous epoch") + + # [REJECT] The attestation's epoch matches its target + if target_epoch != compute_epoch_at_slot(data.slot): + raise GossipReject("attestation epoch does not match target epoch") + + # [REJECT] The attester is a member of the committee + committee = get_beacon_committee(state, data.slot, committee_index) + if attester_index not in committee: + raise GossipReject("attester is not a member of the committee") + + # [IGNORE] No other valid attestation seen for this target epoch and validator + attestation_epoch_key = (target_epoch, attester_index) + if attestation_epoch_key in seen.attestation_validator_epochs: + raise GossipIgnore("already seen attestation for this epoch and validator") + + # [REJECT] The attestation signature is valid + attester = state.validators[attester_index] + domain = get_domain(state, DOMAIN_BEACON_ATTESTER, target_epoch) + signing_root = compute_signing_root(data, domain) + if not bls.Verify(attester.pubkey, signing_root, attestation.signature): + raise GossipReject("invalid attestation signature") + + # [IGNORE] The block being voted for has been seen (via gossip or non-gossip sources) + # (MAY be queued until block is retrieved) + block_root = data.beacon_block_root + if block_root not in store.blocks: + raise GossipIgnore("block being voted for has not been seen") + + # [REJECT] The block being voted for passes validation + if block_root not in store.block_states: + raise GossipReject("block being voted for failed validation") + + # [REJECT] The attestation's target block is an ancestor of the LMD vote block + target_checkpoint_block = get_checkpoint_block(store, block_root, target_epoch) + if target_checkpoint_block != data.target.root: + raise GossipReject("target block is not an ancestor of LMD vote block") + + # [IGNORE] The current finalized checkpoint is an ancestor of the block + finalized_epoch = store.finalized_checkpoint.epoch + finalized_checkpoint_block = get_checkpoint_block(store, block_root, finalized_epoch) if finalized_checkpoint_block != store.finalized_checkpoint.root: raise GossipIgnore("finalized checkpoint is not an ancestor of block") + # [New in Gloas:EIP7732] + # The attested payload status is consistent with the block's execution payload + verify_attestation_payload_status(store, data, block_payload_statuses) + # Mark this attestation as seen - seen.attestation_validator_epochs.add((attester_index, target_epoch)) + seen.attestation_validator_epochs.add(attestation_epoch_key) - name: validate_beacon_block_gossip#phase0 sources: [] spec: | - + def validate_beacon_block_gossip( seen: Seen, store: Store, @@ -14115,7 +14527,7 @@ # [IGNORE] The block is not from a future slot # (MAY be queued for processing at the appropriate slot) - if not is_not_from_future_slot(state, block.slot, current_time_ms): + if is_future_slot(store, block.slot, current_time_ms): raise GossipIgnore("block is from a future slot") # [IGNORE] The block is from a slot greater than the latest finalized slot @@ -14125,9 +14537,10 @@ if block.slot <= finalized_slot: raise GossipIgnore("block is not from a slot greater than the latest finalized slot") - # [IGNORE] The block is the first block with valid signature received for the proposer for the slot - if (block.proposer_index, block.slot) in seen.proposer_slots: - raise GossipIgnore("block is not the first valid block for this proposer and slot") + # [IGNORE] The block is the first block with valid signature received for the slot and proposer + proposer_slot_key = (block.slot, block.proposer_index) + if proposer_slot_key in seen.proposer_slots: + raise GossipIgnore("block is not the first valid block for this slot and proposer") # [REJECT] The proposer index is a valid validator index if block.proposer_index >= len(state.validators): @@ -14154,10 +14567,9 @@ raise GossipReject("block is not from a higher slot than its parent") # [REJECT] The current finalized checkpoint is an ancestor of the block - checkpoint_block = get_checkpoint_block( - store, block.parent_root, store.finalized_checkpoint.epoch - ) - if checkpoint_block != store.finalized_checkpoint.root: + finalized_epoch = store.finalized_checkpoint.epoch + finalized_checkpoint_block = get_checkpoint_block(store, block.parent_root, finalized_epoch) + if finalized_checkpoint_block != store.finalized_checkpoint.root: raise GossipReject("finalized checkpoint is not an ancestor of block") # [REJECT] The block is proposed by the expected proposer for the slot @@ -14169,13 +14581,13 @@ raise GossipReject("block proposer_index does not match expected proposer") # Mark this block as seen - seen.proposer_slots.add((block.proposer_index, block.slot)) + seen.proposer_slots.add(proposer_slot_key) - name: validate_beacon_block_gossip#bellatrix sources: [] spec: | - + def validate_beacon_block_gossip( seen: Seen, store: Store, @@ -14194,7 +14606,7 @@ # [IGNORE] The block is not from a future slot # (MAY be queued for processing at the appropriate slot) - if not is_not_from_future_slot(state, block.slot, current_time_ms): + if is_future_slot(store, block.slot, current_time_ms): raise GossipIgnore("block is from a future slot") # [IGNORE] The block is from a slot greater than the latest finalized slot @@ -14204,9 +14616,10 @@ if block.slot <= finalized_slot: raise GossipIgnore("block is not from a slot greater than the latest finalized slot") - # [IGNORE] The block is the first block with valid signature received for the proposer for the slot - if (block.proposer_index, block.slot) in seen.proposer_slots: - raise GossipIgnore("block is not the first valid block for this proposer and slot") + # [IGNORE] The block is the first block with valid signature received for the slot and proposer + proposer_slot_key = (block.slot, block.proposer_index) + if proposer_slot_key in seen.proposer_slots: + raise GossipIgnore("block is not the first valid block for this slot and proposer") # [REJECT] The proposer index is a valid validator index if block.proposer_index >= len(state.validators): @@ -14256,10 +14669,9 @@ raise GossipReject("block is not from a higher slot than its parent") # [REJECT] The current finalized checkpoint is an ancestor of the block - checkpoint_block = get_checkpoint_block( - store, block.parent_root, store.finalized_checkpoint.epoch - ) - if checkpoint_block != store.finalized_checkpoint.root: + finalized_epoch = store.finalized_checkpoint.epoch + finalized_checkpoint_block = get_checkpoint_block(store, block.parent_root, finalized_epoch) + if finalized_checkpoint_block != store.finalized_checkpoint.root: raise GossipReject("finalized checkpoint is not an ancestor of block") # [REJECT] The block is proposed by the expected proposer for the slot @@ -14271,13 +14683,13 @@ raise GossipReject("block proposer_index does not match expected proposer") # Mark this block as seen - seen.proposer_slots.add((block.proposer_index, block.slot)) + seen.proposer_slots.add(proposer_slot_key) - name: validate_beacon_block_gossip#capella sources: [] spec: | - + def validate_beacon_block_gossip( seen: Seen, store: Store, @@ -14295,7 +14707,7 @@ # [IGNORE] The block is not from a future slot # (MAY be queued for processing at the appropriate slot) - if not is_not_from_future_slot(state, block.slot, current_time_ms): + if is_future_slot(store, block.slot, current_time_ms): raise GossipIgnore("block is from a future slot") # [IGNORE] The block is from a slot greater than the latest finalized slot @@ -14305,9 +14717,10 @@ if block.slot <= finalized_slot: raise GossipIgnore("block is not from a slot greater than the latest finalized slot") - # [IGNORE] The block is the first block with valid signature received for the proposer for the slot - if (block.proposer_index, block.slot) in seen.proposer_slots: - raise GossipIgnore("block is not the first valid block for this proposer and slot") + # [IGNORE] The block is the first block with valid signature received for the slot and proposer + proposer_slot_key = (block.slot, block.proposer_index) + if proposer_slot_key in seen.proposer_slots: + raise GossipIgnore("block is not the first valid block for this slot and proposer") # [REJECT] The proposer index is a valid validator index if block.proposer_index >= len(state.validators): @@ -14350,10 +14763,9 @@ raise GossipReject("block is not from a higher slot than its parent") # [REJECT] The current finalized checkpoint is an ancestor of the block - checkpoint_block = get_checkpoint_block( - store, block.parent_root, store.finalized_checkpoint.epoch - ) - if checkpoint_block != store.finalized_checkpoint.root: + finalized_epoch = store.finalized_checkpoint.epoch + finalized_checkpoint_block = get_checkpoint_block(store, block.parent_root, finalized_epoch) + if finalized_checkpoint_block != store.finalized_checkpoint.root: raise GossipReject("finalized checkpoint is not an ancestor of block") # [REJECT] The block is proposed by the expected proposer for the slot @@ -14365,13 +14777,13 @@ raise GossipReject("block proposer_index does not match expected proposer") # Mark this block as seen - seen.proposer_slots.add((block.proposer_index, block.slot)) + seen.proposer_slots.add(proposer_slot_key) - name: validate_beacon_block_gossip#deneb sources: [] spec: | - + def validate_beacon_block_gossip( seen: Seen, store: Store, @@ -14389,7 +14801,7 @@ # [IGNORE] The block is not from a future slot # (MAY be queued for processing at the appropriate slot) - if not is_not_from_future_slot(state, block.slot, current_time_ms): + if is_future_slot(store, block.slot, current_time_ms): raise GossipIgnore("block is from a future slot") # [IGNORE] The block is from a slot greater than the latest finalized slot @@ -14399,9 +14811,10 @@ if block.slot <= finalized_slot: raise GossipIgnore("block is not from a slot greater than the latest finalized slot") - # [IGNORE] The block is the first block with valid signature received for the proposer for the slot - if (block.proposer_index, block.slot) in seen.proposer_slots: - raise GossipIgnore("block is not the first valid block for this proposer and slot") + # [IGNORE] The block is the first block with valid signature received for the slot and proposer + proposer_slot_key = (block.slot, block.proposer_index) + if proposer_slot_key in seen.proposer_slots: + raise GossipIgnore("block is not the first valid block for this slot and proposer") # [REJECT] The proposer index is a valid validator index if block.proposer_index >= len(state.validators): @@ -14444,10 +14857,9 @@ raise GossipReject("block is not from a higher slot than its parent") # [REJECT] The current finalized checkpoint is an ancestor of the block - checkpoint_block = get_checkpoint_block( - store, block.parent_root, store.finalized_checkpoint.epoch - ) - if checkpoint_block != store.finalized_checkpoint.root: + finalized_epoch = store.finalized_checkpoint.epoch + finalized_checkpoint_block = get_checkpoint_block(store, block.parent_root, finalized_epoch) + if finalized_checkpoint_block != store.finalized_checkpoint.root: raise GossipReject("finalized checkpoint is not an ancestor of block") # [New in Deneb:EIP4844] @@ -14464,13 +14876,13 @@ raise GossipReject("block proposer_index does not match expected proposer") # Mark this block as seen - seen.proposer_slots.add((block.proposer_index, block.slot)) + seen.proposer_slots.add(proposer_slot_key) - name: validate_beacon_block_gossip#electra sources: [] spec: | - + def validate_beacon_block_gossip( seen: Seen, store: Store, @@ -14488,7 +14900,7 @@ # [IGNORE] The block is not from a future slot # (MAY be queued for processing at the appropriate slot) - if not is_not_from_future_slot(state, block.slot, current_time_ms): + if is_future_slot(store, block.slot, current_time_ms): raise GossipIgnore("block is from a future slot") # [IGNORE] The block is from a slot greater than the latest finalized slot @@ -14498,9 +14910,10 @@ if block.slot <= finalized_slot: raise GossipIgnore("block is not from a slot greater than the latest finalized slot") - # [IGNORE] The block is the first block with valid signature received for the proposer for the slot - if (block.proposer_index, block.slot) in seen.proposer_slots: - raise GossipIgnore("block is not the first valid block for this proposer and slot") + # [IGNORE] The block is the first block with valid signature received for the slot and proposer + proposer_slot_key = (block.slot, block.proposer_index) + if proposer_slot_key in seen.proposer_slots: + raise GossipIgnore("block is not the first valid block for this slot and proposer") # [REJECT] The proposer index is a valid validator index if block.proposer_index >= len(state.validators): @@ -14543,10 +14956,9 @@ raise GossipReject("block is not from a higher slot than its parent") # [REJECT] The current finalized checkpoint is an ancestor of the block - checkpoint_block = get_checkpoint_block( - store, block.parent_root, store.finalized_checkpoint.epoch - ) - if checkpoint_block != store.finalized_checkpoint.root: + finalized_epoch = store.finalized_checkpoint.epoch + finalized_checkpoint_block = get_checkpoint_block(store, block.parent_root, finalized_epoch) + if finalized_checkpoint_block != store.finalized_checkpoint.root: raise GossipReject("finalized checkpoint is not an ancestor of block") # [Modified in Electra:EIP7691] @@ -14563,33 +14975,31 @@ raise GossipReject("block proposer_index does not match expected proposer") # Mark this block as seen - seen.proposer_slots.add((block.proposer_index, block.slot)) + seen.proposer_slots.add(proposer_slot_key) - name: validate_beacon_block_gossip#fulu sources: [] spec: | - + def validate_beacon_block_gossip( seen: Seen, store: Store, state: BeaconState, signed_beacon_block: SignedBeaconBlock, current_time_ms: Uint64, - block_payload_statuses: Optional[Dict[Root, PayloadValidationStatus]] = None, + block_payload_statuses: Dict[Root, PayloadValidationStatus], ) -> None: """ Validate a SignedBeaconBlock for gossip propagation. Raises GossipIgnore or GossipReject on validation failure. """ - if block_payload_statuses is None: - block_payload_statuses = {} block = signed_beacon_block.message execution_payload = block.body.execution_payload # [IGNORE] The block is not from a future slot # (MAY be queued for processing at the appropriate slot) - if not is_not_from_future_slot(state, block.slot, current_time_ms): + if is_future_slot(store, block.slot, current_time_ms): raise GossipIgnore("block is from a future slot") # [IGNORE] The block is from a slot greater than the latest finalized slot @@ -14599,9 +15009,10 @@ if block.slot <= finalized_slot: raise GossipIgnore("block is not from a slot greater than the latest finalized slot") - # [IGNORE] The block is the first block with valid signature received for the proposer for the slot - if (block.proposer_index, block.slot) in seen.proposer_slots: - raise GossipIgnore("block is not the first valid block for this proposer and slot") + # [IGNORE] The block is the first block with valid signature received for the slot and proposer + proposer_slot_key = (block.slot, block.proposer_index) + if proposer_slot_key in seen.proposer_slots: + raise GossipIgnore("block is not the first valid block for this slot and proposer") # [REJECT] The proposer index is a valid validator index if block.proposer_index >= len(state.validators): @@ -14644,10 +15055,9 @@ raise GossipReject("block is not from a higher slot than its parent") # [REJECT] The current finalized checkpoint is an ancestor of the block - checkpoint_block = get_checkpoint_block( - store, block.parent_root, store.finalized_checkpoint.epoch - ) - if checkpoint_block != store.finalized_checkpoint.root: + finalized_epoch = store.finalized_checkpoint.epoch + finalized_checkpoint_block = get_checkpoint_block(store, block.parent_root, finalized_epoch) + if finalized_checkpoint_block != store.finalized_checkpoint.root: raise GossipReject("finalized checkpoint is not an ancestor of block") # [Modified in Fulu:EIP7892] @@ -14657,21 +15067,131 @@ raise GossipReject("too many blob kzg commitments") # [REJECT] The block is proposed by the expected proposer for the slot - # (if shuffling is not available, IGNORE instead and MAY be queued for later) + # (if shuffling is not available, IGNORE instead and MAY be queued for later) + parent_state = store.block_states[block.parent_root].copy() + process_slots(parent_state, block.slot) + expected_proposer = get_beacon_proposer_index(parent_state) + if block.proposer_index != expected_proposer: + raise GossipReject("block proposer_index does not match expected proposer") + + # Mark this block as seen + seen.proposer_slots.add(proposer_slot_key) + + +- name: validate_beacon_block_gossip#gloas + sources: [] + spec: | + + def validate_beacon_block_gossip( + seen: Seen, + store: Store, + state: BeaconState, + signed_beacon_block: SignedBeaconBlock, + current_time_ms: Uint64, + # [Modified in Gloas:EIP7732] + # Removed `block_payload_statuses` + ) -> None: + """ + Validate a SignedBeaconBlock for gossip propagation. + Raises GossipIgnore or GossipReject on validation failure. + """ + block = signed_beacon_block.message + bid = block.body.signed_execution_payload_bid.message + + # [IGNORE] The block is not from a future slot + # (MAY be queued for processing at the appropriate slot) + if is_future_slot(store, block.slot, current_time_ms): + raise GossipIgnore("block is from a future slot") + + # [IGNORE] The block is from a slot greater than the latest finalized slot + # (MAY choose to validate and store such blocks for additional purposes + # -- e.g. slashing detection, archive nodes, etc) + finalized_slot = compute_start_slot_at_epoch(store.finalized_checkpoint.epoch) + if block.slot <= finalized_slot: + raise GossipIgnore("block is not from a slot greater than the latest finalized slot") + + # [IGNORE] The block is the first block with valid signature received for the slot and proposer + proposer_slot_key = (block.slot, block.proposer_index) + if proposer_slot_key in seen.proposer_slots: + raise GossipIgnore("block is not the first valid block for this slot and proposer") + + # [New in Gloas:EIP7688] + # [REJECT] The block body operation counts are within their limits + verify_block_body_operation_limits(block.body) + + # [New in Gloas:EIP7688] + # [REJECT] The parent execution request counts are within their limits + verify_execution_requests_limits(block.body.parent_execution_requests) + + # [REJECT] The proposer index is a valid validator index + if block.proposer_index >= len(state.validators): + raise GossipReject("proposer index out of range") + + # [REJECT] The proposer signature is valid + proposer = state.validators[block.proposer_index] + domain = get_domain(state, DOMAIN_BEACON_PROPOSER, compute_epoch_at_slot(block.slot)) + signing_root = compute_signing_root(block, domain) + if not bls.Verify(proposer.pubkey, signing_root, signed_beacon_block.signature): + raise GossipReject("invalid proposer signature") + + # [IGNORE] The block's parent has been seen (via gossip or non-gossip sources) + # (MAY be queued until parent is retrieved) + if block.parent_root not in store.blocks: + raise GossipIgnore("block's parent has not been seen") + + # [New in Gloas:EIP7732] + # [IGNORE] If the parent block is full, the parent payload is valid + # (MAY be queued until the parent payload is verified) + if is_parent_node_full(store, block): + if not is_payload_verified(store, block.parent_root): + raise GossipIgnore("parent payload is not verified") + + # [REJECT] The block is from a higher slot than its parent + if block.slot <= store.blocks[block.parent_root].slot: + raise GossipReject("block is not from a higher slot than its parent") + + # [REJECT] The current finalized checkpoint is an ancestor of the block + finalized_epoch = store.finalized_checkpoint.epoch + finalized_checkpoint_block = get_checkpoint_block(store, block.parent_root, finalized_epoch) + if finalized_checkpoint_block != store.finalized_checkpoint.root: + raise GossipReject("finalized checkpoint is not an ancestor of block") + + # [Modified in Gloas:EIP7732] + # [REJECT] The bid's blob KZG commitment count is within the per-epoch limit + max_blobs = get_blob_parameters(get_current_epoch(state)).max_blobs_per_block + if len(bid.blob_kzg_commitments) > max_blobs: + raise GossipReject("too many blob kzg commitments") + + # [Modified in Gloas:EIP7732] + # [REJECT] The bid's parent equals the block's parent + if bid.parent_block_root != block.parent_root: + raise GossipReject("bid's parent does not equal block's parent") + + # [REJECT] The block's parent passes validation + if block.parent_root not in store.block_states: + raise GossipReject("block's parent is invalid") + + # [REJECT] The block is proposed by the expected proposer for the slot parent_state = store.block_states[block.parent_root].copy() process_slots(parent_state, block.slot) expected_proposer = get_beacon_proposer_index(parent_state) if block.proposer_index != expected_proposer: raise GossipReject("block proposer_index does not match expected proposer") + # [New in Gloas:EIP7732] + # [REJECT] If the parent is not full, the bid builds on the parent's execution head + if not is_parent_node_full(store, block): + if bid.parent_block_hash != parent_state.latest_block_hash: + raise GossipReject("bid does not build on the parent's execution head") + # Mark this block as seen - seen.proposer_slots.add((block.proposer_index, block.slot)) + seen.proposer_slots.add(proposer_slot_key) - name: validate_blob_sidecar_gossip#deneb sources: [] spec: | - + def validate_blob_sidecar_gossip( seen: Seen, store: Store, @@ -14696,7 +15216,7 @@ # [IGNORE] The sidecar is not from a future slot # (MAY be queued for processing at the appropriate slot) - if not is_not_from_future_slot(state, block_header.slot, current_time_ms): + if is_future_slot(store, block_header.slot, current_time_ms): raise GossipIgnore("blob sidecar is from a future slot") # [IGNORE] The sidecar is from a slot greater than the latest finalized slot @@ -14717,22 +15237,22 @@ # [IGNORE] The sidecar's block's parent has been seen # (MAY be queued for processing once the parent block is retrieved) - if block_header.parent_root not in store.blocks: + parent_root = block_header.parent_root + if parent_root not in store.blocks: raise GossipIgnore("blob sidecar's parent has not been seen") # [REJECT] The sidecar's block's parent passes validation - if block_header.parent_root not in store.block_states: + if parent_root not in store.block_states: raise GossipReject("blob sidecar's parent failed validation") # [REJECT] The sidecar is from a higher slot than the sidecar's block's parent - if block_header.slot <= store.blocks[block_header.parent_root].slot: + if block_header.slot <= store.blocks[parent_root].slot: raise GossipReject("blob sidecar is not from a higher slot than its parent") # [REJECT] The current finalized_checkpoint is an ancestor of the sidecar's block - checkpoint_block = get_checkpoint_block( - store, block_header.parent_root, store.finalized_checkpoint.epoch - ) - if checkpoint_block != store.finalized_checkpoint.root: + finalized_epoch = store.finalized_checkpoint.epoch + finalized_checkpoint_block = get_checkpoint_block(store, parent_root, finalized_epoch) + if finalized_checkpoint_block != store.finalized_checkpoint.root: raise GossipReject("finalized checkpoint is not an ancestor of blob sidecar's block") # [REJECT] The sidecar's inclusion proof is valid as verified by verify_blob_sidecar_inclusion_proof @@ -14753,7 +15273,7 @@ # [REJECT] The sidecar is proposed by the expected proposer_index # (if shuffling is not available, IGNORE instead and MAY be queued for later) - parent_state = store.block_states[block_header.parent_root].copy() + parent_state = store.block_states[parent_root].copy() process_slots(parent_state, block_header.slot) expected_proposer = get_beacon_proposer_index(parent_state) if block_header.proposer_index != expected_proposer: @@ -14766,7 +15286,7 @@ - name: validate_blob_sidecar_gossip#electra sources: [] spec: | - + def validate_blob_sidecar_gossip( seen: Seen, store: Store, @@ -14792,7 +15312,7 @@ # [IGNORE] The sidecar is not from a future slot # (MAY be queued for processing at the appropriate slot) - if not is_not_from_future_slot(state, block_header.slot, current_time_ms): + if is_future_slot(store, block_header.slot, current_time_ms): raise GossipIgnore("blob sidecar is from a future slot") # [IGNORE] The sidecar is from a slot greater than the latest finalized slot @@ -14813,22 +15333,22 @@ # [IGNORE] The sidecar's block's parent has been seen # (MAY be queued for processing once the parent block is retrieved) - if block_header.parent_root not in store.blocks: + parent_root = block_header.parent_root + if parent_root not in store.blocks: raise GossipIgnore("blob sidecar's parent has not been seen") # [REJECT] The sidecar's block's parent passes validation - if block_header.parent_root not in store.block_states: + if parent_root not in store.block_states: raise GossipReject("blob sidecar's parent failed validation") # [REJECT] The sidecar is from a higher slot than the sidecar's block's parent - if block_header.slot <= store.blocks[block_header.parent_root].slot: + if block_header.slot <= store.blocks[parent_root].slot: raise GossipReject("blob sidecar is not from a higher slot than its parent") # [REJECT] The current finalized_checkpoint is an ancestor of the sidecar's block - checkpoint_block = get_checkpoint_block( - store, block_header.parent_root, store.finalized_checkpoint.epoch - ) - if checkpoint_block != store.finalized_checkpoint.root: + finalized_epoch = store.finalized_checkpoint.epoch + finalized_checkpoint_block = get_checkpoint_block(store, parent_root, finalized_epoch) + if finalized_checkpoint_block != store.finalized_checkpoint.root: raise GossipReject("finalized checkpoint is not an ancestor of blob sidecar's block") # [REJECT] The sidecar's inclusion proof is valid as verified by verify_blob_sidecar_inclusion_proof @@ -14849,7 +15369,7 @@ # [REJECT] The sidecar is proposed by the expected proposer_index # (if shuffling is not available, IGNORE instead and MAY be queued for later) - parent_state = store.block_states[block_header.parent_root].copy() + parent_state = store.block_states[parent_root].copy() process_slots(parent_state, block_header.slot) expected_proposer = get_beacon_proposer_index(parent_state) if block_header.proposer_index != expected_proposer: @@ -14921,7 +15441,7 @@ - name: validate_data_column_sidecar_gossip#fulu sources: [] spec: | - + def validate_data_column_sidecar_gossip( seen: Seen, store: Store, @@ -14938,8 +15458,8 @@ # [IGNORE] The sidecar is the first sidecar for the tuple # (block_header.slot, block_header.proposer_index, sidecar.index) - sidecar_tuple = (block_header.slot, block_header.proposer_index, sidecar.index) - if sidecar_tuple in seen.data_column_sidecar_tuples: + sidecar_key = (block_header.slot, block_header.proposer_index, sidecar.index) + if sidecar_key in seen.data_column_sidecar_tuples: raise GossipIgnore("already seen sidecar from this proposer for this slot and index") # [REJECT] The sidecar is valid as verified by verify_data_column_sidecar @@ -14952,7 +15472,7 @@ # [IGNORE] The sidecar is not from a future slot # (MAY be queued for processing at the appropriate slot) - if not is_not_from_future_slot(state, block_header.slot, current_time_ms): + if is_future_slot(store, block_header.slot, current_time_ms): raise GossipIgnore("sidecar is from a future slot") # [IGNORE] The sidecar is from a slot greater than the latest finalized slot @@ -14973,22 +15493,22 @@ # [IGNORE] The sidecar's block's parent has been seen # (MAY be queued for processing once the parent block is retrieved) - if block_header.parent_root not in store.blocks: + parent_root = block_header.parent_root + if parent_root not in store.blocks: raise GossipIgnore("sidecar's parent has not been seen") # [REJECT] The sidecar's block's parent passes validation - if block_header.parent_root not in store.block_states: + if parent_root not in store.block_states: raise GossipReject("sidecar's parent failed validation") # [REJECT] The sidecar is from a higher slot than the sidecar's block's parent - if block_header.slot <= store.blocks[block_header.parent_root].slot: + if block_header.slot <= store.blocks[parent_root].slot: raise GossipReject("sidecar is not from a higher slot than its parent") # [REJECT] The current finalized_checkpoint is an ancestor of the sidecar's block - checkpoint_block = get_checkpoint_block( - store, block_header.parent_root, store.finalized_checkpoint.epoch - ) - if checkpoint_block != store.finalized_checkpoint.root: + finalized_epoch = store.finalized_checkpoint.epoch + finalized_checkpoint_block = get_checkpoint_block(store, parent_root, finalized_epoch) + if finalized_checkpoint_block != store.finalized_checkpoint.root: raise GossipReject("finalized checkpoint is not an ancestor of sidecar's block") # [REJECT] The sidecar is valid as verified by verify_data_column_sidecar_inclusion_proof @@ -15001,20 +15521,275 @@ # [REJECT] The sidecar is proposed by the expected proposer_index # (if shuffling is not available, IGNORE instead and MAY be queued for later) - parent_state = store.block_states[block_header.parent_root].copy() + parent_state = store.block_states[parent_root].copy() process_slots(parent_state, block_header.slot) expected_proposer = get_beacon_proposer_index(parent_state) if block_header.proposer_index != expected_proposer: raise GossipReject("sidecar proposer_index does not match expected proposer") # Mark this data column sidecar as seen - seen.data_column_sidecar_tuples.add(sidecar_tuple) + seen.data_column_sidecar_tuples.add(sidecar_key) + + +- name: validate_data_column_sidecar_gossip#gloas + sources: [] + spec: | + + def validate_data_column_sidecar_gossip( + seen: Seen, + store: Store, + # [Modified in Gloas:EIP7732] + # Removed `state` + sidecar: DataColumnSidecar, + current_time_ms: Uint64, + subnet_id: SubnetID, + ) -> None: + """ + Validate a DataColumnSidecar for gossip propagation on a subnet. + Raises GossipIgnore or GossipReject on validation failure. + """ + # [IGNORE] This is the first sidecar seen for this block root and column index + sidecar_key = (sidecar.beacon_block_root, sidecar.index) + if sidecar_key in seen.data_column_sidecar_tuples: + raise GossipIgnore("already seen sidecar for this block root and index") + + # [REJECT] The sidecar is for the correct subnet + if compute_subnet_for_data_column_sidecar(sidecar.index) != subnet_id: + raise GossipReject("sidecar is for wrong subnet") + + # [IGNORE] The sidecar is not from a future slot + # (MAY be queued for processing at the appropriate slot) + if is_future_slot(store, sidecar.slot, current_time_ms): + raise GossipIgnore("sidecar is from a future slot") + + # [IGNORE] A block for the sidecar has been seen (via gossip or non-gossip sources) + # (MAY be queued until block is retrieved) + # (SHOULD queue at least one sidecar per peer per subnet) + if sidecar.beacon_block_root not in store.blocks: + raise GossipIgnore("block for sidecar's beacon block root has not been seen") + + # [REJECT] The block for the sidecar passes validation + if sidecar.beacon_block_root not in store.block_states: + raise GossipReject("block for sidecar's beacon block root failed validation") + + block = store.blocks[sidecar.beacon_block_root] + + # [REJECT] The sidecar's slot matches the slot of the block + if sidecar.slot != block.slot: + raise GossipReject("sidecar's slot does not match block's slot") + + bid = block.body.signed_execution_payload_bid.message + + # [REJECT] The sidecar passes structural validation + if not verify_data_column_sidecar(sidecar, bid.blob_kzg_commitments): + raise GossipReject("invalid sidecar") + + # [REJECT] The sidecar's column data passes KZG verification + if not verify_data_column_sidecar_kzg_proofs(sidecar, bid.blob_kzg_commitments): + raise GossipReject("invalid sidecar kzg proofs") + + # Mark this data column sidecar as seen + seen.data_column_sidecar_tuples.add(sidecar_key) + + +- name: validate_execution_payload_bid_gossip#gloas + sources: [] + spec: | + + def validate_execution_payload_bid_gossip( + seen: Seen, + store: Store, + state: BeaconState, + signed_execution_payload_bid: SignedExecutionPayloadBid, + current_time_ms: Uint64, + ) -> None: + """ + Validate a SignedExecutionPayloadBid for gossip propagation. + Raises GossipIgnore or GossipReject on validation failure. + """ + bid = signed_execution_payload_bid.message + + # [IGNORE] The bid's slot is the current slot or the next slot + if not is_current_or_next_slot(store, bid.slot, current_time_ms): + raise GossipIgnore("bid's slot is not the current or next slot") + + # [IGNORE] This is the first bid for this slot, parent, and builder + bid_key = (bid.slot, bid.parent_block_hash, bid.parent_block_root, bid.builder_index) + if bid_key in seen.execution_payload_bids: + raise GossipIgnore("already seen valid bid for this slot, parent, and builder") + + # [IGNORE] This is the highest value bid seen for the slot and parent + best_bid_key = (bid.slot, bid.parent_block_hash, bid.parent_block_root) + if best_bid_key in seen.best_execution_payload_bid: + if bid.value <= seen.best_execution_payload_bid[best_bid_key]: + raise GossipIgnore("bid is not the highest value bid seen for this slot and parent") + + # [REJECT] The bid is for a higher slot than its parent block + if bid.slot <= state.slot: + raise GossipReject("bid's slot is not higher than its parent's slot") + + # [REJECT] The bid's execution payment is zero + if bid.execution_payment != 0: + raise GossipReject("bid's execution payment must be zero") + + # [REJECT] The bid's blob KZG commitment count is within the per-epoch limit + proposal_epoch = compute_epoch_at_slot(bid.slot) + max_blobs = get_blob_parameters(proposal_epoch).max_blobs_per_block + if len(bid.blob_kzg_commitments) > max_blobs: + raise GossipReject("too many blob kzg commitments") + + # [IGNORE] The bid's parent block root is a known beacon block + # (MAY be queued until parent is retrieved) + if bid.parent_block_root not in store.blocks: + raise GossipIgnore("bid's parent block root is not a known beacon block") + + # [IGNORE] The state is the bid's parent block post-state + parent_block = store.blocks[bid.parent_block_root] + header = state.latest_block_header.copy() + header.state_root = parent_block.state_root + if hash_tree_root(header) != bid.parent_block_root: + raise GossipIgnore("state is not the bid's parent block post-state") + + # [IGNORE] The bid's slot is within the parent's proposer lookahead + if proposal_epoch > get_current_epoch(state) + Epoch(MIN_SEED_LOOKAHEAD): + raise GossipIgnore("bid's slot is past the parent's proposer lookahead") + + # [IGNORE] The matching proposer preferences have been seen + dependent_root = get_shuffling_dependent_root(store, bid.parent_block_root, proposal_epoch) + prefs_key = (dependent_root, bid.slot) + if prefs_key not in seen.proposer_preferences: + raise GossipIgnore("matching proposer preferences have not been seen") + + proposer_preferences = seen.proposer_preferences[prefs_key] + + # [IGNORE] The bid's fee recipient matches the proposer's preference + if bid.fee_recipient != proposer_preferences.fee_recipient: + raise GossipIgnore("bid's fee recipient does not match the proposer's preference") + + # [IGNORE] The bid's parent block hash is the hash of a known execution payload + if bid.parent_block_hash not in seen.execution_payloads: + raise GossipIgnore("bid's parent block hash is not a known execution payload") + + # [IGNORE] The bid's gas limit is compatible with the proposer's target gas limit + parent_gas_limit = seen.execution_payloads[bid.parent_block_hash].gas_limit + if not is_gas_limit_target_compatible( + parent_gas_limit, bid.gas_limit, proposer_preferences.target_gas_limit + ): + raise GossipIgnore("bid's gas limit is not compatible with the proposer's target") + + # [IGNORE] The bid is compatible with the current head branch + if not is_bid_compatible_with_head(store, bid): + raise GossipIgnore("bid is not compatible with the current head branch") + + # [REJECT] The bid's previous randao is correct + if bid.prev_randao != get_randao_mix(state, get_current_epoch(state)): + raise GossipReject("bid's previous randao is incorrect") + + # Advance state + state = state.copy() + process_slots(state, bid.slot) + + # [REJECT] The builder index is valid + if bid.builder_index >= len(state.builders): + raise GossipReject("builder index out of range") + + # [IGNORE] The builder can cover the bid + if not can_builder_cover_bid(state, bid.builder_index, bid.value): + raise GossipIgnore("builder cannot cover bid value") + + # [REJECT] The builder is active + if not is_active_builder(state, bid.builder_index): + raise GossipReject("builder is not active") + + # [REJECT] The builder is a payload builder + if state.builders[bid.builder_index].version != PAYLOAD_BUILDER_VERSION: + raise GossipReject("builder is not a payload builder") + + # [REJECT] The bid signature is valid + if not verify_execution_payload_bid_signature(state, signed_execution_payload_bid): + raise GossipReject("invalid bid signature") + + # Mark this bid as seen and update the highest-value bid for this slot/parent + seen.execution_payload_bids.add(bid_key) + seen.best_execution_payload_bid[best_bid_key] = bid.value + + +- name: validate_execution_payload_envelope_gossip#gloas + sources: [] + spec: | + + def validate_execution_payload_envelope_gossip( + seen: Seen, + store: Store, + state: BeaconState, + signed_execution_payload_envelope: SignedExecutionPayloadEnvelope, + ) -> None: + """ + Validate a SignedExecutionPayloadEnvelope for gossip propagation. + Raises GossipIgnore or GossipReject on validation failure. + """ + envelope = signed_execution_payload_envelope.message + payload = envelope.payload + block_root = envelope.beacon_block_root + + # [IGNORE] The envelope's block root has been seen (via gossip or non-gossip sources) + # (MAY be queued until block is retrieved) + if block_root not in store.blocks: + raise GossipIgnore("envelope's block has not been seen") + + # [REJECT] The envelope's block passes validation + if block_root not in store.block_states: + raise GossipReject("envelope's block failed validation") + + # [IGNORE] The node has not seen another valid envelope for this block root from this builder + envelope_key = (block_root, envelope.builder_index) + if envelope_key in seen.execution_payload_envelopes: + raise GossipIgnore("already seen envelope for this block root from this builder") + + # [IGNORE] The envelope is from a slot greater than or equal to the latest finalized slot + finalized_slot = compute_start_slot_at_epoch(store.finalized_checkpoint.epoch) + if payload.slot_number < finalized_slot: + raise GossipIgnore("envelope is from a slot before the latest finalized slot") + + block = store.blocks[block_root] + bid = block.body.signed_execution_payload_bid.message + + # [REJECT] The block's slot matches the payload's slot number + if block.slot != payload.slot_number: + raise GossipReject("block's slot does not match payload's slot number") + + # [REJECT] The envelope is from the builder committed to by the bid + if envelope.builder_index != bid.builder_index: + raise GossipReject("envelope's builder index does not match the bid's builder index") + + # [REJECT] The payload's block hash matches the bid's block hash + if payload.block_hash != bid.block_hash: + raise GossipReject("payload's block hash does not match the bid's block hash") + + # [REJECT] The envelope's execution requests root matches the bid's execution requests root + if hash_tree_root(envelope.execution_requests) != bid.execution_requests_root: + raise GossipReject("envelope's execution requests root does not match the bid's") + + # [REJECT] The execution request counts are within their limits + verify_execution_requests_limits(envelope.execution_requests) + + # [REJECT] The number of withdrawals is within the limit + if len(payload.withdrawals) > MAX_WITHDRAWALS_PER_PAYLOAD: + raise GossipReject("too many withdrawals") + + # [REJECT] The envelope signature is valid + if not verify_execution_payload_envelope_signature(state, signed_execution_payload_envelope): + raise GossipReject("invalid envelope signature") + + # Mark this envelope as seen and store its payload + seen.execution_payload_envelopes.add(envelope_key) + seen.execution_payloads[payload.block_hash] = payload - name: validate_light_client_update#altair sources: [] spec: | - + def validate_light_client_update( store: LightClientStore, update: LightClientUpdate, @@ -15023,7 +15798,7 @@ ) -> None: # Verify sync committee has sufficient participants sync_aggregate = update.sync_aggregate - assert sum(sync_aggregate.sync_committee_bits) >= MIN_SYNC_COMMITTEE_PARTICIPANTS + assert get_set_bit_count(sync_aggregate.sync_committee_bits) >= MIN_SYNC_COMMITTEE_PARTICIPANTS # Verify update does not skip a sync committee period assert is_valid_light_client_header(update.attested_header) @@ -15211,7 +15986,7 @@ - name: validate_partial_data_column_sidecar_gossip#fulu sources: [] spec: | - + def validate_partial_data_column_sidecar_gossip( seen: Seen, store: Store, @@ -15226,7 +16001,7 @@ Raises GossipIgnore or GossipReject on validation failure. """ has_header = len(sidecar.header) == 1 - num_cells_present = sum(1 for b in sidecar.cells_present_bitmap if b) + num_cells_present = get_set_bit_count(sidecar.cells_present_bitmap) has_cells = num_cells_present > 0 # [REJECT] A header and/or cells are present in the message @@ -15260,7 +16035,7 @@ # [IGNORE] The header is not from a future slot # (MAY be queued for processing at the appropriate slot) - if not is_not_from_future_slot(state, block_header.slot, current_time_ms): + if is_future_slot(store, block_header.slot, current_time_ms): raise GossipIgnore("header is from a future slot") # [IGNORE] The header is from a slot greater than the latest finalized slot @@ -15281,22 +16056,22 @@ # [IGNORE] The header's block's parent has been seen # (MAY be queued for processing once the parent block is retrieved) - if block_header.parent_root not in store.blocks: + parent_root = block_header.parent_root + if parent_root not in store.blocks: raise GossipIgnore("header's parent has not been seen") # [REJECT] The header's block's parent passes validation - if block_header.parent_root not in store.block_states: + if parent_root not in store.block_states: raise GossipReject("header's parent failed validation") # [REJECT] The header is from a higher slot than the header's block's parent - if block_header.slot <= store.blocks[block_header.parent_root].slot: + if block_header.slot <= store.blocks[parent_root].slot: raise GossipReject("header is not from a higher slot than its parent") # [REJECT] The current finalized_checkpoint is an ancestor of the header's block - checkpoint_block = get_checkpoint_block( - store, block_header.parent_root, store.finalized_checkpoint.epoch - ) - if checkpoint_block != store.finalized_checkpoint.root: + finalized_epoch = store.finalized_checkpoint.epoch + finalized_checkpoint_block = get_checkpoint_block(store, parent_root, finalized_epoch) + if finalized_checkpoint_block != store.finalized_checkpoint.root: raise GossipReject("finalized checkpoint is not an ancestor of header's block") # [REJECT] The header's kzg_commitments inclusion proof is valid @@ -15305,7 +16080,7 @@ # [REJECT] The header is proposed by the expected proposer_index # (if shuffling is not available, IGNORE instead and MAY be queued for later) - parent_state = store.block_states[block_header.parent_root].copy() + parent_state = store.block_states[parent_root].copy() process_slots(parent_state, block_header.slot) expected_proposer = get_beacon_proposer_index(parent_state) if block_header.proposer_index != expected_proposer: @@ -15324,7 +16099,7 @@ # [IGNORE] The corresponding header is not from a future slot # (MAY be queued for processing at the appropriate slot) - if not is_not_from_future_slot(state, block_header.slot, current_time_ms): + if is_future_slot(store, block_header.slot, current_time_ms): raise GossipIgnore("corresponding header is from a future slot") # [IGNORE] The corresponding header is from a slot greater than the latest finalized slot @@ -15345,6 +16120,201 @@ raise GossipReject("invalid sidecar kzg proofs") +- name: validate_partial_data_column_sidecar_gossip#gloas + sources: [] + spec: | + + def validate_partial_data_column_sidecar_gossip( + # [Modified in Gloas:EIP7732] + # Removed `seen` + store: Store, + # [Modified in Gloas:EIP7732] + # Removed `state` + sidecar: PartialDataColumnSidecar, + # [Modified in Gloas:EIP7732] + # Removed `current_time_ms` + group_id: PartialDataColumnGroupID, + column_index: ColumnIndex, + ) -> None: + """ + Validate a PartialDataColumnSidecar for gossip propagation on a subnet. + Raises GossipIgnore or GossipReject on validation failure. + """ + num_cells_present = get_set_bit_count(sidecar.cells_present_bitmap) + + # [Modified in Gloas:EIP7732] + # [REJECT] The message contains at least one cell + if num_cells_present == 0: + raise GossipReject("partial message is semantically empty") + + # [REJECT] The cell count equals the number of set bits in the bitmap + if len(sidecar.partial_column) != num_cells_present: + raise GossipReject("number of cells does not match number of set bits") + + # [REJECT] The proof count equals the number of set bits in the bitmap + if len(sidecar.kzg_proofs) != num_cells_present: + raise GossipReject("number of proofs does not match number of set bits") + + # [New in Gloas:EIP7732] + # [IGNORE] The group ID's block has been seen (via gossip or non-gossip sources) + # (MAY be queued until block is retrieved) + # (SHOULD queue at least one sidecar per peer per subnet) + if group_id.beacon_block_root not in store.blocks: + raise GossipIgnore("group id's block has not been seen") + + # [New in Gloas:EIP7732] + # [REJECT] The group ID's block passes validation + if group_id.beacon_block_root not in store.block_states: + raise GossipReject("group id's block failed validation") + + block = store.blocks[group_id.beacon_block_root] + + # [New in Gloas:EIP7732] + # [REJECT] The group ID's slot matches the slot of the block + if group_id.slot != block.slot: + raise GossipReject("group id's slot does not match the block's slot") + + bid = block.body.signed_execution_payload_bid.message + + # [Modified in Gloas:EIP7732] + # [REJECT] The cells present bitmap length equals the number of bid commitments + if len(sidecar.cells_present_bitmap) != len(bid.blob_kzg_commitments): + raise GossipReject("bitmap length does not match commitments length") + + # [Modified in Gloas:EIP7732] + # [REJECT] The sidecar's cell and proof data passes KZG verification + if not verify_partial_data_column_sidecar_kzg_proofs( + sidecar, bid.blob_kzg_commitments, column_index + ): + raise GossipReject("invalid sidecar kzg proofs") + + +- name: validate_payload_attestation_message_gossip#gloas + sources: [] + spec: | + + def validate_payload_attestation_message_gossip( + seen: Seen, + store: Store, + state: BeaconState, + payload_attestation_message: PayloadAttestationMessage, + current_time_ms: Uint64, + ) -> None: + """ + Validate a PayloadAttestationMessage for gossip propagation. + Raises GossipIgnore or GossipReject on validation failure. + """ + data = payload_attestation_message.data + validator_index = payload_attestation_message.validator_index + + # [IGNORE] The payload attestation's slot is the current slot + if not is_current_slot(store, data.slot, current_time_ms): + raise GossipIgnore("payload attestation's slot is not the current slot") + + # [IGNORE] This is the first valid payload attestation from this validator index + payload_attestation_key = (data.slot, validator_index) + if payload_attestation_key in seen.payload_attestation_validators: + raise GossipIgnore("already seen payload attestation from this validator") + + # [IGNORE] The payload attestation's block has been seen (via gossip or non-gossip sources) + # (MAY be queued until block is retrieved) + if data.beacon_block_root not in store.blocks: + raise GossipIgnore("payload attestation's block has not been seen") + + # [REJECT] The payload attestation's block passes validation + if data.beacon_block_root not in store.block_states: + raise GossipReject("payload attestation's block failed validation") + + # [IGNORE] The payload attestation's block is at the assigned slot + if store.blocks[data.beacon_block_root].slot != data.slot: + raise GossipIgnore("payload attestation's block is not at the assigned slot") + + # [REJECT] The validator index is valid + if validator_index >= len(state.validators): + raise GossipReject("validator index out of range") + + # [REJECT] The validator is a member of the payload timeliness committee + if validator_index not in get_ptc(state, data.slot): + raise GossipReject("validator is not in the payload timeliness committee") + + # [REJECT] The signature is valid with respect to the validator's public key + validator = state.validators[validator_index] + domain = get_domain(state, DOMAIN_PTC_ATTESTER, compute_epoch_at_slot(data.slot)) + signing_root = compute_signing_root(data, domain) + if not bls.Verify(validator.pubkey, signing_root, payload_attestation_message.signature): + raise GossipReject("invalid payload attestation signature") + + # Mark this payload_attestation as seen + seen.payload_attestation_validators.add(payload_attestation_key) + + +- name: validate_proposer_preferences_gossip#gloas + sources: [] + spec: | + + def validate_proposer_preferences_gossip( + seen: Seen, + store: Store, + signed_proposer_preferences: SignedProposerPreferences, + current_time_ms: Uint64, + ) -> None: + """ + Validate a SignedProposerPreferences for gossip propagation. + Raises GossipIgnore or GossipReject on validation failure. + """ + preferences = signed_proposer_preferences.message + proposal_epoch = compute_epoch_at_slot(preferences.proposal_slot) + + # [IGNORE] The proposal slot has not started yet + if is_past_slot(store, preferences.proposal_slot, current_time_ms): + raise GossipIgnore("proposal slot has already started") + + # [IGNORE] The proposer for the proposal slot is known + lookahead_epoch = Epoch(proposal_epoch - MIN_SEED_LOOKAHEAD) + lookahead_epoch_start_slot = compute_start_slot_at_epoch(lookahead_epoch) + if is_future_slot(store, lookahead_epoch_start_slot, current_time_ms): + raise GossipIgnore("proposer for the proposal slot is not yet known") + + # [IGNORE] The dependent block has been seen (via gossip or non-gossip sources) + # (MAY be queued until block is retrieved) + if preferences.dependent_root not in store.blocks: + raise GossipIgnore("dependent block has not been seen") + + # [IGNORE] These are the first valid preferences seen for this dependent root and slot + prefs_key = (preferences.dependent_root, preferences.proposal_slot) + if prefs_key in seen.proposer_preferences: + raise GossipIgnore("already seen preferences for this dependent root and proposal slot") + + # [IGNORE] The dependent block passes validation + if preferences.dependent_root not in store.block_states: + raise GossipIgnore("dependent block failed validation") + + # [REJECT] The dependent root is a valid dependent block for the proposal slot + if store.blocks[preferences.dependent_root].slot >= lookahead_epoch_start_slot: + raise GossipReject("dependent root is not before the proposer lookahead epoch") + + # [IGNORE] The dependent root is a possible dependent block for the lookahead epoch + if not is_valid_dependent_root(store, preferences.dependent_root, lookahead_epoch): + raise GossipIgnore("dependent root is not a possible dependent block") + + # [REJECT] The validator is the proposer for the given slot in the proposer lookahead + lookahead_state = store.block_states[preferences.dependent_root].copy() + process_slots(lookahead_state, lookahead_epoch_start_slot) + lookahead_index = preferences.proposal_slot - lookahead_epoch_start_slot + if lookahead_state.proposer_lookahead[lookahead_index] != preferences.validator_index: + raise GossipReject("validator is not the proposer for the given slot") + + # [REJECT] The signature is valid with respect to the validator's public key + validator = lookahead_state.validators[preferences.validator_index] + domain = get_domain(lookahead_state, DOMAIN_PROPOSER_PREFERENCES, proposal_epoch) + signing_root = compute_signing_root(preferences, domain) + if not bls.Verify(validator.pubkey, signing_root, signed_proposer_preferences.signature): + raise GossipReject("invalid proposer preferences signature") + + # Mark these preferences as seen + seen.proposer_preferences[prefs_key] = preferences + + - name: validate_proposer_slashing_gossip#phase0 sources: [] spec: | @@ -15403,9 +16373,10 @@ - name: validate_sync_committee_contribution_and_proof_gossip#altair sources: [] spec: | - + def validate_sync_committee_contribution_and_proof_gossip( seen: Seen, + store: Store, state: BeaconState, signed_contribution_and_proof: SignedContributionAndProof, current_time_ms: Uint64, @@ -15418,7 +16389,7 @@ contribution = contribution_and_proof.contribution # [IGNORE] The contribution's slot is for the current slot - if not is_current_slot(state, contribution.slot, current_time_ms): + if not is_current_slot(store, contribution.slot, current_time_ms): raise GossipIgnore("contribution is not for the current slot") # [REJECT] The subcommittee index is in the allowed range @@ -15458,11 +16429,11 @@ raise GossipIgnore("already seen contribution for this data") # [IGNORE] The sync committee contribution is the first valid contribution received - # for the aggregator with index contribution_and_proof.aggregator_index - # for the slot contribution.slot and subcommittee index contribution.subcommittee_index + # for the slot contribution.slot, aggregator with index contribution_and_proof.aggregator_index, + # and subcommittee index contribution.subcommittee_index aggregator_key = ( - contribution_and_proof.aggregator_index, contribution.slot, + contribution_and_proof.aggregator_index, contribution.subcommittee_index, ) if aggregator_key in seen.sync_contribution_aggregator_slots: @@ -15511,9 +16482,10 @@ - name: validate_sync_committee_message_gossip#altair sources: [] spec: | - + def validate_sync_committee_message_gossip( seen: Seen, + store: Store, state: BeaconState, sync_committee_message: SyncCommitteeMessage, current_time_ms: Uint64, @@ -15524,7 +16496,7 @@ Raises GossipIgnore or GossipReject on validation failure. """ # [IGNORE] The message's slot is for the current slot - if not is_current_slot(state, sync_committee_message.slot, current_time_ms): + if not is_current_slot(store, sync_committee_message.slot, current_time_ms): raise GossipIgnore("message is not for the current slot") # [REJECT] The validator index is valid @@ -15686,6 +16658,46 @@ seen.voluntary_exit_indices.add(validator_index) +- name: verify_attestation_payload_status#gloas + sources: [] + spec: | + + def verify_attestation_payload_status( + store: Store, + data: AttestationData, + block_payload_statuses: Dict[Root, PayloadValidationStatus], + ) -> None: + """ + Verify that the attested payload status is consistent with the block's payload. + Raises GossipIgnore or GossipReject on validation failure. + """ + block_root = data.beacon_block_root + block = store.blocks[block_root] + + # [REJECT] For same-slot attestations, the payload cannot yet be present + if block.slot == data.slot and data.index != 0: + raise GossipReject("same-slot attestation must attest with index 0") + + if data.index != 1: + return + + # [IGNORE] The corresponding execution payload envelope has been seen and verified + # (MAY queue attestations for processing once the payload is retrieved and + # SHOULD request the payload envelope via ExecutionPayloadEnvelopesByRoot + # using data.beacon_block_root) + if not is_payload_verified(store, block_root): + raise GossipIgnore("execution payload envelope has not been seen") + + # [IGNORE] The attested execution payload is optimistic + payload_status = block_payload_statuses.get(block_root, PAYLOAD_STATUS_NOT_VALIDATED) + if payload_status == PAYLOAD_STATUS_NOT_VALIDATED: + raise GossipIgnore("attested payload is optimistic") + + # [REJECT] The attested execution payload is processed and invalid + if payload_status == PAYLOAD_STATUS_INVALIDATED: + raise GossipReject("attested payload is invalid") + + - name: verify_blob_sidecar_inclusion_proof#deneb sources: - file: consensus-types/blocks/kzg.go @@ -15705,6 +16717,44 @@ ) +- name: verify_block_body_operation_limits#gloas + sources: [] + spec: | + + def verify_block_body_operation_limits(body: BeaconBlockBody) -> None: + """ + Verify that each block body operation count is within its limit. + Raises GossipReject on validation failure. + """ + # [REJECT] The proposer slashing count is within the limit + if len(body.proposer_slashings) > MAX_PROPOSER_SLASHINGS: + raise GossipReject("too many proposer slashings") + + # [REJECT] The attester slashing count is within the limit + if len(body.attester_slashings) > MAX_ATTESTER_SLASHINGS_ELECTRA: + raise GossipReject("too many attester slashings") + + # [REJECT] The attestation count is within the limit + if len(body.attestations) > MAX_ATTESTATIONS_ELECTRA: + raise GossipReject("too many attestations") + + # [REJECT] The block contains no deposits + if len(body.deposits) != 0: + raise GossipReject("block must not contain deposits") + + # [REJECT] The voluntary exit count is within the limit + if len(body.voluntary_exits) > MAX_VOLUNTARY_EXITS: + raise GossipReject("too many voluntary exits") + + # [REJECT] The BLS to execution change count is within the limit + if len(body.bls_to_execution_changes) > MAX_BLS_TO_EXECUTION_CHANGES: + raise GossipReject("too many bls to execution changes") + + # [REJECT] The payload attestation count is within the limit + if len(body.payload_attestations) > MAX_PAYLOAD_ATTESTATIONS: + raise GossipReject("too many payload attestations") + + - name: verify_block_signature#phase0 sources: - file: beacon-chain/core/blocks/signature.go @@ -15724,7 +16774,7 @@ - file: beacon-chain/core/peerdas/p2p_interface.go search: func VerifyDataColumnSidecar( spec: | - + def verify_data_column_sidecar(sidecar: DataColumnSidecar) -> bool: """ Verify if the data column sidecar is valid. @@ -15742,10 +16792,12 @@ if len(sidecar.kzg_commitments) > get_blob_parameters(epoch).max_blobs_per_block: return False - # The column length must be equal to the number of commitments/proofs - if len(sidecar.column) != len(sidecar.kzg_commitments) or len(sidecar.column) != len( - sidecar.kzg_proofs - ): + # The column length must be equal to the number of commitments + if len(sidecar.column) != len(sidecar.kzg_commitments): + return False + + # The column length must be equal to the number of proofs + if len(sidecar.column) != len(sidecar.kzg_proofs): return False return True @@ -15754,11 +16806,11 @@ - name: verify_data_column_sidecar#gloas sources: [] spec: | - + def verify_data_column_sidecar( sidecar: DataColumnSidecar, # [New in Gloas:EIP7732] - kzg_commitments: ProgressiveList[KZGCommitment], + kzg_commitments: BlobKZGCommitments, ) -> bool: """ Verify if the data column sidecar is valid. @@ -15773,10 +16825,12 @@ return False # [Modified in Gloas:EIP7732] - # The column length must be equal to the number of commitments/proofs - if len(sidecar.column) != len(kzg_commitments) or len(sidecar.column) != len( - sidecar.kzg_proofs - ): + # The column length must be equal to the number of commitments + if len(sidecar.column) != len(kzg_commitments): + return False + + # The column length must be equal to the number of proofs + if len(sidecar.column) != len(sidecar.kzg_proofs): return False return True @@ -15906,6 +16960,32 @@ return bls.Verify(pubkey, signing_root, signed_envelope.signature) +- name: verify_execution_requests_limits#gloas + sources: [] + spec: | + + def verify_execution_requests_limits(execution_requests: ExecutionRequests) -> None: + """ + Verify that each execution request count is within its limit. + Raises GossipReject on validation failure. + """ + # [REJECT] The withdrawal request count is within the limit + if len(execution_requests.withdrawals) > MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD: + raise GossipReject("too many withdrawal requests") + + # [REJECT] The consolidation request count is within the limit + if len(execution_requests.consolidations) > MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD: + raise GossipReject("too many consolidation requests") + + # [REJECT] The builder deposit request count is within the limit + if len(execution_requests.builder_deposits) > MAX_BUILDER_DEPOSIT_REQUESTS_PER_PAYLOAD: + raise GossipReject("too many builder deposit requests") + + # [REJECT] The builder exit request count is within the limit + if len(execution_requests.builder_exits) > MAX_BUILDER_EXIT_REQUESTS_PER_PAYLOAD: + raise GossipReject("too many builder exit requests") + + - name: verify_partial_data_column_header_inclusion_proof#fulu sources: [] spec: | @@ -15926,10 +17006,10 @@ - name: verify_partial_data_column_sidecar_kzg_proofs#fulu sources: [] spec: | - + def verify_partial_data_column_sidecar_kzg_proofs( sidecar: PartialDataColumnSidecar, - all_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK], + all_commitments: BlobKZGCommitments, column_index: ColumnIndex, ) -> bool: """ From 2955b3b5caa3deba21fa518f0987e97333f58d9e Mon Sep 17 00:00:00 2001 From: terence Date: Wed, 19 Aug 2026 13:50:02 -0700 Subject: [PATCH 21/23] Disallow proposer reorgs at epoch boundaries before Fulu --- .../forkchoice/doubly-linked-tree/reorg_late_blocks.go | 10 ++++++++++ .../doubly-linked-tree/reorg_late_blocks_test.go | 8 ++++++++ 2 files changed, 18 insertions(+) diff --git a/beacon-chain/forkchoice/doubly-linked-tree/reorg_late_blocks.go b/beacon-chain/forkchoice/doubly-linked-tree/reorg_late_blocks.go index 689758c69192..465714e757d7 100644 --- a/beacon-chain/forkchoice/doubly-linked-tree/reorg_late_blocks.go +++ b/beacon-chain/forkchoice/doubly-linked-tree/reorg_late_blocks.go @@ -46,6 +46,12 @@ func (f *ForkChoice) ShouldOverrideFCU() (override bool) { return } + // is_shuffling_stable, removed in Fulu by EIP-7917 + proposalSlot := consensusHead.slot + 1 + if slots.ToEpoch(proposalSlot) < params.BeaconConfig().FuluForkEpoch && slots.IsEpochStart(proposalSlot) { + return + } + head := f.store.choosePayloadContent(consensusHead) // Only reorg blocks that arrive late early, err := head.arrivedEarly(f.store.genesisTime) @@ -112,6 +118,10 @@ func (f *ForkChoice) GetProposerHead() [32]byte { if consensusHead.slot+1 != currentSlot { return consensusHead.root } + // is_shuffling_stable, removed in Fulu by EIP-7917 + if slots.ToEpoch(currentSlot) < params.BeaconConfig().FuluForkEpoch && slots.IsEpochStart(currentSlot) { + return consensusHead.root + } // Only reorg blocks that arrive late head := f.store.choosePayloadContent(consensusHead) if slots.ToEpoch(consensusHead.slot) >= params.BeaconConfig().GloasForkEpoch { diff --git a/beacon-chain/forkchoice/doubly-linked-tree/reorg_late_blocks_test.go b/beacon-chain/forkchoice/doubly-linked-tree/reorg_late_blocks_test.go index 02844c0e511c..87b874057e8d 100644 --- a/beacon-chain/forkchoice/doubly-linked-tree/reorg_late_blocks_test.go +++ b/beacon-chain/forkchoice/doubly-linked-tree/reorg_late_blocks_test.go @@ -186,6 +186,10 @@ func TestForkChoice_GetProposerHead(t *testing.T) { // Regression test: a weak, late head whose next slot lands on an epoch boundary // must still be reorgeable. Reorgs used to be skipped on epoch boundaries. func TestForkChoice_ShouldOverrideFCU_EpochBoundary(t *testing.T) { + params.SetupTestConfigCleanup(t) + cfg := params.BeaconConfig().Copy() + cfg.FuluForkEpoch = 0 + params.OverrideBeaconConfig(cfg) f := setup(0, 0) numValidators := uint64(640) f.justifiedBalances = make([]uint64, numValidators) @@ -223,6 +227,10 @@ func TestForkChoice_ShouldOverrideFCU_EpochBoundary(t *testing.T) { // Regression test: GetProposerHead must orphan a weak, late head even when the // proposing slot is an epoch boundary. func TestForkChoice_GetProposerHead_EpochBoundary(t *testing.T) { + params.SetupTestConfigCleanup(t) + cfg := params.BeaconConfig().Copy() + cfg.FuluForkEpoch = 0 + params.OverrideBeaconConfig(cfg) f := setup(0, 0) numValidators := uint64(640) f.justifiedBalances = make([]uint64, numValidators) From 9926459f745f939bae6c17c0173fc7eb0db5889c Mon Sep 17 00:00:00 2001 From: terence Date: Wed, 19 Aug 2026 14:14:33 -0700 Subject: [PATCH 22/23] Recognize alpha.14 config fields in the config loader test --- config/params/loader_test.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/config/params/loader_test.go b/config/params/loader_test.go index cefb2189589f..c6fa7fcb0909 100644 --- a/config/params/loader_test.go +++ b/config/params/loader_test.go @@ -38,6 +38,8 @@ var placeholderFields = []string{ "EIP7928_FORK_VERSION", "EIP8025_FORK_EPOCH", "EIP8025_FORK_VERSION", + "EIP8321_FORK_EPOCH", + "EIP8321_FORK_VERSION", "EPOCHS_PER_SHUFFLING_PHASE", "FIELD_ELEMENTS_PER_CELL", // Configured as a constant in config/fieldparams/mainnet.go "FIELD_ELEMENTS_PER_EXT_BLOB", // Configured in proto/ssz_proto_library.bzl @@ -47,8 +49,8 @@ var placeholderFields = []string{ "INCLUSION_LIST_DUE_BPS", "INCLUSION_LIST_SUBMISSION_DEADLINE", "KZG_COMMITMENTS_INCLUSION_PROOF_DEPTH", // Configured in proto/ssz_proto_library.bzl - "MAX_BYTES_PER_INCLUSION_LIST", "MAX_REQUEST_INCLUSION_LIST", + "MAX_TRANSACTIONS_BYTES_PER_INCLUSION_LIST", "MIN_SLOTS_FOR_INCLUSION_LISTS_REQUESTS", "NUMBER_OF_COLUMNS", // Configured as a constant in config/fieldparams/mainnet.go "TARGET_NUMBER_OF_PEERS", @@ -429,7 +431,10 @@ func assertYamlFieldsMatch(t *testing.T, name string, fields []string, c1, c2 *p v1 := reflect.ValueOf(*c1).Field(i).Interface() v2 := reflect.ValueOf(*c2).Field(i).Interface() if reflect.ValueOf(v1).Kind() == reflect.Slice { - assert.DeepEqual(t, v1, v2, "%s: %s", name, field) + // A nil slice and an empty yaml list are equivalent configs. + if reflect.ValueOf(v1).Len() != 0 || reflect.ValueOf(v2).Len() != 0 { + assert.DeepEqual(t, v1, v2, "%s: %s", name, field) + } } else { assert.Equal(t, v1, v2, "%s: %s", name, field) } From 8d02cafc0b9b5c2380c0a28c70c1b6f1e02c4170 Mon Sep 17 00:00:00 2001 From: Bastin <43618253+Inspector-Butters@users.noreply.github.com> Date: Thu, 20 Aug 2026 14:56:36 +0200 Subject: [PATCH 23/23] Fix quadratic BLS signature verification during Gloas builder onboarding (#17387) --- .../core/gloas/payload_attestation_test.go | 6 +- beacon-chain/core/gloas/upgrade.go | 6 +- beacon-chain/core/gloas/upgrade_test.go | 14 +- beacon-chain/core/transition/transition.go | 2 +- beacon-chain/db/kv/state_diff_test.go | 2 +- beacon-chain/state/interfaces_gloas.go | 4 +- .../state/state-native/setters_gloas.go | 80 +++++++- .../state/state-native/setters_gloas_test.go | 183 +++++++++++++++++- consensus-types/hdiff/state_diff.go | 2 +- .../hdiff/state_diff_gloas_test.go | 6 +- .../shared/gloas/fork/upgrade_to_gloas.go | 2 +- testing/util/gloas_state.go | 2 +- 12 files changed, 275 insertions(+), 34 deletions(-) diff --git a/beacon-chain/core/gloas/payload_attestation_test.go b/beacon-chain/core/gloas/payload_attestation_test.go index 7929e400ffef..73924a26a583 100644 --- a/beacon-chain/core/gloas/payload_attestation_test.go +++ b/beacon-chain/core/gloas/payload_attestation_test.go @@ -329,7 +329,7 @@ func signAttestation(t *testing.T, st state.ReadOnlyBeaconState, data *eth.Paylo func TestProcessPTCWindow(t *testing.T) { fuluSt, _ := testutil.DeterministicGenesisStateFulu(t, 256) - st, err := gloas.UpgradeToGloas(fuluSt) + st, err := gloas.UpgradeToGloas(t.Context(), fuluSt) require.NoError(t, err) slotsPerEpoch := params.BeaconConfig().SlotsPerEpoch @@ -376,7 +376,7 @@ func TestProcessPTCWindow(t *testing.T) { // state, guarding against unintended behavioral drift. func TestProcessPTCWindow_GoldenVector(t *testing.T) { fuluSt, _ := testutil.DeterministicGenesisStateFulu(t, 256) - st, err := gloas.UpgradeToGloas(fuluSt) + st, err := gloas.UpgradeToGloas(t.Context(), fuluSt) require.NoError(t, err) require.NoError(t, st.SetSlot(params.BeaconConfig().SlotsPerEpoch)) require.NoError(t, gloas.ProcessPTCWindow(t.Context(), st)) @@ -426,7 +426,7 @@ func (s *validatorLookupErrState) ValidatorAtIndexReadOnly(idx primitives.Valida // what's expected: we skipped SHA256 work, not memory traffic. func BenchmarkProcessPTCWindow(b *testing.B) { fuluSt, _ := testutil.DeterministicGenesisStateFulu(b, 2048) - st, err := gloas.UpgradeToGloas(fuluSt) + st, err := gloas.UpgradeToGloas(b.Context(), fuluSt) require.NoError(b, err) require.NoError(b, st.SetSlot(params.BeaconConfig().SlotsPerEpoch)) diff --git a/beacon-chain/core/gloas/upgrade.go b/beacon-chain/core/gloas/upgrade.go index 763635747639..b0f119fc6b5b 100644 --- a/beacon-chain/core/gloas/upgrade.go +++ b/beacon-chain/core/gloas/upgrade.go @@ -116,19 +116,19 @@ import ( // // return post // -func UpgradeToGloas(beaconState state.BeaconState) (state.BeaconState, error) { +func UpgradeToGloas(ctx context.Context, beaconState state.BeaconState) (state.BeaconState, error) { s, err := upgradeToGloas(beaconState) if err != nil { return nil, errors.Wrap(err, "could not convert to gloas") } - ptcWindow, err := initializePTCWindow(context.Background(), s) + ptcWindow, err := initializePTCWindow(ctx, s) if err != nil { return nil, errors.Wrap(err, "failed to initialize ptc window") } if err := s.SetPTCWindow(ptcWindow); err != nil { return nil, errors.Wrap(err, "failed to set ptc window") } - if err := s.OnboardBuildersFromPendingDeposits(); err != nil { + if err := s.OnboardBuildersFromPendingDeposits(ctx); err != nil { return nil, errors.Wrap(err, "failed to onboard builders from pending deposits") } return s, nil diff --git a/beacon-chain/core/gloas/upgrade_test.go b/beacon-chain/core/gloas/upgrade_test.go index 9dfd70982ef1..c2890a26c95f 100644 --- a/beacon-chain/core/gloas/upgrade_test.go +++ b/beacon-chain/core/gloas/upgrade_test.go @@ -2,6 +2,7 @@ package gloas_test import ( "bytes" + "context" "testing" "github.com/OffchainLabs/prysm/v7/beacon-chain/core/gloas" @@ -20,6 +21,15 @@ import ( "github.com/OffchainLabs/prysm/v7/time/slots" ) +func TestUpgradeToGloas_ContextCancellation(t *testing.T) { + st, _ := util.DeterministicGenesisStateFulu(t, params.BeaconConfig().MaxValidatorsPerCommittee) + ctx, cancel := context.WithCancel(t.Context()) + cancel() + + _, err := gloas.UpgradeToGloas(ctx, st) + require.ErrorIs(t, err, context.Canceled) +} + func TestUpgradeToGloas_Basic(t *testing.T) { st, _ := util.DeterministicGenesisStateFulu(t, params.BeaconConfig().MaxValidatorsPerCommittee) @@ -44,7 +54,7 @@ func TestUpgradeToGloas_Basic(t *testing.T) { require.NoError(t, st.SetLatestExecutionPayloadHeader(wrappedHeader)) preForkState := st.Copy() - mSt, err := gloas.UpgradeToGloas(st) + mSt, err := gloas.UpgradeToGloas(t.Context(), st) require.NoError(t, err) require.Equal(t, preForkState.GenesisTime(), mSt.GenesisTime()) @@ -119,7 +129,7 @@ func TestUpgradeToGloas_OnboardsBuilderDeposit(t *testing.T) { require.NoError(t, st.SetPendingDeposits([]*ethpb.PendingDeposit{deposit})) - mSt, err := gloas.UpgradeToGloas(st) + mSt, err := gloas.UpgradeToGloas(t.Context(), st) require.NoError(t, err) pbState, ok := mSt.ToProtoUnsafe().(*ethpb.BeaconStateGloas) diff --git a/beacon-chain/core/transition/transition.go b/beacon-chain/core/transition/transition.go index bbb3d6bf97fe..22c59548e7e4 100644 --- a/beacon-chain/core/transition/transition.go +++ b/beacon-chain/core/transition/transition.go @@ -425,7 +425,7 @@ func UpgradeState(ctx context.Context, state state.BeaconState) (state.BeaconSta } if time.CanUpgradeToGloas(slot) { - state, err = gloas.UpgradeToGloas(state) + state, err = gloas.UpgradeToGloas(ctx, state) if err != nil { tracing.AnnotateError(span, err) return nil, err diff --git a/beacon-chain/db/kv/state_diff_test.go b/beacon-chain/db/kv/state_diff_test.go index d33be67c04a0..de8fa028550b 100644 --- a/beacon-chain/db/kv/state_diff_test.go +++ b/beacon-chain/db/kv/state_diff_test.go @@ -746,7 +746,7 @@ func TestStateDiff_SaveAndReadDiffForkTransitionGloas(t *testing.T) { require.NoError(t, err) slot := primitives.Slot(math.PowerOf2(5)) - gloasSt, err := gloas.UpgradeToGloas(st.Copy()) + gloasSt, err := gloas.UpgradeToGloas(t.Context(), st.Copy()) require.NoError(t, err) require.NoError(t, gloasSt.SetSlot(slot)) diff --git a/beacon-chain/state/interfaces_gloas.go b/beacon-chain/state/interfaces_gloas.go index ea39e3e3387a..6f4280d84076 100644 --- a/beacon-chain/state/interfaces_gloas.go +++ b/beacon-chain/state/interfaces_gloas.go @@ -1,6 +1,8 @@ package state import ( + "context" + fieldparams "github.com/OffchainLabs/prysm/v7/config/fieldparams" "github.com/OffchainLabs/prysm/v7/consensus-types/interfaces" "github.com/OffchainLabs/prysm/v7/consensus-types/primitives" @@ -45,7 +47,7 @@ type writeOnlyGloasFields interface { DecreaseWithdrawalBalances(withdrawals []*enginev1.Withdrawal) error DequeueBuilderPendingWithdrawals(num uint64) error SetNextWithdrawalBuilderIndex(idx primitives.BuilderIndex) error - OnboardBuildersFromPendingDeposits() error + OnboardBuildersFromPendingDeposits(context.Context) error } type readOnlyGloasFields interface { diff --git a/beacon-chain/state/state-native/setters_gloas.go b/beacon-chain/state/state-native/setters_gloas.go index c5cd26e8cd75..140aae766f52 100644 --- a/beacon-chain/state/state-native/setters_gloas.go +++ b/beacon-chain/state/state-native/setters_gloas.go @@ -1,6 +1,7 @@ package state_native import ( + "context" "errors" "fmt" @@ -681,6 +682,17 @@ func decreaseBalanceWithVal(currBalance, delta primitives.Gwei) primitives.Gwei return currBalance - delta } +type depositSignatureVerifier func(*ethpb.Deposit_Data) (bool, error) + +// pendingValidatorStatus caches signature checks for the already-processed prefix of pending +// deposits for one pubkey. A literal implementation of is_pending_validator rescans and +// reverifies that prefix for every builder deposit, which can require quadratic work. +type pendingValidatorStatus struct { + deposits []*ethpb.PendingDeposit + checked int + found bool +} + // OnboardBuildersFromPendingDeposits applies any pending builder deposits at the fork. // It mutates the state and prunes pending deposits accordingly. // @@ -736,18 +748,31 @@ func decreaseBalanceWithVal(currBalance, delta primitives.Gwei) primitives.Gwei // // state.pending_deposits = pending_deposits // -func (b *BeaconState) OnboardBuildersFromPendingDeposits() error { +func (b *BeaconState) OnboardBuildersFromPendingDeposits(ctx context.Context) error { + return b.onboardBuildersFromPendingDeposits(ctx, helpers.IsValidDepositSignature) +} + +func (b *BeaconState) onboardBuildersFromPendingDeposits(ctx context.Context, verify depositSignatureVerifier) error { if b.version < version.Gloas { return errNotSupported("OnboardBuildersFromPendingDeposits", b.version) } + if err := ctx.Err(); err != nil { + return err + } b.lock.Lock() defer b.lock.Unlock() pendingDeposits := b.pendingDeposits newPendingDeposits := make([]*ethpb.PendingDeposit, 0, len(pendingDeposits)) + // For every pubkey in this map, found is true exactly when the already-built + // newPendingDeposits prefix contains a valid deposit for that pubkey. + pendingValidators := make(map[[fieldparams.BLSPubkeyLength]byte]*pendingValidatorStatus) for _, deposit := range pendingDeposits { + if err := ctx.Err(); err != nil { + return err + } pubkey := bytesutil.ToBytes48(deposit.PublicKey) if _, ok := b.validatorIndexByPubkey(pubkey); ok { newPendingDeposits = append(newPendingDeposits, deposit) @@ -764,21 +789,54 @@ func (b *BeaconState) OnboardBuildersFromPendingDeposits() error { if !helpers.IsBuilderWithdrawalCredential(deposit.WithdrawalCredentials) { newPendingDeposits = append(newPendingDeposits, deposit) + status := pendingValidators[pubkey] + if status == nil { + status = &pendingValidatorStatus{} + pendingValidators[pubkey] = status + } + if !status.found { + status.deposits = append(status.deposits, deposit) + } continue } - isPending, err := helpers.IsPendingValidator(newPendingDeposits, deposit.PublicKey) - if err != nil { - return err + + status := pendingValidators[pubkey] + if status != nil { + // Verify only deposits appended since the previous builder candidate. Invalid + // deposits remain in the pending queue but never need to be verified again here. + for !status.found && status.checked < len(status.deposits) { + if err := ctx.Err(); err != nil { + return err + } + pendingDeposit := status.deposits[status.checked] + status.checked++ + valid, err := verify(ðpb.Deposit_Data{ + PublicKey: pendingDeposit.PublicKey, + WithdrawalCredentials: pendingDeposit.WithdrawalCredentials, + Amount: pendingDeposit.Amount, + Signature: pendingDeposit.Signature, + }) + if err != nil { + log.WithField("pubkey", fmt.Sprintf("%x", pendingDeposit.PublicKey)).WithError(err).Warn("Could not verify pending deposit signature") + continue + } + if valid { + status.found = true + } + } } - if isPending { + if status != nil && status.found { newPendingDeposits = append(newPendingDeposits, deposit) continue } - if err := b.applyDepositForNewBuilder(deposit); err != nil { + if err := b.applyDepositForNewBuilder(ctx, deposit, verify); err != nil { return err } } + if err := ctx.Err(); err != nil { + return err + } b.sharedFieldReferences[types.PendingDeposits].MinusRef() b.sharedFieldReferences[types.PendingDeposits] = stateutil.NewRef(1) @@ -789,8 +847,11 @@ func (b *BeaconState) OnboardBuildersFromPendingDeposits() error { } // applyDepositForNewBuilder onboards a single pending deposit as a new builder, used by onboard_builders_from_pending_deposits. -func (b *BeaconState) applyDepositForNewBuilder(deposit *ethpb.PendingDeposit) error { - valid, err := helpers.IsValidDepositSignature(ðpb.Deposit_Data{ +func (b *BeaconState) applyDepositForNewBuilder(ctx context.Context, deposit *ethpb.PendingDeposit, verify depositSignatureVerifier) error { + if err := ctx.Err(); err != nil { + return err + } + valid, err := verify(ðpb.Deposit_Data{ PublicKey: deposit.PublicKey, WithdrawalCredentials: deposit.WithdrawalCredentials, Amount: deposit.Amount, @@ -804,6 +865,9 @@ func (b *BeaconState) applyDepositForNewBuilder(deposit *ethpb.PendingDeposit) e log.WithField("pubkey", fmt.Sprintf("%x", deposit.PublicKey)).Debug("Skipping builder deposit with invalid signature") return nil } + if err := ctx.Err(); err != nil { + return err + } pubkey := bytesutil.ToBytes48(deposit.PublicKey) depositEpoch := slots.ToEpoch(deposit.Slot) if err := b.addBuilderFromDepositAtEpoch(pubkey, params.BeaconConfig().PayloadBuilderVersion, bytesutil.ToBytes32(deposit.WithdrawalCredentials), deposit.Amount, depositEpoch); err != nil { diff --git a/beacon-chain/state/state-native/setters_gloas_test.go b/beacon-chain/state/state-native/setters_gloas_test.go index 8c2d5a22d9e8..2d59d6ff9797 100644 --- a/beacon-chain/state/state-native/setters_gloas_test.go +++ b/beacon-chain/state/state-native/setters_gloas_test.go @@ -2,6 +2,7 @@ package state_native import ( "bytes" + "context" "testing" "github.com/OffchainLabs/prysm/v7/beacon-chain/core/signing" @@ -1004,7 +1005,7 @@ func TestAddBuilderFromDeposit_CopyOnWrite(t *testing.T) { func TestOnboardBuildersFromPendingDeposits(t *testing.T) { t.Run("returns error before gloas", func(t *testing.T) { st := &BeaconState{version: version.Fulu} - err := st.OnboardBuildersFromPendingDeposits() + err := st.OnboardBuildersFromPendingDeposits(t.Context()) require.ErrorContains(t, "OnboardBuildersFromPendingDeposits", err) }) @@ -1023,7 +1024,7 @@ func TestOnboardBuildersFromPendingDeposits(t *testing.T) { } st := newGloasState(t, []*ethpb.Validator{validator}, nil, []*ethpb.PendingDeposit{deposit}, 0) - require.NoError(t, st.OnboardBuildersFromPendingDeposits()) + require.NoError(t, st.OnboardBuildersFromPendingDeposits(t.Context())) require.Equal(t, 1, len(st.pendingDeposits)) require.Equal(t, 0, len(st.builders)) }) @@ -1037,7 +1038,7 @@ func TestOnboardBuildersFromPendingDeposits(t *testing.T) { deposit := newPendingDeposit(t, sk, builderCreds, amount, depSlot, true) st := newGloasState(t, nil, nil, []*ethpb.PendingDeposit{deposit}, 0) - require.NoError(t, st.OnboardBuildersFromPendingDeposits()) + require.NoError(t, st.OnboardBuildersFromPendingDeposits(t.Context())) require.Equal(t, 0, len(st.pendingDeposits)) require.Equal(t, 1, len(st.builders)) @@ -1061,7 +1062,7 @@ func TestOnboardBuildersFromPendingDeposits(t *testing.T) { deposit := newPendingDeposit(t, sk, nonBuilderCreds, 5, 0, false) st := newGloasState(t, nil, []*ethpb.Builder{builder}, []*ethpb.PendingDeposit{deposit}, 0) - require.NoError(t, st.OnboardBuildersFromPendingDeposits()) + require.NoError(t, st.OnboardBuildersFromPendingDeposits(t.Context())) require.Equal(t, 0, len(st.pendingDeposits)) require.Equal(t, 1, len(st.builders)) require.Equal(t, primitives.Gwei(15), st.builders[0].Balance) @@ -1074,7 +1075,7 @@ func TestOnboardBuildersFromPendingDeposits(t *testing.T) { deposit := newPendingDeposit(t, sk, builderCreds, 10, 0, false) st := newGloasState(t, nil, nil, []*ethpb.PendingDeposit{deposit}, 0) - require.NoError(t, st.OnboardBuildersFromPendingDeposits()) + require.NoError(t, st.OnboardBuildersFromPendingDeposits(t.Context())) require.Equal(t, 0, len(st.pendingDeposits)) require.Equal(t, 0, len(st.builders)) }) @@ -1089,11 +1090,27 @@ func TestOnboardBuildersFromPendingDeposits(t *testing.T) { depositBuilder := newPendingDeposit(t, sk, builderCreds, 7, 0, true) st := newGloasState(t, nil, nil, []*ethpb.PendingDeposit{depositValidator, depositBuilder}, 0) - require.NoError(t, st.OnboardBuildersFromPendingDeposits()) + require.NoError(t, st.OnboardBuildersFromPendingDeposits(t.Context())) require.Equal(t, 2, len(st.pendingDeposits)) require.Equal(t, 0, len(st.builders)) }) + t.Run("builder deposit before validator deposit creates builder", func(t *testing.T) { + sk, err := bls.RandKey() + require.NoError(t, err) + builderCreds := builderWithdrawalCredentials(0xEF) + validatorCreds := nonBuilderWithdrawalCredentials() + + depositBuilder := newPendingDeposit(t, sk, builderCreds, 7, 0, true) + depositValidator := newPendingDeposit(t, sk, validatorCreds, 5, 0, true) + + st := newGloasState(t, nil, nil, []*ethpb.PendingDeposit{depositBuilder, depositValidator}, 0) + require.NoError(t, st.OnboardBuildersFromPendingDeposits(t.Context())) + require.Equal(t, 0, len(st.pendingDeposits)) + require.Equal(t, 1, len(st.builders)) + require.Equal(t, primitives.Gwei(12), st.builders[0].Balance) + }) + t.Run("keeps invalid non-builder deposit in pending queue", func(t *testing.T) { sk, err := bls.RandKey() require.NoError(t, err) @@ -1101,7 +1118,7 @@ func TestOnboardBuildersFromPendingDeposits(t *testing.T) { deposit := newPendingDeposit(t, sk, validatorCreds, 5, 0, false) st := newGloasState(t, nil, nil, []*ethpb.PendingDeposit{deposit}, 0) - require.NoError(t, st.OnboardBuildersFromPendingDeposits()) + require.NoError(t, st.OnboardBuildersFromPendingDeposits(t.Context())) require.Equal(t, 1, len(st.pendingDeposits)) require.Equal(t, 0, len(st.builders)) }) @@ -1115,7 +1132,7 @@ func TestOnboardBuildersFromPendingDeposits(t *testing.T) { depositTopUp := newPendingDeposit(t, sk, builderCreds, 5, depSlot, true) st := newGloasState(t, nil, nil, []*ethpb.PendingDeposit{depositCreate, depositTopUp}, 0) - require.NoError(t, st.OnboardBuildersFromPendingDeposits()) + require.NoError(t, st.OnboardBuildersFromPendingDeposits(t.Context())) require.Equal(t, 0, len(st.pendingDeposits)) require.Equal(t, 1, len(st.builders)) require.Equal(t, primitives.Gwei(15), st.builders[0].Balance) @@ -1131,7 +1148,7 @@ func TestOnboardBuildersFromPendingDeposits(t *testing.T) { depositBuilder := newPendingDeposit(t, sk, builderCreds, 7, 0, true) st := newGloasState(t, nil, nil, []*ethpb.PendingDeposit{depositInvalidValidator, depositBuilder}, 0) - require.NoError(t, st.OnboardBuildersFromPendingDeposits()) + require.NoError(t, st.OnboardBuildersFromPendingDeposits(t.Context())) require.Equal(t, 1, len(st.pendingDeposits)) require.DeepEqual(t, depositInvalidValidator, st.pendingDeposits[0]) require.Equal(t, 1, len(st.builders)) @@ -1139,6 +1156,154 @@ func TestOnboardBuildersFromPendingDeposits(t *testing.T) { }) } +func TestOnboardBuildersFromPendingDeposits_VerificationWorkIsLinear(t *testing.T) { + t.Run("invalid pending deposits are checked once", func(t *testing.T) { + const ( + pendingCount = 100 + builderCount = 50 + ) + pubkey := bytes.Repeat([]byte{0x42}, fieldparams.BLSPubkeyLength) + pendingDeposits := make([]*ethpb.PendingDeposit, 0, pendingCount+builderCount) + for i := range pendingCount { + pendingDeposits = append(pendingDeposits, ðpb.PendingDeposit{ + PublicKey: pubkey, + WithdrawalCredentials: nonBuilderWithdrawalCredentials(), + Amount: uint64(i + 1), + Signature: make([]byte, fieldparams.BLSSignatureLength), + }) + } + for i := range builderCount { + pendingDeposits = append(pendingDeposits, ðpb.PendingDeposit{ + PublicKey: pubkey, + WithdrawalCredentials: builderWithdrawalCredentials(byte(i)), + Amount: uint64(pendingCount + i + 1), + Signature: make([]byte, fieldparams.BLSSignatureLength), + }) + } + + st := newGloasState(t, nil, nil, pendingDeposits, 0) + verificationCount := 0 + err := st.onboardBuildersFromPendingDeposits(t.Context(), func(*ethpb.Deposit_Data) (bool, error) { + verificationCount++ + return false, nil + }) + require.NoError(t, err) + + // Each retained pending deposit and each builder candidate is verified at most once. + // The previous implementation performed pendingCount*builderCount+builderCount checks. + require.Equal(t, pendingCount+builderCount, verificationCount) + require.Equal(t, pendingCount, len(st.pendingDeposits)) + require.Equal(t, 0, len(st.builders)) + }) + + t.Run("valid pending validator result is reused", func(t *testing.T) { + const builderCount = 50 + pubkey := bytes.Repeat([]byte{0x43}, fieldparams.BLSPubkeyLength) + pendingDeposits := []*ethpb.PendingDeposit{ + { + PublicKey: pubkey, + WithdrawalCredentials: nonBuilderWithdrawalCredentials(), + Amount: 1, + }, + { + PublicKey: pubkey, + WithdrawalCredentials: nonBuilderWithdrawalCredentials(), + Amount: 2, + }, + } + for i := range builderCount { + pendingDeposits = append(pendingDeposits, ðpb.PendingDeposit{ + PublicKey: pubkey, + WithdrawalCredentials: builderWithdrawalCredentials(byte(i)), + Amount: uint64(i + 3), + }) + } + + st := newGloasState(t, nil, nil, pendingDeposits, 0) + verificationCount := 0 + err := st.onboardBuildersFromPendingDeposits(t.Context(), func(data *ethpb.Deposit_Data) (bool, error) { + verificationCount++ + return data.Amount == 2, nil + }) + require.NoError(t, err) + + require.Equal(t, 2, verificationCount) + require.Equal(t, len(pendingDeposits), len(st.pendingDeposits)) + require.Equal(t, 0, len(st.builders)) + }) + + t.Run("only newly appended pending deposits are checked", func(t *testing.T) { + pubkey := bytes.Repeat([]byte{0x45}, fieldparams.BLSPubkeyLength) + pendingDeposits := []*ethpb.PendingDeposit{ + { + PublicKey: pubkey, + WithdrawalCredentials: nonBuilderWithdrawalCredentials(), + Amount: 1, + }, + { + PublicKey: pubkey, + WithdrawalCredentials: builderWithdrawalCredentials(0xA1), + Amount: 2, + }, + { + PublicKey: pubkey, + WithdrawalCredentials: nonBuilderWithdrawalCredentials(), + Amount: 3, + }, + { + PublicKey: pubkey, + WithdrawalCredentials: builderWithdrawalCredentials(0xA2), + Amount: 4, + }, + { + PublicKey: pubkey, + WithdrawalCredentials: builderWithdrawalCredentials(0xA3), + Amount: 5, + }, + } + + st := newGloasState(t, nil, nil, pendingDeposits, 0) + verifiedAmounts := make([]uint64, 0, len(pendingDeposits)) + err := st.onboardBuildersFromPendingDeposits(t.Context(), func(data *ethpb.Deposit_Data) (bool, error) { + verifiedAmounts = append(verifiedAmounts, data.Amount) + return false, nil + }) + require.NoError(t, err) + + require.DeepEqual(t, []uint64{1, 2, 3, 4, 5}, verifiedAmounts) + require.Equal(t, 2, len(st.pendingDeposits)) + require.Equal(t, 0, len(st.builders)) + }) +} + +func TestOnboardBuildersFromPendingDeposits_ContextCancellation(t *testing.T) { + pubkey := bytes.Repeat([]byte{0x44}, fieldparams.BLSPubkeyLength) + pendingDeposits := []*ethpb.PendingDeposit{ + { + PublicKey: pubkey, + WithdrawalCredentials: nonBuilderWithdrawalCredentials(), + Amount: 1, + }, + { + PublicKey: pubkey, + WithdrawalCredentials: builderWithdrawalCredentials(0xAA), + Amount: 2, + }, + } + st := newGloasState(t, nil, nil, pendingDeposits, 0) + ctx, cancel := context.WithCancel(t.Context()) + verificationCount := 0 + err := st.onboardBuildersFromPendingDeposits(ctx, func(*ethpb.Deposit_Data) (bool, error) { + verificationCount++ + cancel() + return false, nil + }) + require.ErrorIs(t, err, context.Canceled) + require.Equal(t, 1, verificationCount) + require.Equal(t, len(pendingDeposits), len(st.pendingDeposits)) + require.Equal(t, 0, len(st.builders)) +} + func newGloasState( t *testing.T, validators []*ethpb.Validator, diff --git a/consensus-types/hdiff/state_diff.go b/consensus-types/hdiff/state_diff.go index c5a354dd964e..fae4c786278b 100644 --- a/consensus-types/hdiff/state_diff.go +++ b/consensus-types/hdiff/state_diff.go @@ -2211,7 +2211,7 @@ func updateToVersion(ctx context.Context, source state.BeaconState, target int) case version.Electra: ret, err = fulu.ConvertToFulu(source) case version.Fulu: - ret, err = gloas.UpgradeToGloas(source) + ret, err = gloas.UpgradeToGloas(ctx, source) default: return nil, errors.Errorf("unsupported version %s", version.String(source.Version())) } diff --git a/consensus-types/hdiff/state_diff_gloas_test.go b/consensus-types/hdiff/state_diff_gloas_test.go index 6932701ac91f..7dbffec00821 100644 --- a/consensus-types/hdiff/state_diff_gloas_test.go +++ b/consensus-types/hdiff/state_diff_gloas_test.go @@ -19,7 +19,7 @@ import ( func gloasState(t testing.TB, numValidators uint64) (state.BeaconState, error) { fuluState, _ := util.DeterministicGenesisStateFulu(t, numValidators) - return gloas.UpgradeToGloas(fuluState) + return gloas.UpgradeToGloas(t.Context(), fuluState) } func requireEqualState(t testing.TB, expected, actual state.BeaconState) { @@ -244,7 +244,7 @@ func TestGloasCrossForkDiff(t *testing.T) { // Test Fulu → Gloas cross-fork diff via updateToVersion. fuluSource, _ := util.DeterministicGenesisStateFulu(t, 64) - gloasTarget, err := gloas.UpgradeToGloas(fuluSource.Copy()) + gloasTarget, err := gloas.UpgradeToGloas(t.Context(), fuluSource.Copy()) require.NoError(t, err) require.NoError(t, gloasTarget.SetSlot(fuluSource.Slot()+1)) @@ -280,7 +280,7 @@ func TestGloasCrossForkDiffOnboardsBuilderDeposit(t *testing.T) { Slot: 0, }})) - gloasTarget, err := gloas.UpgradeToGloas(fuluSource.Copy()) + gloasTarget, err := gloas.UpgradeToGloas(t.Context(), fuluSource.Copy()) require.NoError(t, err) require.NoError(t, gloasTarget.SetSlot(fuluSource.Slot()+1)) diff --git a/testing/spectest/shared/gloas/fork/upgrade_to_gloas.go b/testing/spectest/shared/gloas/fork/upgrade_to_gloas.go index 76c0e7e0573a..d39f01191108 100644 --- a/testing/spectest/shared/gloas/fork/upgrade_to_gloas.go +++ b/testing/spectest/shared/gloas/fork/upgrade_to_gloas.go @@ -38,7 +38,7 @@ func RunUpgradeToGloas(t *testing.T, config string) { } preState, err := state_native.InitializeFromProtoFulu(preStateBase) require.NoError(t, err) - postState, err := gloas.UpgradeToGloas(preState) + postState, err := gloas.UpgradeToGloas(t.Context(), preState) require.NoError(t, err) postStateFromFunction, err := state_native.ProtobufBeaconStateGloas(postState.ToProtoUnsafe()) require.NoError(t, err) diff --git a/testing/util/gloas_state.go b/testing/util/gloas_state.go index c431235ba3ff..805154d9d47c 100644 --- a/testing/util/gloas_state.go +++ b/testing/util/gloas_state.go @@ -15,7 +15,7 @@ func DeterministicGenesisStateGloas(t testing.TB, numValidators uint64) (state.B t.Helper() fuluState, privKeys := DeterministicGenesisStateFulu(t, numValidators) - beaconState, err := gloas.UpgradeToGloas(fuluState) + beaconState, err := gloas.UpgradeToGloas(t.Context(), fuluState) if err != nil { t.Fatal(errors.Wrapf(err, "failed to upgrade genesis beacon state of %d validators to gloas", numValidators)) }