diff --git a/chain/src/merkle_root.rs b/chain/src/merkle_root.rs index 40ffdb63..8273bfdd 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)) } @@ -46,11 +46,14 @@ mod tests { // https://blockchain.info/block/000000000043a8c0fd1d6f726790caa2a406010d19efd2780db27bdbbd93baf6 #[test] fn test_merkle_root_with_2_hashes() { + assert_eq!(result, expected); let tx1 = H256::from_reversed_str("c06fbab289f723c6261d3030ddb6be121f7d2508d77862bb1e484f5cd7f92b25"); 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/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/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 }