From cd87082f25890409bd626b7bac44897a997a2e21 Mon Sep 17 00:00:00 2001 From: Bastin <43618253+Inspector-Butters@users.noreply.github.com> Date: Mon, 14 Apr 2025 12:57:31 +0200 Subject: [PATCH] Refactor lc tests (#15155) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor setUpAltair * remove debug code * refactor bellatrix setup * refactor capella setup * refactor rest - core tests remain * refactor tests to use new functional options utils * use the options * add noFinalizedCheckpoint and finalizedCheckpointInPrevFork options * add tests * changelog entry * refactor tests * deps * Update testing/util/lightclient.go Co-authored-by: Radosław Kapka * Update testing/util/lightclient.go Co-authored-by: Radosław Kapka * Update testing/util/lightclient.go Co-authored-by: Radosław Kapka * address comments * address comments * address comments * go mod tidy * fix annoying conflicts * go mod tidy --------- Co-authored-by: Radosław Kapka --- beacon-chain/blockchain/process_block_test.go | 24 +- beacon-chain/core/light-client/BUILD.bazel | 1 + .../core/light-client/lightclient_test.go | 47 +- beacon-chain/core/light-client/store_test.go | 5 +- .../rpc/eth/light-client/handlers_test.go | 22 +- changelog/bastin_refactor-lc-testutils.md | 3 + testing/util/BUILD.bazel | 2 + testing/util/lightclient.go | 1542 ++++++++--------- testing/util/lightclient_test.go | 71 + 9 files changed, 813 insertions(+), 904 deletions(-) create mode 100644 changelog/bastin_refactor-lc-testutils.md create mode 100644 testing/util/lightclient_test.go diff --git a/beacon-chain/blockchain/process_block_test.go b/beacon-chain/blockchain/process_block_test.go index a708ed03f4..fee90168ad 100644 --- a/beacon-chain/blockchain/process_block_test.go +++ b/beacon-chain/blockchain/process_block_test.go @@ -2653,7 +2653,7 @@ func TestSaveLightClientUpdate(t *testing.T) { t.Run("Altair", func(t *testing.T) { t.Run("No old update", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestAltair(0, true) + l := util.NewTestLightClient(t, version.Altair) s.genesisTime = time.Unix(time.Now().Unix()-(int64(params.BeaconConfig().AltairForkEpoch)*int64(params.BeaconConfig().SlotsPerEpoch)*int64(params.BeaconConfig().SecondsPerSlot)), 0) @@ -2699,7 +2699,7 @@ func TestSaveLightClientUpdate(t *testing.T) { }) t.Run("New update is better", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestAltair(0, true) + l := util.NewTestLightClient(t, version.Altair) s.genesisTime = time.Unix(time.Now().Unix()-(int64(params.BeaconConfig().AltairForkEpoch)*int64(params.BeaconConfig().SlotsPerEpoch)*int64(params.BeaconConfig().SecondsPerSlot)), 0) @@ -2751,7 +2751,7 @@ func TestSaveLightClientUpdate(t *testing.T) { }) t.Run("Old update is better", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestAltair(0, false) + l := util.NewTestLightClient(t, version.Altair) s.genesisTime = time.Unix(time.Now().Unix()-(int64(params.BeaconConfig().AltairForkEpoch)*int64(params.BeaconConfig().SlotsPerEpoch)*int64(params.BeaconConfig().SecondsPerSlot)), 0) @@ -2812,7 +2812,7 @@ func TestSaveLightClientUpdate(t *testing.T) { t.Run("Capella", func(t *testing.T) { t.Run("No old update", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestCapella(false, 0, true) + l := util.NewTestLightClient(t, version.Capella) s.genesisTime = time.Unix(time.Now().Unix()-(int64(params.BeaconConfig().CapellaForkEpoch)*int64(params.BeaconConfig().SlotsPerEpoch)*int64(params.BeaconConfig().SecondsPerSlot)), 0) @@ -2857,7 +2857,7 @@ func TestSaveLightClientUpdate(t *testing.T) { }) t.Run("New update is better", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestCapella(false, 0, true) + l := util.NewTestLightClient(t, version.Capella) s.genesisTime = time.Unix(time.Now().Unix()-(int64(params.BeaconConfig().CapellaForkEpoch)*int64(params.BeaconConfig().SlotsPerEpoch)*int64(params.BeaconConfig().SecondsPerSlot)), 0) @@ -2909,7 +2909,7 @@ func TestSaveLightClientUpdate(t *testing.T) { }) t.Run("Old update is better", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestCapella(false, 0, false) + l := util.NewTestLightClient(t, version.Capella) s.genesisTime = time.Unix(time.Now().Unix()-(int64(params.BeaconConfig().CapellaForkEpoch)*int64(params.BeaconConfig().SlotsPerEpoch)*int64(params.BeaconConfig().SecondsPerSlot)), 0) @@ -2970,7 +2970,7 @@ func TestSaveLightClientUpdate(t *testing.T) { t.Run("Deneb", func(t *testing.T) { t.Run("No old update", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestDeneb(false, 0, true) + l := util.NewTestLightClient(t, version.Deneb) s.genesisTime = time.Unix(time.Now().Unix()-(int64(params.BeaconConfig().DenebForkEpoch)*int64(params.BeaconConfig().SlotsPerEpoch)*int64(params.BeaconConfig().SecondsPerSlot)), 0) @@ -3015,7 +3015,7 @@ func TestSaveLightClientUpdate(t *testing.T) { }) t.Run("New update is better", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestDeneb(false, 0, true) + l := util.NewTestLightClient(t, version.Deneb) s.genesisTime = time.Unix(time.Now().Unix()-(int64(params.BeaconConfig().DenebForkEpoch)*int64(params.BeaconConfig().SlotsPerEpoch)*int64(params.BeaconConfig().SecondsPerSlot)), 0) @@ -3067,7 +3067,7 @@ func TestSaveLightClientUpdate(t *testing.T) { }) t.Run("Old update is better", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestDeneb(false, 0, false) + l := util.NewTestLightClient(t, version.Deneb) s.genesisTime = time.Unix(time.Now().Unix()-(int64(params.BeaconConfig().DenebForkEpoch)*int64(params.BeaconConfig().SlotsPerEpoch)*int64(params.BeaconConfig().SecondsPerSlot)), 0) @@ -3138,7 +3138,7 @@ func TestSaveLightClientBootstrap(t *testing.T) { ctx := tr.ctx t.Run("Altair", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestAltair(0, true) + l := util.NewTestLightClient(t, version.Altair) s.genesisTime = time.Unix(time.Now().Unix()-(int64(params.BeaconConfig().AltairForkEpoch)*int64(params.BeaconConfig().SlotsPerEpoch)*int64(params.BeaconConfig().SecondsPerSlot)), 0) @@ -3173,7 +3173,7 @@ func TestSaveLightClientBootstrap(t *testing.T) { }) t.Run("Capella", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestCapella(false, 0, true) + l := util.NewTestLightClient(t, version.Capella) s.genesisTime = time.Unix(time.Now().Unix()-(int64(params.BeaconConfig().CapellaForkEpoch)*int64(params.BeaconConfig().SlotsPerEpoch)*int64(params.BeaconConfig().SecondsPerSlot)), 0) @@ -3208,7 +3208,7 @@ func TestSaveLightClientBootstrap(t *testing.T) { }) t.Run("Deneb", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestDeneb(false, 0, true) + l := util.NewTestLightClient(t, version.Deneb) s.genesisTime = time.Unix(time.Now().Unix()-(int64(params.BeaconConfig().DenebForkEpoch)*int64(params.BeaconConfig().SlotsPerEpoch)*int64(params.BeaconConfig().SecondsPerSlot)), 0) diff --git a/beacon-chain/core/light-client/BUILD.bazel b/beacon-chain/core/light-client/BUILD.bazel index 3651c5d6de..b22c964bd3 100644 --- a/beacon-chain/core/light-client/BUILD.bazel +++ b/beacon-chain/core/light-client/BUILD.bazel @@ -45,6 +45,7 @@ go_test( "//encoding/ssz:go_default_library", "//proto/engine/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", + "//runtime/version:go_default_library", "//testing/require:go_default_library", "//testing/util:go_default_library", "@com_github_pkg_errors//:go_default_library", diff --git a/beacon-chain/core/light-client/lightclient_test.go b/beacon-chain/core/light-client/lightclient_test.go index ac661e74c1..de09af2e77 100644 --- a/beacon-chain/core/light-client/lightclient_test.go +++ b/beacon-chain/core/light-client/lightclient_test.go @@ -8,6 +8,7 @@ import ( "github.com/OffchainLabs/prysm/v6/config/params" light_client "github.com/OffchainLabs/prysm/v6/consensus-types/light-client" "github.com/OffchainLabs/prysm/v6/consensus-types/primitives" + "github.com/OffchainLabs/prysm/v6/runtime/version" lightClient "github.com/OffchainLabs/prysm/v6/beacon-chain/core/light-client" fieldparams "github.com/OffchainLabs/prysm/v6/config/fieldparams" @@ -32,7 +33,7 @@ func TestLightClient_NewLightClientOptimisticUpdateFromBeaconState(t *testing.T) params.OverrideBeaconConfig(cfg) t.Run("Altair", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestAltair(0, true) + l := util.NewTestLightClient(t, version.Altair) update, err := lightClient.NewLightClientOptimisticUpdateFromBeaconState(l.Ctx, l.State.Slot(), l.State, l.Block, l.AttestedState, l.AttestedBlock) require.NoError(t, err) @@ -44,7 +45,7 @@ func TestLightClient_NewLightClientOptimisticUpdateFromBeaconState(t *testing.T) }) t.Run("Capella", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestCapella(false, 0, true) + l := util.NewTestLightClient(t, version.Capella) update, err := lightClient.NewLightClientOptimisticUpdateFromBeaconState(l.Ctx, l.State.Slot(), l.State, l.Block, l.AttestedState, l.AttestedBlock) require.NoError(t, err) @@ -57,7 +58,7 @@ func TestLightClient_NewLightClientOptimisticUpdateFromBeaconState(t *testing.T) }) t.Run("Deneb", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestDeneb(false, 0, true) + l := util.NewTestLightClient(t, version.Deneb) update, err := lightClient.NewLightClientOptimisticUpdateFromBeaconState(l.Ctx, l.State.Slot(), l.State, l.Block, l.AttestedState, l.AttestedBlock) require.NoError(t, err) @@ -70,7 +71,7 @@ func TestLightClient_NewLightClientOptimisticUpdateFromBeaconState(t *testing.T) }) t.Run("Electra", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestElectra(false, 0, true) + l := util.NewTestLightClient(t, version.Electra) update, err := lightClient.NewLightClientOptimisticUpdateFromBeaconState(l.Ctx, l.State.Slot(), l.State, l.Block, l.AttestedState, l.AttestedBlock) require.NoError(t, err) @@ -94,7 +95,7 @@ func TestLightClient_NewLightClientFinalityUpdateFromBeaconState(t *testing.T) { params.OverrideBeaconConfig(cfg) t.Run("Altair", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestAltair(0, true) + l := util.NewTestLightClient(t, version.Altair) t.Run("FinalizedBlock Not Nil", func(t *testing.T) { update, err := lightClient.NewLightClientFinalityUpdateFromBeaconState(l.Ctx, l.State.Slot(), l.State, l.Block, l.AttestedState, l.AttestedBlock, l.FinalizedBlock) @@ -131,7 +132,7 @@ func TestLightClient_NewLightClientFinalityUpdateFromBeaconState(t *testing.T) { t.Run("Capella", func(t *testing.T) { t.Run("FinalizedBlock Not Nil", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestCapella(false, 0, true) + l := util.NewTestLightClient(t, version.Capella) update, err := lightClient.NewLightClientFinalityUpdateFromBeaconState(l.Ctx, l.State.Slot(), l.State, l.Block, l.AttestedState, l.AttestedBlock, l.FinalizedBlock) require.NoError(t, err) require.NotNil(t, update, "update is nil") @@ -205,7 +206,7 @@ func TestLightClient_NewLightClientFinalityUpdateFromBeaconState(t *testing.T) { }) t.Run("FinalizedBlock In Previous Fork", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestCapellaFinalizedBlockAltair(false) + l := util.NewTestLightClient(t, version.Capella, util.WithFinalizedCheckpointInPrevFork()) update, err := lightClient.NewLightClientFinalityUpdateFromBeaconState(l.Ctx, l.State.Slot(), l.State, l.Block, l.AttestedState, l.AttestedBlock, l.FinalizedBlock) require.NoError(t, err) require.NotNil(t, update, "update is nil") @@ -238,7 +239,7 @@ func TestLightClient_NewLightClientFinalityUpdateFromBeaconState(t *testing.T) { t.Run("Deneb", func(t *testing.T) { t.Run("FinalizedBlock Not Nil", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestDeneb(false, 0, true) + l := util.NewTestLightClient(t, version.Deneb) update, err := lightClient.NewLightClientFinalityUpdateFromBeaconState(l.Ctx, l.State.Slot(), l.State, l.Block, l.AttestedState, l.AttestedBlock, l.FinalizedBlock) require.NoError(t, err) @@ -313,7 +314,7 @@ func TestLightClient_NewLightClientFinalityUpdateFromBeaconState(t *testing.T) { }) t.Run("FinalizedBlock In Previous Fork", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestDenebFinalizedBlockCapella(false) + l := util.NewTestLightClient(t, version.Deneb, util.WithFinalizedCheckpointInPrevFork()) update, err := lightClient.NewLightClientFinalityUpdateFromBeaconState(l.Ctx, l.State.Slot(), l.State, l.Block, l.AttestedState, l.AttestedBlock, l.FinalizedBlock) require.NoError(t, err) @@ -390,7 +391,7 @@ func TestLightClient_NewLightClientFinalityUpdateFromBeaconState(t *testing.T) { t.Run("Electra", func(t *testing.T) { t.Run("FinalizedBlock Not Nil", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestElectra(false, 0, true) + l := util.NewTestLightClient(t, version.Electra) update, err := lightClient.NewLightClientFinalityUpdateFromBeaconState(l.Ctx, l.State.Slot(), l.State, l.Block, l.AttestedState, l.AttestedBlock, l.FinalizedBlock) require.NoError(t, err) @@ -465,7 +466,7 @@ func TestLightClient_NewLightClientFinalityUpdateFromBeaconState(t *testing.T) { }) t.Run("FinalizedBlock In Previous Fork", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestElectraFinalizedBlockDeneb(false) + l := util.NewTestLightClient(t, version.Electra, util.WithFinalizedCheckpointInPrevFork()) update, err := lightClient.NewLightClientFinalityUpdateFromBeaconState(l.Ctx, l.State.Slot(), l.State, l.Block, l.AttestedState, l.AttestedBlock, l.FinalizedBlock) require.NoError(t, err) @@ -542,7 +543,7 @@ func TestLightClient_NewLightClientFinalityUpdateFromBeaconState(t *testing.T) { func TestLightClient_BlockToLightClientHeader(t *testing.T) { t.Run("Altair", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestAltair(0, true) + l := util.NewTestLightClient(t, version.Altair) header, err := lightClient.BlockToLightClientHeader( l.Ctx, @@ -565,7 +566,7 @@ func TestLightClient_BlockToLightClientHeader(t *testing.T) { }) t.Run("Bellatrix", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestBellatrix(0, true) + l := util.NewTestLightClient(t, version.Bellatrix) header, err := lightClient.BlockToLightClientHeader( l.Ctx, @@ -589,7 +590,7 @@ func TestLightClient_BlockToLightClientHeader(t *testing.T) { t.Run("Capella", func(t *testing.T) { t.Run("Non-Blinded Beacon Block", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestCapella(false, 0, true) + l := util.NewTestLightClient(t, version.Capella) header, err := lightClient.BlockToLightClientHeader( l.Ctx, @@ -650,7 +651,7 @@ func TestLightClient_BlockToLightClientHeader(t *testing.T) { }) t.Run("Blinded Beacon Block", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestCapella(true, 0, true) + l := util.NewTestLightClient(t, version.Capella, util.WithBlinded()) header, err := lightClient.BlockToLightClientHeader( l.Ctx, @@ -713,7 +714,7 @@ func TestLightClient_BlockToLightClientHeader(t *testing.T) { t.Run("Deneb", func(t *testing.T) { t.Run("Non-Blinded Beacon Block", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestDeneb(false, 0, true) + l := util.NewTestLightClient(t, version.Deneb) header, err := lightClient.BlockToLightClientHeader( l.Ctx, @@ -782,7 +783,7 @@ func TestLightClient_BlockToLightClientHeader(t *testing.T) { }) t.Run("Blinded Beacon Block", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestDeneb(true, 0, true) + l := util.NewTestLightClient(t, version.Deneb, util.WithBlinded()) header, err := lightClient.BlockToLightClientHeader( l.Ctx, @@ -853,7 +854,7 @@ func TestLightClient_BlockToLightClientHeader(t *testing.T) { t.Run("Electra", func(t *testing.T) { t.Run("Non-Blinded Beacon Block", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestElectra(false, 0, true) + l := util.NewTestLightClient(t, version.Electra) header, err := lightClient.BlockToLightClientHeader(l.Ctx, l.State.Slot(), l.Block) require.NoError(t, err) @@ -918,7 +919,7 @@ func TestLightClient_BlockToLightClientHeader(t *testing.T) { }) t.Run("Blinded Beacon Block", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestElectra(true, 0, true) + l := util.NewTestLightClient(t, version.Electra, util.WithBlinded()) header, err := lightClient.BlockToLightClientHeader(l.Ctx, l.State.Slot(), l.Block) require.NoError(t, err) @@ -984,7 +985,7 @@ func TestLightClient_BlockToLightClientHeader(t *testing.T) { }) t.Run("Capella fork with Altair block", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestAltair(0, true) + l := util.NewTestLightClient(t, version.Altair) header, err := lightClient.BlockToLightClientHeader( l.Ctx, @@ -1006,7 +1007,7 @@ func TestLightClient_BlockToLightClientHeader(t *testing.T) { }) t.Run("Deneb fork with Altair block", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestAltair(0, true) + l := util.NewTestLightClient(t, version.Altair) header, err := lightClient.BlockToLightClientHeader( l.Ctx, @@ -1029,7 +1030,7 @@ func TestLightClient_BlockToLightClientHeader(t *testing.T) { t.Run("Deneb fork with Capella block", func(t *testing.T) { t.Run("Non-Blinded Beacon Block", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestCapella(false, 0, true) + l := util.NewTestLightClient(t, version.Capella) header, err := lightClient.BlockToLightClientHeader( l.Ctx, @@ -1089,7 +1090,7 @@ func TestLightClient_BlockToLightClientHeader(t *testing.T) { }) t.Run("Blinded Beacon Block", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestCapella(true, 0, true) + l := util.NewTestLightClient(t, version.Capella, util.WithBlinded()) header, err := lightClient.BlockToLightClientHeader( l.Ctx, diff --git a/beacon-chain/core/light-client/store_test.go b/beacon-chain/core/light-client/store_test.go index 4a3073a19c..c11e1a4632 100644 --- a/beacon-chain/core/light-client/store_test.go +++ b/beacon-chain/core/light-client/store_test.go @@ -5,6 +5,7 @@ import ( lightClient "github.com/OffchainLabs/prysm/v6/beacon-chain/core/light-client" "github.com/OffchainLabs/prysm/v6/config/params" + "github.com/OffchainLabs/prysm/v6/runtime/version" "github.com/OffchainLabs/prysm/v6/testing/require" "github.com/OffchainLabs/prysm/v6/testing/util" ) @@ -23,7 +24,7 @@ func TestLightClientStore(t *testing.T) { lcStore := &lightClient.Store{} // Create test light client updates for Capella and Deneb - lCapella := util.NewTestLightClient(t).SetupTestCapella(false, 0, true) + lCapella := util.NewTestLightClient(t, version.Capella) opUpdateCapella, err := lightClient.NewLightClientOptimisticUpdateFromBeaconState(lCapella.Ctx, lCapella.State.Slot(), lCapella.State, lCapella.Block, lCapella.AttestedState, lCapella.AttestedBlock) require.NoError(t, err) require.NotNil(t, opUpdateCapella, "OptimisticUpdateCapella is nil") @@ -31,7 +32,7 @@ func TestLightClientStore(t *testing.T) { require.NoError(t, err) require.NotNil(t, finUpdateCapella, "FinalityUpdateCapella is nil") - lDeneb := util.NewTestLightClient(t).SetupTestDeneb(false, 0, true) + lDeneb := util.NewTestLightClient(t, version.Deneb) opUpdateDeneb, err := lightClient.NewLightClientOptimisticUpdateFromBeaconState(lDeneb.Ctx, lDeneb.State.Slot(), lDeneb.State, lDeneb.Block, lDeneb.AttestedState, lDeneb.AttestedBlock) require.NoError(t, err) require.NotNil(t, opUpdateDeneb, "OptimisticUpdateDeneb is nil") diff --git a/beacon-chain/rpc/eth/light-client/handlers_test.go b/beacon-chain/rpc/eth/light-client/handlers_test.go index 718d9246fb..8d63230965 100644 --- a/beacon-chain/rpc/eth/light-client/handlers_test.go +++ b/beacon-chain/rpc/eth/light-client/handlers_test.go @@ -51,7 +51,7 @@ func TestLightClientHandler_GetLightClientBootstrap(t *testing.T) { params.OverrideBeaconConfig(cfg) t.Run("altair", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestAltair(0, true) + l := util.NewTestLightClient(t, version.Altair) slot := primitives.Slot(params.BeaconConfig().AltairForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) blockRoot, err := l.Block.Block().HashTreeRoot() @@ -93,7 +93,7 @@ func TestLightClientHandler_GetLightClientBootstrap(t *testing.T) { require.NotNil(t, resp.Data.CurrentSyncCommitteeBranch) }) t.Run("altairSSZ", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestAltair(0, true) + l := util.NewTestLightClient(t, version.Altair) slot := primitives.Slot(params.BeaconConfig().AltairForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) blockRoot, err := l.Block.Block().HashTreeRoot() @@ -127,7 +127,7 @@ func TestLightClientHandler_GetLightClientBootstrap(t *testing.T) { require.NotNil(t, resp.CurrentSyncCommitteeBranch) }) t.Run("altair - no bootstrap found", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestAltair(0, true) + l := util.NewTestLightClient(t, version.Altair) slot := primitives.Slot(params.BeaconConfig().AltairForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) blockRoot, err := l.Block.Block().HashTreeRoot() @@ -153,7 +153,7 @@ func TestLightClientHandler_GetLightClientBootstrap(t *testing.T) { require.Equal(t, http.StatusNotFound, writer.Code) }) t.Run("bellatrix", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestBellatrix(0, true) + l := util.NewTestLightClient(t, version.Bellatrix) slot := primitives.Slot(params.BeaconConfig().BellatrixForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) blockRoot, err := l.Block.Block().HashTreeRoot() @@ -194,7 +194,7 @@ func TestLightClientHandler_GetLightClientBootstrap(t *testing.T) { require.NotNil(t, resp.Data.CurrentSyncCommitteeBranch) }) t.Run("bellatrixSSZ", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestBellatrix(0, true) + l := util.NewTestLightClient(t, version.Bellatrix) slot := primitives.Slot(params.BeaconConfig().BellatrixForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) blockRoot, err := l.Block.Block().HashTreeRoot() @@ -228,7 +228,7 @@ func TestLightClientHandler_GetLightClientBootstrap(t *testing.T) { require.NotNil(t, resp.CurrentSyncCommitteeBranch) }) t.Run("capella", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestCapella(false, 0, true) // result is same for true and false + l := util.NewTestLightClient(t, version.Capella) slot := primitives.Slot(params.BeaconConfig().CapellaForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) blockRoot, err := l.Block.Block().HashTreeRoot() @@ -269,7 +269,7 @@ func TestLightClientHandler_GetLightClientBootstrap(t *testing.T) { require.NotNil(t, resp.Data.CurrentSyncCommitteeBranch) }) t.Run("capellaSSZ", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestCapella(false, 0, true) // result is same for true and false + l := util.NewTestLightClient(t, version.Capella) slot := primitives.Slot(params.BeaconConfig().CapellaForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) blockRoot, err := l.Block.Block().HashTreeRoot() @@ -303,7 +303,7 @@ func TestLightClientHandler_GetLightClientBootstrap(t *testing.T) { require.NotNil(t, resp.CurrentSyncCommitteeBranch) }) t.Run("deneb", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestDeneb(false, 0, true) // result is same for true and false + l := util.NewTestLightClient(t, version.Deneb) slot := primitives.Slot(params.BeaconConfig().DenebForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) blockRoot, err := l.Block.Block().HashTreeRoot() @@ -344,7 +344,7 @@ func TestLightClientHandler_GetLightClientBootstrap(t *testing.T) { require.NotNil(t, resp.Data.CurrentSyncCommitteeBranch) }) t.Run("denebSSZ", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestDeneb(false, 0, true) // result is same for true and false + l := util.NewTestLightClient(t, version.Deneb) slot := primitives.Slot(params.BeaconConfig().DenebForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) blockRoot, err := l.Block.Block().HashTreeRoot() @@ -378,7 +378,7 @@ func TestLightClientHandler_GetLightClientBootstrap(t *testing.T) { require.NotNil(t, resp.CurrentSyncCommitteeBranch) }) t.Run("electra", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestElectra(false, 0, true) // result is same for true and false + l := util.NewTestLightClient(t, version.Electra) slot := primitives.Slot(params.BeaconConfig().ElectraForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) blockRoot, err := l.Block.Block().HashTreeRoot() @@ -419,7 +419,7 @@ func TestLightClientHandler_GetLightClientBootstrap(t *testing.T) { require.NotNil(t, resp.Data.CurrentSyncCommitteeBranch) }) t.Run("electraSSZ", func(t *testing.T) { - l := util.NewTestLightClient(t).SetupTestElectra(false, 0, true) // result is same for true and false + l := util.NewTestLightClient(t, version.Electra) slot := primitives.Slot(params.BeaconConfig().ElectraForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) blockRoot, err := l.Block.Block().HashTreeRoot() diff --git a/changelog/bastin_refactor-lc-testutils.md b/changelog/bastin_refactor-lc-testutils.md new file mode 100644 index 0000000000..ccc36caf66 --- /dev/null +++ b/changelog/bastin_refactor-lc-testutils.md @@ -0,0 +1,3 @@ +### Ignored + +- Refactor light client test utils to use functional options. \ No newline at end of file diff --git a/testing/util/BUILD.bazel b/testing/util/BUILD.bazel index 6a5835ec17..2db1a866f5 100644 --- a/testing/util/BUILD.bazel +++ b/testing/util/BUILD.bazel @@ -86,6 +86,7 @@ go_test( "deneb_test.go", "deposits_test.go", "helpers_test.go", + "lightclient_test.go", "logging_test.go", "state_test.go", ], @@ -106,6 +107,7 @@ go_test( "//encoding/ssz:go_default_library", "//proto/eth/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", + "//runtime/version:go_default_library", "//testing/assert:go_default_library", "//testing/require:go_default_library", "//time/slots:go_default_library", diff --git a/testing/util/lightclient.go b/testing/util/lightclient.go index be3206f52a..4404605e5f 100644 --- a/testing/util/lightclient.go +++ b/testing/util/lightclient.go @@ -16,10 +16,19 @@ import ( ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1" "github.com/OffchainLabs/prysm/v6/runtime/version" "github.com/OffchainLabs/prysm/v6/testing/require" + "github.com/OffchainLabs/prysm/v6/time/slots" "github.com/pkg/errors" ) type TestLightClient struct { + finalizedCheckpointInPrevFork bool + blinded bool + supermajority bool + noFinalizedCheckpoint bool + version int + increaseAttestedSlotBy uint64 + increaseFinalizedSlotBy uint64 + T *testing.T Ctx context.Context State state.BeaconState @@ -28,1049 +37,870 @@ type TestLightClient struct { AttestedBlock interfaces.ReadOnlySignedBeaconBlock FinalizedBlock interfaces.ReadOnlySignedBeaconBlock } +type LightClientOption func(l *TestLightClient) -func NewTestLightClient(t *testing.T) *TestLightClient { - return &TestLightClient{T: t} +func NewTestLightClient(t *testing.T, forkVersion int, options ...LightClientOption) *TestLightClient { + l := &TestLightClient{T: t, version: forkVersion} + + for _, option := range options { + option(l) + } + + switch l.version { + case version.Altair: + return l.setupTestAltair() + case version.Bellatrix: + return l.setupTestBellatrix() + case version.Capella: + return l.setupTestCapella() + case version.Deneb: + return l.setupTestDeneb() + case version.Electra: + return l.setupTestElectra() + default: + l.T.Fatalf("Unsupported version %s", version.String(l.version)) + return nil + } } -func (l *TestLightClient) SetupTestCapella(blinded bool, increaseAttestedSlotBy int, supermajority bool) *TestLightClient { - ctx := context.Background() - - slot := primitives.Slot(params.BeaconConfig().CapellaForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) - if increaseAttestedSlotBy > 0 { - slot = slot.Add(uint64(increaseAttestedSlotBy)) +// WithBlinded specifies whether the signature block is blinded or not +func WithBlinded() LightClientOption { + return func(l *TestLightClient) { + if l.version == version.Altair { + l.T.Fatalf("Blinded blocks are not supported in Altair") + } + l.blinded = true } - - attestedState, err := NewBeaconStateCapella() - require.NoError(l.T, err) - err = attestedState.SetSlot(slot) - require.NoError(l.T, err) - - finalizedBlock, err := blocks.NewSignedBeaconBlock(NewBeaconBlockCapella()) - require.NoError(l.T, err) - finalizedBlock.SetSlot(primitives.Slot(params.BeaconConfig().CapellaForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch))) - finalizedHeader, err := finalizedBlock.Header() - require.NoError(l.T, err) - finalizedRoot, err := finalizedHeader.Header.HashTreeRoot() - require.NoError(l.T, err) - - require.NoError(l.T, attestedState.SetFinalizedCheckpoint(ðpb.Checkpoint{ - Epoch: params.BeaconConfig().CapellaForkEpoch, - Root: finalizedRoot[:], - })) - - parent := NewBeaconBlockCapella() - parent.Block.Slot = slot - - signedParent, err := blocks.NewSignedBeaconBlock(parent) - require.NoError(l.T, err) - - parentHeader, err := signedParent.Header() - require.NoError(l.T, err) - attestedHeader := parentHeader.Header - - err = attestedState.SetLatestBlockHeader(attestedHeader) - require.NoError(l.T, err) - attestedStateRoot, err := attestedState.HashTreeRoot(ctx) - require.NoError(l.T, err) - - // get a new signed block so the root is updated with the new state root - parent.Block.StateRoot = attestedStateRoot[:] - signedParent, err = blocks.NewSignedBeaconBlock(parent) - require.NoError(l.T, err) - - state, err := NewBeaconStateCapella() - require.NoError(l.T, err) - err = state.SetSlot(slot) - require.NoError(l.T, err) - - parentRoot, err := signedParent.Block().HashTreeRoot() - require.NoError(l.T, err) - - var signedBlock interfaces.SignedBeaconBlock - if blinded { - block := NewBlindedBeaconBlockCapella() - block.Block.Slot = slot - block.Block.ParentRoot = parentRoot[:] - - var trueBitNum uint64 - if supermajority { - trueBitNum = (params.BeaconConfig().SyncCommitteeSize / 3 * 2) + 1 - } else { - trueBitNum = params.BeaconConfig().MinSyncCommitteeParticipants - } - for i := uint64(0); i < trueBitNum; i++ { - block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) - } - - signedBlock, err = blocks.NewSignedBeaconBlock(block) - require.NoError(l.T, err) - - h, err := signedBlock.Header() - require.NoError(l.T, err) - - err = state.SetLatestBlockHeader(h.Header) - require.NoError(l.T, err) - stateRoot, err := state.HashTreeRoot(ctx) - require.NoError(l.T, err) - - // get a new signed block so the root is updated with the new state root - block.Block.StateRoot = stateRoot[:] - signedBlock, err = blocks.NewSignedBeaconBlock(block) - require.NoError(l.T, err) - } else { - block := NewBeaconBlockCapella() - block.Block.Slot = slot - block.Block.ParentRoot = parentRoot[:] - - var trueBitNum uint64 - if supermajority { - trueBitNum = (params.BeaconConfig().SyncCommitteeSize / 3 * 2) + 1 - } else { - trueBitNum = params.BeaconConfig().MinSyncCommitteeParticipants - } - for i := uint64(0); i < trueBitNum; i++ { - block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) - } - - signedBlock, err = blocks.NewSignedBeaconBlock(block) - require.NoError(l.T, err) - - h, err := signedBlock.Header() - require.NoError(l.T, err) - - err = state.SetLatestBlockHeader(h.Header) - require.NoError(l.T, err) - stateRoot, err := state.HashTreeRoot(ctx) - require.NoError(l.T, err) - - // get a new signed block so the root is updated with the new state root - block.Block.StateRoot = stateRoot[:] - signedBlock, err = blocks.NewSignedBeaconBlock(block) - require.NoError(l.T, err) - } - - l.State = state - l.AttestedState = attestedState - l.AttestedBlock = signedParent - l.Block = signedBlock - l.Ctx = ctx - l.FinalizedBlock = finalizedBlock - - return l } -func (l *TestLightClient) SetupTestCapellaFinalizedBlockAltair(blinded bool) *TestLightClient { - ctx := context.Background() - - slot := primitives.Slot(params.BeaconConfig().CapellaForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) - - attestedState, err := NewBeaconStateCapella() - require.NoError(l.T, err) - err = attestedState.SetSlot(slot) - require.NoError(l.T, err) - - finalizedBlock, err := blocks.NewSignedBeaconBlock(NewBeaconBlockAltair()) - require.NoError(l.T, err) - finalizedBlock.SetSlot(1) - finalizedHeader, err := finalizedBlock.Header() - require.NoError(l.T, err) - finalizedRoot, err := finalizedHeader.Header.HashTreeRoot() - require.NoError(l.T, err) - - require.NoError(l.T, attestedState.SetFinalizedCheckpoint(ðpb.Checkpoint{ - Epoch: params.BeaconConfig().AltairForkEpoch - 10, - Root: finalizedRoot[:], - })) - - parent := NewBeaconBlockCapella() - parent.Block.Slot = slot - - signedParent, err := blocks.NewSignedBeaconBlock(parent) - require.NoError(l.T, err) - - parentHeader, err := signedParent.Header() - require.NoError(l.T, err) - attestedHeader := parentHeader.Header - - err = attestedState.SetLatestBlockHeader(attestedHeader) - require.NoError(l.T, err) - attestedStateRoot, err := attestedState.HashTreeRoot(ctx) - require.NoError(l.T, err) - - // get a new signed block so the root is updated with the new state root - parent.Block.StateRoot = attestedStateRoot[:] - signedParent, err = blocks.NewSignedBeaconBlock(parent) - require.NoError(l.T, err) - - state, err := NewBeaconStateCapella() - require.NoError(l.T, err) - err = state.SetSlot(slot) - require.NoError(l.T, err) - - parentRoot, err := signedParent.Block().HashTreeRoot() - require.NoError(l.T, err) - - var signedBlock interfaces.SignedBeaconBlock - if blinded { - block := NewBlindedBeaconBlockCapella() - block.Block.Slot = slot - block.Block.ParentRoot = parentRoot[:] - - for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ { - block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) - } - - signedBlock, err = blocks.NewSignedBeaconBlock(block) - require.NoError(l.T, err) - - h, err := signedBlock.Header() - require.NoError(l.T, err) - - err = state.SetLatestBlockHeader(h.Header) - require.NoError(l.T, err) - stateRoot, err := state.HashTreeRoot(ctx) - require.NoError(l.T, err) - - // get a new signed block so the root is updated with the new state root - block.Block.StateRoot = stateRoot[:] - signedBlock, err = blocks.NewSignedBeaconBlock(block) - require.NoError(l.T, err) - } else { - block := NewBeaconBlockCapella() - block.Block.Slot = slot - block.Block.ParentRoot = parentRoot[:] - - for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ { - block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) - } - - signedBlock, err = blocks.NewSignedBeaconBlock(block) - require.NoError(l.T, err) - - h, err := signedBlock.Header() - require.NoError(l.T, err) - - err = state.SetLatestBlockHeader(h.Header) - require.NoError(l.T, err) - stateRoot, err := state.HashTreeRoot(ctx) - require.NoError(l.T, err) - - // get a new signed block so the root is updated with the new state root - block.Block.StateRoot = stateRoot[:] - signedBlock, err = blocks.NewSignedBeaconBlock(block) - require.NoError(l.T, err) +// WithNoFinalizedCheckpoint avoids setting a finalized checkpoint for the attested state +func WithNoFinalizedCheckpoint() LightClientOption { + return func(l *TestLightClient) { + l.noFinalizedCheckpoint = true } - - l.State = state - l.AttestedState = attestedState - l.AttestedBlock = signedParent - l.Block = signedBlock - l.Ctx = ctx - l.FinalizedBlock = finalizedBlock - - return l } -func (l *TestLightClient) SetupTestAltair(increaseAttestedSlotBy int, supermajority bool) *TestLightClient { +// WithFinalizedCheckpointInPrevFork creates a finalized checkpoint for the attested state, in the previous fork. +func WithFinalizedCheckpointInPrevFork() LightClientOption { + return func(l *TestLightClient) { + if l.version == version.Altair { + l.T.Fatalf("Can't set finalized checkpoint in previous fork for Altair") + } + l.finalizedCheckpointInPrevFork = true + } +} + +// WithSupermajority specifies whether the sync committee bits have supermajority or not +func WithSupermajority() LightClientOption { + return func(l *TestLightClient) { + l.supermajority = true + } +} + +// WithIncreasedAttestedSlot specifies the number of slots to increase the attested slot by. This does not affect the finalized block's slot if there is any. +func WithIncreasedAttestedSlot(increaseBy uint64) LightClientOption { + return func(l *TestLightClient) { + l.increaseAttestedSlotBy = increaseBy + } +} + +// WithIncreasedFinalizedSlot specifies the number of slots to increase the finalized slot by. This DOES NOT affect the attested block's slot. That should be handled separately using WithIncreasedAttestedSlot. +func WithIncreasedFinalizedSlot(increaseBy uint64) LightClientOption { + return func(l *TestLightClient) { + l.increaseFinalizedSlotBy = increaseBy + } +} + +func (l *TestLightClient) setupTestAltair() *TestLightClient { ctx := context.Background() - slot := primitives.Slot(uint64(params.BeaconConfig().AltairForkEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch)).Add(1) - if increaseAttestedSlotBy > 0 { - slot = slot.Add(uint64(increaseAttestedSlotBy)) + attestedSlot := primitives.Slot(uint64(params.BeaconConfig().AltairForkEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch)).Add(1) + if l.increaseAttestedSlotBy > 0 { + attestedSlot = attestedSlot.Add(l.increaseAttestedSlotBy) } + signatureSlot := attestedSlot.Add(1) + + // Attested State attestedState, err := NewBeaconStateAltair() require.NoError(l.T, err) - err = attestedState.SetSlot(slot) - require.NoError(l.T, err) + require.NoError(l.T, attestedState.SetSlot(attestedSlot)) - finalizedState, err := NewBeaconStateAltair() - require.NoError(l.T, err) - err = finalizedState.SetSlot(1) - require.NoError(l.T, err) - finalizedStateRoot, err := finalizedState.HashTreeRoot(ctx) - require.NoError(l.T, err) - SignedFinalizedBlock, err := blocks.NewSignedBeaconBlock(NewBeaconBlockAltair()) - require.NoError(l.T, err) - SignedFinalizedBlock.SetSlot(1) - SignedFinalizedBlock.SetStateRoot(finalizedStateRoot[:]) - finalizedHeader, err := SignedFinalizedBlock.Header() - require.NoError(l.T, err) - finalizedRoot, err := finalizedHeader.Header.HashTreeRoot() - require.NoError(l.T, err) + var signedFinalizedBlock interfaces.SignedBeaconBlock + // Finalized checkpoint + if !l.noFinalizedCheckpoint { + finalizedSlot := primitives.Slot(uint64(params.BeaconConfig().AltairForkEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch)) + if l.increaseFinalizedSlotBy > 0 { + finalizedSlot = finalizedSlot.Add(l.increaseFinalizedSlotBy) + } + // Finalized State & Block + finalizedState, err := NewBeaconStateAltair() + require.NoError(l.T, err) + require.NoError(l.T, finalizedState.SetSlot(finalizedSlot)) - finalizedCheckpoint := ðpb.Checkpoint{ - Epoch: params.BeaconConfig().AltairForkEpoch - 10, - Root: finalizedRoot[:], + finalizedBlock := NewBeaconBlockAltair() + require.NoError(l.T, err) + finalizedBlock.Block.Slot = finalizedSlot + signedFinalizedBlock, err = blocks.NewSignedBeaconBlock(finalizedBlock) + require.NoError(l.T, err) + finalizedHeader, err := signedFinalizedBlock.Header() + require.NoError(l.T, err) + require.NoError(l.T, finalizedState.SetLatestBlockHeader(finalizedHeader.Header)) + finalizedStateRoot, err := finalizedState.HashTreeRoot(ctx) + require.NoError(l.T, err) + finalizedBlock.Block.StateRoot = finalizedStateRoot[:] + signedFinalizedBlock, err = blocks.NewSignedBeaconBlock(finalizedBlock) + require.NoError(l.T, err) + + // Set the finalized checkpoint + finalizedBlockRoot, err := signedFinalizedBlock.Block().HashTreeRoot() + require.NoError(l.T, err) + finalizedCheckpoint := ðpb.Checkpoint{ + Epoch: slots.ToEpoch(finalizedSlot), + Root: finalizedBlockRoot[:], + } + + require.NoError(l.T, attestedState.SetFinalizedCheckpoint(finalizedCheckpoint)) } - require.NoError(l.T, attestedState.SetFinalizedCheckpoint(finalizedCheckpoint)) - parent := NewBeaconBlockAltair() - parent.Block.Slot = slot - - signedParent, err := blocks.NewSignedBeaconBlock(parent) + // Attested Block + attestedBlock := NewBeaconBlockAltair() + attestedBlock.Block.Slot = attestedSlot + signedAttestedBlock, err := blocks.NewSignedBeaconBlock(attestedBlock) require.NoError(l.T, err) - - parentHeader, err := signedParent.Header() - require.NoError(l.T, err) - attestedHeader := parentHeader.Header - - err = attestedState.SetLatestBlockHeader(attestedHeader) + attestedBlockHeader, err := signedAttestedBlock.Header() require.NoError(l.T, err) + require.NoError(l.T, attestedState.SetLatestBlockHeader(attestedBlockHeader.Header)) attestedStateRoot, err := attestedState.HashTreeRoot(ctx) require.NoError(l.T, err) - - // get a new signed block so the root is updated with the new state root - parent.Block.StateRoot = attestedStateRoot[:] - signedParent, err = blocks.NewSignedBeaconBlock(parent) + attestedBlock.Block.StateRoot = attestedStateRoot[:] + signedAttestedBlock, err = blocks.NewSignedBeaconBlock(attestedBlock) require.NoError(l.T, err) - state, err := NewBeaconStateAltair() - require.NoError(l.T, err) - err = state.SetSlot(slot) + // Signature State & Block + signatureState, err := NewBeaconStateAltair() require.NoError(l.T, err) + require.NoError(l.T, signatureState.SetSlot(signatureSlot)) - parentRoot, err := signedParent.Block().HashTreeRoot() + signatureBlock := NewBeaconBlockAltair() + signatureBlock.Block.Slot = signatureSlot + attestedBlockRoot, err := signedAttestedBlock.Block().HashTreeRoot() require.NoError(l.T, err) - - block := NewBeaconBlockAltair() - block.Block.Slot = slot - block.Block.ParentRoot = parentRoot[:] + signatureBlock.Block.ParentRoot = attestedBlockRoot[:] var trueBitNum uint64 - if supermajority { - trueBitNum = (params.BeaconConfig().SyncCommitteeSize / 3 * 2) + 1 + if l.supermajority { + trueBitNum = uint64((float64(params.BeaconConfig().SyncCommitteeSize) * 2.0 / 3.0) + 1) } else { trueBitNum = params.BeaconConfig().MinSyncCommitteeParticipants } for i := uint64(0); i < trueBitNum; i++ { - block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + signatureBlock.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) } - signedBlock, err := blocks.NewSignedBeaconBlock(block) + signedSignatureBlock, err := blocks.NewSignedBeaconBlock(signatureBlock) + require.NoError(l.T, err) + signatureBlockHeader, err := signedSignatureBlock.Header() + require.NoError(l.T, err) + err = signatureState.SetLatestBlockHeader(signatureBlockHeader.Header) + require.NoError(l.T, err) + signatureStateRoot, err := signatureState.HashTreeRoot(ctx) + require.NoError(l.T, err) + signatureBlock.Block.StateRoot = signatureStateRoot[:] + signedSignatureBlock, err = blocks.NewSignedBeaconBlock(signatureBlock) require.NoError(l.T, err) - h, err := signedBlock.Header() - require.NoError(l.T, err) - - err = state.SetLatestBlockHeader(h.Header) - require.NoError(l.T, err) - stateRoot, err := state.HashTreeRoot(ctx) - require.NoError(l.T, err) - - // get a new signed block so the root is updated with the new state root - block.Block.StateRoot = stateRoot[:] - signedBlock, err = blocks.NewSignedBeaconBlock(block) - require.NoError(l.T, err) - - l.State = state + l.State = signatureState l.AttestedState = attestedState - l.Block = signedBlock + l.Block = signedSignatureBlock l.Ctx = ctx - l.FinalizedBlock = SignedFinalizedBlock - l.AttestedBlock = signedParent + l.FinalizedBlock = signedFinalizedBlock + l.AttestedBlock = signedAttestedBlock return l } -func (l *TestLightClient) SetupTestBellatrix(increaseAttestedSlotBy int, supermajority bool) *TestLightClient { +func (l *TestLightClient) setupTestBellatrix() *TestLightClient { ctx := context.Background() - slot := primitives.Slot(params.BeaconConfig().BellatrixForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) - if increaseAttestedSlotBy > 0 { - slot = slot.Add(uint64(increaseAttestedSlotBy)) + attestedSlot := primitives.Slot(uint64(params.BeaconConfig().BellatrixForkEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch)).Add(1) + if l.increaseAttestedSlotBy > 0 { + attestedSlot = attestedSlot.Add(l.increaseAttestedSlotBy) } + signatureSlot := attestedSlot.Add(1) + + // Attested State & Block attestedState, err := NewBeaconStateBellatrix() require.NoError(l.T, err) - err = attestedState.SetSlot(slot) - require.NoError(l.T, err) + require.NoError(l.T, attestedState.SetSlot(attestedSlot)) - finalizedBlock, err := blocks.NewSignedBeaconBlock(NewBeaconBlockBellatrix()) - require.NoError(l.T, err) - finalizedBlock.SetSlot(1) - finalizedHeader, err := finalizedBlock.Header() - require.NoError(l.T, err) - finalizedRoot, err := finalizedHeader.Header.HashTreeRoot() - require.NoError(l.T, err) + var signedFinalizedBlock interfaces.SignedBeaconBlock + // Finalized checkpoint + if !l.noFinalizedCheckpoint { + var finalizedSlot primitives.Slot + if l.finalizedCheckpointInPrevFork { + finalizedSlot = primitives.Slot(uint64(params.BeaconConfig().AltairForkEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch)) + if l.increaseFinalizedSlotBy > 0 { + finalizedSlot = finalizedSlot.Add(l.increaseFinalizedSlotBy) + } - require.NoError(l.T, attestedState.SetFinalizedCheckpoint(ðpb.Checkpoint{ - Epoch: params.BeaconConfig().BellatrixForkEpoch - 10, - Root: finalizedRoot[:], - })) + finalizedState, err := NewBeaconStateAltair() + require.NoError(l.T, err) + require.NoError(l.T, finalizedState.SetSlot(finalizedSlot)) - parent := NewBeaconBlockBellatrix() - parent.Block.Slot = slot + finalizedBlock := NewBeaconBlockAltair() + require.NoError(l.T, err) + finalizedBlock.Block.Slot = finalizedSlot + signedFinalizedBlock, err = blocks.NewSignedBeaconBlock(finalizedBlock) + require.NoError(l.T, err) + finalizedHeader, err := signedFinalizedBlock.Header() + require.NoError(l.T, err) + require.NoError(l.T, finalizedState.SetLatestBlockHeader(finalizedHeader.Header)) + finalizedStateRoot, err := finalizedState.HashTreeRoot(ctx) + require.NoError(l.T, err) + finalizedBlock.Block.StateRoot = finalizedStateRoot[:] + signedFinalizedBlock, err = blocks.NewSignedBeaconBlock(finalizedBlock) + require.NoError(l.T, err) + } else { + finalizedSlot = primitives.Slot(uint64(params.BeaconConfig().BellatrixForkEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch)) + if l.increaseFinalizedSlotBy > 0 { + finalizedSlot = finalizedSlot.Add(l.increaseFinalizedSlotBy) + } - signedParent, err := blocks.NewSignedBeaconBlock(parent) + finalizedState, err := NewBeaconStateBellatrix() + require.NoError(l.T, err) + require.NoError(l.T, finalizedState.SetSlot(finalizedSlot)) + + finalizedBlock := NewBeaconBlockBellatrix() + require.NoError(l.T, err) + finalizedBlock.Block.Slot = finalizedSlot + signedFinalizedBlock, err = blocks.NewSignedBeaconBlock(finalizedBlock) + require.NoError(l.T, err) + finalizedHeader, err := signedFinalizedBlock.Header() + require.NoError(l.T, err) + require.NoError(l.T, finalizedState.SetLatestBlockHeader(finalizedHeader.Header)) + finalizedStateRoot, err := finalizedState.HashTreeRoot(ctx) + require.NoError(l.T, err) + finalizedBlock.Block.StateRoot = finalizedStateRoot[:] + signedFinalizedBlock, err = blocks.NewSignedBeaconBlock(finalizedBlock) + require.NoError(l.T, err) + } + + // Set the finalized checkpoint + finalizedBlockRoot, err := signedFinalizedBlock.Block().HashTreeRoot() + require.NoError(l.T, err) + finalizedCheckpoint := ðpb.Checkpoint{ + Epoch: slots.ToEpoch(finalizedSlot), + Root: finalizedBlockRoot[:], + } + require.NoError(l.T, attestedState.SetFinalizedCheckpoint(finalizedCheckpoint)) + } + + attestedBlock := NewBeaconBlockBellatrix() + attestedBlock.Block.Slot = attestedSlot + signedAttestedBlock, err := blocks.NewSignedBeaconBlock(attestedBlock) require.NoError(l.T, err) - - parentHeader, err := signedParent.Header() - require.NoError(l.T, err) - attestedHeader := parentHeader.Header - - err = attestedState.SetLatestBlockHeader(attestedHeader) + attestedBlockHeader, err := signedAttestedBlock.Header() require.NoError(l.T, err) + require.NoError(l.T, attestedState.SetLatestBlockHeader(attestedBlockHeader.Header)) attestedStateRoot, err := attestedState.HashTreeRoot(ctx) require.NoError(l.T, err) - - // get a new signed block so the root is updated with the new state root - parent.Block.StateRoot = attestedStateRoot[:] - signedParent, err = blocks.NewSignedBeaconBlock(parent) + attestedBlock.Block.StateRoot = attestedStateRoot[:] + signedAttestedBlock, err = blocks.NewSignedBeaconBlock(attestedBlock) require.NoError(l.T, err) - state, err := NewBeaconStateBellatrix() - require.NoError(l.T, err) - err = state.SetSlot(slot) + // Signature State & Block + signatureState, err := NewBeaconStateBellatrix() require.NoError(l.T, err) + require.NoError(l.T, signatureState.SetSlot(signatureSlot)) - parentRoot, err := signedParent.Block().HashTreeRoot() - require.NoError(l.T, err) + var signedSignatureBlock interfaces.SignedBeaconBlock + if l.blinded { + signatureBlock := NewBlindedBeaconBlockBellatrix() + signatureBlock.Block.Slot = signatureSlot + attestedBlockRoot, err := signedAttestedBlock.Block().HashTreeRoot() + require.NoError(l.T, err) + signatureBlock.Block.ParentRoot = attestedBlockRoot[:] - block := NewBeaconBlockBellatrix() - block.Block.Slot = slot - block.Block.ParentRoot = parentRoot[:] + var trueBitNum uint64 + if l.supermajority { + trueBitNum = uint64((float64(params.BeaconConfig().SyncCommitteeSize) * 2.0 / 3.0) + 1) + } else { + trueBitNum = params.BeaconConfig().MinSyncCommitteeParticipants + } + for i := uint64(0); i < trueBitNum; i++ { + signatureBlock.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + } - var trueBitNum uint64 - if supermajority { - trueBitNum = (params.BeaconConfig().SyncCommitteeSize / 3 * 2) + 1 + signedSignatureBlock, err = blocks.NewSignedBeaconBlock(signatureBlock) + require.NoError(l.T, err) + + signatureBlockHeader, err := signedSignatureBlock.Header() + require.NoError(l.T, err) + + err = signatureState.SetLatestBlockHeader(signatureBlockHeader.Header) + require.NoError(l.T, err) + stateRoot, err := signatureState.HashTreeRoot(ctx) + require.NoError(l.T, err) + + signatureBlock.Block.StateRoot = stateRoot[:] + signedSignatureBlock, err = blocks.NewSignedBeaconBlock(signatureBlock) + require.NoError(l.T, err) } else { - trueBitNum = params.BeaconConfig().MinSyncCommitteeParticipants - } - for i := uint64(0); i < trueBitNum; i++ { - block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + signatureBlock := NewBeaconBlockBellatrix() + signatureBlock.Block.Slot = signatureSlot + attestedBlockRoot, err := signedAttestedBlock.Block().HashTreeRoot() + require.NoError(l.T, err) + signatureBlock.Block.ParentRoot = attestedBlockRoot[:] + + var trueBitNum uint64 + if l.supermajority { + trueBitNum = uint64((float64(params.BeaconConfig().SyncCommitteeSize) * 2.0 / 3.0) + 1) + } else { + trueBitNum = params.BeaconConfig().MinSyncCommitteeParticipants + } + for i := uint64(0); i < trueBitNum; i++ { + signatureBlock.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + } + + signedSignatureBlock, err = blocks.NewSignedBeaconBlock(signatureBlock) + require.NoError(l.T, err) + + signatureBlockHeader, err := signedSignatureBlock.Header() + require.NoError(l.T, err) + + err = signatureState.SetLatestBlockHeader(signatureBlockHeader.Header) + require.NoError(l.T, err) + signatureStateRoot, err := signatureState.HashTreeRoot(ctx) + require.NoError(l.T, err) + + signatureBlock.Block.StateRoot = signatureStateRoot[:] + signedSignatureBlock, err = blocks.NewSignedBeaconBlock(signatureBlock) + require.NoError(l.T, err) } - signedBlock, err := blocks.NewSignedBeaconBlock(block) - require.NoError(l.T, err) - - h, err := signedBlock.Header() - require.NoError(l.T, err) - - err = state.SetLatestBlockHeader(h.Header) - require.NoError(l.T, err) - stateRoot, err := state.HashTreeRoot(ctx) - require.NoError(l.T, err) - - // get a new signed block so the root is updated with the new state root - block.Block.StateRoot = stateRoot[:] - signedBlock, err = blocks.NewSignedBeaconBlock(block) - require.NoError(l.T, err) - - l.State = state + l.State = signatureState l.AttestedState = attestedState - l.Block = signedBlock + l.Block = signedSignatureBlock l.Ctx = ctx - l.FinalizedBlock = finalizedBlock - l.AttestedBlock = signedParent + l.FinalizedBlock = signedFinalizedBlock + l.AttestedBlock = signedAttestedBlock return l } -func (l *TestLightClient) SetupTestDeneb(blinded bool, increaseAttestedSlotBy int, supermajority bool) *TestLightClient { +func (l *TestLightClient) setupTestCapella() *TestLightClient { ctx := context.Background() - slot := primitives.Slot(params.BeaconConfig().DenebForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) - if increaseAttestedSlotBy > 0 { - slot = slot.Add(uint64(increaseAttestedSlotBy)) + attestedSlot := primitives.Slot(uint64(params.BeaconConfig().CapellaForkEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch)).Add(1) + if l.increaseAttestedSlotBy > 0 { + attestedSlot = attestedSlot.Add(l.increaseAttestedSlotBy) } + signatureSlot := attestedSlot.Add(1) + + // Attested State + attestedState, err := NewBeaconStateCapella() + require.NoError(l.T, err) + require.NoError(l.T, attestedState.SetSlot(attestedSlot)) + + var signedFinalizedBlock interfaces.SignedBeaconBlock + // Finalized checkpoint + if !l.noFinalizedCheckpoint { + var finalizedSlot primitives.Slot + if l.finalizedCheckpointInPrevFork { + finalizedSlot = primitives.Slot(uint64(params.BeaconConfig().BellatrixForkEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch)) + if l.increaseFinalizedSlotBy > 0 { + finalizedSlot = finalizedSlot.Add(l.increaseFinalizedSlotBy) + } + + finalizedState, err := NewBeaconStateBellatrix() + require.NoError(l.T, err) + require.NoError(l.T, finalizedState.SetSlot(finalizedSlot)) + + finalizedBlock := NewBeaconBlockBellatrix() + require.NoError(l.T, err) + finalizedBlock.Block.Slot = finalizedSlot + signedFinalizedBlock, err = blocks.NewSignedBeaconBlock(finalizedBlock) + require.NoError(l.T, err) + finalizedHeader, err := signedFinalizedBlock.Header() + require.NoError(l.T, err) + require.NoError(l.T, finalizedState.SetLatestBlockHeader(finalizedHeader.Header)) + finalizedStateRoot, err := finalizedState.HashTreeRoot(ctx) + require.NoError(l.T, err) + finalizedBlock.Block.StateRoot = finalizedStateRoot[:] + signedFinalizedBlock, err = blocks.NewSignedBeaconBlock(finalizedBlock) + require.NoError(l.T, err) + } else { + finalizedSlot = primitives.Slot(uint64(params.BeaconConfig().CapellaForkEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch)) + if l.increaseFinalizedSlotBy > 0 { + finalizedSlot = finalizedSlot.Add(l.increaseFinalizedSlotBy) + } + + finalizedState, err := NewBeaconStateCapella() + require.NoError(l.T, err) + require.NoError(l.T, finalizedState.SetSlot(finalizedSlot)) + + finalizedBlock := NewBeaconBlockCapella() + require.NoError(l.T, err) + finalizedBlock.Block.Slot = finalizedSlot + signedFinalizedBlock, err = blocks.NewSignedBeaconBlock(finalizedBlock) + require.NoError(l.T, err) + finalizedHeader, err := signedFinalizedBlock.Header() + require.NoError(l.T, err) + require.NoError(l.T, finalizedState.SetLatestBlockHeader(finalizedHeader.Header)) + finalizedStateRoot, err := finalizedState.HashTreeRoot(ctx) + require.NoError(l.T, err) + finalizedBlock.Block.StateRoot = finalizedStateRoot[:] + signedFinalizedBlock, err = blocks.NewSignedBeaconBlock(finalizedBlock) + require.NoError(l.T, err) + } + + // Set the finalized checkpoint + finalizedBlockRoot, err := signedFinalizedBlock.Block().HashTreeRoot() + require.NoError(l.T, err) + finalizedCheckpoint := ðpb.Checkpoint{ + Epoch: slots.ToEpoch(finalizedSlot), + Root: finalizedBlockRoot[:], + } + require.NoError(l.T, attestedState.SetFinalizedCheckpoint(finalizedCheckpoint)) + } + + // Attested Block + attestedBlock := NewBeaconBlockCapella() + attestedBlock.Block.Slot = attestedSlot + signedAttestedBlock, err := blocks.NewSignedBeaconBlock(attestedBlock) + require.NoError(l.T, err) + attestedBlockHeader, err := signedAttestedBlock.Header() + require.NoError(l.T, err) + require.NoError(l.T, attestedState.SetLatestBlockHeader(attestedBlockHeader.Header)) + attestedStateRoot, err := attestedState.HashTreeRoot(ctx) + require.NoError(l.T, err) + attestedBlock.Block.StateRoot = attestedStateRoot[:] + signedAttestedBlock, err = blocks.NewSignedBeaconBlock(attestedBlock) + require.NoError(l.T, err) + + // Signature State & Block + signatureState, err := NewBeaconStateCapella() + require.NoError(l.T, err) + require.NoError(l.T, signatureState.SetSlot(signatureSlot)) + + var signedSignatureBlock interfaces.SignedBeaconBlock + if l.blinded { + signatureBlock := NewBlindedBeaconBlockCapella() + signatureBlock.Block.Slot = signatureSlot + attestedBlockRoot, err := signedAttestedBlock.Block().HashTreeRoot() + require.NoError(l.T, err) + signatureBlock.Block.ParentRoot = attestedBlockRoot[:] + + var trueBitNum uint64 + if l.supermajority { + trueBitNum = uint64((float64(params.BeaconConfig().SyncCommitteeSize) * 2.0 / 3.0) + 1) + } else { + trueBitNum = params.BeaconConfig().MinSyncCommitteeParticipants + } + for i := uint64(0); i < trueBitNum; i++ { + signatureBlock.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + } + + signedSignatureBlock, err = blocks.NewSignedBeaconBlock(signatureBlock) + require.NoError(l.T, err) + + signatureBlockHeader, err := signedSignatureBlock.Header() + require.NoError(l.T, err) + + err = signatureState.SetLatestBlockHeader(signatureBlockHeader.Header) + require.NoError(l.T, err) + stateRoot, err := signatureState.HashTreeRoot(ctx) + require.NoError(l.T, err) + + signatureBlock.Block.StateRoot = stateRoot[:] + signedSignatureBlock, err = blocks.NewSignedBeaconBlock(signatureBlock) + require.NoError(l.T, err) + } else { + signatureBlock := NewBeaconBlockCapella() + signatureBlock.Block.Slot = signatureSlot + attestedBlockRoot, err := signedAttestedBlock.Block().HashTreeRoot() + require.NoError(l.T, err) + signatureBlock.Block.ParentRoot = attestedBlockRoot[:] + + var trueBitNum uint64 + if l.supermajority { + trueBitNum = uint64((float64(params.BeaconConfig().SyncCommitteeSize) * 2.0 / 3.0) + 1) + } else { + trueBitNum = params.BeaconConfig().MinSyncCommitteeParticipants + } + for i := uint64(0); i < trueBitNum; i++ { + signatureBlock.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + } + + signedSignatureBlock, err = blocks.NewSignedBeaconBlock(signatureBlock) + require.NoError(l.T, err) + + signatureBlockHeader, err := signedSignatureBlock.Header() + require.NoError(l.T, err) + + err = signatureState.SetLatestBlockHeader(signatureBlockHeader.Header) + require.NoError(l.T, err) + signatureStateRoot, err := signatureState.HashTreeRoot(ctx) + require.NoError(l.T, err) + + signatureBlock.Block.StateRoot = signatureStateRoot[:] + signedSignatureBlock, err = blocks.NewSignedBeaconBlock(signatureBlock) + require.NoError(l.T, err) + } + + l.State = signatureState + l.AttestedState = attestedState + l.AttestedBlock = signedAttestedBlock + l.Block = signedSignatureBlock + l.Ctx = ctx + l.FinalizedBlock = signedFinalizedBlock + + return l +} + +func (l *TestLightClient) setupTestDeneb() *TestLightClient { + ctx := context.Background() + + attestedSlot := primitives.Slot(uint64(params.BeaconConfig().DenebForkEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch)).Add(1) + if l.increaseAttestedSlotBy > 0 { + attestedSlot = attestedSlot.Add(l.increaseAttestedSlotBy) + } + + signatureSlot := attestedSlot.Add(1) + + // Attested State attestedState, err := NewBeaconStateDeneb() require.NoError(l.T, err) - err = attestedState.SetSlot(slot) - require.NoError(l.T, err) + require.NoError(l.T, attestedState.SetSlot(attestedSlot)) - finalizedBlock, err := blocks.NewSignedBeaconBlock(NewBeaconBlockDeneb()) - require.NoError(l.T, err) - finalizedBlock.SetSlot(primitives.Slot(params.BeaconConfig().DenebForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch))) - finalizedHeader, err := finalizedBlock.Header() - require.NoError(l.T, err) - finalizedRoot, err := finalizedHeader.Header.HashTreeRoot() - require.NoError(l.T, err) + var signedFinalizedBlock interfaces.SignedBeaconBlock + // Finalized checkpoint + if !l.noFinalizedCheckpoint { + var finalizedSlot primitives.Slot - require.NoError(l.T, attestedState.SetFinalizedCheckpoint(ðpb.Checkpoint{ - Epoch: params.BeaconConfig().DenebForkEpoch, - Root: finalizedRoot[:], - })) + if l.finalizedCheckpointInPrevFork { + finalizedSlot = primitives.Slot(uint64(params.BeaconConfig().CapellaForkEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch)) + if l.increaseFinalizedSlotBy > 0 { + finalizedSlot = finalizedSlot.Add(l.increaseFinalizedSlotBy) + } - parent := NewBeaconBlockDeneb() - parent.Block.Slot = slot + finalizedState, err := NewBeaconStateCapella() + require.NoError(l.T, err) + require.NoError(l.T, finalizedState.SetSlot(finalizedSlot)) - signedParent, err := blocks.NewSignedBeaconBlock(parent) + finalizedBlock := NewBeaconBlockCapella() + require.NoError(l.T, err) + finalizedBlock.Block.Slot = finalizedSlot + signedFinalizedBlock, err = blocks.NewSignedBeaconBlock(finalizedBlock) + require.NoError(l.T, err) + finalizedHeader, err := signedFinalizedBlock.Header() + require.NoError(l.T, err) + require.NoError(l.T, finalizedState.SetLatestBlockHeader(finalizedHeader.Header)) + finalizedStateRoot, err := finalizedState.HashTreeRoot(ctx) + require.NoError(l.T, err) + finalizedBlock.Block.StateRoot = finalizedStateRoot[:] + signedFinalizedBlock, err = blocks.NewSignedBeaconBlock(finalizedBlock) + require.NoError(l.T, err) + } else { + finalizedSlot = primitives.Slot(uint64(params.BeaconConfig().DenebForkEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch)) + if l.increaseFinalizedSlotBy > 0 { + finalizedSlot = finalizedSlot.Add(l.increaseFinalizedSlotBy) + } + + finalizedState, err := NewBeaconStateDeneb() + require.NoError(l.T, err) + require.NoError(l.T, finalizedState.SetSlot(finalizedSlot)) + + finalizedBlock := NewBeaconBlockDeneb() + require.NoError(l.T, err) + finalizedBlock.Block.Slot = finalizedSlot + signedFinalizedBlock, err = blocks.NewSignedBeaconBlock(finalizedBlock) + require.NoError(l.T, err) + finalizedHeader, err := signedFinalizedBlock.Header() + require.NoError(l.T, err) + require.NoError(l.T, finalizedState.SetLatestBlockHeader(finalizedHeader.Header)) + finalizedStateRoot, err := finalizedState.HashTreeRoot(ctx) + require.NoError(l.T, err) + finalizedBlock.Block.StateRoot = finalizedStateRoot[:] + signedFinalizedBlock, err = blocks.NewSignedBeaconBlock(finalizedBlock) + require.NoError(l.T, err) + } + + // Set the finalized checkpoint + finalizedBlockRoot, err := signedFinalizedBlock.Block().HashTreeRoot() + require.NoError(l.T, err) + finalizedCheckpoint := ðpb.Checkpoint{ + Epoch: slots.ToEpoch(finalizedSlot), + Root: finalizedBlockRoot[:], + } + require.NoError(l.T, attestedState.SetFinalizedCheckpoint(finalizedCheckpoint)) + } + + // Attested Block + attestedBlock := NewBeaconBlockDeneb() + attestedBlock.Block.Slot = attestedSlot + signedAttestedBlock, err := blocks.NewSignedBeaconBlock(attestedBlock) require.NoError(l.T, err) - - parentHeader, err := signedParent.Header() - require.NoError(l.T, err) - attestedHeader := parentHeader.Header - - err = attestedState.SetLatestBlockHeader(attestedHeader) + attestedBlockHeader, err := signedAttestedBlock.Header() require.NoError(l.T, err) + require.NoError(l.T, attestedState.SetLatestBlockHeader(attestedBlockHeader.Header)) attestedStateRoot, err := attestedState.HashTreeRoot(ctx) require.NoError(l.T, err) - - // get a new signed block so the root is updated with the new state root - parent.Block.StateRoot = attestedStateRoot[:] - signedParent, err = blocks.NewSignedBeaconBlock(parent) + attestedBlock.Block.StateRoot = attestedStateRoot[:] + signedAttestedBlock, err = blocks.NewSignedBeaconBlock(attestedBlock) require.NoError(l.T, err) - state, err := NewBeaconStateDeneb() - require.NoError(l.T, err) - err = state.SetSlot(slot) + // Signature State & Block + signatureState, err := NewBeaconStateDeneb() require.NoError(l.T, err) + require.NoError(l.T, signatureState.SetSlot(signatureSlot)) - parentRoot, err := signedParent.Block().HashTreeRoot() - require.NoError(l.T, err) - - var signedBlock interfaces.SignedBeaconBlock - if blinded { - block := NewBlindedBeaconBlockDeneb() - block.Message.Slot = slot - block.Message.ParentRoot = parentRoot[:] + var signedSignatureBlock interfaces.SignedBeaconBlock + if l.blinded { + signatureBlock := NewBlindedBeaconBlockDeneb() + signatureBlock.Message.Slot = signatureSlot + attestedBlockRoot, err := signedAttestedBlock.Block().HashTreeRoot() + require.NoError(l.T, err) + signatureBlock.Message.ParentRoot = attestedBlockRoot[:] var trueBitNum uint64 - if supermajority { - trueBitNum = (params.BeaconConfig().SyncCommitteeSize / 3 * 2) + 1 + if l.supermajority { + trueBitNum = uint64((float64(params.BeaconConfig().SyncCommitteeSize) * 2.0 / 3.0) + 1) } else { trueBitNum = params.BeaconConfig().MinSyncCommitteeParticipants } for i := uint64(0); i < trueBitNum; i++ { - block.Message.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + signatureBlock.Message.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) } - signedBlock, err = blocks.NewSignedBeaconBlock(block) + signedSignatureBlock, err = blocks.NewSignedBeaconBlock(signatureBlock) require.NoError(l.T, err) - h, err := signedBlock.Header() + signatureBlockHeader, err := signedSignatureBlock.Header() require.NoError(l.T, err) - err = state.SetLatestBlockHeader(h.Header) + err = signatureState.SetLatestBlockHeader(signatureBlockHeader.Header) require.NoError(l.T, err) - stateRoot, err := state.HashTreeRoot(ctx) + stateRoot, err := signatureState.HashTreeRoot(ctx) require.NoError(l.T, err) - // get a new signed block so the root is updated with the new state root - block.Message.StateRoot = stateRoot[:] - signedBlock, err = blocks.NewSignedBeaconBlock(block) + signatureBlock.Message.StateRoot = stateRoot[:] + signedSignatureBlock, err = blocks.NewSignedBeaconBlock(signatureBlock) require.NoError(l.T, err) } else { - block := NewBeaconBlockDeneb() - block.Block.Slot = slot - block.Block.ParentRoot = parentRoot[:] + signatureBlock := NewBeaconBlockDeneb() + signatureBlock.Block.Slot = signatureSlot + attestedBlockRoot, err := signedAttestedBlock.Block().HashTreeRoot() + require.NoError(l.T, err) + signatureBlock.Block.ParentRoot = attestedBlockRoot[:] var trueBitNum uint64 - if supermajority { - trueBitNum = (params.BeaconConfig().SyncCommitteeSize / 3 * 2) + 1 + if l.supermajority { + trueBitNum = uint64((float64(params.BeaconConfig().SyncCommitteeSize) * 2.0 / 3.0) + 1) } else { trueBitNum = params.BeaconConfig().MinSyncCommitteeParticipants } for i := uint64(0); i < trueBitNum; i++ { - block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + signatureBlock.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) } - signedBlock, err = blocks.NewSignedBeaconBlock(block) + signedSignatureBlock, err = blocks.NewSignedBeaconBlock(signatureBlock) require.NoError(l.T, err) - h, err := signedBlock.Header() + signatureBlockHeader, err := signedSignatureBlock.Header() require.NoError(l.T, err) - err = state.SetLatestBlockHeader(h.Header) + err = signatureState.SetLatestBlockHeader(signatureBlockHeader.Header) require.NoError(l.T, err) - stateRoot, err := state.HashTreeRoot(ctx) + signatureStateRoot, err := signatureState.HashTreeRoot(ctx) require.NoError(l.T, err) - // get a new signed block so the root is updated with the new state root - block.Block.StateRoot = stateRoot[:] - signedBlock, err = blocks.NewSignedBeaconBlock(block) + signatureBlock.Block.StateRoot = signatureStateRoot[:] + signedSignatureBlock, err = blocks.NewSignedBeaconBlock(signatureBlock) require.NoError(l.T, err) } - l.State = state + l.State = signatureState l.AttestedState = attestedState - l.AttestedBlock = signedParent - l.Block = signedBlock + l.AttestedBlock = signedAttestedBlock + l.Block = signedSignatureBlock l.Ctx = ctx - l.FinalizedBlock = finalizedBlock + l.FinalizedBlock = signedFinalizedBlock return l } -func (l *TestLightClient) SetupTestElectra(blinded bool, increaseAttestedSlotBy int, supermajority bool) *TestLightClient { +func (l *TestLightClient) setupTestElectra() *TestLightClient { ctx := context.Background() - slot := primitives.Slot(params.BeaconConfig().ElectraForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) - if increaseAttestedSlotBy > 0 { - slot = slot.Add(uint64(increaseAttestedSlotBy)) + attestedSlot := primitives.Slot(uint64(params.BeaconConfig().ElectraForkEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch)).Add(1) + if l.increaseAttestedSlotBy > 0 { + attestedSlot = attestedSlot.Add(l.increaseAttestedSlotBy) } - finalizedBlockSlot := primitives.Slot(params.BeaconConfig().ElectraForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)) + signatureSlot := attestedSlot.Add(1) + + // Attested State & Block attestedState, err := NewBeaconStateElectra() require.NoError(l.T, err) - err = attestedState.SetSlot(slot) - require.NoError(l.T, err) + require.NoError(l.T, attestedState.SetSlot(attestedSlot)) - finalizedBlock, err := blocks.NewSignedBeaconBlock(NewBeaconBlockDeneb()) - require.NoError(l.T, err) - finalizedBlock.SetSlot(finalizedBlockSlot) - finalizedHeader, err := finalizedBlock.Header() - require.NoError(l.T, err) - finalizedRoot, err := finalizedHeader.Header.HashTreeRoot() - require.NoError(l.T, err) + var signedFinalizedBlock interfaces.SignedBeaconBlock + // Finalized checkpoint + if !l.noFinalizedCheckpoint { + var finalizedSlot primitives.Slot - require.NoError(l.T, attestedState.SetFinalizedCheckpoint(ðpb.Checkpoint{ - Epoch: params.BeaconConfig().ElectraForkEpoch, - Root: finalizedRoot[:], - })) + if l.finalizedCheckpointInPrevFork { + finalizedSlot = primitives.Slot(uint64(params.BeaconConfig().DenebForkEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch)) + if l.increaseFinalizedSlotBy > 0 { + finalizedSlot = finalizedSlot.Add(l.increaseFinalizedSlotBy) + } - parent := NewBeaconBlockElectra() - parent.Block.Slot = slot + finalizedState, err := NewBeaconStateDeneb() + require.NoError(l.T, err) + require.NoError(l.T, finalizedState.SetSlot(finalizedSlot)) - signedParent, err := blocks.NewSignedBeaconBlock(parent) + finalizedBlock := NewBeaconBlockDeneb() + require.NoError(l.T, err) + finalizedBlock.Block.Slot = finalizedSlot + signedFinalizedBlock, err = blocks.NewSignedBeaconBlock(finalizedBlock) + require.NoError(l.T, err) + finalizedHeader, err := signedFinalizedBlock.Header() + require.NoError(l.T, err) + require.NoError(l.T, finalizedState.SetLatestBlockHeader(finalizedHeader.Header)) + finalizedStateRoot, err := finalizedState.HashTreeRoot(ctx) + require.NoError(l.T, err) + finalizedBlock.Block.StateRoot = finalizedStateRoot[:] + signedFinalizedBlock, err = blocks.NewSignedBeaconBlock(finalizedBlock) + require.NoError(l.T, err) + } else { + finalizedSlot = primitives.Slot(uint64(params.BeaconConfig().ElectraForkEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch)) + if l.increaseFinalizedSlotBy > 0 { + finalizedSlot = finalizedSlot.Add(l.increaseFinalizedSlotBy) + } + + finalizedState, err := NewBeaconStateElectra() + require.NoError(l.T, err) + require.NoError(l.T, finalizedState.SetSlot(finalizedSlot)) + + finalizedBlock := NewBeaconBlockElectra() + require.NoError(l.T, err) + finalizedBlock.Block.Slot = finalizedSlot + signedFinalizedBlock, err = blocks.NewSignedBeaconBlock(finalizedBlock) + require.NoError(l.T, err) + finalizedHeader, err := signedFinalizedBlock.Header() + require.NoError(l.T, err) + require.NoError(l.T, finalizedState.SetLatestBlockHeader(finalizedHeader.Header)) + finalizedStateRoot, err := finalizedState.HashTreeRoot(ctx) + require.NoError(l.T, err) + finalizedBlock.Block.StateRoot = finalizedStateRoot[:] + signedFinalizedBlock, err = blocks.NewSignedBeaconBlock(finalizedBlock) + require.NoError(l.T, err) + } + + // Set the finalized checkpoint + finalizedBlockRoot, err := signedFinalizedBlock.Block().HashTreeRoot() + require.NoError(l.T, err) + finalizedCheckpoint := ðpb.Checkpoint{ + Epoch: slots.ToEpoch(finalizedSlot), + Root: finalizedBlockRoot[:], + } + require.NoError(l.T, attestedState.SetFinalizedCheckpoint(finalizedCheckpoint)) + } + + // Attested Block + attestedBlock := NewBeaconBlockElectra() + attestedBlock.Block.Slot = attestedSlot + signedAttestedBlock, err := blocks.NewSignedBeaconBlock(attestedBlock) require.NoError(l.T, err) - - parentHeader, err := signedParent.Header() - require.NoError(l.T, err) - attestedHeader := parentHeader.Header - - err = attestedState.SetLatestBlockHeader(attestedHeader) + attestedBlockHeader, err := signedAttestedBlock.Header() require.NoError(l.T, err) + require.NoError(l.T, attestedState.SetLatestBlockHeader(attestedBlockHeader.Header)) attestedStateRoot, err := attestedState.HashTreeRoot(ctx) require.NoError(l.T, err) - - // get a new signed block so the root is updated with the new state root - parent.Block.StateRoot = attestedStateRoot[:] - signedParent, err = blocks.NewSignedBeaconBlock(parent) + attestedBlock.Block.StateRoot = attestedStateRoot[:] + signedAttestedBlock, err = blocks.NewSignedBeaconBlock(attestedBlock) require.NoError(l.T, err) - state, err := NewBeaconStateElectra() - require.NoError(l.T, err) - err = state.SetSlot(slot) + // Signature State & Block + signatureState, err := NewBeaconStateElectra() require.NoError(l.T, err) + require.NoError(l.T, signatureState.SetSlot(signatureSlot)) - parentRoot, err := signedParent.Block().HashTreeRoot() - require.NoError(l.T, err) - - var signedBlock interfaces.SignedBeaconBlock - if blinded { - block := NewBlindedBeaconBlockElectra() - block.Message.Slot = slot - block.Message.ParentRoot = parentRoot[:] + var signedSignatureBlock interfaces.SignedBeaconBlock + if l.blinded { + signatureBlock := NewBlindedBeaconBlockElectra() + signatureBlock.Message.Slot = signatureSlot + attestedBlockRoot, err := signedAttestedBlock.Block().HashTreeRoot() + require.NoError(l.T, err) + signatureBlock.Message.ParentRoot = attestedBlockRoot[:] var trueBitNum uint64 - if supermajority { - trueBitNum = (params.BeaconConfig().SyncCommitteeSize / 3 * 2) + 1 + if l.supermajority { + trueBitNum = uint64((float64(params.BeaconConfig().SyncCommitteeSize) * 2.0 / 3.0) + 1) } else { trueBitNum = params.BeaconConfig().MinSyncCommitteeParticipants } for i := uint64(0); i < trueBitNum; i++ { - block.Message.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + signatureBlock.Message.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) } - signedBlock, err = blocks.NewSignedBeaconBlock(block) + signedSignatureBlock, err = blocks.NewSignedBeaconBlock(signatureBlock) require.NoError(l.T, err) - h, err := signedBlock.Header() + signatureBlockHeader, err := signedSignatureBlock.Header() require.NoError(l.T, err) - err = state.SetLatestBlockHeader(h.Header) + err = signatureState.SetLatestBlockHeader(signatureBlockHeader.Header) require.NoError(l.T, err) - stateRoot, err := state.HashTreeRoot(ctx) + stateRoot, err := signatureState.HashTreeRoot(ctx) require.NoError(l.T, err) - // get a new signed block so the root is updated with the new state root - block.Message.StateRoot = stateRoot[:] - signedBlock, err = blocks.NewSignedBeaconBlock(block) + signatureBlock.Message.StateRoot = stateRoot[:] + signedSignatureBlock, err = blocks.NewSignedBeaconBlock(signatureBlock) require.NoError(l.T, err) } else { - block := NewBeaconBlockElectra() - block.Block.Slot = slot - block.Block.ParentRoot = parentRoot[:] + signatureBlock := NewBeaconBlockElectra() + signatureBlock.Block.Slot = signatureSlot + attestedBlockRoot, err := signedAttestedBlock.Block().HashTreeRoot() + require.NoError(l.T, err) + signatureBlock.Block.ParentRoot = attestedBlockRoot[:] var trueBitNum uint64 - if supermajority { - trueBitNum = (params.BeaconConfig().SyncCommitteeSize / 3 * 2) + 1 + if l.supermajority { + trueBitNum = uint64((float64(params.BeaconConfig().SyncCommitteeSize) * 2.0 / 3.0) + 1) } else { trueBitNum = params.BeaconConfig().MinSyncCommitteeParticipants } for i := uint64(0); i < trueBitNum; i++ { - block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + signatureBlock.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) } - signedBlock, err = blocks.NewSignedBeaconBlock(block) + signedSignatureBlock, err = blocks.NewSignedBeaconBlock(signatureBlock) require.NoError(l.T, err) - h, err := signedBlock.Header() + signatureBlockHeader, err := signedSignatureBlock.Header() require.NoError(l.T, err) - err = state.SetLatestBlockHeader(h.Header) + err = signatureState.SetLatestBlockHeader(signatureBlockHeader.Header) require.NoError(l.T, err) - stateRoot, err := state.HashTreeRoot(ctx) + signatureStateRoot, err := signatureState.HashTreeRoot(ctx) require.NoError(l.T, err) - // get a new signed block so the root is updated with the new state root - block.Block.StateRoot = stateRoot[:] - signedBlock, err = blocks.NewSignedBeaconBlock(block) + signatureBlock.Block.StateRoot = signatureStateRoot[:] + signedSignatureBlock, err = blocks.NewSignedBeaconBlock(signatureBlock) require.NoError(l.T, err) } - l.State = state + l.State = signatureState l.AttestedState = attestedState - l.AttestedBlock = signedParent - l.Block = signedBlock + l.AttestedBlock = signedAttestedBlock + l.Block = signedSignatureBlock l.Ctx = ctx - l.FinalizedBlock = finalizedBlock - - return l -} - -func (l *TestLightClient) SetupTestFulu(blinded bool, increaseAttestedSlotBy int, supermajority bool) *TestLightClient { - ctx := context.Background() - - slot := primitives.Slot(params.BeaconConfig().FuluForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) - if increaseAttestedSlotBy > 0 { - slot = slot.Add(uint64(increaseAttestedSlotBy)) - } - - attestedState, err := NewBeaconStateFulu() - require.NoError(l.T, err) - err = attestedState.SetSlot(slot) - require.NoError(l.T, err) - - finalizedBlock, err := blocks.NewSignedBeaconBlock(NewBeaconBlockFulu()) - require.NoError(l.T, err) - finalizedBlock.SetSlot(1) - finalizedHeader, err := finalizedBlock.Header() - require.NoError(l.T, err) - finalizedRoot, err := finalizedHeader.Header.HashTreeRoot() - require.NoError(l.T, err) - - require.NoError(l.T, attestedState.SetFinalizedCheckpoint(ðpb.Checkpoint{ - Epoch: params.BeaconConfig().FuluForkEpoch - 10, - Root: finalizedRoot[:], - })) - - parent := NewBeaconBlockFulu() - parent.Block.Slot = slot - - signedParent, err := blocks.NewSignedBeaconBlock(parent) - require.NoError(l.T, err) - - parentHeader, err := signedParent.Header() - require.NoError(l.T, err) - attestedHeader := parentHeader.Header - - err = attestedState.SetLatestBlockHeader(attestedHeader) - require.NoError(l.T, err) - attestedStateRoot, err := attestedState.HashTreeRoot(ctx) - require.NoError(l.T, err) - - // get a new signed block so the root is updated with the new state root - parent.Block.StateRoot = attestedStateRoot[:] - signedParent, err = blocks.NewSignedBeaconBlock(parent) - require.NoError(l.T, err) - - state, err := NewBeaconStateFulu() - require.NoError(l.T, err) - err = state.SetSlot(slot) - require.NoError(l.T, err) - - parentRoot, err := signedParent.Block().HashTreeRoot() - require.NoError(l.T, err) - - var signedBlock interfaces.SignedBeaconBlock - if blinded { - block := NewBlindedBeaconBlockFulu() - block.Message.Slot = slot - block.Message.ParentRoot = parentRoot[:] - - var trueBitNum uint64 - if supermajority { - trueBitNum = (params.BeaconConfig().SyncCommitteeSize / 3 * 2) + 1 - } else { - trueBitNum = params.BeaconConfig().MinSyncCommitteeParticipants - } - for i := uint64(0); i < trueBitNum; i++ { - block.Message.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) - } - - signedBlock, err = blocks.NewSignedBeaconBlock(block) - require.NoError(l.T, err) - - h, err := signedBlock.Header() - require.NoError(l.T, err) - - err = state.SetLatestBlockHeader(h.Header) - require.NoError(l.T, err) - stateRoot, err := state.HashTreeRoot(ctx) - require.NoError(l.T, err) - - // get a new signed block so the root is updated with the new state root - block.Message.StateRoot = stateRoot[:] - signedBlock, err = blocks.NewSignedBeaconBlock(block) - require.NoError(l.T, err) - } else { - block := NewBeaconBlockFulu() - block.Block.Slot = slot - block.Block.ParentRoot = parentRoot[:] - - var trueBitNum uint64 - if supermajority { - trueBitNum = (params.BeaconConfig().SyncCommitteeSize / 3 * 2) + 1 - } else { - trueBitNum = params.BeaconConfig().MinSyncCommitteeParticipants - } - for i := uint64(0); i < trueBitNum; i++ { - block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) - } - - signedBlock, err = blocks.NewSignedBeaconBlock(block) - require.NoError(l.T, err) - - h, err := signedBlock.Header() - require.NoError(l.T, err) - - err = state.SetLatestBlockHeader(h.Header) - require.NoError(l.T, err) - stateRoot, err := state.HashTreeRoot(ctx) - require.NoError(l.T, err) - - // get a new signed block so the root is updated with the new state root - block.Block.StateRoot = stateRoot[:] - signedBlock, err = blocks.NewSignedBeaconBlock(block) - require.NoError(l.T, err) - } - - l.State = state - l.AttestedState = attestedState - l.AttestedBlock = signedParent - l.Block = signedBlock - l.Ctx = ctx - l.FinalizedBlock = finalizedBlock - - return l -} - -func (l *TestLightClient) SetupTestDenebFinalizedBlockCapella(blinded bool) *TestLightClient { - ctx := context.Background() - - slot := primitives.Slot(params.BeaconConfig().DenebForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) - - attestedState, err := NewBeaconStateDeneb() - require.NoError(l.T, err) - err = attestedState.SetSlot(slot) - require.NoError(l.T, err) - - finalizedBlock, err := blocks.NewSignedBeaconBlock(NewBeaconBlockCapella()) - require.NoError(l.T, err) - finalizedBlock.SetSlot(primitives.Slot(params.BeaconConfig().DenebForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Sub(15)) - finalizedHeader, err := finalizedBlock.Header() - require.NoError(l.T, err) - finalizedRoot, err := finalizedHeader.Header.HashTreeRoot() - require.NoError(l.T, err) - - require.NoError(l.T, attestedState.SetFinalizedCheckpoint(ðpb.Checkpoint{ - Epoch: params.BeaconConfig().DenebForkEpoch - 1, - Root: finalizedRoot[:], - })) - - parent := NewBeaconBlockDeneb() - parent.Block.Slot = slot - - signedParent, err := blocks.NewSignedBeaconBlock(parent) - require.NoError(l.T, err) - - parentHeader, err := signedParent.Header() - require.NoError(l.T, err) - attestedHeader := parentHeader.Header - - err = attestedState.SetLatestBlockHeader(attestedHeader) - require.NoError(l.T, err) - attestedStateRoot, err := attestedState.HashTreeRoot(ctx) - require.NoError(l.T, err) - - // get a new signed block so the root is updated with the new state root - parent.Block.StateRoot = attestedStateRoot[:] - signedParent, err = blocks.NewSignedBeaconBlock(parent) - require.NoError(l.T, err) - - state, err := NewBeaconStateDeneb() - require.NoError(l.T, err) - err = state.SetSlot(slot) - require.NoError(l.T, err) - - parentRoot, err := signedParent.Block().HashTreeRoot() - require.NoError(l.T, err) - - var signedBlock interfaces.SignedBeaconBlock - if blinded { - block := NewBlindedBeaconBlockDeneb() - block.Message.Slot = slot - block.Message.ParentRoot = parentRoot[:] - - for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ { - block.Message.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) - } - - signedBlock, err = blocks.NewSignedBeaconBlock(block) - require.NoError(l.T, err) - - h, err := signedBlock.Header() - require.NoError(l.T, err) - - err = state.SetLatestBlockHeader(h.Header) - require.NoError(l.T, err) - stateRoot, err := state.HashTreeRoot(ctx) - require.NoError(l.T, err) - - // get a new signed block so the root is updated with the new state root - block.Message.StateRoot = stateRoot[:] - signedBlock, err = blocks.NewSignedBeaconBlock(block) - require.NoError(l.T, err) - } else { - block := NewBeaconBlockDeneb() - block.Block.Slot = slot - block.Block.ParentRoot = parentRoot[:] - - for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ { - block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) - } - - signedBlock, err = blocks.NewSignedBeaconBlock(block) - require.NoError(l.T, err) - - h, err := signedBlock.Header() - require.NoError(l.T, err) - - err = state.SetLatestBlockHeader(h.Header) - require.NoError(l.T, err) - stateRoot, err := state.HashTreeRoot(ctx) - require.NoError(l.T, err) - - // get a new signed block so the root is updated with the new state root - block.Block.StateRoot = stateRoot[:] - signedBlock, err = blocks.NewSignedBeaconBlock(block) - require.NoError(l.T, err) - } - - l.State = state - l.AttestedState = attestedState - l.AttestedBlock = signedParent - l.Block = signedBlock - l.Ctx = ctx - l.FinalizedBlock = finalizedBlock - - return l -} - -func (l *TestLightClient) SetupTestElectraFinalizedBlockDeneb(blinded bool) *TestLightClient { - ctx := context.Background() - - slot := primitives.Slot(params.BeaconConfig().ElectraForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) - finalizedBlockSlot := primitives.Slot(params.BeaconConfig().DenebForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)) - - attestedState, err := NewBeaconStateElectra() - require.NoError(l.T, err) - err = attestedState.SetSlot(slot) - require.NoError(l.T, err) - - finalizedBlock, err := blocks.NewSignedBeaconBlock(NewBeaconBlockDeneb()) - require.NoError(l.T, err) - finalizedBlock.SetSlot(finalizedBlockSlot) - finalizedHeader, err := finalizedBlock.Header() - require.NoError(l.T, err) - finalizedRoot, err := finalizedHeader.Header.HashTreeRoot() - require.NoError(l.T, err) - - require.NoError(l.T, attestedState.SetFinalizedCheckpoint(ðpb.Checkpoint{ - Epoch: params.BeaconConfig().DenebForkEpoch, - Root: finalizedRoot[:], - })) - - parent := NewBeaconBlockElectra() - parent.Block.Slot = slot - - signedParent, err := blocks.NewSignedBeaconBlock(parent) - require.NoError(l.T, err) - - parentHeader, err := signedParent.Header() - require.NoError(l.T, err) - attestedHeader := parentHeader.Header - - err = attestedState.SetLatestBlockHeader(attestedHeader) - require.NoError(l.T, err) - attestedStateRoot, err := attestedState.HashTreeRoot(ctx) - require.NoError(l.T, err) - - // get a new signed block so the root is updated with the new state root - parent.Block.StateRoot = attestedStateRoot[:] - signedParent, err = blocks.NewSignedBeaconBlock(parent) - require.NoError(l.T, err) - - state, err := NewBeaconStateElectra() - require.NoError(l.T, err) - err = state.SetSlot(slot) - require.NoError(l.T, err) - - parentRoot, err := signedParent.Block().HashTreeRoot() - require.NoError(l.T, err) - - var signedBlock interfaces.SignedBeaconBlock - if blinded { - block := NewBlindedBeaconBlockElectra() - block.Message.Slot = slot - block.Message.ParentRoot = parentRoot[:] - - for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ { - block.Message.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) - } - - signedBlock, err = blocks.NewSignedBeaconBlock(block) - require.NoError(l.T, err) - - h, err := signedBlock.Header() - require.NoError(l.T, err) - - err = state.SetLatestBlockHeader(h.Header) - require.NoError(l.T, err) - stateRoot, err := state.HashTreeRoot(ctx) - require.NoError(l.T, err) - - // get a new signed block so the root is updated with the new state root - block.Message.StateRoot = stateRoot[:] - signedBlock, err = blocks.NewSignedBeaconBlock(block) - require.NoError(l.T, err) - } else { - block := NewBeaconBlockElectra() - block.Block.Slot = slot - block.Block.ParentRoot = parentRoot[:] - - for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ { - block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) - } - - signedBlock, err = blocks.NewSignedBeaconBlock(block) - require.NoError(l.T, err) - - h, err := signedBlock.Header() - require.NoError(l.T, err) - - err = state.SetLatestBlockHeader(h.Header) - require.NoError(l.T, err) - stateRoot, err := state.HashTreeRoot(ctx) - require.NoError(l.T, err) - - // get a new signed block so the root is updated with the new state root - block.Block.StateRoot = stateRoot[:] - signedBlock, err = blocks.NewSignedBeaconBlock(block) - require.NoError(l.T, err) - } - - l.State = state - l.AttestedState = attestedState - l.AttestedBlock = signedParent - l.Block = signedBlock - l.Ctx = ctx - l.FinalizedBlock = finalizedBlock + l.FinalizedBlock = signedFinalizedBlock return l } diff --git a/testing/util/lightclient_test.go b/testing/util/lightclient_test.go new file mode 100644 index 0000000000..8a29e47d9a --- /dev/null +++ b/testing/util/lightclient_test.go @@ -0,0 +1,71 @@ +package util_test + +import ( + "testing" + + "github.com/OffchainLabs/prysm/v6/config/params" + "github.com/OffchainLabs/prysm/v6/runtime/version" + "github.com/OffchainLabs/prysm/v6/testing/require" + "github.com/OffchainLabs/prysm/v6/testing/util" +) + +func TestLightClientUtils(t *testing.T) { + + t.Run("WithNoFinalizedBlock", func(t *testing.T) { + for i := 1; i < 6; i++ { + t.Run(version.String(i), func(t *testing.T) { + l := util.NewTestLightClient(t, i, util.WithNoFinalizedCheckpoint()) + require.IsNil(t, l.FinalizedBlock) + }) + } + }) + + t.Run("WithFinalizedBlockInPrevFork", func(t *testing.T) { + for i := 2; i < 6; i++ { + t.Run(version.String(i), func(t *testing.T) { + l := util.NewTestLightClient(t, i, util.WithFinalizedCheckpointInPrevFork()) + require.Equal(t, l.FinalizedBlock.Version(), i-1) + }) + } + }) + + t.Run("WithIncreasedAttestedSlot", func(t *testing.T) { + for i := 1; i < 6; i++ { + t.Run(version.String(i), func(t *testing.T) { + l1 := util.NewTestLightClient(t, i) + l2 := util.NewTestLightClient(t, i, util.WithIncreasedAttestedSlot(1)) + require.Equal(t, l1.AttestedBlock.Block().Slot()+1, l2.AttestedBlock.Block().Slot()) + }) + } + }) + + t.Run("WithIncreasedFinalizedSlot", func(t *testing.T) { + for i := 1; i < 6; i++ { + t.Run(version.String(i), func(t *testing.T) { + l1 := util.NewTestLightClient(t, i) + l2 := util.NewTestLightClient(t, i, util.WithIncreasedFinalizedSlot(1)) + require.Equal(t, l1.FinalizedBlock.Block().Slot()+1, l2.FinalizedBlock.Block().Slot()) + }) + } + }) + + t.Run("WithSupermajority", func(t *testing.T) { + for i := 1; i < 6; i++ { + t.Run(version.String(i), func(t *testing.T) { + l1 := util.NewTestLightClient(t, i) + l2 := util.NewTestLightClient(t, i, util.WithSupermajority()) + l1SyncAgg, err := l1.Block.Block().Body().SyncAggregate() + require.NoError(t, err) + l1Bits := l1SyncAgg.SyncCommitteeBits.Count() + l2SyncAgg, err := l2.Block.Block().Body().SyncAggregate() + require.NoError(t, err) + l2Bits := l2SyncAgg.SyncCommitteeBits.Count() + supermajorityCount := uint64(float64(params.BeaconConfig().SyncCommitteeSize) * 2.0 / 3.0) + + require.Equal(t, true, l1Bits < supermajorityCount) + require.Equal(t, true, l2Bits >= supermajorityCount) + }) + } + }) + +}