Tx kernel entry (#1957)

* Wrap tx kernels in tx kernel entries when storing them in the MMR.
Decouples the storage impl of kernels.

* rustfmt
This commit is contained in:
Antioch Peverell 2018-11-11 16:03:03 +01:00 committed by GitHub
parent d0d8d14ac2
commit 207621b545
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 74 additions and 16 deletions

View file

@ -28,7 +28,9 @@ use lru_cache::LruCache;
use core::core::hash::{Hash, Hashed, ZERO_HASH}; use core::core::hash::{Hash, Hashed, ZERO_HASH};
use core::core::merkle_proof::MerkleProof; use core::core::merkle_proof::MerkleProof;
use core::core::verifier_cache::VerifierCache; use core::core::verifier_cache::VerifierCache;
use core::core::{Block, BlockHeader, BlockSums, Output, OutputIdentifier, Transaction, TxKernel}; use core::core::{
Block, BlockHeader, BlockSums, Output, OutputIdentifier, Transaction, TxKernelEntry,
};
use core::global; use core::global;
use core::pow; use core::pow;
use error::{Error, ErrorKind}; use error::{Error, ErrorKind};
@ -966,7 +968,7 @@ impl Chain {
} }
/// as above, for kernels /// as above, for kernels
pub fn get_last_n_kernel(&self, distance: u64) -> Vec<(Hash, TxKernel)> { pub fn get_last_n_kernel(&self, distance: u64) -> Vec<(Hash, TxKernelEntry)> {
let mut txhashset = self.txhashset.write(); let mut txhashset = self.txhashset.write();
txhashset.last_n_kernel(distance) txhashset.last_n_kernel(distance)
} }

View file

@ -15,7 +15,7 @@
//! Lightweight readonly view into kernel MMR for convenience. //! Lightweight readonly view into kernel MMR for convenience.
use core::core::pmmr::RewindablePMMR; use core::core::pmmr::RewindablePMMR;
use core::core::{BlockHeader, TxKernel}; use core::core::{BlockHeader, TxKernelEntry};
use error::{Error, ErrorKind}; use error::{Error, ErrorKind};
use grin_store::pmmr::PMMRBackend; use grin_store::pmmr::PMMRBackend;
@ -23,7 +23,7 @@ use store::Batch;
/// Rewindable (but readonly) view of the kernel set (based on kernel MMR). /// Rewindable (but readonly) view of the kernel set (based on kernel MMR).
pub struct RewindableKernelView<'a> { pub struct RewindableKernelView<'a> {
pmmr: RewindablePMMR<'a, TxKernel, PMMRBackend<TxKernel>>, pmmr: RewindablePMMR<'a, TxKernelEntry, PMMRBackend<TxKernelEntry>>,
batch: &'a Batch<'a>, batch: &'a Batch<'a>,
header: BlockHeader, header: BlockHeader,
} }
@ -31,7 +31,7 @@ pub struct RewindableKernelView<'a> {
impl<'a> RewindableKernelView<'a> { impl<'a> RewindableKernelView<'a> {
/// Build a new readonly kernel view. /// Build a new readonly kernel view.
pub fn new( pub fn new(
pmmr: RewindablePMMR<'a, TxKernel, PMMRBackend<TxKernel>>, pmmr: RewindablePMMR<'a, TxKernelEntry, PMMRBackend<TxKernelEntry>>,
batch: &'a Batch, batch: &'a Batch,
header: BlockHeader, header: BlockHeader,
) -> RewindableKernelView<'a> { ) -> RewindableKernelView<'a> {

View file

@ -29,7 +29,9 @@ use core::core::committed::Committed;
use core::core::hash::{Hash, Hashed}; use core::core::hash::{Hash, Hashed};
use core::core::merkle_proof::MerkleProof; use core::core::merkle_proof::MerkleProof;
use core::core::pmmr::{self, ReadonlyPMMR, RewindablePMMR, DBPMMR, PMMR}; use core::core::pmmr::{self, ReadonlyPMMR, RewindablePMMR, DBPMMR, PMMR};
use core::core::{Block, BlockHeader, Input, Output, OutputFeatures, OutputIdentifier, TxKernel}; use core::core::{
Block, BlockHeader, Input, Output, OutputFeatures, OutputIdentifier, TxKernel, TxKernelEntry,
};
use core::global; use core::global;
use core::ser::{PMMRIndexHashable, PMMRable}; use core::ser::{PMMRIndexHashable, PMMRable};
@ -119,7 +121,7 @@ pub struct TxHashSet {
output_pmmr_h: PMMRHandle<OutputIdentifier>, output_pmmr_h: PMMRHandle<OutputIdentifier>,
rproof_pmmr_h: PMMRHandle<RangeProof>, rproof_pmmr_h: PMMRHandle<RangeProof>,
kernel_pmmr_h: PMMRHandle<TxKernel>, kernel_pmmr_h: PMMRHandle<TxKernelEntry>,
// chain store used as index of commitments to MMR positions // chain store used as index of commitments to MMR positions
commit_index: Arc<ChainStore>, commit_index: Arc<ChainStore>,
@ -205,8 +207,8 @@ impl TxHashSet {
} }
/// as above, for kernels /// as above, for kernels
pub fn last_n_kernel(&mut self, distance: u64) -> Vec<(Hash, TxKernel)> { pub fn last_n_kernel(&mut self, distance: u64) -> Vec<(Hash, TxKernelEntry)> {
let kernel_pmmr: PMMR<TxKernel, _> = let kernel_pmmr: PMMR<TxKernelEntry, _> =
PMMR::at(&mut self.kernel_pmmr_h.backend, self.kernel_pmmr_h.last_pos); PMMR::at(&mut self.kernel_pmmr_h.backend, self.kernel_pmmr_h.last_pos);
kernel_pmmr.get_last_n_insertions(distance) kernel_pmmr.get_last_n_insertions(distance)
} }
@ -247,7 +249,7 @@ impl TxHashSet {
PMMR::at(&mut self.output_pmmr_h.backend, self.output_pmmr_h.last_pos); PMMR::at(&mut self.output_pmmr_h.backend, self.output_pmmr_h.last_pos);
let rproof_pmmr: PMMR<RangeProof, _> = let rproof_pmmr: PMMR<RangeProof, _> =
PMMR::at(&mut self.rproof_pmmr_h.backend, self.rproof_pmmr_h.last_pos); PMMR::at(&mut self.rproof_pmmr_h.backend, self.rproof_pmmr_h.last_pos);
let kernel_pmmr: PMMR<TxKernel, _> = let kernel_pmmr: PMMR<TxKernelEntry, _> =
PMMR::at(&mut self.kernel_pmmr_h.backend, self.kernel_pmmr_h.last_pos); PMMR::at(&mut self.kernel_pmmr_h.backend, self.kernel_pmmr_h.last_pos);
TxHashSetRoots { TxHashSetRoots {
@ -733,7 +735,7 @@ pub struct Extension<'a> {
header_pmmr: DBPMMR<'a, BlockHeader, HashOnlyMMRBackend>, header_pmmr: DBPMMR<'a, BlockHeader, HashOnlyMMRBackend>,
output_pmmr: PMMR<'a, OutputIdentifier, PMMRBackend<OutputIdentifier>>, output_pmmr: PMMR<'a, OutputIdentifier, PMMRBackend<OutputIdentifier>>,
rproof_pmmr: PMMR<'a, RangeProof, PMMRBackend<RangeProof>>, rproof_pmmr: PMMR<'a, RangeProof, PMMRBackend<RangeProof>>,
kernel_pmmr: PMMR<'a, TxKernel, PMMRBackend<TxKernel>>, kernel_pmmr: PMMR<'a, TxKernelEntry, PMMRBackend<TxKernelEntry>>,
/// Rollback flag. /// Rollback flag.
rollback: bool, rollback: bool,
@ -766,7 +768,7 @@ impl<'a> Committed for Extension<'a> {
for n in 1..self.kernel_pmmr.unpruned_size() + 1 { for n in 1..self.kernel_pmmr.unpruned_size() + 1 {
if pmmr::is_leaf(n) { if pmmr::is_leaf(n) {
if let Some(kernel) = self.kernel_pmmr.get_data(n) { if let Some(kernel) = self.kernel_pmmr.get_data(n) {
commitments.push(kernel.excess); commitments.push(kernel.excess());
} }
} }
} }
@ -951,14 +953,14 @@ impl<'a> Extension<'a> {
/// Push kernel onto MMR (hash and data files). /// Push kernel onto MMR (hash and data files).
fn apply_kernel(&mut self, kernel: &TxKernel) -> Result<(), Error> { fn apply_kernel(&mut self, kernel: &TxKernel) -> Result<(), Error> {
self.kernel_pmmr self.kernel_pmmr
.push(kernel.clone()) .push(TxKernelEntry::from(kernel.clone()))
.map_err(&ErrorKind::TxHashSetErr)?; .map_err(&ErrorKind::TxHashSetErr)?;
Ok(()) Ok(())
} }
fn apply_header(&mut self, header: &BlockHeader) -> Result<(), Error> { fn apply_header(&mut self, header: &BlockHeader) -> Result<(), Error> {
self.header_pmmr self.header_pmmr
.push(&header) .push(header)
.map_err(&ErrorKind::TxHashSetErr)?; .map_err(&ErrorKind::TxHashSetErr)?;
Ok(()) Ok(())
} }

View file

@ -250,13 +250,67 @@ impl TxKernel {
} }
} }
impl FixedLength for TxKernel { /// Wrapper around a tx kernel used when maintaining them in the MMR.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct TxKernelEntry {
/// The underlying tx kernel.
pub kernel: TxKernel,
}
impl Writeable for TxKernelEntry {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
ser_multiwrite!(
writer,
[write_u8, self.kernel.features.bits()],
[write_u64, self.kernel.fee],
[write_u64, self.kernel.lock_height],
[write_fixed_bytes, &self.kernel.excess]
);
self.kernel.excess_sig.write(writer)?;
Ok(())
}
}
impl Readable for TxKernelEntry {
fn read(reader: &mut Reader) -> Result<TxKernelEntry, ser::Error> {
let features =
KernelFeatures::from_bits(reader.read_u8()?).ok_or(ser::Error::CorruptedData)?;
let kernel = TxKernel {
features: features,
fee: reader.read_u64()?,
lock_height: reader.read_u64()?,
excess: Commitment::read(reader)?,
excess_sig: secp::Signature::read(reader)?,
};
Ok(TxKernelEntry { kernel })
}
}
impl TxKernelEntry {
/// The excess on the underlying tx kernel.
pub fn excess(&self) -> Commitment {
self.kernel.excess
}
/// Verify the underlying tx kernel.
pub fn verify(&self) -> Result<(), Error> {
self.kernel.verify()
}
}
impl From<TxKernel> for TxKernelEntry {
fn from(kernel: TxKernel) -> Self {
TxKernelEntry { kernel }
}
}
impl FixedLength for TxKernelEntry {
const LEN: usize = 17 // features plus fee and lock_height const LEN: usize = 17 // features plus fee and lock_height
+ secp::constants::PEDERSEN_COMMITMENT_SIZE + secp::constants::PEDERSEN_COMMITMENT_SIZE
+ secp::constants::AGG_SIGNATURE_SIZE; + secp::constants::AGG_SIGNATURE_SIZE;
} }
impl PMMRable for TxKernel {} impl PMMRable for TxKernelEntry {}
/// TransactionBody is a common abstraction for transaction and block /// TransactionBody is a common abstraction for transaction and block
#[derive(Serialize, Deserialize, Debug, Clone)] #[derive(Serialize, Deserialize, Debug, Clone)]