mirror of
https://github.com/mimblewimble/grin.git
synced 2025-01-20 19:11:08 +03:00
Several simple fixes to reflect changes from core (Result instead of Option for errors, consensus module, etc.)
This commit is contained in:
parent
3c5e2b2958
commit
1d2b23a4a5
6 changed files with 57 additions and 61 deletions
|
@ -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;
|
||||
|
|
|
@ -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<Error> {
|
||||
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<Err
|
|||
tip: None,
|
||||
};
|
||||
|
||||
try_o!(validate_header(&b, &mut ctx));
|
||||
try_o!(set_tip(&b.header, &mut ctx));
|
||||
try_o!(validate_block(b, &mut ctx));
|
||||
try_o!(add_block(b, &mut ctx));
|
||||
try_o!(update_tips(&mut ctx));
|
||||
None
|
||||
try!(validate_header(&b, &mut ctx));
|
||||
try!(set_tip(&b.header, &mut ctx));
|
||||
try!(validate_block(b, &mut ctx));
|
||||
try!(add_block(b, &mut ctx));
|
||||
try!(update_tips(&mut ctx));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// block processing pipeline
|
||||
|
@ -87,46 +86,45 @@ pub fn process_block(b: &Block, store: &ChainStore, opts: Options) -> Option<Err
|
|||
/// to make it as cheap as possible. The different validations are also
|
||||
/// arranged by order of cost to have as little DoS surface as possible.
|
||||
/// TODO actually require only the block header (with length information)
|
||||
fn validate_header(b: &Block, ctx: &mut BlockContext) -> Option<Error> {
|
||||
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<Error> {
|
||||
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<Error> {
|
||||
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<Error> {
|
||||
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<Error> {
|
||||
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)
|
||||
}
|
||||
|
|
|
@ -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<Error> {
|
||||
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<Error> {
|
||||
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<Error> {
|
||||
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::<BigEndian>(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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<ser::Error> {
|
||||
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<ser::Error> {
|
||||
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<Tip, Error>;
|
||||
|
||||
/// Save the provided block in store
|
||||
fn save_block(&self, b: &Block) -> Option<Error>;
|
||||
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<Error>;
|
||||
fn save_head(&self, t: &Tip) -> Result<(), Error>;
|
||||
|
||||
/// Save the provided tip without setting it as head
|
||||
fn save_tip(&self, t: &Tip) -> Option<Error>;
|
||||
fn save_tip(&self, t: &Tip) -> Result<(), Error>;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -63,18 +63,18 @@ impl Store {
|
|||
}
|
||||
|
||||
/// Writes a single key/value pair to the db
|
||||
pub fn put(&self, key: &[u8], value: Vec<u8>) -> Option<Error> {
|
||||
pub fn put(&self, key: &[u8], value: Vec<u8>) -> 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<Error> {
|
||||
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<Error> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue