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
3 changes: 2 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,8 @@ actual_slot = finalized_slot + 1 + relative_index
### Protocols
- **Transport**: QUIC over UDP (TLS 1.3)
- **Gossipsub**: Blocks + Attestations (snappy raw compression)
- Topic: `/leanconsensus/{network}/{block|attestation}/ssz_snappy`
- Topic: `/leanconsensus/{fork_digest}/{block|aggregation|attestation_N}/ssz_snappy`
- `fork_digest` is a 4-byte hex string (no `0x` prefix); currently the dummy `12345678` agreed across clients
- Mesh size: 8 (6-12 bounds), heartbeat: 700ms
- **Req/Resp**: Status, BlocksByRoot (snappy frame compression + varint length)

Expand Down
32 changes: 26 additions & 6 deletions crates/net/p2p/src/gossipsub/messages.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,40 @@
/// Fork digest embedded in every gossipsub topic string, as lowercase hex
/// without a `0x` prefix.
///
/// The [leanSpec](https://github.com/leanEthereum/leanSpec/pull/622)
/// currently mandates a dummy value shared across all clients; this will
/// eventually be derived from the fork version and genesis validators root.
// TODO: derive dynamically once the spec defines fork identification.
pub const FORK_DIGEST: &str = "12345678";

/// Topic kind for block gossip
pub const BLOCK_TOPIC_KIND: &str = "block";
/// Topic kind prefix for per-committee attestation subnets.
///
/// Full topic format: `/leanconsensus/{network}/attestation_{subnet_id}/ssz_snappy`
/// Full topic format: `/leanconsensus/{FORK_DIGEST}/attestation_{subnet_id}/ssz_snappy`
pub const ATTESTATION_SUBNET_TOPIC_PREFIX: &str = "attestation";
/// Topic kind for aggregated attestation gossip.
///
/// Full topic format: `/leanconsensus/{network}/aggregation/ssz_snappy`
/// Full topic format: `/leanconsensus/{FORK_DIGEST}/aggregation/ssz_snappy`
pub const AGGREGATION_TOPIC_KIND: &str = "aggregation";

// TODO: make this configurable (e.g., via GenesisConfig or CLI)
pub const NETWORK_NAME: &str = "devnet0";
/// Build the block gossipsub topic.
pub fn block_topic() -> libp2p::gossipsub::IdentTopic {
libp2p::gossipsub::IdentTopic::new(format!(
"/leanconsensus/{FORK_DIGEST}/{BLOCK_TOPIC_KIND}/ssz_snappy"
))
}

/// Build the aggregated-attestation gossipsub topic.
pub fn aggregation_topic() -> libp2p::gossipsub::IdentTopic {
libp2p::gossipsub::IdentTopic::new(format!(
"/leanconsensus/{FORK_DIGEST}/{AGGREGATION_TOPIC_KIND}/ssz_snappy"
))
}

/// Build an attestation subnet topic for the given subnet ID.
/// Build an attestation subnet gossipsub topic for the given subnet.
pub fn attestation_subnet_topic(subnet_id: u64) -> libp2p::gossipsub::IdentTopic {
libp2p::gossipsub::IdentTopic::new(format!(
"/leanconsensus/{NETWORK_NAME}/{ATTESTATION_SUBNET_TOPIC_PREFIX}_{subnet_id}/ssz_snappy"
"/leanconsensus/{FORK_DIGEST}/{ATTESTATION_SUBNET_TOPIC_PREFIX}_{subnet_id}/ssz_snappy"
))
}
4 changes: 1 addition & 3 deletions crates/net/p2p/src/gossipsub/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,4 @@ pub use encoding::decompress_message;
pub use handler::{
handle_gossipsub_message, publish_aggregated_attestation, publish_attestation, publish_block,
};
pub use messages::{
AGGREGATION_TOPIC_KIND, BLOCK_TOPIC_KIND, NETWORK_NAME, attestation_subnet_topic,
};
pub use messages::{aggregation_topic, attestation_subnet_topic, block_topic};
11 changes: 4 additions & 7 deletions crates/net/p2p/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ use tracing::{info, trace, warn};

use crate::{
gossipsub::{
AGGREGATION_TOPIC_KIND, BLOCK_TOPIC_KIND, NETWORK_NAME, attestation_subnet_topic,
publish_aggregated_attestation, publish_attestation, publish_block,
aggregation_topic, attestation_subnet_topic, block_topic, publish_aggregated_attestation,
publish_attestation, publish_block,
},
req_resp::{
BLOCKS_BY_ROOT_PROTOCOL_V1, Codec, MAX_COMPRESSED_PAYLOAD_SIZE, Request,
Expand Down Expand Up @@ -188,18 +188,15 @@ pub fn build_swarm(
.expect("failed to bind gossipsub listening address");

// Subscribe to block topic (all nodes)
let block_topic_str = format!("/leanconsensus/{NETWORK_NAME}/{BLOCK_TOPIC_KIND}/ssz_snappy");
let block_topic = libp2p::gossipsub::IdentTopic::new(block_topic_str);
let block_topic = block_topic();
swarm
.behaviour_mut()
.gossipsub
.subscribe(&block_topic)
.unwrap();

// Subscribe to aggregation topic (all validators)
let aggregation_topic_str =
format!("/leanconsensus/{NETWORK_NAME}/{AGGREGATION_TOPIC_KIND}/ssz_snappy");
let aggregation_topic = libp2p::gossipsub::IdentTopic::new(aggregation_topic_str);
let aggregation_topic = aggregation_topic();
swarm
.behaviour_mut()
.gossipsub
Expand Down
Loading