Started block verification
This commit is contained in:
parent
b272595183
commit
f1cdc0a17d
@ -1,10 +1,11 @@
|
||||
use std::sync::Arc;
|
||||
use std::path::Path;
|
||||
use util::uint::U256;
|
||||
use util::hash::*;
|
||||
use util::sha3::*;
|
||||
use util::rlp::*;
|
||||
use util::bytes::Bytes;
|
||||
use blockchain::BlockChain;
|
||||
use queue::BlockQueue;
|
||||
use views::BlockView;
|
||||
|
||||
/// Status for a block in a queue.
|
||||
@ -106,7 +107,7 @@ pub trait BlockChainClient : Sync {
|
||||
/// Get block queue information.
|
||||
fn queue_status(&self) -> BlockQueueStatus;
|
||||
|
||||
/// Clear block qeueu and abort all import activity.
|
||||
/// Clear block queue and abort all import activity.
|
||||
fn clear_queue(&mut self);
|
||||
|
||||
/// Get blockchain information.
|
||||
@ -115,13 +116,16 @@ pub trait BlockChainClient : Sync {
|
||||
|
||||
/// Blockchain database client backed by a persistent database. Owns and manages a blockchain and a block queue.
|
||||
pub struct Client {
|
||||
chain: BlockChain
|
||||
chain: Arc<BlockChain>,
|
||||
queue: BlockQueue,
|
||||
}
|
||||
|
||||
impl Client {
|
||||
pub fn new(genesis: &[u8], path: &Path) -> Client {
|
||||
let chain = Arc::new(BlockChain::new(genesis, path));
|
||||
Client {
|
||||
chain: BlockChain::new(genesis, path)
|
||||
chain: chain.clone(),
|
||||
queue: BlockQueue::new(chain)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -181,17 +185,7 @@ impl BlockChainClient for Client {
|
||||
}
|
||||
|
||||
fn import_block(&mut self, bytes: &[u8]) -> ImportResult {
|
||||
//TODO: verify block
|
||||
{
|
||||
let block = BlockView::new(bytes);
|
||||
let header = block.header_view();
|
||||
let hash = header.sha3();
|
||||
if self.chain.is_known(&hash) {
|
||||
return ImportResult::Bad;
|
||||
}
|
||||
}
|
||||
self.chain.insert_block(bytes);
|
||||
ImportResult::Queued(QueueStatus::Known)
|
||||
self.queue.import_block(bytes)
|
||||
}
|
||||
|
||||
fn queue_status(&self) -> BlockQueueStatus {
|
||||
@ -201,6 +195,7 @@ impl BlockChainClient for Client {
|
||||
}
|
||||
|
||||
fn clear_queue(&mut self) {
|
||||
self.queue.clear();
|
||||
}
|
||||
|
||||
fn chain_info(&self) -> BlockChainInfo {
|
||||
|
@ -105,6 +105,7 @@ pub mod views;
|
||||
pub mod blockchain;
|
||||
pub mod extras;
|
||||
pub mod client;
|
||||
|
||||
pub mod sync;
|
||||
pub mod verification;
|
||||
pub mod queue;
|
||||
|
||||
|
37
src/queue.rs
Normal file
37
src/queue.rs
Normal file
@ -0,0 +1,37 @@
|
||||
use std::sync::Arc;
|
||||
//use util::bytes::*;
|
||||
use util::sha3::*;
|
||||
use blockchain::BlockChain;
|
||||
use client::{QueueStatus, ImportResult};
|
||||
use views::{BlockView};
|
||||
|
||||
|
||||
pub struct BlockQueue {
|
||||
chain: Arc<BlockChain>
|
||||
}
|
||||
|
||||
impl BlockQueue {
|
||||
pub fn new(chain: Arc<BlockChain>) -> BlockQueue {
|
||||
BlockQueue {
|
||||
chain: chain
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
}
|
||||
|
||||
pub fn import_block(&mut self, bytes: &[u8]) -> ImportResult {
|
||||
//TODO: verify block
|
||||
{
|
||||
let block = BlockView::new(bytes);
|
||||
let header = block.header_view();
|
||||
let hash = header.sha3();
|
||||
if self.chain.is_known(&hash) {
|
||||
return ImportResult::Bad;
|
||||
}
|
||||
}
|
||||
self.chain.insert_block(bytes);
|
||||
ImportResult::Queued(QueueStatus::Known)
|
||||
}
|
||||
}
|
||||
|
109
src/verification.rs
Normal file
109
src/verification.rs
Normal file
@ -0,0 +1,109 @@
|
||||
use util::uint::*;
|
||||
use util::hash::*;
|
||||
use util::rlp::*;
|
||||
use util::sha3::Hashable;
|
||||
use util::triehash::ordered_trie_root;
|
||||
use header::Header;
|
||||
use client::BlockNumber;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum TransactionVerificationError {
|
||||
OutOfGasBase,
|
||||
OutOfGasIntrinsic,
|
||||
NotEnoughCash,
|
||||
GasPriceTooLow,
|
||||
BlockGasLimitReached,
|
||||
FeeTooSmall,
|
||||
TooMuchGasUsed {
|
||||
used: U256,
|
||||
limit: U256
|
||||
},
|
||||
ExtraDataTooBig,
|
||||
InvalidSignature,
|
||||
InvalidTransactionFormat,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum BlockVerificationError {
|
||||
TooMuchGasUsed {
|
||||
used: U256,
|
||||
limit: U256,
|
||||
},
|
||||
InvalidBlockFormat,
|
||||
InvalidUnclesHash {
|
||||
expected: H256,
|
||||
got: H256,
|
||||
},
|
||||
TooManyUncles,
|
||||
UncleTooOld,
|
||||
UncleIsBrother,
|
||||
UncleInChain,
|
||||
UncleParentNotInChain,
|
||||
InvalidStateRoot,
|
||||
InvalidGasUsed,
|
||||
InvalidTransactionsRoot {
|
||||
expected: H256,
|
||||
got: H256,
|
||||
},
|
||||
InvalidDifficulty,
|
||||
InvalidGasLimit,
|
||||
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 {
|
||||
expected: expected_root.clone(),
|
||||
got: transactions_root.clone(),
|
||||
});
|
||||
}
|
||||
let expected_uncles = block.at(2).as_raw().sha3();
|
||||
if &expected_uncles != uncles_hash {
|
||||
return Err(BlockVerificationError::InvalidUnclesHash {
|
||||
expected: expected_uncles.clone(),
|
||||
got: uncles_hash.clone(),
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user