few optimizations with Borrow and AsRef

This commit is contained in:
debris 2016-12-13 13:33:06 +01:00
parent 80f17977c1
commit 6ecdfd78c5
6 changed files with 32 additions and 29 deletions

View File

@ -2,21 +2,21 @@ use crypto::dhash256;
use hash::{H256, H512};
#[inline]
fn concat(a: &H256, b: &H256) -> H512 {
fn concat<T>(a: T, b: T) -> H512 where T: AsRef<H256> {
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<T>(hashes: &[T]) -> H256 where T: AsRef<H256> {
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<T>(left: T, right: T) -> H256 where T: AsRef<H256> {
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);
}
}

View File

@ -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::<usize>();
header_size + txs_len_size + txs_size
let transactions = self.transactions.iter().map(|tx| &tx.raw).collect::<Vec<_>>();
let txs_size = serialized_list_size::<Transaction, &Transaction>(&transactions);
header_size + txs_size
}
pub fn merkle_root(&self) -> H256 {
merkle_root(&self.transactions.iter().map(|tx| tx.hash.clone()).collect::<Vec<_>>())
merkle_root(&self.transactions.iter().map(|tx| &tx.hash).collect::<Vec<&H256>>())
}
pub fn is_final(&self, height: u32) -> bool {

View File

@ -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::<NetAddress, &'a NetAddress>(&vec_ref);
}
}

View File

@ -104,8 +104,9 @@ pub fn find_solution<T>(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

View File

@ -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();

View File

@ -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: &[T]) -> usize where T: Serializable {
pub fn serialized_list_size<T, K>(t: &[K]) -> usize where T: Serializable, K: Borrow<T> {
CompactInteger::from(t.len()).serialized_size() +
t.iter().map(Serializable::serialized_size).sum::<usize>()
t.iter().map(Borrow::borrow).map(Serializable::serialized_size).sum::<usize>()
}
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<T>(&mut self, t: &[T]) -> &mut Self where T: Serializable {
pub fn append_list<T, K>(&mut self, t: &[K]) -> &mut Self where T: Serializable, K: Borrow<T> {
CompactInteger::from(t.len()).serialize(self);
for i in t {
i.serialize(self);
}
self
}
pub fn append_list_ref<T>(&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
}