Refactor block val. into "BlockValidationContext"
This commit is contained in:
parent
bc27be147f
commit
0b99951bf8
@ -5,7 +5,7 @@ use self::test::Bencher;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
validate_ssz_block,
|
BlockValidationContext,
|
||||||
AttesterMap,
|
AttesterMap,
|
||||||
ProposerMap,
|
ProposerMap,
|
||||||
};
|
};
|
||||||
@ -50,17 +50,18 @@ fn bench_block_validation_scenario<F>(
|
|||||||
let proposer_map = Arc::new(proposer_map);
|
let proposer_map = Arc::new(proposer_map);
|
||||||
let attester_map = Arc::new(attester_map);
|
let attester_map = Arc::new(attester_map);
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
validate_ssz_block(
|
let context = BlockValidationContext {
|
||||||
&ssz_block,
|
present_slot: validation_slot,
|
||||||
validation_slot,
|
cycle_length: params.cycle_length,
|
||||||
params.cycle_length,
|
last_justified_slot: validation_last_justified_slot,
|
||||||
validation_last_justified_slot,
|
parent_hashes: parent_hashes.clone(),
|
||||||
&parent_hashes.clone(),
|
proposer_map: proposer_map.clone(),
|
||||||
&proposer_map.clone(),
|
attester_map: attester_map.clone(),
|
||||||
&attester_map.clone(),
|
block_store: stores.block.clone(),
|
||||||
&stores.block.clone(),
|
validator_store: stores.validator.clone(),
|
||||||
&stores.validator.clone(),
|
pow_store: stores.pow_chain.clone()
|
||||||
&stores.pow_chain.clone())
|
};
|
||||||
|
context.validate_ssz_block(&ssz_block)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ use super::common::maps::{
|
|||||||
ProposerMap,
|
ProposerMap,
|
||||||
};
|
};
|
||||||
pub use self::validate_ssz_block::{
|
pub use self::validate_ssz_block::{
|
||||||
validate_ssz_block,
|
BlockValidationContext,
|
||||||
SszBlockValidationError,
|
SszBlockValidationError,
|
||||||
BlockStatus,
|
BlockStatus,
|
||||||
};
|
};
|
||||||
|
@ -5,7 +5,7 @@ use self::ssz::{
|
|||||||
};
|
};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use super::{
|
use super::{
|
||||||
validate_ssz_block,
|
BlockValidationContext,
|
||||||
SszBlockValidationError,
|
SszBlockValidationError,
|
||||||
BlockStatus,
|
BlockStatus,
|
||||||
AttesterMap,
|
AttesterMap,
|
||||||
@ -101,21 +101,7 @@ pub fn setup_block_validation_scenario(params: &TestParams)
|
|||||||
proposer_map.insert(block_slot, validator_index);
|
proposer_map.insert(block_slot, validator_index);
|
||||||
proposer_map
|
proposer_map
|
||||||
};
|
};
|
||||||
/*
|
|
||||||
let attestation_slot = block_slot - 1;
|
|
||||||
let (attester_map, attestations, _keypairs) =
|
|
||||||
generate_attestations_for_slot(
|
|
||||||
attestation_slot,
|
|
||||||
block_slot,
|
|
||||||
shards_per_slot,
|
|
||||||
validators_per_shard,
|
|
||||||
cycle_length,
|
|
||||||
&parent_hashes,
|
|
||||||
&Hash256::from("shard_hash".as_bytes()),
|
|
||||||
&justified_block_hash,
|
|
||||||
attestations_justified_slot,
|
|
||||||
&stores);
|
|
||||||
*/
|
|
||||||
let (attester_map, attestations, _keypairs) = {
|
let (attester_map, attestations, _keypairs) = {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
let attestation_slot = block_slot - 1;
|
let attestation_slot = block_slot - 1;
|
||||||
@ -244,17 +230,18 @@ pub fn run_block_validation_scenario<F>(
|
|||||||
let ssz_block = SszBlock::from_slice(&ssz_bytes[..])
|
let ssz_block = SszBlock::from_slice(&ssz_bytes[..])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
validate_ssz_block(
|
let context = BlockValidationContext {
|
||||||
&ssz_block,
|
present_slot: validation_slot,
|
||||||
validation_slot,
|
cycle_length: params.cycle_length,
|
||||||
params.cycle_length,
|
last_justified_slot: validation_last_justified_slot,
|
||||||
validation_last_justified_slot,
|
parent_hashes: Arc::new(parent_hashes),
|
||||||
&Arc::new(parent_hashes),
|
proposer_map: Arc::new(proposer_map),
|
||||||
&Arc::new(proposer_map),
|
attester_map: Arc::new(attester_map),
|
||||||
&Arc::new(attester_map),
|
block_store: stores.block.clone(),
|
||||||
&stores.block.clone(),
|
validator_store: stores.validator.clone(),
|
||||||
&stores.validator.clone(),
|
pow_store: stores.pow_chain.clone()
|
||||||
&stores.pow_chain.clone())
|
};
|
||||||
|
context.validate_ssz_block(&ssz_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_simple_params() -> TestParams {
|
fn get_simple_params() -> TestParams {
|
||||||
|
@ -60,237 +60,256 @@ pub enum SszBlockValidationError {
|
|||||||
DatabaseError(String),
|
DatabaseError(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Validate some SszBlock. An SszBlock varies from a Block in that is a read-only structure
|
/// The context against which a block should be validated.
|
||||||
/// that reads directly from encoded SSZ.
|
pub struct BlockValidationContext<T>
|
||||||
///
|
|
||||||
/// The reason to validate an SzzBlock is to avoid decoding it in its entirety if there is
|
|
||||||
/// a suspicion that the block might be invalid. Such a suspicion should be applied to
|
|
||||||
/// all blocks coming from the network.
|
|
||||||
///
|
|
||||||
/// Of course, this function will only be more efficient if a block is already serialized.
|
|
||||||
/// Serializing a complete block and then validating with this function will be less
|
|
||||||
/// efficient than just validating the original block.
|
|
||||||
///
|
|
||||||
/// This function will determine if the block is new, already known or invalid (either
|
|
||||||
/// intrinsically or due to some application error.)
|
|
||||||
///
|
|
||||||
/// Note: this function does not implement randao_reveal checking as it is not in the
|
|
||||||
/// specification.
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn validate_ssz_block<T>(b: &SszBlock,
|
|
||||||
expected_slot: u64,
|
|
||||||
cycle_length: u8,
|
|
||||||
last_justified_slot: u64,
|
|
||||||
parent_hashes: &Arc<Vec<Hash256>>,
|
|
||||||
proposer_map: &Arc<ProposerMap>,
|
|
||||||
attester_map: &Arc<AttesterMap>,
|
|
||||||
block_store: &Arc<BlockStore<T>>,
|
|
||||||
validator_store: &Arc<ValidatorStore<T>>,
|
|
||||||
pow_store: &Arc<PoWChainStore<T>>)
|
|
||||||
-> Result<(BlockStatus, Option<Block>), SszBlockValidationError>
|
|
||||||
where T: ClientDB + Sized
|
where T: ClientDB + Sized
|
||||||
{
|
{
|
||||||
|
/// The slot as determined by the system time.
|
||||||
|
pub present_slot: u64,
|
||||||
|
/// The cycle_length as determined by the chain configuration.
|
||||||
|
pub cycle_length: u8,
|
||||||
|
/// The last justified slot as per the client's view of the canonical chain.
|
||||||
|
pub last_justified_slot: u64,
|
||||||
|
/// A vec of the hashes of the blocks preceeding the present slot.
|
||||||
|
pub parent_hashes: Arc<Vec<Hash256>>,
|
||||||
|
/// A map of slots to a block proposer validation index.
|
||||||
|
pub proposer_map: Arc<ProposerMap>,
|
||||||
|
/// A map of (slot, shard_id) to the attestation set of validation indices.
|
||||||
|
pub attester_map: Arc<AttesterMap>,
|
||||||
|
/// The store containing block information.
|
||||||
|
pub block_store: Arc<BlockStore<T>>,
|
||||||
|
/// The store containing validator information.
|
||||||
|
pub validator_store: Arc<ValidatorStore<T>>,
|
||||||
|
/// The store containing information about the proof-of-work chain.
|
||||||
|
pub pow_store: Arc<PoWChainStore<T>>,
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
impl<T> BlockValidationContext<T>
|
||||||
* If the block slot corresponds to a slot in the future (according to the local time),
|
where T: ClientDB
|
||||||
* drop it.
|
{
|
||||||
*/
|
/// Validate some SszBlock against a block validation context. An SszBlock varies from a Block in
|
||||||
let block_slot = b.slot_number();
|
/// that is a read-only structure that reads directly from encoded SSZ.
|
||||||
if block_slot > expected_slot {
|
///
|
||||||
return Err(SszBlockValidationError::FutureSlot);
|
/// The reason to validate an SzzBlock is to avoid decoding it in its entirety if there is
|
||||||
}
|
/// a suspicion that the block might be invalid. Such a suspicion should be applied to
|
||||||
|
/// all blocks coming from the network.
|
||||||
|
///
|
||||||
|
/// Of course, this function will only be more efficient if a block is already serialized.
|
||||||
|
/// Serializing a complete block and then validating with this function will be less
|
||||||
|
/// efficient than just validating the original block.
|
||||||
|
///
|
||||||
|
/// This function will determine if the block is new, already known or invalid (either
|
||||||
|
/// intrinsically or due to some application error.)
|
||||||
|
///
|
||||||
|
/// Note: this function does not implement randao_reveal checking as it is not in the
|
||||||
|
/// specification.
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn validate_ssz_block(&self, b: &SszBlock)
|
||||||
|
-> Result<(BlockStatus, Option<Block>), SszBlockValidationError>
|
||||||
|
where T: ClientDB + Sized
|
||||||
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If this block is already known, return immediately.
|
* If the block slot corresponds to a slot in the future (according to the local time),
|
||||||
*/
|
* drop it.
|
||||||
let block_hash = &b.block_hash();
|
*/
|
||||||
if block_store.block_exists(&block_hash)? {
|
let block_slot = b.slot_number();
|
||||||
return Ok((BlockStatus::KnownBlock, None));
|
if block_slot > self.present_slot {
|
||||||
}
|
return Err(SszBlockValidationError::FutureSlot);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If this block is already known, return immediately.
|
||||||
|
*/
|
||||||
|
let block_hash = &b.block_hash();
|
||||||
|
if self.block_store.block_exists(&block_hash)? {
|
||||||
|
return Ok((BlockStatus::KnownBlock, None));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the PoW chain hash is not known to us, drop it.
|
* If the PoW chain hash is not known to us, drop it.
|
||||||
*
|
*
|
||||||
* We only accept blocks that reference a known PoW hash.
|
* We only accept blocks that reference a known PoW hash.
|
||||||
*
|
*
|
||||||
* Note: it is not clear what a "known" PoW chain ref is. Likely,
|
* Note: it is not clear what a "known" PoW chain ref is. Likely,
|
||||||
* it means "sufficienty deep in the canonical PoW chain".
|
* it means "sufficienty deep in the canonical PoW chain".
|
||||||
*/
|
*/
|
||||||
let pow_chain_ref = b.pow_chain_ref();
|
let pow_chain_ref = b.pow_chain_ref();
|
||||||
if !pow_store.block_hash_exists(b.pow_chain_ref())? {
|
if !self.pow_store.block_hash_exists(b.pow_chain_ref())? {
|
||||||
return Err(SszBlockValidationError::UnknownPoWChainRef);
|
return Err(SszBlockValidationError::UnknownPoWChainRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Store a reference to the serialized attestations from the block.
|
* Store a reference to the serialized attestations from the block.
|
||||||
*/
|
*/
|
||||||
let attestations_ssz = &b.attestations();
|
let attestations_ssz = &b.attestations();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get a slice of the first serialized attestation (the 0th) and decode it into
|
* Get a slice of the first serialized attestation (the 0th) and decode it into
|
||||||
* a full AttestationRecord object.
|
* a full AttestationRecord object.
|
||||||
*/
|
*/
|
||||||
let (first_attestation_ssz, next_index) = split_one_attestation(
|
let (first_attestation_ssz, next_index) = split_one_attestation(
|
||||||
&attestations_ssz,
|
&attestations_ssz,
|
||||||
0)?;
|
0)?;
|
||||||
let (first_attestation, _) = AttestationRecord::ssz_decode(
|
let (first_attestation, _) = AttestationRecord::ssz_decode(
|
||||||
&first_attestation_ssz, 0)?;
|
&first_attestation_ssz, 0)?;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Validate this first attestation.
|
* Validate this first attestation.
|
||||||
*
|
*
|
||||||
* It is a requirement that the block proposer for this slot
|
* It is a requirement that the block proposer for this slot
|
||||||
* must have signed the 0th attestation record.
|
* must have signed the 0th attestation record.
|
||||||
*/
|
*/
|
||||||
let attestation_voters = validate_attestation(
|
let attestation_voters = validate_attestation(
|
||||||
&first_attestation,
|
&first_attestation,
|
||||||
block_slot,
|
block_slot,
|
||||||
cycle_length,
|
self.cycle_length,
|
||||||
last_justified_slot,
|
self.last_justified_slot,
|
||||||
&parent_hashes,
|
&self.parent_hashes,
|
||||||
&block_store,
|
&self.block_store,
|
||||||
&validator_store,
|
&self.validator_store,
|
||||||
&attester_map)?;
|
&self.attester_map)?;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the set of voters is None, the attestation was invalid.
|
* If the set of voters is None, the attestation was invalid.
|
||||||
*/
|
*/
|
||||||
let attestation_voters = attestation_voters
|
let attestation_voters = attestation_voters
|
||||||
.ok_or(SszBlockValidationError::
|
.ok_or(SszBlockValidationError::
|
||||||
FirstAttestationSignatureFailed)?;
|
FirstAttestationSignatureFailed)?;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read the proposer from the map of slot -> validator index.
|
* Read the proposer from the map of slot -> validator index.
|
||||||
*/
|
*/
|
||||||
let proposer = proposer_map.get(&block_slot)
|
let proposer = self.proposer_map.get(&block_slot)
|
||||||
.ok_or(SszBlockValidationError::BadProposerMap)?;
|
.ok_or(SszBlockValidationError::BadProposerMap)?;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the proposer for this slot was not a voter, reject the block.
|
* If the proposer for this slot was not a voter, reject the block.
|
||||||
*/
|
*/
|
||||||
if !attestation_voters.contains(&proposer) {
|
if !attestation_voters.contains(&proposer) {
|
||||||
return Err(SszBlockValidationError::NoProposerSignature);
|
return Err(SszBlockValidationError::NoProposerSignature);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Split the remaining attestations into a vector of slices, each containing
|
* Split the remaining attestations into a vector of slices, each containing
|
||||||
* a single serialized attestation record.
|
* a single serialized attestation record.
|
||||||
*/
|
*/
|
||||||
let other_attestations = split_all_attestations(attestations_ssz,
|
let other_attestations = split_all_attestations(attestations_ssz,
|
||||||
next_index)?;
|
next_index)?;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Verify each other AttestationRecord.
|
* Verify each other AttestationRecord.
|
||||||
*
|
*
|
||||||
* This uses the `rayon` library to do "sometimes" parallelization. Put simply,
|
* This uses the `rayon` library to do "sometimes" parallelization. Put simply,
|
||||||
* if there are some spare threads, the verification of attestation records will happen
|
* if there are some spare threads, the verification of attestation records will happen
|
||||||
* concurrently.
|
* concurrently.
|
||||||
*
|
*
|
||||||
* There is a thread-safe `failure` variable which is set whenever an attestation fails
|
* There is a thread-safe `failure` variable which is set whenever an attestation fails
|
||||||
* validation. This is so all attestation validation is halted if a single bad attestation
|
* validation. This is so all attestation validation is halted if a single bad attestation
|
||||||
* is found.
|
* is found.
|
||||||
*/
|
*/
|
||||||
let failure: RwLock<Option<SszBlockValidationError>> = RwLock::new(None);
|
let failure: RwLock<Option<SszBlockValidationError>> = RwLock::new(None);
|
||||||
let deserialized_attestations: Vec<AttestationRecord> = other_attestations
|
let deserialized_attestations: Vec<AttestationRecord> = other_attestations
|
||||||
.par_iter()
|
.par_iter()
|
||||||
.filter_map(|attestation_ssz| {
|
.filter_map(|attestation_ssz| {
|
||||||
/*
|
|
||||||
* If some thread has set the `failure` variable to `Some(error)` the abandon
|
|
||||||
* attestation serialization and validation.
|
|
||||||
*/
|
|
||||||
if let Some(_) = *failure.read().unwrap() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* If there has not been a failure yet, attempt to serialize and validate the
|
|
||||||
* attestation.
|
|
||||||
*/
|
|
||||||
match AttestationRecord::ssz_decode(&attestation_ssz, 0) {
|
|
||||||
/*
|
/*
|
||||||
* Deserialization failed, therefore the block is invalid.
|
* If some thread has set the `failure` variable to `Some(error)` the abandon
|
||||||
|
* attestation serialization and validation.
|
||||||
*/
|
*/
|
||||||
Err(e) => {
|
if let Some(_) = *failure.read().unwrap() {
|
||||||
let mut failure = failure.write().unwrap();
|
return None;
|
||||||
*failure = Some(SszBlockValidationError::from(e));
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Deserialization succeeded and the attestation should be validated.
|
* If there has not been a failure yet, attempt to serialize and validate the
|
||||||
|
* attestation.
|
||||||
*/
|
*/
|
||||||
Ok((attestation, _)) => {
|
match AttestationRecord::ssz_decode(&attestation_ssz, 0) {
|
||||||
let result = validate_attestation(
|
/*
|
||||||
&attestation,
|
* Deserialization failed, therefore the block is invalid.
|
||||||
block_slot,
|
*/
|
||||||
cycle_length,
|
Err(e) => {
|
||||||
last_justified_slot,
|
let mut failure = failure.write().unwrap();
|
||||||
&parent_hashes,
|
*failure = Some(SszBlockValidationError::from(e));
|
||||||
&block_store,
|
None
|
||||||
&validator_store,
|
}
|
||||||
&attester_map);
|
/*
|
||||||
match result {
|
* Deserialization succeeded and the attestation should be validated.
|
||||||
/*
|
*/
|
||||||
* Attestation validation failed with some error.
|
Ok((attestation, _)) => {
|
||||||
*/
|
let result = validate_attestation(
|
||||||
Err(e) => {
|
&attestation,
|
||||||
let mut failure = failure.write().unwrap();
|
block_slot,
|
||||||
*failure = Some(SszBlockValidationError::from(e));
|
self.cycle_length,
|
||||||
None
|
self.last_justified_slot,
|
||||||
|
&self.parent_hashes,
|
||||||
|
&self.block_store,
|
||||||
|
&self.validator_store,
|
||||||
|
&self.attester_map);
|
||||||
|
match result {
|
||||||
|
/*
|
||||||
|
* Attestation validation failed with some error.
|
||||||
|
*/
|
||||||
|
Err(e) => {
|
||||||
|
let mut failure = failure.write().unwrap();
|
||||||
|
*failure = Some(SszBlockValidationError::from(e));
|
||||||
|
None
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Attestation validation failed due to a bad signature.
|
||||||
|
*/
|
||||||
|
Ok(None) => {
|
||||||
|
let mut failure = failure.write().unwrap();
|
||||||
|
*failure = Some(SszBlockValidationError::AttestationSignatureFailed);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Attestation validation succeded.
|
||||||
|
*/
|
||||||
|
Ok(_) => Some(attestation)
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* Attestation validation failed due to a bad signature.
|
|
||||||
*/
|
|
||||||
Ok(None) => {
|
|
||||||
let mut failure = failure.write().unwrap();
|
|
||||||
*failure = Some(SszBlockValidationError::AttestationSignatureFailed);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Attestation validation succeded.
|
|
||||||
*/
|
|
||||||
Ok(_) => Some(attestation)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
})
|
.collect();
|
||||||
.collect();
|
|
||||||
|
|
||||||
match failure.into_inner() {
|
match failure.into_inner() {
|
||||||
Err(_) => return Err(SszBlockValidationError::RwLockPoisoned),
|
Err(_) => return Err(SszBlockValidationError::RwLockPoisoned),
|
||||||
Ok(failure) => {
|
Ok(failure) => {
|
||||||
match failure {
|
match failure {
|
||||||
Some(error) => return Err(error),
|
Some(error) => return Err(error),
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we have reached this point, the block is a new valid block that is worthy of
|
||||||
|
* processing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the block's parent_hash _is_ in the canonical chain, the block is a
|
||||||
|
* new block in the canonical chain. Otherwise, it's a new block in a fork chain.
|
||||||
|
*/
|
||||||
|
let parent_hash = b.parent_hash();
|
||||||
|
let status = if self.block_store.block_exists_in_canonical_chain(&parent_hash)? {
|
||||||
|
BlockStatus::NewBlockInCanonicalChain
|
||||||
|
} else {
|
||||||
|
BlockStatus::NewBlockInForkChain
|
||||||
|
};
|
||||||
|
let block = Block {
|
||||||
|
parent_hash: Hash256::from(parent_hash),
|
||||||
|
slot_number: block_slot,
|
||||||
|
randao_reveal: Hash256::from(b.randao_reveal()),
|
||||||
|
attestations: deserialized_attestations,
|
||||||
|
pow_chain_ref: Hash256::from(pow_chain_ref),
|
||||||
|
active_state_root: Hash256::from(b.act_state_root()),
|
||||||
|
crystallized_state_root: Hash256::from(b.cry_state_root()),
|
||||||
|
};
|
||||||
|
Ok((status, Some(block)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* If we have reached this point, the block is a new valid block that is worthy of
|
|
||||||
* processing.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the block's parent_hash _is_ in the canonical chain, the block is a
|
|
||||||
* new block in the canonical chain. Otherwise, it's a new block in a fork chain.
|
|
||||||
*/
|
|
||||||
let parent_hash = b.parent_hash();
|
|
||||||
let status = if block_store.block_exists_in_canonical_chain(&parent_hash)? {
|
|
||||||
BlockStatus::NewBlockInCanonicalChain
|
|
||||||
} else {
|
|
||||||
BlockStatus::NewBlockInForkChain
|
|
||||||
};
|
|
||||||
let block = Block {
|
|
||||||
parent_hash: Hash256::from(parent_hash),
|
|
||||||
slot_number: block_slot,
|
|
||||||
randao_reveal: Hash256::from(b.randao_reveal()),
|
|
||||||
attestations: deserialized_attestations,
|
|
||||||
pow_chain_ref: Hash256::from(pow_chain_ref),
|
|
||||||
active_state_root: Hash256::from(b.act_state_root()),
|
|
||||||
crystallized_state_root: Hash256::from(b.cry_state_root()),
|
|
||||||
};
|
|
||||||
Ok((status, Some(block)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<DBError> for SszBlockValidationError {
|
impl From<DBError> for SszBlockValidationError {
|
||||||
|
Loading…
Reference in New Issue
Block a user