ipns

package
v0.38.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 9, 2026 License: Apache-2.0, MIT Imports: 26 Imported by: 85

README

IPNS

A reference implementation of the IPNS Record and Verification specification.

Documentation

Example

Here's an example on how to create an IPNS Record:

import (
	"crypto/rand"
	"time"

	"github.com/ipfs/boxo/ipns"
	"github.com/ipfs/boxo/path"
	ic "github.com/libp2p/go-libp2p/core/crypto"
)

func main() {
	// Create a private key to sign your IPNS record. Most of the time, you
	// will want to retrieve an already-existing key from Kubo, for example.
	sk, _, err := ic.GenerateEd25519Key(rand.Reader)
	if err != nil {
		panic(err)
	}

	// Define the path this record will point to.
	path, err := path.NewPath("/ipfs/bafkqac3jobxhgidsn5rww4yk")
	if err != nil {
		panic(err)
	}

	// Until when the record is valid.
	eol := time.Now().Add(time.Hour)

	// For how long should caches cache the record.
	ttl := time.Second * 20

	record, err := ipns.NewRecord(sk, path, 1, eol, ttl)
	if err != nil {
		panic(err)
	}

	// Now you have an IPNS Record.
}

Documentation

Overview

Package ipns implements IPNS record creation, marshaling, and validation as specified in the IPNS Record specification.

Records

An IPNS Record maps a Name to a content path, with a sequence number, expiration time, and TTL. Records are signed with the private key corresponding to the name.

record, err := ipns.NewRecord(privateKey, path, seq, eol, ttl)
if err != nil {
    // handle error
}

data, err := ipns.MarshalRecord(record)

Records can be deserialized and validated:

record, err := ipns.UnmarshalRecord(data)
err = ipns.ValidateWithName(record, name)

Metadata

Records support custom metadata as additional keys in the signed DAG-CBOR data, as described in the Extensible Data section of the spec. Keys should be prefixed with "_" to avoid collisions with future standard fields.

record, err := ipns.NewRecord(privateKey, path, seq, eol, ttl,
    ipns.WithMetadata(map[string]any{
        "_myapp_version": "1.0",
        "_myapp_flags":   int64(42),
    }),
)

Metadata can be read back from unmarshaled records:

mv, err := record.Metadata("_myapp_version")
val, err := mv.AsString()

Names

A Name is a Multihash of a serialized public key. Names can be created from peer IDs or strings:

name := ipns.NameFromPeer(peerID)
name, err := ipns.NameFromString("k51...")

Index

Constants

View Source
const (

	// DefaultRecordLifetime defines for how long IPNS record should be valid
	// when ValidityType is 0. The default here aims to match the record
	// expiration window of Amino DHT.
	DefaultRecordLifetime = 48 * time.Hour

	// DefaultRecordTTL specifies how long the record can be returned from
	// cache before checking for update again. The function of this TTL is
	// similar to TTL of DNS record, and the default here is a trade-off
	// between faster updates and benefiting from various types of caching.
	DefaultRecordTTL = 5 * time.Minute
)
View Source
const MaxRecordSize int = 10 << (10 * 1)

MaxRecordSize is the IPNS Record size limit.

View Source
const (
	// NamespacePrefix is the prefix of the IPNS namespace.
	NamespacePrefix = "/ipns/"
)
View Source
const NoopValue = "/ipfs/bafkqaaa"

NoopValue is an identity CID that points at zero bytes.

Variables

View Source
var ErrDataMissing = errors.New("record is missing the dag-cbor data field")

ErrDataMissing is returned when an IPNS Record is missing the data field.

View Source
var ErrExpiredRecord = errors.New("record is expired")

ErrExpiredRecord is returned when an IPNS Record is invalid due to being expired.

View Source
var ErrInvalidName = errors.New("name is invalid")

ErrInvalidName is returned when an IPNS Name is invalid.

View Source
var ErrInvalidPath = errors.New("value is not a valid content path")

ErrInvalidPath is returned when an IPNS Record has an invalid path.

View Source
var ErrInvalidPublicKey = errors.New("public key invalid")

ErrInvalidPublicKey is returned when an IPNS Record has an invalid public key,

View Source
var ErrInvalidRecord = errors.New("record is malformed")

ErrInvalidRecord is returned when an IPNS Record is malformed.

View Source
var ErrInvalidValidity = errors.New("record contains an invalid validity")

ErrInvalidValidity is returned when an IPNS Record has a known validity type, but the validity value is invalid.

View Source
var ErrMetadataConflict = errors.New("metadata key uses reserved name")

ErrMetadataConflict is returned when a metadata key uses a reserved IPNS field name.

View Source
var ErrMetadataEmptyKey = errors.New("metadata key must not be empty")

ErrMetadataEmptyKey is returned when an empty string is used as a metadata key.

View Source
var ErrMetadataNotFound = errors.New("metadata key not found in record")

ErrMetadataNotFound is returned when an IPNS metadata dictionary key does not exist.

View Source
var ErrMetadataUnsupportedType = errors.New("unsupported metadata value type")

ErrMetadataUnsupportedType is returned when a metadata value has an unsupported Go type. Supported types: string, []byte, int64, int, and bool.

View Source
var ErrMetadataValueNotSet = errors.New("metadata value is not set")

ErrMetadataValueNotSet is returned when accessing an uninitialized MetadataValue (the zero value of the struct).

View Source
var ErrPublicKeyMismatch = errors.New("record public key does not match the expected public key")

ErrPublicKeyMismatch is return when the public key embedded in an IPNS Record does not match the expected public key.

View Source
var ErrPublicKeyNotFound = errors.New("public key not found")

ErrPublicKeyNotFound is returned when the public key is not found.

View Source
var ErrRecordSize = errors.New("record exceeds allowed size limit")

ErrRecordSize is returned when an IPNS Record exceeds the maximum size.

View Source
var ErrSignature = errors.New("signature verification failed")

ErrSignature is returned when an IPNS Record fails signature verification.

View Source
var ErrUnrecognizedValidity = errors.New("record contains an unrecognized validity type")

ErrUnrecognizedValidity is returned when an IPNS Record has an unknown validity type.

Functions

func ExtractPublicKey

func ExtractPublicKey(rec *Record, name Name) (ic.PubKey, error)

ExtractPublicKey extracts a crypto.PubKey matching the given Name from the IPNS Record, if possible.

func MarshalRecord added in v0.11.0

func MarshalRecord(rec *Record) ([]byte, error)

MarshalRecord encodes the given IPNS Record into its Protobuf serialization format.

func Validate

func Validate(rec *Record, pk ic.PubKey) error

Validate validates the given IPNS Record against the given crypto.PubKey, following the Record Verification specification.

func ValidateWithName added in v0.11.0

func ValidateWithName(rec *Record, name Name) error

ValidateWithName validates the given IPNS Record against the given Name.

Types

type MetadataKind added in v0.38.0

type MetadataKind int

MetadataKind identifies the scalar type stored in a MetadataValue.

const (
	// MetadataKindInvalid indicates the zero value of [MetadataValue] or an
	// unsupported DAG-CBOR kind (e.g. map, list, link).
	MetadataKindInvalid MetadataKind = iota
	MetadataKindString
	MetadataKindBytes
	MetadataKindInt
	MetadataKindBool
)

func (MetadataKind) String added in v0.38.0

func (k MetadataKind) String() string

type MetadataValue added in v0.38.0

type MetadataValue struct {
	// contains filtered or unexported fields
}

MetadataValue wraps a single DAG-CBOR scalar stored in an IPNS record. Use MetadataValue.Kind to inspect the type before calling a typed accessor.

func (MetadataValue) AsBool added in v0.38.0

func (mv MetadataValue) AsBool() (bool, error)

AsBool returns the value as a bool, or ErrMetadataValueNotSet if the receiver is the zero value. Returns an error if the underlying CBOR kind is not a boolean.

func (MetadataValue) AsBytes added in v0.38.0

func (mv MetadataValue) AsBytes() ([]byte, error)

AsBytes returns the value as bytes, or ErrMetadataValueNotSet if the receiver is the zero value. Returns an error if the underlying CBOR kind is not bytes.

func (MetadataValue) AsInt added in v0.38.0

func (mv MetadataValue) AsInt() (int64, error)

AsInt returns the value as an int64, or ErrMetadataValueNotSet if the receiver is the zero value. Returns an error if the underlying CBOR kind is not an integer.

func (MetadataValue) AsString added in v0.38.0

func (mv MetadataValue) AsString() (string, error)

AsString returns the value as a string, or ErrMetadataValueNotSet if the receiver is the zero value. Returns an error if the underlying CBOR kind is not a string.

func (MetadataValue) Kind added in v0.38.0

func (mv MetadataValue) Kind() MetadataKind

Kind returns the scalar type of this value, or MetadataKindInvalid for the zero value.

type Name added in v0.11.0

type Name struct {
	// contains filtered or unexported fields
}

Name represents a Multihash of a serialized public key according to the IPNS Name specifications.

func NameFromCid added in v0.11.0

func NameFromCid(c cid.Cid) (Name, error)

NameFromCid creates a Name from the given cid.Cid.

func NameFromPeer added in v0.11.0

func NameFromPeer(pid peer.ID) Name

NameFromPeer creates a Name from the given peer.ID.

func NameFromRoutingKey added in v0.11.0

func NameFromRoutingKey(data []byte) (Name, error)

NameFromRoutingKey creates a Name from the given IPNS Name in its routing key representation. See Name.RoutingKey for more information.

func NameFromString added in v0.11.0

func NameFromString(str string) (Name, error)

NameFromString creates a Name from the given IPNS Name in its string representation.

func (Name) AsPath added in v0.14.0

func (n Name) AsPath() path.Path

AsPath returns the IPNS Name as a path.Path prefixed by path.IPNSNamespace.

func (Name) Cid added in v0.11.0

func (n Name) Cid() cid.Cid

Cid returns Name encoded as a cid.Cid of the public key. If the IPNS Name is invalid (e.g., empty), this will return the empty Cid.

func (Name) Equal added in v0.11.0

func (n Name) Equal(other Name) bool

Equal returns whether the records are equal.

func (Name) MarshalJSON added in v0.11.0

func (n Name) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler interface. IPNS Name will marshal as a string using Name.String.

func (Name) Peer added in v0.11.0

func (n Name) Peer() peer.ID

Peer returns Name as a peer.ID.

func (Name) RoutingKey added in v0.11.0

func (n Name) RoutingKey() []byte

RoutingKey returns the binary IPNS Routing Key for the given Name. Note that the intended use of this function is for routing purposes only. The output of this function is binary, not human readable. For a human-readable string, see [Name.Key].

func (Name) String added in v0.11.0

func (n Name) String() string

String returns the human-readable IPNS Name, encoded as a CIDv1 with libp2p-key multicodec (0x72) with case-insensitive Base36.

func (*Name) UnmarshalJSON added in v0.11.0

func (n *Name) UnmarshalJSON(b []byte) error

UnmarshalJSON implements json.Unmarshaler interface. IPNS Name will unmarshal from a string via NameFromString.

type Option added in v0.11.0

type Option func(*options)

func WithMetadata added in v0.38.0

func WithMetadata(metadata map[string]any) Option

WithMetadata sets custom metadata entries in the signed DAG-CBOR data of the IPNS record, as described in the Extensible Data section of the spec. Supported value types: string, []byte, int64, int, and bool. Keys should be prefixed with "_" to avoid collisions with future standard fields. Reserved IPNS field names, empty keys, and unsupported value types cause NewRecord to return an error.

func WithPublicKey added in v0.11.0

func WithPublicKey(embedded bool) Option

WithPublicKey controls whether the public key is embedded in the record. By default, the key is embedded only for key types that are too big to be inlined in a CIDv1 (e.g. RSA, ECDSA).

func WithV1Compatibility added in v0.11.0

func WithV1Compatibility(compatible bool) Option

WithV1Compatibility controls whether the record includes legacy V1 protobuf fields and SignatureV1 for backward compatibility with older IPNS implementations. Enabled by default.

type Record added in v0.11.0

type Record struct {
	// contains filtered or unexported fields
}

Record represents an IPNS Record.

func NewRecord added in v0.11.0

func NewRecord(sk ic.PrivKey, value path.Path, seq uint64, eol time.Time, ttl time.Duration, opts ...Option) (*Record, error)

NewRecord creates a new IPNS Record and signs it with the given private key. By default, we embed the public key for key types whose peer IDs do not encode the public key, such as RSA and ECDSA key types. This can be changed with the option WithPublicKey. In addition, records are, by default created with V1 compatibility.

func UnmarshalRecord added in v0.11.0

func UnmarshalRecord(data []byte) (*Record, error)

UnmarshalRecord parses the Protobuf-serialized IPNS Record into a usable Record struct. Please note that this function does not perform a full validation of the record. For that use Validate.

func (*Record) Metadata added in v0.38.0

func (rec *Record) Metadata(key string) (MetadataValue, error)

Metadata returns a custom metadata value by key. Returns ErrMetadataConflict if the key is a reserved IPNS field. Returns ErrMetadataNotFound if the key doesn't exist.

func (*Record) MetadataEntries added in v0.38.0

func (rec *Record) MetadataEntries() iter.Seq2[string, MetadataValue]

MetadataEntries returns an iterator over all custom metadata key-value pairs in the record, skipping reserved IPNS fields.

func (*Record) MetadataExists added in v0.38.0

func (rec *Record) MetadataExists(key string) bool

MetadataExists reports whether a custom metadata key exists in the record. Returns false for reserved IPNS field names.

func (*Record) PubKey added in v0.11.0

func (rec *Record) PubKey() (ic.PubKey, error)

PubKey returns the public key embedded in this record, if present. Returns ErrPublicKeyNotFound when the record does not carry an embedded key (common for Ed25519, where the key is inlined in the IPNS Name itself).

func (*Record) Sequence added in v0.11.0

func (rec *Record) Sequence() (uint64, error)

Sequence returns the sequence number of this record.

func (*Record) TTL added in v0.11.0

func (rec *Record) TTL() (time.Duration, error)

TTL returns the time-to-live of this record as a time.Duration.

func (*Record) Validity added in v0.11.0

func (rec *Record) Validity() (time.Time, error)

Validity returns the validity of the IPNS Record. This function returns ErrUnrecognizedValidity if the validity type of the record isn't EOL. Otherwise, it returns an error if it can't parse the EOL.

func (*Record) ValidityType added in v0.11.0

func (rec *Record) ValidityType() (ValidityType, error)

ValidityType returns the validity type of this record.

func (*Record) Value added in v0.11.0

func (rec *Record) Value() (path.Path, error)

Value returns the path.Path that is embedded in this IPNS Record. If the path is invalid, an error is returned. If the value is a binary CID, it is converted to a path.Path. If the value is empty, a NoopValue is used instead.

type Validator

type Validator struct {
	// KeyBook, if non-nil, is used to lookup keys for validating IPNS Records.
	KeyBook peerstore.KeyBook
}

Validator is an IPNS Record validator that satisfies the record.Validator interface from Libp2p.

func (Validator) Select

func (v Validator) Select(k string, vals [][]byte) (int, error)

Select selects the best record by checking which has the highest sequence number and latest validity. This function returns an error if any of the records fail to parse.

This function does not validate the records. The caller is responsible for ensuring that the Records are valid by using Validate.

func (Validator) Validate

func (v Validator) Validate(key string, value []byte) error

Validate validates an IPNS record.

type ValidityType added in v0.11.0

type ValidityType int64
const ValidityEOL ValidityType = 0

ValidityEOL means "this record is valid until {Validity}". This is currently the only supported Validity type.

Directories

Path Synopsis
These commands work around namespace conflicts that occur when multiple repositories depend on .proto files with generic filenames.
These commands work around namespace conflicts that occur when multiple repositories depend on .proto files with generic filenames.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL