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}; 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))
} }
@ -50,7 +50,9 @@ mod tests {
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);
} }
} }

View File

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

View File

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

View File

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

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(), &tx0), 0);
assert_eq!(transaction_fee_rate(db.as_transaction_provider(), &tx1), 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 { impl Clone for $name {
fn clone(&self) -> Self { fn clone(&self) -> Self {
let mut result = Self::default(); let mut result = Self::default();

View File

@ -10,5 +10,5 @@ pub use self::traits::BlockChain;
pub use self::traits::Network; pub use self::traits::Network;
pub use self::impls::{RawClient, RawClientCore}; pub use self::impls::{RawClient, RawClientCore};
pub use self::impls::{MinerClient, MinerClientCore}; pub use self::impls::{MinerClient, MinerClientCore};
pub use self::impls::{NetworkClient, NetworkClientCore};
pub use self::impls::{BlockChainClient, BlockChainClientCore}; pub use self::impls::{BlockChainClient, BlockChainClientCore};
pub use self::impls::{NetworkClient, NetworkClientCore};

View File

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

View File

@ -1,12 +1,12 @@
//! Block builder //! Block builder
use super::genesis; use std::cell::Cell;
use chain;
use primitives::hash::H256; use primitives::hash::H256;
use primitives::bytes::Bytes; use primitives::bytes::Bytes;
use primitives::compact::Compact; use primitives::compact::Compact;
use chain;
use invoke::{Invoke, Identity}; use invoke::{Invoke, Identity};
use std::cell::Cell; use super::genesis;
thread_local! { thread_local! {
pub static TIMESTAMP_COUNTER: Cell<u32> = Cell::new(0); 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> { pub struct TransactionOutputBuilder<F=Identity> {
callback: F, callback: F,
value: u64, value: u64,
signature: Bytes, script_pubkey: Bytes,
} }
impl<F> TransactionOutputBuilder<F> where F: Invoke<chain::TransactionOutput> { impl<F> TransactionOutputBuilder<F> where F: Invoke<chain::TransactionOutput> {
fn with_callback(callback: F) -> Self { fn with_callback(callback: F) -> Self {
TransactionOutputBuilder { TransactionOutputBuilder {
callback: callback, 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, value: 0,
} }
} }
@ -394,20 +396,20 @@ impl<F> TransactionOutputBuilder<F> where F: Invoke<chain::TransactionOutput> {
self self
} }
pub fn signature(mut self, sig: &'static str) -> Self { pub fn script_pubkey(mut self, script_pubkey: &'static str) -> Self {
self.signature = sig.into(); self.script_pubkey = script_pubkey.into();
self self
} }
pub fn signature_bytes(mut self, sig: Bytes) -> Self { pub fn script_pubkey_bytes(mut self, script_pubkey: Bytes) -> Self {
self.signature = sig; self.script_pubkey = script_pubkey;
self self
} }
pub fn build(self) -> F::Result { pub fn build(self) -> F::Result {
self.callback.invoke( self.callback.invoke(
chain::TransactionOutput { chain::TransactionOutput {
script_pubkey: self.signature, script_pubkey: self.script_pubkey,
value: self.value, value: self.value,
} }
) )

View File

@ -40,23 +40,14 @@ impl<'a> ChainAcceptor<'a> {
pub fn check(&self) -> Result<(), Error> { pub fn check(&self) -> Result<(), Error> {
try!(self.block.check()); try!(self.block.check());
try!(self.header.check()); try!(self.header.check());
try!(self.check_transactions_with_eval(true)); try!(self.check_transactions());
Ok(()) Ok(())
} }
/// backwards test compatibility fn check_transactions(&self) -> Result<(), Error> {
/// 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> {
self.transactions.par_iter() self.transactions.par_iter()
.enumerate() .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)) .reduce(|| Ok(()), |acc, check| acc.and(check))
} }
} }

View File

@ -53,20 +53,6 @@ impl<'a> TransactionAcceptor<'a> {
try!(self.eval.check()); try!(self.eval.check());
Ok(()) 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> { pub struct MemoryPoolTransactionAcceptor<'a> {

View File

@ -30,7 +30,6 @@ pub type VerificationResult = Result<Chain, Error>;
pub struct BackwardsCompatibleChainVerifier { pub struct BackwardsCompatibleChainVerifier {
store: db::SharedStore, store: db::SharedStore,
skip_pow: bool, skip_pow: bool,
skip_sig: bool,
network: Magic, network: Magic,
} }
@ -39,7 +38,6 @@ impl BackwardsCompatibleChainVerifier {
BackwardsCompatibleChainVerifier { BackwardsCompatibleChainVerifier {
store: store, store: store,
skip_pow: false, skip_pow: false,
skip_sig: false,
network: network, network: network,
} }
} }
@ -50,12 +48,6 @@ impl BackwardsCompatibleChainVerifier {
self self
} }
#[cfg(test)]
pub fn signatures_skip(mut self) -> Self {
self.skip_sig = true;
self
}
fn verify_block(&self, block: &db::IndexedBlock) -> VerificationResult { fn verify_block(&self, block: &db::IndexedBlock) -> VerificationResult {
let current_time = ::time::get_time().sec as u32; let current_time = ::time::get_time().sec as u32;
// first run pre-verification // first run pre-verification
@ -73,7 +65,7 @@ impl BackwardsCompatibleChainVerifier {
// now do full verification // now do full verification
let canon_block = CanonBlock::new(block); let canon_block = CanonBlock::new(block);
let chain_acceptor = ChainAcceptor::new(&self.store, self.network, canon_block, location.height()); 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 { match location {
BlockLocation::Main(_) => Ok(Chain::Main), BlockLocation::Main(_) => Ok(Chain::Main),
@ -206,7 +198,7 @@ mod tests {
.merkled_header().parent(genesis.hash()).build() .merkled_header().parent(genesis.hash()).build()
.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( let expected = Err(Error::Transaction(
1, 1,
@ -247,7 +239,7 @@ mod tests {
.merkled_header().parent(genesis.hash()).build() .merkled_header().parent(genesis.hash()).build()
.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); let expected = Ok(Chain::Main);
assert_eq!(expected, verifier.verify(&block.into())); assert_eq!(expected, verifier.verify(&block.into()));
@ -289,7 +281,7 @@ mod tests {
.merkled_header().parent(genesis.hash()).build() .merkled_header().parent(genesis.hash()).build()
.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); let expected = Ok(Chain::Main);
assert_eq!(expected, verifier.verify(&block.into())); assert_eq!(expected, verifier.verify(&block.into()));
@ -333,7 +325,7 @@ mod tests {
.merkled_header().parent(genesis.hash()).build() .merkled_header().parent(genesis.hash()).build()
.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)); let expected = Err(Error::Transaction(2, TransactionError::Overspend));
assert_eq!(expected, verifier.verify(&block.into())); assert_eq!(expected, verifier.verify(&block.into()));
@ -377,7 +369,7 @@ mod tests {
.merkled_header().parent(best_hash).build() .merkled_header().parent(best_hash).build()
.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); let expected = Ok(Chain::Main);
@ -430,7 +422,7 @@ mod tests {
.build() .build()
.into(); .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); let expected = Err(Error::MaximumSigops);
assert_eq!(expected, verifier.verify(&block.into())); assert_eq!(expected, verifier.verify(&block.into()));
@ -457,7 +449,7 @@ mod tests {
.build() .build()
.into(); .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 { let expected = Err(Error::CoinbaseOverspend {
expected_max: 5000000000, expected_max: 5000000000,