2023-01-26 22:50:44 +00:00
package transition
import (
"encoding/binary"
"fmt"
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/Giulio2002/bls"
"github.com/ledgerwatch/erigon/cl/cltypes"
"github.com/ledgerwatch/erigon/cl/utils"
2023-03-04 21:14:45 +00:00
"github.com/ledgerwatch/erigon/cmd/erigon-cl/core/state"
2023-01-26 22:50:44 +00:00
)
func computeSigningRootEpoch ( epoch uint64 , domain [ ] byte ) ( libcommon . Hash , error ) {
b := make ( [ ] byte , 32 )
binary . LittleEndian . PutUint64 ( b , epoch )
2023-02-05 20:53:59 +00:00
return utils . Keccak256 ( b , domain ) , nil
2023-01-26 22:50:44 +00:00
}
2023-03-04 21:14:45 +00:00
func ProcessBlockHeader ( state * state . BeaconState , block * cltypes . BeaconBlock , fullValidation bool ) error {
if fullValidation {
if block . Slot != state . Slot ( ) {
return fmt . Errorf ( "state slot: %d, not equal to block slot: %d" , state . Slot ( ) , block . Slot )
2023-02-07 16:44:37 +00:00
}
2023-03-04 21:14:45 +00:00
if block . Slot <= state . LatestBlockHeader ( ) . Slot {
return fmt . Errorf ( "slock slot: %d, not greater than latest block slot: %d" , block . Slot , state . LatestBlockHeader ( ) . Slot )
2023-02-07 16:44:37 +00:00
}
2023-03-04 21:14:45 +00:00
propInd , err := state . GetBeaconProposerIndex ( )
2023-02-07 16:44:37 +00:00
if err != nil {
return fmt . Errorf ( "error in GetBeaconProposerIndex: %v" , err )
}
if block . ProposerIndex != propInd {
return fmt . Errorf ( "block proposer index: %d, does not match beacon proposer index: %d" , block . ProposerIndex , propInd )
}
2023-03-26 22:25:08 +00:00
blockHeader := state . LatestBlockHeader ( )
latestRoot , err := ( & blockHeader ) . HashSSZ ( )
2023-02-07 16:44:37 +00:00
if err != nil {
return fmt . Errorf ( "unable to hash tree root of latest block header: %v" , err )
}
if block . ParentRoot != latestRoot {
return fmt . Errorf ( "block parent root: %x, does not match latest block root: %x" , block . ParentRoot , latestRoot )
}
2023-01-26 22:50:44 +00:00
}
2023-02-07 16:44:37 +00:00
2023-01-26 22:50:44 +00:00
bodyRoot , err := block . Body . HashSSZ ( )
if err != nil {
return fmt . Errorf ( "unable to hash tree root of block body: %v" , err )
}
2023-03-04 21:14:45 +00:00
state . SetLatestBlockHeader ( & cltypes . BeaconBlockHeader {
2023-01-26 22:50:44 +00:00
Slot : block . Slot ,
ProposerIndex : block . ProposerIndex ,
ParentRoot : block . ParentRoot ,
BodyRoot : bodyRoot ,
} )
2023-03-26 22:25:08 +00:00
proposer , err := state . ValidatorForValidatorIndex ( int ( block . ProposerIndex ) )
2023-02-02 11:16:28 +00:00
if err != nil {
return err
}
2023-01-26 22:50:44 +00:00
if proposer . Slashed {
return fmt . Errorf ( "proposer: %d is slashed" , block . ProposerIndex )
}
return nil
}
2023-05-04 13:18:42 +00:00
func ProcessRandao ( s * state . BeaconState , randao [ 96 ] byte , proposerIndex uint64 , fullValidation bool ) error {
epoch := state . Epoch ( s . BeaconState )
proposer , err := s . ValidatorForValidatorIndex ( int ( proposerIndex ) )
2023-02-02 11:16:28 +00:00
if err != nil {
return err
}
2023-03-04 21:14:45 +00:00
if fullValidation {
2023-05-04 13:18:42 +00:00
domain , err := s . GetDomain ( s . BeaconConfig ( ) . DomainRandao , epoch )
2023-02-05 20:53:59 +00:00
if err != nil {
return fmt . Errorf ( "ProcessRandao: unable to get domain: %v" , err )
}
signingRoot , err := computeSigningRootEpoch ( epoch , domain )
if err != nil {
return fmt . Errorf ( "ProcessRandao: unable to compute signing root: %v" , err )
}
valid , err := bls . Verify ( randao [ : ] , signingRoot [ : ] , proposer . PublicKey [ : ] )
if err != nil {
return fmt . Errorf ( "ProcessRandao: unable to verify public key: %x, with signing root: %x, and signature: %x, %v" , proposer . PublicKey [ : ] , signingRoot [ : ] , randao [ : ] , err )
}
if ! valid {
return fmt . Errorf ( "ProcessRandao: invalid signature: public key: %x, signing root: %x, signature: %x" , proposer . PublicKey [ : ] , signingRoot [ : ] , randao [ : ] )
}
2023-01-26 22:50:44 +00:00
}
2023-02-05 20:53:59 +00:00
2023-05-04 13:18:42 +00:00
randaoMixes := s . GetRandaoMixes ( epoch )
2023-01-26 22:50:44 +00:00
randaoHash := utils . Keccak256 ( randao [ : ] )
mix := [ 32 ] byte { }
for i := range mix {
mix [ i ] = randaoMixes [ i ] ^ randaoHash [ i ]
}
2023-05-04 13:18:42 +00:00
s . SetRandaoMixAt ( int ( epoch % s . BeaconConfig ( ) . EpochsPerHistoricalVector ) , mix )
2023-01-26 22:50:44 +00:00
return nil
}
2023-03-04 21:14:45 +00:00
func ProcessEth1Data ( state * state . BeaconState , eth1Data * cltypes . Eth1Data ) error {
state . AddEth1DataVote ( eth1Data )
newVotes := state . Eth1DataVotes ( )
2023-01-26 22:50:44 +00:00
2023-02-07 16:44:37 +00:00
// Count how many times body.Eth1Data appears in the votes.
2023-01-26 22:50:44 +00:00
numVotes := 0
for i := 0 ; i < len ( newVotes ) ; i ++ {
2023-02-07 16:44:37 +00:00
if eth1Data . Equal ( newVotes [ i ] ) {
2023-01-26 22:50:44 +00:00
numVotes += 1
}
}
2023-03-04 21:14:45 +00:00
if uint64 ( numVotes * 2 ) > state . BeaconConfig ( ) . EpochsPerEth1VotingPeriod * state . BeaconConfig ( ) . SlotsPerEpoch {
state . SetEth1Data ( eth1Data )
2023-01-26 22:50:44 +00:00
}
return nil
}