diff --git a/beacon_node/beacon_chain/src/beacon_chain.rs b/beacon_node/beacon_chain/src/beacon_chain.rs index f6cef7dac..afc7a992a 100644 --- a/beacon_node/beacon_chain/src/beacon_chain.rs +++ b/beacon_node/beacon_chain/src/beacon_chain.rs @@ -466,6 +466,14 @@ impl BeaconChain { state.build_committee_cache(RelativeEpoch::Current, &self.spec)?; } + if epoch(state.as_ref().slot) != epoch(slot) { + return Err(Error::InvariantViolated(format!( + "Epochs in consistent in proposer lookup: state: {}, requested: {}", + epoch(state.as_ref().slot), + epoch(slot) + ))); + } + state .as_ref() .get_beacon_proposer_index(slot, RelativeEpoch::Current, &self.spec) @@ -494,6 +502,14 @@ impl BeaconChain { state.build_committee_cache(RelativeEpoch::Current, &self.spec)?; } + if as_epoch(state.as_ref().slot) != epoch { + return Err(Error::InvariantViolated(format!( + "Epochs in consistent in attestation duties lookup: state: {}, requested: {}", + as_epoch(state.as_ref().slot), + epoch + ))); + } + if let Some(attestation_duty) = state .as_ref() .get_attestation_duties(validator_index, RelativeEpoch::Current)? @@ -1123,13 +1139,9 @@ impl BeaconChain { slot: Slot, ) -> Result<(BeaconBlock, BeaconState), BlockProductionError> { let state = self - .state_at_slot(slot) + .state_at_slot(slot - 1) .map_err(|_| BlockProductionError::UnableToProduceAtSlot(slot))?; - let slot = self - .slot() - .map_err(|_| BlockProductionError::UnableToReadSlot)?; - self.produce_block_on_state(state.as_ref().clone(), slot, randao_reveal) } diff --git a/beacon_node/beacon_chain/src/errors.rs b/beacon_node/beacon_chain/src/errors.rs index cd8d6aad6..5ef68f2cd 100644 --- a/beacon_node/beacon_chain/src/errors.rs +++ b/beacon_node/beacon_chain/src/errors.rs @@ -37,6 +37,8 @@ pub enum BeaconChainError { beacon_block_root: Hash256, }, AttestationValidationError(AttestationValidationError), + /// Returned when an internal check fails, indicating corrupt data. + InvariantViolated(String), } easy_from_to!(SlotProcessingError, BeaconChainError); diff --git a/beacon_node/rpc/src/beacon_block.rs b/beacon_node/rpc/src/beacon_block.rs index f6be6207f..346d7e263 100644 --- a/beacon_node/rpc/src/beacon_block.rs +++ b/beacon_node/rpc/src/beacon_block.rs @@ -34,8 +34,7 @@ impl BeaconBlockService for BeaconBlockServiceInstance { trace!(self.log, "Generating a beacon block"; "req" => format!("{:?}", req)); // decode the request - // TODO: requested slot currently unused, see: https://github.com/sigp/lighthouse/issues/336 - let _requested_slot = Slot::from(req.get_slot()); + let requested_slot = Slot::from(req.get_slot()); let randao_reveal = match Signature::from_ssz_bytes(req.get_randao_reveal()) { Ok(reveal) => reveal, Err(_) => { @@ -51,22 +50,7 @@ impl BeaconBlockService for BeaconBlockServiceInstance { } }; - let slot = match self.chain.slot() { - Ok(slot) => slot, - Err(_) => { - // decode error, incorrect signature - let log_clone = self.log.clone(); - let f = sink - .fail(RpcStatus::new( - RpcStatusCode::InvalidArgument, - Some("No slot from chain".to_string()), - )) - .map_err(move |e| warn!(log_clone, "failed to reply {:?}: {:?}", req, e)); - return ctx.spawn(f); - } - }; - - let produced_block = match self.chain.produce_block(randao_reveal, slot) { + let produced_block = match self.chain.produce_block(randao_reveal, requested_slot) { Ok((block, _state)) => block, Err(e) => { // could not produce a block @@ -82,6 +66,11 @@ impl BeaconBlockService for BeaconBlockServiceInstance { } }; + assert_eq!( + produced_block.slot, requested_slot, + "should produce at the requested slot" + ); + let mut block = BeaconBlockProto::new(); block.set_ssz(ssz_encode(&produced_block)); diff --git a/beacon_node/rpc/src/validator.rs b/beacon_node/rpc/src/validator.rs index 2a1ad45f4..84995ca50 100644 --- a/beacon_node/rpc/src/validator.rs +++ b/beacon_node/rpc/src/validator.rs @@ -46,12 +46,20 @@ impl ValidatorService for ValidatorServiceInstance { let _ = state.build_all_caches(&self.chain.spec); + assert_eq!( + state.current_epoch(), + epoch, + "Retrieved state should be from the same epoch" + ); + let mut resp = GetDutiesResponse::new(); let resp_validators = resp.mut_active_validators(); let validator_proposers: Result, _> = epoch .slot_iter(T::EthSpec::slots_per_epoch()) - .map(|slot| self.chain.block_proposer(slot)) + .map(|slot| { + state.get_beacon_proposer_index(slot, RelativeEpoch::Current, &self.chain.spec) + }) .collect(); let validator_proposers = match validator_proposers { Ok(v) => v,