TransactionOutputGenerator always creates spendable transactions
This commit is contained in:
parent
80f17977c1
commit
8d7a45f2ca
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue