diff --git a/chain/src/linked_list.rs b/chain/src/linked_list.rs index f32cf6a3bd..0decd70663 100644 --- a/chain/src/linked_list.rs +++ b/chain/src/linked_list.rs @@ -14,41 +14,32 @@ //! Implements storage primitives required by the chain -use crate::core::consensus::HeaderInfo; -use crate::core::core::hash::{Hash, Hashed}; -use crate::core::core::{Block, BlockHeader, BlockSums}; -use crate::core::pow::Difficulty; -use crate::core::ser::{self, ProtocolVersion, Readable, Reader, Writeable, Writer}; -use crate::store::{ - Batch, KERNEL_POS_PREFIX, NEW_COINBASE_OUTPUT_POS_PREFIX, NEW_PLAIN_OUTPUT_POS_PREFIX, -}; -use crate::types::{CommitPos, OutputPos, Tip}; +use crate::core::ser::{self, Readable, Reader, Writeable, Writer}; +use crate::store::{Batch, COINBASE_KERNEL_POS_PREFIX}; +use crate::types::{CommitPos, OutputPos}; use crate::util::secp::pedersen::Commitment; -use croaring::Bitmap; use enum_primitive::FromPrimitive; use grin_store as store; -use grin_store::{option_to_not_found, to_key, to_key_u64, Error, SerIterator}; -use std::convert::TryInto; use std::marker::PhantomData; -use std::sync::Arc; +use store::{to_key, to_key_u64, Error}; enum_from_primitive! { #[derive(Copy, Clone, Debug, PartialEq)] - enum LinkedListVariant { + enum ListWrapperVariant { Unique = 0, Multi = 1, } } -impl Writeable for LinkedListVariant { +impl Writeable for ListWrapperVariant { fn write(&self, writer: &mut W) -> Result<(), ser::Error> { writer.write_u8(*self as u8) } } -impl Readable for LinkedListVariant { - fn read(reader: &mut dyn Reader) -> Result { - LinkedListVariant::from_u8(reader.read_u8()?).ok_or(ser::Error::CorruptedData) +impl Readable for ListWrapperVariant { + fn read(reader: &mut dyn Reader) -> Result { + ListWrapperVariant::from_u8(reader.read_u8()?).ok_or(ser::Error::CorruptedData) } } @@ -73,7 +64,7 @@ impl Readable for ListEntryVariant { } } -pub trait FooLinkedList { +pub trait ListIndex { /// List type type List: Readable + Writeable; @@ -117,12 +108,12 @@ pub trait FooLinkedList { } #[derive(Copy, Clone, Debug, PartialEq)] -pub enum LinkedList { +pub enum ListWrapper { Unique { pos: T }, Multi { head: u64, tail: u64 }, } -impl Writeable for LinkedList +impl Writeable for ListWrapper where T: Writeable, { @@ -131,12 +122,12 @@ where /// "Multi" has references to "head" and "tail". fn write(&self, writer: &mut W) -> Result<(), ser::Error> { match self { - LinkedList::Unique { pos } => { - LinkedListVariant::Unique.write(writer)?; + ListWrapper::Unique { pos } => { + ListWrapperVariant::Unique.write(writer)?; pos.write(writer)?; } - LinkedList::Multi { head, tail } => { - LinkedListVariant::Multi.write(writer)?; + ListWrapper::Multi { head, tail } => { + ListWrapperVariant::Multi.write(writer)?; writer.write_u64(*head)?; writer.write_u64(*tail)?; } @@ -145,17 +136,17 @@ where } } -impl Readable for LinkedList +impl Readable for ListWrapper where T: Readable, { /// Read the first byte to determine what needs to be read beyond that. - fn read(reader: &mut dyn Reader) -> Result, ser::Error> { - let entry = match LinkedListVariant::read(reader)? { - LinkedListVariant::Unique => LinkedList::Unique { + fn read(reader: &mut dyn Reader) -> Result, ser::Error> { + let entry = match ListWrapperVariant::read(reader)? { + ListWrapperVariant::Unique => ListWrapper::Unique { pos: T::read(reader)?, }, - LinkedListVariant::Multi => LinkedList::Multi { + ListWrapperVariant::Multi => ListWrapper::Multi { head: reader.read_u64()?, tail: reader.read_u64()?, }, @@ -164,37 +155,25 @@ where } } -pub struct MyLinkedList { +pub struct MultiIndex { phantom: PhantomData<*const T>, prefix: u8, } -pub fn output_plain_index() -> MyLinkedList { - MyLinkedList { - phantom: PhantomData, - prefix: NEW_PLAIN_OUTPUT_POS_PREFIX, - } -} - -pub fn output_coinbase_index() -> MyLinkedList { - MyLinkedList { - phantom: PhantomData, - prefix: NEW_COINBASE_OUTPUT_POS_PREFIX, - } -} - -pub fn kernel_index() -> MyLinkedList { - MyLinkedList { - phantom: PhantomData, - prefix: KERNEL_POS_PREFIX, +impl MultiIndex { + pub fn init(prefix: u8) -> MultiIndex { + MultiIndex { + phantom: PhantomData, + prefix, + } } } -impl FooLinkedList for MyLinkedList +impl ListIndex for MultiIndex where T: PosEntry, { - type List = LinkedList; + type List = ListWrapper; type Entry = ListEntry; fn list_key(&self, commit: Commitment) -> Vec { @@ -211,12 +190,12 @@ where fn pop_entry(&self, batch: &Batch<'_>, commit: Commitment) -> Result, Error> { match self.get_list(batch, commit)? { None => Ok(None), - Some(LinkedList::Unique { pos }) => { + Some(ListWrapper::Unique { pos }) => { // TODO - delete the list itself. Ok(Some(pos)) } - Some(LinkedList::Multi { head, tail }) => { + Some(ListWrapper::Multi { head, tail }) => { // read head from db // read next one // update next to a head if it was a middle @@ -230,10 +209,10 @@ where fn push_entry(&self, batch: &Batch<'_>, commit: Commitment, new_pos: T) -> Result<(), Error> { match self.get_list(batch, commit)? { None => { - let list = LinkedList::Unique { pos: new_pos }; + let list = ListWrapper::Unique { pos: new_pos }; batch.db.put_ser(&self.list_key(commit), &list)?; } - Some(LinkedList::Unique { pos: current_pos }) => { + Some(ListWrapper::Unique { pos: current_pos }) => { let head = ListEntry::Head { pos: new_pos, next: current_pos.pos(), @@ -242,7 +221,7 @@ where pos: current_pos, prev: new_pos.pos(), }; - let list: LinkedList = LinkedList::Multi { + let list: ListWrapper = ListWrapper::Multi { head: new_pos.pos(), tail: current_pos.pos(), }; @@ -254,7 +233,7 @@ where .put_ser(&self.entry_key(commit, current_pos.pos()), &tail)?; batch.db.put_ser(&self.list_key(commit), &list)?; } - Some(LinkedList::Multi { head, tail }) => { + Some(ListWrapper::Multi { head, tail }) => { if let Some(ListEntry::Head { pos: current_pos, next: current_next, @@ -269,7 +248,7 @@ where next: current_next, prev: new_pos.pos(), }; - let list: LinkedList = LinkedList::Multi { + let list: ListWrapper = ListWrapper::Multi { head: new_pos.pos(), tail, }; @@ -293,7 +272,7 @@ pub trait PosEntry: Readable + Writeable + Copy { fn pos(&self) -> u64; } -impl PosEntry for OutputPos { +impl PosEntry for CommitPos { fn pos(&self) -> u64 { self.pos } diff --git a/chain/src/store.rs b/chain/src/store.rs index 4cf14b2bc4..bd25794eca 100644 --- a/chain/src/store.rs +++ b/chain/src/store.rs @@ -18,15 +18,14 @@ use crate::core::consensus::HeaderInfo; use crate::core::core::hash::{Hash, Hashed}; use crate::core::core::{Block, BlockHeader, BlockSums}; use crate::core::pow::Difficulty; -use crate::core::ser::{self, ProtocolVersion, Readable, Reader, Writeable, Writer}; +use crate::core::ser::ProtocolVersion; +use crate::linked_list::{ListIndex, MultiIndex}; use crate::types::{CommitPos, OutputPos, Tip}; use crate::util::secp::pedersen::Commitment; use croaring::Bitmap; -use enum_primitive::FromPrimitive; use grin_store as store; -use grin_store::{option_to_not_found, to_key, to_key_u64, Error, SerIterator}; +use grin_store::{option_to_not_found, to_key, Error, SerIterator}; use std::convert::TryInto; -use std::marker::PhantomData; use std::sync::Arc; const STORE_SUBPATH: &str = "chain"; @@ -38,9 +37,8 @@ const TAIL_PREFIX: u8 = b'T'; const HEADER_HEAD_PREFIX: u8 = b'G'; const OUTPUT_POS_PREFIX: u8 = b'p'; -pub const NEW_PLAIN_OUTPUT_POS_PREFIX: u8 = b'P'; -pub const NEW_COINBASE_OUTPUT_POS_PREFIX: u8 = b'C'; -pub const KERNEL_POS_PREFIX: u8 = b'K'; +// Proof of concept until we support NRD kernels. +pub const COINBASE_KERNEL_POS_PREFIX: u8 = b'K'; const BLOCK_INPUT_BITMAP_PREFIX: u8 = b'B'; const BLOCK_SUMS_PREFIX: u8 = b'M'; @@ -508,3 +506,7 @@ impl<'a> Iterator for DifficultyIter<'a> { } } } + +pub fn coinbase_kernel_index() -> MultiIndex { + MultiIndex::init(COINBASE_KERNEL_POS_PREFIX) +} diff --git a/chain/src/types.rs b/chain/src/types.rs index ffc9a614f8..5732ee18b2 100644 --- a/chain/src/types.rs +++ b/chain/src/types.rs @@ -259,7 +259,7 @@ impl OutputRoots { } /// Minimal struct representing a known MMR position and associated block height. -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, PartialEq)] pub struct CommitPos { /// MMR position pub pos: u64, diff --git a/chain/tests/store_output_pos_list.rs b/chain/tests/store_kernel_pos_index.rs similarity index 64% rename from chain/tests/store_output_pos_list.rs rename to chain/tests/store_kernel_pos_index.rs index 8a2cdca963..399c3e141f 100644 --- a/chain/tests/store_output_pos_list.rs +++ b/chain/tests/store_kernel_pos_index.rs @@ -16,7 +16,7 @@ use grin_chain as chain; use grin_core as core; use grin_util as util; -use crate::chain::linked_list::{self, FooLinkedList, LinkedList}; +use crate::chain::linked_list::{self, ListIndex, ListWrapper}; use crate::chain::store::{self, ChainStore}; use crate::chain::types::{CommitPos, OutputPos}; use crate::core::core::OutputFeatures; @@ -26,7 +26,7 @@ mod chain_test_helper; use self::chain_test_helper::clean_output_dir; #[test] -fn test_store_output_pos_list() { +fn test_store_kernel_index() { util::init_test_logger(); let chain_dir = ".grin_idx_1"; @@ -38,82 +38,50 @@ fn test_store_output_pos_list() { let commit = Commitment::from_vec(vec![]); - let index = linked_list::output_plain_index(); + let index = store::coinbase_kernel_index(); assert_eq!(index.get_list(&batch, commit), Ok(None)); assert_eq!( - index.push_entry( - &batch, - commit, - OutputPos { - pos: 1, - height: 1, - features: OutputFeatures::Plain, - }, - ), + index.push_entry(&batch, commit, CommitPos { pos: 1, height: 1 },), Ok(()), ); assert_eq!( index.get_list(&batch, commit), - Ok(Some(LinkedList::Unique { - pos: OutputPos { - pos: 1, - height: 1, - features: OutputFeatures::Plain - } + Ok(Some(ListWrapper::Unique { + pos: CommitPos { pos: 1, height: 1 } })), ); assert_eq!( - index.push_entry( - &batch, - commit, - OutputPos { - pos: 2, - height: 2, - features: OutputFeatures::Plain, - }, - ), + index.push_entry(&batch, commit, CommitPos { pos: 2, height: 2 },), Ok(()), ); assert_eq!( index.get_list(&batch, commit), - Ok(Some(LinkedList::Multi { head: 2, tail: 1 })), + Ok(Some(ListWrapper::Multi { head: 2, tail: 1 })), ); assert_eq!( - index.push_entry( - &batch, - commit, - OutputPos { - pos: 3, - height: 3, - features: OutputFeatures::Plain, - }, - ), + index.push_entry(&batch, commit, CommitPos { pos: 3, height: 3 },), Ok(()), ); assert_eq!( index.get_list(&batch, commit), - Ok(Some(LinkedList::Multi { head: 3, tail: 1 })), + Ok(Some(ListWrapper::Multi { head: 3, tail: 1 })), ); assert_eq!( index.pop_entry(&batch, commit,), - Ok(Some(OutputPos { - pos: 3, - height: 3, - features: OutputFeatures::Plain, - })), + Ok(Some(CommitPos { pos: 3, height: 3 })), ); assert_eq!( index.get_list(&batch, commit), - Ok(Some(LinkedList::Multi { head: 2, tail: 1 })), + Ok(Some(ListWrapper::Multi { head: 2, tail: 1 })), ); // Cleanup chain directory