Skip to content

Commit

Permalink
Refactor Output Identifiers (#3371)
Browse files Browse the repository at this point in the history
* refactor output to have internal output identifier

refactor to use AsRef for output identifier

make the output MMR explicit in terms of output identifiers

* put the serde deser back for rangeproof

* add json test for transactions
antiochp authored Sep 3, 2020
1 parent caa6b8c commit 133089e
Showing 17 changed files with 198 additions and 154 deletions.
4 changes: 2 additions & 2 deletions api/src/handlers/chain_api.rs
Original file line number Diff line number Diff line change
@@ -246,7 +246,7 @@ impl OutputHandler {
let outputs = block
.outputs()
.iter()
.filter(|output| commitments.is_empty() || commitments.contains(&output.commit))
.filter(|output| commitments.is_empty() || commitments.contains(&output.commitment()))
.map(|output| {
OutputPrintable::from_output(output, &chain, Some(&header), include_proof, true)
})
@@ -279,7 +279,7 @@ impl OutputHandler {
let outputs = block
.outputs()
.iter()
.filter(|output| commitments.is_empty() || commitments.contains(&output.commit))
.filter(|output| commitments.is_empty() || commitments.contains(&output.commitment()))
.map(|output| {
OutputPrintable::from_output(
output,
7 changes: 3 additions & 4 deletions api/src/types.rs
Original file line number Diff line number Diff line change
@@ -290,8 +290,7 @@ impl OutputPrintable {
OutputType::Transaction
};

let out_id = core::OutputIdentifier::from(output);
let pos = chain.get_unspent(out_id.commitment())?;
let pos = chain.get_unspent(output.commitment())?;

let spent = pos.is_none();

@@ -319,13 +318,13 @@ impl OutputPrintable {
let mut merkle_proof = None;
if include_merkle_proof && output.is_coinbase() && !spent {
if let Some(block_header) = block_header {
merkle_proof = chain.get_merkle_proof(&out_id, &block_header).ok();
merkle_proof = chain.get_merkle_proof(output, &block_header).ok();
}
};

Ok(OutputPrintable {
output_type,
commit: output.commit,
commit: output.commitment(),
spent,
proof,
proof_hash: output.proof.hash().to_hex(),
12 changes: 4 additions & 8 deletions chain/src/chain.rs
Original file line number Diff line number Diff line change
@@ -767,17 +767,17 @@ impl Chain {
}

/// Return a Merkle proof for the given commitment from the store.
pub fn get_merkle_proof(
pub fn get_merkle_proof<T: AsRef<OutputIdentifier>>(
&self,
output: &OutputIdentifier,
out_id: T,
header: &BlockHeader,
) -> Result<MerkleProof, Error> {
let mut header_pmmr = self.header_pmmr.write();
let mut txhashset = self.txhashset.write();
let merkle_proof =
txhashset::extending_readonly(&mut header_pmmr, &mut txhashset, |ext, batch| {
pipe::rewind_and_apply_fork(&header, ext, batch)?;
ext.extension.merkle_proof(output, batch)
ext.extension.merkle_proof(out_id, batch)
})?;

Ok(merkle_proof)
@@ -1304,11 +1304,7 @@ impl Chain {
}
let mut output_vec: Vec<Output> = vec![];
for (ref x, &y) in outputs.1.iter().zip(rangeproofs.1.iter()) {
output_vec.push(Output {
commit: x.commit,
features: x.features,
proof: y,
});
output_vec.push(Output::new(x.features, x.commitment(), y));
}
Ok((outputs.0, last_index, output_vec))
}
23 changes: 13 additions & 10 deletions chain/src/txhashset/txhashset.rs
Original file line number Diff line number Diff line change
@@ -144,7 +144,7 @@ impl PMMRHandle<BlockHeader> {
/// may have commitments that have already been spent, even with
/// pruning enabled.
pub struct TxHashSet {
output_pmmr_h: PMMRHandle<Output>,
output_pmmr_h: PMMRHandle<OutputIdentifier>,
rproof_pmmr_h: PMMRHandle<RangeProof>,
kernel_pmmr_h: PMMRHandle<TxKernel>,

@@ -237,7 +237,9 @@ impl TxHashSet {
}

// Build a new bitmap accumulator for the provided output PMMR.
fn bitmap_accumulator(pmmr_h: &PMMRHandle<Output>) -> Result<BitmapAccumulator, Error> {
fn bitmap_accumulator(
pmmr_h: &PMMRHandle<OutputIdentifier>,
) -> Result<BitmapAccumulator, Error> {
let pmmr = ReadonlyPMMR::at(&pmmr_h.backend, pmmr_h.last_pos);
let size = pmmr::n_leaves(pmmr_h.last_pos);
let mut bitmap_accumulator = BitmapAccumulator::new();
@@ -261,7 +263,7 @@ impl TxHashSet {
) -> Result<Option<(OutputIdentifier, CommitPos)>, Error> {
match self.commit_index.get_output_pos_height(&commit) {
Ok(Some(pos)) => {
let output_pmmr: ReadonlyPMMR<'_, Output, _> =
let output_pmmr: ReadonlyPMMR<'_, OutputIdentifier, _> =
ReadonlyPMMR::at(&self.output_pmmr_h.backend, self.output_pmmr_h.last_pos);
if let Some(out) = output_pmmr.get_data(pos.pos) {
if out.commitment() == commit {
@@ -997,7 +999,7 @@ pub struct ExtensionPair<'a> {
pub struct Extension<'a> {
head: Tip,

output_pmmr: PMMR<'a, Output, PMMRBackend<Output>>,
output_pmmr: PMMR<'a, OutputIdentifier, PMMRBackend<OutputIdentifier>>,
rproof_pmmr: PMMR<'a, RangeProof, PMMRBackend<RangeProof>>,
kernel_pmmr: PMMR<'a, TxKernel, PMMRBackend<TxKernel>>,

@@ -1171,13 +1173,13 @@ impl<'a> Extension<'a> {
// push the new output to the MMR.
let output_pos = self
.output_pmmr
.push(out)
.push(&out.identifier())
.map_err(&ErrorKind::TxHashSetErr)?;

// push the rangeproof to the MMR.
let rproof_pos = self
.rproof_pmmr
.push(&out.proof)
.push(&out.proof())
.map_err(&ErrorKind::TxHashSetErr)?;

// The output and rproof MMRs should be exactly the same size
@@ -1231,14 +1233,15 @@ impl<'a> Extension<'a> {
/// Note: this relies on the MMR being stable even after pruning/compaction.
/// We need the hash of each sibling pos from the pos up to the peak
/// including the sibling leaf node which may have been removed.
pub fn merkle_proof(
pub fn merkle_proof<T: AsRef<OutputIdentifier>>(
&self,
output: &OutputIdentifier,
out_id: T,
batch: &Batch<'_>,
) -> Result<MerkleProof, Error> {
debug!("txhashset: merkle_proof: output: {:?}", output.commit,);
let out_id = out_id.as_ref();
debug!("txhashset: merkle_proof: output: {:?}", out_id.commit);
// then calculate the Merkle Proof based on the known pos
let pos = batch.get_output_pos(&output.commit)?;
let pos = batch.get_output_pos(&out_id.commit)?;
let merkle_proof = self
.output_pmmr
.merkle_proof(pos)
4 changes: 2 additions & 2 deletions chain/src/txhashset/utxo_view.rs
Original file line number Diff line number Diff line change
@@ -27,15 +27,15 @@ use grin_store::pmmr::PMMRBackend;
/// Readonly view of the UTXO set (based on output MMR).
pub struct UTXOView<'a> {
header_pmmr: ReadonlyPMMR<'a, BlockHeader, PMMRBackend<BlockHeader>>,
output_pmmr: ReadonlyPMMR<'a, Output, PMMRBackend<Output>>,
output_pmmr: ReadonlyPMMR<'a, OutputIdentifier, PMMRBackend<OutputIdentifier>>,
rproof_pmmr: ReadonlyPMMR<'a, RangeProof, PMMRBackend<RangeProof>>,
}

impl<'a> UTXOView<'a> {
/// Build a new UTXO view.
pub fn new(
header_pmmr: ReadonlyPMMR<'a, BlockHeader, PMMRBackend<BlockHeader>>,
output_pmmr: ReadonlyPMMR<'a, Output, PMMRBackend<Output>>,
output_pmmr: ReadonlyPMMR<'a, OutputIdentifier, PMMRBackend<OutputIdentifier>>,
rproof_pmmr: ReadonlyPMMR<'a, RangeProof, PMMRBackend<RangeProof>>,
) -> UTXOView<'a> {
UTXOView {
8 changes: 3 additions & 5 deletions chain/tests/mine_simple_chain.rs
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ use self::chain::types::{NoopAdapter, Tip};
use self::chain::Chain;
use self::core::core::hash::Hashed;
use self::core::core::verifier_cache::LruVerifierCache;
use self::core::core::{Block, BlockHeader, KernelFeatures, OutputIdentifier, Transaction};
use self::core::core::{Block, BlockHeader, KernelFeatures, Transaction};
use self::core::global::ChainTypes;
use self::core::libtx::{self, build, ProofBuilder};
use self::core::pow::Difficulty;
@@ -549,8 +549,7 @@ fn spend_rewind_spend() {
// mine the first block and keep track of the block_hash
// so we can spend the coinbase later
let b = prepare_block_key_idx(&kc, &head, &chain, 2, 1);
let out_id = OutputIdentifier::from(&b.outputs()[0]);
assert!(out_id.features.is_coinbase());
assert!(b.outputs()[0].is_coinbase());
head = b.header.clone();
chain
.process_block(b.clone(), chain::Options::SKIP_POW)
@@ -623,8 +622,7 @@ fn spend_in_fork_and_compact() {
// mine the first block and keep track of the block_hash
// so we can spend the coinbase later
let b = prepare_block(&kc, &fork_head, &chain, 2);
let out_id = OutputIdentifier::from(&b.outputs()[0]);
assert!(out_id.features.is_coinbase());
assert!(b.outputs()[0].is_coinbase());
fork_head = b.header.clone();
chain
.process_block(b.clone(), chain::Options::SKIP_POW)
Loading

0 comments on commit 133089e

Please sign in to comment.