openethereum/src/verification.rs

158 lines
3.7 KiB
Rust
Raw Normal View History

2016-01-09 19:10:05 +01:00
use util::*;
2016-01-09 10:16:35 +01:00
use header::Header;
use client::BlockNumber;
2016-01-09 19:10:05 +01:00
use engine::{Engine, VerificationMode};
use views::BlockView;
#[derive(Debug)]
pub struct VerificationError {
pub block: Option<Bytes>,
pub error: VerificationErrorOption,
}
impl VerificationError {
pub fn block(error: BlockVerificationError, block: Option<Bytes>) -> VerificationError {
VerificationError {
block: block,
error: VerificationErrorOption::Block(error),
}
}
pub fn transaction(error: TransactionVerificationError, block: Option<Bytes>) -> VerificationError {
VerificationError {
block: block,
error: VerificationErrorOption::Transaction(error),
}
}
}
#[derive(Debug)]
pub enum VerificationErrorOption {
Transaction(TransactionVerificationError),
Block(BlockVerificationError),
}
2016-01-09 10:16:35 +01:00
#[derive(Debug)]
pub enum TransactionVerificationError {
OutOfGasBase,
OutOfGasIntrinsic,
NotEnoughCash,
GasPriceTooLow,
BlockGasLimitReached,
FeeTooSmall,
TooMuchGasUsed {
used: U256,
limit: U256
},
InvalidSignature,
InvalidTransactionFormat,
}
#[derive(Debug)]
pub enum BlockVerificationError {
TooMuchGasUsed {
used: U256,
limit: U256,
},
InvalidBlockFormat,
2016-01-09 19:10:05 +01:00
ExtraDataTooBig {
required: U256,
got: U256,
},
2016-01-09 10:16:35 +01:00
InvalidUnclesHash {
2016-01-09 19:10:05 +01:00
required: H256,
2016-01-09 10:16:35 +01:00
got: H256,
},
TooManyUncles,
UncleTooOld,
UncleIsBrother,
UncleInChain,
UncleParentNotInChain,
InvalidStateRoot,
InvalidGasUsed,
InvalidTransactionsRoot {
2016-01-09 19:10:05 +01:00
required: H256,
2016-01-09 10:16:35 +01:00
got: H256,
},
2016-01-09 19:10:05 +01:00
InvalidDifficulty {
required: U256,
got: U256,
},
InvalidGasLimit {
min: U256,
max: U256,
got: U256,
},
2016-01-09 10:16:35 +01:00
InvalidReceiptsStateRoot,
InvalidTimestamp,
InvalidLogBloom,
InvalidNonce,
InvalidBlockHeaderItemCount,
InvalidBlockNonce,
InvalidParentHash,
InvalidUncleParentHash,
InvalidNumber,
BlockNotFound,
UnknownParent,
}
pub fn verify_header(header: &Header) -> Result<(), BlockVerificationError> {
if header.number > From::from(BlockNumber::max_value()) {
return Err(BlockVerificationError::InvalidNumber)
}
if header.gas_used > header.gas_limit {
return Err(BlockVerificationError::TooMuchGasUsed {
used: header.gas_used,
limit: header.gas_limit,
});
}
Ok(())
}
pub fn verify_parent(header: &Header, parent: &Header) -> Result<(), BlockVerificationError> {
if !header.parent_hash.is_zero() && parent.hash() != header.parent_hash {
return Err(BlockVerificationError::InvalidParentHash)
}
if header.timestamp <= parent.timestamp {
return Err(BlockVerificationError::InvalidTimestamp)
}
if header.number <= parent.number {
return Err(BlockVerificationError::InvalidNumber)
}
Ok(())
}
pub fn verify_block_integrity(block: &[u8], transactions_root: &H256, uncles_hash: &H256) -> Result<(), BlockVerificationError> {
let block = Rlp::new(block);
let tx = block.at(1);
let expected_root = ordered_trie_root(tx.iter().map(|r| r.as_raw().to_vec()).collect()); //TODO: get rid of vectors here
if &expected_root != transactions_root {
return Err(BlockVerificationError::InvalidTransactionsRoot {
2016-01-09 19:10:05 +01:00
required: expected_root.clone(),
2016-01-09 10:16:35 +01:00
got: transactions_root.clone(),
});
}
let expected_uncles = block.at(2).as_raw().sha3();
if &expected_uncles != uncles_hash {
return Err(BlockVerificationError::InvalidUnclesHash {
2016-01-09 19:10:05 +01:00
required: expected_uncles.clone(),
2016-01-09 10:16:35 +01:00
got: uncles_hash.clone(),
});
}
Ok(())
}
2016-01-09 19:10:05 +01:00
pub fn verify_block_basic(bytes: &[u8], parent: &Header, engine: &mut Engine) -> Result<(), BlockVerificationError> {
let block = BlockView::new(bytes);
let header = block.header();
try!(verify_header(&header));
try!(verify_parent(&header, parent));
try!(verify_block_integrity(bytes, &header.transactions_root, &header.uncles_hash));
Ok(())
}
pub fn verify_block_unordered(block: &[u8]) -> Result<(), BlockVerificationError> {
Ok(())
}