Skip to content
This repository has been archived by the owner on Jun 20, 2023. It is now read-only.

feat: use PublishOptions for publishing IPNS records #35

Merged
merged 2 commits into from
Jan 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ require (
github.com/ipfs/go-ipfs-ds-help v1.1.0
github.com/ipfs/go-ipfs-keystore v0.1.0
github.com/ipfs/go-ipfs-routing v0.3.0
github.com/ipfs/go-ipns v0.2.0
github.com/ipfs/go-ipns v0.3.0
github.com/ipfs/go-log v1.0.5
github.com/ipfs/go-path v0.1.1
github.com/ipfs/interface-go-ipfs-core v0.8.0
github.com/ipfs/interface-go-ipfs-core v0.9.0
github.com/jbenet/goprocess v0.1.4
github.com/libp2p/go-libp2p v0.23.4
github.com/libp2p/go-libp2p-kad-dht v0.19.0
github.com/libp2p/go-libp2p-record v0.2.0
github.com/libp2p/go-libp2p-testing v0.12.0
github.com/miekg/dns v1.1.50
github.com/multiformats/go-multiaddr v0.7.0
github.com/multiformats/go-multiaddr v0.8.0
github.com/multiformats/go-multiaddr-dns v0.3.1
github.com/multiformats/go-multihash v0.2.1
github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc
Expand Down Expand Up @@ -103,6 +103,7 @@ require (
github.com/raulk/go-watchdog v1.3.0 // indirect
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/stretchr/testify v1.8.1 // indirect
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect
go.opencensus.io v0.23.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
Expand Down
19 changes: 12 additions & 7 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -349,8 +349,8 @@ github.com/ipfs/go-ipld-cbor v0.0.3/go.mod h1:wTBtrQZA3SoFKMVkp6cn6HMRteIB1VsmHA
github.com/ipfs/go-ipld-format v0.0.1/go.mod h1:kyJtbkDALmFHv3QR6et67i35QzO3S0dCDnkOJhcZkms=
github.com/ipfs/go-ipld-format v0.0.2/go.mod h1:4B6+FM2u9OJ9zCV+kSbgFAZlOrv1Hqbf0INGQgiKf9k=
github.com/ipfs/go-ipld-format v0.2.0/go.mod h1:3l3C1uKoadTPbeNfrDi+xMInYKlx2Cvg1BuydPSdzQs=
github.com/ipfs/go-ipns v0.2.0 h1:BgmNtQhqOw5XEZ8RAfWEpK4DhqaYiuP6h71MhIp7xXU=
github.com/ipfs/go-ipns v0.2.0/go.mod h1:3cLT2rbvgPZGkHJoPO1YMJeh6LtkxopCkKFcio/wE24=
github.com/ipfs/go-ipns v0.3.0 h1:ai791nTgVo+zTuq2bLvEGmWP1M0A6kGTXUsgv/Yq67A=
github.com/ipfs/go-ipns v0.3.0/go.mod h1:3cLT2rbvgPZGkHJoPO1YMJeh6LtkxopCkKFcio/wE24=
github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM=
github.com/ipfs/go-log v1.0.2/go.mod h1:1MNjMxe0u6xvJZgeqbJ8vdo2TKaGwZ1a0Bpza+sr2Sk=
github.com/ipfs/go-log v1.0.3/go.mod h1:OsLySYkwIbiSUR/yBTdv1qPtcE4FW3WPWk/ewz9Ru+A=
Expand All @@ -375,8 +375,8 @@ github.com/ipfs/go-peertaskqueue v0.2.0/go.mod h1:5/eNrBEbtSKWCG+kQK8K8fGNixoYUn
github.com/ipfs/go-unixfs v0.2.4/go.mod h1:SUdisfUjNoSDzzhGVxvCL9QO/nKdwXdr+gbMUdqcbYw=
github.com/ipfs/go-unixfsnode v1.1.2/go.mod h1:5dcE2x03pyjHk4JjamXmunTMzz+VUtqvPwZjIEkfV6s=
github.com/ipfs/go-verifcid v0.0.1/go.mod h1:5Hrva5KBeIog4A+UpqlaIU+DEstipcJYQQZc0g37pY0=
github.com/ipfs/interface-go-ipfs-core v0.8.0 h1:pNs34l947fvNOh+XEjXnHW/GV6HXmEzJNeqZFhX4GoQ=
github.com/ipfs/interface-go-ipfs-core v0.8.0/go.mod h1:WYC2H6Mu7aGqhlupi/CVawcs0X1Me4uRvV0rcTlo3zM=
github.com/ipfs/interface-go-ipfs-core v0.9.0 h1:+RCouVtSU/SldgkqWufjIu1smmGaSyKgUIfbYwLukgI=
github.com/ipfs/interface-go-ipfs-core v0.9.0/go.mod h1:F3EcmDy53GFkF0H3iEJpfJC320fZ/4G60eftnItrrJ0=
github.com/ipld/go-codec-dagpb v1.3.0/go.mod h1:ga4JTU3abYApDC3pZ00BC2RSvC3qfBb9MSJkMLSwnhA=
github.com/ipld/go-ipld-prime v0.11.0 h1:jD/b/22R7CSL+F9xNffcexs+wO0Ji/TfwXO/TWck+70=
github.com/ipld/go-ipld-prime v0.11.0/go.mod h1:+WIAkokurHmZ/KwzDOMUuoeJgaRQktHtEaLglS3ZeV8=
Expand Down Expand Up @@ -701,8 +701,8 @@ github.com/multiformats/go-multiaddr v0.2.1/go.mod h1:s/Apk6IyxfvMjDafnhJgJ3/46z
github.com/multiformats/go-multiaddr v0.2.2/go.mod h1:NtfXiOtHvghW9KojvtySjH5y0u0xW5UouOmQQrn6a3Y=
github.com/multiformats/go-multiaddr v0.3.0/go.mod h1:dF9kph9wfJ+3VLAaeBqo9Of8x4fJxp6ggJGteB8HQTI=
github.com/multiformats/go-multiaddr v0.3.1/go.mod h1:uPbspcUPd5AfaP6ql3ujFY+QWzmBD8uLLL4bXW0XfGc=
github.com/multiformats/go-multiaddr v0.7.0 h1:gskHcdaCyPtp9XskVwtvEeQOG465sCohbQIirSyqxrc=
github.com/multiformats/go-multiaddr v0.7.0/go.mod h1:Fs50eBDWvZu+l3/9S6xAE7ZYj6yhxlvaVZjakWN7xRs=
github.com/multiformats/go-multiaddr v0.8.0 h1:aqjksEcqK+iD/Foe1RRFsGZh8+XFiGo7FgUCZlpv3LU=
github.com/multiformats/go-multiaddr v0.8.0/go.mod h1:Fs50eBDWvZu+l3/9S6xAE7ZYj6yhxlvaVZjakWN7xRs=
github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q=
github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q=
github.com/multiformats/go-multiaddr-dns v0.2.0/go.mod h1:TJ5pr5bBO7Y1B18djPuRsVkduhQH2YqYSbxWJzYGdK0=
Expand Down Expand Up @@ -870,14 +870,18 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM
github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
Expand Down Expand Up @@ -1341,6 +1345,7 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
Expand Down
8 changes: 1 addition & 7 deletions interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ package namesys

import (
"errors"
"time"

"context"

Expand Down Expand Up @@ -95,12 +94,7 @@ type Resolver interface {

// Publisher is an object capable of publishing particular names.
type Publisher interface {

// Publish establishes a name-value mapping.
// TODO make this not PrivKey specific.
Publish(ctx context.Context, name ci.PrivKey, value path.Path) error

// TODO: to be replaced by a more generic 'PublishWithValidity' type
// call once the records spec is implemented
PublishWithEOL(ctx context.Context, name ci.PrivKey, value path.Path, eol time.Time) error
Publish(ctx context.Context, name ci.PrivKey, value path.Path, options ...opts.PublishOption) error
}
24 changes: 13 additions & 11 deletions namesys.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,34 +285,36 @@ func emitOnceResult(ctx context.Context, outCh chan<- onceResult, r onceResult)
}

// Publish implements Publisher
func (ns *mpns) Publish(ctx context.Context, name ci.PrivKey, value path.Path) error {
func (ns *mpns) Publish(ctx context.Context, name ci.PrivKey, value path.Path, options ...opts.PublishOption) error {
ctx, span := StartSpan(ctx, "MPNS.Publish")
defer span.End()
return ns.PublishWithEOL(ctx, name, value, time.Now().Add(DefaultRecordEOL))
}

func (ns *mpns) PublishWithEOL(ctx context.Context, name ci.PrivKey, value path.Path, eol time.Time) error {
ctx, span := StartSpan(ctx, "MPNS.PublishWithEOL", trace.WithAttributes(attribute.String("Value", value.String())))
defer span.End()
// This is a bit hacky. We do this because the EOL is based on the current
// time, but also needed in the end of the function. Therefore, we parse
// the options immediately and add an option PublishWithEOL with the EOL
// calculated in this moment.
publishOpts := opts.ProcessPublishOptions(options)
options = append(options, opts.PublishWithEOL(publishOpts.EOL))
Comment on lines +292 to +297
Copy link
Member

@lidel lidel Jan 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💭 I think this is still way better than the old context hackery, and quite futrure-proof (allows us to add more opts if needed, without having to change public API)


id, err := peer.IDFromPrivateKey(name)
if err != nil {
span.RecordError(err)
return err
}
span.SetAttributes(attribute.String("ID", id.String()))
if err := ns.ipnsPublisher.PublishWithEOL(ctx, name, value, eol); err != nil {
if err := ns.ipnsPublisher.Publish(ctx, name, value, options...); err != nil {
// Invalidate the cache. Publishing may _partially_ succeed but
// still return an error.
ns.cacheInvalidate(string(id))
span.RecordError(err)
return err
}
ttl := DefaultResolverCacheTTL
if setTTL, ok := checkCtxTTL(ctx); ok {
ttl = setTTL
if publishOpts.TTL >= 0 {
ttl = publishOpts.TTL
}
if ttEol := time.Until(eol); ttEol < ttl {
ttl = ttEol
if ttEOL := time.Until(publishOpts.EOL); ttEOL < ttl {
ttl = ttEOL
}
ns.cacheSet(string(id), value, ttl)
return nil
Expand Down
3 changes: 1 addition & 2 deletions namesys_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,7 @@ func TestPublishWithTTL(t *testing.T) {
ttl := 1 * time.Second
eol := time.Now().Add(2 * time.Second)

ctx := ContextWithTTL(context.Background(), ttl)
err = nsys.Publish(ctx, priv, p)
err = nsys.Publish(context.Background(), priv, p, opts.PublishWithEOL(eol), opts.PublishWithTTL(ttl))
if err != nil {
t.Fatal(err)
}
Expand Down
64 changes: 15 additions & 49 deletions publisher.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/ipfs/go-ipns"
pb "github.com/ipfs/go-ipns/pb"
"github.com/ipfs/go-path"
opts "github.com/ipfs/interface-go-ipfs-core/options/namesys"
"github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/core/routing"
Expand All @@ -22,11 +23,6 @@ import (

const ipnsPrefix = "/ipns/"

// DefaultRecordEOL specifies the time that the network will cache IPNS
// records after being publihsed. Records should be re-published before this
// interval expires.
const DefaultRecordEOL = 24 * time.Hour

// IpnsPublisher is capable of publishing and resolving names to the IPFS
// routing system.
type IpnsPublisher struct {
Expand All @@ -47,9 +43,18 @@ func NewIpnsPublisher(route routing.ValueStore, ds ds.Datastore) *IpnsPublisher

// Publish implements Publisher. Accepts a keypair and a value,
// and publishes it out to the routing system
func (p *IpnsPublisher) Publish(ctx context.Context, k crypto.PrivKey, value path.Path) error {
func (p *IpnsPublisher) Publish(ctx context.Context, k crypto.PrivKey, value path.Path, options ...opts.PublishOption) error {
log.Debugf("Publish %s", value)
return p.PublishWithEOL(ctx, k, value, time.Now().Add(DefaultRecordEOL))

ctx, span := StartSpan(ctx, "IpnsPublisher.Publish", trace.WithAttributes(attribute.String("Value", value.String())))
defer span.End()

record, err := p.updateRecord(ctx, k, value, options...)
if err != nil {
return err
}

return PutRecordToRouting(ctx, p.routing, k.GetPublic(), record)
}

// IpnsDsKey returns a datastore key given an IPNS identifier (peer
Expand Down Expand Up @@ -142,7 +147,7 @@ func (p *IpnsPublisher) GetPublished(ctx context.Context, id peer.ID, checkRouti
return e, nil
}

func (p *IpnsPublisher) updateRecord(ctx context.Context, k crypto.PrivKey, value path.Path, eol time.Time) (*pb.IpnsEntry, error) {
func (p *IpnsPublisher) updateRecord(ctx context.Context, k crypto.PrivKey, value path.Path, options ...opts.PublishOption) (*pb.IpnsEntry, error) {
id, err := peer.IDFromPrivateKey(k)
if err != nil {
return nil, err
Expand All @@ -164,12 +169,10 @@ func (p *IpnsPublisher) updateRecord(ctx context.Context, k crypto.PrivKey, valu
seqno++
}

// Set the TTL
// TODO: Make this less hacky.
ttl, _ := checkCtxTTL(ctx)
opts := opts.ProcessPublishOptions(options)

// Create record
entry, err := ipns.Create(k, []byte(value), seqno, eol, ttl)
entry, err := ipns.Create(k, []byte(value), seqno, opts.EOL, opts.TTL)
if err != nil {
return nil, err
}
Expand All @@ -190,33 +193,6 @@ func (p *IpnsPublisher) updateRecord(ctx context.Context, k crypto.PrivKey, valu
return entry, nil
}

// PublishWithEOL is a temporary stand in for the ipns records implementation
// see here for more details: https://github.com/ipfs/specs/tree/master/records
func (p *IpnsPublisher) PublishWithEOL(ctx context.Context, k crypto.PrivKey, value path.Path, eol time.Time) error {
ctx, span := StartSpan(ctx, "IpnsPublisher.PublishWithEOL", trace.WithAttributes(attribute.String("Value", value.String())))
defer span.End()

record, err := p.updateRecord(ctx, k, value, eol)
if err != nil {
return err
}

return PutRecordToRouting(ctx, p.routing, k.GetPublic(), record)
}

// setting the TTL on published records is an experimental feature.
// as such, i'm using the context to wire it through to avoid changing too
// much code along the way.
func checkCtxTTL(ctx context.Context) (time.Duration, bool) {
v := ctx.Value(ttlContextKey)
if v == nil {
return 0, false
}

d, ok := v.(time.Duration)
return d, ok
}

// PutRecordToRouting publishes the given entry using the provided ValueStore,
// keyed on the ID associated with the provided public key. The public key is
// also made available to the routing system so that entries can be verified.
Expand Down Expand Up @@ -307,13 +283,3 @@ func PublishEntry(ctx context.Context, r routing.ValueStore, ipnskey string, rec
func PkKeyForID(id peer.ID) string {
return "/pk/" + string(id)
}

// contextKey is a private comparable type used to hold value keys in contexts
type contextKey string

var ttlContextKey contextKey = "ipns-publish-ttl"

// ContextWithTTL returns a copy of the parent context with an added value representing the TTL
func ContextWithTTL(ctx context.Context, ttl time.Duration) context.Context {
return context.WithValue(context.Background(), ttlContextKey, ttl)
}
3 changes: 2 additions & 1 deletion republisher/repub.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/ipfs/go-ipns"
pb "github.com/ipfs/go-ipns/pb"
logging "github.com/ipfs/go-log"
opts "github.com/ipfs/interface-go-ipfs-core/options/namesys"
"github.com/jbenet/goprocess"
gpctx "github.com/jbenet/goprocess/context"
ic "github.com/libp2p/go-libp2p/core/crypto"
Expand Down Expand Up @@ -161,7 +162,7 @@ func (rp *Republisher) republishEntry(ctx context.Context, priv ic.PrivKey) erro
if prevEol.After(eol) {
eol = prevEol
}
err = rp.ns.PublishWithEOL(ctx, priv, p, eol)
err = rp.ns.Publish(ctx, priv, p, opts.PublishWithEOL(eol))
span.RecordError(err)
return err
}
Expand Down
5 changes: 3 additions & 2 deletions republisher/repub_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/ipfs/go-ipns"
ipns_pb "github.com/ipfs/go-ipns/pb"
"github.com/ipfs/go-path"
opts "github.com/ipfs/interface-go-ipfs-core/options/namesys"

keystore "github.com/ipfs/go-ipfs-keystore"
"github.com/ipfs/go-namesys"
Expand Down Expand Up @@ -103,7 +104,7 @@ func TestRepublish(t *testing.T) {
timeout := time.Second
for {
expiration = time.Now().Add(time.Second)
err := rp.PublishWithEOL(ctx, publisher.privKey, p, expiration)
err := rp.Publish(ctx, publisher.privKey, p, opts.PublishWithEOL(expiration))
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -179,7 +180,7 @@ func TestLongEOLRepublish(t *testing.T) {
name := "/ipns/" + publisher.id

expiration := time.Now().Add(time.Hour)
err := rp.PublishWithEOL(ctx, publisher.privKey, p, expiration)
err := rp.Publish(ctx, publisher.privKey, p, opts.PublishWithEOL(expiration))
if err != nil {
t.Fatal(err)
}
Expand Down