diff --git a/test-data/src/block.rs b/test-data/src/block.rs new file mode 100644 index 00000000..341c6dff --- /dev/null +++ b/test-data/src/block.rs @@ -0,0 +1,204 @@ +//! Block builder + +use chain; +use primitives::hash::H256; +use invoke::{Invoke, Identity}; + +pub struct BlockBuilder { + callback: F, + header: Option, + transactions: Vec, +} + +impl BlockBuilder { + pub fn new() -> Self { + BlockBuilder::with_callback(Identity) + } +} + +impl BlockBuilder where F: Invoke { + pub fn with_callback(callback: F) -> Self { + BlockBuilder { + callback: callback, + header: None, + transactions: Vec::new(), + } + } + + pub fn with_header(mut self, header: chain::BlockHeader) -> Self { + self.header = Some(header); + self + } + + pub fn with_transaction(mut self, transaction: chain::Transaction) -> Self { + self.transactions.push(transaction); + self + } + + pub fn with_transactions(mut self, txs: I) -> Self + where I: IntoIterator + { + self.transactions.extend(txs); + self + } + + pub fn with_raw(mut self, raw: &'static str) -> Self { + let raw_block: chain::Block = raw.into(); + self.transactions = raw_block.transactions.to_vec(); + self.header = Some(raw_block.header().clone()); + self + } + + pub fn header(self) -> BlockHeaderBuilder { + BlockHeaderBuilder::with_callback(self) + } + + pub fn transaction(self) -> TransactionBuilder { + TransactionBuilder::with_callback(self) + } + + pub fn build(self) -> F::Result { + self.callback.invoke( + chain::Block::new( + self.header.unwrap(), + self.transactions, + ) + ) + } +} + +impl Invoke for BlockBuilder + where F: Invoke +{ + type Result = Self; + + fn invoke(self, header: chain::BlockHeader) -> Self { + self.with_header(header) + } +} + +impl Invoke for BlockBuilder + where F: Invoke +{ + type Result = Self; + + fn invoke(self, tx: chain::Transaction) -> Self { + self.with_transaction(tx) + } +} + +pub struct BlockHeaderBuilder { + callback: F, + time: u32, + parent: H256, + nonce: u32, + nbits: u32, + version: u32, + merkle_root: H256, +} + +impl BlockHeaderBuilder where F: Invoke { + pub fn with_callback(callback: F) -> Self { + BlockHeaderBuilder { + callback: callback, + time: 0, + nonce: 0, + merkle_root: H256::from(0), + parent: H256::from(0), + nbits: 0, + version: 1, + } + } + + pub fn parent(mut self, parent: H256) -> Self { + self.parent = parent; + self + } + + pub fn time(mut self, time: u32) -> Self { + self.time = time; + self + } + + pub fn merkle_root(mut self, merkle_root: H256) -> Self { + self.merkle_root = merkle_root; + self + } + + pub fn nbits(mut self, nbits: u32) -> Self { + self.nbits = nbits; + self + } + + pub fn nonce(mut self, nonce: u32) -> Self { + self.nonce = nonce; + self + } + + pub fn build(self) -> F::Result { + self.callback.invoke( + chain::BlockHeader { + time: self.time, + previous_header_hash: self.parent, + nbits: self.nbits, + nonce: self.nonce, + merkle_root_hash: self.merkle_root, + version: self.version, + } + ) + } +} + +pub struct TransactionBuilder { + callback: F, + version: i32, + lock_time: u32, + inputs: Vec, + outputs: Vec, +} + +impl TransactionBuilder where F: Invoke { + fn with_callback(callback: F) -> Self { + TransactionBuilder { + callback: callback, + version: 1, + lock_time: 0, + inputs: Vec::new(), + outputs: Vec::new(), + } + } + + pub fn lock_time(mut self, time: u32) -> Self { + self.lock_time = time; + self + } + + pub fn build(self) -> F::Result { + self.callback.invoke( + chain::Transaction { + lock_time: self.lock_time, + version: self.version, + inputs: self.inputs, + outputs: self.outputs, + } + ) + } +} + +pub fn block_builder() -> BlockBuilder { BlockBuilder::new() } + +#[test] +fn example1() { + let block = BlockBuilder::new().header().time(1000).build().build(); + assert_eq!(block.header().time, 1000); +} + +#[test] +fn example2() { + let block = BlockBuilder::new() + .header().build() + .transaction().lock_time(100500).build() + .build(); + + assert_eq!(block.transactions().len(), 1); +} diff --git a/test-data/src/invoke.rs b/test-data/src/invoke.rs new file mode 100644 index 00000000..4223dc58 --- /dev/null +++ b/test-data/src/invoke.rs @@ -0,0 +1,15 @@ +//! invoke helper + +pub trait Invoke { + type Result; + + fn invoke(self, arg: A) -> Self::Result; +} + +pub struct Identity; + +impl Invoke for Identity { + type Result = A; + + fn invoke(self, arg: A) -> A { arg } +} diff --git a/test-data/src/lib.rs b/test-data/src/lib.rs index 3c347d29..a3236e17 100644 --- a/test-data/src/lib.rs +++ b/test-data/src/lib.rs @@ -7,8 +7,11 @@ extern crate serialization as ser; use chain::Block; pub mod chain_builder; +pub mod block; +pub mod invoke; pub use chain_builder::{ChainBuilder, TransactionBuilder}; +pub use block::block_builder; pub fn block1() -> Block { let block: Block = "01000000ba8b9cda965dd8e536670f9ddec10e53aab14b20bacad27b9137190000000000190760b278fe7b8565fda3b968b918d5fd997f993b23674c0af3b6fde300b38f33a5914ce6ed5b1b01e32f570201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704e6ed5b1b014effffffff0100f2052a01000000434104b68a50eaa0287eff855189f949c1c6e5f58b37c88231373d8a59809cbae83059cc6469d65c665ccfd1cfeb75c6e8e19413bba7fbff9bc762419a76d87b16086eac000000000100000001a6b97044d03da79c005b20ea9c0e1a6d9dc12d9f7b91a5911c9030a439eed8f5000000004948304502206e21798a42fae0e854281abd38bacd1aeed3ee3738d9e1446618c4571d1090db022100e2ac980643b0b82c0e88ffdfec6b64e3e6ba35e7ba5fdd7d5d6cc8d25c6b241501ffffffff0100f2052a010000001976a914404371705fa9bd789a2fcd52d2c580b65d35549d88ac00000000".into();