Integrate BACKBEAT SDK and resolve KACHING license validation

Major integrations and fixes:
- Added BACKBEAT SDK integration for P2P operation timing
- Implemented beat-aware status tracking for distributed operations
- Added Docker secrets support for secure license management
- Resolved KACHING license validation via HTTPS/TLS
- Updated docker-compose configuration for clean stack deployment
- Disabled rollback policies to prevent deployment failures
- Added license credential storage (CHORUS-DEV-MULTI-001)

Technical improvements:
- BACKBEAT P2P operation tracking with phase management
- Enhanced configuration system with file-based secrets
- Improved error handling for license validation
- Clean separation of KACHING and CHORUS deployment stacks

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
anthonyrawlins
2025-09-06 07:56:26 +10:00
parent 543ab216f9
commit 9bdcbe0447
4730 changed files with 1480093 additions and 1916 deletions

31
vendor/github.com/ipfs/boxo/ipns/README.md generated vendored Normal file
View File

@@ -0,0 +1,31 @@
## Usage
To create a new IPNS record:
```go
import (
"time"
ipns "github.com/ipfs/boxo/ipns"
crypto "github.com/libp2p/go-libp2p/core/crypto"
)
// Generate a private key to sign the IPNS record with. Most of the time,
// however, you'll want to retrieve an already-existing key from IPFS using the
// go-ipfs/core/coreapi CoreAPI.KeyAPI() interface.
privateKey, publicKey, err := crypto.GenerateKeyPair(crypto.RSA, 2048)
if err != nil {
panic(err)
}
// Create an IPNS record that expires in one hour and points to the IPFS address
// /ipfs/Qme1knMqwt1hKZbc1BmQFmnm9f36nyQGwXxPGVpVJ9rMK5
ipnsRecord, err := ipns.Create(privateKey, []byte("/ipfs/Qme1knMqwt1hKZbc1BmQFmnm9f36nyQGwXxPGVpVJ9rMK5"), 0, time.Now().Add(1*time.Hour))
if err != nil {
panic(err)
}
```
Once you have the record, youll need to use IPFS to *publish* it.
There are several other major operations you can do with `go-ipns`. Check out the [API docs](https://pkg.go.dev/github.com/ipfs/boxo/ipns) or look at the tests in this repo for examples.

44
vendor/github.com/ipfs/boxo/ipns/errors.go generated vendored Normal file
View File

@@ -0,0 +1,44 @@
package ipns
import (
"errors"
)
// ErrExpiredRecord should be returned when an ipns record is
// invalid due to being too old
var ErrExpiredRecord = errors.New("expired record")
// ErrUnrecognizedValidity is returned when an IpnsRecord has an
// unknown validity type.
var ErrUnrecognizedValidity = errors.New("unrecognized validity type")
// ErrInvalidPath should be returned when an ipns record path
// is not in a valid format
var ErrInvalidPath = errors.New("record path invalid")
// ErrSignature should be returned when an ipns record fails
// signature verification
var ErrSignature = errors.New("record signature verification failed")
// ErrKeyFormat should be returned when an ipns record key is
// incorrectly formatted (not a peer ID)
var ErrKeyFormat = errors.New("record key could not be parsed into peer ID")
// ErrPublicKeyNotFound should be returned when the public key
// corresponding to the ipns record path cannot be retrieved
// from the peer store
var ErrPublicKeyNotFound = errors.New("public key not found in peer store")
// ErrPublicKeyMismatch should be returned when the public key embedded in the
// record doesn't match the expected public key.
var ErrPublicKeyMismatch = errors.New("public key in record did not match expected pubkey")
// ErrBadRecord should be returned when an ipns record cannot be unmarshalled
var ErrBadRecord = errors.New("record could not be unmarshalled")
// 10 KiB limit defined in https://github.com/ipfs/specs/pull/319
const MaxRecordSize int = 10 << (10 * 1)
// ErrRecordSize should be returned when an ipns record is
// invalid due to being too big
var ErrRecordSize = errors.New("record exceeds allowed size limit")

419
vendor/github.com/ipfs/boxo/ipns/ipns.go generated vendored Normal file
View File

@@ -0,0 +1,419 @@
package ipns
import (
"bytes"
"fmt"
"sort"
"time"
"github.com/multiformats/go-multicodec"
"github.com/pkg/errors"
"github.com/ipld/go-ipld-prime"
_ "github.com/ipld/go-ipld-prime/codec/dagcbor" // used to import the DagCbor encoder/decoder
ipldcodec "github.com/ipld/go-ipld-prime/multicodec"
basicnode "github.com/ipld/go-ipld-prime/node/basic"
"github.com/gogo/protobuf/proto"
pb "github.com/ipfs/boxo/ipns/pb"
u "github.com/ipfs/boxo/util"
ic "github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/peer"
)
const (
validity = "Validity"
validityType = "ValidityType"
value = "Value"
sequence = "Sequence"
ttl = "TTL"
)
// Create creates a new IPNS entry and signs it with the given private key.
//
// This function does not embed the public key. If you want to do that, use
// `EmbedPublicKey`.
func Create(sk ic.PrivKey, val []byte, seq uint64, eol time.Time, ttl time.Duration) (*pb.IpnsEntry, error) {
entry := new(pb.IpnsEntry)
entry.Value = val
typ := pb.IpnsEntry_EOL
entry.ValidityType = &typ
entry.Sequence = &seq
entry.Validity = []byte(u.FormatRFC3339(eol))
ttlNs := uint64(ttl.Nanoseconds())
entry.Ttl = proto.Uint64(ttlNs)
cborData, err := createCborDataForIpnsEntry(entry)
if err != nil {
return nil, err
}
entry.Data = cborData
// For now we still create V1 signatures. These are deprecated, and not
// used during verification anymore (Validate func requires SignatureV2),
// but setting it here allows legacy nodes (e.g., go-ipfs < v0.9.0) to
// still resolve IPNS published by modern nodes.
sig1, err := sk.Sign(ipnsEntryDataForSigV1(entry))
if err != nil {
return nil, errors.Wrap(err, "could not compute signature data")
}
entry.SignatureV1 = sig1
sig2Data, err := ipnsEntryDataForSigV2(entry)
if err != nil {
return nil, err
}
sig2, err := sk.Sign(sig2Data)
if err != nil {
return nil, err
}
entry.SignatureV2 = sig2
return entry, nil
}
func createCborDataForIpnsEntry(e *pb.IpnsEntry) ([]byte, error) {
m := make(map[string]ipld.Node)
var keys []string
m[value] = basicnode.NewBytes(e.GetValue())
keys = append(keys, value)
m[validity] = basicnode.NewBytes(e.GetValidity())
keys = append(keys, validity)
m[validityType] = basicnode.NewInt(int64(e.GetValidityType()))
keys = append(keys, validityType)
m[sequence] = basicnode.NewInt(int64(e.GetSequence()))
keys = append(keys, sequence)
m[ttl] = basicnode.NewInt(int64(e.GetTtl()))
keys = append(keys, ttl)
sort.Sort(cborMapKeyString_RFC7049(keys))
newNd := basicnode.Prototype__Map{}.NewBuilder()
ma, err := newNd.BeginMap(int64(len(keys)))
if err != nil {
return nil, err
}
for _, k := range keys {
if err := ma.AssembleKey().AssignString(k); err != nil {
return nil, err
}
if err := ma.AssembleValue().AssignNode(m[k]); err != nil {
return nil, err
}
}
if err := ma.Finish(); err != nil {
return nil, err
}
nd := newNd.Build()
enc, err := ipldcodec.LookupEncoder(uint64(multicodec.DagCbor))
if err != nil {
return nil, err
}
buf := new(bytes.Buffer)
if err := enc(nd, buf); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// ValidateWithPeerID validates the given IPNS entry against the given peer ID.
func ValidateWithPeerID(pid peer.ID, entry *pb.IpnsEntry) error {
pk, err := ExtractPublicKey(pid, entry)
if err != nil {
return err
}
return Validate(pk, entry)
}
// Validates validates the given IPNS entry against the given public key.
func Validate(pk ic.PubKey, entry *pb.IpnsEntry) error {
// Make sure max size is respected
if entry.Size() > MaxRecordSize {
return ErrRecordSize
}
// Check the ipns record signature with the public key
if entry.GetSignatureV2() == nil {
// always error if no valid signature could be found
return ErrSignature
}
sig2Data, err := ipnsEntryDataForSigV2(entry)
if err != nil {
return fmt.Errorf("could not compute signature data: %w", err)
}
if ok, err := pk.Verify(sig2Data, entry.GetSignatureV2()); err != nil || !ok {
return ErrSignature
}
// TODO: If we switch from pb.IpnsEntry to a more generic IpnsRecord type then perhaps we should only check
// this if there is no v1 signature. In the meanwhile this helps avoid some potential rough edges around people
// checking the entry fields instead of doing CBOR decoding everywhere.
// See https://github.com/ipfs/boxo/ipns/pull/42 for next steps here
if err := validateCborDataMatchesPbData(entry); err != nil {
return err
}
eol, err := GetEOL(entry)
if err != nil {
return err
}
if time.Now().After(eol) {
return ErrExpiredRecord
}
return nil
}
// TODO: Most of this function could probably be replaced with codegen
func validateCborDataMatchesPbData(entry *pb.IpnsEntry) error {
if len(entry.GetData()) == 0 {
return fmt.Errorf("record data is missing")
}
dec, err := ipldcodec.LookupDecoder(uint64(multicodec.DagCbor))
if err != nil {
return err
}
ndbuilder := basicnode.Prototype__Map{}.NewBuilder()
if err := dec(ndbuilder, bytes.NewReader(entry.GetData())); err != nil {
return err
}
fullNd := ndbuilder.Build()
nd, err := fullNd.LookupByString(value)
if err != nil {
return err
}
ndBytes, err := nd.AsBytes()
if err != nil {
return err
}
if !bytes.Equal(entry.GetValue(), ndBytes) {
return fmt.Errorf("field \"%v\" did not match between protobuf and CBOR", value)
}
nd, err = fullNd.LookupByString(validity)
if err != nil {
return err
}
ndBytes, err = nd.AsBytes()
if err != nil {
return err
}
if !bytes.Equal(entry.GetValidity(), ndBytes) {
return fmt.Errorf("field \"%v\" did not match between protobuf and CBOR", validity)
}
nd, err = fullNd.LookupByString(validityType)
if err != nil {
return err
}
ndInt, err := nd.AsInt()
if err != nil {
return err
}
if int64(entry.GetValidityType()) != ndInt {
return fmt.Errorf("field \"%v\" did not match between protobuf and CBOR", validityType)
}
nd, err = fullNd.LookupByString(sequence)
if err != nil {
return err
}
ndInt, err = nd.AsInt()
if err != nil {
return err
}
if entry.GetSequence() != uint64(ndInt) {
return fmt.Errorf("field \"%v\" did not match between protobuf and CBOR", sequence)
}
nd, err = fullNd.LookupByString("TTL")
if err != nil {
return err
}
ndInt, err = nd.AsInt()
if err != nil {
return err
}
if entry.GetTtl() != uint64(ndInt) {
return fmt.Errorf("field \"%v\" did not match between protobuf and CBOR", ttl)
}
return nil
}
// GetEOL returns the EOL of this IPNS entry
//
// 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 GetEOL(entry *pb.IpnsEntry) (time.Time, error) {
if entry.GetValidityType() != pb.IpnsEntry_EOL {
return time.Time{}, ErrUnrecognizedValidity
}
return u.ParseRFC3339(string(entry.GetValidity()))
}
// EmbedPublicKey embeds the given public key in the given ipns entry. While not
// strictly required, some nodes (e.g., DHT servers) may reject IPNS entries
// that don't embed their public keys as they may not be able to validate them
// efficiently.
func EmbedPublicKey(pk ic.PubKey, entry *pb.IpnsEntry) error {
// Try extracting the public key from the ID. If we can, *don't* embed
// it.
id, err := peer.IDFromPublicKey(pk)
if err != nil {
return err
}
if _, err := id.ExtractPublicKey(); err != peer.ErrNoPublicKey {
// Either a *real* error or nil.
return err
}
// We failed to extract the public key from the peer ID, embed it in the
// record.
pkBytes, err := ic.MarshalPublicKey(pk)
if err != nil {
return err
}
entry.PubKey = pkBytes
return nil
}
// UnmarshalIpnsEntry unmarshalls an IPNS entry from a slice of bytes.
func UnmarshalIpnsEntry(data []byte) (*pb.IpnsEntry, error) {
var entry pb.IpnsEntry
err := proto.Unmarshal(data, &entry)
if err != nil {
return nil, err
}
return &entry, nil
}
// ExtractPublicKey extracts a public key matching `pid` from the IPNS record,
// if possible.
//
// This function returns (nil, nil) when no public key can be extracted and
// nothing is malformed.
func ExtractPublicKey(pid peer.ID, entry *pb.IpnsEntry) (ic.PubKey, error) {
if entry.PubKey != nil {
pk, err := ic.UnmarshalPublicKey(entry.PubKey)
if err != nil {
return nil, fmt.Errorf("unmarshaling pubkey in record: %s", err)
}
expPid, err := peer.IDFromPublicKey(pk)
if err != nil {
return nil, fmt.Errorf("could not regenerate peerID from pubkey: %s", err)
}
if pid != expPid {
return nil, ErrPublicKeyMismatch
}
return pk, nil
}
return pid.ExtractPublicKey()
}
// Compare compares two IPNS entries. It returns:
//
// * -1 if a is older than b
// * 0 if a and b cannot be ordered (this doesn't mean that they are equal)
// * +1 if a is newer than b
//
// It returns an error when either a or b are malformed.
//
// NOTE: It *does not* validate the records, the caller is responsible for calling
// `Validate` first.
//
// NOTE: If a and b cannot be ordered by this function, you can determine their
// order by comparing their serialized byte representations (using
// `bytes.Compare`). You must do this if you are implementing a libp2p record
// validator (or you can just use the one provided for you by this package).
func Compare(a, b *pb.IpnsEntry) (int, error) {
aHasV2Sig := a.GetSignatureV2() != nil
bHasV2Sig := b.GetSignatureV2() != nil
// Having a newer signature version is better than an older signature version
if aHasV2Sig && !bHasV2Sig {
return 1, nil
} else if !aHasV2Sig && bHasV2Sig {
return -1, nil
}
as := a.GetSequence()
bs := b.GetSequence()
if as > bs {
return 1, nil
} else if as < bs {
return -1, nil
}
at, err := u.ParseRFC3339(string(a.GetValidity()))
if err != nil {
return 0, err
}
bt, err := u.ParseRFC3339(string(b.GetValidity()))
if err != nil {
return 0, err
}
if at.After(bt) {
return 1, nil
} else if bt.After(at) {
return -1, nil
}
return 0, nil
}
func ipnsEntryDataForSigV1(e *pb.IpnsEntry) []byte {
return bytes.Join([][]byte{
e.Value,
e.Validity,
[]byte(fmt.Sprint(e.GetValidityType())),
},
[]byte{})
}
func ipnsEntryDataForSigV2(e *pb.IpnsEntry) ([]byte, error) {
dataForSig := []byte("ipns-signature:")
dataForSig = append(dataForSig, e.Data...)
return dataForSig, nil
}
type cborMapKeyString_RFC7049 []string
func (x cborMapKeyString_RFC7049) Len() int { return len(x) }
func (x cborMapKeyString_RFC7049) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x cborMapKeyString_RFC7049) Less(i, j int) bool {
li, lj := len(x[i]), len(x[j])
if li == lj {
return x[i] < x[j]
}
return li < lj
}
var _ sort.Interface = (cborMapKeyString_RFC7049)(nil)

11
vendor/github.com/ipfs/boxo/ipns/pb/Makefile generated vendored Normal file
View File

@@ -0,0 +1,11 @@
PB = $(wildcard *.proto)
GO = $(PB:.proto=.pb.go)
all: $(GO)
%.pb.go: %.proto
protoc --proto_path=$(GOPATH)/src:. --gogofast_out=. $<
clean:
rm -f *.pb.go
rm -f *.go

992
vendor/github.com/ipfs/boxo/ipns/pb/ipns.pb.go generated vendored Normal file
View File

@@ -0,0 +1,992 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: ipns.proto
package ipns_pb
import (
fmt "fmt"
proto "github.com/gogo/protobuf/proto"
io "io"
math "math"
math_bits "math/bits"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
type IpnsEntry_ValidityType int32
const (
// setting an EOL says "this record is valid until..."
IpnsEntry_EOL IpnsEntry_ValidityType = 0
)
var IpnsEntry_ValidityType_name = map[int32]string{
0: "EOL",
}
var IpnsEntry_ValidityType_value = map[string]int32{
"EOL": 0,
}
func (x IpnsEntry_ValidityType) Enum() *IpnsEntry_ValidityType {
p := new(IpnsEntry_ValidityType)
*p = x
return p
}
func (x IpnsEntry_ValidityType) String() string {
return proto.EnumName(IpnsEntry_ValidityType_name, int32(x))
}
func (x *IpnsEntry_ValidityType) UnmarshalJSON(data []byte) error {
value, err := proto.UnmarshalJSONEnum(IpnsEntry_ValidityType_value, data, "IpnsEntry_ValidityType")
if err != nil {
return err
}
*x = IpnsEntry_ValidityType(value)
return nil
}
func (IpnsEntry_ValidityType) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_4d5b16fb32bfe8ea, []int{0, 0}
}
type IpnsEntry struct {
Value []byte `protobuf:"bytes,1,opt,name=value" json:"value,omitempty"`
SignatureV1 []byte `protobuf:"bytes,2,opt,name=signatureV1" json:"signatureV1,omitempty"`
ValidityType *IpnsEntry_ValidityType `protobuf:"varint,3,opt,name=validityType,enum=ipns.v1.pb.IpnsEntry_ValidityType" json:"validityType,omitempty"`
Validity []byte `protobuf:"bytes,4,opt,name=validity" json:"validity,omitempty"`
Sequence *uint64 `protobuf:"varint,5,opt,name=sequence" json:"sequence,omitempty"`
Ttl *uint64 `protobuf:"varint,6,opt,name=ttl" json:"ttl,omitempty"`
// in order for nodes to properly validate a record upon receipt, they need the public
// key associated with it. For old RSA keys, its easiest if we just send this as part of
// the record itself. For newer ed25519 keys, the public key can be embedded in the
// peerID, making this field unnecessary.
PubKey []byte `protobuf:"bytes,7,opt,name=pubKey" json:"pubKey,omitempty"`
SignatureV2 []byte `protobuf:"bytes,8,opt,name=signatureV2" json:"signatureV2,omitempty"`
Data []byte `protobuf:"bytes,9,opt,name=data" json:"data,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *IpnsEntry) Reset() { *m = IpnsEntry{} }
func (m *IpnsEntry) String() string { return proto.CompactTextString(m) }
func (*IpnsEntry) ProtoMessage() {}
func (*IpnsEntry) Descriptor() ([]byte, []int) {
return fileDescriptor_4d5b16fb32bfe8ea, []int{0}
}
func (m *IpnsEntry) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *IpnsEntry) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_IpnsEntry.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *IpnsEntry) XXX_Merge(src proto.Message) {
xxx_messageInfo_IpnsEntry.Merge(m, src)
}
func (m *IpnsEntry) XXX_Size() int {
return m.Size()
}
func (m *IpnsEntry) XXX_DiscardUnknown() {
xxx_messageInfo_IpnsEntry.DiscardUnknown(m)
}
var xxx_messageInfo_IpnsEntry proto.InternalMessageInfo
func (m *IpnsEntry) GetValue() []byte {
if m != nil {
return m.Value
}
return nil
}
func (m *IpnsEntry) GetSignatureV1() []byte {
if m != nil {
return m.SignatureV1
}
return nil
}
func (m *IpnsEntry) GetValidityType() IpnsEntry_ValidityType {
if m != nil && m.ValidityType != nil {
return *m.ValidityType
}
return IpnsEntry_EOL
}
func (m *IpnsEntry) GetValidity() []byte {
if m != nil {
return m.Validity
}
return nil
}
func (m *IpnsEntry) GetSequence() uint64 {
if m != nil && m.Sequence != nil {
return *m.Sequence
}
return 0
}
func (m *IpnsEntry) GetTtl() uint64 {
if m != nil && m.Ttl != nil {
return *m.Ttl
}
return 0
}
func (m *IpnsEntry) GetPubKey() []byte {
if m != nil {
return m.PubKey
}
return nil
}
func (m *IpnsEntry) GetSignatureV2() []byte {
if m != nil {
return m.SignatureV2
}
return nil
}
func (m *IpnsEntry) GetData() []byte {
if m != nil {
return m.Data
}
return nil
}
type IpnsSignatureV2Checker struct {
PubKey []byte `protobuf:"bytes,7,opt,name=pubKey" json:"pubKey,omitempty"`
SignatureV2 []byte `protobuf:"bytes,8,opt,name=signatureV2" json:"signatureV2,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *IpnsSignatureV2Checker) Reset() { *m = IpnsSignatureV2Checker{} }
func (m *IpnsSignatureV2Checker) String() string { return proto.CompactTextString(m) }
func (*IpnsSignatureV2Checker) ProtoMessage() {}
func (*IpnsSignatureV2Checker) Descriptor() ([]byte, []int) {
return fileDescriptor_4d5b16fb32bfe8ea, []int{1}
}
func (m *IpnsSignatureV2Checker) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *IpnsSignatureV2Checker) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_IpnsSignatureV2Checker.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *IpnsSignatureV2Checker) XXX_Merge(src proto.Message) {
xxx_messageInfo_IpnsSignatureV2Checker.Merge(m, src)
}
func (m *IpnsSignatureV2Checker) XXX_Size() int {
return m.Size()
}
func (m *IpnsSignatureV2Checker) XXX_DiscardUnknown() {
xxx_messageInfo_IpnsSignatureV2Checker.DiscardUnknown(m)
}
var xxx_messageInfo_IpnsSignatureV2Checker proto.InternalMessageInfo
func (m *IpnsSignatureV2Checker) GetPubKey() []byte {
if m != nil {
return m.PubKey
}
return nil
}
func (m *IpnsSignatureV2Checker) GetSignatureV2() []byte {
if m != nil {
return m.SignatureV2
}
return nil
}
func init() {
proto.RegisterEnum("ipns.v1.pb.IpnsEntry_ValidityType", IpnsEntry_ValidityType_name, IpnsEntry_ValidityType_value)
proto.RegisterType((*IpnsEntry)(nil), "ipns.v1.pb.IpnsEntry")
proto.RegisterType((*IpnsSignatureV2Checker)(nil), "ipns.v1.pb.IpnsSignatureV2Checker")
}
func init() { proto.RegisterFile("ipns.proto", fileDescriptor_4d5b16fb32bfe8ea) }
var fileDescriptor_4d5b16fb32bfe8ea = []byte{
// 272 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0xca, 0x2c, 0xc8, 0x2b,
0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x82, 0xb0, 0xcb, 0x0c, 0xf5, 0x0a, 0x92, 0x94, 0xf6,
0x30, 0x71, 0x71, 0x7a, 0x16, 0xe4, 0x15, 0xbb, 0xe6, 0x95, 0x14, 0x55, 0x0a, 0x89, 0x70, 0xb1,
0x96, 0x25, 0xe6, 0x94, 0xa6, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0xf0, 0x04, 0x41, 0x38, 0x42, 0x0a,
0x5c, 0xdc, 0xc5, 0x99, 0xe9, 0x79, 0x89, 0x25, 0xa5, 0x45, 0xa9, 0x61, 0x86, 0x12, 0x4c, 0x60,
0x39, 0x64, 0x21, 0x21, 0x37, 0x2e, 0x9e, 0xb2, 0xc4, 0x9c, 0xcc, 0x94, 0xcc, 0x92, 0xca, 0x90,
0xca, 0x82, 0x54, 0x09, 0x66, 0x05, 0x46, 0x0d, 0x3e, 0x23, 0x25, 0x3d, 0x84, 0x45, 0x7a, 0x70,
0x4b, 0xf4, 0xc2, 0x90, 0x54, 0x06, 0xa1, 0xe8, 0x13, 0x92, 0xe2, 0xe2, 0x80, 0xf1, 0x25, 0x58,
0xc0, 0xd6, 0xc0, 0xf9, 0x20, 0xb9, 0xe2, 0xd4, 0xc2, 0xd2, 0xd4, 0xbc, 0xe4, 0x54, 0x09, 0x56,
0x05, 0x46, 0x0d, 0x96, 0x20, 0x38, 0x5f, 0x48, 0x80, 0x8b, 0xb9, 0xa4, 0x24, 0x47, 0x82, 0x0d,
0x2c, 0x0c, 0x62, 0x0a, 0x89, 0x71, 0xb1, 0x15, 0x94, 0x26, 0x79, 0xa7, 0x56, 0x4a, 0xb0, 0x83,
0xcd, 0x81, 0xf2, 0x50, 0xfd, 0x62, 0x24, 0xc1, 0x81, 0xee, 0x17, 0x23, 0x21, 0x21, 0x2e, 0x96,
0x94, 0xc4, 0x92, 0x44, 0x09, 0x4e, 0xb0, 0x14, 0x98, 0xad, 0x24, 0xce, 0xc5, 0x83, 0xec, 0x6a,
0x21, 0x76, 0x2e, 0x66, 0x57, 0x7f, 0x1f, 0x01, 0x06, 0xa5, 0x20, 0x2e, 0x31, 0x90, 0xc7, 0x82,
0x11, 0xfa, 0x9d, 0x33, 0x52, 0x93, 0xb3, 0x53, 0x8b, 0xc8, 0x77, 0x80, 0x93, 0xe8, 0x89, 0x47,
0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x18, 0xc5, 0x0e, 0x0a, 0xc3, 0xf8,
0x82, 0x24, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xbd, 0x45, 0xdd, 0x1a, 0xc2, 0x01, 0x00, 0x00,
}
func (m *IpnsEntry) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *IpnsEntry) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *IpnsEntry) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if m.XXX_unrecognized != nil {
i -= len(m.XXX_unrecognized)
copy(dAtA[i:], m.XXX_unrecognized)
}
if m.Data != nil {
i -= len(m.Data)
copy(dAtA[i:], m.Data)
i = encodeVarintIpns(dAtA, i, uint64(len(m.Data)))
i--
dAtA[i] = 0x4a
}
if m.SignatureV2 != nil {
i -= len(m.SignatureV2)
copy(dAtA[i:], m.SignatureV2)
i = encodeVarintIpns(dAtA, i, uint64(len(m.SignatureV2)))
i--
dAtA[i] = 0x42
}
if m.PubKey != nil {
i -= len(m.PubKey)
copy(dAtA[i:], m.PubKey)
i = encodeVarintIpns(dAtA, i, uint64(len(m.PubKey)))
i--
dAtA[i] = 0x3a
}
if m.Ttl != nil {
i = encodeVarintIpns(dAtA, i, uint64(*m.Ttl))
i--
dAtA[i] = 0x30
}
if m.Sequence != nil {
i = encodeVarintIpns(dAtA, i, uint64(*m.Sequence))
i--
dAtA[i] = 0x28
}
if m.Validity != nil {
i -= len(m.Validity)
copy(dAtA[i:], m.Validity)
i = encodeVarintIpns(dAtA, i, uint64(len(m.Validity)))
i--
dAtA[i] = 0x22
}
if m.ValidityType != nil {
i = encodeVarintIpns(dAtA, i, uint64(*m.ValidityType))
i--
dAtA[i] = 0x18
}
if m.SignatureV1 != nil {
i -= len(m.SignatureV1)
copy(dAtA[i:], m.SignatureV1)
i = encodeVarintIpns(dAtA, i, uint64(len(m.SignatureV1)))
i--
dAtA[i] = 0x12
}
if m.Value != nil {
i -= len(m.Value)
copy(dAtA[i:], m.Value)
i = encodeVarintIpns(dAtA, i, uint64(len(m.Value)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func (m *IpnsSignatureV2Checker) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *IpnsSignatureV2Checker) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *IpnsSignatureV2Checker) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if m.XXX_unrecognized != nil {
i -= len(m.XXX_unrecognized)
copy(dAtA[i:], m.XXX_unrecognized)
}
if m.SignatureV2 != nil {
i -= len(m.SignatureV2)
copy(dAtA[i:], m.SignatureV2)
i = encodeVarintIpns(dAtA, i, uint64(len(m.SignatureV2)))
i--
dAtA[i] = 0x42
}
if m.PubKey != nil {
i -= len(m.PubKey)
copy(dAtA[i:], m.PubKey)
i = encodeVarintIpns(dAtA, i, uint64(len(m.PubKey)))
i--
dAtA[i] = 0x3a
}
return len(dAtA) - i, nil
}
func encodeVarintIpns(dAtA []byte, offset int, v uint64) int {
offset -= sovIpns(v)
base := offset
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return base
}
func (m *IpnsEntry) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if m.Value != nil {
l = len(m.Value)
n += 1 + l + sovIpns(uint64(l))
}
if m.SignatureV1 != nil {
l = len(m.SignatureV1)
n += 1 + l + sovIpns(uint64(l))
}
if m.ValidityType != nil {
n += 1 + sovIpns(uint64(*m.ValidityType))
}
if m.Validity != nil {
l = len(m.Validity)
n += 1 + l + sovIpns(uint64(l))
}
if m.Sequence != nil {
n += 1 + sovIpns(uint64(*m.Sequence))
}
if m.Ttl != nil {
n += 1 + sovIpns(uint64(*m.Ttl))
}
if m.PubKey != nil {
l = len(m.PubKey)
n += 1 + l + sovIpns(uint64(l))
}
if m.SignatureV2 != nil {
l = len(m.SignatureV2)
n += 1 + l + sovIpns(uint64(l))
}
if m.Data != nil {
l = len(m.Data)
n += 1 + l + sovIpns(uint64(l))
}
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
return n
}
func (m *IpnsSignatureV2Checker) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if m.PubKey != nil {
l = len(m.PubKey)
n += 1 + l + sovIpns(uint64(l))
}
if m.SignatureV2 != nil {
l = len(m.SignatureV2)
n += 1 + l + sovIpns(uint64(l))
}
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
return n
}
func sovIpns(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
func sozIpns(x uint64) (n int) {
return sovIpns(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *IpnsEntry) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowIpns
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: IpnsEntry: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: IpnsEntry: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowIpns
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthIpns
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthIpns
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Value = append(m.Value[:0], dAtA[iNdEx:postIndex]...)
if m.Value == nil {
m.Value = []byte{}
}
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field SignatureV1", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowIpns
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthIpns
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthIpns
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.SignatureV1 = append(m.SignatureV1[:0], dAtA[iNdEx:postIndex]...)
if m.SignatureV1 == nil {
m.SignatureV1 = []byte{}
}
iNdEx = postIndex
case 3:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field ValidityType", wireType)
}
var v IpnsEntry_ValidityType
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowIpns
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= IpnsEntry_ValidityType(b&0x7F) << shift
if b < 0x80 {
break
}
}
m.ValidityType = &v
case 4:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Validity", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowIpns
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthIpns
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthIpns
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Validity = append(m.Validity[:0], dAtA[iNdEx:postIndex]...)
if m.Validity == nil {
m.Validity = []byte{}
}
iNdEx = postIndex
case 5:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Sequence", wireType)
}
var v uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowIpns
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
m.Sequence = &v
case 6:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Ttl", wireType)
}
var v uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowIpns
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
m.Ttl = &v
case 7:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field PubKey", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowIpns
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthIpns
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthIpns
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.PubKey = append(m.PubKey[:0], dAtA[iNdEx:postIndex]...)
if m.PubKey == nil {
m.PubKey = []byte{}
}
iNdEx = postIndex
case 8:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field SignatureV2", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowIpns
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthIpns
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthIpns
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.SignatureV2 = append(m.SignatureV2[:0], dAtA[iNdEx:postIndex]...)
if m.SignatureV2 == nil {
m.SignatureV2 = []byte{}
}
iNdEx = postIndex
case 9:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowIpns
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthIpns
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthIpns
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...)
if m.Data == nil {
m.Data = []byte{}
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipIpns(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthIpns
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthIpns
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *IpnsSignatureV2Checker) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowIpns
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: IpnsSignatureV2Checker: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: IpnsSignatureV2Checker: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 7:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field PubKey", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowIpns
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthIpns
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthIpns
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.PubKey = append(m.PubKey[:0], dAtA[iNdEx:postIndex]...)
if m.PubKey == nil {
m.PubKey = []byte{}
}
iNdEx = postIndex
case 8:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field SignatureV2", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowIpns
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthIpns
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthIpns
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.SignatureV2 = append(m.SignatureV2[:0], dAtA[iNdEx:postIndex]...)
if m.SignatureV2 == nil {
m.SignatureV2 = []byte{}
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipIpns(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthIpns
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthIpns
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipIpns(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
depth := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowIpns
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowIpns
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
case 1:
iNdEx += 8
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowIpns
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if length < 0 {
return 0, ErrInvalidLengthIpns
}
iNdEx += length
case 3:
depth++
case 4:
if depth == 0 {
return 0, ErrUnexpectedEndOfGroupIpns
}
depth--
case 5:
iNdEx += 4
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
if iNdEx < 0 {
return 0, ErrInvalidLengthIpns
}
if depth == 0 {
return iNdEx, nil
}
}
return 0, io.ErrUnexpectedEOF
}
var (
ErrInvalidLengthIpns = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowIpns = fmt.Errorf("proto: integer overflow")
ErrUnexpectedEndOfGroupIpns = fmt.Errorf("proto: unexpected end of group")
)

36
vendor/github.com/ipfs/boxo/ipns/pb/ipns.proto generated vendored Normal file
View File

@@ -0,0 +1,36 @@
syntax = "proto2";
package ipns.v1.pb;
option go_package = "ipns_pb";
message IpnsEntry {
enum ValidityType {
// setting an EOL says "this record is valid until..."
EOL = 0;
}
optional bytes value = 1;
optional bytes signatureV1 = 2;
optional ValidityType validityType = 3;
optional bytes validity = 4;
optional uint64 sequence = 5;
optional uint64 ttl = 6;
// in order for nodes to properly validate a record upon receipt, they need the public
// key associated with it. For old RSA keys, its easiest if we just send this as part of
// the record itself. For newer ed25519 keys, the public key can be embedded in the
// peerID, making this field unnecessary.
optional bytes pubKey = 7;
optional bytes signatureV2 = 8;
optional bytes data = 9;
}
message IpnsSignatureV2Checker {
optional bytes pubKey = 7;
optional bytes signatureV2 = 8;
}

126
vendor/github.com/ipfs/boxo/ipns/record.go generated vendored Normal file
View File

@@ -0,0 +1,126 @@
package ipns
import (
"bytes"
"errors"
pb "github.com/ipfs/boxo/ipns/pb"
"github.com/gogo/protobuf/proto"
logging "github.com/ipfs/go-log/v2"
record "github.com/libp2p/go-libp2p-record"
ic "github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/peer"
pstore "github.com/libp2p/go-libp2p/core/peerstore"
)
var log = logging.Logger("ipns")
var _ record.Validator = Validator{}
// RecordKey returns the libp2p record key for a given peer ID.
func RecordKey(pid peer.ID) string {
return "/ipns/" + string(pid)
}
// Validator is an IPNS record validator that satisfies the libp2p record
// validator interface.
type Validator struct {
// KeyBook, if non-nil, will be used to lookup keys for validating IPNS
// records.
KeyBook pstore.KeyBook
}
// Validate validates an IPNS record.
func (v Validator) Validate(key string, value []byte) error {
ns, pidString, err := record.SplitKey(key)
if err != nil || ns != "ipns" {
return ErrInvalidPath
}
// Parse the value into an IpnsEntry
entry := new(pb.IpnsEntry)
err = proto.Unmarshal(value, entry)
if err != nil {
return ErrBadRecord
}
// Get the public key defined by the ipns path
pid, err := peer.IDFromBytes([]byte(pidString))
if err != nil {
log.Debugf("failed to parse ipns record key %s into peer ID", pidString)
return ErrKeyFormat
}
pubk, err := v.getPublicKey(pid, entry)
if err != nil {
return err
}
return Validate(pubk, entry)
}
func (v Validator) getPublicKey(pid peer.ID, entry *pb.IpnsEntry) (ic.PubKey, error) {
switch pk, err := ExtractPublicKey(pid, entry); err {
case peer.ErrNoPublicKey:
case nil:
return pk, nil
default:
return nil, err
}
if v.KeyBook == nil {
log.Debugf("public key with hash %s not found in IPNS record and no peer store provided", pid)
return nil, ErrPublicKeyNotFound
}
pubk := v.KeyBook.PubKey(pid)
if pubk == nil {
log.Debugf("public key with hash %s not found in peer store", pid)
return nil, ErrPublicKeyNotFound
}
return pubk, nil
}
// Select selects the best record by checking which has the highest sequence
// number and latest EOL.
//
// This function returns an error if any of the records fail to parse. Validate
// your records first!
func (v Validator) Select(k string, vals [][]byte) (int, error) {
var recs []*pb.IpnsEntry
for _, v := range vals {
e := new(pb.IpnsEntry)
if err := proto.Unmarshal(v, e); err != nil {
return -1, err
}
recs = append(recs, e)
}
return selectRecord(recs, vals)
}
func selectRecord(recs []*pb.IpnsEntry, vals [][]byte) (int, error) {
switch len(recs) {
case 0:
return -1, errors.New("no usable records in given set")
case 1:
return 0, nil
}
var i int
for j := 1; j < len(recs); j++ {
cmp, err := Compare(recs[i], recs[j])
if err != nil {
return -1, err
}
if cmp == 0 {
cmp = bytes.Compare(vals[i], vals[j])
}
if cmp < 0 {
i = j
}
}
return i, nil
}