More Error implementations

This commit is contained in:
Andrew Poelstra 2015-10-25 12:55:48 -05:00
parent a69ae2c7ad
commit 67c0b8fba7
3 changed files with 97 additions and 6 deletions

View File

@ -1,7 +1,7 @@
[package] [package]
name = "bitcoin" name = "bitcoin"
version = "0.3.8" version = "0.3.9"
authors = ["Andrew Poelstra <apoelstra@wpsoftware.net>"] authors = ["Andrew Poelstra <apoelstra@wpsoftware.net>"]
license = "CC0-1.0" license = "CC0-1.0"
homepage = "https://github.com/apoelstra/rust-bitcoin/" homepage = "https://github.com/apoelstra/rust-bitcoin/"

View File

@ -27,7 +27,7 @@
use std::hash; use std::hash;
use std::char::from_digit; use std::char::from_digit;
use std::default::Default; use std::default::Default;
use std::{fmt, ops}; use std::{error, fmt, ops};
use serialize::hex::ToHex; use serialize::hex::ToHex;
use crypto::digest::Digest; use crypto::digest::Digest;
@ -101,8 +101,6 @@ impl hash::Hash for Script {
/// would help you. /// would help you.
#[derive(PartialEq, Eq, Debug, Clone)] #[derive(PartialEq, Eq, Debug, Clone)]
pub enum Error { pub enum Error {
/// The script returns false no matter the input
AnalyzeAlwaysReturnsFalse,
/// Tried to set a boolean to both values, but neither worked /// Tried to set a boolean to both values, but neither worked
AnalyzeNeitherBoolWorks, AnalyzeNeitherBoolWorks,
/// Tried to set a boolean to the given value, but it already /// Tried to set a boolean to the given value, but it already
@ -158,7 +156,59 @@ pub enum Error {
/// An OP_VERIFY happened with zero on the stack /// An OP_VERIFY happened with zero on the stack
VerifyFailed, VerifyFailed,
} }
display_from_debug!(Error);
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::Ecdsa(ref e) => fmt::Display::fmt(e, f),
Error::EqualVerifyFailed(ref exp, ref got) => write!(f, "OP_EQUALVERIFY failed; {} != {}", exp, got),
Error::MultisigBadKeyCount(n) => write!(f, "bad number {} of keys for multisignature", n),
Error::MultisigBadSigCount(n) => write!(f, "bad number {} of signatures for multisignature", n),
Error::NumEqualVerifyFailed(exp, got) => write!(f, "OP_NUMEQUALVERIFY failed; {} != {}", exp, got),
_ => f.write_str(error::Error::description(self))
}
}
}
impl error::Error for Error {
fn cause(&self) -> Option<&error::Error> {
match *self {
Error::Ecdsa(ref e) => Some(e),
_ => None
}
}
fn description(&self) -> &'static str {
match *self {
Error::AnalyzeNeitherBoolWorks => "analyzer: switch on boolean but neither side is satisfiable",
Error::AnalyzeSetBoolMismatch(_) => "analyzer: conflicting requirements on boolean",
Error::AnalyzeValidateFailed => "analyzer: conflicting requirements on stack element",
Error::BadPublicKey => "analyzer: CHECKSIG called with bad public key",
Error::BadSignature => "analyzer: CHECKSIG called with bad signature",
Error::Ecdsa(_) => "libsecp error",
Error::ElseWithoutIf => "unexpected OP_ELSE",
Error::EndifWithoutIf => "unexpected OP_ENDIF",
Error::EqualVerifyFailed(_, _) => "OP_EQUALVERIFY failed",
Error::IfEmptyStack => "OP_IF called with nothing on the stack",
Error::IllegalOpcode => "an illegal opcode exists in the script",
Error::InterpreterStackOverflow => "analyzer: stack overflow",
Error::EarlyEndOfScript => "unexpected end of script",
Error::ExecutedReturn => "OP_RETURN or equivalent was executed",
Error::MultisigBadKeyCount(_) => "bad key count for multisignature",
Error::MultisigBadSigCount(_) => "bad signature count for multisignature",
Error::NegativePick => "OP_PICK called with negative index",
Error::NegativeRoll => "OP_ROLL called with negative index",
Error::NoTransaction => "OP_CHECKSIG evaluated outside of transaction environment",
Error::NumEqualVerifyFailed(_, _) => "OP_NUMEQUALVERIFY failed",
Error::NumericOverflow => "numeric overflow (number on stack larger than 4 bytes)",
Error::PopEmptyStack => "stack was empty but script expected otherwise",
Error::Unanalyzable => "analyzer: unable to determine script satisfiability",
Error::Unsatisfiable => "analyzer: script is unsatisfiable",
Error::VerifyEmptyStack => "OP_VERIFY called on an empty stack",
Error::VerifyFailed => "OP_VERIFY called with false on top of stack"
}
}
}
/// A rule for validating an abstract stack element /// A rule for validating an abstract stack element
pub struct Validator { pub struct Validator {
@ -2461,7 +2511,7 @@ impl Script {
match stack.peek_mut().bool_value() { match stack.peek_mut().bool_value() {
None => stack.peek_mut().set_bool_value(true).map(|_| stack.build_initial_stack()), None => stack.peek_mut().set_bool_value(true).map(|_| stack.build_initial_stack()),
Some(true) => Ok(stack.build_initial_stack()), Some(true) => Ok(stack.build_initial_stack()),
Some(false) => Err(Error::AnalyzeAlwaysReturnsFalse) Some(false) => Err(Error::Unsatisfiable)
} }
} }

View File

@ -23,6 +23,8 @@ use blockdata::{opcodes, script};
use crypto::{hmac, sha2}; use crypto::{hmac, sha2};
use crypto::mac::Mac; use crypto::mac::Mac;
use std::{error, fmt};
use network::constants::Network; use network::constants::Network;
use util::{address, hash}; use util::{address, hash};
@ -54,6 +56,45 @@ pub enum Error {
TooManyKeys(usize) TooManyKeys(usize)
} }
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::BadTweak(ref e) => fmt::Display::fmt(&e, f),
Error::Secp(ref e) => fmt::Display::fmt(&e, f),
Error::Script(ref e) => fmt::Display::fmt(&e, f),
Error::UncompressedKey => f.write_str("encountered uncompressed secp public key"),
Error::ExpectedKey => f.write_str("expected key when deserializing script"),
Error::ExpectedChecksig => f.write_str("expected OP_*CHECKSIG* when deserializing script"),
Error::TooFewKeys(n) => write!(f, "got {} keys, which was not enough", n),
Error::TooManyKeys(n) => write!(f, "got {} keys, which was too many", n)
}
}
}
impl error::Error for Error {
fn cause(&self) -> Option<&error::Error> {
match *self {
Error::BadTweak(ref e) => Some(e),
Error::Secp(ref e) => Some(e),
Error::Script(ref e) => Some(e),
_ => None
}
}
fn description(&self) -> &'static str {
match *self {
Error::BadTweak(_) => "bad public key tweak",
Error::Secp(_) => "libsecp256k1 error",
Error::Script(_) => "script error",
Error::UncompressedKey => "encountered uncompressed secp public key",
Error::ExpectedKey => "expected key when deserializing script",
Error::ExpectedChecksig => "expected OP_*CHECKSIG* when deserializing script",
Error::TooFewKeys(_) => "too few keys for template",
Error::TooManyKeys(_) => "too many keys for template"
}
}
}
/// An element of a script template /// An element of a script template
#[derive(Copy, Clone, PartialEq, Eq, Debug)] #[derive(Copy, Clone, PartialEq, Eq, Debug)]
enum TemplateElement { enum TemplateElement {