diff --git a/chain/src/merkle_root.rs b/chain/src/merkle_root.rs index 40ffdb63..adce114e 100644 --- a/chain/src/merkle_root.rs +++ b/chain/src/merkle_root.rs @@ -2,21 +2,21 @@ use crypto::dhash256; use hash::{H256, H512}; #[inline] -fn concat(a: &H256, b: &H256) -> H512 { +fn concat(a: T, b: T) -> H512 where T: AsRef { let mut result = H512::default(); - result[0..32].copy_from_slice(&**a); - result[32..64].copy_from_slice(&**b); + result[0..32].copy_from_slice(&**a.as_ref()); + result[32..64].copy_from_slice(&**b.as_ref()); result } /// Calculates the root of the merkle tree /// https://en.bitcoin.it/wiki/Protocol_documentation#Merkle_Trees -pub fn merkle_root(hashes: &[H256]) -> H256 { +pub fn merkle_root(hashes: &[T]) -> H256 where T: AsRef { if hashes.len() == 1 { - return hashes[0].clone(); + return hashes[0].as_ref().clone(); } - let mut row = vec![]; + let mut row = Vec::with_capacity(hashes.len() / 2); let mut i = 0; while i + 1 < hashes.len() { row.push(merkle_node_hash(&hashes[i], &hashes[i + 1])); @@ -33,7 +33,7 @@ pub fn merkle_root(hashes: &[H256]) -> H256 { } /// Calculate merkle tree node hash -pub fn merkle_node_hash(left: &H256, right: &H256) -> H256 { +pub fn merkle_node_hash(left: T, right: T) -> H256 where T: AsRef { dhash256(&*concat(left, right)) } @@ -50,7 +50,9 @@ mod tests { let tx2 = H256::from_reversed_str("5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2"); let expected = H256::from_reversed_str("8fb300e3fdb6f30a4c67233b997f99fdd518b968b9a3fd65857bfe78b2600719"); - let result = merkle_root(&[tx1, tx2]); + let result = merkle_root(&[&tx1, &tx2]); + let result2 = merkle_root(&[tx1, tx2]); assert_eq!(result, expected); + assert_eq!(result2, expected); } } diff --git a/db/src/indexed_block.rs b/db/src/indexed_block.rs index 7a31680f..dee6936b 100644 --- a/db/src/indexed_block.rs +++ b/db/src/indexed_block.rs @@ -1,6 +1,6 @@ use primitives::hash::H256; -use chain::{Block, OutPoint, TransactionOutput, merkle_root}; -use serialization::{Serializable, CompactInteger}; +use chain::{Block, OutPoint, TransactionOutput, merkle_root, Transaction}; +use serialization::{Serializable, serialized_list_size}; use indexed_header::IndexedBlockHeader; use indexed_transaction::IndexedTransaction; use {TransactionOutputObserver, PreviousTransactionOutputProvider}; @@ -74,13 +74,13 @@ impl IndexedBlock { pub fn size(&self) -> usize { let header_size = self.header.raw.serialized_size(); - let txs_len_size = CompactInteger::from(self.transactions.len()).serialized_size(); - let txs_size = self.transactions.iter().map(|tx| tx.raw.serialized_size()).sum::(); - header_size + txs_len_size + txs_size + let transactions = self.transactions.iter().map(|tx| &tx.raw).collect::>(); + let txs_size = serialized_list_size::(&transactions); + header_size + txs_size } pub fn merkle_root(&self) -> H256 { - merkle_root(&self.transactions.iter().map(|tx| tx.hash.clone()).collect::>()) + merkle_root(&self.transactions.iter().map(|tx| &tx.hash).collect::>()) } pub fn is_final(&self, height: u32) -> bool { diff --git a/message/src/types/addr.rs b/message/src/types/addr.rs index 985bb7c0..079f9f90 100644 --- a/message/src/types/addr.rs +++ b/message/src/types/addr.rs @@ -137,7 +137,7 @@ impl<'a> V31402AsV0<'a> { impl<'a> Serializable for V31402AsV0<'a> { fn serialize(&self, stream: &mut Stream) { let vec_ref: Vec<&'a NetAddress> = self.v.addresses.iter().map(|x| &x.address).collect(); - stream.append_list_ref(&vec_ref); + stream.append_list::(&vec_ref); } } diff --git a/miner/src/cpu_miner.rs b/miner/src/cpu_miner.rs index b02eb820..7e3c3f03 100644 --- a/miner/src/cpu_miner.rs +++ b/miner/src/cpu_miner.rs @@ -104,8 +104,9 @@ pub fn find_solution(block: BlockTemplate, mut coinbase_transaction: T) -> Op coinbase_transaction.set_extranonce(&extranonce); // recalculate merkle root hash - let mut merkle_tree = vec![coinbase_transaction.hash()]; - merkle_tree.extend(block.transactions.iter().map(|tx| tx.hash.clone())); + let coinbase_hash = coinbase_transaction.hash(); + let mut merkle_tree = vec![&coinbase_hash]; + merkle_tree.extend(block.transactions.iter().map(|tx| &tx.hash)); let merkle_root_hash = merkle_root(&merkle_tree); // update header with new merkle root hash diff --git a/miner/src/fee.rs b/miner/src/fee.rs index 5a5c7e81..53ba6bf7 100644 --- a/miner/src/fee.rs +++ b/miner/src/fee.rs @@ -54,6 +54,6 @@ mod tests { assert_eq!(transaction_fee_rate(db.as_transaction_provider(), &tx0), 0); assert_eq!(transaction_fee_rate(db.as_transaction_provider(), &tx1), 0); - assert_eq!(transaction_fee_rate(db.as_transaction_provider(), &tx2), 4_950); + assert_eq!(transaction_fee_rate(db.as_transaction_provider(), &tx2), 4_901); } } diff --git a/primitives/src/hash.rs b/primitives/src/hash.rs index b2f20db6..53df7548 100644 --- a/primitives/src/hash.rs +++ b/primitives/src/hash.rs @@ -13,6 +13,12 @@ macro_rules! impl_hash { } } + impl AsRef<$name> for $name { + fn as_ref(&self) -> &$name { + self + } + } + impl Clone for $name { fn clone(&self) -> Self { let mut result = Self::default(); diff --git a/rpc/src/v1/mod.rs b/rpc/src/v1/mod.rs index 54b1b345..8557cb78 100644 --- a/rpc/src/v1/mod.rs +++ b/rpc/src/v1/mod.rs @@ -10,5 +10,5 @@ pub use self::traits::BlockChain; pub use self::traits::Network; pub use self::impls::{RawClient, RawClientCore}; pub use self::impls::{MinerClient, MinerClientCore}; -pub use self::impls::{NetworkClient, NetworkClientCore}; pub use self::impls::{BlockChainClient, BlockChainClientCore}; +pub use self::impls::{NetworkClient, NetworkClientCore}; diff --git a/serialization/src/stream.rs b/serialization/src/stream.rs index 9b124ef0..be1403ee 100644 --- a/serialization/src/stream.rs +++ b/serialization/src/stream.rs @@ -1,5 +1,6 @@ //! Stream used for serialization. use std::io::{self, Write}; +use std::borrow::Borrow; use compact_integer::CompactInteger; use bytes::Bytes; @@ -9,9 +10,9 @@ pub fn serialize(t: &Serializable) -> Bytes { stream.out() } -pub fn serialized_list_size(t: &[T]) -> usize where T: Serializable { +pub fn serialized_list_size(t: &[K]) -> usize where T: Serializable, K: Borrow { CompactInteger::from(t.len()).serialized_size() + - t.iter().map(Serializable::serialized_size).sum::() + t.iter().map(Borrow::borrow).map(Serializable::serialized_size).sum::() } pub trait Serializable { @@ -51,18 +52,10 @@ impl Stream { } /// Appends a list of serializable structs to the end of the stream. - pub fn append_list(&mut self, t: &[T]) -> &mut Self where T: Serializable { + pub fn append_list(&mut self, t: &[K]) -> &mut Self where T: Serializable, K: Borrow { CompactInteger::from(t.len()).serialize(self); for i in t { - i.serialize(self); - } - self - } - - pub fn append_list_ref(&mut self, t: &[&T]) -> &mut Self where T: Serializable { - CompactInteger::from(t.len()).serialize(self); - for i in t { - i.serialize(self); + i.borrow().serialize(self); } self } diff --git a/test-data/src/block.rs b/test-data/src/block.rs index 78f0fb85..da795574 100644 --- a/test-data/src/block.rs +++ b/test-data/src/block.rs @@ -1,12 +1,12 @@ //! Block builder -use super::genesis; -use chain; +use std::cell::Cell; use primitives::hash::H256; use primitives::bytes::Bytes; use primitives::compact::Compact; +use chain; use invoke::{Invoke, Identity}; -use std::cell::Cell; +use super::genesis; thread_local! { pub static TIMESTAMP_COUNTER: Cell = Cell::new(0); @@ -377,14 +377,16 @@ impl TransactionInputBuilder where F: Invoke { pub struct TransactionOutputBuilder { callback: F, value: u64, - signature: Bytes, + script_pubkey: Bytes, } impl TransactionOutputBuilder where F: Invoke { fn with_callback(callback: F) -> Self { TransactionOutputBuilder { callback: callback, - signature: Bytes::new_with_len(0), + // 0x51 is OP_1 opcode + // so the evaluation is always true + script_pubkey: vec![0x51].into(), value: 0, } } @@ -394,20 +396,20 @@ impl TransactionOutputBuilder where F: Invoke { self } - pub fn signature(mut self, sig: &'static str) -> Self { - self.signature = sig.into(); + pub fn script_pubkey(mut self, script_pubkey: &'static str) -> Self { + self.script_pubkey = script_pubkey.into(); self } - pub fn signature_bytes(mut self, sig: Bytes) -> Self { - self.signature = sig; + pub fn script_pubkey_bytes(mut self, script_pubkey: Bytes) -> Self { + self.script_pubkey = script_pubkey; self } pub fn build(self) -> F::Result { self.callback.invoke( chain::TransactionOutput { - script_pubkey: self.signature, + script_pubkey: self.script_pubkey, value: self.value, } ) diff --git a/verification/src/accept_chain.rs b/verification/src/accept_chain.rs index 579647da..3b82fef5 100644 --- a/verification/src/accept_chain.rs +++ b/verification/src/accept_chain.rs @@ -40,23 +40,14 @@ impl<'a> ChainAcceptor<'a> { pub fn check(&self) -> Result<(), Error> { try!(self.block.check()); try!(self.header.check()); - try!(self.check_transactions_with_eval(true)); + try!(self.check_transactions()); Ok(()) } - /// backwards test compatibility - /// TODO: get rid of this - pub fn check_with_eval(&self, eval: bool) -> Result<(), Error> { - try!(self.block.check()); - try!(self.header.check()); - try!(self.check_transactions_with_eval(eval)); - Ok(()) - } - - fn check_transactions_with_eval(&self, eval: bool) -> Result<(), Error> { + fn check_transactions(&self) -> Result<(), Error> { self.transactions.par_iter() .enumerate() - .fold(|| Ok(()), |result, (index, tx)| result.and_then(|_| tx.check_with_eval(eval).map_err(|err| Error::Transaction(index, err)))) + .fold(|| Ok(()), |result, (index, tx)| result.and_then(|_| tx.check().map_err(|err| Error::Transaction(index, err)))) .reduce(|| Ok(()), |acc, check| acc.and(check)) } } diff --git a/verification/src/accept_transaction.rs b/verification/src/accept_transaction.rs index 08390954..4a045ac9 100644 --- a/verification/src/accept_transaction.rs +++ b/verification/src/accept_transaction.rs @@ -53,20 +53,6 @@ impl<'a> TransactionAcceptor<'a> { try!(self.eval.check()); Ok(()) } - - /// backwards test compatibility - /// TODO: get rid of this - pub fn check_with_eval(&self, eval: bool) -> Result<(), TransactionError> { - try!(self.bip30.check()); - try!(self.missing_inputs.check()); - try!(self.maturity.check()); - try!(self.overspent.check()); - try!(self.double_spent.check()); - if eval { - try!(self.eval.check()); - } - Ok(()) - } } pub struct MemoryPoolTransactionAcceptor<'a> { diff --git a/verification/src/chain_verifier.rs b/verification/src/chain_verifier.rs index 658b07b8..3fa700e3 100644 --- a/verification/src/chain_verifier.rs +++ b/verification/src/chain_verifier.rs @@ -30,7 +30,6 @@ pub type VerificationResult = Result; pub struct BackwardsCompatibleChainVerifier { store: db::SharedStore, skip_pow: bool, - skip_sig: bool, network: Magic, } @@ -39,7 +38,6 @@ impl BackwardsCompatibleChainVerifier { BackwardsCompatibleChainVerifier { store: store, skip_pow: false, - skip_sig: false, network: network, } } @@ -50,12 +48,6 @@ impl BackwardsCompatibleChainVerifier { self } - #[cfg(test)] - pub fn signatures_skip(mut self) -> Self { - self.skip_sig = true; - self - } - fn verify_block(&self, block: &db::IndexedBlock) -> VerificationResult { let current_time = ::time::get_time().sec as u32; // first run pre-verification @@ -73,7 +65,7 @@ impl BackwardsCompatibleChainVerifier { // now do full verification let canon_block = CanonBlock::new(block); let chain_acceptor = ChainAcceptor::new(&self.store, self.network, canon_block, location.height()); - try!(chain_acceptor.check_with_eval(!self.skip_sig)); + try!(chain_acceptor.check()); match location { BlockLocation::Main(_) => Ok(Chain::Main), @@ -206,7 +198,7 @@ mod tests { .merkled_header().parent(genesis.hash()).build() .build(); - let verifier = ChainVerifier::new(Arc::new(storage), Magic::Testnet).pow_skip().signatures_skip(); + let verifier = ChainVerifier::new(Arc::new(storage), Magic::Testnet).pow_skip(); let expected = Err(Error::Transaction( 1, @@ -247,7 +239,7 @@ mod tests { .merkled_header().parent(genesis.hash()).build() .build(); - let verifier = ChainVerifier::new(Arc::new(storage), Magic::Testnet).pow_skip().signatures_skip(); + let verifier = ChainVerifier::new(Arc::new(storage), Magic::Testnet).pow_skip(); let expected = Ok(Chain::Main); assert_eq!(expected, verifier.verify(&block.into())); @@ -289,7 +281,7 @@ mod tests { .merkled_header().parent(genesis.hash()).build() .build(); - let verifier = ChainVerifier::new(Arc::new(storage), Magic::Testnet).pow_skip().signatures_skip(); + let verifier = ChainVerifier::new(Arc::new(storage), Magic::Testnet).pow_skip(); let expected = Ok(Chain::Main); assert_eq!(expected, verifier.verify(&block.into())); @@ -333,7 +325,7 @@ mod tests { .merkled_header().parent(genesis.hash()).build() .build(); - let verifier = ChainVerifier::new(Arc::new(storage), Magic::Testnet).pow_skip().signatures_skip(); + let verifier = ChainVerifier::new(Arc::new(storage), Magic::Testnet).pow_skip(); let expected = Err(Error::Transaction(2, TransactionError::Overspend)); assert_eq!(expected, verifier.verify(&block.into())); @@ -377,7 +369,7 @@ mod tests { .merkled_header().parent(best_hash).build() .build(); - let verifier = ChainVerifier::new(Arc::new(storage), Magic::Testnet).pow_skip().signatures_skip(); + let verifier = ChainVerifier::new(Arc::new(storage), Magic::Testnet).pow_skip(); let expected = Ok(Chain::Main); @@ -430,7 +422,7 @@ mod tests { .build() .into(); - let verifier = ChainVerifier::new(Arc::new(storage), Magic::Testnet).pow_skip().signatures_skip(); + let verifier = ChainVerifier::new(Arc::new(storage), Magic::Testnet).pow_skip(); let expected = Err(Error::MaximumSigops); assert_eq!(expected, verifier.verify(&block.into())); @@ -457,7 +449,7 @@ mod tests { .build() .into(); - let verifier = ChainVerifier::new(Arc::new(storage), Magic::Testnet).pow_skip().signatures_skip(); + let verifier = ChainVerifier::new(Arc::new(storage), Magic::Testnet).pow_skip(); let expected = Err(Error::CoinbaseOverspend { expected_max: 5000000000,