Merge branch 'master' into rpc_raw_continue

This commit is contained in:
Svyatoslav Nikolsky 2016-12-13 16:51:02 +03:00
commit ea0727a4de
12 changed files with 56 additions and 83 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))
}
@ -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);
}
}

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

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

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

@ -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};

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
}

View File

@ -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<u32> = Cell::new(0);
@ -377,14 +377,16 @@ impl<F> TransactionInputBuilder<F> where F: Invoke<chain::TransactionInput> {
pub struct TransactionOutputBuilder<F=Identity> {
callback: F,
value: u64,
signature: Bytes,
script_pubkey: Bytes,
}
impl<F> TransactionOutputBuilder<F> where F: Invoke<chain::TransactionOutput> {
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<F> TransactionOutputBuilder<F> where F: Invoke<chain::TransactionOutput> {
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,
}
)

View File

@ -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))
}
}

View File

@ -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> {

View File

@ -30,7 +30,6 @@ pub type VerificationResult = Result<Chain, Error>;
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,