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

     1  // Package state implements the whole state transition
     2  // function which consists of per slot, per-epoch transitions, and
     3  // bootstrapping the genesis state according to the Ethereum Beacon chain spec.
     4  package state
     5  
     6  import (
     7  	"context"
     8  
     9  	"github.com/pkg/errors"
    10  	b "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
    11  	"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
    12  	iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
    13  	"github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
    14  	pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
    15  	ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
    16  	"github.com/prysmaticlabs/prysm/shared/params"
    17  )
    18  
    19  // GenesisBeaconState gets called when MinGenesisActiveValidatorCount count of
    20  // full deposits were made to the deposit contract and the ChainStart log gets emitted.
    21  //
    22  // Spec pseudocode definition:
    23  //  def initialize_beacon_state_from_eth1(eth1_block_hash: Bytes32,
    24  //                                      eth1_timestamp: uint64,
    25  //                                      deposits: Sequence[Deposit]) -> BeaconState:
    26  //    fork = Fork(
    27  //        previous_version=GENESIS_FORK_VERSION,
    28  //        current_version=GENESIS_FORK_VERSION,
    29  //        epoch=GENESIS_EPOCH,
    30  //    )
    31  //    state = BeaconState(
    32  //        genesis_time=eth1_timestamp + GENESIS_DELAY,
    33  //        fork=fork,
    34  //        eth1_data=Eth1Data(block_hash=eth1_block_hash, deposit_count=uint64(len(deposits))),
    35  //        latest_block_header=BeaconBlockHeader(body_root=hash_tree_root(BeaconBlockBody())),
    36  //        randao_mixes=[eth1_block_hash] * EPOCHS_PER_HISTORICAL_VECTOR,  # Seed RANDAO with Eth1 entropy
    37  //    )
    38  //
    39  //    # Process deposits
    40  //    leaves = list(map(lambda deposit: deposit.data, deposits))
    41  //    for index, deposit in enumerate(deposits):
    42  //        deposit_data_list = List[DepositData, 2**DEPOSIT_CONTRACT_TREE_DEPTH](*leaves[:index + 1])
    43  //        state.eth1_data.deposit_root = hash_tree_root(deposit_data_list)
    44  //        process_deposit(state, deposit)
    45  //
    46  //    # Process activations
    47  //    for index, validator in enumerate(state.validators):
    48  //        balance = state.balances[index]
    49  //        validator.effective_balance = min(balance - balance % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE)
    50  //        if validator.effective_balance == MAX_EFFECTIVE_BALANCE:
    51  //            validator.activation_eligibility_epoch = GENESIS_EPOCH
    52  //            validator.activation_epoch = GENESIS_EPOCH
    53  //
    54  //    # Set genesis validators root for domain separation and chain versioning
    55  //    state.genesis_validators_root = hash_tree_root(state.validators)
    56  //
    57  //    return state
    58  // This method differs from the spec so as to process deposits beforehand instead of the end of the function.
    59  func GenesisBeaconState(ctx context.Context, deposits []*ethpb.Deposit, genesisTime uint64, eth1Data *ethpb.Eth1Data) (iface.BeaconState, error) {
    60  	state, err := EmptyGenesisState()
    61  	if err != nil {
    62  		return nil, err
    63  	}
    64  
    65  	// Process initial deposits.
    66  	state, err = helpers.UpdateGenesisEth1Data(state, deposits, eth1Data)
    67  	if err != nil {
    68  		return nil, err
    69  	}
    70  
    71  	state, err = b.ProcessPreGenesisDeposits(ctx, state, deposits)
    72  	if err != nil {
    73  		return nil, errors.Wrap(err, "could not process validator deposits")
    74  	}
    75  
    76  	return OptimizedGenesisBeaconState(genesisTime, state, state.Eth1Data())
    77  }
    78  
    79  // OptimizedGenesisBeaconState is used to create a state that has already processed deposits. This is to efficiently
    80  // create a mainnet state at chainstart.
    81  func OptimizedGenesisBeaconState(genesisTime uint64, preState iface.BeaconState, eth1Data *ethpb.Eth1Data) (iface.BeaconState, error) {
    82  	if eth1Data == nil {
    83  		return nil, errors.New("no eth1data provided for genesis state")
    84  	}
    85  
    86  	randaoMixes := make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector)
    87  	for i := 0; i < len(randaoMixes); i++ {
    88  		h := make([]byte, 32)
    89  		copy(h, eth1Data.BlockHash)
    90  		randaoMixes[i] = h
    91  	}
    92  
    93  	zeroHash := params.BeaconConfig().ZeroHash[:]
    94  
    95  	activeIndexRoots := make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector)
    96  	for i := 0; i < len(activeIndexRoots); i++ {
    97  		activeIndexRoots[i] = zeroHash
    98  	}
    99  
   100  	blockRoots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot)
   101  	for i := 0; i < len(blockRoots); i++ {
   102  		blockRoots[i] = zeroHash
   103  	}
   104  
   105  	stateRoots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot)
   106  	for i := 0; i < len(stateRoots); i++ {
   107  		stateRoots[i] = zeroHash
   108  	}
   109  
   110  	slashings := make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector)
   111  
   112  	genesisValidatorsRoot, err := v1.ValidatorRegistryRoot(preState.Validators())
   113  	if err != nil {
   114  		return nil, errors.Wrapf(err, "could not hash tree root genesis validators %v", err)
   115  	}
   116  
   117  	state := &pb.BeaconState{
   118  		// Misc fields.
   119  		Slot:                  0,
   120  		GenesisTime:           genesisTime,
   121  		GenesisValidatorsRoot: genesisValidatorsRoot[:],
   122  
   123  		Fork: &pb.Fork{
   124  			PreviousVersion: params.BeaconConfig().GenesisForkVersion,
   125  			CurrentVersion:  params.BeaconConfig().GenesisForkVersion,
   126  			Epoch:           0,
   127  		},
   128  
   129  		// Validator registry fields.
   130  		Validators: preState.Validators(),
   131  		Balances:   preState.Balances(),
   132  
   133  		// Randomness and committees.
   134  		RandaoMixes: randaoMixes,
   135  
   136  		// Finality.
   137  		PreviousJustifiedCheckpoint: &ethpb.Checkpoint{
   138  			Epoch: 0,
   139  			Root:  params.BeaconConfig().ZeroHash[:],
   140  		},
   141  		CurrentJustifiedCheckpoint: &ethpb.Checkpoint{
   142  			Epoch: 0,
   143  			Root:  params.BeaconConfig().ZeroHash[:],
   144  		},
   145  		JustificationBits: []byte{0},
   146  		FinalizedCheckpoint: &ethpb.Checkpoint{
   147  			Epoch: 0,
   148  			Root:  params.BeaconConfig().ZeroHash[:],
   149  		},
   150  
   151  		HistoricalRoots:           [][]byte{},
   152  		BlockRoots:                blockRoots,
   153  		StateRoots:                stateRoots,
   154  		Slashings:                 slashings,
   155  		CurrentEpochAttestations:  []*pb.PendingAttestation{},
   156  		PreviousEpochAttestations: []*pb.PendingAttestation{},
   157  
   158  		// Eth1 data.
   159  		Eth1Data:         eth1Data,
   160  		Eth1DataVotes:    []*ethpb.Eth1Data{},
   161  		Eth1DepositIndex: preState.Eth1DepositIndex(),
   162  	}
   163  
   164  	bodyRoot, err := (&ethpb.BeaconBlockBody{
   165  		RandaoReveal: make([]byte, 96),
   166  		Eth1Data: &ethpb.Eth1Data{
   167  			DepositRoot: make([]byte, 32),
   168  			BlockHash:   make([]byte, 32),
   169  		},
   170  		Graffiti: make([]byte, 32),
   171  	}).HashTreeRoot()
   172  	if err != nil {
   173  		return nil, errors.Wrap(err, "could not hash tree root empty block body")
   174  	}
   175  
   176  	state.LatestBlockHeader = &ethpb.BeaconBlockHeader{
   177  		ParentRoot: zeroHash,
   178  		StateRoot:  zeroHash,
   179  		BodyRoot:   bodyRoot[:],
   180  	}
   181  
   182  	return v1.InitializeFromProto(state)
   183  }
   184  
   185  // EmptyGenesisState returns an empty beacon state object.
   186  func EmptyGenesisState() (iface.BeaconState, error) {
   187  	state := &pb.BeaconState{
   188  		// Misc fields.
   189  		Slot: 0,
   190  		Fork: &pb.Fork{
   191  			PreviousVersion: params.BeaconConfig().GenesisForkVersion,
   192  			CurrentVersion:  params.BeaconConfig().GenesisForkVersion,
   193  			Epoch:           0,
   194  		},
   195  		// Validator registry fields.
   196  		Validators: []*ethpb.Validator{},
   197  		Balances:   []uint64{},
   198  
   199  		JustificationBits:         []byte{0},
   200  		HistoricalRoots:           [][]byte{},
   201  		CurrentEpochAttestations:  []*pb.PendingAttestation{},
   202  		PreviousEpochAttestations: []*pb.PendingAttestation{},
   203  
   204  		// Eth1 data.
   205  		Eth1Data:         &ethpb.Eth1Data{},
   206  		Eth1DataVotes:    []*ethpb.Eth1Data{},
   207  		Eth1DepositIndex: 0,
   208  	}
   209  	return v1.InitializeFromProto(state)
   210  }
   211  
   212  // IsValidGenesisState gets called whenever there's a deposit event,
   213  // it checks whether there's enough effective balance to trigger and
   214  // if the minimum genesis time arrived already.
   215  //
   216  // Spec pseudocode definition:
   217  //  def is_valid_genesis_state(state: BeaconState) -> bool:
   218  //     if state.genesis_time < MIN_GENESIS_TIME:
   219  //         return False
   220  //     if len(get_active_validator_indices(state, GENESIS_EPOCH)) < MIN_GENESIS_ACTIVE_VALIDATOR_COUNT:
   221  //         return False
   222  //     return True
   223  // This method has been modified from the spec to allow whole states not to be saved
   224  // but instead only cache the relevant information.
   225  func IsValidGenesisState(chainStartDepositCount, currentTime uint64) bool {
   226  	if currentTime < params.BeaconConfig().MinGenesisTime {
   227  		return false
   228  	}
   229  	if chainStartDepositCount < params.BeaconConfig().MinGenesisActiveValidatorCount {
   230  		return false
   231  	}
   232  	return true
   233  }