diff --git a/chain/src/lib.rs b/chain/src/lib.rs index e7e5d0886..c4cd00b2e 100644 --- a/chain/src/lib.rs +++ b/chain/src/lib.rs @@ -24,7 +24,6 @@ extern crate bitflags; extern crate byteorder; -#[macro_use(try_o)] extern crate grin_core as core; extern crate grin_store; extern crate secp256k1zkp as secp; diff --git a/chain/src/pipe.rs b/chain/src/pipe.rs index c2f6335b8..c040b203e 100644 --- a/chain/src/pipe.rs +++ b/chain/src/pipe.rs @@ -16,7 +16,9 @@ use secp; -use core::core::{Hash, BlockHeader, Block, Proof}; +use core::consensus; +use core::core::hash::Hash; +use core::core::{BlockHeader, Block, Proof}; use core::pow; use types; use types::{Tip, ChainStore}; @@ -51,14 +53,11 @@ pub enum Error { StoreErr(types::Error), } -pub fn process_block(b: &Block, store: &ChainStore, opts: Options) -> Option { +pub fn process_block(b: &Block, store: &ChainStore, opts: Options) -> Result<(), Error> { // TODO should just take a promise for a block with a full header so we don't // spend resources reading the full block when its header is invalid - let head = match store.head() { - Ok(head) => head, - Err(err) => return Some(Error::StoreErr(err)), - }; + let head = try!(store.head().map_err(&Error::StoreErr)); let mut ctx = BlockContext { opts: opts, store: store, @@ -66,12 +65,12 @@ pub fn process_block(b: &Block, store: &ChainStore, opts: Options) -> Option Option Option { +fn validate_header(b: &Block, ctx: &mut BlockContext) -> Result<(), Error> { let header = &b.header; - println!("{} {}", header.height, ctx.head.height); if header.height > ctx.head.height + 1 { // TODO actually handle orphans and add them to a size-limited set - return Some(Error::Unfit("orphan".to_string())); + return Err(Error::Unfit("orphan".to_string())); } // TODO check time wrt to chain time, refuse older than 100 blocks or too far // in future // TODO maintain current difficulty - let diff_target = Proof(pow::MAX_TARGET); + let diff_target = consensus::MAX_TARGET; if ctx.opts.intersects(EASY_POW) { if !pow::verify20(b, diff_target) { - return Some(Error::InvalidPow); + return Err(Error::InvalidPow); } } else if !pow::verify(b, diff_target) { - return Some(Error::InvalidPow); + return Err(Error::InvalidPow); } - None + Ok(()) } -fn set_tip(h: &BlockHeader, ctx: &mut BlockContext) -> Option { +fn set_tip(h: &BlockHeader, ctx: &mut BlockContext) -> Result<(), Error> { ctx.tip = Some(ctx.head.clone()); - None + Ok(()) } -fn validate_block(b: &Block, ctx: &mut BlockContext) -> Option { +fn validate_block(b: &Block, ctx: &mut BlockContext) -> Result<(), Error> { // TODO check tx merkle tree let curve = secp::Secp256k1::with_caps(secp::ContextFlag::Commit); - try_o!(b.verify(&curve).err().map(&Error::InvalidBlockProof)); - None + try!(b.verify(&curve).map_err(&Error::InvalidBlockProof)); + Ok(()) } -fn add_block(b: &Block, ctx: &mut BlockContext) -> Option { +fn add_block(b: &Block, ctx: &mut BlockContext) -> Result<(), Error> { ctx.tip = ctx.tip.as_ref().map(|t| t.append(b.hash())); - ctx.store.save_block(b).map(&Error::StoreErr) + ctx.store.save_block(b).map_err(&Error::StoreErr) } -fn update_tips(ctx: &mut BlockContext) -> Option { - ctx.store.save_head(ctx.tip.as_ref().unwrap()).map(&Error::StoreErr) +fn update_tips(ctx: &mut BlockContext) -> Result<(), Error> { + ctx.store.save_head(ctx.tip.as_ref().unwrap()).map_err(&Error::StoreErr) } diff --git a/chain/src/store.rs b/chain/src/store.rs index f1ed27585..594d2b275 100644 --- a/chain/src/store.rs +++ b/chain/src/store.rs @@ -46,20 +46,20 @@ impl ChainStore for ChainKVStore { option_to_not_found(self.db.get_ser(&vec![HEAD_PREFIX])) } - fn save_block(&self, b: &Block) -> Option { - self.db.put_ser(&to_key(BLOCK_PREFIX, &mut b.hash().to_vec())[..], b).map(&to_store_err) + fn save_block(&self, b: &Block) -> Result<(), Error> { + self.db.put_ser(&to_key(BLOCK_PREFIX, &mut b.hash().to_vec())[..], b).map_err(&to_store_err) } - fn save_head(&self, t: &Tip) -> Option { - try_o!(self.save_tip(t)); - self.db.put_ser(&vec![HEAD_PREFIX], t).map(&to_store_err) + fn save_head(&self, t: &Tip) -> Result<(), Error> { + try!(self.save_tip(t)); + self.db.put_ser(&vec![HEAD_PREFIX], t).map_err(&to_store_err) } - fn save_tip(&self, t: &Tip) -> Option { + fn save_tip(&self, t: &Tip) -> Result<(), Error> { let last_branch = t.lineage.last_branch(); let mut k = vec![TIP_PREFIX, SEP]; k.write_u32::(last_branch); - self.db.put_ser(&mut k, t).map(&to_store_err) + self.db.put_ser(&mut k, t).map_err(&to_store_err) } } diff --git a/chain/src/types.rs b/chain/src/types.rs index f1ce594bd..185742554 100644 --- a/chain/src/types.rs +++ b/chain/src/types.rs @@ -14,7 +14,8 @@ //! Base types that the block chain pipeline requires. -use core::core::{Hash, Block}; +use core::core::hash::Hash; +use core::core::Block; use core::ser; /// The lineage of a fork, defined as a series of numbers. Each new branch gets @@ -40,12 +41,12 @@ impl Lineage { /// Serialization for lineage, necessary to serialize fork tips. impl ser::Writeable for Lineage { - fn write(&self, writer: &mut ser::Writer) -> Option { - try_o!(writer.write_u32(self.0.len() as u32)); + fn write(&self, writer: &mut ser::Writer) -> Result<(), ser::Error> { + try!(writer.write_u32(self.0.len() as u32)); for num in &self.0 { - try_o!(writer.write_u32(*num)); + try!(writer.write_u32(*num)); } - None + Ok(()) } } /// Deserialization for lineage, necessary to deserialize fork tips. @@ -99,10 +100,10 @@ impl Tip { /// Serialization of a tip, required to save to datastore. impl ser::Writeable for Tip { - fn write(&self, writer: &mut ser::Writer) -> Option { - try_o!(writer.write_u64(self.height)); - try_o!(writer.write_fixed_bytes(&self.last_block_h)); - try_o!(writer.write_fixed_bytes(&self.prev_block_h)); + fn write(&self, writer: &mut ser::Writer) -> Result<(), ser::Error> { + try!(writer.write_u64(self.height)); + try!(writer.write_fixed_bytes(&self.last_block_h)); + try!(writer.write_fixed_bytes(&self.prev_block_h)); self.lineage.write(writer) } } @@ -137,11 +138,11 @@ pub trait ChainStore { fn head(&self) -> Result; /// Save the provided block in store - fn save_block(&self, b: &Block) -> Option; + fn save_block(&self, b: &Block) -> Result<(), Error>; /// Save the provided tip as the current head of our chain - fn save_head(&self, t: &Tip) -> Option; + fn save_head(&self, t: &Tip) -> Result<(), Error>; /// Save the provided tip without setting it as head - fn save_tip(&self, t: &Tip) -> Option; + fn save_tip(&self, t: &Tip) -> Result<(), Error>; } diff --git a/chain/tests/mine_simple_chain.rs b/chain/tests/mine_simple_chain.rs index 7fb1cdb3b..102d6cac5 100644 --- a/chain/tests/mine_simple_chain.rs +++ b/chain/tests/mine_simple_chain.rs @@ -22,6 +22,7 @@ use rand::os::OsRng; use grin_chain::types::*; use grin_core::pow; use grin_core::core; +use grin_core::consensus; #[test] fn mine_empty_chain() { @@ -31,11 +32,11 @@ fn mine_empty_chain() { // save a genesis block let gen = grin_core::genesis::genesis(); - assert!(store.save_block(&gen).is_none()); + store.save_block(&gen).unwrap(); // setup a new head tip let tip = Tip::new(gen.hash()); - assert!(store.save_head(&tip).is_none()); + store.save_head(&tip).unwrap(); // mine and add a few blocks let mut prev = gen; @@ -46,13 +47,10 @@ fn mine_empty_chain() { let mut b = core::Block::new(prev.header, vec![], reward_key).unwrap(); println!("=> {} {:?}", b.header.height, b.verify(&curve)); - let (proof, nonce) = pow::pow20(&b, core::Proof(pow::MAX_TARGET)).unwrap(); + let (proof, nonce) = pow::pow20(&b, consensus::MAX_TARGET).unwrap(); b.header.pow = proof; b.header.nonce = nonce; - if let Some(e) = grin_chain::pipe::process_block(&b, &store, grin_chain::pipe::EASY_POW) { - println!("err: {:?}", e); - panic!(); - } + grin_chain::pipe::process_block(&b, &store, grin_chain::pipe::EASY_POW).unwrap(); // checking our new head let head = store.head().unwrap(); diff --git a/store/src/lib.rs b/store/src/lib.rs index d70cfe189..beb793c5f 100644 --- a/store/src/lib.rs +++ b/store/src/lib.rs @@ -63,18 +63,18 @@ impl Store { } /// Writes a single key/value pair to the db - pub fn put(&self, key: &[u8], value: Vec) -> Option { + pub fn put(&self, key: &[u8], value: Vec) -> Result<(), Error> { let db = self.rdb.write().unwrap(); - db.put(key, &value[..]).err().map(Error::RocksDbErr) + db.put(key, &value[..]).map_err(Error::RocksDbErr) } /// Writes a single key and its `Writeable` value to the db. Encapsulates /// serialization. - pub fn put_ser(&self, key: &[u8], value: &ser::Writeable) -> Option { + pub fn put_ser(&self, key: &[u8], value: &ser::Writeable) -> Result<(), Error> { let ser_value = ser::ser_vec(value); match ser_value { Ok(data) => self.put(key, data), - Err(err) => Some(Error::SerErr(err)), + Err(err) => Err(Error::SerErr(err)), } } @@ -98,8 +98,8 @@ impl Store { } /// Deletes a key/value pair from the db - pub fn delete(&self, key: &[u8]) -> Option { + pub fn delete(&self, key: &[u8]) -> Result<(), Error> { let db = self.rdb.write().unwrap(); - db.delete(key).err().map(Error::RocksDbErr) + db.delete(key).map_err(Error::RocksDbErr) } }