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

Commit 75d18a4

Browse files
committed
feat: use PublishOptions for publishing IPNS records
1 parent 8e7bf04 commit 75d18a4

File tree

8 files changed

+305
-77
lines changed

8 files changed

+305
-77
lines changed

go.mod

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,17 @@ require (
88
github.com/ipfs/go-ipfs-ds-help v1.1.0
99
github.com/ipfs/go-ipfs-keystore v0.1.0
1010
github.com/ipfs/go-ipfs-routing v0.3.0
11-
github.com/ipfs/go-ipns v0.2.0
11+
github.com/ipfs/go-ipns v0.3.0
1212
github.com/ipfs/go-log v1.0.5
1313
github.com/ipfs/go-path v0.1.1
14-
github.com/ipfs/interface-go-ipfs-core v0.8.0
14+
github.com/ipfs/interface-go-ipfs-core v0.8.3-0.20230124085856-8e5d734998e2
1515
github.com/jbenet/goprocess v0.1.4
1616
github.com/libp2p/go-libp2p v0.23.4
1717
github.com/libp2p/go-libp2p-kad-dht v0.19.0
1818
github.com/libp2p/go-libp2p-record v0.2.0
1919
github.com/libp2p/go-libp2p-testing v0.12.0
2020
github.com/miekg/dns v1.1.50
21-
github.com/multiformats/go-multiaddr v0.7.0
21+
github.com/multiformats/go-multiaddr v0.8.0
2222
github.com/multiformats/go-multiaddr-dns v0.3.1
2323
github.com/multiformats/go-multihash v0.2.1
2424
github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc
@@ -32,6 +32,7 @@ require (
3232
github.com/cespare/xxhash/v2 v2.1.2 // indirect
3333
github.com/containerd/cgroups v1.0.4 // indirect
3434
github.com/coreos/go-systemd/v22 v22.4.0 // indirect
35+
github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 // indirect
3536
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
3637
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect
3738
github.com/docker/go-units v0.5.0 // indirect
@@ -51,9 +52,22 @@ require (
5152
github.com/hashicorp/errwrap v1.1.0 // indirect
5253
github.com/hashicorp/go-multierror v1.1.1 // indirect
5354
github.com/huin/goupnp v1.0.3 // indirect
55+
github.com/ipfs/bbloom v0.0.4 // indirect
56+
github.com/ipfs/go-block-format v0.0.3 // indirect
57+
github.com/ipfs/go-blockservice v0.3.0 // indirect
58+
github.com/ipfs/go-ipfs-blockstore v1.2.0 // indirect
5459
github.com/ipfs/go-ipfs-delay v0.0.1 // indirect
60+
github.com/ipfs/go-ipfs-exchange-interface v0.1.0 // indirect
5561
github.com/ipfs/go-ipfs-util v0.0.2 // indirect
62+
github.com/ipfs/go-ipld-cbor v0.0.5 // indirect
63+
github.com/ipfs/go-ipld-format v0.3.0 // indirect
64+
github.com/ipfs/go-ipld-legacy v0.1.0 // indirect
65+
github.com/ipfs/go-libipfs v0.1.0 // indirect
5666
github.com/ipfs/go-log/v2 v2.5.1 // indirect
67+
github.com/ipfs/go-merkledag v0.6.0 // indirect
68+
github.com/ipfs/go-metrics-interface v0.0.1 // indirect
69+
github.com/ipfs/go-verifcid v0.0.1 // indirect
70+
github.com/ipld/go-codec-dagpb v1.3.0 // indirect
5771
github.com/ipld/go-ipld-prime v0.11.0 // indirect
5872
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
5973
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
@@ -103,6 +117,7 @@ require (
103117
github.com/raulk/go-watchdog v1.3.0 // indirect
104118
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect
105119
github.com/spaolacci/murmur3 v1.1.0 // indirect
120+
github.com/whyrusleeping/cbor-gen v0.0.0-20200123233031-1cdf64d27158 // indirect
106121
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect
107122
go.opencensus.io v0.23.0 // indirect
108123
go.uber.org/atomic v1.10.0 // indirect
@@ -115,6 +130,7 @@ require (
115130
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect
116131
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect
117132
golang.org/x/tools v0.1.12 // indirect
133+
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
118134
google.golang.org/protobuf v1.28.1 // indirect
119135
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
120136
lukechampine.com/blake3 v1.1.7 // indirect

go.sum

Lines changed: 251 additions & 2 deletions
Large diffs are not rendered by default.

interface.go

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ package namesys
3131

3232
import (
3333
"errors"
34-
"time"
3534

3635
"context"
3736

@@ -95,12 +94,7 @@ type Resolver interface {
9594

9695
// Publisher is an object capable of publishing particular names.
9796
type Publisher interface {
98-
9997
// Publish establishes a name-value mapping.
10098
// TODO make this not PrivKey specific.
101-
Publish(ctx context.Context, name ci.PrivKey, value path.Path) error
102-
103-
// TODO: to be replaced by a more generic 'PublishWithValidity' type
104-
// call once the records spec is implemented
105-
PublishWithEOL(ctx context.Context, name ci.PrivKey, value path.Path, eol time.Time) error
99+
Publish(ctx context.Context, name ci.PrivKey, value path.Path, options ...opts.PublishOption) error
106100
}

namesys.go

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -285,34 +285,36 @@ func emitOnceResult(ctx context.Context, outCh chan<- onceResult, r onceResult)
285285
}
286286

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

294-
func (ns *mpns) PublishWithEOL(ctx context.Context, name ci.PrivKey, value path.Path, eol time.Time) error {
295-
ctx, span := StartSpan(ctx, "MPNS.PublishWithEOL", trace.WithAttributes(attribute.String("Value", value.String())))
296-
defer span.End()
292+
// This is a bit hacky. We do this because the EOL is based on the current
293+
// time, but also needed in the end of the function. Therefore, we parse
294+
// the options immediately and add an option PublishWithEOL with the EOL
295+
// calculated in this moment.
296+
publishOpts := opts.ProcessPublishOptions(options)
297+
options = append(options, opts.PublishWithEOL(publishOpts.EOL))
298+
297299
id, err := peer.IDFromPrivateKey(name)
298300
if err != nil {
299301
span.RecordError(err)
300302
return err
301303
}
302304
span.SetAttributes(attribute.String("ID", id.String()))
303-
if err := ns.ipnsPublisher.PublishWithEOL(ctx, name, value, eol); err != nil {
305+
if err := ns.ipnsPublisher.Publish(ctx, name, value, options...); err != nil {
304306
// Invalidate the cache. Publishing may _partially_ succeed but
305307
// still return an error.
306308
ns.cacheInvalidate(string(id))
307309
span.RecordError(err)
308310
return err
309311
}
310312
ttl := DefaultResolverCacheTTL
311-
if setTTL, ok := checkCtxTTL(ctx); ok {
312-
ttl = setTTL
313+
if publishOpts.TTL >= 0 {
314+
ttl = publishOpts.TTL
313315
}
314-
if ttEol := time.Until(eol); ttEol < ttl {
315-
ttl = ttEol
316+
if ttEOL := time.Until(publishOpts.EOL); ttEOL < ttl {
317+
ttl = ttEOL
316318
}
317319
ns.cacheSet(string(id), value, ttl)
318320
return nil

namesys_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,7 @@ func TestPublishWithTTL(t *testing.T) {
166166
ttl := 1 * time.Second
167167
eol := time.Now().Add(2 * time.Second)
168168

169-
ctx := ContextWithTTL(context.Background(), ttl)
170-
err = nsys.Publish(ctx, priv, p)
169+
err = nsys.Publish(context.Background(), priv, p, opts.PublishWithEOL(eol), opts.PublishWithTTL(ttl))
171170
if err != nil {
172171
t.Fatal(err)
173172
}

publisher.go

Lines changed: 15 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/ipfs/go-ipns"
1313
pb "github.com/ipfs/go-ipns/pb"
1414
"github.com/ipfs/go-path"
15+
opts "github.com/ipfs/interface-go-ipfs-core/options/namesys"
1516
"github.com/libp2p/go-libp2p/core/crypto"
1617
"github.com/libp2p/go-libp2p/core/peer"
1718
"github.com/libp2p/go-libp2p/core/routing"
@@ -22,11 +23,6 @@ import (
2223

2324
const ipnsPrefix = "/ipns/"
2425

25-
// DefaultRecordEOL specifies the time that the network will cache IPNS
26-
// records after being publihsed. Records should be re-published before this
27-
// interval expires.
28-
const DefaultRecordEOL = 24 * time.Hour
29-
3026
// IpnsPublisher is capable of publishing and resolving names to the IPFS
3127
// routing system.
3228
type IpnsPublisher struct {
@@ -47,9 +43,18 @@ func NewIpnsPublisher(route routing.ValueStore, ds ds.Datastore) *IpnsPublisher
4743

4844
// Publish implements Publisher. Accepts a keypair and a value,
4945
// and publishes it out to the routing system
50-
func (p *IpnsPublisher) Publish(ctx context.Context, k crypto.PrivKey, value path.Path) error {
46+
func (p *IpnsPublisher) Publish(ctx context.Context, k crypto.PrivKey, value path.Path, options ...opts.PublishOption) error {
5147
log.Debugf("Publish %s", value)
52-
return p.PublishWithEOL(ctx, k, value, time.Now().Add(DefaultRecordEOL))
48+
49+
ctx, span := StartSpan(ctx, "IpnsPublisher.Publish", trace.WithAttributes(attribute.String("Value", value.String())))
50+
defer span.End()
51+
52+
record, err := p.updateRecord(ctx, k, value, options...)
53+
if err != nil {
54+
return err
55+
}
56+
57+
return PutRecordToRouting(ctx, p.routing, k.GetPublic(), record)
5358
}
5459

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

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

167-
// Set the TTL
168-
// TODO: Make this less hacky.
169-
ttl, _ := checkCtxTTL(ctx)
172+
opts := opts.ProcessPublishOptions(options)
170173

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

193-
// PublishWithEOL is a temporary stand in for the ipns records implementation
194-
// see here for more details: https://github.com/ipfs/specs/tree/master/records
195-
func (p *IpnsPublisher) PublishWithEOL(ctx context.Context, k crypto.PrivKey, value path.Path, eol time.Time) error {
196-
ctx, span := StartSpan(ctx, "IpnsPublisher.PublishWithEOL", trace.WithAttributes(attribute.String("Value", value.String())))
197-
defer span.End()
198-
199-
record, err := p.updateRecord(ctx, k, value, eol)
200-
if err != nil {
201-
return err
202-
}
203-
204-
return PutRecordToRouting(ctx, p.routing, k.GetPublic(), record)
205-
}
206-
207-
// setting the TTL on published records is an experimental feature.
208-
// as such, i'm using the context to wire it through to avoid changing too
209-
// much code along the way.
210-
func checkCtxTTL(ctx context.Context) (time.Duration, bool) {
211-
v := ctx.Value(ttlContextKey)
212-
if v == nil {
213-
return 0, false
214-
}
215-
216-
d, ok := v.(time.Duration)
217-
return d, ok
218-
}
219-
220196
// PutRecordToRouting publishes the given entry using the provided ValueStore,
221197
// keyed on the ID associated with the provided public key. The public key is
222198
// also made available to the routing system so that entries can be verified.
@@ -307,13 +283,3 @@ func PublishEntry(ctx context.Context, r routing.ValueStore, ipnskey string, rec
307283
func PkKeyForID(id peer.ID) string {
308284
return "/pk/" + string(id)
309285
}
310-
311-
// contextKey is a private comparable type used to hold value keys in contexts
312-
type contextKey string
313-
314-
var ttlContextKey contextKey = "ipns-publish-ttl"
315-
316-
// ContextWithTTL returns a copy of the parent context with an added value representing the TTL
317-
func ContextWithTTL(ctx context.Context, ttl time.Duration) context.Context {
318-
return context.WithValue(context.Background(), ttlContextKey, ttl)
319-
}

republisher/repub.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/ipfs/go-ipns"
1818
pb "github.com/ipfs/go-ipns/pb"
1919
logging "github.com/ipfs/go-log"
20+
opts "github.com/ipfs/interface-go-ipfs-core/options/namesys"
2021
"github.com/jbenet/goprocess"
2122
gpctx "github.com/jbenet/goprocess/context"
2223
ic "github.com/libp2p/go-libp2p/core/crypto"
@@ -161,7 +162,7 @@ func (rp *Republisher) republishEntry(ctx context.Context, priv ic.PrivKey) erro
161162
if prevEol.After(eol) {
162163
eol = prevEol
163164
}
164-
err = rp.ns.PublishWithEOL(ctx, priv, p, eol)
165+
err = rp.ns.Publish(ctx, priv, p, opts.PublishWithEOL(eol))
165166
span.RecordError(err)
166167
return err
167168
}

republisher/repub_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"github.com/ipfs/go-ipns"
2222
ipns_pb "github.com/ipfs/go-ipns/pb"
2323
"github.com/ipfs/go-path"
24+
opts "github.com/ipfs/interface-go-ipfs-core/options/namesys"
2425

2526
keystore "github.com/ipfs/go-ipfs-keystore"
2627
"github.com/ipfs/go-namesys"
@@ -103,7 +104,7 @@ func TestRepublish(t *testing.T) {
103104
timeout := time.Second
104105
for {
105106
expiration = time.Now().Add(time.Second)
106-
err := rp.PublishWithEOL(ctx, publisher.privKey, p, expiration)
107+
err := rp.Publish(ctx, publisher.privKey, p, opts.PublishWithEOL(expiration))
107108
if err != nil {
108109
t.Fatal(err)
109110
}
@@ -179,7 +180,7 @@ func TestLongEOLRepublish(t *testing.T) {
179180
name := "/ipns/" + publisher.id
180181

181182
expiration := time.Now().Add(time.Hour)
182-
err := rp.PublishWithEOL(ctx, publisher.privKey, p, expiration)
183+
err := rp.Publish(ctx, publisher.privKey, p, opts.PublishWithEOL(expiration))
183184
if err != nil {
184185
t.Fatal(err)
185186
}

0 commit comments

Comments
 (0)