pub fn produce_block_on_state(
        &self,
        mut state: BeaconState<T::EthSpec>,
        state_root_opt: Option<Hash256>,
        produce_at_slot: Slot,
        randao_reveal: Signature,
        validator_graffiti: Option<Graffiti>,
    ) -> Result<BeaconBlockAndState<T::EthSpec>, BlockProductionError> {
        let eth1_chain = self
            .eth1_chain
            .as_ref()
            .ok_or(BlockProductionError::NoEth1ChainConnection)?;

        // It is invalid to try to produce a block using a state from a future slot.
        if state.slot > produce_at_slot {
            return Err(BlockProductionError::StateSlotTooHigh {
                produce_at_slot,
                state_slot: state.slot,
            });
        }

        let slot_timer = metrics::start_timer(&metrics::BLOCK_PRODUCTION_SLOT_PROCESS_TIMES);

        // Ensure the state has performed a complete transition into the required slot.
        complete_state_advance(&mut state, state_root_opt, produce_at_slot, &self.spec)?;

        drop(slot_timer);

        state.build_committee_cache(RelativeEpoch::Current, &self.spec)?;

        let parent_root = if state.slot > 0 {
            *state
                .get_block_root(state.slot - 1)
                .map_err(|_| BlockProductionError::UnableToGetBlockRootFromState)?
        } else {
            state.latest_block_header.canonical_root()
        };

        let (proposer_slashings, attester_slashings) =
            self.op_pool.get_slashings(&state, &self.spec);

        let eth1_data = eth1_chain.eth1_data_for_block_production(&state, &self.spec)?;
        let deposits = eth1_chain
            .deposits_for_block_inclusion(&state, &eth1_data, &self.spec)?
            .into();

        // Map from attestation head block root to shuffling compatibility.
        // Used to memoize the `attestation_shuffling_is_compatible` function.
        let mut shuffling_filter_cache = HashMap::new();
        let attestation_filter = |att: &&Attestation<T::EthSpec>| -> bool {
            *shuffling_filter_cache
                .entry((att.data.beacon_block_root, att.data.target.epoch))
                .or_insert_with(|| {
                    self.shuffling_is_compatible(
                        &att.data.beacon_block_root,
                        att.data.target.epoch,
                        &state,
                    )
                })
        };

        // Iterate through the naive aggregation pool and ensure all the attestations from there
        // are included in the operation pool.
        let unagg_import_timer =
            metrics::start_timer(&metrics::BLOCK_PRODUCTION_UNAGGREGATED_TIMES);
        for attestation in self.naive_aggregation_pool.read().iter() {
            if let Err(e) = self.op_pool.insert_attestation(
                attestation.clone(),
                &state.fork,
                state.genesis_validators_root,
                &self.spec,
            ) {
                // Don't stop block production if there's an error, just create a log.
                error!(
                    self.log,
                    "Attestation did not transfer to op pool";
                    "reason" => ?e
                );
            }
        }
        drop(unagg_import_timer);

        // Override the beacon node's graffiti with graffiti from the validator, if present.
        let graffiti = match validator_graffiti {
            Some(graffiti) => graffiti,
            None => self.graffiti,
        };

        let attestation_packing_timer =
            metrics::start_timer(&metrics::BLOCK_PRODUCTION_ATTESTATION_TIMES);
        let attestations = self
            .op_pool
            .get_attestations(&state, attestation_filter, &self.spec)
            .map_err(BlockProductionError::OpPoolError)?
            .into();
        drop(attestation_packing_timer);

        let mut block = SignedBeaconBlock {
            message: BeaconBlock {
                slot: state.slot,
                proposer_index: state.get_beacon_proposer_index(state.slot, &self.spec)? as u64,
                parent_root,
                state_root: Hash256::zero(),
                body: BeaconBlockBody {
                    randao_reveal,
                    eth1_data,
                    graffiti,
                    proposer_slashings: proposer_slashings.into(),
                    attester_slashings: attester_slashings.into(),
                    attestations,
                    deposits,
                    voluntary_exits: self.op_pool.get_voluntary_exits(&state, &self.spec).into(),
                },
            },
            // The block is not signed here, that is the task of a validator client.
            signature: Signature::empty(),
        };

        let process_timer = metrics::start_timer(&metrics::BLOCK_PRODUCTION_PROCESS_TIMES);
        per_block_processing(
            &mut state,
            &block,
            None,
            BlockSignatureStrategy::NoVerification,
            &self.spec,
        )?;
        drop(process_timer);

        let state_root_timer = metrics::start_timer(&metrics::BLOCK_PRODUCTION_STATE_ROOT_TIMES);
        let state_root = state.update_tree_hash_cache()?;
        drop(state_root_timer);

        block.message.state_root = state_root;

        metrics::inc_counter(&metrics::BLOCK_PRODUCTION_SUCCESSES);

        trace!(
            self.log,
            "Produced beacon block";
            "parent" => %block.message.parent_root,
            "attestations" => block.message.body.attestations.len(),
            "slot" => block.message.slot
        );

        Ok((block.message, state))
    }
/// Produce a block for some `slot` upon the given `state`.
///
/// Typically the `self.produce_block()` function should be used, instead of calling this
/// function directly. This function is useful for purposefully creating forks or blocks at
/// non-current slots.
///
/// If required, the given state will be advanced to the given `produce_at_slot`, then a block
/// will be produced at that slot height.
///
/// The provided `state_root_opt` should only ever be set to `Some` if the contained value is
/// equal to the root of `state`. Providing this value will serve as an optimization to avoid
/// performing a tree hash in some scenarios.
Produce a block for some `slot` upon the given `state`.
Typically the `self.produce_block()` function should be used, instead of calling this
function directly. This function is useful for purposefully creating forks or blocks at
non-current slots.

If required, the given state will be advanced to the given `produce_at_slot`, then a block
will be produced at that slot height.


Produce a block for some ` slot ` upon the given ` state ` . Typically the ` self . produce_block () ` function should be used instead of calling this function directly . This function is useful for purposefully creating forks or blocks at non - current slots . If required the given state will be advanced to the given ` produce_at_slot ` then a block will be produced at that slot height .
pub fn produce_block_on_state(
        &self,
        mut state: BeaconState<T::EthSpec>,
        state_root_opt: Option<Hash256>,
        produce_at_slot: Slot,
        randao_reveal: Signature,
        validator_graffiti: Option<Graffiti>,
    ) -> Result<BeaconBlockAndState<T::EthSpec>, BlockProductionError> {
        let eth1_chain = self
            .eth1_chain
            .as_ref()
            .ok_or(BlockProductionError::NoEth1ChainConnection)?;
        // It is invalid to try to produce a block using a state from a future slot.
        if state.slot > produce_at_slot {
            return Err(BlockProductionError::StateSlotTooHigh {
                produce_at_slot,
                state_slot: state.slot,
            });
        }
        let slot_timer = metrics::start_timer(&metrics::BLOCK_PRODUCTION_SLOT_PROCESS_TIMES);
        // Ensure the state has performed a complete transition into the required slot.
        complete_state_advance(&mut state, state_root_opt, produce_at_slot, &self.spec)?;
        drop(slot_timer);
        state.build_committee_cache(RelativeEpoch::Current, &self.spec)?;
        let parent_root = if state.slot > 0 {
            *state
                .get_block_root(state.slot - 1)
                .map_err(|_| BlockProductionError::UnableToGetBlockRootFromState)?
        } else {
            state.latest_block_header.canonical_root()
        };
        let (proposer_slashings, attester_slashings) =
            self.op_pool.get_slashings(&state, &self.spec);
        let eth1_data = eth1_chain.eth1_data_for_block_production(&state, &self.spec)?;
        let deposits = eth1_chain
            .deposits_for_block_inclusion(&state, &eth1_data, &self.spec)?
            .into();
        // Map from attestation head block root to shuffling compatibility.
        // Used to memoize the `attestation_shuffling_is_compatible` function.
        let mut shuffling_filter_cache = HashMap::new();
        let attestation_filter = |att: &&Attestation<T::EthSpec>| -> bool {
            *shuffling_filter_cache
                .entry((att.data.beacon_block_root, att.data.target.epoch))
                .or_insert_with(|| {
                    self.shuffling_is_compatible(
                        &att.data.beacon_block_root,
                        att.data.target.epoch,
                        &state,
                    )
                })
        };
        // Iterate through the naive aggregation pool and ensure all the attestations from there
        // are included in the operation pool.
        let unagg_import_timer =
            metrics::start_timer(&metrics::BLOCK_PRODUCTION_UNAGGREGATED_TIMES);
        for attestation in self.naive_aggregation_pool.read().iter() {
            if let Err(e) = self.op_pool.insert_attestation(
                attestation.clone(),
                &state.fork,
                state.genesis_validators_root,
                &self.spec,
            ) {
                // Don't stop block production if there's an error, just create a log.
                error!(
                    self.log,
                    "Attestation did not transfer to op pool";
                    "reason" => ?e
                );
            }
        }
        drop(unagg_import_timer);
        // Override the beacon node's graffiti with graffiti from the validator, if present.
        let graffiti = match validator_graffiti {
            Some(graffiti) => graffiti,
            None => self.graffiti,
        };
        let attestation_packing_timer =
            metrics::start_timer(&metrics::BLOCK_PRODUCTION_ATTESTATION_TIMES);
        let attestations = self
            .op_pool
            .get_attestations(&state, attestation_filter, &self.spec)
            .map_err(BlockProductionError::OpPoolError)?
            .into();
        drop(attestation_packing_timer);
        let mut block = SignedBeaconBlock {
            message: BeaconBlock {
                slot: state.slot,
                proposer_index: state.get_beacon_proposer_index(state.slot, &self.spec)? as u64,
                parent_root,
                state_root: Hash256::zero(),
                body: BeaconBlockBody {
                    randao_reveal,
                    eth1_data,
                    graffiti,
                    proposer_slashings: proposer_slashings.into(),
                    attester_slashings: attester_slashings.into(),
                    attestations,
                    deposits,
                    voluntary_exits: self.op_pool.get_voluntary_exits(&state, &self.spec).into(),
                },
            },
            // The block is not signed here, that is the task of a validator client.
            signature: Signature::empty(),
        };
        let process_timer = metrics::start_timer(&metrics::BLOCK_PRODUCTION_PROCESS_TIMES);
        per_block_processing(
            &mut state,
            &block,
            None,
            BlockSignatureStrategy::NoVerification,
            &self.spec,
        )?;
        drop(process_timer);
        let state_root_timer = metrics::start_timer(&metrics::BLOCK_PRODUCTION_STATE_ROOT_TIMES);
        let state_root = state.update_tree_hash_cache()?;
        drop(state_root_timer);
        block.message.state_root = state_root;
        metrics::inc_counter(&metrics::BLOCK_PRODUCTION_SUCCESSES);
        trace!(
            self.log,
            "Produced beacon block";
            "parent" => %block.message.parent_root,
            "attestations" => block.message.body.attestations.len(),
            "slot" => block.message.slot
        );
        Ok((block.message, state))
    }
pub fn produce_block_on_state ( & self , mut state : BeaconState < T :: EthSpec > , state_root_opt : Option < Hash256 > , produce_at_slot : Slot , randao_reveal : Signature , validator_graffiti : Option < Graffiti > , ) -> Result < BeaconBlockAndState < T :: EthSpec > , BlockProductionError > { let eth1_chain = self . eth1_chain . as_ref ( ) . ok_or ( BlockProductionError :: NoEth1ChainConnection ) ? ; // It is invalid to try to produce a block using a state from a future slot. if state . slot > produce_at_slot { return Err ( BlockProductionError :: StateSlotTooHigh { produce_at_slot , state_slot : state . slot , } ) ; } let slot_timer = metrics :: start_timer ( & metrics :: BLOCK_PRODUCTION_SLOT_PROCESS_TIMES ) ; // Ensure the state has performed a complete transition into the required slot. complete_state_advance ( & mut state , state_root_opt , produce_at_slot , & self . spec ) ? ; drop ( slot_timer ) ; state . build_committee_cache ( RelativeEpoch :: Current , & self . spec ) ? ; let parent_root = if state . slot > 0 { * state . get_block_root ( state . slot - 1 ) . map_err ( | _ | BlockProductionError :: UnableToGetBlockRootFromState ) ? } else { state . latest_block_header . canonical_root ( ) } ; let ( proposer_slashings , attester_slashings ) = self . op_pool . get_slashings ( & state , & self . spec ) ; let eth1_data = eth1_chain . eth1_data_for_block_production ( & state , & self . spec ) ? ; let deposits = eth1_chain . deposits_for_block_inclusion ( & state , & eth1_data , & self . spec ) ? . into ( ) ; // Map from attestation head block root to shuffling compatibility. // Used to memoize the `attestation_shuffling_is_compatible` function. let mut shuffling_filter_cache = HashMap :: new ( ) ; let attestation_filter = | att : & & Attestation < T :: EthSpec > | -> bool { * shuffling_filter_cache . entry ( ( att . data . beacon_block_root , att . data . target . epoch ) ) . or_insert_with ( | | { self . shuffling_is_compatible ( & att . data . beacon_block_root , att . data . target . epoch , & state , ) } ) } ; // Iterate through the naive aggregation pool and ensure all the attestations from there // are included in the operation pool. let unagg_import_timer = metrics :: start_timer ( & metrics :: BLOCK_PRODUCTION_UNAGGREGATED_TIMES ) ; for attestation in self . naive_aggregation_pool . read ( ) . iter ( ) { if let Err ( e ) = self . op_pool . insert_attestation ( attestation . clone ( ) , & state . fork , state . genesis_validators_root , & self . spec , ) { // Don't stop block production if there's an error, just create a log. error ! ( self log " " " " e ) ; } } drop ( unagg_import_timer ) ; // Override the beacon node's graffiti with graffiti from the validator, if present. let graffiti = match validator_graffiti { Some ( graffiti ) => graffiti , None => self . graffiti , } ; let attestation_packing_timer = metrics :: start_timer ( & metrics :: BLOCK_PRODUCTION_ATTESTATION_TIMES ) ; let attestations = self . op_pool . get_attestations ( & state , attestation_filter , & self . spec ) . map_err ( BlockProductionError :: OpPoolError ) ? . into ( ) ; drop ( attestation_packing_timer ) ; let mut block = SignedBeaconBlock { message : BeaconBlock { slot : state . slot , proposer_index : state . get_beacon_proposer_index ( state . slot , & self . spec ) ? as u64 , parent_root , state_root : Hash256 :: zero ( ) , body : BeaconBlockBody { randao_reveal , eth1_data , graffiti , proposer_slashings : proposer_slashings . into ( ) , attester_slashings : attester_slashings . into ( ) , attestations , deposits , voluntary_exits : self . op_pool . get_voluntary_exits ( & state , & self . spec ) . into ( ) , } , } , // The block is not signed here, that is the task of a validator client. signature : Signature :: empty ( ) , } ; let process_timer = metrics :: start_timer ( & metrics :: BLOCK_PRODUCTION_PROCESS_TIMES ) ; per_block_processing ( & mut state , & block , None , BlockSignatureStrategy :: NoVerification , & self . spec , ) ? ; drop ( process_timer ) ; let state_root_timer = metrics :: start_timer ( & metrics :: BLOCK_PRODUCTION_STATE_ROOT_TIMES ) ; let state_root = state . update_tree_hash_cache ( ) ? ; drop ( state_root_timer ) ; block . message . state_root = state_root ; metrics :: inc_counter ( & metrics :: BLOCK_PRODUCTION_SUCCESSES ) ; trace ! ( self log " " " " block message parent_root " " block message body attestations len ( ) " " block message slot ) ; Ok ( ( block . message , state ) ) }
Produce a block for some `slot` upon the given `state`.
Produce a block for some ` slot ` upon the given ` state ` .
&self
state
BeaconState<T::EthSpec>
state_root_opt
Option<Hash256>
produce_at_slot
Slot
randao_reveal
Signature
validator_graffiti
Option<Graffiti>