Progress on block validation
This commit is contained in:
parent
2141b8c623
commit
1677b6dcc8
@ -61,7 +61,7 @@ impl Decodable for AttestationRecord {
|
|||||||
// Do aggregate sig decoding properly.
|
// Do aggregate sig decoding properly.
|
||||||
let (agg_sig_bytes, i) = decode_ssz_list(bytes, i)?;
|
let (agg_sig_bytes, i) = decode_ssz_list(bytes, i)?;
|
||||||
let aggregate_sig = AggregateSignature::from_bytes(&agg_sig_bytes)
|
let aggregate_sig = AggregateSignature::from_bytes(&agg_sig_bytes)
|
||||||
.map_err(|_| DecodeError::OutOfBounds)?;
|
.map_err(|_| DecodeError::TooShort)?; // also could be TooLong
|
||||||
|
|
||||||
let attestation_record = Self {
|
let attestation_record = Self {
|
||||||
slot,
|
slot,
|
||||||
|
@ -11,7 +11,7 @@ pub use self::attestation_record::{
|
|||||||
MIN_SSZ_ATTESTION_RECORD_LENGTH,
|
MIN_SSZ_ATTESTION_RECORD_LENGTH,
|
||||||
};
|
};
|
||||||
pub use self::ssz_splitter::{
|
pub use self::ssz_splitter::{
|
||||||
split_all,
|
split_all_attestations,
|
||||||
split_one,
|
split_one_attestation,
|
||||||
AttestationSplitError,
|
AttestationSplitError,
|
||||||
};
|
};
|
||||||
|
@ -9,13 +9,13 @@ pub enum AttestationSplitError {
|
|||||||
|
|
||||||
/// Given some ssz slice, find the bounds of each serialized AttestationRecord and return a vec of
|
/// Given some ssz slice, find the bounds of each serialized AttestationRecord and return a vec of
|
||||||
/// slices point to each.
|
/// slices point to each.
|
||||||
pub fn split_all<'a>(full_ssz: &'a [u8], index: usize)
|
pub fn split_all_attestations<'a>(full_ssz: &'a [u8], index: usize)
|
||||||
-> Result<Vec<&'a [u8]>, AttestationSplitError>
|
-> Result<Vec<&'a [u8]>, AttestationSplitError>
|
||||||
{
|
{
|
||||||
let mut v = vec![];
|
let mut v = vec![];
|
||||||
let mut index = index;
|
let mut index = index;
|
||||||
while index < full_ssz.len() - 1 {
|
while index < full_ssz.len() - 1 {
|
||||||
let (slice, i) = split_one(full_ssz, index)?;
|
let (slice, i) = split_one_attestation(full_ssz, index)?;
|
||||||
v.push(slice);
|
v.push(slice);
|
||||||
index = i;
|
index = i;
|
||||||
}
|
}
|
||||||
@ -24,27 +24,27 @@ pub fn split_all<'a>(full_ssz: &'a [u8], index: usize)
|
|||||||
|
|
||||||
/// Given some ssz slice, find the bounds of one serialized AttestationRecord
|
/// Given some ssz slice, find the bounds of one serialized AttestationRecord
|
||||||
/// and return a slice pointing to that.
|
/// and return a slice pointing to that.
|
||||||
pub fn split_one<'a>(full_ssz: &'a [u8], index: usize)
|
pub fn split_one_attestation<'a>(full_ssz: &'a [u8], index: usize)
|
||||||
-> Result<(&'a [u8], usize), AttestationSplitError>
|
-> Result<(&'a [u8], usize), AttestationSplitError>
|
||||||
{
|
{
|
||||||
if full_ssz.len() < MIN_LENGTH {
|
if full_ssz.len() < MIN_LENGTH {
|
||||||
return Err(AttestationSplitError::TooShort);
|
return Err(AttestationSplitError::TooShort);
|
||||||
}
|
}
|
||||||
|
|
||||||
let hashes_len = decode_length(full_ssz, 10, LENGTH_BYTES)
|
let hashes_len = decode_length(full_ssz, index + 10, LENGTH_BYTES)
|
||||||
.map_err(|_| AttestationSplitError::TooShort)?;
|
.map_err(|_| AttestationSplitError::TooShort)?;
|
||||||
|
|
||||||
let bitfield_len = decode_length(
|
let bitfield_len = decode_length(
|
||||||
full_ssz, hashes_len + 46,
|
full_ssz, index + hashes_len + 46,
|
||||||
LENGTH_BYTES)
|
LENGTH_BYTES)
|
||||||
.map_err(|_| AttestationSplitError::TooShort)?;
|
.map_err(|_| AttestationSplitError::TooShort)?;
|
||||||
|
|
||||||
// Subtract one because the min length assume 1 byte of bitfield
|
// Subtract one because the min length assumes 1 byte of bitfield
|
||||||
let len = MIN_LENGTH
|
let len = MIN_LENGTH - 1
|
||||||
+ hashes_len
|
+ hashes_len
|
||||||
+ bitfield_len.saturating_sub(1);
|
+ bitfield_len;
|
||||||
|
|
||||||
if full_ssz.len() < len {
|
if index + full_ssz.len() < len {
|
||||||
return Err(AttestationSplitError::TooShort);
|
return Err(AttestationSplitError::TooShort);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,7 +102,7 @@ mod tests {
|
|||||||
let mut ssz_stream = SszStream::new();
|
let mut ssz_stream = SszStream::new();
|
||||||
ssz_stream.append(&a);
|
ssz_stream.append(&a);
|
||||||
let ssz = ssz_stream.drain();
|
let ssz = ssz_stream.drain();
|
||||||
let (a_ssz, i) = split_one(&ssz, 0).unwrap();
|
let (a_ssz, i) = split_one_attestation(&ssz, 0).unwrap();
|
||||||
assert_eq!(i, ssz.len());
|
assert_eq!(i, ssz.len());
|
||||||
let (decoded_a, _) = AttestationRecord::ssz_decode(a_ssz, 0)
|
let (decoded_a, _) = AttestationRecord::ssz_decode(a_ssz, 0)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -115,7 +115,7 @@ mod tests {
|
|||||||
ssz_stream.append(&a);
|
ssz_stream.append(&a);
|
||||||
ssz_stream.append(&b);
|
ssz_stream.append(&b);
|
||||||
let ssz = ssz_stream.drain();
|
let ssz = ssz_stream.drain();
|
||||||
let ssz_vec = split_all(&ssz, 0).unwrap();
|
let ssz_vec = split_all_attestations(&ssz, 0).unwrap();
|
||||||
let (decoded_a, _) =
|
let (decoded_a, _) =
|
||||||
AttestationRecord::ssz_decode(ssz_vec[0], 0)
|
AttestationRecord::ssz_decode(ssz_vec[0], 0)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -133,7 +133,7 @@ mod tests {
|
|||||||
ssz_stream.append(&b);
|
ssz_stream.append(&b);
|
||||||
let ssz = ssz_stream.drain();
|
let ssz = ssz_stream.drain();
|
||||||
let ssz = &ssz[0..ssz.len() - 1];
|
let ssz = &ssz[0..ssz.len() - 1];
|
||||||
assert!(split_all(&ssz, 0).is_err());
|
assert!(split_all_attestations(&ssz, 0).is_err());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use super::AttestationRecord;
|
use super::attestation_record::AttestationRecord;
|
||||||
use super::attestation_parent_hashes::{
|
use super::attestation_parent_hashes::{
|
||||||
attestation_parent_hashes,
|
attestation_parent_hashes,
|
||||||
ParentHashesError,
|
ParentHashesError,
|
||||||
};
|
};
|
||||||
|
use super::AttesterMap;
|
||||||
use super::db::{
|
use super::db::{
|
||||||
ClientDB,
|
ClientDB,
|
||||||
DBError
|
DBError
|
||||||
@ -17,7 +18,6 @@ use super::utils::hash::canonical_hash;
|
|||||||
use super::utils::types::{
|
use super::utils::types::{
|
||||||
Hash256,
|
Hash256,
|
||||||
};
|
};
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use super::signatures::{
|
use super::signatures::{
|
||||||
verify_aggregate_signature_for_indices,
|
verify_aggregate_signature_for_indices,
|
||||||
@ -44,10 +44,6 @@ pub enum AttestationValidationError {
|
|||||||
DBError(String),
|
DBError(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
type Slot = u64;
|
|
||||||
type ShardId = u64;
|
|
||||||
type AttesterMap = HashMap<(Slot, ShardId), Vec<usize>>;
|
|
||||||
|
|
||||||
fn bytes_for_bits(bits: usize) -> usize {
|
fn bytes_for_bits(bits: usize) -> usize {
|
||||||
(bits.saturating_sub(1) / 8) + 1
|
(bits.saturating_sub(1) / 8) + 1
|
||||||
}
|
}
|
||||||
@ -62,12 +58,14 @@ pub fn validate_attestation<T>(a: &AttestationRecord,
|
|||||||
cycle_length: u8,
|
cycle_length: u8,
|
||||||
known_last_justified_slot: u64,
|
known_last_justified_slot: u64,
|
||||||
known_parent_hashes: Arc<Vec<Hash256>>,
|
known_parent_hashes: Arc<Vec<Hash256>>,
|
||||||
block_store: BlockStore<T>,
|
block_store: Arc<BlockStore<T>>,
|
||||||
validator_store: ValidatorStore<T>,
|
validator_store: Arc<ValidatorStore<T>>,
|
||||||
attester_map: Arc<AttesterMap>)
|
attester_map: Arc<AttesterMap>)
|
||||||
-> Result<(bool, Option<HashSet<usize>>), AttestationValidationError>
|
-> Result<Option<HashSet<usize>>, AttestationValidationError>
|
||||||
where T: ClientDB + Sized
|
where T: ClientDB + Sized
|
||||||
{
|
{
|
||||||
|
// TODO: assert attestion isn't already known
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The attesation slot must not be higher than the block that contained it.
|
* The attesation slot must not be higher than the block that contained it.
|
||||||
*/
|
*/
|
||||||
@ -156,7 +154,7 @@ pub fn validate_attestation<T>(a: &AttestationRecord,
|
|||||||
a.justified_slot)
|
a.justified_slot)
|
||||||
};
|
};
|
||||||
|
|
||||||
let (signature_valid, voted_hashmap) =
|
let voted_hashmap =
|
||||||
verify_aggregate_signature_for_indices(
|
verify_aggregate_signature_for_indices(
|
||||||
&signed_message,
|
&signed_message,
|
||||||
&a.aggregate_sig,
|
&a.aggregate_sig,
|
||||||
@ -164,7 +162,7 @@ pub fn validate_attestation<T>(a: &AttestationRecord,
|
|||||||
&a.attester_bitfield,
|
&a.attester_bitfield,
|
||||||
&validator_store)?;
|
&validator_store)?;
|
||||||
|
|
||||||
Ok((signature_valid, voted_hashmap))
|
Ok(voted_hashmap)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates the message used to validate the signature provided with an AttestationRecord.
|
/// Generates the message used to validate the signature provided with an AttestationRecord.
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
use super::AttesterMap;
|
||||||
use super::db;
|
use super::db;
|
||||||
use super::bls;
|
use super::bls;
|
||||||
use super::AttestationRecord;
|
use super::attestation_record;
|
||||||
use super::ssz;
|
use super::ssz;
|
||||||
use super::attestation_parent_hashes;
|
use super::attestation_parent_hashes;
|
||||||
use super::utils;
|
use super::utils;
|
||||||
@ -8,4 +9,7 @@ use super::utils;
|
|||||||
mod attestation_validation;
|
mod attestation_validation;
|
||||||
mod signatures;
|
mod signatures;
|
||||||
|
|
||||||
pub use self::attestation_validation::validate_attestation;
|
pub use self::attestation_validation::{
|
||||||
|
validate_attestation,
|
||||||
|
AttestationValidationError,
|
||||||
|
};
|
||||||
|
@ -24,7 +24,7 @@ pub fn verify_aggregate_signature_for_indices<T>(
|
|||||||
attestation_indices: &[usize],
|
attestation_indices: &[usize],
|
||||||
bitfield: &Bitfield,
|
bitfield: &Bitfield,
|
||||||
validator_store: &ValidatorStore<T>)
|
validator_store: &ValidatorStore<T>)
|
||||||
-> Result<(bool, Option<HashSet<usize>>), SignatureVerificationError>
|
-> Result<Option<HashSet<usize>>, SignatureVerificationError>
|
||||||
where T: ClientDB + Sized
|
where T: ClientDB + Sized
|
||||||
{
|
{
|
||||||
let mut voters = HashSet::new();
|
let mut voters = HashSet::new();
|
||||||
@ -41,9 +41,9 @@ pub fn verify_aggregate_signature_for_indices<T>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if agg_sig.verify(&message, &agg_pub_key) {
|
if agg_sig.verify(&message, &agg_pub_key) {
|
||||||
Ok((true, Some(voters)))
|
Ok(Some(voters))
|
||||||
} else {
|
} else {
|
||||||
Ok((false, None))
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +126,7 @@ mod tests {
|
|||||||
/*
|
/*
|
||||||
* Test using all valid parameters.
|
* Test using all valid parameters.
|
||||||
*/
|
*/
|
||||||
let (is_valid, voters) = verify_aggregate_signature_for_indices(
|
let voters = verify_aggregate_signature_for_indices(
|
||||||
&message,
|
&message,
|
||||||
&agg_sig,
|
&agg_sig,
|
||||||
&attestation_indices,
|
&attestation_indices,
|
||||||
@ -134,7 +134,6 @@ mod tests {
|
|||||||
&store).unwrap();
|
&store).unwrap();
|
||||||
|
|
||||||
let voters = voters.unwrap();
|
let voters = voters.unwrap();
|
||||||
assert_eq!(is_valid, true);
|
|
||||||
(0..signing_keypairs.len())
|
(0..signing_keypairs.len())
|
||||||
.for_each(|i| assert!(voters.contains(&i)));
|
.for_each(|i| assert!(voters.contains(&i)));
|
||||||
(signing_keypairs.len()..non_signing_keypairs.len())
|
(signing_keypairs.len()..non_signing_keypairs.len())
|
||||||
@ -145,14 +144,13 @@ mod tests {
|
|||||||
* parameters the same and assert that it fails.
|
* parameters the same and assert that it fails.
|
||||||
*/
|
*/
|
||||||
bitfield.set_bit(signing_keypairs.len() + 1, true);
|
bitfield.set_bit(signing_keypairs.len() + 1, true);
|
||||||
let (is_valid, voters) = verify_aggregate_signature_for_indices(
|
let voters = verify_aggregate_signature_for_indices(
|
||||||
&message,
|
&message,
|
||||||
&agg_sig,
|
&agg_sig,
|
||||||
&attestation_indices,
|
&attestation_indices,
|
||||||
&bitfield,
|
&bitfield,
|
||||||
&store).unwrap();
|
&store).unwrap();
|
||||||
|
|
||||||
assert_eq!(is_valid, false);
|
|
||||||
assert_eq!(voters, None);
|
assert_eq!(voters, None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,17 @@
|
|||||||
/*
|
use std::collections::HashMap;
|
||||||
use super::crystallized_state::CrystallizedState;
|
|
||||||
use super::active_state::ActiveState;
|
|
||||||
use super::attestation_record::AttestationRecord;
|
|
||||||
use super::block::Block;
|
|
||||||
use super::chain_config::ChainConfig;
|
|
||||||
*/
|
|
||||||
use super::block;
|
use super::block;
|
||||||
use super::bls;
|
use super::bls;
|
||||||
use super::Logger;
|
use super::Logger;
|
||||||
use super::db;
|
use super::db;
|
||||||
use super::attestation_record::AttestationRecord;
|
use super::attestation_record;
|
||||||
use super::ssz;
|
use super::ssz;
|
||||||
use super::transition::attestation_parent_hashes;
|
use super::transition::attestation_parent_hashes;
|
||||||
use super::utils;
|
use super::utils;
|
||||||
|
|
||||||
mod attestation;
|
mod attestation;
|
||||||
mod ssz_block;
|
mod ssz_block;
|
||||||
|
|
||||||
|
type Slot = u64;
|
||||||
|
type ShardId = u64;
|
||||||
|
type AttesterMap = HashMap<(Slot, ShardId), Vec<usize>>;
|
||||||
|
type ProposerMap = HashMap<Slot, usize>;
|
||||||
|
@ -1,14 +1,34 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
use super::attestation::{
|
||||||
|
validate_attestation,
|
||||||
|
AttestationValidationError,
|
||||||
|
};
|
||||||
|
use super::attestation_record::{
|
||||||
|
AttestationRecord,
|
||||||
|
split_one_attestation,
|
||||||
|
split_all_attestations,
|
||||||
|
AttestationSplitError,
|
||||||
|
};
|
||||||
|
use super::{
|
||||||
|
AttesterMap,
|
||||||
|
ProposerMap,
|
||||||
|
};
|
||||||
use super::block::SszBlock;
|
use super::block::SszBlock;
|
||||||
use super::Logger;
|
|
||||||
use super::db::{
|
use super::db::{
|
||||||
ClientDB,
|
ClientDB,
|
||||||
DBError,
|
DBError,
|
||||||
};
|
};
|
||||||
|
use super::Logger;
|
||||||
use super::db::stores::{
|
use super::db::stores::{
|
||||||
BlockStore,
|
BlockStore,
|
||||||
PoWChainStore,
|
PoWChainStore,
|
||||||
ValidatorStore,
|
ValidatorStore,
|
||||||
};
|
};
|
||||||
|
use super::ssz::{
|
||||||
|
Decodable,
|
||||||
|
DecodeError,
|
||||||
|
};
|
||||||
|
use super::utils::types::Hash256;
|
||||||
|
|
||||||
pub enum BlockStatus {
|
pub enum BlockStatus {
|
||||||
NewBlock,
|
NewBlock,
|
||||||
@ -18,21 +38,25 @@ pub enum BlockStatus {
|
|||||||
pub enum SszBlockValidationError {
|
pub enum SszBlockValidationError {
|
||||||
FutureSlot,
|
FutureSlot,
|
||||||
UnknownPoWChainRef,
|
UnknownPoWChainRef,
|
||||||
|
BadAttestationSsz,
|
||||||
|
AttestationValidationError(AttestationValidationError),
|
||||||
|
InvalidAttestation,
|
||||||
|
NoProposerSignature,
|
||||||
|
BadProposerMap,
|
||||||
DatabaseError(String),
|
DatabaseError(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<DBError> for SszBlockValidationError {
|
|
||||||
fn from(e: DBError) -> SszBlockValidationError {
|
|
||||||
SszBlockValidationError::DatabaseError(e.message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn validate_ssz_block<T>(b: &SszBlock,
|
pub fn validate_ssz_block<T>(b: &SszBlock,
|
||||||
expected_slot: u64,
|
expected_slot: u64,
|
||||||
block_store: &BlockStore<T>,
|
|
||||||
pow_store: &PoWChainStore<T>,
|
pow_store: &PoWChainStore<T>,
|
||||||
_validator_store: &ValidatorStore<T>,
|
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>>,
|
||||||
_log: &Logger)
|
_log: &Logger)
|
||||||
-> Result<BlockStatus, SszBlockValidationError>
|
-> Result<BlockStatus, SszBlockValidationError>
|
||||||
where T: ClientDB + Sized
|
where T: ClientDB + Sized
|
||||||
@ -41,7 +65,8 @@ pub fn validate_ssz_block<T>(b: &SszBlock,
|
|||||||
return Ok(BlockStatus::KnownBlock);
|
return Ok(BlockStatus::KnownBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.slot_number() > expected_slot {
|
let block_slot = b.slot_number();
|
||||||
|
if block_slot > expected_slot {
|
||||||
return Err(SszBlockValidationError::FutureSlot);
|
return Err(SszBlockValidationError::FutureSlot);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,6 +74,84 @@ pub fn validate_ssz_block<T>(b: &SszBlock,
|
|||||||
return Err(SszBlockValidationError::UnknownPoWChainRef);
|
return Err(SszBlockValidationError::UnknownPoWChainRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do validation here
|
let attestations_ssz = &b.attestations();
|
||||||
|
|
||||||
|
let (first_attestation_ssz, next_index) = split_one_attestation(
|
||||||
|
&attestations_ssz,
|
||||||
|
0)?;
|
||||||
|
let (first_attestation, _) = AttestationRecord::ssz_decode(
|
||||||
|
&first_attestation_ssz, 0)?;
|
||||||
|
|
||||||
|
let attestation_voters = validate_attestation(
|
||||||
|
&first_attestation,
|
||||||
|
block_slot,
|
||||||
|
cycle_length,
|
||||||
|
last_justified_slot,
|
||||||
|
parent_hashes.clone(),
|
||||||
|
block_store.clone(),
|
||||||
|
validator_store.clone(),
|
||||||
|
attester_map.clone())?;
|
||||||
|
|
||||||
|
let attestation_voters = attestation_voters
|
||||||
|
.ok_or(SszBlockValidationError::InvalidAttestation)?;
|
||||||
|
|
||||||
|
let proposer = proposer_map.get(&block_slot)
|
||||||
|
.ok_or(SszBlockValidationError::BadProposerMap)?;
|
||||||
|
|
||||||
|
if !attestation_voters.contains(&proposer) {
|
||||||
|
return Err(SszBlockValidationError::NoProposerSignature);
|
||||||
|
}
|
||||||
|
|
||||||
|
let other_attestations = split_all_attestations(attestations_ssz,
|
||||||
|
next_index)?;
|
||||||
|
|
||||||
|
for attestation in other_attestations {
|
||||||
|
let (a, _) = AttestationRecord::ssz_decode(&attestation, 0)?;
|
||||||
|
let attestation_voters = validate_attestation(
|
||||||
|
&a,
|
||||||
|
block_slot,
|
||||||
|
cycle_length,
|
||||||
|
last_justified_slot,
|
||||||
|
parent_hashes.clone(),
|
||||||
|
block_store.clone(),
|
||||||
|
validator_store.clone(),
|
||||||
|
attester_map.clone())?;
|
||||||
|
if attestation_voters.is_none() {
|
||||||
|
return Err(SszBlockValidationError::InvalidAttestation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(BlockStatus::NewBlock)
|
Ok(BlockStatus::NewBlock)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<DBError> for SszBlockValidationError {
|
||||||
|
fn from(e: DBError) -> Self {
|
||||||
|
SszBlockValidationError::DatabaseError(e.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<AttestationSplitError> for SszBlockValidationError {
|
||||||
|
fn from(e: AttestationSplitError) -> Self {
|
||||||
|
match e {
|
||||||
|
AttestationSplitError::TooShort =>
|
||||||
|
SszBlockValidationError::BadAttestationSsz
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<DecodeError> for SszBlockValidationError {
|
||||||
|
fn from(e: DecodeError) -> Self {
|
||||||
|
match e {
|
||||||
|
DecodeError::TooShort =>
|
||||||
|
SszBlockValidationError::BadAttestationSsz,
|
||||||
|
DecodeError::TooLong =>
|
||||||
|
SszBlockValidationError::BadAttestationSsz,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<AttestationValidationError> for SszBlockValidationError {
|
||||||
|
fn from(e: AttestationValidationError) -> Self {
|
||||||
|
SszBlockValidationError::AttestationValidationError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -4,7 +4,6 @@ use super::{
|
|||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum DecodeError {
|
pub enum DecodeError {
|
||||||
OutOfBounds,
|
|
||||||
TooShort,
|
TooShort,
|
||||||
TooLong,
|
TooLong,
|
||||||
}
|
}
|
||||||
@ -22,7 +21,7 @@ pub fn decode_ssz<T>(ssz_bytes: &[u8], index: usize)
|
|||||||
where T: Decodable
|
where T: Decodable
|
||||||
{
|
{
|
||||||
if index >= ssz_bytes.len() {
|
if index >= ssz_bytes.len() {
|
||||||
return Err(DecodeError::OutOfBounds)
|
return Err(DecodeError::TooShort)
|
||||||
}
|
}
|
||||||
T::ssz_decode(ssz_bytes, index)
|
T::ssz_decode(ssz_bytes, index)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user