mirror of
https://github.com/mimblewimble/grin.git
synced 2025-02-01 17:01:09 +03:00
Fix is_unspent
to consider MMR and not only index
The method `is_unspent` hadn't been fixed with the other sumtree functions to check the MMR before deciding whether something is really unspent. This is now fixed and also checks the output hash is the one we expect.
This commit is contained in:
parent
2dac10a690
commit
707a2073a5
3 changed files with 32 additions and 21 deletions
|
@ -120,7 +120,7 @@ impl UtxoHandler {
|
||||||
let outputs = block
|
let outputs = block
|
||||||
.outputs
|
.outputs
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|c|self.chain.is_unspent(&c.commit).unwrap())
|
.filter(|c|self.chain.is_unspent(&c.commit, &c.switch_commit_hash).unwrap())
|
||||||
.map(|k|OutputSwitch::from_output(k, &header))
|
.map(|k|OutputSwitch::from_output(k, &header))
|
||||||
.collect();
|
.collect();
|
||||||
BlockOutputs {
|
BlockOutputs {
|
||||||
|
|
|
@ -23,7 +23,7 @@ use util::secp::pedersen::{Commitment, RangeProof};
|
||||||
use core::core::SumCommit;
|
use core::core::SumCommit;
|
||||||
use core::core::pmmr::{HashSum, NoSum};
|
use core::core::pmmr::{HashSum, NoSum};
|
||||||
|
|
||||||
use core::core::{Block, BlockHeader, Output, TxKernel};
|
use core::core::{Block, BlockHeader, Output, TxKernel, SwitchCommitHash};
|
||||||
use core::core::target::Difficulty;
|
use core::core::target::Difficulty;
|
||||||
use core::core::hash::Hash;
|
use core::core::hash::Hash;
|
||||||
use grin_store::Error::NotFoundErr;
|
use grin_store::Error::NotFoundErr;
|
||||||
|
@ -360,21 +360,26 @@ impl Chain {
|
||||||
/// way that's consistent with the current chain state and more
|
/// way that's consistent with the current chain state and more
|
||||||
/// specifically the current winning fork.
|
/// specifically the current winning fork.
|
||||||
pub fn get_unspent(&self, output_ref: &Commitment) -> Result<Output, Error> {
|
pub fn get_unspent(&self, output_ref: &Commitment) -> Result<Output, Error> {
|
||||||
let sumtrees = self.sumtrees.read().unwrap();
|
match self.store.get_output_by_commit(output_ref) {
|
||||||
let is_unspent = sumtrees.is_unspent(output_ref)?;
|
Ok(out) => {
|
||||||
if is_unspent {
|
let mut sumtrees = self.sumtrees.write().unwrap();
|
||||||
self.store
|
if sumtrees.is_unspent(output_ref, &out.switch_commit_hash())? {
|
||||||
.get_output_by_commit(output_ref)
|
Ok(out)
|
||||||
.map_err(|e| Error::StoreErr(e, "chain get unspent".to_owned()))
|
|
||||||
} else {
|
} else {
|
||||||
Err(Error::OutputNotFound)
|
Err(Error::OutputNotFound)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Err(NotFoundErr) => Err(Error::OutputNotFound),
|
||||||
|
Err(e) => Err(Error::StoreErr(e, "chain get unspent".to_owned())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Checks whether an output is unspent
|
/// Checks whether an output is unspent
|
||||||
pub fn is_unspent(&self, output_ref: &Commitment) -> Result<bool, Error> {
|
pub fn is_unspent(&self, output_ref: &Commitment, switch: &SwitchCommitHash)
|
||||||
let sumtrees = self.sumtrees.read().unwrap();
|
-> Result<bool, Error> {
|
||||||
sumtrees.is_unspent(output_ref)
|
|
||||||
|
let mut sumtrees = self.sumtrees.write().unwrap();
|
||||||
|
sumtrees.is_unspent(output_ref, switch)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the sumtree roots on a brand new block by applying the block on the
|
/// Sets the sumtree roots on a brand new block by applying the block on the
|
||||||
|
|
|
@ -22,8 +22,8 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use util::secp::pedersen::{RangeProof, Commitment};
|
use util::secp::pedersen::{RangeProof, Commitment};
|
||||||
|
|
||||||
use core::core::{Block, SumCommit, TxKernel};
|
use core::core::{Block, SumCommit, SwitchCommitHash, TxKernel};
|
||||||
use core::core::pmmr::{Backend, HashSum, NoSum, Summable, PMMR};
|
use core::core::pmmr::{HashSum, NoSum, Summable, PMMR};
|
||||||
use core::core::hash::Hashed;
|
use core::core::hash::Hashed;
|
||||||
use grin_store;
|
use grin_store;
|
||||||
use grin_store::sumtree::PMMRBackend;
|
use grin_store::sumtree::PMMRBackend;
|
||||||
|
@ -90,16 +90,22 @@ impl SumTrees {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether a given commitment exists in the Output MMR and it's unspent
|
/// Whether a given commitment exists in the Output MMR and it's unspent
|
||||||
pub fn is_unspent(&self, commit: &Commitment) -> Result<bool, Error> {
|
pub fn is_unspent(&mut self, commit: &Commitment, switch: &SwitchCommitHash)
|
||||||
|
-> Result<bool, Error> {
|
||||||
|
|
||||||
let rpos = self.commit_index.get_output_pos(commit);
|
let rpos = self.commit_index.get_output_pos(commit);
|
||||||
match rpos {
|
match rpos {
|
||||||
Ok(pos) => {
|
Ok(pos) => {
|
||||||
// checking the position is within the MMR, the commit index could be
|
let output_pmmr = PMMR::at(
|
||||||
// returning rewound data
|
&mut self.output_pmmr_h.backend,
|
||||||
if pos > self.output_pmmr_h.last_pos {
|
self.output_pmmr_h.last_pos
|
||||||
Ok(false)
|
);
|
||||||
|
if let Some(hs) = output_pmmr.get(pos) {
|
||||||
|
let hashsum = HashSum::from_summable(
|
||||||
|
pos, &SumCommit{commit: commit.clone()}, Some(switch));
|
||||||
|
Ok(hs.hash == hashsum.hash)
|
||||||
} else {
|
} else {
|
||||||
Ok(self.output_pmmr_h.backend.get(pos).is_some())
|
Ok(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(grin_store::Error::NotFoundErr) => Ok(false),
|
Err(grin_store::Error::NotFoundErr) => Ok(false),
|
||||||
|
|
Loading…
Reference in a new issue