Cleanup for block validation errors

This commit is contained in:
Ignotus Peverell 2017-10-03 22:27:26 +00:00
parent bc11d23908
commit 4e49b85b82
No known key found for this signature in database
GPG key ID: 99CD25F39F8F8211

View file

@ -28,7 +28,6 @@ use ser::{self, Readable, Reader, Writeable, Writer};
use global; use global;
use keychain; use keychain;
bitflags! { bitflags! {
/// Options for block validation /// Options for block validation
pub flags BlockFeatures: u8 { pub flags BlockFeatures: u8 {
@ -37,6 +36,23 @@ bitflags! {
} }
} }
/// Errors thrown by Block validation
#[derive(Debug, PartialEq)]
pub enum Error {
/// The sum of output minus input commitments does not match the sum of
/// kernel commitments
KernelSumMismatch,
/// Underlying Secp256k1 error (signature validation or invalid public
/// key typically)
Secp(secp::Error),
}
impl From<secp::Error> for Error {
fn from(e: secp::Error) -> Error {
Error::Secp(e)
}
}
/// Block header, fairly standard compared to other blockchains. /// Block header, fairly standard compared to other blockchains.
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub struct BlockHeader { pub struct BlockHeader {
@ -400,18 +416,17 @@ impl Block {
} }
/// Validates all the elements in a block that can be checked without /// Validates all the elements in a block that can be checked without
/// additional /// additional data. Includes commitment sums and kernels, Merkle
/// data. Includes commitment sums and kernels, Merkle trees, reward, etc. /// trees, reward, etc.
pub fn validate(&self, secp: &Secp256k1) -> Result<(), secp::Error> { pub fn validate(&self, secp: &Secp256k1) -> Result<(), Error> {
self.verify_coinbase(secp)?; self.verify_coinbase(secp)?;
self.verify_kernels(secp)?; self.verify_kernels(secp)?;
Ok(()) Ok(())
} }
/// Validate the sum of input/output commitments match the sum in kernels /// Validate the sum of input/output commitments match the sum in kernels
/// and /// and that all kernel signatures are valid.
/// that all kernel signatures are valid. pub fn verify_kernels(&self, secp: &Secp256k1) -> Result<(), Error> {
pub fn verify_kernels(&self, secp: &Secp256k1) -> Result<(), secp::Error> {
// sum all inputs and outs commitments // sum all inputs and outs commitments
let io_sum = self.sum_commitments(secp)?; let io_sum = self.sum_commitments(secp)?;
@ -421,8 +436,7 @@ impl Block {
// both should be the same // both should be the same
if proof_sum != io_sum { if proof_sum != io_sum {
// TODO more specific error return Err(Error::KernelSumMismatch);
return Err(secp::Error::IncorrectCommitSum);
} }
// verify all signatures with the commitment as pk // verify all signatures with the commitment as pk
@ -437,7 +451,7 @@ impl Block {
// * That the sum of all coinbase-marked outputs equal the supply. // * That the sum of all coinbase-marked outputs equal the supply.
// * That the sum of blinding factors for all coinbase-marked outputs match // * That the sum of blinding factors for all coinbase-marked outputs match
// the coinbase-marked kernels. // the coinbase-marked kernels.
fn verify_coinbase(&self, secp: &Secp256k1) -> Result<(), secp::Error> { fn verify_coinbase(&self, secp: &Secp256k1) -> Result<(), Error> {
let cb_outs = self.outputs let cb_outs = self.outputs
.iter() .iter()
.filter(|out| out.features.contains(COINBASE_OUTPUT)) .filter(|out| out.features.contains(COINBASE_OUTPUT))
@ -617,13 +631,13 @@ mod test {
assert_eq!( assert_eq!(
b.verify_coinbase(&keychain.secp()), b.verify_coinbase(&keychain.secp()),
Err(secp::Error::IncorrectCommitSum) Err(Error::KernelSumMismatch)
); );
assert_eq!(b.verify_kernels(&keychain.secp()), Ok(())); assert_eq!(b.verify_kernels(&keychain.secp()), Ok(()));
assert_eq!( assert_eq!(
b.validate(&keychain.secp()), b.validate(&keychain.secp()),
Err(secp::Error::IncorrectCommitSum) Err(Error::KernelSumMismatch)
); );
} }
@ -639,13 +653,13 @@ mod test {
assert_eq!( assert_eq!(
b.verify_coinbase(&keychain.secp()), b.verify_coinbase(&keychain.secp()),
Err(secp::Error::IncorrectCommitSum) Err(Error::Secp(secp::Error::IncorrectCommitSum))
); );
assert_eq!(b.verify_kernels(&keychain.secp()), Ok(())); assert_eq!(b.verify_kernels(&keychain.secp()), Ok(()));
assert_eq!( assert_eq!(
b.validate(&keychain.secp()), b.validate(&keychain.secp()),
Err(secp::Error::IncorrectCommitSum) Err(Error::Secp(secp::Error::IncorrectCommitSum))
); );
} }