few optimizations with Borrow and AsRef
This commit is contained in:
parent
80f17977c1
commit
6ecdfd78c5
|
@ -2,21 +2,21 @@ use crypto::dhash256;
|
||||||
use hash::{H256, H512};
|
use hash::{H256, H512};
|
||||||
|
|
||||||
#[inline]
|
#[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();
|
let mut result = H512::default();
|
||||||
result[0..32].copy_from_slice(&**a);
|
result[0..32].copy_from_slice(&**a.as_ref());
|
||||||
result[32..64].copy_from_slice(&**b);
|
result[32..64].copy_from_slice(&**b.as_ref());
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculates the root of the merkle tree
|
/// Calculates the root of the merkle tree
|
||||||
/// https://en.bitcoin.it/wiki/Protocol_documentation#Merkle_Trees
|
/// 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 {
|
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;
|
let mut i = 0;
|
||||||
while i + 1 < hashes.len() {
|
while i + 1 < hashes.len() {
|
||||||
row.push(merkle_node_hash(&hashes[i], &hashes[i + 1]));
|
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
|
/// 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))
|
dhash256(&*concat(left, right))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,11 +46,14 @@ mod tests {
|
||||||
// https://blockchain.info/block/000000000043a8c0fd1d6f726790caa2a406010d19efd2780db27bdbbd93baf6
|
// https://blockchain.info/block/000000000043a8c0fd1d6f726790caa2a406010d19efd2780db27bdbbd93baf6
|
||||||
#[test]
|
#[test]
|
||||||
fn test_merkle_root_with_2_hashes() {
|
fn test_merkle_root_with_2_hashes() {
|
||||||
|
assert_eq!(result, expected);
|
||||||
let tx1 = H256::from_reversed_str("c06fbab289f723c6261d3030ddb6be121f7d2508d77862bb1e484f5cd7f92b25");
|
let tx1 = H256::from_reversed_str("c06fbab289f723c6261d3030ddb6be121f7d2508d77862bb1e484f5cd7f92b25");
|
||||||
let tx2 = H256::from_reversed_str("5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2");
|
let tx2 = H256::from_reversed_str("5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2");
|
||||||
let expected = H256::from_reversed_str("8fb300e3fdb6f30a4c67233b997f99fdd518b968b9a3fd65857bfe78b2600719");
|
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!(result, expected);
|
||||||
|
assert_eq!(result2, expected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use primitives::hash::H256;
|
use primitives::hash::H256;
|
||||||
use chain::{Block, OutPoint, TransactionOutput, merkle_root};
|
use chain::{Block, OutPoint, TransactionOutput, merkle_root, Transaction};
|
||||||
use serialization::{Serializable, CompactInteger};
|
use serialization::{Serializable, serialized_list_size};
|
||||||
use indexed_header::IndexedBlockHeader;
|
use indexed_header::IndexedBlockHeader;
|
||||||
use indexed_transaction::IndexedTransaction;
|
use indexed_transaction::IndexedTransaction;
|
||||||
use {TransactionOutputObserver, PreviousTransactionOutputProvider};
|
use {TransactionOutputObserver, PreviousTransactionOutputProvider};
|
||||||
|
@ -74,13 +74,13 @@ impl IndexedBlock {
|
||||||
|
|
||||||
pub fn size(&self) -> usize {
|
pub fn size(&self) -> usize {
|
||||||
let header_size = self.header.raw.serialized_size();
|
let header_size = self.header.raw.serialized_size();
|
||||||
let txs_len_size = CompactInteger::from(self.transactions.len()).serialized_size();
|
let transactions = self.transactions.iter().map(|tx| &tx.raw).collect::<Vec<_>>();
|
||||||
let txs_size = self.transactions.iter().map(|tx| tx.raw.serialized_size()).sum::<usize>();
|
let txs_size = serialized_list_size::<Transaction, &Transaction>(&transactions);
|
||||||
header_size + txs_len_size + txs_size
|
header_size + txs_size
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn merkle_root(&self) -> H256 {
|
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 {
|
pub fn is_final(&self, height: u32) -> bool {
|
||||||
|
|
|
@ -137,7 +137,7 @@ impl<'a> V31402AsV0<'a> {
|
||||||
impl<'a> Serializable for V31402AsV0<'a> {
|
impl<'a> Serializable for V31402AsV0<'a> {
|
||||||
fn serialize(&self, stream: &mut Stream) {
|
fn serialize(&self, stream: &mut Stream) {
|
||||||
let vec_ref: Vec<&'a NetAddress> = self.v.addresses.iter().map(|x| &x.address).collect();
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,8 +104,9 @@ pub fn find_solution<T>(block: BlockTemplate, mut coinbase_transaction: T) -> Op
|
||||||
coinbase_transaction.set_extranonce(&extranonce);
|
coinbase_transaction.set_extranonce(&extranonce);
|
||||||
|
|
||||||
// recalculate merkle root hash
|
// recalculate merkle root hash
|
||||||
let mut merkle_tree = vec![coinbase_transaction.hash()];
|
let coinbase_hash = coinbase_transaction.hash();
|
||||||
merkle_tree.extend(block.transactions.iter().map(|tx| tx.hash.clone()));
|
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);
|
let merkle_root_hash = merkle_root(&merkle_tree);
|
||||||
|
|
||||||
// update header with new merkle root hash
|
// update header with new merkle root hash
|
||||||
|
|
|
@ -13,6 +13,12 @@ macro_rules! impl_hash {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AsRef<$name> for $name {
|
||||||
|
fn as_ref(&self) -> &$name {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Clone for $name {
|
impl Clone for $name {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
let mut result = Self::default();
|
let mut result = Self::default();
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
//! Stream used for serialization.
|
//! Stream used for serialization.
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
|
use std::borrow::Borrow;
|
||||||
use compact_integer::CompactInteger;
|
use compact_integer::CompactInteger;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
|
|
||||||
|
@ -9,9 +10,9 @@ pub fn serialize(t: &Serializable) -> Bytes {
|
||||||
stream.out()
|
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() +
|
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 {
|
pub trait Serializable {
|
||||||
|
@ -51,18 +52,10 @@ impl Stream {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Appends a list of serializable structs to the end of the 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);
|
CompactInteger::from(t.len()).serialize(self);
|
||||||
for i in t {
|
for i in t {
|
||||||
i.serialize(self);
|
i.borrow().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);
|
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue