mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-25 13:07:17 +00:00
Implement ProcessEth1Data (#6445)
Spec: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#eth1-data Part of https://github.com/ledgerwatch/erigon/issues/5965
This commit is contained in:
parent
05f715ca51
commit
f0be116bc2
@ -14,10 +14,11 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
SHUFFLE_ROUND_COUNT = uint8(90)
|
||||
EPOCHS_PER_HISTORICAL_VECTOR = uint64(1 << 16)
|
||||
MIN_SEED_LOOKAHEAD = uint64(1)
|
||||
SLOTS_PER_EPOCH = uint64(1 << 5)
|
||||
SHUFFLE_ROUND_COUNT = uint8(90)
|
||||
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
|
||||
}
|
||||
|
@ -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])
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user