Skip to content

Commit

Permalink
use rkyv for serde
Browse files Browse the repository at this point in the history
  • Loading branch information
hashcashier committed Dec 11, 2024
1 parent 31f73c8 commit deedd06
Show file tree
Hide file tree
Showing 18 changed files with 871 additions and 46 deletions.
126 changes: 126 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ log = "0.4.22"
flate2 = "1.0.34"
once_cell = "1.20.2"
pot = "3.0.1"
rkyv = "0.8.9"
serde = { version = "1.0.210", features = ["derive"] }
serde_json = { version = "1.0.128", features = ["alloc"] }
thiserror = "1.0.64"
Expand Down
1 change: 1 addition & 0 deletions crates/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ alloy-primitives.workspace = true
alloy-rlp.workspace = true
k256.workspace = true
pot.workspace = true
rkyv.workspace = true
serde.workspace = true
thiserror.workspace = true
tiny-keccak.workspace = true
Expand Down
4 changes: 2 additions & 2 deletions crates/core/src/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ use std::sync::Arc;

pub trait CoreDriver: Default {
type ChainSpec: 'static;
type Block: Serialize + DeserializeOwned + 'static;
type Header: Serialize + DeserializeOwned + 'static;
type Block: Clone + Serialize + DeserializeOwned + 'static;
type Header: Clone + Serialize + DeserializeOwned + 'static;
type Receipt: Serialize + DeserializeOwned + 'static;
type Transaction: Serialize + DeserializeOwned + 'static;

Expand Down
83 changes: 77 additions & 6 deletions crates/core/src/mpt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,41 @@ pub const EMPTY_ROOT: B256 =
/// optimizing storage. However, operations targeting a truncated part will fail and
/// return an error. Another distinction of this implementation is that branches cannot
/// store values, aligning with the construction of MPTs in Ethereum.
#[derive(Clone, Debug, Default, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize)]
#[derive(
Clone,
Debug,
Default,
PartialEq,
Eq,
Ord,
PartialOrd,
Serialize,
Deserialize,
rkyv::Archive,
rkyv::Serialize,
rkyv::Deserialize,
)]
#[rkyv(bytecheck(
bounds(
__C: rkyv::validation::ArchiveContext,
__C::Error: rkyv::rancor::Source,
)
))]
#[rkyv(serialize_bounds(
__S: rkyv::ser::Writer + rkyv::ser::Allocator,
__S::Error: rkyv::rancor::Source,
))]
#[rkyv(deserialize_bounds(
__D::Error: rkyv::rancor::Source
))]
pub struct MptNode {
/// The type and data of the node.
data: MptNodeData,
#[rkyv(omit_bounds)]
pub data: MptNodeData,
/// Cache for a previously computed reference of this node. This is skipped during
/// serialization.
#[serde(skip)]
#[rkyv(with = rkyv::with::Skip)]
cached_reference: RefCell<Option<MptNodeReference>>,
}

Expand Down Expand Up @@ -88,21 +116,64 @@ impl From<B256> for MptNode {
/// Each node in the trie can be of one of several types, each with its own specific data
/// structure. This enum provides a clear and type-safe way to represent the data
/// associated with each node type.
#[derive(Clone, Debug, Default, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize)]
#[derive(
Clone,
Debug,
Default,
PartialEq,
Eq,
Ord,
PartialOrd,
Serialize,
Deserialize,
rkyv::Archive,
rkyv::Serialize,
rkyv::Deserialize,
)]
#[rkyv(bytecheck(
bounds(
__C: rkyv::validation::ArchiveContext,
)
))]
#[rkyv(serialize_bounds(
__S: rkyv::ser::Writer + rkyv::ser::Allocator,
__S::Error: rkyv::rancor::Source,
))]
#[rkyv(deserialize_bounds(
__D::Error: rkyv::rancor::Source
))]
pub enum MptNodeData {
/// Represents an empty trie node.
#[default]
Null,
/// A node that can have up to 16 children. Each child is an optional boxed [MptNode].
Branch([Option<Box<MptNode>>; 16]),
Branch(
// #[rkyv(with = rkyv::with::Map<rkyv::with::Map<Box<ArchivedMptNode>>>)]
#[rkyv(omit_bounds)] [Option<Box<MptNode>>; 16],
),
/// A leaf node that contains a key and a value, both represented as byte vectors.
Leaf(Vec<u8>, Vec<u8>),
/// A node that has exactly one child and is used to represent a shared prefix of
/// several keys.
Extension(Vec<u8>, Box<MptNode>),
Extension(
Vec<u8>,
// #[rkyv(with = Box<ArchivedMptNode>)]
#[rkyv(omit_bounds)] Box<MptNode>,
),
/// Represents a sub-trie by its hash, allowing for efficient storage of large
/// sub-tries without storing their entire content.
Digest(B256),
Digest(#[rkyv(with = B256Def)] B256),
}

#[derive(Clone, Debug, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
#[rkyv(remote = B256)]
#[rkyv(archived = ArchivedB256)]
pub struct B256Def(pub [u8; 32]);

impl From<B256Def> for B256 {
fn from(value: B256Def) -> Self {
B256::new(value.0)
}
}

/// Represents the ways in which one node can reference another node inside the sparse
Expand Down
22 changes: 14 additions & 8 deletions crates/core/src/stateless/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@

use crate::driver::CoreDriver;
use crate::rescue::{Recoverable, Wrapper};
use crate::stateless::data::StatelessClientData;
use crate::stateless::data::{
RkyvStatelessClientData, StatelessClientChainData, StatelessClientData,
};
use crate::stateless::engine::StatelessClientEngine;
use crate::stateless::execute::ExecutionStrategy;
use crate::stateless::finalize::FinalizationStrategy;
use crate::stateless::initialize::InitializationStrategy;
use crate::stateless::validate::ValidationStrategy;
use std::io::Read;

pub trait StatelessClient<Driver, Database>
where
Expand All @@ -32,18 +33,23 @@ where
type Execution: ExecutionStrategy<Driver, Wrapper<Database>>;
type Finalization: FinalizationStrategy<Driver, Database>;

fn data_from_reader<I: Read>(
reader: I,
) -> anyhow::Result<StatelessClientData<Driver::Block, Driver::Header>> {
Ok(pot::from_reader(reader)?)
}

fn data_from_slice(
slice: &[u8],
) -> anyhow::Result<StatelessClientData<Driver::Block, Driver::Header>> {
Ok(pot::from_slice(slice)?)
}

fn data_from_parts(
rkyv_slice: &[u8],
pot_slice: &[u8],
) -> anyhow::Result<StatelessClientData<Driver::Block, Driver::Header>> {
let rkyv_data =
rkyv::from_bytes::<RkyvStatelessClientData, rkyv::rancor::Error>(rkyv_slice)?;
let chain_data =
pot::from_slice::<StatelessClientChainData<Driver::Block, Driver::Header>>(pot_slice)?;
Ok(StatelessClientData::<Driver::Block, Driver::Header>::from_parts(rkyv_data, chain_data))
}

fn validate(
data: StatelessClientData<Driver::Block, Driver::Header>,
) -> anyhow::Result<StatelessClientEngine<Driver, Database>> {
Expand Down
Loading

0 comments on commit deedd06

Please sign in to comment.