Module IPC Protocol
Overview
The Module IPC (Inter-Process Communication) protocol enables secure communication between process-isolated modules and the base node. Modules run in separate processes and communicate via Unix domain sockets using a length-delimited binary message protocol.
Architecture
┌─────────────────────────────────────┐
│ blvm-node Process │
│ ┌───────────────────────────────┐ │
│ │ Module IPC Server │ │
│ │ (Unix Domain Socket) │ │
│ └───────────────────────────────┘ │
└─────────────────────────────────────┘
│ IPC Protocol
│ (Unix Domain Socket)
│
┌─────────────┴─────────────────────┐
│ Module Process (Isolated) │
│ ┌───────────────────────────────┐ │
│ │ Module IPC Client │ │
│ │ (Unix Domain Socket) │ │
│ └───────────────────────────────┘ │
└─────────────────────────────────────┘
Protocol Format
Message Encoding
Messages use length-delimited binary encoding:
[4-byte length][message payload]
- Length: 4-byte little-endian integer (message size)
- Payload: Binary-encoded message (bincode serialization)
Code: mod.rs
Message Types
The protocol uses length-delimited ModuleMessage variants:
- Request — module → node (NodeAPI calls, handshake,
RegisterModuleApi, …) - Response — node → module
- Event — node → module (subscribed notifications)
- Log — module → node (forwarded to node logging)
- Invocation — node → module (CLI, RPC, or
ModuleApidispatch) - InvocationResult — module → node (correlated reply)
Code: protocol.rs (ModuleMessage)
Message Structure
Request Message
#![allow(unused)] fn main() { pub struct RequestMessage { pub correlation_id: CorrelationId, pub request_type: MessageType, pub payload: RequestPayload, } }
Request types (representative):
Reads and subscriptions include GetBlock, GetBlockHeader, GetTransaction, GetChainTip, GetBlockHeight, GetUTXO, SubscribeEvents, GetMempoolTransactions, GetNetworkStats, GetNetworkPeers, GetChainInfo, and many others (mining, storage, RPC, timers, …).
P2P serve policy & sync (module → node):
MessageType | Role |
|---|---|
MergeBlockServeDenylist | Add block hashes that must not receive full block on getdata (notfound instead). |
GetBlockServeDenylistSnapshot | Bounded snapshot of the block denylist. |
ClearBlockServeDenylist / ReplaceBlockServeDenylist | Clear or replace the full set. |
MergeTxServeDenylist | Same pattern for full tx on getdata. |
GetTxServeDenylistSnapshot | Bounded snapshot of the tx denylist. |
ClearTxServeDenylist / ReplaceTxServeDenylist | Clear or replace the tx set. |
GetSyncStatus | Sync coordinator status (SyncStatus). |
BanPeer | Ban peer by address; optional duration. |
SetBlockServeMaintenanceMode | Refuse all full-block getdata answers when enabled. |
These affect relay/serving only, not consensus validation. See NodeAPI for the Rust surface.
Code: protocol.rs
Response Message
#![allow(unused)] fn main() { pub struct ResponseMessage { pub correlation_id: CorrelationId, pub payload: ResponsePayload, } }
Response payload variants carry typed data (blocks, templates, snapshots, booleans, errors, etc.); denylist merges return dedicated merged/snapshot payloads where applicable.
Code: protocol.rs
Event Message
#![allow(unused)] fn main() { pub struct EventMessage { pub event_type: EventType, pub payload: EventPayload, } }
Event types: The node defines many EventType values (chain, mempool, network, payments, mining, mesh, sync, modules, governance, maintenance, …). Modules subscribe to a subset via SubscribeEvents. See the EventType enum in traits.rs for the authoritative list — do not assume a fixed count in docs.
Code: protocol.rs, traits.rs
Log Message
#![allow(unused)] fn main() { pub struct LogMessage { pub level: LogLevel, pub message: String, pub module_id: String, } }
Log Levels: Error, Warn, Info, Debug, Trace
Code: protocol.rs
Communication Flow
Request-Response Pattern
- Module sends Request: Module sends request message with correlation ID
- Node processes Request: Node processes request and generates response
- Node sends Response: Node sends response with matching correlation ID
- Module receives Response: Module matches response to request using correlation ID
Code: server.rs
Invocation pattern (CLI, RPC, ModuleAPI)
The node sends Invocation messages to a connected module subprocess:
InvocationType | Use |
|---|---|
Cli | runmodulecli / module CLI dispatch |
Rpc | Module-registered RPC methods |
ModuleApi | Inter-module call_module forwarded to the subprocess handler |
The module replies with InvocationResult (same correlation_id). For ModuleApi, the payload is opaque bytes (InvocationResultPayload::ModuleApi).
Subprocess ModuleAPI registration
Spawned modules cannot pass Arc<dyn ModuleAPI> into the node process. Instead:
- Module sends
RegisterModuleApiwith method names and API version. - Node installs
IpcForwardingModuleAPIin the module registry. - Other callers use
call_module(or node RPC such asmeshsendpacket) → node sendsInvocationType::ModuleApito the subprocess. - On disconnect, the node unregisters the proxy.
Cross-task invocations use ModuleIpcHandle so callers do not lock the server accept loop.
Code: server.rs, ipc_proxy.rs, runner.rs
Event Subscription Pattern
- Module subscribes: Module sends
SubscribeEventsrequest with event types - Node confirms: Node sends subscription confirmation
- Node publishes Events: Node sends event messages as they occur
- Module receives Events: Module processes events asynchronously
Code: server.rs
Connection Management
Handshake
On connection, the module sends a handshake as the first Request:
#![allow(unused)] fn main() { RequestPayload::Handshake { module_id, module_name, version, } }
The node replies with HandshakeAck (node version). Modules without a handshake receive a fallback connection id (legacy path).
Code: server.rs
Connection Lifecycle
- Connect: Module connects to Unix domain socket
- Handshake: Module sends handshake, node validates
- Active: Connection active, ready for requests/events
- Disconnect: Connection closed (graceful or error)
Code: server.rs
Security
Process Isolation
- Modules run in separate processes with isolated memory
- No shared memory between node and modules
- Module crashes don't affect the base node
Code: spawner.rs
Permission System
Modules request capabilities that are validated before API access:
ReadBlockchain- Read-only blockchain accessReadUTXO- Query UTXO set (read-only)ReadChainState- Query chain state (height, tip)SubscribeEvents- Subscribe to node eventsSendTransactions- Submit transactions to mempool
Code: permissions.rs
Sandboxing
Modules run in sandboxed environments with:
- Resource limits (CPU, memory, file descriptors)
- Filesystem restrictions (module data dir)
- Network: modules do not open arbitrary sockets; P2P and mesh sends go through NodeAPI with the
network_accesscapability - Permission-based API access
Code: mod.rs, permissions.rs
Error Handling
Error Types
#![allow(unused)] fn main() { pub enum ModuleError { ConnectionError(String), ProtocolError(String), PermissionDenied(String), ResourceExhausted(String), Timeout(String), } }
Code: traits.rs
Error Recovery
- Connection Errors: Automatic reconnection with exponential backoff
- Protocol Errors: Clear error messages, connection termination
- Permission Errors: Detailed error messages, request rejection
- Timeout Errors: Request timeout, connection remains active
Code: client.rs
Performance
Message Serialization
- Format: bincode (binary encoding)
- Size: Compact binary representation
- Speed: Fast serialization/deserialization
Code: protocol.rs
Connection Pooling
- Persistent Connections: Connections remain open for multiple requests
- Concurrent Requests: Multiple requests can be in-flight simultaneously
- Correlation IDs: Match responses to requests asynchronously
Code: client.rs
Implementation Details
IPC Server
The node-side IPC server:
- Listens on Unix domain socket
- Accepts module connections
- Routes requests to NodeAPI implementation
- Publishes events to subscribed modules
Code: server.rs
IPC Client
The module-side IPC client:
- Connects to Unix domain socket
- Sends requests and receives responses
- Subscribes to events
- Handles connection errors
Code: client.rs
See Also
- Module System - Module system architecture
- Module Development - Building modules
- Modules Overview - Available modules