Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Changelog

## 0.1.0

Initial release of the Signet storage workspace.

### Crates

- **signet-storage-types**: Shared primitive types adapted from Reth
- **signet-hot**: Trait-based hot storage abstractions
- **signet-hot-mdbx**: MDBX implementation of hot storage
- **signet-cold**: Append-only cold storage for historical data
- **signet-cold-mdbx**: MDBX table definitions for cold storage
- **signet-storage**: Unified storage interface combining hot and cold backends
15 changes: 7 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ members = ["crates/*"]
resolver = "2"

[workspace.package]
version = "0.0.1"
version = "0.1.0"
edition = "2024"
rust-version = "1.92"
authors = ["init4"]
Expand Down Expand Up @@ -35,13 +35,12 @@ incremental = false

[workspace.dependencies]
# internal
signet-hot = { version = "0.0.1", path = "./crates/hot" }
signet-hot-mdbx = { version = "0.0.1", path = "./crates/hot-mdbx" }
signet-mdbx-hot = { version = "0.0.1", path = "./crates/mdbx-hot" }
signet-cold = { version = "0.0.1", path = "./crates/cold" }
signet-cold-mdbx = { version = "0.0.1", path = "./crates/cold-mdbx" }
signet-storage = { version = "0.0.1", path = "./crates/storage" }
signet-storage-types = { version = "0.0.1", path = "./crates/types" }
signet-hot = { version = "0.1.0", path = "./crates/hot" }
signet-hot-mdbx = { version = "0.1.0", path = "./crates/hot-mdbx" }
signet-cold = { version = "0.1.0", path = "./crates/cold" }
signet-cold-mdbx = { version = "0.1.0", path = "./crates/cold-mdbx" }
signet-storage = { version = "0.1.0", path = "./crates/storage" }
signet-storage-types = { version = "0.1.0", path = "./crates/types" }

# External, in-house
signet-libmdbx = { version = "0.8.0" }
Expand Down
6 changes: 5 additions & 1 deletion crates/cold-mdbx/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,13 @@ repository.workspace = true
keywords = ["mdbx", "storage", "cold-storage", "blockchain"]
categories = ["database-implementations"]

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

[dependencies]
alloy.workspace = true
signet-cold = { version = "0.0.1", path = "../cold" }
signet-cold.workspace = true
signet-hot.workspace = true
signet-hot-mdbx.workspace = true
signet-storage-types.workspace = true
Expand Down
5 changes: 5 additions & 0 deletions crates/cold-mdbx/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@
//! ## Metadata Tables
//!
//! - [`ColdMetadata`]: Storage metadata (latest block, finalized, safe, earliest).
//!
//! # Feature Flags
//!
//! - **`test-utils`**: Propagates `signet-cold/test-utils` for conformance
//! testing against the MDBX backend.

#![warn(
missing_copy_implementations,
Expand Down
10 changes: 9 additions & 1 deletion crates/cold/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,23 @@ repository.workspace = true
keywords = ["blockchain", "storage", "cold-storage", "historical"]
categories = ["database-implementations"]

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

[dependencies]
alloy.workspace = true
lru.workspace = true
signet-storage-types = { version = "0.0.1", path = "../types" }
signet-storage-types.workspace = true
thiserror.workspace = true
tokio.workspace = true
tokio-util.workspace = true
tracing.workspace = true

[dev-dependencies]
signet-cold = { path = ".", features = ["test-utils"] }
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }

[features]
in-memory = []
test-utils = ["in-memory"]
7 changes: 7 additions & 0 deletions crates/cold/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,13 @@
//! ```
//!
//! This is a design sketch; no implementation is provided yet.
//!
//! # Feature Flags
//!
//! - **`in-memory`**: Enables the [`mem`] module, providing an in-memory
//! [`ColdStorage`] backend for testing.
//! - **`test-utils`**: Enables the [`conformance`] module with backend
//! conformance tests. Implies `in-memory`.

#![warn(
missing_copy_implementations,
Expand Down
9 changes: 9 additions & 0 deletions crates/cold/tests/conformance.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//! Conformance tests for the in-memory cold storage backend.

use signet_cold::{conformance::conformance, mem::MemColdBackend};

#[tokio::test]
async fn mem_backend_conformance() {
let backend = MemColdBackend::new();
conformance(&backend).await.unwrap();
}
4 changes: 4 additions & 0 deletions crates/hot-mdbx/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ repository.workspace = true
keywords = ["mdbx", "storage", "key-value", "blockchain"]
categories = ["database-implementations"]

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

[dependencies]
alloy.workspace = true
bytes.workspace = true
Expand Down
7 changes: 7 additions & 0 deletions crates/hot-mdbx/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@
//!
//! Overall, we do NOT recommend using this to open existing databases that
//! were not created and managed by this implementation.
//!
//! # Feature Flags
//!
//! - **`test-utils`**: Enables the [`test_utils`] module with MDBX test
//! helpers and conformance tests. Adds a `tempfile` dependency.
//! - **`disable-lock`**: Disables the storage lock file, allowing multiple
//! processes to open the same database. Intended for testing scenarios.

#![warn(
missing_copy_implementations,
Expand Down
14 changes: 0 additions & 14 deletions crates/hot-mdbx/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1302,11 +1302,6 @@ mod tests {
entries.push(next);
}
}

eprintln!("\nStorageChangeSets entries ({} total):", entries.len());
for ((bn, addr), slot, val) in &entries {
eprintln!(" block={}, addr={:?}, slot={}, old_value={}", bn, addr, slot, val);
}
}

// Count PlainStorageState entries before unwind
Expand All @@ -1329,10 +1324,6 @@ mod tests {
}
}

eprintln!("\nPlainStorageState BEFORE unwind ({} total):", entries.len());
for (addr, slot, val) in &entries {
eprintln!(" addr={:?}, slot={}, value={}", addr, slot, val);
}
assert_eq!(entries.len(), 7, "Expected 7 storage entries before unwind");
}

Expand Down Expand Up @@ -1363,11 +1354,6 @@ mod tests {
}
}

eprintln!("\nPlainStorageState AFTER unwind ({} total):", entries.len());
for (addr, slot, val) in &entries {
eprintln!(" addr={:?}, slot={}, value={}", addr, slot, val);
}

// Expected: addr1.slot1=20, addr2.slot1=100 (2 entries)
assert_eq!(entries.len(), 2, "Expected 2 storage entries after unwind");

Expand Down
4 changes: 4 additions & 0 deletions crates/hot/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ repository.workspace = true
keywords = ["storage", "key-value", "blockchain", "database"]
categories = ["database-implementations"]

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

[dependencies]
signet-storage-types.workspace = true
signet-zenith.workspace = true
Expand Down
7 changes: 7 additions & 0 deletions crates/hot/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,13 @@
//! [`HotKvRead`]: model::HotKvRead
//! [`HotKvWrite`]: model::HotKvWrite
//! [`HotKv`]: model::HotKv
//! # Feature Flags
//!
//! - **`in-memory`**: Enables the [`mem`] module, providing an in-memory
//! [`HotKv`] backend for testing.
//! - **`test-utils`**: Enables the [`conformance`] module with backend
//! conformance tests. Implies `in-memory`.
//!
//! [`DualKey`]: tables::DualKey
//! [`SingleKey`]: tables::SingleKey
//! [`Table`]: tables::Table
Expand Down
10 changes: 10 additions & 0 deletions crates/storage/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ repository.workspace = true
keywords = ["blockchain", "storage", "ethereum"]
categories = ["data-structures"]

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

[dependencies]
signet-cold.workspace = true
signet-hot.workspace = true
Expand All @@ -20,6 +24,12 @@ alloy.workspace = true
thiserror.workspace = true
tokio-util.workspace = true

[dev-dependencies]
signet-storage = { path = ".", features = ["test-utils"] }
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
tokio-util.workspace = true
trevm.workspace = true

[features]
default = []
test-utils = ["signet-hot/test-utils", "signet-cold/test-utils"]
6 changes: 6 additions & 0 deletions crates/storage/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@
//! // Write to both storages (takes ownership)
//! storage.append_blocks(vec![block])?;
//! ```
//!
//! # Feature Flags
//!
//! - **`test-utils`**: Propagates `signet-hot/test-utils` and
//! `signet-cold/test-utils`, enabling in-memory backends and conformance
//! tests for both storage layers.

#![warn(
missing_copy_implementations,
Expand Down
76 changes: 76 additions & 0 deletions crates/storage/tests/unified.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
//! Integration tests for [`UnifiedStorage`].

use alloy::consensus::{Header, Sealable};
use signet_cold::{ColdStorageTask, HeaderSpecifier, mem::MemColdBackend};
use signet_hot::{HistoryRead, HotKv, mem::MemKv};
use signet_storage::UnifiedStorage;
use signet_storage_types::{ExecutedBlock, ExecutedBlockBuilder, SealedHeader};
use tokio_util::sync::CancellationToken;
use trevm::revm::database::BundleState;

/// Build a chain of blocks with valid parent hash linkage.
fn make_chain(count: u64) -> Vec<ExecutedBlock> {
let mut blocks = Vec::with_capacity(count as usize);
let mut parent_hash = alloy::primitives::B256::ZERO;

for number in 0..count {
let header = Header { number, parent_hash, ..Default::default() };
let sealed: SealedHeader = header.seal_slow();
parent_hash = sealed.hash();
let block = ExecutedBlockBuilder::new()
.header(sealed)
.bundle(BundleState::default())
.build()
.unwrap();
blocks.push(block);
}
blocks
}

#[tokio::test]
async fn append_and_read_back() {
let hot = MemKv::new();
let cancel = CancellationToken::new();
let cold_handle = ColdStorageTask::spawn(MemColdBackend::new(), cancel.clone());

let storage = UnifiedStorage::new(hot.clone(), cold_handle.clone());

// Append a block
let blocks = make_chain(1);
let expected_hash = blocks[0].header.hash();
storage.append_blocks(blocks).unwrap();

// Verify hot storage has the block
let reader = hot.reader().unwrap();
let tip = reader.get_chain_tip().unwrap();
assert_eq!(tip, Some((0, expected_hash)));

// Verify cold storage has the header
let header = cold_handle.get_header(HeaderSpecifier::Number(0)).await.unwrap();
assert!(header.is_some());

cancel.cancel();
}

#[tokio::test]
async fn append_multiple_and_unwind() {
let hot = MemKv::new();
let cancel = CancellationToken::new();
let cold_handle = ColdStorageTask::spawn(MemColdBackend::new(), cancel.clone());

let storage = UnifiedStorage::new(hot.clone(), cold_handle.clone());

// Append blocks 0, 1, 2
storage.append_blocks(make_chain(3)).unwrap();

// Verify tip is at block 2
assert_eq!(hot.reader().unwrap().get_chain_tip().unwrap().unwrap().0, 2);

// Unwind above block 0
storage.unwind_above(0).unwrap();

// Hot tip should be block 0
assert_eq!(hot.reader().unwrap().get_chain_tip().unwrap().unwrap().0, 0);

cancel.cancel();
}
4 changes: 4 additions & 0 deletions crates/types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ repository.workspace = true
keywords = ["blockchain", "storage", "types", "ethereum"]
categories = ["data-structures"]

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

[dependencies]
alloy.workspace = true
bitflags = "2.10.0"
Expand Down
3 changes: 3 additions & 0 deletions rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[toolchain]
channel = "1.92"
components = ["clippy", "rustfmt"]