lightweight validation during deserialization (#1422)

* introduce validate_read (for lightweight validation when reading)

* rustfmt
This commit is contained in:
Antioch Peverell 2018-08-26 11:43:44 +01:00 committed by GitHub
parent 953d910776
commit bd03528d33
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 51 additions and 8 deletions

View file

@ -301,8 +301,12 @@ impl Readable for Block {
let body = TransactionBody::read(reader)?; let body = TransactionBody::read(reader)?;
// Now validate the body and treat any validation error as corrupted data. // Now "lightweight" validation of the block.
body.validate(true).map_err(|_| ser::Error::CorruptedData)?; // Treat any validation issues as data corruption.
// An example of this would be reading a block
// that exceeded the allowed number of inputs.
body.validate_read(true)
.map_err(|_| ser::Error::CorruptedData)?;
Ok(Block { Ok(Block {
header: header, header: header,
@ -528,6 +532,18 @@ impl Block {
}) })
} }
/// "Lightweight" validation that we can perform quickly during read/deserialization.
/// Subset of full validation that skips expensive verification steps, specifically -
/// * rangeproof verification (on the body)
/// * kernel signature verification (on the body)
/// * coinbase sum verification
/// * kernel sum verification
pub fn validate_read(&self) -> Result<(), Error> {
self.body.validate_read(true)?;
self.verify_kernel_lock_heights()?;
Ok(())
}
/// 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 data. Includes commitment sums and kernels, Merkle /// additional data. Includes commitment sums and kernels, Merkle
/// trees, reward, etc. /// trees, reward, etc.

View file

@ -68,7 +68,8 @@ impl CompactBlockBody {
self.kern_ids.sort(); self.kern_ids.sort();
} }
fn validate(&self) -> Result<(), Error> { /// "Lightweight" validation.
fn validate_read(&self) -> Result<(), Error> {
self.verify_sorted()?; self.verify_sorted()?;
Ok(()) Ok(())
} }
@ -138,8 +139,9 @@ pub struct CompactBlock {
} }
impl CompactBlock { impl CompactBlock {
fn validate(&self) -> Result<(), Error> { /// "Lightweight" validation.
self.body.validate()?; fn validate_read(&self) -> Result<(), Error> {
self.body.validate_read()?;
Ok(()) Ok(())
} }
@ -225,7 +227,7 @@ impl Readable for CompactBlock {
}; };
// Now validate the compact block and treat any validation error as corrupted data. // Now validate the compact block and treat any validation error as corrupted data.
cb.validate().map_err(|_| ser::Error::CorruptedData)?; cb.validate_read().map_err(|_| ser::Error::CorruptedData)?;
Ok(cb) Ok(cb)
} }

View file

@ -544,6 +544,17 @@ impl TransactionBody {
Ok(()) Ok(())
} }
/// "Lightweight" validation that we can perform quickly during read/deserialization.
/// Subset of full validation that skips expensive verification steps, specifically -
/// * rangeproof verification
/// * kernel signature verification
pub fn validate_read(&self, with_reward: bool) -> Result<(), Error> {
self.verify_weight(with_reward)?;
self.verify_sorted()?;
self.verify_cut_through()?;
Ok(())
}
/// Validates all relevant parts of a transaction body. Checks the /// Validates all relevant parts of a transaction body. Checks the
/// excess value against the signature as well as range proofs for each /// excess value against the signature as well as range proofs for each
/// output. /// output.
@ -598,11 +609,12 @@ impl Readable for Transaction {
let body = TransactionBody::read(reader)?; let body = TransactionBody::read(reader)?;
let tx = Transaction { offset, body }; let tx = Transaction { offset, body };
// Now validate the tx. // Now "lightweight" validation of the tx.
// Treat any validation issues as data corruption. // Treat any validation issues as data corruption.
// An example of this would be reading a tx // An example of this would be reading a tx
// that exceeded the allowed number of inputs. // that exceeded the allowed number of inputs.
tx.validate(false).map_err(|_| ser::Error::CorruptedData)?; tx.validate_read(false)
.map_err(|_| ser::Error::CorruptedData)?;
Ok(tx) Ok(tx)
} }
@ -732,6 +744,19 @@ impl Transaction {
self.body.lock_height() self.body.lock_height()
} }
/// "Lightweight" validation that we can perform quickly during read/deserialization.
/// Subset of full validation that skips expensive verification steps, specifically -
/// * rangeproof verification (on the body)
/// * kernel signature verification (on the body)
/// * kernel sum verification
pub fn validate_read(&self, with_reward: bool) -> Result<(), Error> {
self.body.validate_read(with_reward)?;
if !with_reward {
self.body.verify_features()?;
}
Ok(())
}
/// Validates all relevant parts of a fully built transaction. Checks the /// Validates all relevant parts of a fully built transaction. Checks the
/// excess value against the signature as well as range proofs for each /// excess value against the signature as well as range proofs for each
/// output. /// output.