diff --git a/chain/src/constants.rs b/chain/src/constants.rs new file mode 100644 index 00000000..72ecc5f5 --- /dev/null +++ b/chain/src/constants.rs @@ -0,0 +1,22 @@ + +// Below flags apply in the context of BIP 68 +// If this flag set, CTxIn::nSequence is NOT interpreted as a +// relative lock-time. +pub const SEQUENCE_LOCKTIME_DISABLE_FLAG: u32 = 1u32 << 31; + +// Setting nSequence to this value for every input in a transaction +// disables nLockTime. +pub const SEQUENCE_FINAL: u32 = 0xffffffff; + +// If CTxIn::nSequence encodes a relative lock-time and this flag +// is set, the relative lock-time has units of 512 seconds, +// otherwise it specifies blocks with a granularity of 1. +pub const SEQUENCE_LOCKTIME_TYPE_FLAG: u32 = (1 << 22); + +// If CTxIn::nSequence encodes a relative lock-time, this mask is +// applied to extract that lock-time from the sequence field. +pub const SEQUENCE_LOCKTIME_MASK: u32 = 0x0000ffff; + +/// Threshold for `nLockTime`: below this value it is interpreted as block number, +/// otherwise as UNIX timestamp. +pub const LOCKTIME_THRESHOLD: u32 = 500000000; // Tue Nov 5 00:53:20 1985 UTC diff --git a/db/src/indexed_block.rs b/chain/src/indexed_block.rs similarity index 52% rename from db/src/indexed_block.rs rename to chain/src/indexed_block.rs index e788a580..9e02979f 100644 --- a/db/src/indexed_block.rs +++ b/chain/src/indexed_block.rs @@ -1,9 +1,14 @@ -use primitives::hash::H256; -use chain::{Block, OutPoint, TransactionOutput, merkle_root, Transaction}; -use serialization::{Serializable, serialized_list_size}; +use std::{io, cmp}; +use hash::H256; +use ser::{ + Serializable, serialized_list_size, + Deserializable, Reader, Error as ReaderError +}; +use block::Block; +use transaction::Transaction; +use merkle_root::merkle_root; use indexed_header::IndexedBlockHeader; use indexed_transaction::IndexedTransaction; -use {TransactionOutputObserver, PreviousTransactionOutputProvider}; #[derive(Debug, Clone)] pub struct IndexedBlock { @@ -11,40 +16,6 @@ pub struct IndexedBlock { pub transactions: Vec, } -impl PreviousTransactionOutputProvider for IndexedBlock { - fn previous_transaction_output(&self, prevout: &OutPoint) -> Option { - let txs: &[_] = &self.transactions; - txs.previous_transaction_output(prevout) - } -} - -impl TransactionOutputObserver for IndexedBlock { - fn is_spent(&self, _prevout: &OutPoint) -> Option { - // the code below is valid, but commented out due it's poor performance - // we could optimize it by indexing all outputs once - // let tx: IndexedTransaction = { .. } - // let indexed_outputs: IndexedOutputs = tx.indexed_outputs(); - // indexed_outputs.is_spent() - None - - // if previous transaction output appears more than once than we can safely - // tell that it's spent (double spent) - - //let spends = self.transactions.iter() - //.flat_map(|tx| &tx.raw.inputs) - //.filter(|input| &input.previous_output == prevout) - //.take(2) - //.count(); - - //match spends { - //0 => None, - //1 => Some(false), - //2 => Some(true), - //_ => unreachable!("spends <= 2; self.take(2); qed"), - //} - } -} - impl From for IndexedBlock { fn from(block: Block) -> Self { let Block { block_header, transactions } = block; @@ -56,6 +27,12 @@ impl From for IndexedBlock { } } +impl cmp::PartialEq for IndexedBlock { + fn eq(&self, other: &Self) -> bool { + self.header.hash == other.header.hash + } +} + impl IndexedBlock { pub fn new(header: IndexedBlockHeader, transactions: Vec) -> Self { IndexedBlock { @@ -87,3 +64,14 @@ impl IndexedBlock { self.transactions.iter().all(|tx| tx.raw.is_final_in_block(height, self.header.raw.time)) } } + +impl Deserializable for IndexedBlock { + fn deserialize(reader: &mut Reader) -> Result where T: io::Read { + let block = IndexedBlock { + header: try!(reader.read()), + transactions: try!(reader.read_list()), + }; + + Ok(block) + } +} diff --git a/chain/src/indexed_header.rs b/chain/src/indexed_header.rs new file mode 100644 index 00000000..6e2142e9 --- /dev/null +++ b/chain/src/indexed_header.rs @@ -0,0 +1,48 @@ +use std::{io, cmp}; +use hash::H256; +use ser::{Deserializable, Reader, Error as ReaderError}; +use block_header::BlockHeader; +use read_and_hash::ReadAndHash; + +#[derive(Debug, Clone)] +pub struct IndexedBlockHeader { + pub hash: H256, + pub raw: BlockHeader, +} + +impl From for IndexedBlockHeader { + fn from(header: BlockHeader) -> Self { + IndexedBlockHeader { + hash: header.hash(), + raw: header, + } + } +} + +impl IndexedBlockHeader { + pub fn new(hash: H256, header: BlockHeader) -> Self { + IndexedBlockHeader { + hash: hash, + raw: header, + } + } +} + +impl cmp::PartialEq for IndexedBlockHeader { + fn eq(&self, other: &Self) -> bool { + self.hash == other.hash + } +} + +impl Deserializable for IndexedBlockHeader { + fn deserialize(reader: &mut Reader) -> Result where T: io::Read { + let data = try!(reader.read_and_hash::()); + // TODO: use len + let header = IndexedBlockHeader { + raw: data.data, + hash: data.hash, + }; + + Ok(header) + } +} diff --git a/chain/src/indexed_transaction.rs b/chain/src/indexed_transaction.rs new file mode 100644 index 00000000..d15fd813 --- /dev/null +++ b/chain/src/indexed_transaction.rs @@ -0,0 +1,60 @@ +use std::{cmp, io, borrow}; +use hash::H256; +use ser::{Deserializable, Reader, Error as ReaderError}; +use transaction::Transaction; +use read_and_hash::ReadAndHash; + +#[derive(Debug, Clone)] +pub struct IndexedTransaction { + pub hash: H256, + pub raw: Transaction, +} + +impl From for IndexedTransaction { + fn from(tx: Transaction) -> Self { + IndexedTransaction { + hash: tx.hash(), + raw: tx, + } + } +} + +impl IndexedTransaction { + pub fn new(hash: H256, transaction: Transaction) -> Self { + IndexedTransaction { + hash: hash, + raw: transaction, + } + } +} + +impl cmp::PartialEq for IndexedTransaction { + fn eq(&self, other: &Self) -> bool { + self.hash == other.hash + } +} + +impl Deserializable for IndexedTransaction { + fn deserialize(reader: &mut Reader) -> Result where T: io::Read { + let data = try!(reader.read_and_hash::()); + // TODO: use len + let tx = IndexedTransaction { + raw: data.data, + hash: data.hash, + }; + + Ok(tx) + } +} + +pub struct IndexedTransactionsRef<'a, T> where T: 'a { + pub transactions: &'a [T], +} + +impl<'a, T> IndexedTransactionsRef<'a, T> where T: borrow::Borrow { + pub fn new(transactions: &'a [T]) -> Self { + IndexedTransactionsRef { + transactions: transactions, + } + } +} diff --git a/chain/src/lib.rs b/chain/src/lib.rs index 08d8c4ee..7d0a59b7 100644 --- a/chain/src/lib.rs +++ b/chain/src/lib.rs @@ -4,27 +4,34 @@ extern crate primitives; extern crate bitcrypto as crypto; extern crate serialization as ser; +pub mod constants; + mod block; mod block_header; mod merkle_root; mod transaction; +/// `IndexedBlock` extension +mod read_and_hash; +mod indexed_block; +mod indexed_header; +mod indexed_transaction; + pub trait RepresentH256 { - fn h256(&self) -> primitives::hash::H256; + fn h256(&self) -> hash::H256; } pub use rustc_serialize::hex; pub use primitives::{hash, bytes, uint, compact}; -pub use self::block::Block; -pub use self::block_header::BlockHeader; -pub use self::merkle_root::merkle_root; -pub use self::merkle_root::merkle_node_hash; -pub use self::transaction::{ - Transaction, TransactionInput, TransactionOutput, OutPoint, - SEQUENCE_LOCKTIME_DISABLE_FLAG, SEQUENCE_FINAL, - SEQUENCE_LOCKTIME_TYPE_FLAG, SEQUENCE_LOCKTIME_MASK, - LOCKTIME_THRESHOLD -}; +pub use block::Block; +pub use block_header::BlockHeader; +pub use merkle_root::{merkle_root, merkle_node_hash}; +pub use transaction::{Transaction, TransactionInput, TransactionOutput, OutPoint}; + +pub use read_and_hash::{ReadAndHash, HashedData}; +pub use indexed_block::IndexedBlock; +pub use indexed_header::IndexedBlockHeader; +pub use indexed_transaction::{IndexedTransaction, IndexedTransactionsRef}; pub type ShortTransactionID = hash::H48; diff --git a/chain/src/read_and_hash.rs b/chain/src/read_and_hash.rs new file mode 100644 index 00000000..5c294dcf --- /dev/null +++ b/chain/src/read_and_hash.rs @@ -0,0 +1,33 @@ +use std::io; +use hash::H256; +use crypto::{DHash256, Digest}; +use ser::{Reader, Error as ReaderError, Deserializable}; + +pub struct HashedData { + pub size: usize, + pub hash: H256, + pub data: T, +} + +pub trait ReadAndHash { + fn read_and_hash(&mut self) -> Result, ReaderError> where T: Deserializable; +} + +impl ReadAndHash for Reader where R: io::Read { + fn read_and_hash(&mut self) -> Result, ReaderError> where T: Deserializable { + let mut size = 0usize; + let mut hasher = DHash256::new(); + let data = self.read_with_proxy(|bytes| { + size += bytes.len(); + hasher.input(bytes); + })?; + + let result = HashedData { + hash: hasher.finish(), + data: data, + size: size, + }; + + Ok(result) + } +} diff --git a/chain/src/transaction.rs b/chain/src/transaction.rs index 8e6c984f..1f28a05c 100644 --- a/chain/src/transaction.rs +++ b/chain/src/transaction.rs @@ -11,28 +11,7 @@ use ser::{ }; use crypto::dhash256; use hash::H256; - -// Below flags apply in the context of BIP 68 -// If this flag set, CTxIn::nSequence is NOT interpreted as a -// relative lock-time. -pub const SEQUENCE_LOCKTIME_DISABLE_FLAG: u32 = 1u32 << 31; - -// Setting nSequence to this value for every input in a transaction -// disables nLockTime. -pub const SEQUENCE_FINAL: u32 = 0xffffffff; - -// If CTxIn::nSequence encodes a relative lock-time and this flag -// is set, the relative lock-time has units of 512 seconds, -// otherwise it specifies blocks with a granularity of 1. -pub const SEQUENCE_LOCKTIME_TYPE_FLAG: u32 = (1 << 22); - -// If CTxIn::nSequence encodes a relative lock-time, this mask is -// applied to extract that lock-time from the sequence field. -pub const SEQUENCE_LOCKTIME_MASK: u32 = 0x0000ffff; - -/// Threshold for `nLockTime`: below this value it is interpreted as block number, -/// otherwise as UNIX timestamp. -pub const LOCKTIME_THRESHOLD: u32 = 500000000; // Tue Nov 5 00:53:20 1985 UTC +use constants::{SEQUENCE_FINAL, LOCKTIME_THRESHOLD}; #[derive(Debug, PartialEq, Eq, Clone, Default)] pub struct OutPoint { diff --git a/crypto/src/lib.rs b/crypto/src/lib.rs index 5fed6d43..02a11c3f 100644 --- a/crypto/src/lib.rs +++ b/crypto/src/lib.rs @@ -2,11 +2,11 @@ extern crate crypto as rcrypto; extern crate primitives; extern crate siphasher; +pub use rcrypto::digest::Digest; use std::hash::Hasher; use rcrypto::sha1::Sha1; use rcrypto::sha2::Sha256; use rcrypto::ripemd160::Ripemd160; -use rcrypto::digest::Digest; use siphasher::sip::SipHasher24; use primitives::hash::{H32, H160, H256}; @@ -72,6 +72,12 @@ impl DHash256 { pub fn new() -> Self { DHash256::default() } + + pub fn finish(mut self) -> H256 { + let mut result = H256::default(); + self.result(&mut *result); + result + } } impl Digest for DHash256 { diff --git a/db/src/block_stapler.rs b/db/src/block_stapler.rs index 20d2cf45..af361db4 100644 --- a/db/src/block_stapler.rs +++ b/db/src/block_stapler.rs @@ -1,7 +1,7 @@ use primitives::hash::H256; -use super::{BlockLocation, IndexedBlock}; -use chain; +use chain::{self, IndexedBlock}; use error::Error; +use super::BlockLocation; #[derive(Debug, PartialEq)] pub struct Reorganization { diff --git a/db/src/impls.rs b/db/src/impls.rs new file mode 100644 index 00000000..ceed0c60 --- /dev/null +++ b/db/src/impls.rs @@ -0,0 +1,49 @@ +use std::borrow::Borrow; +use chain::{OutPoint, TransactionOutput, IndexedTransactionsRef, IndexedTransaction, IndexedBlock}; +use transaction_provider::PreviousTransactionOutputProvider; +use transaction_meta_provider::TransactionOutputObserver; + +impl<'a, T> PreviousTransactionOutputProvider for IndexedTransactionsRef<'a, T> + where T: Borrow + Send + Sync { + fn previous_transaction_output(&self, prevout: &OutPoint) -> Option { + self.transactions.iter() + .map(Borrow::borrow) + .find(|tx| tx.hash == prevout.hash) + .and_then(|tx| tx.raw.outputs.get(prevout.index as usize)) + .cloned() + } +} + +impl PreviousTransactionOutputProvider for IndexedBlock { + fn previous_transaction_output(&self, prevout: &OutPoint) -> Option { + let txs = IndexedTransactionsRef::new(&self.transactions); + txs.previous_transaction_output(prevout) + } +} + +impl TransactionOutputObserver for IndexedBlock { + fn is_spent(&self, _prevout: &OutPoint) -> Option { + // the code below is valid, but commented out due it's poor performance + // we could optimize it by indexing all outputs once + // let tx: IndexedTransaction = { .. } + // let indexed_outputs: IndexedOutputs = tx.indexed_outputs(); + // indexed_outputs.is_spent() + None + + // if previous transaction output appears more than once than we can safely + // tell that it's spent (double spent) + + //let spends = self.transactions.iter() + //.flat_map(|tx| &tx.raw.inputs) + //.filter(|input| &input.previous_output == prevout) + //.take(2) + //.count(); + + //match spends { + //0 => None, + //1 => Some(false), + //2 => Some(true), + //_ => unreachable!("spends <= 2; self.take(2); qed"), + //} + } +} diff --git a/db/src/indexed_header.rs b/db/src/indexed_header.rs deleted file mode 100644 index df117833..00000000 --- a/db/src/indexed_header.rs +++ /dev/null @@ -1,26 +0,0 @@ -use primitives::hash::H256; -use chain::BlockHeader; - -#[derive(Debug, Clone)] -pub struct IndexedBlockHeader { - pub hash: H256, - pub raw: BlockHeader, -} - -impl From for IndexedBlockHeader { - fn from(header: BlockHeader) -> Self { - IndexedBlockHeader { - hash: header.hash(), - raw: header, - } - } -} - -impl IndexedBlockHeader { - pub fn new(hash: H256, header: BlockHeader) -> Self { - IndexedBlockHeader { - hash: hash, - raw: header, - } - } -} diff --git a/db/src/indexed_transaction.rs b/db/src/indexed_transaction.rs deleted file mode 100644 index bcfec139..00000000 --- a/db/src/indexed_transaction.rs +++ /dev/null @@ -1,43 +0,0 @@ -use std::cmp; -use primitives::hash::H256; -use chain::{Transaction, OutPoint, TransactionOutput}; -use PreviousTransactionOutputProvider; - -#[derive(Debug, Clone)] -pub struct IndexedTransaction { - pub hash: H256, - pub raw: Transaction, -} - -impl From for IndexedTransaction { - fn from(tx: Transaction) -> Self { - IndexedTransaction { - hash: tx.hash(), - raw: tx, - } - } -} - -impl IndexedTransaction { - pub fn new(hash: H256, transaction: Transaction) -> Self { - IndexedTransaction { - hash: hash, - raw: transaction, - } - } -} - -impl cmp::PartialEq for IndexedTransaction { - fn eq(&self, other: &Self) -> bool { - self.hash == other.hash - } -} - -impl<'a> PreviousTransactionOutputProvider for &'a [IndexedTransaction] { - fn previous_transaction_output(&self, prevout: &OutPoint) -> Option { - self.iter() - .find(|tx| tx.hash == prevout.hash) - .and_then(|tx| tx.raw.outputs.get(prevout.index as usize)) - .cloned() - } -} diff --git a/db/src/lib.rs b/db/src/lib.rs index 10a05309..1262e4f7 100644 --- a/db/src/lib.rs +++ b/db/src/lib.rs @@ -28,9 +28,7 @@ mod transaction_provider; mod transaction_meta_provider; mod error; mod update_context; -mod indexed_block; -mod indexed_header; -mod indexed_transaction; +mod impls; #[derive(Debug, Clone)] pub enum BlockRef { @@ -75,9 +73,6 @@ pub use transaction_meta_provider::{TransactionMetaProvider, TransactionOutputOb pub use transaction_meta::TransactionMeta; pub use block_stapler::{BlockStapler, BlockInsertedChain}; pub use block_provider::{BlockProvider, BlockHeaderProvider}; -pub use indexed_block::IndexedBlock; -pub use indexed_header::IndexedBlockHeader; -pub use indexed_transaction::IndexedTransaction; #[cfg(feature="dev")] pub use test_storage::TestStorage; diff --git a/db/src/storage.rs b/db/src/storage.rs index a7c5d6d5..72eacab6 100644 --- a/db/src/storage.rs +++ b/db/src/storage.rs @@ -4,14 +4,13 @@ use std::fs; use std::path::Path; use kvdb::{Database, DatabaseConfig}; use byteorder::{LittleEndian, ByteOrder}; -use primitives::hash::H256; -use primitives::bytes::Bytes; -use super::{BlockRef, BestBlock, BlockLocation, IndexedBlock}; -use serialization::{serialize, deserialize}; -use chain; use parking_lot::RwLock; use lru_cache::LruCache; +use primitives::hash::H256; +use primitives::bytes::Bytes; +use chain::{self, IndexedBlock, IndexedBlockHeader, IndexedTransaction}; +use serialization::{serialize, deserialize}; use transaction_meta::TransactionMeta; use error::{Error, ConsistencyError, MetaError}; use update_context::UpdateContext; @@ -19,9 +18,7 @@ use block_provider::{BlockProvider, BlockHeaderProvider}; use transaction_provider::{TransactionProvider, PreviousTransactionOutputProvider}; use transaction_meta_provider::TransactionMetaProvider; use block_stapler::{BlockStapler, BlockInsertedChain, Reorganization}; - -use indexed_header::IndexedBlockHeader; -use indexed_transaction::IndexedTransaction; +use super::{BlockRef, BestBlock, BlockLocation}; pub const COL_COUNT: u32 = 10; pub const COL_META: u32 = 0; diff --git a/db/src/test_storage.rs b/db/src/test_storage.rs index c5b3928f..2ea1ce18 100644 --- a/db/src/test_storage.rs +++ b/db/src/test_storage.rs @@ -3,9 +3,9 @@ use super::{ BlockRef, Store, Error, BestBlock, BlockLocation, BlockInsertedChain, BlockProvider, BlockStapler, TransactionMetaProvider, TransactionProvider, PreviousTransactionOutputProvider, - IndexedBlock, BlockHeaderProvider, + BlockHeaderProvider, }; -use chain::{self, Block}; +use chain::{self, Block, IndexedBlock}; use primitives::hash::H256; use serialization; use chain::bytes::Bytes; diff --git a/import/src/block.rs b/import/src/block.rs index 0cadd73f..fb893881 100644 --- a/import/src/block.rs +++ b/import/src/block.rs @@ -1,13 +1,13 @@ use std::io; use hash::H32; use ser::{Deserializable, Reader, Error as ReaderError}; -use chain; +use chain::IndexedBlock; #[derive(Debug, PartialEq)] pub struct Block { pub magic: H32, pub block_size: u32, - pub block: chain::Block, + pub block: IndexedBlock, } impl Deserializable for Block { diff --git a/miner/src/block_assembler.rs b/miner/src/block_assembler.rs index eb119947..6e2a5f7e 100644 --- a/miner/src/block_assembler.rs +++ b/miner/src/block_assembler.rs @@ -1,7 +1,7 @@ use std::collections::HashSet; use primitives::hash::H256; -use chain::{OutPoint, TransactionOutput}; -use db::{SharedStore, IndexedTransaction, PreviousTransactionOutputProvider}; +use chain::{OutPoint, TransactionOutput, IndexedTransaction}; +use db::{SharedStore, PreviousTransactionOutputProvider}; use network::Magic; use memory_pool::{MemoryPool, OrderingStrategy, Entry}; use verification::{work_required, block_reward_satoshi, transaction_sigops}; @@ -278,7 +278,7 @@ impl BlockAssembler { #[cfg(test)] mod tests { - use db::IndexedTransaction; + use chain::{IndexedTransaction, IndexedTransactionsRef}; use verification::constants::{MAX_BLOCK_SIZE, MAX_BLOCK_SIGOPS}; use memory_pool::Entry; use super::{SizePolicy, NextStep, FittingTransactionsIterator}; @@ -317,8 +317,8 @@ mod tests { #[test] fn test_fitting_transactions_iterator_no_transactions() { let store: Vec = Vec::new(); + let store_ref = IndexedTransactionsRef::new(&store); let entries: Vec = Vec::new(); - let store_ref: &[_] = &store; let iter = FittingTransactionsIterator::new(&store_ref, entries.iter(), MAX_BLOCK_SIZE as u32, MAX_BLOCK_SIGOPS as u32, 0, 0); assert!(iter.collect::>().is_empty()); diff --git a/p2p/src/lib.rs b/p2p/src/lib.rs index 381b64e3..6f183238 100644 --- a/p2p/src/lib.rs +++ b/p2p/src/lib.rs @@ -32,5 +32,5 @@ pub use config::Config; pub use net::Config as NetConfig; pub use p2p::{P2P, Context}; pub use event_loop::{event_loop, forever}; -pub use util::{NodeTableError, PeerId, PeerInfo, InternetProtocol}; +pub use util::{NodeTableError, PeerId, PeerInfo, InternetProtocol, Direction}; pub use protocol::{InboundSyncConnection, InboundSyncConnectionRef, OutboundSyncConnection, OutboundSyncConnectionRef, LocalSyncNode, LocalSyncNodeRef}; diff --git a/p2p/src/net/connections.rs b/p2p/src/net/connections.rs index c3ed4c17..ed56eb9b 100644 --- a/p2p/src/net/connections.rs +++ b/p2p/src/net/connections.rs @@ -35,8 +35,13 @@ impl Connections { self.channels().values().map(|channel| channel.peer_info().address).collect() } + /// Returns info on every peer + pub fn info(&self) -> Vec { + self.channels().values().map(|channel| channel.peer_info()).collect() + } + /// Returns number of connections. - pub fn _count(&self) -> usize { + pub fn count(&self) -> usize { self.channels.read().len() } diff --git a/p2p/src/p2p.rs b/p2p/src/p2p.rs index 6c658f2f..6db84249 100644 --- a/p2p/src/p2p.rs +++ b/p2p/src/p2p.rs @@ -386,6 +386,14 @@ impl Context { pub fn create_sync_session(&self, start_height: i32, outbound_connection: OutboundSyncConnectionRef) -> InboundSyncConnectionRef { self.local_sync_node.create_sync_session(start_height, outbound_connection) } + + pub fn connections(&self) -> &Connections { + &self.connections + } + + pub fn nodes(&self) -> Vec { + self.node_table.read().nodes() + } } pub struct P2P { diff --git a/p2p/src/util/node_table.rs b/p2p/src/util/node_table.rs index afc8bc64..f197c804 100644 --- a/p2p/src/util/node_table.rs +++ b/p2p/src/util/node_table.rs @@ -296,6 +296,11 @@ impl NodeTable where T: Time { .collect() } + /// Returnes all nodes + pub fn nodes(&self) -> Vec { + self.by_addr.iter().map(|(_, n)| n).cloned().collect() + } + /// Returns most recently active nodes. /// /// The documenation says: diff --git a/pbtc/cli.yml b/pbtc/cli.yml index 2c24665f..86c8d1a3 100644 --- a/pbtc/cli.yml +++ b/pbtc/cli.yml @@ -78,3 +78,6 @@ subcommands: - PATH: required: true help: Path of the bitcoin core database + - skip-verification: + long: skip-verification + help: Skip blocks verification diff --git a/pbtc/commands/import.rs b/pbtc/commands/import.rs index ce5c10ef..ee283d7c 100644 --- a/pbtc/commands/import.rs +++ b/pbtc/commands/import.rs @@ -8,9 +8,11 @@ pub fn import(cfg: Config, matches: &ArgMatches) -> Result<(), String> { // TODO: this might be unnecessary here! try!(init_db(&cfg, &db)); - let mut writer = create_sync_blocks_writer(db, cfg.magic); - let blk_path = matches.value_of("PATH").expect("PATH is required in cli.yml; qed"); + let skip_verification = matches.is_present("skip-verification"); + + let mut writer = create_sync_blocks_writer(db, cfg.magic, !skip_verification); + let blk_dir = try!(::import::open_blk_dir(blk_path).map_err(|_| "Import directory does not exist".to_owned())); let mut counter = 0; for blk in blk_dir { @@ -20,7 +22,7 @@ pub fn import(cfg: Config, matches: &ArgMatches) -> Result<(), String> { Ok(_) => { counter += 1; if counter % 1000 == 0 { - info!("Imported {} blocks", counter); + info!(target: "sync", "Imported {} blocks", counter); } } Err(Error::TooManyOrphanBlocks) => return Err("Too many orphan (unordered) blocks".into()), diff --git a/rpc/src/v1/helpers/errors.rs b/rpc/src/v1/helpers/errors.rs index b14f70a5..984b0a27 100644 --- a/rpc/src/v1/helpers/errors.rs +++ b/rpc/src/v1/helpers/errors.rs @@ -2,6 +2,7 @@ mod codes { // NOTE [ToDr] Codes from [-32099, -32000] + pub const UNKNOWN: i64 = -32000; pub const EXECUTION_ERROR: i64 = -32015; pub const TRANSACTION_NOT_FOUND: i64 = -32096; pub const TRANSACTION_OUTPUT_NOT_FOUND: i64 = -32097; @@ -97,3 +98,11 @@ pub fn node_not_added() -> Error { data: None, } } + +pub fn unknown() -> Error { + Error { + code: ErrorCode::ServerError(codes::UNKNOWN), + message: "Unknown error has occurred".into(), + data: None, + } +} diff --git a/rpc/src/v1/impls/blockchain.rs b/rpc/src/v1/impls/blockchain.rs index 63ae0c16..0063b3af 100644 --- a/rpc/src/v1/impls/blockchain.rs +++ b/rpc/src/v1/impls/blockchain.rs @@ -9,7 +9,7 @@ use v1::helpers::errors::{block_not_found, block_at_height_not_found, transactio transaction_output_not_found, transaction_of_side_branch}; use jsonrpc_macros::Trailing; use jsonrpc_core::Error; -use db; +use {db, chain}; use global_script::Script; use chain::OutPoint; use verification; @@ -69,7 +69,7 @@ impl BlockChainClientCoreApi for BlockChainClientCore { fn verbose_block(&self, hash: GlobalH256) -> Option { self.storage.block(hash.into()) .map(|block| { - let block: db::IndexedBlock = block.into(); + let block: chain::IndexedBlock = block.into(); let height = self.storage.block_number(block.hash()); let confirmations = match height { Some(block_number) => (self.storage.best_block().expect("genesis block is required").number - block_number + 1) as i64, diff --git a/rpc/src/v1/impls/network.rs b/rpc/src/v1/impls/network.rs index 842996c8..01e6b2ae 100644 --- a/rpc/src/v1/impls/network.rs +++ b/rpc/src/v1/impls/network.rs @@ -1,8 +1,9 @@ use std::sync::Arc; -use std::net::SocketAddr; +use std::net::{SocketAddr, IpAddr}; use v1::traits::Network as NetworkRpc; -use v1::types::AddNodeOperation; +use v1::types::{AddNodeOperation, NodeInfo}; use jsonrpc_core::Error; +use jsonrpc_macros::Trailing; use v1::helpers::errors; use p2p; @@ -10,6 +11,9 @@ pub trait NetworkApi : Send + Sync + 'static { fn add_node(&self, socket_addr: SocketAddr) -> Result<(), p2p::NodeTableError>; fn remove_node(&self, socket_addr: SocketAddr) -> Result<(), p2p::NodeTableError>; fn connect(&self, socket_addr: SocketAddr); + fn node_info(&self, node_addr: IpAddr) -> Result; + fn nodes_info(&self) -> Vec; + fn connection_count(&self) -> usize; } impl NetworkRpc for NetworkClient where T: NetworkApi { @@ -29,6 +33,27 @@ impl NetworkRpc for NetworkClient where T: NetworkApi { } } } + + fn node_info(&self, _dns: bool, node_addr: Trailing) -> Result, Error> { + Ok( + if node_addr.0.is_empty() { + self.api.nodes_info() + } + else { + let addr = try!(node_addr.0.parse().map_err( + |_| errors::invalid_params("node", "Invalid ip address format, should be ip address (127.0.0.1)"))); + let node_info = try!( + self.api.node_info(addr) + .map_err(|_| errors::node_not_added()) + ); + vec![node_info] + } + ) + } + + fn connection_count(&self) -> Result { + Ok(self.api.connection_count()) + } } pub struct NetworkClient { @@ -65,4 +90,43 @@ impl NetworkApi for NetworkClientCore { fn connect(&self, socket_addr: SocketAddr) { p2p::Context::connect_normal(self.p2p.clone(), socket_addr); } + + fn node_info(&self, node_addr: IpAddr) -> Result { + let exact_node = try!( + self.p2p.nodes() + .iter() + .find(|n| n.address().ip() == node_addr) + .cloned() + .ok_or(p2p::NodeTableError::NoAddressInTable) + ); + + let peers: Vec = self.p2p.connections().info() + .into_iter() + .filter(|p| p.address == exact_node.address()).collect(); + + Ok( + NodeInfo { + addednode: format!("{}", exact_node.address()), + connected: !peers.is_empty(), + addresses: peers.into_iter().map(|p| p.into()).collect(), + } + ) + } + + fn nodes_info(&self) -> Vec { + let peers: Vec = self.p2p.connections().info(); + + self.p2p.nodes().iter().map(|n| { + let node_peers: Vec = peers.iter().filter(|p| p.address == n.address()).cloned().collect(); + NodeInfo { + addednode: format!("{}", n.address()), + connected: !node_peers.is_empty(), + addresses: node_peers.into_iter().map(|p| p.into()).collect(), + } + }).collect() + } + + fn connection_count(&self) -> usize { + self.p2p.connections().count() + } } diff --git a/rpc/src/v1/traits/network.rs b/rpc/src/v1/traits/network.rs index c09cf60b..5fcc0004 100644 --- a/rpc/src/v1/traits/network.rs +++ b/rpc/src/v1/traits/network.rs @@ -1,14 +1,24 @@ use jsonrpc_core::Error; -use v1::types::AddNodeOperation; +use jsonrpc_macros::Trailing; +use v1::types::{AddNodeOperation, NodeInfo}; build_rpc_trait! { /// Parity-bitcoin network interface pub trait Network { - /// Add/remove/connecto to the node + /// Add/remove/connect to the node /// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "method": "addnode", "params": ["127.0.0.1:8888", "add"], "id":1 }' -H 'content-type: application/json;' http://127.0.0.1:8332/ /// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "method": "addnode", "params": ["127.0.0.1:8888", "remove"], "id":1 }' -H 'content-type: application/json;' http://127.0.0.1:8332/ /// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "method": "addnode", "params": ["127.0.0.1:8888", "onetry"], "id":1 }' -H 'content-type: application/json;' http://127.0.0.1:8332/ #[rpc(name = "addnode")] fn add_node(&self, String, AddNodeOperation) -> Result<(), Error>; + /// Query node(s) info + /// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "id":"1", "method": "getaddednodeinfo", "params": [true] }' -H 'content-type: application/json;' http://127.0.0.1:8332/ + /// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "id":"1", "method": "getaddednodeinfo", "params": [true, "192.168.0.201"] }' -H 'content-type: application/json;' http://127.0.0.1:8332/ + #[rpc(name = "getaddednodeinfo")] + fn node_info(&self, bool, Trailing) -> Result, Error>; + /// Query node(s) info + /// @curl-example: curl --data-binary '{"jsonrpc": "2.0", "id":"1", "method": "getconnectioncount", "params": [] }' -H 'content-type: application/json;' http://127.0.0.1:8332/ + #[rpc(name = "getconnectioncount")] + fn connection_count(&self) -> Result; } } diff --git a/rpc/src/v1/types/block_template.rs b/rpc/src/v1/types/block_template.rs index 706e7516..1e774771 100644 --- a/rpc/src/v1/types/block_template.rs +++ b/rpc/src/v1/types/block_template.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use super::hash::H256; +use chain; use super::transaction::RawTransaction; -use db; use miner; /// Block template as described in: @@ -96,8 +96,8 @@ impl From for BlockTemplate { } } -impl From for BlockTemplateTransaction { - fn from(transaction: db::IndexedTransaction) -> Self { +impl From for BlockTemplateTransaction { + fn from(transaction: chain::IndexedTransaction) -> Self { use ser::serialize; let serialize = serialize(&transaction.raw); BlockTemplateTransaction { diff --git a/rpc/src/v1/types/mod.rs.in b/rpc/src/v1/types/mod.rs.in index 3012cd1e..5d1fe7b6 100644 --- a/rpc/src/v1/types/mod.rs.in +++ b/rpc/src/v1/types/mod.rs.in @@ -26,4 +26,4 @@ pub use self::transaction::{RawTransaction, Transaction, TransactionInput, Trans TransactionInputScript, TransactionOutputScript, SignedTransactionInput, GetRawTransactionResponse, SignedTransactionOutput, TransactionOutputs}; pub use self::uint::U256; -pub use self::nodes::AddNodeOperation; +pub use self::nodes::{AddNodeOperation, NodeInfo}; diff --git a/rpc/src/v1/types/nodes.rs b/rpc/src/v1/types/nodes.rs index 0ba9ff50..cce26540 100644 --- a/rpc/src/v1/types/nodes.rs +++ b/rpc/src/v1/types/nodes.rs @@ -1,4 +1,5 @@ -use serde::{Deserialize, Deserializer}; +use serde::{Serialize, Serializer, Deserialize, Deserializer}; +use p2p::{Direction, PeerInfo}; #[derive(Debug, PartialEq)] pub enum AddNodeOperation { @@ -29,3 +30,42 @@ impl Deserialize for AddNodeOperation { deserializer.deserialize(DummyVisitor) } } + +#[derive(Serialize)] +pub struct NodeInfoAddress { + address: String, + connected: NodeInfoAddressConnectionType, +} + +impl From for NodeInfoAddress { + fn from(info: PeerInfo) -> Self { + NodeInfoAddress { + address: format!("{}", info.address), + connected: match info.direction { + Direction::Inbound => NodeInfoAddressConnectionType::Inbound, + Direction::Outbound => NodeInfoAddressConnectionType::Outbound, + }, + } + } +} + +#[derive(Serialize)] +pub struct NodeInfo { + pub addednode: String, + pub connected: bool, + pub addresses: Vec, +} + +pub enum NodeInfoAddressConnectionType { + Inbound, + Outbound, +} + +impl Serialize for NodeInfoAddressConnectionType { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer { + match *self { + NodeInfoAddressConnectionType::Inbound => "inbound".serialize(serializer), + NodeInfoAddressConnectionType::Outbound => "outbound".serialize(serializer), + } + } +} diff --git a/script/src/interpreter.rs b/script/src/interpreter.rs index c73e58ec..a361bbca 100644 --- a/script/src/interpreter.rs +++ b/script/src/interpreter.rs @@ -1,7 +1,7 @@ use std::{cmp, mem}; use bytes::Bytes; use keys::{Signature, Public}; -use chain::SEQUENCE_LOCKTIME_DISABLE_FLAG; +use chain::constants::SEQUENCE_LOCKTIME_DISABLE_FLAG; use crypto::{sha1, sha256, dhash160, dhash256, ripemd160}; use { script, Script, Num, VerificationFlags, Opcode, Error, diff --git a/script/src/verify.rs b/script/src/verify.rs index 6ea02240..d3a5bffa 100644 --- a/script/src/verify.rs +++ b/script/src/verify.rs @@ -1,7 +1,7 @@ use keys::{Public, Signature}; -use chain::{ - self, SEQUENCE_FINAL, SEQUENCE_LOCKTIME_DISABLE_FLAG, - SEQUENCE_LOCKTIME_MASK, SEQUENCE_LOCKTIME_TYPE_FLAG +use chain::constants::{ + SEQUENCE_FINAL, SEQUENCE_LOCKTIME_DISABLE_FLAG, + SEQUENCE_LOCKTIME_MASK, SEQUENCE_LOCKTIME_TYPE_FLAG, LOCKTIME_THRESHOLD }; use {SignatureVersion, Script, TransactionInputSigner, Num}; @@ -64,8 +64,8 @@ impl SignatureChecker for TransactionSignatureChecker { // the nLockTime in the transaction. let lock_time_u32: u32 = lock_time.into(); if !( - (self.signer.lock_time < chain::LOCKTIME_THRESHOLD && lock_time_u32 < chain::LOCKTIME_THRESHOLD) || - (self.signer.lock_time >= chain::LOCKTIME_THRESHOLD && lock_time_u32 >= chain::LOCKTIME_THRESHOLD) + (self.signer.lock_time < LOCKTIME_THRESHOLD && lock_time_u32 < LOCKTIME_THRESHOLD) || + (self.signer.lock_time >= LOCKTIME_THRESHOLD && lock_time_u32 >= LOCKTIME_THRESHOLD) ) { return false; } diff --git a/serialization/src/reader.rs b/serialization/src/reader.rs index 51dacb61..653a99b5 100644 --- a/serialization/src/reader.rs +++ b/serialization/src/reader.rs @@ -84,6 +84,11 @@ impl Reader where R: io::Read { T::deserialize(self) } + pub fn read_with_proxy(&mut self, proxy: F) -> Result where T: Deserializable, F: FnMut(&[u8]) { + let mut reader = Reader::from_read(Proxy::new(self, proxy)); + T::deserialize(&mut reader) + } + pub fn read_slice(&mut self, bytes: &mut [u8]) -> Result<(), Error> { io::Read::read_exact(self, bytes).map_err(|_| Error::UnexpectedEnd) } @@ -148,3 +153,26 @@ impl Iterator for ReadIterator where R: io::Read, T: Deserializable } } } + +struct Proxy { + from: F, + to: T, +} + +impl Proxy { + fn new(from: F, to: T) -> Self { + Proxy { + from: from, + to: to, + } + } +} + +impl io::Read for Proxy where F: io::Read, T: FnMut(&[u8]) { + fn read(&mut self, buf: &mut [u8]) -> Result { + let len = try!(io::Read::read(&mut self.from, buf)); + let to = &mut self.to; + to(&buf[..len]); + Ok(len) + } +} diff --git a/sync/src/blocks_writer.rs b/sync/src/blocks_writer.rs index 489fcdba..21c35d99 100644 --- a/sync/src/blocks_writer.rs +++ b/sync/src/blocks_writer.rs @@ -17,6 +17,7 @@ pub struct BlocksWriter { orphaned_blocks_pool: OrphanBlocksPool, verifier: SyncVerifier, sink: Arc, + verification: bool, } struct BlocksWriterSink { @@ -29,7 +30,7 @@ struct BlocksWriterSinkData { } impl BlocksWriter { - pub fn new(storage: db::SharedStore, network: Magic) -> BlocksWriter { + pub fn new(storage: db::SharedStore, network: Magic, verification: bool) -> BlocksWriter { let sink_data = Arc::new(BlocksWriterSinkData::new(storage.clone())); let sink = Arc::new(BlocksWriterSink::new(sink_data.clone())); let verifier = SyncVerifier::new(network, storage.clone(), sink); @@ -38,18 +39,18 @@ impl BlocksWriter { orphaned_blocks_pool: OrphanBlocksPool::new(), verifier: verifier, sink: sink_data, + verification: verification, } } - pub fn append_block(&mut self, block: chain::Block) -> Result<(), Error> { - let indexed_block: db::IndexedBlock = block.into(); + pub fn append_block(&mut self, block: chain::IndexedBlock) -> Result<(), Error> { // do not append block if it is already there - if self.storage.contains_block(db::BlockRef::Hash(indexed_block.hash().clone())) { + if self.storage.contains_block(db::BlockRef::Hash(block.hash().clone())) { return Ok(()); } // verify && insert only if parent block is already in the storage - if !self.storage.contains_block(db::BlockRef::Hash(indexed_block.header.raw.previous_header_hash.clone())) { - self.orphaned_blocks_pool.insert_orphaned_block(indexed_block.hash().clone(), indexed_block); + if !self.storage.contains_block(db::BlockRef::Hash(block.header.raw.previous_header_hash.clone())) { + self.orphaned_blocks_pool.insert_orphaned_block(block.hash().clone(), block); // we can't hold many orphaned blocks in memory during import if self.orphaned_blocks_pool.len() > MAX_ORPHANED_BLOCKS { return Err(Error::TooManyOrphanBlocks); @@ -58,13 +59,17 @@ impl BlocksWriter { } // verify && insert block && all its orphan children - let mut verification_queue: VecDeque = self.orphaned_blocks_pool.remove_blocks_for_parent(indexed_block.hash()).into_iter().map(|(_, b)| b).collect(); - verification_queue.push_front(indexed_block); + let mut verification_queue: VecDeque = self.orphaned_blocks_pool.remove_blocks_for_parent(block.hash()).into_iter().map(|(_, b)| b).collect(); + verification_queue.push_front(block); while let Some(block) = verification_queue.pop_front() { - self.verifier.verify_block(block); + if self.verification { + self.verifier.verify_block(block); - if let Some(err) = self.sink.error() { - return Err(err); + if let Some(err) = self.sink.error() { + return Err(err); + } + } else { + try!(self.storage.insert_indexed_block(&block).map_err(Error::Database)); } } @@ -97,7 +102,7 @@ impl VerificationSink for BlocksWriterSink { } impl BlockVerificationSink for BlocksWriterSink { - fn on_block_verification_success(&self, block: db::IndexedBlock) -> Option> { + fn on_block_verification_success(&self, block: chain::IndexedBlock) -> Option> { if let Err(err) = self.data.storage.insert_indexed_block(&block) { *self.data.err.lock() = Some(Error::Database(err)); } @@ -132,8 +137,8 @@ mod tests { #[test] fn blocks_writer_appends_blocks() { let db = Arc::new(db::TestStorage::with_genesis_block()); - let mut blocks_target = BlocksWriter::new(db.clone(), Magic::Testnet); - blocks_target.append_block(test_data::block_h1()).expect("Expecting no error"); + let mut blocks_target = BlocksWriter::new(db.clone(), Magic::Testnet, true); + blocks_target.append_block(test_data::block_h1().into()).expect("Expecting no error"); assert_eq!(db.best_block().expect("Block is inserted").number, 1); } @@ -141,9 +146,9 @@ mod tests { fn blocks_writer_verification_error() { let db = Arc::new(db::TestStorage::with_genesis_block()); let blocks = test_data::build_n_empty_blocks_from_genesis((MAX_ORPHANED_BLOCKS + 2) as u32, 1); - let mut blocks_target = BlocksWriter::new(db.clone(), Magic::Testnet); + let mut blocks_target = BlocksWriter::new(db.clone(), Magic::Testnet, true); for (index, block) in blocks.into_iter().skip(1).enumerate() { - match blocks_target.append_block(block) { + match blocks_target.append_block(block.into()) { Err(Error::TooManyOrphanBlocks) if index == MAX_ORPHANED_BLOCKS => (), Ok(_) if index != MAX_ORPHANED_BLOCKS => (), _ => panic!("unexpected"), @@ -155,12 +160,12 @@ mod tests { #[test] fn blocks_writer_out_of_order_block() { let db = Arc::new(db::TestStorage::with_genesis_block()); - let mut blocks_target = BlocksWriter::new(db.clone(), Magic::Testnet); + let mut blocks_target = BlocksWriter::new(db.clone(), Magic::Testnet, true); let wrong_block = test_data::block_builder() .header().parent(test_data::genesis().hash()).build() .build(); - match blocks_target.append_block(wrong_block).unwrap_err() { + match blocks_target.append_block(wrong_block.into()).unwrap_err() { Error::Verification(_) => (), _ => panic!("Unexpected error"), }; @@ -170,12 +175,12 @@ mod tests { #[test] fn blocks_writer_append_to_existing_db() { let db = Arc::new(db::TestStorage::with_genesis_block()); - let mut blocks_target = BlocksWriter::new(db.clone(), Magic::Testnet); + let mut blocks_target = BlocksWriter::new(db.clone(), Magic::Testnet, true); - assert!(blocks_target.append_block(test_data::genesis()).is_ok()); + assert!(blocks_target.append_block(test_data::genesis().into()).is_ok()); assert_eq!(db.best_block().expect("Block is inserted").number, 0); - assert!(blocks_target.append_block(test_data::block_h1()).is_ok()); + assert!(blocks_target.append_block(test_data::block_h1().into()).is_ok()); assert_eq!(db.best_block().expect("Block is inserted").number, 1); } } diff --git a/sync/src/compact_block_builder.rs b/sync/src/compact_block_builder.rs index 3084f337..217b4bc1 100644 --- a/sync/src/compact_block_builder.rs +++ b/sync/src/compact_block_builder.rs @@ -2,8 +2,7 @@ use std::collections::HashSet; use rand::{thread_rng, Rng}; use bitcrypto::{sha256, siphash24}; use byteorder::{LittleEndian, ByteOrder}; -use chain::{BlockHeader, ShortTransactionID}; -use db::IndexedBlock; +use chain::{BlockHeader, ShortTransactionID, IndexedBlock}; use message::common::{BlockHeaderAndIDs, PrefilledTransaction}; use primitives::hash::H256; use ser::{Stream, Serializable}; diff --git a/sync/src/lib.rs b/sync/src/lib.rs index aebaefbd..96b53144 100644 --- a/sync/src/lib.rs +++ b/sync/src/lib.rs @@ -63,8 +63,8 @@ pub enum Error { } /// Create blocks writer. -pub fn create_sync_blocks_writer(db: db::SharedStore, network: Magic) -> blocks_writer::BlocksWriter { - blocks_writer::BlocksWriter::new(db, network) +pub fn create_sync_blocks_writer(db: db::SharedStore, network: Magic, verification: bool) -> blocks_writer::BlocksWriter { + blocks_writer::BlocksWriter::new(db, network, verification) } /// Creates local sync node for given `db` diff --git a/sync/src/orphan_blocks_pool.rs b/sync/src/orphan_blocks_pool.rs index 4e2e3dab..37cfcfc1 100644 --- a/sync/src/orphan_blocks_pool.rs +++ b/sync/src/orphan_blocks_pool.rs @@ -3,7 +3,7 @@ use std::collections::hash_map::Entry; use linked_hash_map::LinkedHashMap; use time; use primitives::hash::H256; -use db::IndexedBlock; +use chain::IndexedBlock; #[derive(Debug)] /// Storage for blocks, for which we have no parent yet. diff --git a/sync/src/synchronization_chain.rs b/sync/src/synchronization_chain.rs index 28a1ea4d..e018378f 100644 --- a/sync/src/synchronization_chain.rs +++ b/sync/src/synchronization_chain.rs @@ -3,8 +3,8 @@ use std::sync::Arc; use std::collections::{VecDeque, HashSet}; use linked_hash_map::LinkedHashMap; use parking_lot::RwLock; -use chain::{BlockHeader, Transaction}; -use db::{self, IndexedBlock}; +use chain::{BlockHeader, Transaction, IndexedBlock}; +use db; use best_headers_chain::{BestHeadersChain, Information as BestHeadersInformation}; use primitives::bytes::Bytes; use primitives::hash::H256; diff --git a/sync/src/synchronization_client.rs b/sync/src/synchronization_client.rs index 9bf722cf..2dfd8db8 100644 --- a/sync/src/synchronization_client.rs +++ b/sync/src/synchronization_client.rs @@ -7,8 +7,8 @@ use futures::{BoxFuture, Future, finished}; use futures::stream::Stream; use tokio_core::reactor::{Handle, Interval}; use futures_cpupool::CpuPool; -use db::{self, IndexedBlock, BlockHeaderProvider, BlockRef}; -use chain::{BlockHeader, Transaction}; +use db::{self, BlockHeaderProvider, BlockRef}; +use chain::{BlockHeader, Transaction, IndexedBlock}; use message::types; use message::common::{InventoryVector, InventoryType}; use primitives::hash::H256; @@ -1312,7 +1312,7 @@ impl SynchronizationClientCore where T: TaskExecutor { } }, BlockAnnouncementType::SendCompactBlock => { - let indexed_blocks: Vec = { + let indexed_blocks: Vec = { let chain = self.chain.read(); new_blocks_hashes.iter() .filter_map(|h| chain.storage().block(db::BlockRef::Hash(h.clone()))) diff --git a/sync/src/synchronization_verifier.rs b/sync/src/synchronization_verifier.rs index c1c9492a..5c71eae9 100644 --- a/sync/src/synchronization_verifier.rs +++ b/sync/src/synchronization_verifier.rs @@ -2,7 +2,7 @@ use std::thread; use std::collections::{VecDeque, HashSet}; use std::sync::Arc; use std::sync::mpsc::{channel, Sender, Receiver}; -use chain::{Transaction, OutPoint, TransactionOutput}; +use chain::{Transaction, OutPoint, TransactionOutput, IndexedBlock}; use network::Magic; use miner::{HashedOutPoint, DoubleSpendCheckResult}; use primitives::hash::H256; diff --git a/verification/src/canon.rs b/verification/src/canon.rs index 9b3e379a..dd8f94ff 100644 --- a/verification/src/canon.rs +++ b/verification/src/canon.rs @@ -1,6 +1,6 @@ use std::ops; use primitives::hash::H256; -use db::{IndexedBlock, IndexedTransaction, IndexedBlockHeader}; +use chain::{IndexedBlock, IndexedTransaction, IndexedBlockHeader}; /// Blocks whose parents are known to be in the chain #[derive(Clone, Copy)] diff --git a/verification/src/chain_verifier.rs b/verification/src/chain_verifier.rs index 3fa700e3..8501a9dc 100644 --- a/verification/src/chain_verifier.rs +++ b/verification/src/chain_verifier.rs @@ -1,10 +1,10 @@ //! Bitcoin chain verifier use hash::H256; -use db::{self, IndexedBlockHeader, BlockLocation, PreviousTransactionOutputProvider, BlockHeaderProvider, TransactionOutputObserver}; +use chain::{IndexedBlock, IndexedBlockHeader, BlockHeader, Transaction}; +use db::{BlockLocation, SharedStore, PreviousTransactionOutputProvider, BlockHeaderProvider, TransactionOutputObserver}; use network::Magic; use error::{Error, TransactionError}; -use {Verify, chain}; use canon::{CanonBlock, CanonTransaction}; use duplex_store::{DuplexTransactionOutputProvider, NoopStore}; use verify_chain::ChainVerifier; @@ -12,6 +12,7 @@ use verify_header::HeaderVerifier; use verify_transaction::MemoryPoolTransactionVerifier; use accept_chain::ChainAcceptor; use accept_transaction::MemoryPoolTransactionAcceptor; +use Verify; #[derive(PartialEq, Debug)] /// Block verification chain @@ -28,13 +29,13 @@ pub enum Chain { pub type VerificationResult = Result; pub struct BackwardsCompatibleChainVerifier { - store: db::SharedStore, + store: SharedStore, skip_pow: bool, network: Magic, } impl BackwardsCompatibleChainVerifier { - pub fn new(store: db::SharedStore, network: Magic) -> Self { + pub fn new(store: SharedStore, network: Magic) -> Self { BackwardsCompatibleChainVerifier { store: store, skip_pow: false, @@ -48,7 +49,7 @@ impl BackwardsCompatibleChainVerifier { self } - fn verify_block(&self, block: &db::IndexedBlock) -> VerificationResult { + fn verify_block(&self, block: &IndexedBlock) -> VerificationResult { let current_time = ::time::get_time().sec as u32; // first run pre-verification let chain_verifier = ChainVerifier::new(block, self.network, current_time); @@ -77,7 +78,7 @@ impl BackwardsCompatibleChainVerifier { &self, _block_header_provider: &BlockHeaderProvider, hash: &H256, - header: &chain::BlockHeader + header: &BlockHeader ) -> Result<(), Error> { // let's do only preverifcation // TODO: full verification @@ -92,7 +93,7 @@ impl BackwardsCompatibleChainVerifier { prevout_provider: &T, height: u32, time: u32, - transaction: &chain::Transaction, + transaction: &Transaction, ) -> Result<(), TransactionError> where T: PreviousTransactionOutputProvider + TransactionOutputObserver { let indexed_tx = transaction.clone().into(); // let's do preverification first @@ -117,7 +118,7 @@ impl BackwardsCompatibleChainVerifier { } impl Verify for BackwardsCompatibleChainVerifier { - fn verify(&self, block: &db::IndexedBlock) -> VerificationResult { + fn verify(&self, block: &IndexedBlock) -> VerificationResult { let result = self.verify_block(block); trace!( target: "verification", "Block {} (transactions: {}) verification finished. Result {:?}", @@ -132,7 +133,8 @@ impl Verify for BackwardsCompatibleChainVerifier { #[cfg(test)] mod tests { use std::sync::Arc; - use db::{TestStorage, Storage, Store, BlockStapler, IndexedBlock}; + use chain::IndexedBlock; + use db::{TestStorage, Storage, Store, BlockStapler}; use network::Magic; use devtools::RandomTempPath; use {script, test_data}; diff --git a/verification/src/lib.rs b/verification/src/lib.rs index a5db9899..91e40b72 100644 --- a/verification/src/lib.rs +++ b/verification/src/lib.rs @@ -112,5 +112,5 @@ pub use work::{work_required, is_valid_proof_of_work, is_valid_proof_of_work_has /// Interface for block verification pub trait Verify : Send + Sync { - fn verify(&self, block: &db::IndexedBlock) -> VerificationResult; + fn verify(&self, block: &chain::IndexedBlock) -> VerificationResult; } diff --git a/verification/src/verify_block.rs b/verification/src/verify_block.rs index cb8937c0..9672a272 100644 --- a/verification/src/verify_block.rs +++ b/verification/src/verify_block.rs @@ -1,5 +1,5 @@ use std::collections::HashSet; -use db::IndexedBlock; +use chain::IndexedBlock; use sigops::transaction_sigops; use duplex_store::NoopStore; use error::{Error, TransactionError}; diff --git a/verification/src/verify_chain.rs b/verification/src/verify_chain.rs index 84c663cd..bce19e14 100644 --- a/verification/src/verify_chain.rs +++ b/verification/src/verify_chain.rs @@ -1,5 +1,5 @@ use rayon::prelude::{IntoParallelRefIterator, IndexedParallelIterator, ParallelIterator}; -use db::IndexedBlock; +use chain::IndexedBlock; use network::Magic; use error::Error; use verify_block::BlockVerifier; diff --git a/verification/src/verify_header.rs b/verification/src/verify_header.rs index f71a0d6f..d8d05191 100644 --- a/verification/src/verify_header.rs +++ b/verification/src/verify_header.rs @@ -1,5 +1,5 @@ use primitives::compact::Compact; -use db::IndexedBlockHeader; +use chain::IndexedBlockHeader; use network::Magic; use work::is_valid_proof_of_work; use error::Error; diff --git a/verification/src/verify_transaction.rs b/verification/src/verify_transaction.rs index 49647e40..9e3f7a34 100644 --- a/verification/src/verify_transaction.rs +++ b/verification/src/verify_transaction.rs @@ -1,6 +1,6 @@ use std::ops; use serialization::Serializable; -use db::IndexedTransaction; +use chain::IndexedTransaction; use duplex_store::NoopStore; use sigops::transaction_sigops; use error::TransactionError;