Documentation
¶
Index ¶
- Constants
- Variables
- func EncodeMailboxPayload(senderAddr, recipientAddr a2al.Address, recipientPub ed25519.PublicKey, ...) ([]byte, error)
- func FindNodeResponseWireSize(resp *BodyFindNodeResp) (int, error)
- func FindValueResponseWireSize(resp *BodyFindValueResp) (int, error)
- func FormatObservedUDP(ip net.IP, port uint16) ([]byte, error)
- func MarshalSignedMessage(hdr Header, body any, priv ed25519.PrivateKey) ([]byte, error)
- func MarshalSignedMessageKeyStore(hdr Header, body any, ks acrypto.KeyStore, addr a2al.Address) ([]byte, error)
- func MarshalTopicPayload(p TopicPayload) ([]byte, error)
- func ParseObservedUDP(b []byte) (host string, port uint16, ok bool)
- func RecordCategory(recType uint8) uint8
- func RecordIsNewer(a, b SignedRecord) bool
- func TopicNodeID(topic string) a2al.NodeID
- func VerifySignedRecord(sr SignedRecord, now time.Time) error
- type BodyFindNode
- type BodyFindNodeResp
- type BodyFindValue
- type BodyFindValueResp
- type BodyPing
- type BodyPong
- type BodyStore
- type BodyStoreResp
- type DecodedMessage
- type DiscoverFilter
- type EndpointPayload
- type EndpointRecord
- type Header
- type MailboxMessage
- type MailboxPayload
- type NodeInfo
- type SignedRecord
- func SignEndpointRecord(priv ed25519.PrivateKey, addr a2al.Address, ep EndpointPayload, ...) (SignedRecord, error)
- func SignEndpointRecordDelegated(opPriv ed25519.PrivateKey, delegationCBOR []byte, addr a2al.Address, ...) (SignedRecord, error)
- func SignRecord(priv ed25519.PrivateKey, addr a2al.Address, recType uint8, payload []byte, ...) (SignedRecord, error)
- func SignRecordDelegated(opPriv ed25519.PrivateKey, delegationCBOR []byte, addr a2al.Address, ...) (SignedRecord, error)
- type TopicEntry
- type TopicPayload
Constants ¶
const ( CategoryUnknown uint8 = 0 CategorySovereign uint8 = 1 // RecType 0x01–0x0F CategoryTopic uint8 = 2 // RecType 0x10–0x1F CategoryMailbox uint8 = 3 // RecType 0x80–0x8F )
DHT record categories (Phase 4 spec §2.1).
const ( RecTypeTopic uint8 = 0x10 RecTypeMailbox uint8 = 0x80 )
RecType constants beyond endpoint (Phase 4).
const ( // MaxMailboxPayloadCBOR is the spec §4.8 cap on SignedRecord.payload (MailboxPayload CBOR). MaxMailboxPayloadCBOR = 512 // DefaultMailboxTTL is the recommended mailbox record TTL in seconds (spec §4.8). DefaultMailboxTTL uint32 = 3600 )
const ( MailboxMsgConnectRequest uint8 = 0x01 MailboxMsgCandidates uint8 = 0x02 MailboxMsgText uint8 = 0x03 )
Mailbox message types (spec §4.3).
const ( MsgPing uint8 = 0x01 MsgPong uint8 = 0x02 MsgFindNode uint8 = 0x03 MsgFindNodeResp uint8 = 0x04 MsgFindValue uint8 = 0x05 MsgFindValueResp uint8 = 0x06 MsgStore uint8 = 0x07 MsgStoreResp uint8 = 0x08 )
Message type IDs (spec §7.4).
const ( // RecTypeEndpoint is the Phase 1 endpoint advertisement (spec §7.6). RecTypeEndpoint uint8 = 0x01 // MaxEndpointSignalURLLen caps EndpointPayload.Signal (WebSocket ICE signaling base URL). MaxEndpointSignalURLLen = 2048 // MaxTurnURLs caps EndpointPayload.Turns entry count (credential-free relay hints for DHT). MaxTurnURLs = 16 // MaxTurnURLEntryLen caps each turn:// string length in Turns. MaxTurnURLEntryLen = 512 )
const ( NATUnknown uint8 = iota NATFullCone NATRestricted NATPortRestricted NATSymmetric )
NAT types for EndpointPayload (spec §7.6).
const MaxTopicBriefRunes = 140
MaxTopicBriefRunes is spec §5.3 one-line description limit.
const MaxTopicPayloadCBOR = 512
MaxTopicPayloadCBOR is the spec §5.9 cap on SignedRecord.payload for RecType 0x10.
const ProtocolVersion uint8 = 1
ProtocolVersion is the wire protocol version (spec §7.3).
Variables ¶
var ( // ErrInvalidMessage is returned for malformed wire data or failed verification. ErrInvalidMessage = errors.New("a2al/protocol: invalid message") // ErrUnknownMsgType is returned when msg_type is not defined in Phase 1. ErrUnknownMsgType = errors.New("a2al/protocol: unknown msg_type") )
var ( // ErrInvalidRecord is returned when structure, signature, or address binding fails. ErrInvalidRecord = errors.New("a2al/protocol: invalid record") // ErrRecordExpired means now is past Timestamp+TTL (VerifySignedRecord). ErrRecordExpired = errors.New("a2al/protocol: record expired") )
Functions ¶
func EncodeMailboxPayload ¶
func EncodeMailboxPayload(senderAddr, recipientAddr a2al.Address, recipientPub ed25519.PublicKey, msgType uint8, body []byte) ([]byte, error)
EncodeMailboxPayload encrypts (msgType, body) and returns canonical CBOR MailboxPayload.
func FindNodeResponseWireSize ¶
func FindNodeResponseWireSize(resp *BodyFindNodeResp) (int, error)
FindNodeResponseWireSize returns the canonical CBOR size of a FIND_NODE_RESP body (UDP trim, spec §3.7).
func FindValueResponseWireSize ¶
func FindValueResponseWireSize(resp *BodyFindValueResp) (int, error)
FindValueResponseWireSize returns the canonical CBOR size of a FIND_VALUE_RESP body (UDP trim, spec §3.7).
func FormatObservedUDP ¶
FormatObservedUDP encodes IP:port to the same wire form as BodyPong.observed_addr.
func MarshalSignedMessage ¶
MarshalSignedMessage canonical-encodes header and body, signs, and returns the outer CBOR bytes.
func MarshalSignedMessageKeyStore ¶
func MarshalSignedMessageKeyStore(hdr Header, body any, ks acrypto.KeyStore, addr a2al.Address) ([]byte, error)
MarshalSignedMessageKeyStore signs with KeyStore (spec: same preimage as MarshalSignedMessage).
func MarshalTopicPayload ¶
func MarshalTopicPayload(p TopicPayload) ([]byte, error)
MarshalTopicPayload canonical-encodes p and enforces size / brief limits. If p.Version == 0, it is treated as 1 for encoding.
func ParseObservedUDP ¶
ParseObservedUDP decodes wire observed_addr (4+2 IPv4 or 16+2 IPv6, big-endian port).
func RecordCategory ¶
RecordCategory maps RecType to a storage/query policy bucket. Reserved ranges (0x20–0x7F, 0x90–0xFF) return CategoryUnknown and are stored like sovereign (key must be NodeID(Address)) for forward compatibility.
func RecordIsNewer ¶
func RecordIsNewer(a, b SignedRecord) bool
RecordIsNewer reports whether a should replace b (spec: larger seq wins; tie-break by timestamp).
func TopicNodeID ¶
TopicNodeID returns SHA-256("topic:" || topicUTF8) as the DHT key for Topic rendezvous (Phase 4 / v2 §10.3). The formula is immutable on the wire.
func VerifySignedRecord ¶
func VerifySignedRecord(sr SignedRecord, now time.Time) error
VerifySignedRecord checks cryptographic integrity: signature validity, endpoint payload shape, and expiry. It does NOT enforce pubkey↔address authority (whether the signing key is allowed to publish for the given Address). Authority is a deployment policy; inject it via dht.Config.RecordAuth at the storage layer.
Types ¶
type BodyFindNode ¶
type BodyFindNode struct {
Target []byte `cbor:"1,keyasint"` // 32 NodeID
}
type BodyFindNodeResp ¶
type BodyFindValue ¶
type BodyFindValueResp ¶
type BodyFindValueResp struct {
Nodes []NodeInfo `cbor:"1,keyasint"`
Record *SignedRecord `cbor:"2,keyasint,omitempty"`
ObservedAddr []byte `cbor:"3,keyasint"`
Records []SignedRecord `cbor:"4,keyasint,omitempty"`
}
type BodyStore ¶
type BodyStore struct {
Record SignedRecord `cbor:"1,keyasint"`
Key []byte `cbor:"2,keyasint,omitempty"` // 32-byte DHT key; omit = NodeID(Address)
}
type BodyStoreResp ¶
type BodyStoreResp struct {
Stored bool `cbor:"1,keyasint"`
}
type DecodedMessage ¶
type DecodedMessage struct {
Header Header
SenderPubkey ed25519.PublicKey
SenderAddr a2al.Address
Body any
}
DecodedMessage is a verified, parsed wire message.
func VerifyAndDecode ¶
func VerifyAndDecode(raw []byte) (*DecodedMessage, error)
VerifyAndDecode parses the outer message, re-canonicalizes header/body, verifies Ed25519, checks sender_pubkey matches body.address for PING and PONG (spec §Step 3).
type DiscoverFilter ¶
type DiscoverFilter struct {
Protocols []string `json:"protocols,omitempty"`
Tags []string `json:"tags,omitempty"`
}
DiscoverFilter is optional client-side filtering (spec §5.5).
type EndpointPayload ¶
type EndpointPayload struct {
Endpoints []string `cbor:"1,keyasint"`
NatType uint8 `cbor:"2,keyasint"`
// Signal is an optional WebSocket base URL for ICE trickle signaling (no query; room is appended by peers).
Signal string `cbor:"3,keyasint,omitempty"`
// Turns lists optional turn:// URLs without credentials (public relay hints).
Turns []string `cbor:"4,keyasint,omitempty"`
}
EndpointPayload is the CBOR inside SignedRecord.payload for rec_type=0x01 (spec §7.6).
type EndpointRecord ¶
type EndpointRecord struct {
Address a2al.Address
Endpoints []string
NatType uint8
Signal string
Turns []string
Timestamp uint64
Seq uint64
TTL uint32
}
EndpointRecord is the decoded logical view (spec Step 4); no signature material.
func ParseEndpointRecord ¶
func ParseEndpointRecord(sr SignedRecord) (EndpointRecord, error)
ParseEndpointRecord decodes an endpoint record after verification.
type Header ¶
type Header struct {
Version uint8 `cbor:"1,keyasint"`
Features uint16 `cbor:"2,keyasint"`
MsgType uint8 `cbor:"3,keyasint"`
TxID []byte `cbor:"4,keyasint"`
}
Header is the CBOR map in field 1 of the outer message (spec §7.3).
type MailboxMessage ¶
type MailboxMessage struct {
Sender a2al.Address
MsgType uint8
Body []byte
// Seq is copied from the outer SignedRecord.Seq; it is monotonically
// increasing per sender and serves as a unique record identifier.
Seq uint64
}
MailboxMessage is one decrypted mailbox entry for the application (spec §4.6).
func OpenMailboxRecord ¶
func OpenMailboxRecord(recipientPriv ed25519.PrivateKey, recipientAddr a2al.Address, sr SignedRecord) (MailboxMessage, error)
OpenMailboxRecord decrypts a verified mailbox SignedRecord for recipientAddr.
type MailboxPayload ¶
type MailboxPayload struct {
Recipient []byte `cbor:"1,keyasint"`
SenderAddr []byte `cbor:"2,keyasint"`
EphemeralPK []byte `cbor:"3,keyasint"`
Ciphertext []byte `cbor:"4,keyasint"`
Nonce []byte `cbor:"5,keyasint"`
}
MailboxPayload is the CBOR inside SignedRecord.payload for rec_type=0x80 (spec §4.1).
type NodeInfo ¶
type NodeInfo struct {
Address []byte `cbor:"1,keyasint"` // 21 bytes
NodeID []byte `cbor:"2,keyasint"` // 32 bytes
IP []byte `cbor:"3,keyasint"` // 4 or 16 bytes
Port uint16 `cbor:"4,keyasint"`
}
NodeInfo is the DHT routing contact shape (spec §7.6).
type SignedRecord ¶
type SignedRecord struct {
Address []byte `cbor:"1,keyasint"`
RecType uint8 `cbor:"2,keyasint"`
Payload []byte `cbor:"3,keyasint"`
Seq uint64 `cbor:"4,keyasint"`
Timestamp uint64 `cbor:"5,keyasint"`
TTL uint32 `cbor:"6,keyasint"`
Pubkey []byte `cbor:"7,keyasint"`
Signature []byte `cbor:"8,keyasint"`
Delegation []byte `cbor:"9,keyasint,omitempty"`
}
SignedRecord is the on-wire record container (spec §7.6). Record signing uses prefix "a2al-rec\0" over CBOR of fields 1–6 (implemented in record.go, Step 4). Field 9 (Delegation) is optional and carries a CBOR-encoded DelegationProof when the signing key (Pubkey) is an operational key publishing on behalf of a master-derived Address.
func SignEndpointRecord ¶
func SignEndpointRecord(priv ed25519.PrivateKey, addr a2al.Address, ep EndpointPayload, seq, timestamp uint64, ttl uint32) (SignedRecord, error)
SignEndpointRecord builds a SignedRecord for a self-signed endpoint advertisement. The signing key must derive the same Address as addr (Phase 1/2 path).
func SignEndpointRecordDelegated ¶
func SignEndpointRecordDelegated(opPriv ed25519.PrivateKey, delegationCBOR []byte, addr a2al.Address, ep EndpointPayload, seq, timestamp uint64, ttl uint32) (SignedRecord, error)
SignEndpointRecordDelegated builds a SignedRecord where an operational key signs on behalf of a master-derived AID (Phase 3 delegation path). delegationCBOR is embedded verbatim in the record and will be verified by receivers via the RecordAuth policy injected into the DHT store. Callers must ensure delegationCBOR is a valid DelegationProof for addr authorized to opPriv.
func SignRecord ¶
func SignRecord(priv ed25519.PrivateKey, addr a2al.Address, recType uint8, payload []byte, seq, timestamp uint64, ttl uint32) (SignedRecord, error)
SignRecord builds a signed record for RecType sovereign custom (0x02–0x0F), topic (0x10–0x1F), or mailbox (0x80–0x8F). payload must be CBOR-encoded bytes.
func SignRecordDelegated ¶
func SignRecordDelegated(opPriv ed25519.PrivateKey, delegationCBOR []byte, addr a2al.Address, recType uint8, payload []byte, seq, timestamp uint64, ttl uint32) (SignedRecord, error)
SignRecordDelegated is SignRecord with an operational key and DelegationProof.
type TopicEntry ¶
type TopicEntry struct {
Address a2al.Address
Seq uint64
Timestamp uint64
TTL uint32
Version uint8
Topic string
Name string
Protocols []string
Tags []string
Brief string
Meta map[string]any
}
TopicEntry is the decoded logical view for discovery (spec §5.7), like EndpointRecord.
func FilterTopicEntries ¶
func FilterTopicEntries(in []TopicEntry, f *DiscoverFilter) []TopicEntry
FilterTopicEntries applies protocol/tag filters (AND: all filter tags must appear in entry.Tags; at least one protocol match if filter protocols non-empty).
func TopicEntryFromSignedRecord ¶
func TopicEntryFromSignedRecord(sr SignedRecord) (TopicEntry, error)
TopicEntryFromSignedRecord builds TopicEntry after caller verifies signature / expiry.
type TopicPayload ¶
type TopicPayload struct {
Version uint8 `cbor:"1,keyasint"`
Topic string `cbor:"2,keyasint"`
Name string `cbor:"3,keyasint"`
Protocols []string `cbor:"4,keyasint"`
Tags []string `cbor:"5,keyasint"`
Brief string `cbor:"6,keyasint"`
Meta map[string]any `cbor:"7,keyasint,omitempty"`
}
TopicPayload is the CBOR inside SignedRecord.payload for rec_type=0x10 (spec §5.3).
func ParseTopicRecord ¶
func ParseTopicRecord(sr SignedRecord) (TopicPayload, error)
ParseTopicRecord decodes a topic SignedRecord payload.