github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/core/blocks/eth1_data.go (about) 1 package blocks 2 3 import ( 4 "bytes" 5 "context" 6 "errors" 7 8 iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface" 9 ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" 10 "github.com/prysmaticlabs/prysm/shared/copyutil" 11 "github.com/prysmaticlabs/prysm/shared/params" 12 ) 13 14 // ProcessEth1DataInBlock is an operation performed on each 15 // beacon block to ensure the ETH1 data votes are processed 16 // into the beacon state. 17 // 18 // Official spec definition: 19 // def process_eth1_data(state: BeaconState, body: BeaconBlockBody) -> None: 20 // state.eth1_data_votes.append(body.eth1_data) 21 // if state.eth1_data_votes.count(body.eth1_data) * 2 > EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH: 22 // state.eth1_data = body.eth1_data 23 func ProcessEth1DataInBlock(_ context.Context, beaconState iface.BeaconState, eth1Data *ethpb.Eth1Data) (iface.BeaconState, error) { 24 if beaconState == nil || beaconState.IsNil() { 25 return nil, errors.New("nil state") 26 } 27 if err := beaconState.AppendEth1DataVotes(eth1Data); err != nil { 28 return nil, err 29 } 30 hasSupport, err := Eth1DataHasEnoughSupport(beaconState, eth1Data) 31 if err != nil { 32 return nil, err 33 } 34 if hasSupport { 35 if err := beaconState.SetEth1Data(eth1Data); err != nil { 36 return nil, err 37 } 38 } 39 return beaconState, nil 40 } 41 42 // AreEth1DataEqual checks equality between two eth1 data objects. 43 func AreEth1DataEqual(a, b *ethpb.Eth1Data) bool { 44 if a == nil && b == nil { 45 return true 46 } 47 if a == nil || b == nil { 48 return false 49 } 50 return a.DepositCount == b.DepositCount && 51 bytes.Equal(a.BlockHash, b.BlockHash) && 52 bytes.Equal(a.DepositRoot, b.DepositRoot) 53 } 54 55 // Eth1DataHasEnoughSupport returns true when the given eth1data has more than 50% votes in the 56 // eth1 voting period. A vote is cast by including eth1data in a block and part of state processing 57 // appends eth1data to the state in the Eth1DataVotes list. Iterating through this list checks the 58 // votes to see if they match the eth1data. 59 func Eth1DataHasEnoughSupport(beaconState iface.ReadOnlyBeaconState, data *ethpb.Eth1Data) (bool, error) { 60 voteCount := uint64(0) 61 data = copyutil.CopyETH1Data(data) 62 63 for _, vote := range beaconState.Eth1DataVotes() { 64 if AreEth1DataEqual(vote, data) { 65 voteCount++ 66 } 67 } 68 69 // If 50+% majority converged on the same eth1data, then it has enough support to update the 70 // state. 71 support := params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().EpochsPerEth1VotingPeriod)) 72 return voteCount*2 > uint64(support), nil 73 }