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