Skip to content
Closed
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
31 changes: 31 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Signet Node Components

## Commands

- `cargo +nightly fmt` - format
- `cargo clippy -p <crate> --all-features --all-targets` - lint with features
- `cargo clippy -p <crate> --no-default-features --all-targets` - lint without
- `cargo t -p <crate>` - test specific crate

Pre-commit: clippy (both feature sets where applicable) + fmt. Never use `cargo check/build`.

## Style

- Functional combinators over imperative control flow
- `let else` for early returns, avoid nesting
- No glob imports; group imports from same crate; no blank lines between imports
- Private by default, `pub(crate)` for internal, `pub` for API only; never `pub(super)`
- `thiserror` for library errors, `eyre` for apps, never `anyhow`
- `tracing` for instrumentation: instrument work items not long-lived tasks; `skip(self)` on methods
- Builders for structs with >4 fields or multiple same-type fields
- Tests: fail fast with `unwrap()`, never return `Result`; unit tests in `mod tests`
- Rustdoc on all public items with usage examples; hide scaffolding with `#`
- `// SAFETY:` comments on all unsafe blocks

## Workspace Crates

All crates use `signet-` prefix. Features exist in:
- `signet-blobber`: `test-utils`
- `signet-node-config`: `test_utils`

Other crates (`signet-node`, `signet-node-types`, `signet-rpc`, `signet-db`, `signet-block-processor`, `signet-genesis`, `signet-node-tests`) have no feature flags — lint with `--all-features` only.
6 changes: 4 additions & 2 deletions crates/blobber/src/shim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,10 @@ impl From<RethRecovered> for RecoveredBlockShim {
}

impl HasTxns for RecoveredBlockShim {
fn transactions(&self) -> &[signet_types::primitives::TransactionSigned] {
&self.block.sealed_block().body().transactions
fn transactions(
&self,
) -> impl ExactSizeIterator<Item = &signet_types::primitives::TransactionSigned> {
self.block.sealed_block().body().transactions.iter()
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/db/src/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,6 @@ impl DataCompat<signet_types::primitives::SealedHeader> for reth::primitives::Se

impl DataCompat<reth::primitives::SealedHeader> for signet_types::primitives::SealedHeader {
fn convert(self) -> reth::primitives::SealedHeader {
reth::primitives::SealedHeader::new_unhashed(self.header().to_owned())
reth::primitives::SealedHeader::new_unhashed(self.clone_inner())
}
}
13 changes: 4 additions & 9 deletions crates/db/src/journal/trait.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use crate::RuWriter;
use alloy::consensus::{BlockHeader, Header};
use alloy::consensus::BlockHeader;
use reth::{providers::ProviderResult, revm::db::BundleState};
use signet_evm::{BlockResult, ExecutionOutcome};
use signet_journal::HostJournal;
use signet_types::primitives::{RecoveredBlock, SealedBlock, SealedHeader, TransactionSigned};
use signet_types::primitives::{SealedBlock, SealedHeader};

/// A database that can be updated with journals.
pub trait JournalDb: RuWriter {
Expand Down Expand Up @@ -31,13 +31,8 @@ pub trait JournalDb: RuWriter {
let bundle_state: BundleState = bsi.into();
let execution_outcome = ExecutionOutcome::new(bundle_state, vec![], header.number());

let block: SealedBlock<TransactionSigned, Header> =
SealedBlock { header: SealedHeader::new(header), body: Default::default() };
let block_result = BlockResult {
sealed_block: RecoveredBlock::new(block, vec![]),
execution_outcome,
host_height,
};
let block = SealedBlock::new(SealedHeader::new(header), vec![]);
let block_result = BlockResult { sealed_block: block, execution_outcome, host_height };

self.append_host_block(
None,
Expand Down
14 changes: 7 additions & 7 deletions crates/db/src/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,8 @@ where
// Put journal hash into the DB
self.tx_ref().put::<crate::JournalHashes>(block_number, journal_hash)?;

let block_hash = block.block.header.hash();
let block_header = block.block.header.header();
let block_hash = block.header.seal();
let block_header = block.header.inner();

self.static_file_provider()
.get_writer(block_number, StaticFileSegment::Headers)?
Expand All @@ -179,14 +179,14 @@ where
.map(|(n, _)| n + 1)
.unwrap_or_default();
let first_tx_num = next_tx_num;
let tx_count = block.block.body.transactions.len() as u64;
let tx_count = block.transactions.len() as u64;

for (sender, transaction) in block.senders.iter().zip(block.block.body.transactions()) {
for (sender, transaction) in block.senders().zip(block.transactions()) {
let hash = *transaction.hash();
debug_assert_ne!(hash, B256::ZERO, "transaction hash is zero");

if self.prune_modes_ref().sender_recovery.as_ref().is_none_or(|m| !m.is_full()) {
self.tx_ref().put::<tables::TransactionSenders>(next_tx_num, *sender)?;
self.tx_ref().put::<tables::TransactionSenders>(next_tx_num, sender)?;
}

if self.prune_modes_ref().transaction_lookup.is_none_or(|m| !m.is_full()) {
Expand Down Expand Up @@ -231,7 +231,7 @@ where
// Increment block on static file header
tx_writer.increment_block(block_number)?;

let tx_count = block.block.body.transactions.len() as u64;
let tx_count = block.transactions.len() as u64;
let block_indices = StoredBlockBodyIndices { first_tx_num: next_tx_num, tx_count };

// insert block meta
Expand All @@ -243,7 +243,7 @@ where
}

// Write transactions
for transaction in block.block.body.transactions() {
for transaction in block.transactions() {
tx_writer.append_transaction(next_tx_num, transaction)?;

// Increment transaction id for each transaction
Expand Down
51 changes: 21 additions & 30 deletions crates/db/tests/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
mod test_common;

use alloy::{
consensus::{BlockBody, BlockHeader, Signed, TxEip1559, TxEnvelope},
consensus::{BlockHeader, Signed, TxEip1559, TxEnvelope},
primitives::{Address, B256, U256},
signers::Signature,
};
use reth::providers::{BlockNumReader, BlockReader};
use signet_constants::test_utils::{DEPLOY_HEIGHT, RU_CHAIN_ID};
use signet_db::RuWriter;
use signet_types::primitives::{RecoveredBlock, SealedBlock, SealedHeader, TransactionSigned};
use signet_types::primitives::{SealedBlock, SealedHeader, TransactionSigned};
use signet_zenith::Zenith;

#[test]
Expand All @@ -35,25 +35,19 @@ fn test_insert_signet_block() {
blockDataHash: B256::repeat_byte(0x22),
});

let block = RecoveredBlock {
block: SealedBlock {
header: SealedHeader::new(alloy::consensus::Header::default()),
body: BlockBody {
transactions: std::iter::repeat_n(
TxEnvelope::Eip1559(Signed::new_unhashed(
TxEip1559::default(),
Signature::test_signature(),
))
.into(),
10,
)
.collect(),
ommers: vec![],
withdrawals: None,
},
},
senders: std::iter::repeat_n(Address::repeat_byte(0x33), 10).collect(),
};
let transactions: Vec<TransactionSigned> = std::iter::repeat_n(
TxEnvelope::Eip1559(Signed::new_unhashed(
TxEip1559::default(),
Signature::test_signature(),
))
.into(),
10,
)
.collect();
let senders: Vec<Address> = std::iter::repeat_n(Address::repeat_byte(0x33), 10).collect();
let sealed =
SealedBlock::new(SealedHeader::new(alloy::consensus::Header::default()), transactions);
let block = sealed.recover_unchecked(senders);

writer.insert_signet_block(header, &block, journal_hash).unwrap();
writer.commit().unwrap();
Expand All @@ -74,8 +68,8 @@ fn test_insert_signet_block() {
.first()
.cloned()
.unwrap();
assert_eq!(loaded_block.header(), block.block.header.header());
assert_eq!(loaded_block.body().transactions.len(), block.block.body.transactions.len());
assert_eq!(loaded_block.header(), block.header.inner());
assert_eq!(loaded_block.body().transactions.len(), block.transactions.len());

// Check that the ZenithHeader can be loaded back
let loaded_header = reader.get_signet_header(block.number()).unwrap();
Expand Down Expand Up @@ -111,13 +105,10 @@ fn test_transaction_hash_indexing() {
let expected_hashes: Vec<B256> =
transactions.iter().map(|tx: &TransactionSigned| *tx.hash()).collect();

let block = RecoveredBlock {
block: SealedBlock {
header: SealedHeader::new(alloy::consensus::Header::default()),
body: BlockBody { transactions, ommers: vec![], withdrawals: None },
},
senders: std::iter::repeat_n(Address::repeat_byte(0x33), 5).collect(),
};
let senders: Vec<Address> = std::iter::repeat_n(Address::repeat_byte(0x33), 5).collect();
let sealed =
SealedBlock::new(SealedHeader::new(alloy::consensus::Header::default()), transactions);
let block = sealed.recover_unchecked(senders);

writer.insert_signet_block(header, &block, journal_hash).unwrap();
writer.commit().unwrap();
Expand Down
26 changes: 22 additions & 4 deletions crates/node-tests/src/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,14 @@ impl ToRethPrimitive for SealedBlock {
type RethPrimitive = reth::primitives::SealedBlock<reth::primitives::Block>;

fn to_reth(self) -> Self::RethPrimitive {
let (hash, header) = self.header.split();
let (header, hash) = self.header.into_parts();
let body = alloy::consensus::BlockBody {
transactions: self.transactions,
ommers: vec![],
withdrawals: None,
};
reth::primitives::SealedBlock::new_unchecked(
reth::primitives::Block::new(header, self.body),
reth::primitives::Block::new(header, body),
hash,
)
}
Expand All @@ -58,8 +63,21 @@ impl ToRethPrimitive for RecoveredBlock {
type RethPrimitive = reth::primitives::RecoveredBlock<reth::primitives::Block>;

fn to_reth(self) -> Self::RethPrimitive {
let hash = self.block.header.hash();
reth::primitives::RecoveredBlock::new(self.block.to_reth().into_block(), self.senders, hash)
let (header, hash) = self.header.into_parts();
let (senders, transactions): (Vec<_>, Vec<_>) = self
.transactions
.into_iter()
.map(|r| {
let (tx, sender) = r.into_parts();
(sender, tx)
})
.unzip();
let body = alloy::consensus::BlockBody { transactions, ommers: vec![], withdrawals: None };
reth::primitives::RecoveredBlock::new(
reth::primitives::Block::new(header, body),
senders,
hash,
)
}
}

Expand Down