Skip to content

Commit

Permalink
refactor(chain): LocalChain takes a generic
Browse files Browse the repository at this point in the history
  • Loading branch information
LagginTimes committed Sep 5, 2024
1 parent cd2cd40 commit c993106
Showing 1 changed file with 45 additions and 25 deletions.
70 changes: 45 additions & 25 deletions crates/chain/src/local_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,17 @@ fn apply_changeset_to_checkpoint(

for cp in init_cp.iter() {
if cp.height() >= start_height {
extension.insert(cp.height(), cp.hash());
extension.insert(cp.height(), *cp.data());
} else {
base = Some(cp);
break;
}
}

for (&height, &hash) in &changeset.blocks {
match hash {
Some(hash) => {
extension.insert(height, hash);
for (&height, &data) in &changeset.blocks {
match data {
Some(data) => {
extension.insert(height, data);
}
None => {
extension.remove(&height);
Expand All @@ -42,7 +42,7 @@ fn apply_changeset_to_checkpoint(

let new_tip = match base {
Some(base) => base
.extend(extension.into_iter().map(BlockId::from))
.extend_data(extension)
.expect("extension is strictly greater than base"),
None => LocalChain::from_blocks(extension)?.tip(),
};
Expand All @@ -53,12 +53,24 @@ fn apply_changeset_to_checkpoint(
}

/// This is a local implementation of [`ChainOracle`].
#[derive(Debug, Clone, PartialEq)]
pub struct LocalChain {
tip: CheckPoint,
#[derive(Debug, Clone)]
pub struct LocalChain<B = BlockHash> {
tip: CheckPoint<B>,
}

impl ChainOracle for LocalChain {
impl<B> PartialEq for LocalChain<B>
where
B: Copy + core::cmp::PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.tip == other.tip
}
}

impl<B> ChainOracle for LocalChain<B>
where
B: Copy,
{
type Error = Infallible;

fn is_block_in_chain(
Expand All @@ -83,18 +95,18 @@ impl ChainOracle for LocalChain {
}
}

impl LocalChain {
impl LocalChain<BlockHash> {
/// Get the genesis hash.
pub fn genesis_hash(&self) -> BlockHash {
self.tip.get(0).expect("genesis must exist").hash()
self.tip.get(0).expect("genesis must exist").block_id().hash
}

/// Construct [`LocalChain`] from genesis `hash`.
#[must_use]
pub fn from_genesis_hash(hash: BlockHash) -> (Self, ChangeSet) {
let height = 0;
let chain = Self {
tip: CheckPoint::new(BlockId { height, hash }),
tip: CheckPoint::from_data(height, hash),
};
let changeset = chain.initial_changeset();
(chain, changeset)
Expand Down Expand Up @@ -134,7 +146,7 @@ impl LocalChain {
return Err(MissingGenesisError);
}

let mut tip: Option<CheckPoint> = None;
let mut tip: Option<CheckPoint<BlockHash>> = None;
for block in &blocks {
match tip {
Some(curr) => {
Expand All @@ -153,7 +165,7 @@ impl LocalChain {
}

/// Get the highest checkpoint.
pub fn tip(&self) -> CheckPoint {
pub fn tip(&self) -> CheckPoint<BlockHash> {
self.tip.clone()
}

Expand Down Expand Up @@ -405,17 +417,25 @@ impl LocalChain {
}

/// The [`ChangeSet`] represents changes to [`LocalChain`].
#[derive(Debug, Default, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct ChangeSet {
pub struct ChangeSet<B = BlockHash> {
/// Changes to the [`LocalChain`] blocks.
///
/// The key represents the block height, and the value either represents added a new [`CheckPoint`]
/// (if [`Some`]), or removing a [`CheckPoint`] (if [`None`]).
pub blocks: BTreeMap<u32, Option<BlockHash>>,
pub blocks: BTreeMap<u32, Option<B>>,
}

impl<B> Default for ChangeSet<B> {
fn default() -> Self {
ChangeSet {
blocks: BTreeMap::default(),
}
}
}

impl Merge for ChangeSet {
impl<B> Merge for ChangeSet<B> {
fn merge(&mut self, other: Self) {
Merge::merge(&mut self.blocks, other.blocks)
}
Expand All @@ -425,24 +445,24 @@ impl Merge for ChangeSet {
}
}

impl<B: IntoIterator<Item = (u32, Option<BlockHash>)>> From<B> for ChangeSet {
fn from(blocks: B) -> Self {
impl<B, I: IntoIterator<Item = (u32, Option<B>)>> From<I> for ChangeSet<B> {
fn from(blocks: I) -> Self {
Self {
blocks: blocks.into_iter().collect(),
}
}
}

impl FromIterator<(u32, Option<BlockHash>)> for ChangeSet {
fn from_iter<T: IntoIterator<Item = (u32, Option<BlockHash>)>>(iter: T) -> Self {
impl<B> FromIterator<(u32, Option<B>)> for ChangeSet<B> {
fn from_iter<T: IntoIterator<Item = (u32, Option<B>)>>(iter: T) -> Self {
Self {
blocks: iter.into_iter().collect(),
}
}
}

impl FromIterator<(u32, BlockHash)> for ChangeSet {
fn from_iter<T: IntoIterator<Item = (u32, BlockHash)>>(iter: T) -> Self {
impl<B> FromIterator<(u32, B)> for ChangeSet<B> {
fn from_iter<T: IntoIterator<Item = (u32, B)>>(iter: T) -> Self {
Self {
blocks: iter
.into_iter()
Expand Down

0 comments on commit c993106

Please sign in to comment.