The Blockchain Example
1) Protocol Design
Write protocol first, then implementation. A mini spec avoids accidental complexity.
Messages
Tx { id, from, sig, payload, protocol_version }Block { header, txs, protocol_version }GetBlock { hash, protocol_version }BlockResponse { block, protocol_version }Status { tip_hash, height, protocol_version }
Transport decisions
For P2P, use libp2p:
- Gossip pubsub for
new_txandnew_blocktopics. request_responsefor block sync (GetBlock).
References:
- Pubsub: https://libp2p.io/guides/pubsub/
- Request/Response: https://docs.rs/libp2p/latest/libp2p/request_response/index.html
This is also aligned with real Rust blockchain stacks (for example Substrate networking on libp2p): https://docs.rs/sc-network.
Versioning and compatibility
Keep compatibility explicit from day one:
- Add
protocol_versionin messages. - Version topic names (
tx/v1,blocks/v1). - Rollouts: publish
v1andv2in parallel, deprecate old topics after an agreed window.
Deliverable: protocol.rs
#![allow(unused)]
fn main() {
#[derive(Debug, Clone)]
pub enum Message {
Tx(Tx),
Block(Block),
GetBlock(GetBlock),
BlockResponse(BlockResponse),
Status(Status),
}
#[derive(Debug, Clone)]
pub struct Tx {
pub id: [u8; 32],
pub from: [u8; 20],
pub sig: Vec<u8>,
pub payload: Vec<u8>,
pub protocol_version: u16,
}
#[derive(Debug, Clone)]
pub struct Block {
pub header: BlockHeader,
pub txs: Vec<Tx>,
pub protocol_version: u16,
}
#[derive(Debug, Clone)]
pub struct BlockHeader {
pub parent_hash: [u8; 32],
pub height: u64,
pub state_root: [u8; 32],
pub tx_root: [u8; 32],
pub timestamp_ms: u64,
}
#[derive(Debug, Clone)]
pub struct GetBlock {
pub hash: [u8; 32],
pub protocol_version: u16,
}
#[derive(Debug, Clone)]
pub struct BlockResponse {
pub block: Option<Block>,
pub protocol_version: u16,
}
#[derive(Debug, Clone)]
pub struct Status {
pub tip_hash: [u8; 32],
pub height: u64,
pub protocol_version: u16,
}
}