libp2p-hs-0.1.0.0: Haskell implementation of the libp2p networking stack
Safe HaskellNone
LanguageGHC2021

LibP2P.Switch.CertifiedRecords

Description

Certified peer records: the signed routing records a node has accepted, and the freshness rule that governs replacing them (specsRFC0003-routing-records.md).

RFC 0003, Peer Store APIs:

a receiving peer MUST keep track of the latest @seq@ value received
for each peer and reject incoming records unless they contain a
greater @seq@ value than the last received.

Verifying an envelope's signature says only that the peer signed it at some point, not that it is current. Without the sequence check a correctly signed but older record replayed at a peer rolls its certified addresses back to stale state, which is exactly what signing them was supposed to prevent.

The state lives here rather than in IdentifyInfo because a record does not only arrive over Identify: Identify Push and GossipSub peer exchange carry the same envelopes and must be held to the same rule, and none of them is an Identify message.

Synopsis

Types

data CertifiedRecord Source #

A signed peer record this node has verified and accepted, kept alongside the envelope it came in so it can be forwarded verbatim (a record is only self-certifying while its signature travels with it).

Constructors

CertifiedRecord 

Fields

Verification

verifyPeerRecord :: PeerId -> ByteString -> Either String CertifiedRecord Source #

Verify an envelope against an authenticated peer id.

The envelope must open (valid signature, expected domain and payload type) and its signing key must derive the peer id the security handshake authenticated — otherwise the sender is making a claim about an identity it does not hold.

This says nothing about whether the record is current; that is consumeCertifiedRecord.

Freshness

consumeCertifiedRecord :: TVar (Map PeerId CertifiedRecord) -> PeerId -> CertifiedRecord -> STM Bool Source #

Apply the RFC 0003 freshness rule and, when the record wins, retain it. Returns whether the record was accepted.

A first record for a peer is always accepted. After that only a strictly greater seq is, so an equal or lower one leaves the retained record untouched — replaying a record we already hold changes nothing.

Note that go-libp2p is more permissive here: pstoremem rejects only lastState.Seq > rec.Seq, accepting an equal sequence number as a TTL refresh for its address book. This implementation has no address TTL for such a refresh to renew, so it follows the RFC's wording instead.

lookupCertifiedRecord :: TVar (Map PeerId CertifiedRecord) -> PeerId -> STM (Maybe CertifiedRecord) Source #

The record currently retained for a peer, if any.