Introduce `BitcoinResult`, use it instead of boolean returns in blockchain
This commit is contained in:
parent
426e1fc556
commit
8f826a959d
|
@ -0,0 +1,2 @@
|
|||
target
|
||||
|
|
@ -23,6 +23,7 @@
|
|||
use std::io::IoResult;
|
||||
use std::num::{Zero, from_u64};
|
||||
|
||||
use util::error::{BitcoinResult, SpvBadTarget, SpvBadProofOfWork};
|
||||
use util::hash::Sha256dHash;
|
||||
use util::uint::Uint256;
|
||||
use network::serialize::{Serializable, SerializeIter, VarInt};
|
||||
|
@ -95,13 +96,13 @@ impl BlockHeader {
|
|||
/// Performs an SPV validation of a block, which confirms that the proof-of-work
|
||||
/// is correct, but does not verify that the transactions are valid or encoded
|
||||
/// correctly.
|
||||
pub fn spv_validate(&self, required_target: &Uint256) -> bool {
|
||||
pub fn spv_validate(&self, required_target: &Uint256) -> BitcoinResult<()> {
|
||||
let ref target = self.target();
|
||||
if target != required_target {
|
||||
return false;
|
||||
return Err(SpvBadTarget);
|
||||
}
|
||||
let ref hash = self.hash().as_uint256();
|
||||
hash <= target
|
||||
if hash <= target { Ok(()) } else { Err(SpvBadProofOfWork) }
|
||||
}
|
||||
|
||||
/// Returns the total work of the block
|
||||
|
|
|
@ -33,6 +33,7 @@ use blockdata::transaction::Transaction;
|
|||
use blockdata::constants::{DIFFCHANGE_INTERVAL, DIFFCHANGE_TIMESPAN, max_target};
|
||||
use network::serialize::{Serializable, SerializeIter};
|
||||
use util::BitArray;
|
||||
use util::error::{BitcoinResult, BlockNotFound, DuplicateHash, PrevHashNotFound};
|
||||
use util::uint::Uint256;
|
||||
use util::hash::Sha256dHash;
|
||||
use util::misc::prepend_err;
|
||||
|
@ -389,7 +390,7 @@ impl Blockchain {
|
|||
}
|
||||
}
|
||||
|
||||
fn replace_txdata(&mut self, hash: &Uint256, txdata: Vec<Transaction>, has_txdata: bool) -> bool {
|
||||
fn replace_txdata(&mut self, hash: &Uint256, txdata: Vec<Transaction>, has_txdata: bool) -> BitcoinResult<()> {
|
||||
match self.tree.lookup_mut(hash, 256) {
|
||||
Some(existing_block) => {
|
||||
unsafe {
|
||||
|
@ -417,33 +418,33 @@ impl Blockchain {
|
|||
*mutable_bool = has_txdata;
|
||||
forget(mutable_bool);
|
||||
}
|
||||
return true
|
||||
Ok(())
|
||||
},
|
||||
None => return false
|
||||
None => Err(BlockNotFound)
|
||||
}
|
||||
}
|
||||
|
||||
/// Locates a block in the chain and overwrites its txdata
|
||||
pub fn add_txdata(&mut self, block: Block) -> bool {
|
||||
pub fn add_txdata(&mut self, block: Block) -> BitcoinResult<()> {
|
||||
self.replace_txdata(&block.header.hash().as_uint256(), block.txdata, true)
|
||||
}
|
||||
|
||||
/// Locates a block in the chain and removes its txdata
|
||||
pub fn remove_txdata(&mut self, hash: Sha256dHash) -> bool {
|
||||
pub fn remove_txdata(&mut self, hash: Sha256dHash) -> BitcoinResult<()> {
|
||||
self.replace_txdata(&hash.as_uint256(), vec![], false)
|
||||
}
|
||||
|
||||
/// Adds a block header to the chain
|
||||
pub fn add_header(&mut self, header: BlockHeader) -> bool {
|
||||
pub fn add_header(&mut self, header: BlockHeader) -> BitcoinResult<()> {
|
||||
self.real_add_block(Block { header: header, txdata: vec![] }, false)
|
||||
}
|
||||
|
||||
/// Adds a block to the chain
|
||||
pub fn add_block(&mut self, block: Block) -> bool {
|
||||
pub fn add_block(&mut self, block: Block) -> BitcoinResult<()> {
|
||||
self.real_add_block(block, true)
|
||||
}
|
||||
|
||||
fn real_add_block(&mut self, block: Block, has_txdata: bool) -> bool {
|
||||
fn real_add_block(&mut self, block: Block, has_txdata: bool) -> BitcoinResult<()> {
|
||||
// get_prev optimizes the common case where we are extending the best tip
|
||||
fn get_prev<'a>(chain: &'a Blockchain, hash: Sha256dHash) -> Option<&'a Rc<BlockchainNode>> {
|
||||
if hash == chain.best_hash { return Some(&chain.best_tip); }
|
||||
|
@ -454,7 +455,7 @@ impl Blockchain {
|
|||
// and this may also happen in case of a reorg.
|
||||
if self.tree.lookup(&block.header.hash().as_uint256(), 256).is_some() {
|
||||
println!("Warning: tried to add block {} twice!", block.header.hash());
|
||||
return true;
|
||||
return Err(DuplicateHash);
|
||||
}
|
||||
// Construct node, if possible
|
||||
let rc_block = match get_prev(self, block.header.prev_blockhash) {
|
||||
|
@ -500,15 +501,12 @@ impl Blockchain {
|
|||
ret
|
||||
},
|
||||
None => {
|
||||
println!("TODO: couldn't add block");
|
||||
return false;
|
||||
return Err(PrevHashNotFound);
|
||||
}
|
||||
};
|
||||
|
||||
// spv validate the block
|
||||
if !rc_block.block.header.spv_validate(&rc_block.required_difficulty) {
|
||||
return false;
|
||||
}
|
||||
try!(rc_block.block.header.spv_validate(&rc_block.required_difficulty));
|
||||
|
||||
// Insert the new block
|
||||
self.tree.insert(&rc_block.block.header.hash().as_uint256(), 256, rc_block.clone());
|
||||
|
@ -516,7 +514,7 @@ impl Blockchain {
|
|||
if rc_block.total_work > self.best_tip.total_work {
|
||||
self.set_best_tip(rc_block);
|
||||
}
|
||||
return true;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sets the best tip (not public)
|
||||
|
|
|
@ -23,7 +23,6 @@ use std::io::timer;
|
|||
|
||||
use network::message::{NetworkMessage, Verack};
|
||||
use network::socket::Socket;
|
||||
use network::constants;
|
||||
|
||||
/// A message which can be sent on the Bitcoin network
|
||||
pub trait Listener {
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
// Rust Bitcoin Library
|
||||
// Written in 2014 by
|
||||
// Andrew Poelstra <apoelstra@wpsoftware.net>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all
|
||||
// copyright and related and neighboring rights to this software to
|
||||
// the public domain worldwide. This software is distributed without
|
||||
// any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication
|
||||
// along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
//
|
||||
|
||||
//! # Error codes
|
||||
//!
|
||||
//! Various utility functions
|
||||
|
||||
use std::io::IoError;
|
||||
|
||||
/// A success/failure return value
|
||||
pub type BitcoinResult<T> = Result<T, BitcoinError>;
|
||||
|
||||
/// A general error code
|
||||
#[deriving(PartialEq, Eq, Show, Clone)]
|
||||
pub enum BitcoinError {
|
||||
/// An I/O error
|
||||
IoError(IoError),
|
||||
/// An object was attempted to be added twice
|
||||
DuplicateHash,
|
||||
/// Some operation was attempted on a block (or blockheader) that doesn't exist
|
||||
BlockNotFound,
|
||||
/// An object was added but it does not link into existing history
|
||||
PrevHashNotFound,
|
||||
/// The `target` field of a block header did not match the expected difficulty
|
||||
SpvBadTarget,
|
||||
/// The header hash is not below the target
|
||||
SpvBadProofOfWork
|
||||
}
|
||||
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
//!
|
||||
//! Functions needed by all parts of the Bitcoin library
|
||||
|
||||
pub mod error;
|
||||
pub mod hash;
|
||||
pub mod iter;
|
||||
pub mod misc;
|
||||
|
|
Loading…
Reference in New Issue