github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/core/blocks/randao.go (about)

     1  package blocks
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/pkg/errors"
     7  	"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
     8  	iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
     9  	"github.com/prysmaticlabs/prysm/proto/interfaces"
    10  	"github.com/prysmaticlabs/prysm/shared/hashutil"
    11  	"github.com/prysmaticlabs/prysm/shared/params"
    12  )
    13  
    14  // ProcessRandao checks the block proposer's
    15  // randao commitment and generates a new randao mix to update
    16  // in the beacon state's latest randao mixes slice.
    17  //
    18  // Spec pseudocode definition:
    19  //   def process_randao(state: BeaconState, body: BeaconBlockBody) -> None:
    20  //    epoch = get_current_epoch(state)
    21  //    # Verify RANDAO reveal
    22  //    proposer = state.validators[get_beacon_proposer_index(state)]
    23  //    signing_root = compute_signing_root(epoch, get_domain(state, DOMAIN_RANDAO))
    24  //    assert bls.Verify(proposer.pubkey, signing_root, body.randao_reveal)
    25  //    # Mix in RANDAO reveal
    26  //    mix = xor(get_randao_mix(state, epoch), hash(body.randao_reveal))
    27  //    state.randao_mixes[epoch % EPOCHS_PER_HISTORICAL_VECTOR] = mix
    28  func ProcessRandao(
    29  	_ context.Context,
    30  	beaconState iface.BeaconState,
    31  	b interfaces.SignedBeaconBlock,
    32  ) (iface.BeaconState, error) {
    33  	if err := helpers.VerifyNilBeaconBlock(b); err != nil {
    34  		return nil, err
    35  	}
    36  	body := b.Block().Body()
    37  	buf, proposerPub, domain, err := randaoSigningData(beaconState)
    38  	if err != nil {
    39  		return nil, err
    40  	}
    41  	if err := verifySignature(buf, proposerPub, body.RandaoReveal(), domain); err != nil {
    42  		return nil, errors.Wrap(err, "could not verify block randao")
    43  	}
    44  
    45  	beaconState, err = ProcessRandaoNoVerify(beaconState, body.RandaoReveal())
    46  	if err != nil {
    47  		return nil, errors.Wrap(err, "could not process randao")
    48  	}
    49  	return beaconState, nil
    50  }
    51  
    52  // ProcessRandaoNoVerify generates a new randao mix to update
    53  // in the beacon state's latest randao mixes slice.
    54  //
    55  // Spec pseudocode definition:
    56  //     # Mix it in
    57  //     state.latest_randao_mixes[get_current_epoch(state) % LATEST_RANDAO_MIXES_LENGTH] = (
    58  //         xor(get_randao_mix(state, get_current_epoch(state)),
    59  //             hash(body.randao_reveal))
    60  //     )
    61  func ProcessRandaoNoVerify(
    62  	beaconState iface.BeaconState,
    63  	randaoReveal []byte,
    64  ) (iface.BeaconState, error) {
    65  	currentEpoch := helpers.SlotToEpoch(beaconState.Slot())
    66  	// If block randao passed verification, we XOR the state's latest randao mix with the block's
    67  	// randao and update the state's corresponding latest randao mix value.
    68  	latestMixesLength := params.BeaconConfig().EpochsPerHistoricalVector
    69  	latestMixSlice, err := beaconState.RandaoMixAtIndex(uint64(currentEpoch % latestMixesLength))
    70  	if err != nil {
    71  		return nil, err
    72  	}
    73  	blockRandaoReveal := hashutil.Hash(randaoReveal)
    74  	if len(blockRandaoReveal) != len(latestMixSlice) {
    75  		return nil, errors.New("blockRandaoReveal length doesnt match latestMixSlice length")
    76  	}
    77  	for i, x := range blockRandaoReveal {
    78  		latestMixSlice[i] ^= x
    79  	}
    80  	if err := beaconState.UpdateRandaoMixesAtIndex(uint64(currentEpoch%latestMixesLength), latestMixSlice); err != nil {
    81  		return nil, err
    82  	}
    83  	return beaconState, nil
    84  }