Fix VC DB conversion when no proposer settings is defined and add Experimental flag in the --enable-minimal-slashing-protection help. (#13691)

* VC: Allow DB conversion without proposer settings.

* `enable-minimal-slashing-protection` flag: Add `Experimental warning`.
This commit is contained in:
Manu NALEPA 2024-03-06 15:48:18 +01:00 committed by GitHub
parent ee9274a9bc
commit 21775eed52
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 196 additions and 184 deletions

View File

@ -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",

View File

@ -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

View File

@ -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: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{
Epoch: 1,
},
Target: &ethpb.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: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{
Epoch: 1,
},
Target: &ethpb.Checkpoint{
Epoch: 2,
{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{
Epoch: 2,
},
Target: &ethpb.Checkpoint{
Epoch: 3,
},
},
},
},
{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{
Epoch: 2,
},
Target: &ethpb.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")
})
}
}
}