Tidy BeaconChain
; del spec
, unify head updates
This commit is contained in:
parent
8acffcc0db
commit
2f9f8bf772
@ -88,15 +88,28 @@ pub trait BeaconChainTypes {
|
|||||||
type EthSpec: types::EthSpec;
|
type EthSpec: types::EthSpec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Represents the "Beacon Chain" component of Ethereum 2.0. Allows import of blocks and block
|
||||||
|
/// operations and chooses a canonical head.
|
||||||
pub struct BeaconChain<T: BeaconChainTypes> {
|
pub struct BeaconChain<T: BeaconChainTypes> {
|
||||||
|
/// Persistent storage for blocks, states, etc. Typically an on-disk store, such as LevelDB.
|
||||||
pub store: Arc<T::Store>,
|
pub store: Arc<T::Store>,
|
||||||
|
/// Reports the current slot, typically based upon the system clock.
|
||||||
pub slot_clock: T::SlotClock,
|
pub slot_clock: T::SlotClock,
|
||||||
|
/// Stores all operations (e.g., `Attestation`, `Deposit`, etc) that are candidates for
|
||||||
|
/// inclusion in a block.
|
||||||
pub op_pool: OperationPool<T::EthSpec>,
|
pub op_pool: OperationPool<T::EthSpec>,
|
||||||
|
/// Stores a "snapshot" of the chain at the time the head-of-the-chain block was recieved.
|
||||||
canonical_head: RwLock<CheckPoint<T::EthSpec>>,
|
canonical_head: RwLock<CheckPoint<T::EthSpec>>,
|
||||||
|
/// Stores a "snapshot" of the chain at the latest finalized point.
|
||||||
finalized_head: RwLock<CheckPoint<T::EthSpec>>,
|
finalized_head: RwLock<CheckPoint<T::EthSpec>>,
|
||||||
|
/// The same state from `self.canonical_head`, but updated at the start of each slot with a
|
||||||
|
/// skip slot if no block is recieved. This is effectively a cache that avoids repeating calls
|
||||||
|
/// to `per_slot_processing`.
|
||||||
state: RwLock<BeaconState<T::EthSpec>>,
|
state: RwLock<BeaconState<T::EthSpec>>,
|
||||||
pub spec: ChainSpec,
|
/// A state-machine that is updated with information from the network and chooses a canonical
|
||||||
|
/// head block.
|
||||||
pub fork_choice: RwLock<T::ForkChoice>,
|
pub fork_choice: RwLock<T::ForkChoice>,
|
||||||
|
/// Stores metrics about this `BeaconChain`.
|
||||||
pub metrics: Metrics,
|
pub metrics: Metrics,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +151,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
state: RwLock::new(genesis_state),
|
state: RwLock::new(genesis_state),
|
||||||
finalized_head,
|
finalized_head,
|
||||||
canonical_head,
|
canonical_head,
|
||||||
spec,
|
|
||||||
fork_choice: RwLock::new(fork_choice),
|
fork_choice: RwLock::new(fork_choice),
|
||||||
metrics: Metrics::new()?,
|
metrics: Metrics::new()?,
|
||||||
})
|
})
|
||||||
@ -170,7 +182,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
canonical_head: RwLock::new(p.canonical_head),
|
canonical_head: RwLock::new(p.canonical_head),
|
||||||
finalized_head: RwLock::new(p.finalized_head),
|
finalized_head: RwLock::new(p.finalized_head),
|
||||||
state: RwLock::new(p.state),
|
state: RwLock::new(p.state),
|
||||||
spec,
|
|
||||||
fork_choice: RwLock::new(fork_choice),
|
fork_choice: RwLock::new(fork_choice),
|
||||||
metrics: Metrics::new()?,
|
metrics: Metrics::new()?,
|
||||||
}))
|
}))
|
||||||
@ -309,103 +320,37 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
Ok(self.store.get(block_root)?)
|
Ok(self.store.get(block_root)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update the canonical head to some new values.
|
/// Update the canonical head to `new_head`.
|
||||||
fn update_canonical_head(
|
fn update_canonical_head(&self, new_head: CheckPoint<T::EthSpec>) -> Result<(), Error> {
|
||||||
&self,
|
// Update the checkpoint that stores the head of the chain at the time it received the
|
||||||
new_beacon_block: BeaconBlock,
|
// block.
|
||||||
new_beacon_block_root: Hash256,
|
*self.canonical_head.write() = new_head;
|
||||||
new_beacon_state: BeaconState<T::EthSpec>,
|
|
||||||
new_beacon_state_root: Hash256,
|
|
||||||
) {
|
|
||||||
debug!(
|
|
||||||
"Updating canonical head with block at slot: {}",
|
|
||||||
new_beacon_block.slot
|
|
||||||
);
|
|
||||||
let mut head = self.canonical_head.write();
|
|
||||||
head.update(
|
|
||||||
new_beacon_block,
|
|
||||||
new_beacon_block_root,
|
|
||||||
new_beacon_state,
|
|
||||||
new_beacon_state_root,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a read-lock guarded `CheckPoint` struct for reading the head (as chosen by the
|
// Update the always-at-the-present-slot state we keep around for performance gains.
|
||||||
/// fork-choice rule).
|
*self.state.write() = {
|
||||||
///
|
let mut state = self.canonical_head.read().beacon_state.clone();
|
||||||
/// It is important to note that the `beacon_state` returned may not match the present slot. It
|
|
||||||
/// is the state as it was when the head block was received, which could be some slots prior to
|
|
||||||
/// now.
|
|
||||||
pub fn head(&self) -> RwLockReadGuard<CheckPoint<T::EthSpec>> {
|
|
||||||
self.canonical_head.read()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the slot of the highest block in the canonical chain.
|
let present_slot = match self.slot_clock.present_slot() {
|
||||||
pub fn best_slot(&self) -> Slot {
|
Ok(Some(slot)) => slot,
|
||||||
self.canonical_head.read().beacon_block.slot
|
_ => return Err(Error::UnableToReadSlot),
|
||||||
}
|
};
|
||||||
|
|
||||||
/// Updates the canonical `BeaconState` with the supplied state.
|
// If required, transition the new state to the present slot.
|
||||||
///
|
for _ in state.slot.as_u64()..present_slot.as_u64() {
|
||||||
/// Advances the chain forward to the present slot. This method is better than just setting
|
per_slot_processing(&mut state, &T::EthSpec::spec())?;
|
||||||
/// state and calling `catchup_state` as it will not result in an old state being installed and
|
}
|
||||||
/// then having it iteratively updated -- in such a case it's possible for another thread to
|
|
||||||
/// find the state at an old slot.
|
state.build_all_caches(&T::EthSpec::spec())?;
|
||||||
///
|
|
||||||
/// Also persists the `BeaconChain` to the store, in the case the client does not exit
|
state
|
||||||
/// gracefully.
|
|
||||||
fn update_state(&self, mut state: BeaconState<T::EthSpec>) -> Result<(), Error> {
|
|
||||||
let present_slot = match self.slot_clock.present_slot() {
|
|
||||||
Ok(Some(slot)) => slot,
|
|
||||||
_ => return Err(Error::UnableToReadSlot),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// If required, transition the new state to the present slot.
|
// Save `self` to `self.store`.
|
||||||
for _ in state.slot.as_u64()..present_slot.as_u64() {
|
|
||||||
per_slot_processing(&mut state, &self.spec)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
state.build_all_caches(&self.spec)?;
|
|
||||||
|
|
||||||
*self.state.write() = state;
|
|
||||||
|
|
||||||
self.persist()?;
|
self.persist()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ensures the current canonical `BeaconState` has been transitioned to match the `slot_clock`.
|
|
||||||
pub fn catchup_state(&self) -> Result<(), Error> {
|
|
||||||
let present_slot = match self.slot_clock.present_slot() {
|
|
||||||
Ok(Some(slot)) => slot,
|
|
||||||
_ => return Err(Error::UnableToReadSlot),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut state = self.state.write();
|
|
||||||
|
|
||||||
// If required, transition the new state to the present slot.
|
|
||||||
for _ in state.slot.as_u64()..present_slot.as_u64() {
|
|
||||||
// Ensure the next epoch state caches are built in case of an epoch transition.
|
|
||||||
state.build_epoch_cache(RelativeEpoch::NextWithoutRegistryChange, &self.spec)?;
|
|
||||||
state.build_epoch_cache(RelativeEpoch::NextWithRegistryChange, &self.spec)?;
|
|
||||||
|
|
||||||
per_slot_processing(&mut *state, &self.spec)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
state.build_all_caches(&self.spec)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Build all of the caches on the current state.
|
|
||||||
///
|
|
||||||
/// Ideally this shouldn't be required, however we leave it here for testing.
|
|
||||||
pub fn ensure_state_caches_are_built(&self) -> Result<(), Error> {
|
|
||||||
self.state.write().build_all_caches(&self.spec)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Update the justified head to some new values.
|
/// Update the justified head to some new values.
|
||||||
fn update_finalized_head(
|
fn update_finalized_head(
|
||||||
&self,
|
&self,
|
||||||
@ -423,6 +368,86 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
/// Updates the canonical `BeaconState` with the supplied state.
|
||||||
|
///
|
||||||
|
/// Advances the chain forward to the present slot. This method is better than just setting
|
||||||
|
/// state and calling `catchup_state` as it will not result in an old state being installed and
|
||||||
|
/// then having it iteratively updated -- in such a case it's possible for another thread to
|
||||||
|
/// find the state at an old slot.
|
||||||
|
///
|
||||||
|
/// Also persists the `BeaconChain` to the store, in the case the client does not exit
|
||||||
|
/// gracefully.
|
||||||
|
fn update_state(&self, mut state: BeaconState<T::EthSpec>) -> Result<(), Error> {
|
||||||
|
let present_slot = match self.slot_clock.present_slot() {
|
||||||
|
Ok(Some(slot)) => slot,
|
||||||
|
_ => return Err(Error::UnableToReadSlot),
|
||||||
|
};
|
||||||
|
|
||||||
|
// If required, transition the new state to the present slot.
|
||||||
|
for _ in state.slot.as_u64()..present_slot.as_u64() {
|
||||||
|
per_slot_processing(&mut state, &T::EthSpec::spec())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
state.build_all_caches(&T::EthSpec::spec())?;
|
||||||
|
|
||||||
|
*self.state.write() = state;
|
||||||
|
|
||||||
|
self.persist()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// Returns a read-lock guarded `CheckPoint` struct for reading the head (as chosen by the
|
||||||
|
/// fork-choice rule).
|
||||||
|
///
|
||||||
|
/// It is important to note that the `beacon_state` returned may not match the present slot. It
|
||||||
|
/// is the state as it was when the head block was received, which could be some slots prior to
|
||||||
|
/// now.
|
||||||
|
pub fn head(&self) -> RwLockReadGuard<CheckPoint<T::EthSpec>> {
|
||||||
|
self.canonical_head.read()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the slot of the highest block in the canonical chain.
|
||||||
|
pub fn best_slot(&self) -> Slot {
|
||||||
|
self.canonical_head.read().beacon_block.slot
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Ensures the current canonical `BeaconState` has been transitioned to match the `slot_clock`.
|
||||||
|
pub fn catchup_state(&self) -> Result<(), Error> {
|
||||||
|
let spec = &T::EthSpec::spec();
|
||||||
|
|
||||||
|
let present_slot = match self.slot_clock.present_slot() {
|
||||||
|
Ok(Some(slot)) => slot,
|
||||||
|
_ => return Err(Error::UnableToReadSlot),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut state = self.state.write();
|
||||||
|
|
||||||
|
// If required, transition the new state to the present slot.
|
||||||
|
for _ in state.slot.as_u64()..present_slot.as_u64() {
|
||||||
|
// Ensure the next epoch state caches are built in case of an epoch transition.
|
||||||
|
state.build_epoch_cache(RelativeEpoch::NextWithoutRegistryChange, spec)?;
|
||||||
|
state.build_epoch_cache(RelativeEpoch::NextWithRegistryChange, spec)?;
|
||||||
|
|
||||||
|
per_slot_processing(&mut *state, spec)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
state.build_all_caches(spec)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Build all of the caches on the current state.
|
||||||
|
///
|
||||||
|
/// Ideally this shouldn't be required, however we leave it here for testing.
|
||||||
|
pub fn ensure_state_caches_are_built(&self) -> Result<(), Error> {
|
||||||
|
self.state.write().build_all_caches(&T::EthSpec::spec())?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns a read-lock guarded `CheckPoint` struct for reading the justified head (as chosen,
|
/// Returns a read-lock guarded `CheckPoint` struct for reading the justified head (as chosen,
|
||||||
/// indirectly, by the fork-choice rule).
|
/// indirectly, by the fork-choice rule).
|
||||||
pub fn finalized_head(&self) -> RwLockReadGuard<CheckPoint<T::EthSpec>> {
|
pub fn finalized_head(&self) -> RwLockReadGuard<CheckPoint<T::EthSpec>> {
|
||||||
@ -467,13 +492,12 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
/// genesis.
|
/// genesis.
|
||||||
pub fn slots_since_genesis(&self) -> Option<SlotHeight> {
|
pub fn slots_since_genesis(&self) -> Option<SlotHeight> {
|
||||||
let now = self.read_slot_clock()?;
|
let now = self.read_slot_clock()?;
|
||||||
|
let genesis_slot = T::EthSpec::spec().genesis_slot;
|
||||||
|
|
||||||
if now < self.spec.genesis_slot {
|
if now < genesis_slot {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(SlotHeight::from(
|
Some(SlotHeight::from(now.as_u64() - genesis_slot.as_u64()))
|
||||||
now.as_u64() - self.spec.genesis_slot.as_u64(),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -493,12 +517,12 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
pub fn block_proposer(&self, slot: Slot) -> Result<usize, BeaconStateError> {
|
pub fn block_proposer(&self, slot: Slot) -> Result<usize, BeaconStateError> {
|
||||||
self.state
|
self.state
|
||||||
.write()
|
.write()
|
||||||
.build_epoch_cache(RelativeEpoch::Current, &self.spec)?;
|
.build_epoch_cache(RelativeEpoch::Current, &T::EthSpec::spec())?;
|
||||||
|
|
||||||
let index = self.state.read().get_beacon_proposer_index(
|
let index = self.state.read().get_beacon_proposer_index(
|
||||||
slot,
|
slot,
|
||||||
RelativeEpoch::Current,
|
RelativeEpoch::Current,
|
||||||
&self.spec,
|
&T::EthSpec::spec(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok(index)
|
Ok(index)
|
||||||
@ -519,7 +543,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
if let Some(attestation_duty) = self
|
if let Some(attestation_duty) = self
|
||||||
.state
|
.state
|
||||||
.read()
|
.read()
|
||||||
.get_attestation_duties(validator_index, &self.spec)?
|
.get_attestation_duties(validator_index, &T::EthSpec::spec())?
|
||||||
{
|
{
|
||||||
Ok(Some((attestation_duty.slot, attestation_duty.shard)))
|
Ok(Some((attestation_duty.slot, attestation_duty.shard)))
|
||||||
} else {
|
} else {
|
||||||
@ -529,7 +553,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
|
|
||||||
/// Produce an `AttestationData` that is valid for the present `slot` and given `shard`.
|
/// Produce an `AttestationData` that is valid for the present `slot` and given `shard`.
|
||||||
pub fn produce_attestation_data(&self, shard: u64) -> Result<AttestationData, Error> {
|
pub fn produce_attestation_data(&self, shard: u64) -> Result<AttestationData, Error> {
|
||||||
trace!("BeaconChain::produce_attestation: shard: {}", shard);
|
let slots_per_epoch = T::EthSpec::spec().slots_per_epoch;
|
||||||
|
|
||||||
self.metrics.attestation_production_requests.inc();
|
self.metrics.attestation_production_requests.inc();
|
||||||
let timer = self.metrics.attestation_production_times.start_timer();
|
let timer = self.metrics.attestation_production_times.start_timer();
|
||||||
@ -540,8 +564,8 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
.state
|
.state
|
||||||
.read()
|
.read()
|
||||||
.slot
|
.slot
|
||||||
.epoch(self.spec.slots_per_epoch)
|
.epoch(slots_per_epoch)
|
||||||
.start_slot(self.spec.slots_per_epoch);
|
.start_slot(slots_per_epoch);
|
||||||
|
|
||||||
let target_root = if state.slot == current_epoch_start_slot {
|
let target_root = if state.slot == current_epoch_start_slot {
|
||||||
// If we're on the first slot of the state's epoch.
|
// If we're on the first slot of the state's epoch.
|
||||||
@ -554,7 +578,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
*self
|
*self
|
||||||
.state
|
.state
|
||||||
.read()
|
.read()
|
||||||
.get_block_root(current_epoch_start_slot - self.spec.slots_per_epoch)?
|
.get_block_root(current_epoch_start_slot - slots_per_epoch)?
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If we're not on the first slot of the epoch.
|
// If we're not on the first slot of the epoch.
|
||||||
@ -587,9 +611,9 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
self.metrics.attestation_processing_requests.inc();
|
self.metrics.attestation_processing_requests.inc();
|
||||||
let timer = self.metrics.attestation_processing_times.start_timer();
|
let timer = self.metrics.attestation_processing_times.start_timer();
|
||||||
|
|
||||||
let result = self
|
let result =
|
||||||
.op_pool
|
self.op_pool
|
||||||
.insert_attestation(attestation, &*self.state.read(), &self.spec);
|
.insert_attestation(attestation, &*self.state.read(), &T::EthSpec::spec());
|
||||||
|
|
||||||
if result.is_ok() {
|
if result.is_ok() {
|
||||||
self.metrics.attestation_production_successes.inc();
|
self.metrics.attestation_production_successes.inc();
|
||||||
@ -606,19 +630,19 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
deposit: Deposit,
|
deposit: Deposit,
|
||||||
) -> Result<DepositInsertStatus, DepositValidationError> {
|
) -> Result<DepositInsertStatus, DepositValidationError> {
|
||||||
self.op_pool
|
self.op_pool
|
||||||
.insert_deposit(deposit, &*self.state.read(), &self.spec)
|
.insert_deposit(deposit, &*self.state.read(), &T::EthSpec::spec())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Accept some exit and queue it for inclusion in an appropriate block.
|
/// Accept some exit and queue it for inclusion in an appropriate block.
|
||||||
pub fn process_voluntary_exit(&self, exit: VoluntaryExit) -> Result<(), ExitValidationError> {
|
pub fn process_voluntary_exit(&self, exit: VoluntaryExit) -> Result<(), ExitValidationError> {
|
||||||
self.op_pool
|
self.op_pool
|
||||||
.insert_voluntary_exit(exit, &*self.state.read(), &self.spec)
|
.insert_voluntary_exit(exit, &*self.state.read(), &T::EthSpec::spec())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Accept some transfer and queue it for inclusion in an appropriate block.
|
/// Accept some transfer and queue it for inclusion in an appropriate block.
|
||||||
pub fn process_transfer(&self, transfer: Transfer) -> Result<(), TransferValidationError> {
|
pub fn process_transfer(&self, transfer: Transfer) -> Result<(), TransferValidationError> {
|
||||||
self.op_pool
|
self.op_pool
|
||||||
.insert_transfer(transfer, &*self.state.read(), &self.spec)
|
.insert_transfer(transfer, &*self.state.read(), &T::EthSpec::spec())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Accept some proposer slashing and queue it for inclusion in an appropriate block.
|
/// Accept some proposer slashing and queue it for inclusion in an appropriate block.
|
||||||
@ -626,8 +650,11 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
&self,
|
&self,
|
||||||
proposer_slashing: ProposerSlashing,
|
proposer_slashing: ProposerSlashing,
|
||||||
) -> Result<(), ProposerSlashingValidationError> {
|
) -> Result<(), ProposerSlashingValidationError> {
|
||||||
self.op_pool
|
self.op_pool.insert_proposer_slashing(
|
||||||
.insert_proposer_slashing(proposer_slashing, &*self.state.read(), &self.spec)
|
proposer_slashing,
|
||||||
|
&*self.state.read(),
|
||||||
|
&T::EthSpec::spec(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Accept some attester slashing and queue it for inclusion in an appropriate block.
|
/// Accept some attester slashing and queue it for inclusion in an appropriate block.
|
||||||
@ -635,8 +662,11 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
&self,
|
&self,
|
||||||
attester_slashing: AttesterSlashing,
|
attester_slashing: AttesterSlashing,
|
||||||
) -> Result<(), AttesterSlashingValidationError> {
|
) -> Result<(), AttesterSlashingValidationError> {
|
||||||
self.op_pool
|
self.op_pool.insert_attester_slashing(
|
||||||
.insert_attester_slashing(attester_slashing, &*self.state.read(), &self.spec)
|
attester_slashing,
|
||||||
|
&*self.state.read(),
|
||||||
|
&T::EthSpec::spec(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Accept some block and attempt to add it to block DAG.
|
/// Accept some block and attempt to add it to block DAG.
|
||||||
@ -686,7 +716,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
// Transition the parent state to the block slot.
|
// Transition the parent state to the block slot.
|
||||||
let mut state: BeaconState<T::EthSpec> = parent_state;
|
let mut state: BeaconState<T::EthSpec> = parent_state;
|
||||||
for _ in state.slot.as_u64()..block.slot.as_u64() {
|
for _ in state.slot.as_u64()..block.slot.as_u64() {
|
||||||
if let Err(e) = per_slot_processing(&mut state, &self.spec) {
|
if let Err(e) = per_slot_processing(&mut state, &T::EthSpec::spec()) {
|
||||||
return Ok(BlockProcessingOutcome::InvalidBlock(
|
return Ok(BlockProcessingOutcome::InvalidBlock(
|
||||||
InvalidBlock::SlotProcessingError(e),
|
InvalidBlock::SlotProcessingError(e),
|
||||||
));
|
));
|
||||||
@ -695,7 +725,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
|
|
||||||
// Apply the received block to its parent state (which has been transitioned into this
|
// Apply the received block to its parent state (which has been transitioned into this
|
||||||
// slot).
|
// slot).
|
||||||
if let Err(e) = per_block_processing(&mut state, &block, &self.spec) {
|
if let Err(e) = per_block_processing(&mut state, &block, &T::EthSpec::spec()) {
|
||||||
return Ok(BlockProcessingOutcome::InvalidBlock(
|
return Ok(BlockProcessingOutcome::InvalidBlock(
|
||||||
InvalidBlock::PerBlockProcessingError(e),
|
InvalidBlock::PerBlockProcessingError(e),
|
||||||
));
|
));
|
||||||
@ -716,7 +746,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
// Register the new block with the fork choice service.
|
// Register the new block with the fork choice service.
|
||||||
self.fork_choice
|
self.fork_choice
|
||||||
.write()
|
.write()
|
||||||
.add_block(&block, &block_root, &self.spec)?;
|
.add_block(&block, &block_root, &T::EthSpec::spec())?;
|
||||||
|
|
||||||
// Execute the fork choice algorithm, enthroning a new head if discovered.
|
// Execute the fork choice algorithm, enthroning a new head if discovered.
|
||||||
//
|
//
|
||||||
@ -744,7 +774,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
|
|
||||||
let mut state = self.state.read().clone();
|
let mut state = self.state.read().clone();
|
||||||
|
|
||||||
state.build_epoch_cache(RelativeEpoch::Current, &self.spec)?;
|
state.build_epoch_cache(RelativeEpoch::Current, &T::EthSpec::spec())?;
|
||||||
|
|
||||||
trace!("Finding attestations for new block...");
|
trace!("Finding attestations for new block...");
|
||||||
|
|
||||||
@ -752,14 +782,15 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
.get_block_root(state.slot - 1)
|
.get_block_root(state.slot - 1)
|
||||||
.map_err(|_| BlockProductionError::UnableToGetBlockRootFromState)?;
|
.map_err(|_| BlockProductionError::UnableToGetBlockRootFromState)?;
|
||||||
|
|
||||||
let (proposer_slashings, attester_slashings) =
|
let (proposer_slashings, attester_slashings) = self
|
||||||
self.op_pool.get_slashings(&*self.state.read(), &self.spec);
|
.op_pool
|
||||||
|
.get_slashings(&*self.state.read(), &T::EthSpec::spec());
|
||||||
|
|
||||||
let mut block = BeaconBlock {
|
let mut block = BeaconBlock {
|
||||||
slot: state.slot,
|
slot: state.slot,
|
||||||
previous_block_root,
|
previous_block_root,
|
||||||
state_root: Hash256::zero(), // Updated after the state is calculated.
|
state_root: Hash256::zero(), // Updated after the state is calculated.
|
||||||
signature: self.spec.empty_signature.clone(), // To be completed by a validator.
|
signature: T::EthSpec::spec().empty_signature.clone(), // To be completed by a validator.
|
||||||
body: BeaconBlockBody {
|
body: BeaconBlockBody {
|
||||||
randao_reveal,
|
randao_reveal,
|
||||||
eth1_data: Eth1Data {
|
eth1_data: Eth1Data {
|
||||||
@ -771,12 +802,16 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
attester_slashings,
|
attester_slashings,
|
||||||
attestations: self
|
attestations: self
|
||||||
.op_pool
|
.op_pool
|
||||||
.get_attestations(&*self.state.read(), &self.spec),
|
.get_attestations(&*self.state.read(), &T::EthSpec::spec()),
|
||||||
deposits: self.op_pool.get_deposits(&*self.state.read(), &self.spec),
|
deposits: self
|
||||||
|
.op_pool
|
||||||
|
.get_deposits(&*self.state.read(), &T::EthSpec::spec()),
|
||||||
voluntary_exits: self
|
voluntary_exits: self
|
||||||
.op_pool
|
.op_pool
|
||||||
.get_voluntary_exits(&*self.state.read(), &self.spec),
|
.get_voluntary_exits(&*self.state.read(), &T::EthSpec::spec()),
|
||||||
transfers: self.op_pool.get_transfers(&*self.state.read(), &self.spec),
|
transfers: self
|
||||||
|
.op_pool
|
||||||
|
.get_transfers(&*self.state.read(), &T::EthSpec::spec()),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -785,7 +820,11 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
block.body.attestations.len()
|
block.body.attestations.len()
|
||||||
);
|
);
|
||||||
|
|
||||||
per_block_processing_without_verifying_block_signature(&mut state, &block, &self.spec)?;
|
per_block_processing_without_verifying_block_signature(
|
||||||
|
&mut state,
|
||||||
|
&block,
|
||||||
|
&T::EthSpec::spec(),
|
||||||
|
)?;
|
||||||
|
|
||||||
let state_root = state.canonical_root();
|
let state_root = state.canonical_root();
|
||||||
|
|
||||||
@ -808,7 +847,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
let new_head_root = self
|
let new_head_root = self
|
||||||
.fork_choice
|
.fork_choice
|
||||||
.write()
|
.write()
|
||||||
.find_head(&present_head_root, &self.spec)?;
|
.find_head(&present_head_root, &T::EthSpec::spec())?;
|
||||||
|
|
||||||
timer.observe_duration();
|
timer.observe_duration();
|
||||||
|
|
||||||
@ -830,10 +869,12 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let state_root = block.state_root;
|
let state_root = block.state_root;
|
||||||
self.update_canonical_head(block, new_head_root, state.clone(), state_root);
|
self.update_canonical_head(CheckPoint {
|
||||||
|
beacon_block: block,
|
||||||
// Update the canonical `BeaconState`.
|
beacon_block_root: new_head_root,
|
||||||
self.update_state(state)?;
|
beacon_state: state.clone(),
|
||||||
|
beacon_state_root: state_root,
|
||||||
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -863,7 +904,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
loop {
|
loop {
|
||||||
let beacon_block_root = last_slot.beacon_block.previous_block_root;
|
let beacon_block_root = last_slot.beacon_block.previous_block_root;
|
||||||
|
|
||||||
if beacon_block_root == self.spec.zero_hash {
|
if beacon_block_root == T::EthSpec::spec().zero_hash {
|
||||||
break; // Genesis has been reached.
|
break; // Genesis has been reached.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ use persistent::Read;
|
|||||||
use router::Router;
|
use router::Router;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use types::EthSpec;
|
||||||
|
|
||||||
/// Yields a handler for the HTTP API.
|
/// Yields a handler for the HTTP API.
|
||||||
pub fn build_handler<T: BeaconChainTypes + 'static>(
|
pub fn build_handler<T: BeaconChainTypes + 'static>(
|
||||||
@ -64,7 +65,7 @@ fn handle_fork<T: BeaconChainTypes + 'static>(req: &mut Request) -> IronResult<R
|
|||||||
|
|
||||||
let response = json!({
|
let response = json!({
|
||||||
"fork": beacon_chain.head().beacon_state.fork,
|
"fork": beacon_chain.head().beacon_state.fork,
|
||||||
"chain_id": beacon_chain.spec.chain_id
|
"chain_id": T::EthSpec::spec().chain_id
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(Response::with((Status::Ok, response.to_string())))
|
Ok(Response::with((Status::Ok, response.to_string())))
|
||||||
|
@ -859,7 +859,7 @@ fn hello_message<T: BeaconChainTypes>(beacon_chain: &BeaconChain<T>) -> HelloMes
|
|||||||
latest_finalized_root: state.finalized_root,
|
latest_finalized_root: state.finalized_root,
|
||||||
latest_finalized_epoch: state.finalized_epoch,
|
latest_finalized_epoch: state.finalized_epoch,
|
||||||
best_root: beacon_chain.head().beacon_block_root,
|
best_root: beacon_chain.head().beacon_block_root,
|
||||||
best_slot: beacon_chain.head().beacon_block.slot,
|
best_slot: state.slot,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
use slot_clock;
|
use slot_clock;
|
||||||
|
|
||||||
use error_chain::error_chain;
|
use error_chain::{
|
||||||
|
error_chain
|
||||||
|
};
|
||||||
|
|
||||||
error_chain! {
|
error_chain! {
|
||||||
links { }
|
links { }
|
||||||
|
Loading…
Reference in New Issue
Block a user