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: ðpb.Checkpoint{ 138 Epoch: 0, 139 Root: params.BeaconConfig().ZeroHash[:], 140 }, 141 CurrentJustifiedCheckpoint: ðpb.Checkpoint{ 142 Epoch: 0, 143 Root: params.BeaconConfig().ZeroHash[:], 144 }, 145 JustificationBits: []byte{0}, 146 FinalizedCheckpoint: ðpb.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 := (ðpb.BeaconBlockBody{ 165 RandaoReveal: make([]byte, 96), 166 Eth1Data: ðpb.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 = ðpb.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: ðpb.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 }