1 Protocol Messages
Claude edited this page 2026-02-19 23:29:30 +00:00

Protocol Messages

Message types, wire format, and payload handling for the go-p2p protocol.

Message Structure

Every message in the protocol is a JSON-encoded Message struct transported over WebSocket.

type Message struct {
    ID        string          `json:"id"`        // UUID v4, unique per message
    Type      MessageType     `json:"type"`      // Determines how the payload is interpreted
    Sender    string          `json:"sender"`    // Node ID of the originator
    Payload   json.RawMessage `json:"payload"`   // Type-specific JSON payload
    Timestamp time.Time       `json:"timestamp"` // When the message was created
}

Working with Payloads

Messages carry arbitrary JSON payloads. Use the helper methods to serialise and deserialise them.

// Setting a payload
msg := &node.Message{
    Type:   node.TypeStartMiner,
    Sender: identity.ID,
}
msg.SetPayload(MinerConfig{
    Algorithm: "randomx",
    Threads:   4,
})

// Parsing a payload
var config MinerConfig
err := msg.ParsePayload(&config)

Message Types

Connection Lifecycle

Type Direction Purpose
handshake A -> B Initiates connection with public key
handshake_ack B -> A Acknowledges with own public key
ping A -> B Keepalive probe
pong B -> A Keepalive response
disconnect Either Graceful connection teardown
const (
    TypeHandshake    MessageType = "handshake"
    TypeHandshakeAck MessageType = "handshake_ack"
    TypePing         MessageType = "ping"
    TypePong         MessageType = "pong"
    TypeDisconnect   MessageType = "disconnect"
)

Operations

Type Direction Purpose
get_stats Controller -> Worker Request node statistics
stats Worker -> Controller Node statistics response
start_miner Controller -> Worker Start mining workload
stop_miner Controller -> Worker Stop mining workload
miner_ack Worker -> Controller Acknowledge miner state change
const (
    TypeGetStats   MessageType = "get_stats"
    TypeStats      MessageType = "stats"
    TypeStartMiner MessageType = "start_miner"
    TypeStopMiner  MessageType = "stop_miner"
    TypeMinerAck   MessageType = "miner_ack"
)

Deployment

Type Direction Purpose
deploy Controller -> Worker Deploy a workload or configuration
deploy_ack Worker -> Controller Acknowledge successful deployment
const (
    TypeDeploy    MessageType = "deploy"
    TypeDeployAck MessageType = "deploy_ack"
)

Logging

Type Direction Purpose
get_logs Controller -> Worker Request log output
logs Worker -> Controller Log entries response
const (
    TypeGetLogs MessageType = "get_logs"
    TypeLogs    MessageType = "logs"
)

Errors

Type Direction Purpose
error Either Protocol or application error
const TypeError MessageType = "error"

ProtocolError

Structured error type carried in error message payloads.

type ProtocolError struct {
    Code    int    `json:"code"`    // Numeric error code
    Message string `json:"message"` // Human-readable description
}

Example usage:

msg := &node.Message{
    Type:   node.TypeError,
    Sender: identity.ID,
}
msg.SetPayload(node.ProtocolError{
    Code:    401,
    Message: "authentication failed: invalid challenge response",
})

ResponseHandler

The ResponseHandler provides helpers for validating and parsing responses in request-response flows.

// ValidateResponse checks the message type matches the expected response type
err := node.ValidateResponse(msg, node.TypeStats)

// ParseResponse validates and extracts the payload in one step
var stats NodeStats
err := node.ParseResponse(msg, node.TypeStats, &stats)

Example: Full Message Exchange

import "forge.lthn.ai/core/go-p2p/node"

// Controller sends a start_miner command
cmd := &node.Message{
    ID:        uuid.New().String(),
    Type:      node.TypeStartMiner,
    Sender:    controller.ID,
    Timestamp: time.Now(),
}
cmd.SetPayload(MinerConfig{
    Algorithm: "randomx",
    Threads:   4,
    Pool:      "pool.lthn.ai:3333",
})

// Worker receives, processes, and acknowledges
ack := &node.Message{
    ID:        uuid.New().String(),
    Type:      node.TypeMinerAck,
    Sender:    worker.ID,
    Timestamp: time.Now(),
}
ack.SetPayload(MinerStatus{
    Running:   true,
    HashRate:  1250.5,
    Algorithm: "randomx",
})

See Also