-
Notifications
You must be signed in to change notification settings - Fork 1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
eip-7251: process_registry_updates (#14005)
* eip-7251: registry_updates * Fix spectest violation * More unit tests for process_registry_updates * Update tests for ProcessRegistryUpdates * Minor refactorings and benchmark * Update beacon-chain/core/electra/registry_updates.go Co-authored-by: Sammy Rosso <15244892+saolyn@users.noreply.github.com> * Wrap errors from process_registry_updates for easier debugging * Rewrite process_registry_updates not to use st.Validators() --------- Co-authored-by: Sammy Rosso <15244892+saolyn@users.noreply.github.com>
- Loading branch information
1 parent
78cf75a
commit 5584249
Showing
10 changed files
with
280 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
package electra_test | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
|
||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/electra" | ||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" | ||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state" | ||
state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" | ||
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" | ||
"github.com/prysmaticlabs/prysm/v5/config/params" | ||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" | ||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" | ||
"github.com/prysmaticlabs/prysm/v5/testing/require" | ||
"github.com/prysmaticlabs/prysm/v5/testing/util" | ||
) | ||
|
||
func TestProcessRegistryUpdates(t *testing.T) { | ||
finalizedEpoch := primitives.Epoch(4) | ||
|
||
tests := []struct { | ||
name string | ||
state state.BeaconState | ||
check func(*testing.T, state.BeaconState) | ||
}{ | ||
{ | ||
name: "No rotation", | ||
state: func() state.BeaconState { | ||
base := ð.BeaconStateElectra{ | ||
Slot: 5 * params.BeaconConfig().SlotsPerEpoch, | ||
Validators: []*eth.Validator{ | ||
{ExitEpoch: params.BeaconConfig().MaxSeedLookahead}, | ||
{ExitEpoch: params.BeaconConfig().MaxSeedLookahead}, | ||
}, | ||
Balances: []uint64{ | ||
params.BeaconConfig().MaxEffectiveBalance, | ||
params.BeaconConfig().MaxEffectiveBalance, | ||
}, | ||
FinalizedCheckpoint: ð.Checkpoint{Root: make([]byte, fieldparams.RootLength)}, | ||
} | ||
st, err := state_native.InitializeFromProtoElectra(base) | ||
require.NoError(t, err) | ||
return st | ||
}(), | ||
check: func(t *testing.T, st state.BeaconState) { | ||
for i, val := range st.Validators() { | ||
require.Equal(t, params.BeaconConfig().MaxSeedLookahead, val.ExitEpoch, "validator updated unexpectedly at index %d", i) | ||
} | ||
}, | ||
}, | ||
{ | ||
name: "Validators are activated", | ||
state: func() state.BeaconState { | ||
base := ð.BeaconStateElectra{ | ||
Slot: 5 * params.BeaconConfig().SlotsPerEpoch, | ||
FinalizedCheckpoint: ð.Checkpoint{Epoch: finalizedEpoch, Root: make([]byte, fieldparams.RootLength)}, | ||
} | ||
for i := uint64(0); i < 10; i++ { | ||
base.Validators = append(base.Validators, ð.Validator{ | ||
ActivationEligibilityEpoch: finalizedEpoch, | ||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, | ||
ActivationEpoch: params.BeaconConfig().FarFutureEpoch, | ||
}) | ||
} | ||
st, err := state_native.InitializeFromProtoElectra(base) | ||
require.NoError(t, err) | ||
return st | ||
}(), | ||
check: func(t *testing.T, st state.BeaconState) { | ||
activationEpoch := helpers.ActivationExitEpoch(5) | ||
// All validators should be activated. | ||
for i, val := range st.Validators() { | ||
require.Equal(t, activationEpoch, val.ActivationEpoch, "failed to update validator at index %d", i) | ||
} | ||
}, | ||
}, | ||
{ | ||
name: "Validators are exited", | ||
state: func() state.BeaconState { | ||
base := ð.BeaconStateElectra{ | ||
Slot: 5 * params.BeaconConfig().SlotsPerEpoch, | ||
FinalizedCheckpoint: ð.Checkpoint{Epoch: finalizedEpoch, Root: make([]byte, fieldparams.RootLength)}, | ||
} | ||
for i := uint64(0); i < 10; i++ { | ||
base.Validators = append(base.Validators, ð.Validator{ | ||
EffectiveBalance: params.BeaconConfig().EjectionBalance - 1, | ||
ExitEpoch: params.BeaconConfig().FarFutureEpoch, | ||
WithdrawableEpoch: params.BeaconConfig().FarFutureEpoch, | ||
}) | ||
} | ||
st, err := state_native.InitializeFromProtoElectra(base) | ||
require.NoError(t, err) | ||
return st | ||
}(), | ||
check: func(t *testing.T, st state.BeaconState) { | ||
// All validators should be exited | ||
for i, val := range st.Validators() { | ||
require.NotEqual(t, params.BeaconConfig().FarFutureEpoch, val.ExitEpoch, "failed to update exit epoch on validator %d", i) | ||
require.NotEqual(t, params.BeaconConfig().FarFutureEpoch, val.WithdrawableEpoch, "failed to update withdrawable epoch on validator %d", i) | ||
} | ||
}, | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
err := electra.ProcessRegistryUpdates(context.TODO(), tt.state) | ||
require.NoError(t, err) | ||
if tt.check != nil { | ||
tt.check(t, tt.state) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func Benchmark_ProcessRegistryUpdates_MassEjection(b *testing.B) { | ||
bal := params.BeaconConfig().EjectionBalance - 1 | ||
ffe := params.BeaconConfig().FarFutureEpoch | ||
genValidators := func(num uint64) []*eth.Validator { | ||
vals := make([]*eth.Validator, num) | ||
for i := range vals { | ||
vals[i] = ð.Validator{ | ||
EffectiveBalance: bal, | ||
ExitEpoch: ffe, | ||
} | ||
} | ||
return vals | ||
} | ||
|
||
st, err := util.NewBeaconStateElectra() | ||
require.NoError(b, err) | ||
|
||
for i := 0; i < b.N; i++ { | ||
b.StopTimer() | ||
if err := st.SetValidators(genValidators(100000)); err != nil { | ||
panic(err) | ||
} | ||
b.StartTimer() | ||
|
||
if err := electra.ProcessRegistryUpdates(context.TODO(), st); err != nil { | ||
panic(err) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
11 changes: 11 additions & 0 deletions
11
testing/spectest/mainnet/electra/epoch_processing/registry_updates_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package epoch_processing | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/electra/epoch_processing" | ||
) | ||
|
||
func TestMainnet_Electra_EpochProcessing_RegistryUpdates(t *testing.T) { | ||
epoch_processing.RunRegistryUpdatesTests(t, "mainnet") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
11 changes: 11 additions & 0 deletions
11
testing/spectest/minimal/electra/epoch_processing/registry_updates_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package epoch_processing | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/electra/epoch_processing" | ||
) | ||
|
||
func TestMinimal_Electra_EpochProcessing_RegistryUpdates(t *testing.T) { | ||
epoch_processing.RunRegistryUpdatesTests(t, "minimal") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
32 changes: 32 additions & 0 deletions
32
testing/spectest/shared/electra/epoch_processing/registry_updates.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package epoch_processing | ||
|
||
import ( | ||
"context" | ||
"path" | ||
"testing" | ||
|
||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/electra" | ||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" | ||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state" | ||
"github.com/prysmaticlabs/prysm/v5/testing/require" | ||
"github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" | ||
) | ||
|
||
// RunRegistryUpdatesTests executes "epoch_processing/registry_updates" tests. | ||
func RunRegistryUpdatesTests(t *testing.T, config string) { | ||
require.NoError(t, utils.SetConfig(t, config)) | ||
|
||
testFolders, testsFolderPath := utils.TestFolders(t, config, "electra", "epoch_processing/registry_updates/pyspec_tests") | ||
for _, folder := range testFolders { | ||
t.Run(folder.Name(), func(t *testing.T) { | ||
// Important to clear cache for every test or else the old value of active validator count gets reused. | ||
helpers.ClearCache() | ||
folderPath := path.Join(testsFolderPath, folder.Name()) | ||
RunEpochOperationTest(t, folderPath, processRegistryUpdatesWrapper) | ||
}) | ||
} | ||
} | ||
|
||
func processRegistryUpdatesWrapper(_ *testing.T, state state.BeaconState) (state.BeaconState, error) { | ||
return state, electra.ProcessRegistryUpdates(context.Background(), state) | ||
} |