utxo_view hash compare ()

* utxo_view validate_input now checks the data in the output MMR
* cleanup apply_input and validate_input
This commit is contained in:
Antioch Peverell 2018-12-05 17:58:40 +00:00 committed by Ignotus Peverell
parent 54a034c40a
commit 02b3bf4b59
2 changed files with 19 additions and 23 deletions
chain/src/txhashset

View file

@ -910,16 +910,9 @@ impl<'a> Extension<'a> {
let commit = input.commitment();
let pos_res = self.batch.get_output_pos(&commit);
if let Ok(pos) = pos_res {
let output_id_hash = OutputIdentifier::from_input(input).hash_with_index(pos - 1);
if let Some(read_hash) = self.output_pmmr.get_hash(pos) {
// check hash from pmmr matches hash from input (or corresponding output)
// if not then the input is not being honest about
// what it is attempting to spend...
let read_elem = self.output_pmmr.get_data(pos);
let read_elem_hash = read_elem
.expect("no output at pos")
.hash_with_index(pos - 1);
if output_id_hash != read_hash || output_id_hash != read_elem_hash {
// First check this input corresponds to an existing entry in the output MMR.
if let Some(hash) = self.output_pmmr.get_hash(pos) {
if hash != input.hash_with_index(pos - 1) {
return Err(
ErrorKind::TxHashSetErr(format!("output pmmr hash mismatch")).into(),
);
@ -933,10 +926,10 @@ impl<'a> Extension<'a> {
Ok(true) => {
self.rproof_pmmr
.prune(pos)
.map_err(|s| ErrorKind::TxHashSetErr(s))?;
.map_err(|e| ErrorKind::TxHashSetErr(e))?;
}
Ok(false) => return Err(ErrorKind::AlreadySpent(commit).into()),
Err(s) => return Err(ErrorKind::TxHashSetErr(s).into()),
Err(e) => return Err(ErrorKind::TxHashSetErr(e).into()),
}
} else {
return Err(ErrorKind::AlreadySpent(commit).into());

View file

@ -16,7 +16,7 @@
use core::core::pmmr::ReadonlyPMMR;
use core::core::{Block, Input, Output, Transaction};
use core::ser::PMMRIndexHashable;
use error::{Error, ErrorKind};
use grin_store::pmmr::PMMRBackend;
use store::Batch;
@ -64,23 +64,26 @@ impl<'a> UTXOView<'a> {
Ok(())
}
// Input is valid if it is spending an (unspent) output
// that currently exists in the output MMR.
// Compare the hash in the output MMR at the expected pos.
fn validate_input(&self, input: &Input) -> Result<(), Error> {
let commit = input.commitment();
let pos_res = self.batch.get_output_pos(&commit);
if let Ok(pos) = pos_res {
if let Some(_) = self.pmmr.get_data(pos) {
return Ok(());
if let Ok(pos) = self.batch.get_output_pos(&input.commitment()) {
if let Some(hash) = self.pmmr.get_hash(pos) {
if hash == input.hash_with_index(pos - 1) {
return Ok(());
}
}
}
Err(ErrorKind::AlreadySpent(commit).into())
Err(ErrorKind::AlreadySpent(input.commitment()).into())
}
// Output is valid if it would not result in a duplicate commitment in the output MMR.
fn validate_output(&self, output: &Output) -> Result<(), Error> {
let commit = output.commitment();
if let Ok(pos) = self.batch.get_output_pos(&commit) {
if let Ok(pos) = self.batch.get_output_pos(&output.commitment()) {
if let Some(out_mmr) = self.pmmr.get_data(pos) {
if out_mmr.commitment() == commit {
return Err(ErrorKind::DuplicateCommitment(commit).into());
if out_mmr.commitment() == output.commitment() {
return Err(ErrorKind::DuplicateCommitment(output.commitment()).into());
}
}
}