From bc7356505faca833790338229aa492403503ad44 Mon Sep 17 00:00:00 2001 From: Dhruv Bodani Date: Tue, 14 Feb 2023 21:00:09 +0530 Subject: [PATCH] compose: fix very large smoke test (#1797) Enables very large smoke test with 7 of 10 cluster and 100 validators. category: test ticket: #1471 --- app/app.go | 8 ++- app/vmock.go | 5 +- cmd/cmd_internal_test.go | 2 + cmd/run.go | 2 + .../TestSchedulerDuties_grouped.golden | 12 ++--- .../TestSchedulerDuties_spread.golden | 12 ++--- .../TestSchedulerDuties_spread_errors.golden | 12 ++--- core/validatorapi/validatorapi_test.go | 12 +++-- docs/configuration.md | 1 + testutil/beaconmock/beaconmock.go | 5 ++ testutil/beaconmock/options.go | 53 ++++++++++--------- .../TestDeterministicAttesterDuties.golden | 2 +- .../TestDeterministicProposerDuties.golden | 12 ++++- testutil/compose/compose/main.go | 9 ++++ testutil/compose/config.go | 30 +++++++---- testutil/compose/lock.go | 3 +- testutil/compose/new_test.go | 2 + testutil/compose/smoke/smoke_test.go | 9 ++-- .../TestDockerCompose_run_template.golden | 16 ++++++ .../testdata/TestDockerCompose_run_yml.golden | 4 ++ .../testdata/TestNewDefaultConfig.golden | 4 +- testutil/random.go | 7 +++ .../testdata/TestAttest_0_aggregations.golden | 6 +-- .../testdata/TestAttest_0_attestations.golden | 6 +-- .../testdata/TestAttest_1_aggregations.golden | 2 +- .../testdata/TestAttest_1_attestations.golden | 2 +- testutil/validatormock/validatormock.go | 37 ++++++------- testutil/validatormock/validatormock_test.go | 10 ++++ 28 files changed, 190 insertions(+), 95 deletions(-) diff --git a/app/app.go b/app/app.go index da76cfe4c..af96f84f6 100644 --- a/app/app.go +++ b/app/app.go @@ -90,6 +90,7 @@ type Config struct { SimnetBMock bool SimnetVMock bool SimnetValidatorKeysDir string + SimnetSlotDuration time.Duration SyntheticBlockProposals bool BuilderAPI bool @@ -685,10 +686,15 @@ func newETH2Client(ctx context.Context, conf Config, life *lifecycle.Manager, return nil, err } + // Default to 1s slot duration if not set. + if conf.SimnetSlotDuration == 0 { + conf.SimnetSlotDuration = time.Second + } + if conf.SimnetBMock { // Configure the beacon mock. const dutyFactor = 100 // Duty factor spreads duties deterministically in an epoch. opts := []beaconmock.Option{ - beaconmock.WithSlotDuration(time.Second), + beaconmock.WithSlotDuration(conf.SimnetSlotDuration), beaconmock.WithDeterministicAttesterDuties(dutyFactor), beaconmock.WithDeterministicSyncCommDuties(2, 8), // First 2 epochs of every 8 beaconmock.WithValidatorSet(createMockValidators(pubkeys)), diff --git a/app/vmock.go b/app/vmock.go index e00e6f8e2..3d877733d 100644 --- a/app/vmock.go +++ b/app/vmock.go @@ -234,7 +234,10 @@ func newVMockSigner(conf Config, pubshares []eth2p0.BLSPubKey) (validatormock.Si } } - signer := validatormock.NewSigner(secrets...) + signer, err := validatormock.NewSigner(secrets...) + if err != nil { + return nil, err + } if len(secrets) == 0 && len(pubshares) != 0 { return nil, errors.New("validator mock keys empty") diff --git a/cmd/cmd_internal_test.go b/cmd/cmd_internal_test.go index 370ade1be..6b6e3f124 100644 --- a/cmd/cmd_internal_test.go +++ b/cmd/cmd_internal_test.go @@ -23,6 +23,7 @@ import ( "os" "strings" "testing" + "time" "github.com/spf13/pflag" "github.com/stretchr/testify/require" @@ -88,6 +89,7 @@ func TestCmdFlags(t *testing.T) { LockFile: ".charon/cluster-lock.json", PrivKeyFile: ".charon/charon-enr-private-key", SimnetValidatorKeysDir: ".charon/validator_keys", + SimnetSlotDuration: time.Second, MonitoringAddr: "127.0.0.1:3620", ValidatorAPIAddr: "127.0.0.1:3600", BeaconNodeAddrs: []string{"http://beacon.node"}, diff --git a/cmd/run.go b/cmd/run.go index d31cf74f8..1fe9142e1 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -18,6 +18,7 @@ package cmd import ( "context" "net/url" + "time" "github.com/spf13/cobra" "github.com/spf13/pflag" @@ -83,6 +84,7 @@ func bindRunFlags(cmd *cobra.Command, config *app.Config) { cmd.Flags().StringVar(&config.SimnetValidatorKeysDir, "simnet-validator-keys-dir", ".charon/validator_keys", "The directory containing the simnet validator key shares.") cmd.Flags().BoolVar(&config.BuilderAPI, "builder-api", false, "Enables the builder api. Will only produce builder blocks. Builder API must also be enabled on the validator client. Beacon node must be connected to a builder-relay to access the builder network.") cmd.Flags().BoolVar(&config.SyntheticBlockProposals, "synthetic-block-proposals", false, "Enables additional synthetic block proposal duties. Used for testing of rare duties.") + cmd.Flags().DurationVar(&config.SimnetSlotDuration, "simnet-slot-duration", time.Second, "Configures slot duration in simnet beacon mock.") wrapPreRunE(cmd, func(cmd *cobra.Command, args []string) error { if len(config.BeaconNodeAddrs) == 0 && !config.SimnetBMock { diff --git a/core/scheduler/testdata/TestSchedulerDuties_grouped.golden b/core/scheduler/testdata/TestSchedulerDuties_grouped.golden index c467566eb..c06c4faef 100644 --- a/core/scheduler/testdata/TestSchedulerDuties_grouped.golden +++ b/core/scheduler/testdata/TestSchedulerDuties_grouped.golden @@ -10,18 +10,18 @@ "Time": "00:04.000", "duty": "0/attester", "DutyDefSet": { - "0x8dae41352b69f2b3a1c0b05330c1bf65f03730c520273028864b11fcb94d8ce8f26d64f979a0ee3025467f45fd2241ea": "{\"pubkey\":\"0x8dae41352b69f2b3a1c0b05330c1bf65f03730c520273028864b11fcb94d8ce8f26d64f979a0ee3025467f45fd2241ea\",\"slot\":\"0\",\"validator_index\":\"2\",\"committee_index\":\"0\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}", - "0x8ee91545183c8c2db86633626f5074fd8ef93c4c9b7a2879ad1768f600c5b5906c3af20d47de42c3b032956fa8db1a76": "{\"pubkey\":\"0x8ee91545183c8c2db86633626f5074fd8ef93c4c9b7a2879ad1768f600c5b5906c3af20d47de42c3b032956fa8db1a76\",\"slot\":\"0\",\"validator_index\":\"3\",\"committee_index\":\"0\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}", - "0x914cff835a769156ba43ad50b931083c2dadd94e8359ce394bc7a3e06424d0214922ddf15f81640530b9c25c0bc0d490": "{\"pubkey\":\"0x914cff835a769156ba43ad50b931083c2dadd94e8359ce394bc7a3e06424d0214922ddf15f81640530b9c25c0bc0d490\",\"slot\":\"0\",\"validator_index\":\"1\",\"committee_index\":\"0\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}" + "0x8dae41352b69f2b3a1c0b05330c1bf65f03730c520273028864b11fcb94d8ce8f26d64f979a0ee3025467f45fd2241ea": "{\"pubkey\":\"0x8dae41352b69f2b3a1c0b05330c1bf65f03730c520273028864b11fcb94d8ce8f26d64f979a0ee3025467f45fd2241ea\",\"slot\":\"0\",\"validator_index\":\"2\",\"committee_index\":\"2\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}", + "0x8ee91545183c8c2db86633626f5074fd8ef93c4c9b7a2879ad1768f600c5b5906c3af20d47de42c3b032956fa8db1a76": "{\"pubkey\":\"0x8ee91545183c8c2db86633626f5074fd8ef93c4c9b7a2879ad1768f600c5b5906c3af20d47de42c3b032956fa8db1a76\",\"slot\":\"0\",\"validator_index\":\"3\",\"committee_index\":\"3\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}", + "0x914cff835a769156ba43ad50b931083c2dadd94e8359ce394bc7a3e06424d0214922ddf15f81640530b9c25c0bc0d490": "{\"pubkey\":\"0x914cff835a769156ba43ad50b931083c2dadd94e8359ce394bc7a3e06424d0214922ddf15f81640530b9c25c0bc0d490\",\"slot\":\"0\",\"validator_index\":\"1\",\"committee_index\":\"1\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}" } }, { "Time": "00:08.000", "duty": "0/aggregator", "DutyDefSet": { - "0x8dae41352b69f2b3a1c0b05330c1bf65f03730c520273028864b11fcb94d8ce8f26d64f979a0ee3025467f45fd2241ea": "{\"pubkey\":\"0x8dae41352b69f2b3a1c0b05330c1bf65f03730c520273028864b11fcb94d8ce8f26d64f979a0ee3025467f45fd2241ea\",\"slot\":\"0\",\"validator_index\":\"2\",\"committee_index\":\"0\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}", - "0x8ee91545183c8c2db86633626f5074fd8ef93c4c9b7a2879ad1768f600c5b5906c3af20d47de42c3b032956fa8db1a76": "{\"pubkey\":\"0x8ee91545183c8c2db86633626f5074fd8ef93c4c9b7a2879ad1768f600c5b5906c3af20d47de42c3b032956fa8db1a76\",\"slot\":\"0\",\"validator_index\":\"3\",\"committee_index\":\"0\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}", - "0x914cff835a769156ba43ad50b931083c2dadd94e8359ce394bc7a3e06424d0214922ddf15f81640530b9c25c0bc0d490": "{\"pubkey\":\"0x914cff835a769156ba43ad50b931083c2dadd94e8359ce394bc7a3e06424d0214922ddf15f81640530b9c25c0bc0d490\",\"slot\":\"0\",\"validator_index\":\"1\",\"committee_index\":\"0\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}" + "0x8dae41352b69f2b3a1c0b05330c1bf65f03730c520273028864b11fcb94d8ce8f26d64f979a0ee3025467f45fd2241ea": "{\"pubkey\":\"0x8dae41352b69f2b3a1c0b05330c1bf65f03730c520273028864b11fcb94d8ce8f26d64f979a0ee3025467f45fd2241ea\",\"slot\":\"0\",\"validator_index\":\"2\",\"committee_index\":\"2\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}", + "0x8ee91545183c8c2db86633626f5074fd8ef93c4c9b7a2879ad1768f600c5b5906c3af20d47de42c3b032956fa8db1a76": "{\"pubkey\":\"0x8ee91545183c8c2db86633626f5074fd8ef93c4c9b7a2879ad1768f600c5b5906c3af20d47de42c3b032956fa8db1a76\",\"slot\":\"0\",\"validator_index\":\"3\",\"committee_index\":\"3\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}", + "0x914cff835a769156ba43ad50b931083c2dadd94e8359ce394bc7a3e06424d0214922ddf15f81640530b9c25c0bc0d490": "{\"pubkey\":\"0x914cff835a769156ba43ad50b931083c2dadd94e8359ce394bc7a3e06424d0214922ddf15f81640530b9c25c0bc0d490\",\"slot\":\"0\",\"validator_index\":\"1\",\"committee_index\":\"1\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}" } } ] \ No newline at end of file diff --git a/core/scheduler/testdata/TestSchedulerDuties_spread.golden b/core/scheduler/testdata/TestSchedulerDuties_spread.golden index f0ff2faa7..64f30cf38 100644 --- a/core/scheduler/testdata/TestSchedulerDuties_spread.golden +++ b/core/scheduler/testdata/TestSchedulerDuties_spread.golden @@ -10,14 +10,14 @@ "Time": "00:04.000", "duty": "0/attester", "DutyDefSet": { - "0x914cff835a769156ba43ad50b931083c2dadd94e8359ce394bc7a3e06424d0214922ddf15f81640530b9c25c0bc0d490": "{\"pubkey\":\"0x914cff835a769156ba43ad50b931083c2dadd94e8359ce394bc7a3e06424d0214922ddf15f81640530b9c25c0bc0d490\",\"slot\":\"0\",\"validator_index\":\"1\",\"committee_index\":\"0\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}" + "0x914cff835a769156ba43ad50b931083c2dadd94e8359ce394bc7a3e06424d0214922ddf15f81640530b9c25c0bc0d490": "{\"pubkey\":\"0x914cff835a769156ba43ad50b931083c2dadd94e8359ce394bc7a3e06424d0214922ddf15f81640530b9c25c0bc0d490\",\"slot\":\"0\",\"validator_index\":\"1\",\"committee_index\":\"1\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}" } }, { "Time": "00:08.000", "duty": "0/aggregator", "DutyDefSet": { - "0x914cff835a769156ba43ad50b931083c2dadd94e8359ce394bc7a3e06424d0214922ddf15f81640530b9c25c0bc0d490": "{\"pubkey\":\"0x914cff835a769156ba43ad50b931083c2dadd94e8359ce394bc7a3e06424d0214922ddf15f81640530b9c25c0bc0d490\",\"slot\":\"0\",\"validator_index\":\"1\",\"committee_index\":\"0\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}" + "0x914cff835a769156ba43ad50b931083c2dadd94e8359ce394bc7a3e06424d0214922ddf15f81640530b9c25c0bc0d490": "{\"pubkey\":\"0x914cff835a769156ba43ad50b931083c2dadd94e8359ce394bc7a3e06424d0214922ddf15f81640530b9c25c0bc0d490\",\"slot\":\"0\",\"validator_index\":\"1\",\"committee_index\":\"1\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}" } }, { @@ -31,14 +31,14 @@ "Time": "00:16.000", "duty": "1/attester", "DutyDefSet": { - "0x8dae41352b69f2b3a1c0b05330c1bf65f03730c520273028864b11fcb94d8ce8f26d64f979a0ee3025467f45fd2241ea": "{\"pubkey\":\"0x8dae41352b69f2b3a1c0b05330c1bf65f03730c520273028864b11fcb94d8ce8f26d64f979a0ee3025467f45fd2241ea\",\"slot\":\"1\",\"validator_index\":\"2\",\"committee_index\":\"1\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}" + "0x8dae41352b69f2b3a1c0b05330c1bf65f03730c520273028864b11fcb94d8ce8f26d64f979a0ee3025467f45fd2241ea": "{\"pubkey\":\"0x8dae41352b69f2b3a1c0b05330c1bf65f03730c520273028864b11fcb94d8ce8f26d64f979a0ee3025467f45fd2241ea\",\"slot\":\"1\",\"validator_index\":\"2\",\"committee_index\":\"2\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}" } }, { "Time": "00:20.000", "duty": "1/aggregator", "DutyDefSet": { - "0x8dae41352b69f2b3a1c0b05330c1bf65f03730c520273028864b11fcb94d8ce8f26d64f979a0ee3025467f45fd2241ea": "{\"pubkey\":\"0x8dae41352b69f2b3a1c0b05330c1bf65f03730c520273028864b11fcb94d8ce8f26d64f979a0ee3025467f45fd2241ea\",\"slot\":\"1\",\"validator_index\":\"2\",\"committee_index\":\"1\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}" + "0x8dae41352b69f2b3a1c0b05330c1bf65f03730c520273028864b11fcb94d8ce8f26d64f979a0ee3025467f45fd2241ea": "{\"pubkey\":\"0x8dae41352b69f2b3a1c0b05330c1bf65f03730c520273028864b11fcb94d8ce8f26d64f979a0ee3025467f45fd2241ea\",\"slot\":\"1\",\"validator_index\":\"2\",\"committee_index\":\"2\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}" } }, { @@ -52,14 +52,14 @@ "Time": "00:28.000", "duty": "2/attester", "DutyDefSet": { - "0x8ee91545183c8c2db86633626f5074fd8ef93c4c9b7a2879ad1768f600c5b5906c3af20d47de42c3b032956fa8db1a76": "{\"pubkey\":\"0x8ee91545183c8c2db86633626f5074fd8ef93c4c9b7a2879ad1768f600c5b5906c3af20d47de42c3b032956fa8db1a76\",\"slot\":\"2\",\"validator_index\":\"3\",\"committee_index\":\"2\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}" + "0x8ee91545183c8c2db86633626f5074fd8ef93c4c9b7a2879ad1768f600c5b5906c3af20d47de42c3b032956fa8db1a76": "{\"pubkey\":\"0x8ee91545183c8c2db86633626f5074fd8ef93c4c9b7a2879ad1768f600c5b5906c3af20d47de42c3b032956fa8db1a76\",\"slot\":\"2\",\"validator_index\":\"3\",\"committee_index\":\"3\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}" } }, { "Time": "00:32.000", "duty": "2/aggregator", "DutyDefSet": { - "0x8ee91545183c8c2db86633626f5074fd8ef93c4c9b7a2879ad1768f600c5b5906c3af20d47de42c3b032956fa8db1a76": "{\"pubkey\":\"0x8ee91545183c8c2db86633626f5074fd8ef93c4c9b7a2879ad1768f600c5b5906c3af20d47de42c3b032956fa8db1a76\",\"slot\":\"2\",\"validator_index\":\"3\",\"committee_index\":\"2\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}" + "0x8ee91545183c8c2db86633626f5074fd8ef93c4c9b7a2879ad1768f600c5b5906c3af20d47de42c3b032956fa8db1a76": "{\"pubkey\":\"0x8ee91545183c8c2db86633626f5074fd8ef93c4c9b7a2879ad1768f600c5b5906c3af20d47de42c3b032956fa8db1a76\",\"slot\":\"2\",\"validator_index\":\"3\",\"committee_index\":\"3\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}" } } ] \ No newline at end of file diff --git a/core/scheduler/testdata/TestSchedulerDuties_spread_errors.golden b/core/scheduler/testdata/TestSchedulerDuties_spread_errors.golden index a01387d6b..4815ac816 100644 --- a/core/scheduler/testdata/TestSchedulerDuties_spread_errors.golden +++ b/core/scheduler/testdata/TestSchedulerDuties_spread_errors.golden @@ -3,14 +3,14 @@ "Time": "00:04.000", "duty": "0/attester", "DutyDefSet": { - "0x914cff835a769156ba43ad50b931083c2dadd94e8359ce394bc7a3e06424d0214922ddf15f81640530b9c25c0bc0d490": "{\"pubkey\":\"0x914cff835a769156ba43ad50b931083c2dadd94e8359ce394bc7a3e06424d0214922ddf15f81640530b9c25c0bc0d490\",\"slot\":\"0\",\"validator_index\":\"1\",\"committee_index\":\"0\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}" + "0x914cff835a769156ba43ad50b931083c2dadd94e8359ce394bc7a3e06424d0214922ddf15f81640530b9c25c0bc0d490": "{\"pubkey\":\"0x914cff835a769156ba43ad50b931083c2dadd94e8359ce394bc7a3e06424d0214922ddf15f81640530b9c25c0bc0d490\",\"slot\":\"0\",\"validator_index\":\"1\",\"committee_index\":\"1\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}" } }, { "Time": "00:08.000", "duty": "0/aggregator", "DutyDefSet": { - "0x914cff835a769156ba43ad50b931083c2dadd94e8359ce394bc7a3e06424d0214922ddf15f81640530b9c25c0bc0d490": "{\"pubkey\":\"0x914cff835a769156ba43ad50b931083c2dadd94e8359ce394bc7a3e06424d0214922ddf15f81640530b9c25c0bc0d490\",\"slot\":\"0\",\"validator_index\":\"1\",\"committee_index\":\"0\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}" + "0x914cff835a769156ba43ad50b931083c2dadd94e8359ce394bc7a3e06424d0214922ddf15f81640530b9c25c0bc0d490": "{\"pubkey\":\"0x914cff835a769156ba43ad50b931083c2dadd94e8359ce394bc7a3e06424d0214922ddf15f81640530b9c25c0bc0d490\",\"slot\":\"0\",\"validator_index\":\"1\",\"committee_index\":\"1\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}" } }, { @@ -24,14 +24,14 @@ "Time": "00:16.000", "duty": "1/attester", "DutyDefSet": { - "0x8dae41352b69f2b3a1c0b05330c1bf65f03730c520273028864b11fcb94d8ce8f26d64f979a0ee3025467f45fd2241ea": "{\"pubkey\":\"0x8dae41352b69f2b3a1c0b05330c1bf65f03730c520273028864b11fcb94d8ce8f26d64f979a0ee3025467f45fd2241ea\",\"slot\":\"1\",\"validator_index\":\"2\",\"committee_index\":\"1\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}" + "0x8dae41352b69f2b3a1c0b05330c1bf65f03730c520273028864b11fcb94d8ce8f26d64f979a0ee3025467f45fd2241ea": "{\"pubkey\":\"0x8dae41352b69f2b3a1c0b05330c1bf65f03730c520273028864b11fcb94d8ce8f26d64f979a0ee3025467f45fd2241ea\",\"slot\":\"1\",\"validator_index\":\"2\",\"committee_index\":\"2\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}" } }, { "Time": "00:20.000", "duty": "1/aggregator", "DutyDefSet": { - "0x8dae41352b69f2b3a1c0b05330c1bf65f03730c520273028864b11fcb94d8ce8f26d64f979a0ee3025467f45fd2241ea": "{\"pubkey\":\"0x8dae41352b69f2b3a1c0b05330c1bf65f03730c520273028864b11fcb94d8ce8f26d64f979a0ee3025467f45fd2241ea\",\"slot\":\"1\",\"validator_index\":\"2\",\"committee_index\":\"1\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}" + "0x8dae41352b69f2b3a1c0b05330c1bf65f03730c520273028864b11fcb94d8ce8f26d64f979a0ee3025467f45fd2241ea": "{\"pubkey\":\"0x8dae41352b69f2b3a1c0b05330c1bf65f03730c520273028864b11fcb94d8ce8f26d64f979a0ee3025467f45fd2241ea\",\"slot\":\"1\",\"validator_index\":\"2\",\"committee_index\":\"2\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}" } }, { @@ -45,14 +45,14 @@ "Time": "00:28.000", "duty": "2/attester", "DutyDefSet": { - "0x8ee91545183c8c2db86633626f5074fd8ef93c4c9b7a2879ad1768f600c5b5906c3af20d47de42c3b032956fa8db1a76": "{\"pubkey\":\"0x8ee91545183c8c2db86633626f5074fd8ef93c4c9b7a2879ad1768f600c5b5906c3af20d47de42c3b032956fa8db1a76\",\"slot\":\"2\",\"validator_index\":\"3\",\"committee_index\":\"2\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}" + "0x8ee91545183c8c2db86633626f5074fd8ef93c4c9b7a2879ad1768f600c5b5906c3af20d47de42c3b032956fa8db1a76": "{\"pubkey\":\"0x8ee91545183c8c2db86633626f5074fd8ef93c4c9b7a2879ad1768f600c5b5906c3af20d47de42c3b032956fa8db1a76\",\"slot\":\"2\",\"validator_index\":\"3\",\"committee_index\":\"3\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}" } }, { "Time": "00:32.000", "duty": "2/aggregator", "DutyDefSet": { - "0x8ee91545183c8c2db86633626f5074fd8ef93c4c9b7a2879ad1768f600c5b5906c3af20d47de42c3b032956fa8db1a76": "{\"pubkey\":\"0x8ee91545183c8c2db86633626f5074fd8ef93c4c9b7a2879ad1768f600c5b5906c3af20d47de42c3b032956fa8db1a76\",\"slot\":\"2\",\"validator_index\":\"3\",\"committee_index\":\"2\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}" + "0x8ee91545183c8c2db86633626f5074fd8ef93c4c9b7a2879ad1768f600c5b5906c3af20d47de42c3b032956fa8db1a76": "{\"pubkey\":\"0x8ee91545183c8c2db86633626f5074fd8ef93c4c9b7a2879ad1768f600c5b5906c3af20d47de42c3b032956fa8db1a76\",\"slot\":\"2\",\"validator_index\":\"3\",\"committee_index\":\"3\",\"committee_length\":\"1\",\"committees_at_slot\":\"16\",\"validator_committee_index\":\"0\"}" } } ] \ No newline at end of file diff --git a/core/validatorapi/validatorapi_test.go b/core/validatorapi/validatorapi_test.go index c46244f96..383b402ab 100644 --- a/core/validatorapi/validatorapi_test.go +++ b/core/validatorapi/validatorapi_test.go @@ -208,7 +208,7 @@ func TestSubmitAttestations_Verify(t *testing.T) { vapi.RegisterPubKeyByAttestation(func(ctx context.Context, slot, commIdx, valCommIdx int64) (core.PubKey, error) { require.EqualValues(t, slot, epochSlot) - require.EqualValues(t, commIdx, 0) + require.EqualValues(t, commIdx, vIdx) require.EqualValues(t, valCommIdx, 0) return corePubKey, nil @@ -226,11 +226,14 @@ func TestSubmitAttestations_Verify(t *testing.T) { // Configure beacon mock to call validator API for submissions bmock.SubmitAttestationsFunc = vapi.SubmitAttestations + signer, err := validatormock.NewSigner(secret) + require.NoError(t, err) + // Run attestation using validator mock attester := validatormock.NewSlotAttester( bmock, eth2p0.Slot(epochSlot), - validatormock.NewSigner(secret), + signer, []eth2p0.BLSPubKey{validator.Validator.PublicKey}, ) @@ -290,8 +293,11 @@ func TestSignAndVerify(t *testing.T) { require.NoError(t, err) eth2Pubkey := eth2p0.BLSPubKey(pubkey) + signer, err := validatormock.NewSigner(secretKey) + require.NoError(t, err) + // Sign - sig, err := validatormock.NewSigner(secretKey)(eth2Pubkey, sigDataBytes[:]) + sig, err := signer(eth2Pubkey, sigDataBytes[:]) require.NoError(t, err) // Assert signature diff --git a/docs/configuration.md b/docs/configuration.md index fd84bdadf..2e87139fa 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -144,6 +144,7 @@ Flags: --p2p-tcp-address strings Comma-separated list of listening TCP addresses (ip and port) for libP2P traffic. Empty default doesn't bind to local port therefore only supports outgoing connections. --private-key-file string The path to the charon enr private key file. (default ".charon/charon-enr-private-key") --simnet-beacon-mock Enables an internal mock beacon node for running a simnet. + --simnet-slot-duration duration Configures slot duration in simnet beacon mock. (default 1s) --simnet-validator-keys-dir string The directory containing the simnet validator key shares. (default ".charon/validator_keys") --simnet-validator-mock Enables an internal mock validator client when running a simnet. Requires simnet-beacon-mock. --synthetic-block-proposals Enables additional synthetic block proposal duties. Used for testing of rare duties. diff --git a/testutil/beaconmock/beaconmock.go b/testutil/beaconmock/beaconmock.go index 24489e74b..ba7cb8230 100644 --- a/testutil/beaconmock/beaconmock.go +++ b/testutil/beaconmock/beaconmock.go @@ -163,6 +163,7 @@ type Mock struct { SyncCommitteeContributionFunc func(ctx context.Context, slot eth2p0.Slot, subcommitteeIndex uint64, beaconBlockRoot eth2p0.Root) (*altair.SyncCommitteeContribution, error) SubmitSyncCommitteeSubscriptionsFunc func(ctx context.Context, subscriptions []*eth2v1.SyncCommitteeSubscription) error SubmitProposalPreparationsFunc func(ctx context.Context, preparations []*eth2v1.ProposalPreparation) error + getAllValidatorsFunc func(ctx context.Context) []*eth2v1.Validator } func (m Mock) BlockAttestations(ctx context.Context, stateID string) ([]*eth2p0.Attestation, error) { @@ -315,3 +316,7 @@ func (m Mock) Close() error { return nil } + +func (m Mock) getAllValidators(ctx context.Context) []*eth2v1.Validator { + return m.getAllValidatorsFunc(ctx) +} diff --git a/testutil/beaconmock/options.go b/testutil/beaconmock/options.go index 013c43b0a..ae79689f4 100644 --- a/testutil/beaconmock/options.go +++ b/testutil/beaconmock/options.go @@ -177,6 +177,10 @@ func WithValidatorSet(set ValidatorSet) Option { return resp, nil } + + mock.getAllValidatorsFunc = func(ctx context.Context) []*eth2v1.Validator { + return set.Validators() + } } } @@ -285,7 +289,7 @@ func WithDeterministicAttesterDuties(factor int) Option { PubKey: val.Validator.PublicKey, Slot: eth2p0.Slot(slotsPerEpoch*uint64(epoch) + uint64(slotOffset)), ValidatorIndex: index, - CommitteeIndex: eth2p0.CommitteeIndex(slotOffset), + CommitteeIndex: eth2p0.CommitteeIndex(index), CommitteeLength: commLength, CommitteesAtSlot: slotsPerEpoch, ValidatorCommitteeIndex: valCommIndex, @@ -301,40 +305,33 @@ func WithDeterministicAttesterDuties(factor int) Option { // Note it depends on ValidatorsFunc being populated, e.g. via WithValidatorSet. func WithDeterministicProposerDuties(factor int) Option { return func(mock *Mock) { - mock.ProposerDutiesFunc = func(ctx context.Context, epoch eth2p0.Epoch, indices []eth2p0.ValidatorIndex) ([]*eth2v1.ProposerDuty, error) { - // if indices slice is empty then it would use 0th index or in that case first validator will be the proposer always - // this would be the case when validator calls for block proposer and expects proposer duties from beacon node. - if len(indices) == 0 { - indices = []eth2p0.ValidatorIndex{0} - } + mock.ProposerDutiesFunc = func(ctx context.Context, epoch eth2p0.Epoch, _ []eth2p0.ValidatorIndex) ([]*eth2v1.ProposerDuty, error) { + vals := mock.getAllValidators(ctx) - vals, err := mock.Validators(ctx, "", indices) - if err != nil { - return nil, err - } + sort.Slice(vals, func(i, j int) bool { + return vals[i].Index < vals[j].Index + }) slotsPerEpoch, err := mock.SlotsPerEpoch(ctx) if err != nil { return nil, err } - sort.Slice(indices, func(i, j int) bool { - return indices[i] < indices[j] - }) + slotsAssigned := make(map[int]bool) var resp []*eth2v1.ProposerDuty - for i, index := range indices { - val, ok := vals[index] - if !ok { - continue + for i, val := range vals { + offset := (i * factor) % int(slotsPerEpoch) + if slotsAssigned[offset] { + break } - offset := (i * factor) % int(slotsPerEpoch) + slotsAssigned[offset] = true resp = append(resp, ð2v1.ProposerDuty{ PubKey: val.Validator.PublicKey, Slot: eth2p0.Slot(slotsPerEpoch*uint64(epoch) + uint64(offset)), - ValidatorIndex: index, + ValidatorIndex: val.Index, }) // there can be only one proposer per slot, in this case it would be the first validator who will propose @@ -558,12 +555,16 @@ func defaultMock(httpMock HTTPMock, httpServer *http.Server, clock clockwork.Clo return nil }, SyncCommitteeContributionFunc: func(ctx context.Context, slot eth2p0.Slot, subcommitteeIndex uint64, beaconBlockRoot eth2p0.Root) (*altair.SyncCommitteeContribution, error) { - contrib := testutil.RandomSyncCommitteeContribution() - contrib.Slot = slot - contrib.SubcommitteeIndex = subcommitteeIndex - contrib.BeaconBlockRoot = beaconBlockRoot - - return contrib, nil + aggBits := bitfield.NewBitvector128() + aggBits.SetBitAt(uint64(slot%128), true) + + return &altair.SyncCommitteeContribution{ + Slot: slot, + SubcommitteeIndex: subcommitteeIndex, + BeaconBlockRoot: beaconBlockRoot, + AggregationBits: aggBits, + Signature: testutil.RandomEth2SignatureWithSeed(int64(slot)), + }, nil }, SubmitSyncCommitteeContributionsFunc: func(context.Context, []*altair.SignedContributionAndProof) error { return nil diff --git a/testutil/beaconmock/testdata/TestDeterministicAttesterDuties.golden b/testutil/beaconmock/testdata/TestDeterministicAttesterDuties.golden index dbaaab5a3..ddaa58541 100644 --- a/testutil/beaconmock/testdata/TestDeterministicAttesterDuties.golden +++ b/testutil/beaconmock/testdata/TestDeterministicAttesterDuties.golden @@ -3,7 +3,7 @@ "pubkey": "0x8dae41352b69f2b3a1c0b05330c1bf65f03730c520273028864b11fcb94d8ce8f26d64f979a0ee3025467f45fd2241ea", "slot": "16", "validator_index": "2", - "committee_index": "0", + "committee_index": "2", "committee_length": "1", "committees_at_slot": "16", "validator_committee_index": "0" diff --git a/testutil/beaconmock/testdata/TestDeterministicProposerDuties.golden b/testutil/beaconmock/testdata/TestDeterministicProposerDuties.golden index cd66838a5..ac08b87cc 100644 --- a/testutil/beaconmock/testdata/TestDeterministicProposerDuties.golden +++ b/testutil/beaconmock/testdata/TestDeterministicProposerDuties.golden @@ -1,7 +1,17 @@ [ { - "pubkey": "0x8dae41352b69f2b3a1c0b05330c1bf65f03730c520273028864b11fcb94d8ce8f26d64f979a0ee3025467f45fd2241ea", + "pubkey": "0x914cff835a769156ba43ad50b931083c2dadd94e8359ce394bc7a3e06424d0214922ddf15f81640530b9c25c0bc0d490", "slot": "16", + "validator_index": "1" + }, + { + "pubkey": "0x8dae41352b69f2b3a1c0b05330c1bf65f03730c520273028864b11fcb94d8ce8f26d64f979a0ee3025467f45fd2241ea", + "slot": "17", "validator_index": "2" + }, + { + "pubkey": "0x8ee91545183c8c2db86633626f5074fd8ef93c4c9b7a2879ad1768f600c5b5906c3af20d47de42c3b032956fa8db1a76", + "slot": "18", + "validator_index": "3" } ] \ No newline at end of file diff --git a/testutil/compose/compose/main.go b/testutil/compose/compose/main.go index a5d132cce..82f7f6221 100644 --- a/testutil/compose/compose/main.go +++ b/testutil/compose/compose/main.go @@ -27,11 +27,13 @@ import ( "context" "os/signal" "syscall" + "time" "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/obolnetwork/charon/app/log" + "github.com/obolnetwork/charon/cluster" "github.com/obolnetwork/charon/testutil/compose" ) @@ -134,6 +136,9 @@ func newNewCmd() *cobra.Command { featureSet := cmd.Flags().String("feature-set", conf.FeatureSet, "Minimum feature set to enable: alpha, beta, stable") numVals := cmd.Flags().Int("num-validators", conf.NumValidators, "Number of distributed validators.") vcTypes := cmd.Flags().StringSlice("validator-types", conf.VCStrings(), "Validator types to include.") + nodes := cmd.Flags().Int("nodes", conf.NumNodes, "Number of charon nodes in the cluster.") + insecureKeys := cmd.Flags().Bool("insecure-keys", conf.InsecureKeys, "To generate keys quickly.") + slotDuration := cmd.Flags().Duration("simnet-slot-duration", time.Second, "Configures slot duration in simnet beacon mock.") cmd.RunE = func(cmd *cobra.Command, _ []string) error { conf.KeyGen = compose.KeyGen(*keygen) @@ -143,6 +148,10 @@ func newNewCmd() *cobra.Command { conf.FeatureSet = *featureSet conf.ExternalRelay = *extRelay conf.NumValidators = *numVals + conf.NumNodes = *nodes + conf.Threshold = cluster.Threshold(conf.NumNodes) + conf.InsecureKeys = *insecureKeys + conf.SlotDuration = *slotDuration if conf.BuildLocal { conf.ImageTag = "local" diff --git a/testutil/compose/config.go b/testutil/compose/config.go index 0b587bbda..06364a90d 100644 --- a/testutil/compose/config.go +++ b/testutil/compose/config.go @@ -15,6 +15,8 @@ package compose +import "time" + const ( version = "obol/charon/compose/1.0.0" configFile = "config.json" @@ -114,6 +116,12 @@ type Config struct { // InsecureKeys generates insecure keys. Useful when testing large validator sets // as it speeds up keystore encryption and decryption. InsecureKeys bool `json:"insecure_keys"` + + // SlotDuration configures slot duration on simnet beacon mock for all the nodes in the cluster. + SlotDuration time.Duration `json:"slot_duration"` + + // SyntheticBlockProposals configures use of synthetic block proposals in simnet cluster. + SyntheticBlockProposals bool `json:"synthetic_block_proposals"` } // VCStrings returns the VCs field as a slice of strings. @@ -129,15 +137,17 @@ func (c Config) VCStrings() []string { // NewDefaultConfig returns a new default config. func NewDefaultConfig() Config { return Config{ - Version: version, - NumNodes: defaultNumNodes, - Threshold: defaultThreshold, - NumValidators: defaultNumVals, - ImageTag: defaultImageTag, - VCs: []VCType{VCTeku, VCLighthouse, VCMock}, - KeyGen: defaultKeyGen, - BeaconNode: defaultBeaconNode, - Step: stepNew, - FeatureSet: defaultFeatureSet, + Version: version, + NumNodes: defaultNumNodes, + Threshold: defaultThreshold, + NumValidators: defaultNumVals, + ImageTag: defaultImageTag, + VCs: []VCType{VCTeku, VCLighthouse, VCMock}, + KeyGen: defaultKeyGen, + BeaconNode: defaultBeaconNode, + Step: stepNew, + FeatureSet: defaultFeatureSet, + SlotDuration: time.Second, + SyntheticBlockProposals: true, } } diff --git a/testutil/compose/lock.go b/testutil/compose/lock.go index 557e138b3..05c87b8a2 100644 --- a/testutil/compose/lock.go +++ b/testutil/compose/lock.go @@ -144,10 +144,11 @@ func newNodeEnvs(index int, conf Config, vcType VCType) []kv { kv{"beacon-node-endpoint", beaconNode}, kv{"simnet-beacon_mock", fmt.Sprintf(`"%v"`, beaconMock)}, kv{"simnet-validator-mock", fmt.Sprintf(`"%v"`, vcType == VCMock)}, + kv{"simnet-slot-duration", conf.SlotDuration.String()}, kv{"simnet-validator-keys-dir", fmt.Sprintf("/compose/node%d/validator_keys", index)}, kv{"loki-addresses", "http://loki:3100/loki/api/v1/push"}, kv{"loki-service", fmt.Sprintf("node%d", index)}, - kv{"synthetic-block-proposals", `"true"`}, + kv{"synthetic-block-proposals", fmt.Sprintf(`"%v"`, conf.SyntheticBlockProposals)}, ) } diff --git a/testutil/compose/new_test.go b/testutil/compose/new_test.go index b96fccd8b..849545622 100644 --- a/testutil/compose/new_test.go +++ b/testutil/compose/new_test.go @@ -27,6 +27,8 @@ import ( "github.com/obolnetwork/charon/testutil/compose" ) +//go:generate go test . -update -clean + func TestNewDefaultConfig(t *testing.T) { dir := t.TempDir() diff --git a/testutil/compose/smoke/smoke_test.go b/testutil/compose/smoke/smoke_test.go index 35d4dd7c0..3d8341a66 100644 --- a/testutil/compose/smoke/smoke_test.go +++ b/testutil/compose/smoke/smoke_test.go @@ -84,15 +84,18 @@ func TestSmoke(t *testing.T) { }, }, { - Name: "very_large", // TODO(dhruv): fix consensus issues in this test + Name: "very_large", ConfigFunc: func(conf *compose.Config) { conf.NumNodes = 10 conf.Threshold = 7 - conf.NumValidators = 15 + conf.NumValidators = 100 conf.InsecureKeys = true conf.KeyGen = compose.KeyGenCreate + conf.VCs = []compose.VCType{compose.VCMock} + conf.SlotDuration = time.Second * 6 + conf.SyntheticBlockProposals = false }, - Timeout: time.Second * 120, + Timeout: time.Minute * 2, }, { Name: "run_version_matrix_with_dkg", diff --git a/testutil/compose/testdata/TestDockerCompose_run_template.golden b/testutil/compose/testdata/TestDockerCompose_run_template.golden index 7a7ff36ba..2cab56371 100644 --- a/testutil/compose/testdata/TestDockerCompose_run_template.golden +++ b/testutil/compose/testdata/TestDockerCompose_run_template.golden @@ -65,6 +65,10 @@ "Key": "simnet-validator-mock", "Value": "\"false\"" }, + { + "Key": "simnet-slot-duration", + "Value": "1s" + }, { "Key": "simnet-validator-keys-dir", "Value": "/compose/node0/validator_keys" @@ -162,6 +166,10 @@ "Key": "simnet-validator-mock", "Value": "\"false\"" }, + { + "Key": "simnet-slot-duration", + "Value": "1s" + }, { "Key": "simnet-validator-keys-dir", "Value": "/compose/node1/validator_keys" @@ -259,6 +267,10 @@ "Key": "simnet-validator-mock", "Value": "\"true\"" }, + { + "Key": "simnet-slot-duration", + "Value": "1s" + }, { "Key": "simnet-validator-keys-dir", "Value": "/compose/node2/validator_keys" @@ -356,6 +368,10 @@ "Key": "simnet-validator-mock", "Value": "\"false\"" }, + { + "Key": "simnet-slot-duration", + "Value": "1s" + }, { "Key": "simnet-validator-keys-dir", "Value": "/compose/node3/validator_keys" diff --git a/testutil/compose/testdata/TestDockerCompose_run_yml.golden b/testutil/compose/testdata/TestDockerCompose_run_yml.golden index e1a83c8cf..13d74cfba 100644 --- a/testutil/compose/testdata/TestDockerCompose_run_yml.golden +++ b/testutil/compose/testdata/TestDockerCompose_run_yml.golden @@ -26,6 +26,7 @@ services: CHARON_BEACON_NODE_ENDPOINT: CHARON_SIMNET_BEACON_MOCK: "true" CHARON_SIMNET_VALIDATOR_MOCK: "false" + CHARON_SIMNET_SLOT_DURATION: 1s CHARON_SIMNET_VALIDATOR_KEYS_DIR: /compose/node0/validator_keys CHARON_LOKI_ADDRESSES: http://loki:3100/loki/api/v1/push CHARON_LOKI_SERVICE: node0 @@ -58,6 +59,7 @@ services: CHARON_BEACON_NODE_ENDPOINT: CHARON_SIMNET_BEACON_MOCK: "true" CHARON_SIMNET_VALIDATOR_MOCK: "false" + CHARON_SIMNET_SLOT_DURATION: 1s CHARON_SIMNET_VALIDATOR_KEYS_DIR: /compose/node1/validator_keys CHARON_LOKI_ADDRESSES: http://loki:3100/loki/api/v1/push CHARON_LOKI_SERVICE: node1 @@ -90,6 +92,7 @@ services: CHARON_BEACON_NODE_ENDPOINT: CHARON_SIMNET_BEACON_MOCK: "true" CHARON_SIMNET_VALIDATOR_MOCK: "true" + CHARON_SIMNET_SLOT_DURATION: 1s CHARON_SIMNET_VALIDATOR_KEYS_DIR: /compose/node2/validator_keys CHARON_LOKI_ADDRESSES: http://loki:3100/loki/api/v1/push CHARON_LOKI_SERVICE: node2 @@ -122,6 +125,7 @@ services: CHARON_BEACON_NODE_ENDPOINT: CHARON_SIMNET_BEACON_MOCK: "true" CHARON_SIMNET_VALIDATOR_MOCK: "false" + CHARON_SIMNET_SLOT_DURATION: 1s CHARON_SIMNET_VALIDATOR_KEYS_DIR: /compose/node3/validator_keys CHARON_LOKI_ADDRESSES: http://loki:3100/loki/api/v1/push CHARON_LOKI_SERVICE: node3 diff --git a/testutil/compose/testdata/TestNewDefaultConfig.golden b/testutil/compose/testdata/TestNewDefaultConfig.golden index 272ba536e..a2bd0cd64 100644 --- a/testutil/compose/testdata/TestNewDefaultConfig.golden +++ b/testutil/compose/testdata/TestNewDefaultConfig.golden @@ -17,5 +17,7 @@ ], "feature_set": "alpha", "disable_monitoring_ports": false, - "insecure_keys": false + "insecure_keys": false, + "slot_duration": 1000000000, + "synthetic_block_proposals": true } \ No newline at end of file diff --git a/testutil/random.go b/testutil/random.go index cba3af22f..0263ac8ff 100644 --- a/testutil/random.go +++ b/testutil/random.go @@ -630,6 +630,13 @@ func RandomEth2Signature() eth2p0.BLSSignature { return resp } +func RandomEth2SignatureWithSeed(seed int64) eth2p0.BLSSignature { + var resp eth2p0.BLSSignature + _, _ = rand.New(rand.NewSource(seed)).Read(resp[:]) + + return resp +} + func RandomCoreSignature() core.Signature { resp := make(core.Signature, 96) _, _ = rand.Read(resp) diff --git a/testutil/validatormock/testdata/TestAttest_0_aggregations.golden b/testutil/validatormock/testdata/TestAttest_0_aggregations.golden index beb299da1..377787c3b 100644 --- a/testutil/validatormock/testdata/TestAttest_0_aggregations.golden +++ b/testutil/validatormock/testdata/TestAttest_0_aggregations.golden @@ -6,7 +6,7 @@ "aggregation_bits": "0x01", "data": { "slot": "16", - "index": "0", + "index": "1", "beacon_block_root": "0x1000000000000000000000000000000000000000000000000000000000000000", "source": { "epoch": "0", @@ -30,7 +30,7 @@ "aggregation_bits": "0x01", "data": { "slot": "16", - "index": "0", + "index": "2", "beacon_block_root": "0x1000000000000000000000000000000000000000000000000000000000000000", "source": { "epoch": "0", @@ -54,7 +54,7 @@ "aggregation_bits": "0x01", "data": { "slot": "16", - "index": "0", + "index": "3", "beacon_block_root": "0x1000000000000000000000000000000000000000000000000000000000000000", "source": { "epoch": "0", diff --git a/testutil/validatormock/testdata/TestAttest_0_attestations.golden b/testutil/validatormock/testdata/TestAttest_0_attestations.golden index ef0efa8e4..81a683400 100644 --- a/testutil/validatormock/testdata/TestAttest_0_attestations.golden +++ b/testutil/validatormock/testdata/TestAttest_0_attestations.golden @@ -3,7 +3,7 @@ "aggregation_bits": "0x03", "data": { "slot": "16", - "index": "0", + "index": "1", "beacon_block_root": "0x1000000000000000000000000000000000000000000000000000000000000000", "source": { "epoch": "0", @@ -20,7 +20,7 @@ "aggregation_bits": "0x03", "data": { "slot": "16", - "index": "0", + "index": "2", "beacon_block_root": "0x1000000000000000000000000000000000000000000000000000000000000000", "source": { "epoch": "0", @@ -37,7 +37,7 @@ "aggregation_bits": "0x03", "data": { "slot": "16", - "index": "0", + "index": "3", "beacon_block_root": "0x1000000000000000000000000000000000000000000000000000000000000000", "source": { "epoch": "0", diff --git a/testutil/validatormock/testdata/TestAttest_1_aggregations.golden b/testutil/validatormock/testdata/TestAttest_1_aggregations.golden index 9a2db7bb9..39f171c1a 100644 --- a/testutil/validatormock/testdata/TestAttest_1_aggregations.golden +++ b/testutil/validatormock/testdata/TestAttest_1_aggregations.golden @@ -6,7 +6,7 @@ "aggregation_bits": "0x01", "data": { "slot": "16", - "index": "0", + "index": "1", "beacon_block_root": "0x1000000000000000000000000000000000000000000000000000000000000000", "source": { "epoch": "0", diff --git a/testutil/validatormock/testdata/TestAttest_1_attestations.golden b/testutil/validatormock/testdata/TestAttest_1_attestations.golden index 5bb409080..581438fa4 100644 --- a/testutil/validatormock/testdata/TestAttest_1_attestations.golden +++ b/testutil/validatormock/testdata/TestAttest_1_attestations.golden @@ -3,7 +3,7 @@ "aggregation_bits": "0x03", "data": { "slot": "16", - "index": "0", + "index": "1", "beacon_block_root": "0x1000000000000000000000000000000000000000000000000000000000000000", "source": { "epoch": "0", diff --git a/testutil/validatormock/validatormock.go b/testutil/validatormock/validatormock.go index 6624efe17..08b4e544a 100644 --- a/testutil/validatormock/validatormock.go +++ b/testutil/validatormock/validatormock.go @@ -304,40 +304,35 @@ func Register(ctx context.Context, eth2Cl eth2wrap.Client, signFunc SignFunc, } // NewSigner returns a signing function supporting the provided private keys. -func NewSigner(secrets ...tblsv2.PrivateKey) SignFunc { - return func(pubkey eth2p0.BLSPubKey, msg []byte) (eth2p0.BLSSignature, error) { - secret, err := getSecret(secrets, pubkey) +func NewSigner(secrets ...tblsv2.PrivateKey) (SignFunc, error) { + secretByPubkey := make(map[eth2p0.BLSPubKey]tblsv2.PrivateKey) + for _, secret := range secrets { + pk, err := tblsv2.SecretToPublicKey(secret) if err != nil { - return eth2p0.BLSSignature{}, err + return nil, errors.Wrap(err, "get pubkey") } - sig, err := tblsv2.Sign(secret, msg) + eth2Pubkey, err := tblsconv2.PubkeyToETH2(pk) if err != nil { - return eth2p0.BLSSignature{}, err + return nil, err } - return tblsconv2.SigToETH2(sig), nil + secretByPubkey[eth2Pubkey] = secret } -} -func getSecret(secrets []tblsv2.PrivateKey, pubkey eth2p0.BLSPubKey) (tblsv2.PrivateKey, error) { - for _, secret := range secrets { - pk, err := tblsv2.SecretToPublicKey(secret) - if err != nil { - return tblsv2.PrivateKey{}, errors.Wrap(err, "get pubkey") + return func(pubkey eth2p0.BLSPubKey, msg []byte) (eth2p0.BLSSignature, error) { + secret, ok := secretByPubkey[pubkey] + if !ok { + return eth2p0.BLSSignature{}, errors.New("secret not found") } - eth2Pubkey, err := tblsconv2.PubkeyToETH2(pk) + sig, err := tblsv2.Sign(secret, msg) if err != nil { - return tblsv2.PrivateKey{}, err + return eth2p0.BLSSignature{}, err } - if eth2Pubkey == pubkey { - return secret, nil - } - } - - return tblsv2.PrivateKey{}, errors.New("private key not found") + return tblsconv2.SigToETH2(sig), nil + }, nil } // versionJSON extracts the version from a response. diff --git a/testutil/validatormock/validatormock_test.go b/testutil/validatormock/validatormock_test.go index 2b30e5802..740091098 100644 --- a/testutil/validatormock/validatormock_test.go +++ b/testutil/validatormock/validatormock_test.go @@ -20,6 +20,7 @@ import ( "fmt" "net/http" "net/http/httptest" + "sort" "testing" "time" @@ -102,6 +103,15 @@ func TestAttest(t *testing.T) { require.Len(t, atts, test.ExpectAttestations) require.Len(t, aggs, test.ExpectAggregations) + // Sort the outputs to make it deterministic to compare with json. + sort.Slice(atts, func(i, j int) bool { + return atts[i].Data.Index < atts[j].Data.Index + }) + + sort.Slice(aggs, func(i, j int) bool { + return aggs[i].Message.Aggregate.Data.Index < aggs[j].Message.Aggregate.Data.Index + }) + t.Run("attestations", func(t *testing.T) { testutil.RequireGoldenJSON(t, atts) })