diff --git a/config/features/flags.go b/config/features/flags.go index 119fcadc2..6e834803d 100644 --- a/config/features/flags.go +++ b/config/features/flags.go @@ -97,7 +97,7 @@ var ( } EnableMinimalSlashingProtection = &cli.BoolFlag{ Name: "enable-minimal-slashing-protection", - Usage: "Enables the minimal slashing protection. See EIP-3076 for more details.", + Usage: "(Experimental): Enables the minimal slashing protection. See EIP-3076 for more details.", } enableDoppelGangerProtection = &cli.BoolFlag{ Name: "enable-doppelganger", diff --git a/validator/db/convert.go b/validator/db/convert.go index 4b55db5f1..25126e9e9 100644 --- a/validator/db/convert.go +++ b/validator/db/convert.go @@ -124,13 +124,18 @@ func ConvertDatabase(ctx context.Context, sourceDataDir string, targetDataDir st // ----------------- // Get the proposer settings. proposerSettings, err := sourceDatabase.ProposerSettings(ctx) - if err != nil { - return errors.Wrap(err, "could not get proposer settings from source database") - } - // Save the proposer settings. - if err := targetDatabase.SaveProposerSettings(ctx, proposerSettings); err != nil { - return errors.Wrap(err, "could not save proposer settings") + switch err { + case nil: + // Save the proposer settings. + if err := targetDatabase.SaveProposerSettings(ctx, proposerSettings); err != nil { + return errors.Wrap(err, "could not save proposer settings") + } + + case kv.ErrNoProposerSettingsFound, filesystem.ErrNoProposerSettingsFound: + // Nothing to do. + default: + return errors.Wrap(err, "could not get proposer settings from source database") } // Attestations diff --git a/validator/db/convert_test.go b/validator/db/convert_test.go index f3e06f6dd..012491f18 100644 --- a/validator/db/convert_test.go +++ b/validator/db/convert_test.go @@ -49,217 +49,224 @@ func TestDB_ConvertDatabase(t *testing.T) { defaultFeeRecipient := getFeeRecipientFromString(t, defaultFeeRecipientString) customFeeRecipient := getFeeRecipientFromString(t, customFeeRecipientString) - for _, minimalToComplete := range []bool{false, true} { - t.Run(fmt.Sprintf("minimalToComplete=%v", minimalToComplete), func(t *testing.T) { - // Create signing root - signingRoot := [fieldparams.RootLength]byte{} - var signingRootBytes []byte - if minimalToComplete { - signingRootBytes = signingRoot[:] - } + for _, minimalToComplete := range [...]bool{false, true} { + for _, withProposerSettings := range [...]bool{false, true} { + t.Run(fmt.Sprintf("minimalToComplete=%v", minimalToComplete), func(t *testing.T) { + // Create signing root + signingRoot := [fieldparams.RootLength]byte{} + var signingRootBytes []byte + if minimalToComplete { + signingRootBytes = signingRoot[:] + } - // Create database directoriy path. - datadir := t.TempDir() + // Create database directoriy path. + datadir := t.TempDir() - // Run source DB preparation. - // -------------------------- - // Create the source database. - var ( - sourceDatabase, targetDatabase iface.ValidatorDB - err error - ) + // Run source DB preparation. + // -------------------------- + // Create the source database. + var ( + sourceDatabase, targetDatabase iface.ValidatorDB + err error + ) - if minimalToComplete { - sourceDatabase, err = filesystem.NewStore(datadir, &filesystem.Config{ - PubKeys: [][fieldparams.BLSPubkeyLength]byte{pubkey1, pubkey2}, - }) - } else { - sourceDatabase, err = kv.NewKVStore(ctx, datadir, &kv.Config{ - PubKeys: [][fieldparams.BLSPubkeyLength]byte{pubkey1, pubkey2}, - }) - } + if minimalToComplete { + sourceDatabase, err = filesystem.NewStore(datadir, &filesystem.Config{ + PubKeys: [][fieldparams.BLSPubkeyLength]byte{pubkey1, pubkey2}, + }) + } else { + sourceDatabase, err = kv.NewKVStore(ctx, datadir, &kv.Config{ + PubKeys: [][fieldparams.BLSPubkeyLength]byte{pubkey1, pubkey2}, + }) + } - require.NoError(t, err, "could not create source database") + require.NoError(t, err, "could not create source database") - // Save the genesis validator root. - expectedGenesisValidatorRoot := []byte("genesis-validator-root") - err = sourceDatabase.SaveGenesisValidatorsRoot(ctx, expectedGenesisValidatorRoot) - require.NoError(t, err, "could not save genesis validator root") + // Save the genesis validator root. + expectedGenesisValidatorRoot := []byte("genesis-validator-root") + err = sourceDatabase.SaveGenesisValidatorsRoot(ctx, expectedGenesisValidatorRoot) + require.NoError(t, err, "could not save genesis validator root") - // Save the graffiti file hash. - // (Getting the graffiti ordered index will set the graffiti file hash) - expectedGraffitiFileHash := [32]byte{1} - _, err = sourceDatabase.GraffitiOrderedIndex(ctx, expectedGraffitiFileHash) - require.NoError(t, err, "could not get graffiti ordered index") + // Save the graffiti file hash. + // (Getting the graffiti ordered index will set the graffiti file hash) + expectedGraffitiFileHash := [32]byte{1} + _, err = sourceDatabase.GraffitiOrderedIndex(ctx, expectedGraffitiFileHash) + require.NoError(t, err, "could not get graffiti ordered index") - // Save the graffiti ordered index. - expectedGraffitiOrderedIndex := uint64(1) - err = sourceDatabase.SaveGraffitiOrderedIndex(ctx, expectedGraffitiOrderedIndex) - require.NoError(t, err, "could not save graffiti ordered index") + // Save the graffiti ordered index. + expectedGraffitiOrderedIndex := uint64(1) + err = sourceDatabase.SaveGraffitiOrderedIndex(ctx, expectedGraffitiOrderedIndex) + require.NoError(t, err, "could not save graffiti ordered index") - // Save the proposer settings. - var relays []string = nil + // Save the proposer settings. + var relays []string = nil + expectedProposerSettings := &proposer.Settings{} - expectedProposerSettings := &proposer.Settings{ - ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option{ - pubkey1: { - FeeRecipientConfig: &proposer.FeeRecipientConfig{ - FeeRecipient: customFeeRecipient, + if withProposerSettings { + expectedProposerSettings = &proposer.Settings{ + ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*proposer.Option{ + pubkey1: { + FeeRecipientConfig: &proposer.FeeRecipientConfig{ + FeeRecipient: customFeeRecipient, + }, + BuilderConfig: &proposer.BuilderConfig{ + Enabled: true, + GasLimit: 42, + Relays: relays, + }, + }, }, - BuilderConfig: &proposer.BuilderConfig{ - Enabled: true, - GasLimit: 42, - Relays: relays, + DefaultConfig: &proposer.Option{ + FeeRecipientConfig: &proposer.FeeRecipientConfig{ + FeeRecipient: defaultFeeRecipient, + }, + BuilderConfig: &proposer.BuilderConfig{ + Enabled: false, + GasLimit: 43, + Relays: relays, + }, + }, + } + + err = sourceDatabase.SaveProposerSettings(ctx, expectedProposerSettings) + require.NoError(t, err, "could not save proposer settings") + } + + // Save some attestations. + completeAttestations := []*ethpb.IndexedAttestation{ + { + Data: ðpb.AttestationData{ + Source: ðpb.Checkpoint{ + Epoch: 1, + }, + Target: ðpb.Checkpoint{ + Epoch: 2, + }, }, }, - }, - DefaultConfig: &proposer.Option{ - FeeRecipientConfig: &proposer.FeeRecipientConfig{ - FeeRecipient: defaultFeeRecipient, - }, - BuilderConfig: &proposer.BuilderConfig{ - Enabled: false, - GasLimit: 43, - Relays: relays, - }, - }, - } - - err = sourceDatabase.SaveProposerSettings(ctx, expectedProposerSettings) - require.NoError(t, err, "could not save proposer settings") - - // Save some attestations. - completeAttestations := []*ethpb.IndexedAttestation{ - { - Data: ðpb.AttestationData{ - Source: ðpb.Checkpoint{ - Epoch: 1, - }, - Target: ðpb.Checkpoint{ - Epoch: 2, + { + Data: ðpb.AttestationData{ + Source: ðpb.Checkpoint{ + Epoch: 2, + }, + Target: ðpb.Checkpoint{ + Epoch: 3, + }, }, }, - }, - { - Data: ðpb.AttestationData{ - Source: ðpb.Checkpoint{ - Epoch: 2, - }, - Target: ðpb.Checkpoint{ - Epoch: 3, - }, + } + + expectedAttestationRecords1 := []*common.AttestationRecord{ + { + PubKey: pubkey1, + Source: primitives.Epoch(2), + Target: primitives.Epoch(3), + SigningRoot: signingRootBytes, }, - }, - } + } - expectedAttestationRecords1 := []*common.AttestationRecord{ - { - PubKey: pubkey1, - Source: primitives.Epoch(2), - Target: primitives.Epoch(3), - SigningRoot: signingRootBytes, - }, - } + expectedAttestationRecords2 := []*common.AttestationRecord{ + { + PubKey: pubkey2, + Source: primitives.Epoch(2), + Target: primitives.Epoch(3), + SigningRoot: signingRootBytes, + }, + } - expectedAttestationRecords2 := []*common.AttestationRecord{ - { - PubKey: pubkey2, - Source: primitives.Epoch(2), - Target: primitives.Epoch(3), - SigningRoot: signingRootBytes, - }, - } + err = sourceDatabase.SaveAttestationsForPubKey(ctx, pubkey1, [][]byte{{1}, {2}}, completeAttestations) + require.NoError(t, err, "could not save attestations") - err = sourceDatabase.SaveAttestationsForPubKey(ctx, pubkey1, [][]byte{{1}, {2}}, completeAttestations) - require.NoError(t, err, "could not save attestations") + err = sourceDatabase.SaveAttestationsForPubKey(ctx, pubkey2, [][]byte{{1}, {2}}, completeAttestations) + require.NoError(t, err, "could not save attestations") - err = sourceDatabase.SaveAttestationsForPubKey(ctx, pubkey2, [][]byte{{1}, {2}}, completeAttestations) - require.NoError(t, err, "could not save attestations") + // Save some block proposals. + err = sourceDatabase.SaveProposalHistoryForSlot(ctx, pubkey1, 42, []byte{}) + require.NoError(t, err, "could not save block proposal") - // Save some block proposals. - err = sourceDatabase.SaveProposalHistoryForSlot(ctx, pubkey1, 42, []byte{}) - require.NoError(t, err, "could not save block proposal") + err = sourceDatabase.SaveProposalHistoryForSlot(ctx, pubkey1, 43, []byte{}) + require.NoError(t, err, "could not save block proposal") - err = sourceDatabase.SaveProposalHistoryForSlot(ctx, pubkey1, 43, []byte{}) - require.NoError(t, err, "could not save block proposal") + expectedProposals := []*common.Proposal{ + { + Slot: 43, + SigningRoot: signingRootBytes, + }, + } - expectedProposals := []*common.Proposal{ - { - Slot: 43, - SigningRoot: signingRootBytes, - }, - } + // Close the source database. + err = sourceDatabase.Close() + require.NoError(t, err, "could not close source database") - // Close the source database. - err = sourceDatabase.Close() - require.NoError(t, err, "could not close source database") + // Source to target DB conversion. + // ------------------------------- + err = ConvertDatabase(ctx, datadir, datadir, minimalToComplete) + require.NoError(t, err, "could not convert source to target database") - // Source to target DB conversion. - // ---------------------------------------- - err = ConvertDatabase(ctx, datadir, datadir, minimalToComplete) - require.NoError(t, err, "could not convert source to target database") + // Check the target database. + // -------------------------- + if minimalToComplete { + targetDatabase, err = kv.NewKVStore(ctx, datadir, nil) + } else { + targetDatabase, err = filesystem.NewStore(datadir, nil) + } + require.NoError(t, err, "could not get minimal database") - // Check the target database. - // -------------------------- - if minimalToComplete { - targetDatabase, err = kv.NewKVStore(ctx, datadir, nil) - } else { - targetDatabase, err = filesystem.NewStore(datadir, nil) - } - require.NoError(t, err, "could not get minimal database") + // Check the genesis validator root. + actualGenesisValidatoRoot, err := targetDatabase.GenesisValidatorsRoot(ctx) + require.NoError(t, err, "could not get genesis validator root from target database") + require.DeepSSZEqual(t, expectedGenesisValidatorRoot, actualGenesisValidatoRoot, "genesis validator root should match") - // Check the genesis validator root. - actualGenesisValidatoRoot, err := targetDatabase.GenesisValidatorsRoot(ctx) - require.NoError(t, err, "could not get genesis validator root from target database") - require.DeepSSZEqual(t, expectedGenesisValidatorRoot, actualGenesisValidatoRoot, "genesis validator root should match") + // Check the graffiti file hash. + actualGraffitiFileHash, exists, err := targetDatabase.GraffitiFileHash() + require.NoError(t, err, "could not get graffiti file hash from target database") + require.Equal(t, true, exists, "graffiti file hash should exist") + require.Equal(t, expectedGraffitiFileHash, actualGraffitiFileHash, "graffiti file hash should match") - // Check the graffiti file hash. - actualGraffitiFileHash, exists, err := targetDatabase.GraffitiFileHash() - require.NoError(t, err, "could not get graffiti file hash from target database") - require.Equal(t, true, exists, "graffiti file hash should exist") - require.Equal(t, expectedGraffitiFileHash, actualGraffitiFileHash, "graffiti file hash should match") + // Check the graffiti ordered index. + actualGraffitiOrderedIndex, err := targetDatabase.GraffitiOrderedIndex(ctx, expectedGraffitiFileHash) + require.NoError(t, err, "could not get graffiti ordered index from target database") + require.Equal(t, expectedGraffitiOrderedIndex, actualGraffitiOrderedIndex, "graffiti ordered index should match") - // Check the graffiti ordered index. - actualGraffitiOrderedIndex, err := targetDatabase.GraffitiOrderedIndex(ctx, expectedGraffitiFileHash) - require.NoError(t, err, "could not get graffiti ordered index from target database") - require.Equal(t, expectedGraffitiOrderedIndex, actualGraffitiOrderedIndex, "graffiti ordered index should match") + if withProposerSettings { + // Check the proposer settings. + actualProposerSettings, err := targetDatabase.ProposerSettings(ctx) + require.NoError(t, err, "could not get proposer settings from target database") + require.DeepEqual(t, expectedProposerSettings, actualProposerSettings, "proposer settings should match") + } - // Check the proposer settings. - actualProposerSettings, err := targetDatabase.ProposerSettings(ctx) - require.NoError(t, err, "could not get proposer settings from target database") - require.DeepEqual(t, expectedProposerSettings, actualProposerSettings, "proposer settings should match") + // Check the attestations. + actualAttestationRecords, err := targetDatabase.AttestationHistoryForPubKey(ctx, pubkey1) + require.NoError(t, err, "could not get attestations from target database") + require.DeepEqual(t, expectedAttestationRecords1, actualAttestationRecords, "attestations should match") - // Check the attestations. - actualAttestationRecords, err := targetDatabase.AttestationHistoryForPubKey(ctx, pubkey1) - require.NoError(t, err, "could not get attestations from target database") - require.DeepEqual(t, expectedAttestationRecords1, actualAttestationRecords, "attestations should match") + actualAttestationRecords, err = targetDatabase.AttestationHistoryForPubKey(ctx, pubkey2) + require.NoError(t, err, "could not get attestations from target database") + require.DeepEqual(t, expectedAttestationRecords2, actualAttestationRecords, "attestations should match") - actualAttestationRecords, err = targetDatabase.AttestationHistoryForPubKey(ctx, pubkey2) - require.NoError(t, err, "could not get attestations from target database") - require.DeepEqual(t, expectedAttestationRecords2, actualAttestationRecords, "attestations should match") + // Check the block proposals. + actualProposals, err := targetDatabase.ProposalHistoryForPubKey(ctx, pubkey1) + require.NoError(t, err, "could not get block proposals from target database") + require.DeepEqual(t, expectedProposals, actualProposals, "block proposals should match") - // Check the block proposals. - actualProposals, err := targetDatabase.ProposalHistoryForPubKey(ctx, pubkey1) - require.NoError(t, err, "could not get block proposals from target database") - require.DeepEqual(t, expectedProposals, actualProposals, "block proposals should match") + // Close the target database. + err = targetDatabase.Close() + require.NoError(t, err, "could not close target database") - // Close the target database. - err = targetDatabase.Close() - require.NoError(t, err, "could not close target database") + // Check the source database does not exist anymore. + var existing bool - // Check the source database does not exist anymore. - var existing bool + if minimalToComplete { + databasePath := filepath.Join(datadir, filesystem.DatabaseDirName) + existing, err = file.Exists(databasePath, file.Directory) + } else { + databasePath := filepath.Join(datadir, kv.ProtectionDbFileName) + existing, err = file.Exists(databasePath, file.Regular) + } - if minimalToComplete { - databasePath := filepath.Join(datadir, filesystem.DatabaseDirName) - existing, err = file.Exists(databasePath, file.Directory) - } else { - databasePath := filepath.Join(datadir, kv.ProtectionDbFileName) - existing, err = file.Exists(databasePath, file.Regular) - } - - require.NoError(t, err, "could not check if source database exists") - require.Equal(t, false, existing, "source database should not exist") - }) + require.NoError(t, err, "could not check if source database exists") + require.Equal(t, false, existing, "source database should not exist") + }) + } } }