Advance Beacon State Transition Part 6: Simulate Validator Exits (#1302)

* deposit definition according to latest spec

* ssz decode input data tests

* fix todo

* ignore XXX fields in struct

* fix

* timestamp

* gazelle run processing

* process deposit complete

* all logic complete

* verify merkle branch

* gazelle

* process deposit func

* diff cov 1005

* add todo"

* all test cases written down

* most tests complete

* ttl timestamp fail

* 100% code coverage in deposits

* fix params

* encode deposit data helper func

* state transition with no slots failing with panic at calcnewblockhashes

* smaller deposits for chain start

* state advancement benches

* ran go tests

* bazel

* improve the thing

* lint

* works works works

* all conflicts fixed

* edit readme to specify tests format

* edit readme to specify tests format

* skip slots works yay

* gazelle

* edit readme to specify tests format

* wrapped up all randao simulation

* fix

* passing

* goimports

* move to slices pkg

* deadcode

* deposit yaml tests

* created deposit trie implementation in Go

* created deposit trie implementation in Go

* gazelle

* merkle branch generation

* merkle branch generation

* more merkle debugging

* fix deposit trie

* include new merkle trie functions

* update all deposit operations

* capitalize

* advancing deposits fully works, grows the validator set

* wrap up time formatting

* lint fix

* include all information in the README

* edit conf

* revert

* clean up before merge

* successfully e2e test proposer slashings

* casper advancement

* wrap up casper slashings

* gazelle

* fix conf

* fix comments

* advance validator exits complete

* wrap up readme
This commit is contained in:
Raul Jordan 2019-01-15 01:02:49 +08:00 committed by GitHub
parent 592c5c3d92
commit d47db5e834
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 42 additions and 1 deletions

View File

@ -112,6 +112,7 @@ The following configuration options are available for state transition tests:
- **deposits**: `[Deposit Config]` trigger a new validator deposit into the beacon state based on configuration options - **deposits**: `[Deposit Config]` trigger a new validator deposit into the beacon state based on configuration options
- **proposer_slashings**: `[Proposer Slashing Config]` trigger a proposer slashing at a certain slot for a certain proposer index - **proposer_slashings**: `[Proposer Slashing Config]` trigger a proposer slashing at a certain slot for a certain proposer index
- **casper_slashings**: `[Casper Slashing Config]` trigger a casper slashing at a certain slot - **casper_slashings**: `[Casper Slashing Config]` trigger a casper slashing at a certain slot
- **validator_exits**: `[Validator Exit Config]` trigger a voluntary validator exit at a certain slot for a validator index
**Deposit Config** **Deposit Config**
- **slot**: `int` a slot in which to trigger a deposit during a state transition test - **slot**: `int` a slot in which to trigger a deposit during a state transition test
@ -140,12 +141,17 @@ The following configuration options are available for state transition tests:
- **votes_2_custody_0_indices**: `[int]` the custody indices 0 for votes2 - **votes_2_custody_0_indices**: `[int]` the custody indices 0 for votes2
- **votes_2_custody_1_indices**: `[int]` the custody indices 1 for votes2 - **votes_2_custody_1_indices**: `[int]` the custody indices 1 for votes2
**Validator Exit Config**
- **slot**: `int` the slot at which a validator wants to voluntarily exit the validator registry
- **validator_index**: `int` the index of the validator in the registry that is exiting
#### Test Results #### Test Results
The following are **mandatory** fields as they correspond to checks done at the end of the test run. The following are **mandatory** fields as they correspond to checks done at the end of the test run.
- **slot**: `int` check the slot of the state resulting from applying N state transitions in the test - **slot**: `int` check the slot of the state resulting from applying N state transitions in the test
- **num_validators** `[int]` check the number of validators in the validator registry after applying N state transitions - **num_validators** `[int]` check the number of validators in the validator registry after applying N state transitions
- **penalized_validators** `[int]` the list of validator indices we verify were penalized during the test - **penalized_validators** `[int]` the list of validator indices we verify were penalized during the test
- **exited_validators**: `[int]` the list of validator indices we verify voluntarily exited the registry during the test
## Stateless Tests ## Stateless Tests

View File

@ -26,6 +26,7 @@ func generateSimulatedBlock(
depositsTrie *trie.DepositTrie, depositsTrie *trie.DepositTrie,
simulatedProposerSlashing *StateTestProposerSlashing, simulatedProposerSlashing *StateTestProposerSlashing,
simulatedCasperSlashing *StateTestCasperSlashing, simulatedCasperSlashing *StateTestCasperSlashing,
simulatedExit *StateTestValidatorExit,
) (*pb.BeaconBlock, [32]byte, error) { ) (*pb.BeaconBlock, [32]byte, error) {
encodedState, err := proto.Marshal(beaconState) encodedState, err := proto.Marshal(beaconState)
if err != nil { if err != nil {
@ -105,6 +106,12 @@ func generateSimulatedBlock(
}, },
}) })
} }
if simulatedExit != nil {
block.Body.Exits = append(block.Body.Exits, &pb.Exit{
Slot: simulatedExit.Slot,
ValidatorIndex: simulatedExit.ValidatorIndex,
})
}
encodedBlock, err := proto.Marshal(block) encodedBlock, err := proto.Marshal(block)
if err != nil { if err != nil {
return nil, [32]byte{}, fmt.Errorf("could not marshal new block: %v", err) return nil, [32]byte{}, fmt.Errorf("could not marshal new block: %v", err)

View File

@ -200,6 +200,13 @@ func (sb *SimulatedBackend) RunStateTransitionTest(testCase *StateTestCase) erro
break break
} }
} }
var simulatedValidatorExit *StateTestValidatorExit
for _, exit := range testCase.Config.ValidatorExits {
if exit.Slot == i {
simulatedValidatorExit = exit
break
}
}
layersPeeled := layersPeeledForProposer[proposerIndex] layersPeeled := layersPeeledForProposer[proposerIndex]
blockRandaoReveal := determineSimulatedBlockRandaoReveal(layersPeeled, hashOnions) blockRandaoReveal := determineSimulatedBlockRandaoReveal(layersPeeled, hashOnions)
@ -214,6 +221,7 @@ func (sb *SimulatedBackend) RunStateTransitionTest(testCase *StateTestCase) erro
depositsTrie, depositsTrie,
simulatedProposerSlashing, simulatedProposerSlashing,
simulatedCasperSlashing, simulatedCasperSlashing,
simulatedValidatorExit,
) )
if err != nil { if err != nil {
return fmt.Errorf("could not generate simulated beacon block %v", err) return fmt.Errorf("could not generate simulated beacon block %v", err)
@ -266,6 +274,14 @@ func (sb *SimulatedBackend) RunStateTransitionTest(testCase *StateTestCase) erro
) )
} }
} }
for _, exited := range testCase.Results.ExitedValidators {
if beaconState.ValidatorRegistry[exited].StatusFlags != pb.ValidatorRecord_INITIATED_EXIT {
return fmt.Errorf(
"expected validator at index %d to have exited",
exited,
)
}
}
return nil return nil
} }

View File

@ -23,6 +23,7 @@ type StateTestConfig struct {
Deposits []*StateTestDeposit `yaml:"deposits"` Deposits []*StateTestDeposit `yaml:"deposits"`
ProposerSlashings []*StateTestProposerSlashing `yaml:"proposer_slashings"` ProposerSlashings []*StateTestProposerSlashing `yaml:"proposer_slashings"`
CasperSlashings []*StateTestCasperSlashing `yaml:"casper_slashings"` CasperSlashings []*StateTestCasperSlashing `yaml:"casper_slashings"`
ValidatorExits []*StateTestValidatorExit `yaml:"validator_exits"`
EpochLength uint64 `yaml:"epoch_length"` EpochLength uint64 `yaml:"epoch_length"`
ShardCount uint64 `yaml:"shard_count"` ShardCount uint64 `yaml:"shard_count"`
DepositsForChainStart uint64 `yaml:"deposits_for_chain_start"` DepositsForChainStart uint64 `yaml:"deposits_for_chain_start"`
@ -62,9 +63,16 @@ type StateTestCasperSlashing struct {
Votes2CustodyBit1Indices []uint32 `yaml:"votes_2_custody_1_indices"` Votes2CustodyBit1Indices []uint32 `yaml:"votes_2_custody_1_indices"`
} }
// StateTestValidatorExit --
type StateTestValidatorExit struct {
Slot uint64 `yaml:"slot"`
ValidatorIndex uint32 `yaml:"validator_index"`
}
// StateTestResults -- // StateTestResults --
type StateTestResults struct { type StateTestResults struct {
Slot uint64 Slot uint64
NumValidators int `yaml:"num_validators"` NumValidators int `yaml:"num_validators"`
PenalizedValidators []uint32 `yaml:"penalized_validators"` PenalizedValidators []uint32 `yaml:"penalized_validators"`
ExitedValidators []uint32 `yaml:"exited_validators"`
} }

View File

@ -52,10 +52,14 @@ test_cases:
votes_1_custody_1_indices: [] votes_1_custody_1_indices: []
votes_2_custody_0_indices: [] votes_2_custody_0_indices: []
votes_2_custody_1_indices: [16386] votes_2_custody_1_indices: [16386]
validator_exits:
- slot: 60
validator_index: 100 # At slot 60, validator at index 100 triggers a voluntary exit
results: results:
slot: 64 slot: 64
num_validators: 16387 num_validators: 16387
penalized_validators: [16385, 16386] # We test that the validators at indices 16385, 16386 were indeed penalized penalized_validators: [16385, 16386] # We test that the validators at indices 16385, 16386 were indeed penalized
exited_validators: [100] # We confirm the indices of validators that willingly exited the registry
- config: - config:
skip_slots: [10, 20] skip_slots: [10, 20]
epoch_length: 64 epoch_length: 64

View File

@ -658,7 +658,7 @@ func TestValidatorAssignments(t *testing.T) {
} }
func TestAssignmentsForPublicKeys_emptyPubKey(t *testing.T) { func TestAssignmentsForPublicKeys_emptyPubKey(t *testing.T) {
pks := []*pb.PublicKey{&pb.PublicKey{}} pks := []*pb.PublicKey{{}}
a, err := assignmentsForPublicKeys(pks, nil) a, err := assignmentsForPublicKeys(pks, nil)
if err != nil { if err != nil {