Mike Neuder 2022-12-27 08:57:32 -05:00 committed by GitHub
parent 05f715ca51
commit f0be116bc2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 113 additions and 4 deletions

View File

@ -18,6 +18,7 @@ const (
EPOCHS_PER_HISTORICAL_VECTOR = uint64(1 << 16)
MIN_SEED_LOOKAHEAD = uint64(1)
SLOTS_PER_EPOCH = uint64(1 << 5)
EPOCHS_PER_ETH1_VOTING_PERIOD = uint64(1 << 6)
)
func ComputeShuffledIndex(ind, ind_count uint64, seed [32]byte) (uint64, error) {
@ -240,3 +241,35 @@ func ProcessRandao(state *state.BeaconState, body *cltypes.BeaconBody) error {
state.RandaoMixes()[epoch%EPOCHS_PER_HISTORICAL_VECTOR] = mix
return nil
}
func ProcessEth1Data(state *state.BeaconState, body *cltypes.BeaconBody) error {
newVotes := append(state.Eth1DataVotes(), body.Eth1Data)
state.SetEth1DataVotes(newVotes)
ethDataHash, err := body.Eth1Data.HashTreeRoot()
if err != nil {
return fmt.Errorf("unable to get hash tree root of eth1data: %v", err)
}
// Count how many times body.Eth1Data appears in the votes by comparing their hashes.
numVotes := 0
for i := 0; i < len(newVotes); i++ {
candidateHash, err := newVotes[i].HashTreeRoot()
if err != nil {
return fmt.Errorf("unable to get hash tree root of eth1data: %v", err)
}
// Check if hash bytes are equal.
match := true
for i := 0; i < len(candidateHash); i++ {
if candidateHash[i] != ethDataHash[i] {
match = false
}
}
if match {
numVotes += 1
}
}
if uint64(numVotes*2) > EPOCHS_PER_ETH1_VOTING_PERIOD*SLOTS_PER_EPOCH {
state.SetEth1Data(body.Eth1Data)
}
return nil
}

View File

@ -415,3 +415,79 @@ func TestProcessRandao(t *testing.T) {
})
}
}
func TestProcessEth1Data(t *testing.T) {
Eth1DataA := &cltypes.Eth1Data{
Root: [32]byte{1, 2, 3},
DepositCount: 42,
BlockHash: [32]byte{4, 5, 6},
}
eth1dataAHash, err := Eth1DataA.HashTreeRoot()
if err != nil {
t.Fatalf("unable to hash expected eth1data: %v", err)
}
Eth1DataB := &cltypes.Eth1Data{
Root: [32]byte{3, 2, 1},
DepositCount: 43,
BlockHash: [32]byte{6, 5, 4},
}
eth1dataBHash, err := Eth1DataB.HashTreeRoot()
if err != nil {
t.Fatalf("unable to hash expected eth1data: %v", err)
}
successState := state.FromBellatrixState(&cltypes.BeaconStateBellatrix{
Eth1DataVotes: []*cltypes.Eth1Data{},
Eth1Data: Eth1DataB,
})
// Fill all votes.
for i := 0; i < int(EPOCHS_PER_ETH1_VOTING_PERIOD)*int(SLOTS_PER_EPOCH)-1; i++ {
successState.SetEth1DataVotes(append(successState.Eth1DataVotes(), Eth1DataA))
}
successBody := &cltypes.BeaconBody{
Eth1Data: Eth1DataA,
}
noUpdateState := state.FromBellatrixState(&cltypes.BeaconStateBellatrix{
Eth1DataVotes: []*cltypes.Eth1Data{},
Eth1Data: Eth1DataB,
})
testCases := []struct {
description string
state *state.BeaconState
body *cltypes.BeaconBody
expectedHash [32]byte
}{
{
description: "success_update",
state: successState,
body: successBody,
expectedHash: eth1dataAHash,
},
{
description: "success_no_update",
state: noUpdateState,
body: successBody,
expectedHash: eth1dataBHash,
},
}
for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
err := ProcessEth1Data(tc.state, tc.body)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
gotEth1Data := tc.state.Eth1Data()
gotHash, err := gotEth1Data.HashTreeRoot()
if err != nil {
t.Fatalf("unable to hash output eth1data: %v", err)
}
for i := 0; i < len(tc.expectedHash); i++ {
if gotHash[i] != tc.expectedHash[i] {
t.Errorf("unexpected output byte: got %x, want %x", gotHash[i], tc.expectedHash[i])
}
}
})
}
}