From b5861cdf3280faf6f27d38bff5de4bf39ebf0c41 Mon Sep 17 00:00:00 2001 From: Hector Sanjuan Date: Fri, 19 Feb 2021 16:48:56 +0100 Subject: [PATCH 1/4] Fix staticcheck issues --- namesys_test.go | 4 +++- resolve_test.go | 7 +++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/namesys_test.go b/namesys_test.go index cc0ca69..68ff467 100644 --- a/namesys_test.go +++ b/namesys_test.go @@ -120,6 +120,8 @@ func TestPublishWithCache0(t *testing.T) { } } +type ctxKey string + func TestPublishWithTTL(t *testing.T) { dst := dssync.MutexWrap(ds.NewMapDatastore()) priv, _, err := ci.GenerateKeyPair(ci.RSA, 2048) @@ -150,7 +152,7 @@ func TestPublishWithTTL(t *testing.T) { ttl := 1 * time.Second eol := time.Now().Add(2 * time.Second) - ctx := context.WithValue(context.Background(), "ipns-publish-ttl", ttl) + ctx := context.WithValue(context.Background(), ctxKey("ipns-publish-ttl"), ttl) err = nsys.Publish(ctx, priv, p) if err != nil { t.Fatal(err) diff --git a/resolve_test.go b/resolve_test.go index 4f92a2d..f8b2436 100644 --- a/resolve_test.go +++ b/resolve_test.go @@ -11,14 +11,13 @@ import ( mockrouting "github.com/ipfs/go-ipfs-routing/mock" ipns "github.com/ipfs/go-ipns" path "github.com/ipfs/go-path" - testutil "github.com/libp2p/go-libp2p-testing/net" tnet "github.com/libp2p/go-libp2p-testing/net" ) func TestRoutingResolve(t *testing.T) { dstore := dssync.MutexWrap(ds.NewMapDatastore()) serv := mockrouting.NewServer() - id := testutil.RandIdentityOrFatal(t) + id := tnet.RandIdentityOrFatal(t) d := serv.ClientWithDatastore(context.Background(), id, dstore) resolver := NewIpnsResolver(d) @@ -44,7 +43,7 @@ func TestRoutingResolve(t *testing.T) { func TestPrexistingExpiredRecord(t *testing.T) { dstore := dssync.MutexWrap(ds.NewMapDatastore()) - d := mockrouting.NewServer().ClientWithDatastore(context.Background(), testutil.RandIdentityOrFatal(t), dstore) + d := mockrouting.NewServer().ClientWithDatastore(context.Background(), tnet.RandIdentityOrFatal(t), dstore) resolver := NewIpnsResolver(d) publisher := NewIpnsPublisher(d, dstore) @@ -78,7 +77,7 @@ func TestPrexistingExpiredRecord(t *testing.T) { func TestPrexistingRecord(t *testing.T) { dstore := dssync.MutexWrap(ds.NewMapDatastore()) - d := mockrouting.NewServer().ClientWithDatastore(context.Background(), testutil.RandIdentityOrFatal(t), dstore) + d := mockrouting.NewServer().ClientWithDatastore(context.Background(), tnet.RandIdentityOrFatal(t), dstore) resolver := NewIpnsResolver(d) publisher := NewIpnsPublisher(d, dstore) From 0d5c0a8201e49123b5a6e9d9f743a89406b89533 Mon Sep 17 00:00:00 2001 From: Hector Sanjuan Date: Fri, 19 Feb 2021 17:56:39 +0100 Subject: [PATCH 2/4] golint: Improve package documentation and readme. --- README.md | 14 +++++++++++--- dns.go | 5 +++-- interface.go | 2 +- namesys.go | 13 +++++++++++++ proquint.go | 2 ++ publisher.go | 15 ++++++++++++++- republisher/repub.go | 6 ++++++ 7 files changed, 50 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index ab950f4..5c17728 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,20 @@ # go-namesys -[![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io) +[![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://protocol.ai) [![](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io/) -[![standard-readme compliant](https://img.shields.io/badge/standard--readme-OK-green.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme) +[![Go Reference](https://pkg.go.dev/badge/github.com/ipfs/go-namesys.svg)](https://pkg.go.dev/github.com/ipfs/go-namesys) [![Travis CI](https://travis-ci.com/ipfs/go-namesys.svg?branch=master)](https://travis-ci.com/ipfs/go-namesys) > go-namesys provides publish and resolution support for the /ipns/ namespace -go-namesys allows to publish and resolve IPNS records or dnslink domain names. +Package namesys defines `Resolver` and `Publisher` interfaces for IPNS paths, that is, paths in the form of `/ipns/`. A "resolved" IPNS path becomes an `/ipfs/` path. + +Traditionally, these paths would be in the form of `/ipns/peer_id`, which references an IPNS record in a distributed `ValueStore` (usually the IPFS DHT). + +Additionally, the /ipns/ namespace can also be used with domain names that use DNSLink (/ipns/my.domain.example, see https://dnslink.io) and proquint strings. + +The package provides implementations for all three resolvers. ## Table of Contents @@ -29,6 +35,8 @@ go-namesys allows to publish and resolve IPNS records or dnslink domain names. import "github.com/ipfs/go-namesys" ``` +See the [Pkg.go.dev documentation](https://pkg.go.dev/github.com/ipfs/go-namesys) + ## Contribute PRs accepted. diff --git a/dns.go b/dns.go index 738612f..d8a42f2 100644 --- a/dns.go +++ b/dns.go @@ -15,6 +15,7 @@ import ( const ethTLD = "eth" const linkTLD = "link" +// LookupTXTFunc is a generic type for a function that lookups TXT record values. type LookupTXTFunc func(name string) (txt []string, err error) // DNSResolver implements a Resolver on DNS domains @@ -146,10 +147,10 @@ func parseEntry(txt string) (path.Path, error) { return p, nil } - return tryParseDnsLink(txt) + return tryParseDNSLink(txt) } -func tryParseDnsLink(txt string) (path.Path, error) { +func tryParseDNSLink(txt string) (path.Path, error) { parts := strings.SplitN(txt, "=", 2) if len(parts) == 2 && parts[0] == "dnslink" { return path.ParsePath(parts[1]) diff --git a/interface.go b/interface.go index ecd8094..b4136df 100644 --- a/interface.go +++ b/interface.go @@ -50,7 +50,7 @@ var ErrResolveRecursion = errors.New( // ErrPublishFailed signals an error when attempting to publish. var ErrPublishFailed = errors.New("could not publish name") -// Namesys represents a cohesive name publishing and resolving system. +// NameSystem represents a cohesive name publishing and resolving system. // // Publishing a name is the process of establishing a mapping, a key-value // pair, according to naming rules and databases. diff --git a/namesys.go b/namesys.go index 760d04c..ae77771 100644 --- a/namesys.go +++ b/namesys.go @@ -1,3 +1,16 @@ +// Package namesys defines Resolver and Publisher interfaces for IPNS paths, +// that is, IPFS paths in the form of /ipns/. A "resolved" +// IPNS path becomes an /ipfs/ path. +// +// Traditionally, these paths would be in the form of /ipns/peer_id, which +// references an IPNS record in a distributed ValueStore (usually the IPFS +// DHT). +// +// Additionally, the /ipns/ namespace can also be used with domain names that +// use DNSLink (/ipns/my.domain.example, see https://dnslink.io) and proquint +// strings. +// +// The package provides implementations for all three resolvers. package namesys import ( diff --git a/proquint.go b/proquint.go index 63cb62a..b918ec9 100644 --- a/proquint.go +++ b/proquint.go @@ -9,6 +9,8 @@ import ( opts "github.com/ipfs/interface-go-ipfs-core/options/namesys" ) +// ProquintResolver implements the Resolver interface for proquint identifiers +// (see http://arxiv.org/html/0901.4016). type ProquintResolver struct{} // Resolve implements Resolver. diff --git a/publisher.go b/publisher.go index f558eaf..11cc6dc 100644 --- a/publisher.go +++ b/publisher.go @@ -22,6 +22,9 @@ 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 @@ -49,11 +52,13 @@ func (p *IpnsPublisher) Publish(ctx context.Context, k ci.PrivKey, value path.Pa return p.PublishWithEOL(ctx, k, value, time.Now().Add(DefaultRecordEOL)) } +// IpnsDsKey returns a datastore key given an IPNS identifier (peer +// ID). Defines the storage key for IPNS records in the local datastore. func IpnsDsKey(id peer.ID) ds.Key { return ds.NewKey("/ipns/" + base32.RawStdEncoding.EncodeToString([]byte(id))) } -// PublishedNames returns the latest IPNS records published by this node and +// ListPublished returns the latest IPNS records published by this node and // their expiration times. // // This method will not search the routing system for records published by other @@ -212,6 +217,10 @@ func checkCtxTTL(ctx context.Context) (time.Duration, bool) { return d, ok } +// PutRecordToRouting publishes the given entry using the provided ValueStore, +// using the ID associated to the provided public key and embedding the public +// key in the IPNS entry when it cannot be extracted from the ID. In that +// case, it calls PublishPublicKey in addition to PublishEntry. func PutRecordToRouting(ctx context.Context, r routing.ValueStore, k ci.PubKey, entry *pb.IpnsEntry) error { ctx, cancel := context.WithCancel(ctx) defer cancel() @@ -260,6 +269,8 @@ func waitOnErrChan(ctx context.Context, errs chan error) error { } } +// PublishPublicKey stores the given public key in the ValueStore with the +// given key. func PublishPublicKey(ctx context.Context, r routing.ValueStore, k string, pubk ci.PubKey) error { log.Debugf("Storing pubkey at: %s", k) pkbytes, err := pubk.Bytes() @@ -271,6 +282,8 @@ func PublishPublicKey(ctx context.Context, r routing.ValueStore, k string, pubk return r.PutValue(ctx, k, pkbytes) } +// PublishEntry stores the given IpnsEntry in the ValueStore with the given +// ipnskey. func PublishEntry(ctx context.Context, r routing.ValueStore, ipnskey string, rec *pb.IpnsEntry) error { data, err := proto.Marshal(rec) if err != nil { diff --git a/republisher/repub.go b/republisher/repub.go index 6e2f862..4ba5d48 100644 --- a/republisher/repub.go +++ b/republisher/repub.go @@ -1,3 +1,5 @@ +// Package republisher provides a utility to automatically re-publish IPNS +// records related to the keys in a Keystore. package republisher import ( @@ -36,6 +38,8 @@ var FailureRetryInterval = time.Minute * 5 // DefaultRecordLifetime is the default lifetime for IPNS records const DefaultRecordLifetime = time.Hour * 24 +// Republisher facilitates the regular publishing of all the IPNS records +// associated to keys in a Keystore. type Republisher struct { ns namesys.Publisher ds ds.Datastore @@ -60,6 +64,8 @@ func NewRepublisher(ns namesys.Publisher, ds ds.Datastore, self ic.PrivKey, ks k } } +// Run starts the republisher facility. It can be stopped by stopping the +// provided proc. func (rp *Republisher) Run(proc goprocess.Process) { timer := time.NewTimer(InitialRebroadcastDelay) defer timer.Stop() From 71c6e11b7f804a4053db4eaf0dd6c7cb3369ae6b Mon Sep 17 00:00:00 2001 From: Hector Sanjuan Date: Fri, 19 Feb 2021 18:08:36 +0100 Subject: [PATCH 3/4] Revert staticcheck fix as it breaks things. --- namesys_test.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/namesys_test.go b/namesys_test.go index 68ff467..cc0ca69 100644 --- a/namesys_test.go +++ b/namesys_test.go @@ -120,8 +120,6 @@ func TestPublishWithCache0(t *testing.T) { } } -type ctxKey string - func TestPublishWithTTL(t *testing.T) { dst := dssync.MutexWrap(ds.NewMapDatastore()) priv, _, err := ci.GenerateKeyPair(ci.RSA, 2048) @@ -152,7 +150,7 @@ func TestPublishWithTTL(t *testing.T) { ttl := 1 * time.Second eol := time.Now().Add(2 * time.Second) - ctx := context.WithValue(context.Background(), ctxKey("ipns-publish-ttl"), ttl) + ctx := context.WithValue(context.Background(), "ipns-publish-ttl", ttl) err = nsys.Publish(ctx, priv, p) if err != nil { t.Fatal(err) From e738bc0769b2eba77d0ba33e147d97293ba72c94 Mon Sep 17 00:00:00 2001 From: Hector Sanjuan Date: Fri, 19 Feb 2021 21:53:22 +0100 Subject: [PATCH 4/4] Update publisher.go Co-authored-by: Adin Schmahmann --- publisher.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/publisher.go b/publisher.go index 11cc6dc..e2f9e67 100644 --- a/publisher.go +++ b/publisher.go @@ -218,9 +218,8 @@ func checkCtxTTL(ctx context.Context) (time.Duration, bool) { } // PutRecordToRouting publishes the given entry using the provided ValueStore, -// using the ID associated to the provided public key and embedding the public -// key in the IPNS entry when it cannot be extracted from the ID. In that -// case, it calls PublishPublicKey in addition to PublishEntry. +// 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. func PutRecordToRouting(ctx context.Context, r routing.ValueStore, k ci.PubKey, entry *pb.IpnsEntry) error { ctx, cancel := context.WithCancel(ctx) defer cancel()