Skip to content

Commit 94e7f79

Browse files
hacdiaslidel
andauthored
fix(ipns): honour --ttl flag in 'ipfs name publish' (#9471)
* fix: honour --ttl flag in 'ipfs name publish' * docs(cli): ipfs name inspect --help Co-authored-by: Marcin Rataj <[email protected]>
1 parent 9652f24 commit 94e7f79

File tree

9 files changed

+269
-30
lines changed

9 files changed

+269
-30
lines changed

core/commands/commands_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ func TestCommands(t *testing.T) {
173173
"/multibase/transcode",
174174
"/multibase/list",
175175
"/name",
176+
"/name/inspect",
176177
"/name/publish",
177178
"/name/pubsub",
178179
"/name/pubsub/cancel",

core/commands/name/name.go

+218-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,25 @@
11
package name
22

33
import (
4-
"github.com/ipfs/go-ipfs-cmds"
4+
"bytes"
5+
"encoding/json"
6+
"fmt"
7+
"io"
8+
"strings"
9+
"text/tabwriter"
10+
"time"
11+
12+
"github.com/gogo/protobuf/proto"
13+
cmds "github.com/ipfs/go-ipfs-cmds"
14+
"github.com/ipfs/go-ipns"
15+
ipns_pb "github.com/ipfs/go-ipns/pb"
16+
cmdenv "github.com/ipfs/kubo/core/commands/cmdenv"
17+
"github.com/ipld/go-ipld-prime"
18+
"github.com/ipld/go-ipld-prime/codec/dagcbor"
19+
"github.com/ipld/go-ipld-prime/codec/dagjson"
20+
ic "github.com/libp2p/go-libp2p/core/crypto"
21+
"github.com/libp2p/go-libp2p/core/peer"
22+
mbase "github.com/multiformats/go-multibase"
523
)
624

725
type IpnsEntry struct {
@@ -62,5 +80,204 @@ Resolve the value of a dnslink:
6280
"publish": PublishCmd,
6381
"resolve": IpnsCmd,
6482
"pubsub": IpnsPubsubCmd,
83+
"inspect": IpnsInspectCmd,
84+
},
85+
}
86+
87+
type IpnsInspectValidation struct {
88+
Valid bool
89+
Reason string
90+
PublicKey peer.ID
91+
}
92+
93+
// IpnsInspectEntry contains the deserialized values from an IPNS Entry:
94+
// https://github.com/ipfs/specs/blob/main/ipns/IPNS.md#record-serialization-format
95+
type IpnsInspectEntry struct {
96+
Value string
97+
ValidityType *ipns_pb.IpnsEntry_ValidityType
98+
Validity *time.Time
99+
Sequence uint64
100+
TTL *uint64
101+
PublicKey string
102+
SignatureV1 string
103+
SignatureV2 string
104+
Data interface{}
105+
}
106+
107+
type IpnsInspectResult struct {
108+
Entry IpnsInspectEntry
109+
Validation *IpnsInspectValidation
110+
}
111+
112+
var IpnsInspectCmd = &cmds.Command{
113+
Status: cmds.Experimental,
114+
Helptext: cmds.HelpText{
115+
Tagline: "Inspects an IPNS Record",
116+
ShortDescription: `
117+
Prints values inside of IPNS Record protobuf and its DAG-CBOR Data field.
118+
Passing --verify will verify signature against provided public key.
119+
`,
120+
LongDescription: `
121+
Prints values inside of IPNS Record protobuf and its DAG-CBOR Data field.
122+
123+
The input can be a file or STDIN, the output can be JSON:
124+
125+
$ ipfs routing get "/ipns/$PEERID" > ipns_record
126+
$ ipfs name inspect --enc=json < ipns_record
127+
128+
Values in PublicKey, SignatureV1 and SignatureV2 fields are raw bytes encoded
129+
in Multibase. The Data field is DAG-CBOR represented as DAG-JSON.
130+
131+
Passing --verify will verify signature against provided public key.
132+
133+
`,
134+
},
135+
Arguments: []cmds.Argument{
136+
cmds.FileArg("record", true, false, "The IPNS record payload to be verified.").EnableStdin(),
137+
},
138+
Options: []cmds.Option{
139+
cmds.StringOption("verify", "CID of the public IPNS key to validate against."),
140+
},
141+
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
142+
file, err := cmdenv.GetFileArg(req.Files.Entries())
143+
if err != nil {
144+
return err
145+
}
146+
defer file.Close()
147+
148+
var b bytes.Buffer
149+
150+
_, err = io.Copy(&b, file)
151+
if err != nil {
152+
return err
153+
}
154+
155+
var entry ipns_pb.IpnsEntry
156+
err = proto.Unmarshal(b.Bytes(), &entry)
157+
if err != nil {
158+
return err
159+
}
160+
161+
encoder, err := mbase.EncoderByName("base64")
162+
if err != nil {
163+
return err
164+
}
165+
166+
result := &IpnsInspectResult{
167+
Entry: IpnsInspectEntry{
168+
Value: string(entry.Value),
169+
ValidityType: entry.ValidityType,
170+
Sequence: *entry.Sequence,
171+
TTL: entry.Ttl,
172+
PublicKey: encoder.Encode(entry.PubKey),
173+
SignatureV1: encoder.Encode(entry.SignatureV1),
174+
SignatureV2: encoder.Encode(entry.SignatureV2),
175+
Data: nil,
176+
},
177+
}
178+
179+
if len(entry.Data) != 0 {
180+
// This is hacky. The variable node (datamodel.Node) doesn't directly marshal
181+
// to JSON. Therefore, we need to first decode from DAG-CBOR, then encode in
182+
// DAG-JSON and finally unmarshal it from JSON. Since DAG-JSON is a subset
183+
// of JSON, that should work. Then, we can store the final value in the
184+
// result.Entry.Data for further inspection.
185+
node, err := ipld.Decode(entry.Data, dagcbor.Decode)
186+
if err != nil {
187+
return err
188+
}
189+
190+
var buf bytes.Buffer
191+
err = dagjson.Encode(node, &buf)
192+
if err != nil {
193+
return err
194+
}
195+
196+
err = json.Unmarshal(buf.Bytes(), &result.Entry.Data)
197+
if err != nil {
198+
return err
199+
}
200+
}
201+
202+
validity, err := ipns.GetEOL(&entry)
203+
if err == nil {
204+
result.Entry.Validity = &validity
205+
}
206+
207+
verify, ok := req.Options["verify"].(string)
208+
if ok {
209+
key := strings.TrimPrefix(verify, "/ipns/")
210+
id, err := peer.Decode(key)
211+
if err != nil {
212+
return err
213+
}
214+
215+
result.Validation = &IpnsInspectValidation{
216+
PublicKey: id,
217+
}
218+
219+
pub, err := id.ExtractPublicKey()
220+
if err != nil {
221+
// Make sure it works with all those RSA that cannot be embedded into the
222+
// Peer ID.
223+
if len(entry.PubKey) > 0 {
224+
pub, err = ic.UnmarshalPublicKey(entry.PubKey)
225+
}
226+
}
227+
if err != nil {
228+
return err
229+
}
230+
231+
err = ipns.Validate(pub, &entry)
232+
if err == nil {
233+
result.Validation.Valid = true
234+
} else {
235+
result.Validation.Reason = err.Error()
236+
}
237+
}
238+
239+
return cmds.EmitOnce(res, result)
240+
},
241+
Type: IpnsInspectResult{},
242+
Encoders: cmds.EncoderMap{
243+
cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *IpnsInspectResult) error {
244+
tw := tabwriter.NewWriter(w, 0, 0, 1, ' ', 0)
245+
defer tw.Flush()
246+
247+
fmt.Fprintf(tw, "Value:\t%q\n", string(out.Entry.Value))
248+
fmt.Fprintf(tw, "Validity Type:\t%q\n", out.Entry.ValidityType)
249+
if out.Entry.Validity != nil {
250+
fmt.Fprintf(tw, "Validity:\t%s\n", out.Entry.Validity.Format(time.RFC3339Nano))
251+
}
252+
fmt.Fprintf(tw, "Sequence:\t%d\n", out.Entry.Sequence)
253+
if out.Entry.TTL != nil {
254+
fmt.Fprintf(tw, "TTL:\t%d\n", *out.Entry.TTL)
255+
}
256+
fmt.Fprintf(tw, "PublicKey:\t%q\n", out.Entry.PublicKey)
257+
fmt.Fprintf(tw, "Signature V1:\t%q\n", out.Entry.SignatureV1)
258+
fmt.Fprintf(tw, "Signature V2:\t%q\n", out.Entry.SignatureV2)
259+
260+
data, err := json.Marshal(out.Entry.Data)
261+
if err != nil {
262+
return err
263+
}
264+
fmt.Fprintf(tw, "Data:\t%s\n", string(data))
265+
266+
if out.Validation == nil {
267+
tw.Flush()
268+
fmt.Fprintf(w, "\nThis record was not validated.\n")
269+
} else {
270+
tw.Flush()
271+
fmt.Fprintf(w, "\nValidation results:\n")
272+
273+
fmt.Fprintf(tw, "\tValid:\t%v\n", out.Validation.Valid)
274+
if out.Validation.Reason != "" {
275+
fmt.Fprintf(tw, "\tReason:\t%s\n", out.Validation.Reason)
276+
}
277+
fmt.Fprintf(tw, "\tPublicKey:\t%s\n", out.Validation.PublicKey)
278+
}
279+
280+
return nil
281+
}),
65282
},
66283
}

core/coreapi/name.go

+9-6
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
ipath "github.com/ipfs/go-path"
1616
coreiface "github.com/ipfs/interface-go-ipfs-core"
1717
caopts "github.com/ipfs/interface-go-ipfs-core/options"
18+
nsopts "github.com/ipfs/interface-go-ipfs-core/options/namesys"
1819
path "github.com/ipfs/interface-go-ipfs-core/path"
1920
ci "github.com/libp2p/go-libp2p/core/crypto"
2021
peer "github.com/libp2p/go-libp2p/core/peer"
@@ -37,8 +38,6 @@ func (e *ipnsEntry) Value() path.Path {
3738
return e.value
3839
}
3940

40-
type requestContextKey string
41-
4241
// Publish announces new IPNS name and returns the new IPNS entry.
4342
func (api *NameAPI) Publish(ctx context.Context, p path.Path, opts ...caopts.NamePublishOption) (coreiface.IpnsEntry, error) {
4443
ctx, span := tracing.Span(ctx, "CoreAPI.NameAPI", "Publish", trace.WithAttributes(attribute.String("path", p.String())))
@@ -76,13 +75,17 @@ func (api *NameAPI) Publish(ctx context.Context, p path.Path, opts ...caopts.Nam
7675
return nil, err
7776
}
7877

78+
eol := time.Now().Add(options.ValidTime)
79+
80+
publishOptions := []nsopts.PublishOption{
81+
nsopts.PublishWithEOL(eol),
82+
}
83+
7984
if options.TTL != nil {
80-
// nolint: staticcheck // non-backward compatible change
81-
ctx = context.WithValue(ctx, requestContextKey("ipns-publish-ttl"), *options.TTL)
85+
publishOptions = append(publishOptions, nsopts.PublishWithTTL(*options.TTL))
8286
}
8387

84-
eol := time.Now().Add(options.ValidTime)
85-
err = api.namesys.PublishWithEOL(ctx, k, pth, eol)
88+
err = api.namesys.Publish(ctx, k, pth, publishOptions...)
8689
if err != nil {
8790
return nil, err
8891
}

core/corehttp/gateway_test.go

+1-6
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
"regexp"
1010
"strings"
1111
"testing"
12-
"time"
1312

1413
namesys "github.com/ipfs/go-namesys"
1514
version "github.com/ipfs/kubo"
@@ -68,11 +67,7 @@ func (m mockNamesys) ResolveAsync(ctx context.Context, name string, opts ...nsop
6867
return out
6968
}
7069

71-
func (m mockNamesys) Publish(ctx context.Context, name ci.PrivKey, value path.Path) error {
72-
return errors.New("not implemented for mockNamesys")
73-
}
74-
75-
func (m mockNamesys) PublishWithEOL(ctx context.Context, name ci.PrivKey, value path.Path, _ time.Time) error {
70+
func (m mockNamesys) Publish(ctx context.Context, name ci.PrivKey, value path.Path, opts ...nsopts.PublishOption) error {
7671
return errors.New("not implemented for mockNamesys")
7772
}
7873

docs/examples/kubo-as-a-library/go.mod

+4-4
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ replace github.com/ipfs/kubo => ./../../..
88

99
require (
1010
github.com/ipfs/go-libipfs v0.3.0
11-
github.com/ipfs/interface-go-ipfs-core v0.8.2
12-
github.com/ipfs/kubo v0.14.0-rc1
11+
github.com/ipfs/interface-go-ipfs-core v0.9.0
12+
github.com/ipfs/kubo v0.0.0-00010101000000-000000000000
1313
github.com/libp2p/go-libp2p v0.24.2
1414
github.com/multiformats/go-multiaddr v0.8.0
1515
)
@@ -101,7 +101,7 @@ require (
101101
github.com/ipfs/go-merkledag v0.9.0 // indirect
102102
github.com/ipfs/go-metrics-interface v0.0.1 // indirect
103103
github.com/ipfs/go-mfs v0.2.1 // indirect
104-
github.com/ipfs/go-namesys v0.6.0 // indirect
104+
github.com/ipfs/go-namesys v0.7.0 // indirect
105105
github.com/ipfs/go-path v0.3.0 // indirect
106106
github.com/ipfs/go-peertaskqueue v0.8.0 // indirect
107107
github.com/ipfs/go-unixfs v0.4.2 // indirect
@@ -209,7 +209,7 @@ require (
209209
golang.org/x/tools v0.3.0 // indirect
210210
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
211211
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect
212-
google.golang.org/grpc v1.47.0 // indirect
212+
google.golang.org/grpc v1.46.0 // indirect
213213
google.golang.org/protobuf v1.28.1 // indirect
214214
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
215215
lukechampine.com/blake3 v1.1.7 // indirect

docs/examples/kubo-as-a-library/go.sum

+5-6
Original file line numberDiff line numberDiff line change
@@ -575,8 +575,8 @@ github.com/ipfs/go-metrics-interface v0.0.1 h1:j+cpbjYvu4R8zbleSs36gvB7jR+wsL2fG
575575
github.com/ipfs/go-metrics-interface v0.0.1/go.mod h1:6s6euYU4zowdslK0GKHmqaIZ3j/b/tL7HTWtJ4VPgWY=
576576
github.com/ipfs/go-mfs v0.2.1 h1:5jz8+ukAg/z6jTkollzxGzhkl3yxm022Za9f2nL5ab8=
577577
github.com/ipfs/go-mfs v0.2.1/go.mod h1:Woj80iuw4ajDnIP6+seRaoHpPsc9hmL0pk/nDNDWP88=
578-
github.com/ipfs/go-namesys v0.6.0 h1:w4+Wq9bCILnuZRT1RBBdzZQFqtJeDG1duzN8mIDnHZ0=
579-
github.com/ipfs/go-namesys v0.6.0/go.mod h1:0L+3CHBgHxr08Cg+chVo9Ew285PGQfToThjll4g0/d4=
578+
github.com/ipfs/go-namesys v0.7.0 h1:xqosk71GIVRkFDtF2UNRcXn4LdNeo7tzuy8feHD6NbU=
579+
github.com/ipfs/go-namesys v0.7.0/go.mod h1:KYSZBVZG3VJC34EfqqJPG7T48aWgxseoMPAPA5gLyyQ=
580580
github.com/ipfs/go-path v0.2.1/go.mod h1:NOScsVgxfC/eIw4nz6OiGwK42PjaSJ4Y/ZFPn1Xe07I=
581581
github.com/ipfs/go-path v0.3.0 h1:tkjga3MtpXyM5v+3EbRvOHEoo+frwi4oumw5K+KYWyA=
582582
github.com/ipfs/go-path v0.3.0/go.mod h1:NOScsVgxfC/eIw4nz6OiGwK42PjaSJ4Y/ZFPn1Xe07I=
@@ -594,8 +594,8 @@ github.com/ipfs/go-unixfsnode v1.5.1/go.mod h1:ed79DaG9IEuZITJVQn4U6MZDftv6I3ygU
594594
github.com/ipfs/go-verifcid v0.0.1/go.mod h1:5Hrva5KBeIog4A+UpqlaIU+DEstipcJYQQZc0g37pY0=
595595
github.com/ipfs/go-verifcid v0.0.2 h1:XPnUv0XmdH+ZIhLGKg6U2vaPaRDXb9urMyNVCE7uvTs=
596596
github.com/ipfs/go-verifcid v0.0.2/go.mod h1:40cD9x1y4OWnFXbLNJYRe7MpNvWlMn3LZAG5Wb4xnPU=
597-
github.com/ipfs/interface-go-ipfs-core v0.8.2 h1:WDeCBnE4MENVOXbtfwwdAPJ2nBBS8PTmhZWWpm24HRM=
598-
github.com/ipfs/interface-go-ipfs-core v0.8.2/go.mod h1:F3EcmDy53GFkF0H3iEJpfJC320fZ/4G60eftnItrrJ0=
597+
github.com/ipfs/interface-go-ipfs-core v0.9.0 h1:+RCouVtSU/SldgkqWufjIu1smmGaSyKgUIfbYwLukgI=
598+
github.com/ipfs/interface-go-ipfs-core v0.9.0/go.mod h1:F3EcmDy53GFkF0H3iEJpfJC320fZ/4G60eftnItrrJ0=
599599
github.com/ipld/edelweiss v0.2.0 h1:KfAZBP8eeJtrLxLhi7r3N0cBCo7JmwSRhOJp3WSpNjk=
600600
github.com/ipld/edelweiss v0.2.0/go.mod h1:FJAzJRCep4iI8FOFlRriN9n0b7OuX3T/S9++NpBDmA4=
601601
github.com/ipld/go-car v0.4.0 h1:U6W7F1aKF/OJMHovnOVdst2cpQE5GhmHibQkAixgNcQ=
@@ -1779,9 +1779,8 @@ google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG
17791779
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
17801780
google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
17811781
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
1782+
google.golang.org/grpc v1.46.0 h1:oCjezcn6g6A75TGoKYBPgKmVBLexhYLM6MebdrPApP8=
17821783
google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
1783-
google.golang.org/grpc v1.47.0 h1:9n77onPX5F3qfFCqjy9dhn8PbNQsIKeVU04J9G7umt8=
1784-
google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
17851784
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
17861785
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
17871786
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=

go.mod

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ require (
1515
github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5
1616
github.com/fsnotify/fsnotify v1.6.0
1717
github.com/gabriel-vasile/mimetype v1.4.1
18+
github.com/gogo/protobuf v1.3.2
1819
github.com/google/uuid v1.3.0
1920
github.com/hashicorp/go-multierror v1.1.1
2021
github.com/ipfs/go-bitswap v0.11.0
@@ -55,13 +56,13 @@ require (
5556
github.com/ipfs/go-metrics-interface v0.0.1
5657
github.com/ipfs/go-metrics-prometheus v0.0.2
5758
github.com/ipfs/go-mfs v0.2.1
58-
github.com/ipfs/go-namesys v0.6.0
59+
github.com/ipfs/go-namesys v0.7.0
5960
github.com/ipfs/go-path v0.3.0
6061
github.com/ipfs/go-pinning-service-http-client v0.1.2
6162
github.com/ipfs/go-unixfs v0.4.2
6263
github.com/ipfs/go-unixfsnode v1.5.1
6364
github.com/ipfs/go-verifcid v0.0.2
64-
github.com/ipfs/interface-go-ipfs-core v0.8.2
65+
github.com/ipfs/interface-go-ipfs-core v0.9.0
6566
github.com/ipld/go-car v0.4.0
6667
github.com/ipld/go-car/v2 v2.5.1
6768
github.com/ipld/go-codec-dagpb v1.5.0
@@ -142,7 +143,6 @@ require (
142143
github.com/go-logr/stdr v1.2.2 // indirect
143144
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
144145
github.com/godbus/dbus/v5 v5.1.0 // indirect
145-
github.com/gogo/protobuf v1.3.2 // indirect
146146
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
147147
github.com/golang/mock v1.6.0 // indirect
148148
github.com/golang/protobuf v1.5.2 // indirect

0 commit comments

Comments
 (0)