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 std::path::Path;
|
||||||
use util::uint::U256;
|
use util::uint::U256;
|
||||||
use util::hash::*;
|
use util::hash::*;
|
||||||
use util::sha3::*;
|
|
||||||
use util::rlp::*;
|
use util::rlp::*;
|
||||||
use util::bytes::Bytes;
|
use util::bytes::Bytes;
|
||||||
use blockchain::BlockChain;
|
use blockchain::BlockChain;
|
||||||
|
use queue::BlockQueue;
|
||||||
use views::BlockView;
|
use views::BlockView;
|
||||||
|
|
||||||
/// Status for a block in a queue.
|
/// Status for a block in a queue.
|
||||||
@ -106,7 +107,7 @@ pub trait BlockChainClient : Sync {
|
|||||||
/// Get block queue information.
|
/// Get block queue information.
|
||||||
fn queue_status(&self) -> BlockQueueStatus;
|
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);
|
fn clear_queue(&mut self);
|
||||||
|
|
||||||
/// Get blockchain information.
|
/// 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.
|
/// Blockchain database client backed by a persistent database. Owns and manages a blockchain and a block queue.
|
||||||
pub struct Client {
|
pub struct Client {
|
||||||
chain: BlockChain
|
chain: Arc<BlockChain>,
|
||||||
|
queue: BlockQueue,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Client {
|
impl Client {
|
||||||
pub fn new(genesis: &[u8], path: &Path) -> Client {
|
pub fn new(genesis: &[u8], path: &Path) -> Client {
|
||||||
|
let chain = Arc::new(BlockChain::new(genesis, path));
|
||||||
Client {
|
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 {
|
fn import_block(&mut self, bytes: &[u8]) -> ImportResult {
|
||||||
//TODO: verify block
|
self.queue.import_block(bytes)
|
||||||
{
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn queue_status(&self) -> BlockQueueStatus {
|
fn queue_status(&self) -> BlockQueueStatus {
|
||||||
@ -201,6 +195,7 @@ impl BlockChainClient for Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn clear_queue(&mut self) {
|
fn clear_queue(&mut self) {
|
||||||
|
self.queue.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn chain_info(&self) -> BlockChainInfo {
|
fn chain_info(&self) -> BlockChainInfo {
|
||||||
|
@ -105,6 +105,7 @@ pub mod views;
|
|||||||
pub mod blockchain;
|
pub mod blockchain;
|
||||||
pub mod extras;
|
pub mod extras;
|
||||||
pub mod client;
|
pub mod client;
|
||||||
|
|
||||||
pub mod sync;
|
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