Merge branch 'master' into rpc_raw_continue
This commit is contained in:
commit
ea0727a4de
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
)
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue