From f05d3dd92021104ff1c7f6b0b45e330ac5ab7c87 Mon Sep 17 00:00:00 2001 From: Antioch Peverell Date: Thu, 29 Nov 2018 10:17:44 +0000 Subject: [PATCH] decouple outputs from output MMR (#2044) --- chain/src/txhashset/txhashset.rs | 16 ++++++++-------- chain/src/txhashset/utxo_view.rs | 6 +++--- core/src/core/transaction.rs | 26 ++++++++++++++++++-------- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/chain/src/txhashset/txhashset.rs b/chain/src/txhashset/txhashset.rs index 2538fc734..babe19f21 100644 --- a/chain/src/txhashset/txhashset.rs +++ b/chain/src/txhashset/txhashset.rs @@ -102,7 +102,7 @@ pub struct TxHashSet { /// via a "sync_extension". sync_pmmr_h: PMMRHandle, - output_pmmr_h: PMMRHandle, + output_pmmr_h: PMMRHandle, rproof_pmmr_h: PMMRHandle, kernel_pmmr_h: PMMRHandle, @@ -163,7 +163,7 @@ impl TxHashSet { pub fn is_unspent(&mut self, output_id: &OutputIdentifier) -> Result<(Hash, u64), Error> { match self.commit_index.get_output_pos(&output_id.commit) { Ok(pos) => { - let output_pmmr: PMMR = + let output_pmmr: PMMR = PMMR::at(&mut self.output_pmmr_h.backend, self.output_pmmr_h.last_pos); if let Some(hash) = output_pmmr.get_hash(pos) { if hash == output_id.hash_with_index(pos - 1) { @@ -185,7 +185,7 @@ impl TxHashSet { /// TODO: These need to return the actual data from the flat-files instead /// of hashes now pub fn last_n_output(&mut self, distance: u64) -> Vec<(Hash, OutputIdentifier)> { - let output_pmmr: PMMR = + let output_pmmr: PMMR = PMMR::at(&mut self.output_pmmr_h.backend, self.output_pmmr_h.last_pos); output_pmmr.get_last_n_insertions(distance) } @@ -227,7 +227,7 @@ impl TxHashSet { start_index: u64, max_count: u64, ) -> (u64, Vec) { - let output_pmmr: PMMR = + let output_pmmr: PMMR = PMMR::at(&mut self.output_pmmr_h.backend, self.output_pmmr_h.last_pos); output_pmmr.elements_from_insertion_index(start_index, max_count) } @@ -252,7 +252,7 @@ impl TxHashSet { pub fn roots(&mut self) -> TxHashSetRoots { let header_pmmr: PMMR = PMMR::at(&mut self.header_pmmr_h.backend, self.header_pmmr_h.last_pos); - let output_pmmr: PMMR = + let output_pmmr: PMMR = PMMR::at(&mut self.output_pmmr_h.backend, self.output_pmmr_h.last_pos); let rproof_pmmr: PMMR = PMMR::at(&mut self.rproof_pmmr_h.backend, self.rproof_pmmr_h.last_pos); @@ -270,7 +270,7 @@ impl TxHashSet { /// build a new merkle proof for the given position pub fn merkle_proof(&mut self, commit: Commitment) -> Result { let pos = self.commit_index.get_output_pos(&commit).unwrap(); - let output_pmmr: PMMR = + let output_pmmr: PMMR = PMMR::at(&mut self.output_pmmr_h.backend, self.output_pmmr_h.last_pos); output_pmmr.merkle_proof(pos) } @@ -773,7 +773,7 @@ pub struct Extension<'a> { header: BlockHeader, header_pmmr: PMMR<'a, BlockHeader, PMMRBackend>, - output_pmmr: PMMR<'a, OutputIdentifier, PMMRBackend>, + output_pmmr: PMMR<'a, Output, PMMRBackend>, rproof_pmmr: PMMR<'a, RangeProof, PMMRBackend>, kernel_pmmr: PMMR<'a, TxKernel, PMMRBackend>, @@ -967,7 +967,7 @@ impl<'a> Extension<'a> { // push the new output to the MMR. let output_pos = self .output_pmmr - .push(OutputIdentifier::from_output(out)) + .push(out.clone()) .map_err(&ErrorKind::TxHashSetErr)?; // push the rangeproof to the MMR. diff --git a/chain/src/txhashset/utxo_view.rs b/chain/src/txhashset/utxo_view.rs index 10fd06380..ceaf13530 100644 --- a/chain/src/txhashset/utxo_view.rs +++ b/chain/src/txhashset/utxo_view.rs @@ -15,7 +15,7 @@ //! Lightweight readonly view into output MMR for convenience. use core::core::pmmr::ReadonlyPMMR; -use core::core::{Block, Input, Output, OutputIdentifier, Transaction}; +use core::core::{Block, Input, Output, Transaction}; use error::{Error, ErrorKind}; use grin_store::pmmr::PMMRBackend; @@ -23,14 +23,14 @@ use store::Batch; /// Readonly view of the UTXO set (based on output MMR). pub struct UTXOView<'a> { - pmmr: ReadonlyPMMR<'a, OutputIdentifier, PMMRBackend>, + pmmr: ReadonlyPMMR<'a, Output, PMMRBackend>, batch: &'a Batch<'a>, } impl<'a> UTXOView<'a> { /// Build a new UTXO view. pub fn new( - pmmr: ReadonlyPMMR<'a, OutputIdentifier, PMMRBackend>, + pmmr: ReadonlyPMMR<'a, Output, PMMRBackend>, batch: &'a Batch, ) -> UTXOView<'a> { UTXOView { pmmr, batch } diff --git a/core/src/core/transaction.rs b/core/src/core/transaction.rs index 33728a3a0..ab510990f 100644 --- a/core/src/core/transaction.rs +++ b/core/src/core/transaction.rs @@ -1147,6 +1147,15 @@ impl Readable for Output { } } +/// We can build an Output MMR but store instances of OutputIdentifier in the MMR data file. +impl PMMRable for Output { + type E = OutputIdentifier; + + fn as_elmt(self) -> Self::E { + self.into() + } +} + impl Output { /// Commitment for the output pub fn commitment(&self) -> Commitment { @@ -1244,14 +1253,6 @@ impl FixedLength for OutputIdentifier { const LEN: usize = 1 + secp::constants::PEDERSEN_COMMITMENT_SIZE; } -impl PMMRable for OutputIdentifier { - type E = Self; - - fn as_elmt(self) -> Self::E { - self - } -} - impl Writeable for OutputIdentifier { fn write(&self, writer: &mut W) -> Result<(), ser::Error> { writer.write_u8(self.features.bits())?; @@ -1271,6 +1272,15 @@ impl Readable for OutputIdentifier { } } +impl From for OutputIdentifier { + fn from(out: Output) -> Self { + OutputIdentifier { + features: out.features, + commit: out.commit, + } + } +} + /// Construct msg from tx fee and lock_height. pub fn kernel_sig_msg(fee: u64, lock_height: u64) -> Result { let mut bytes = [0; 32];