feat(ipns): records with V2-only signatures (#9932)
Henrique Dias committed
Jun 20, 2023 at 14:24 UTC
5156f2116256c45b45720161d1169eab85378f48
21 files changed
+458
-1048
client/rpc/name.go
+7
-17
@@ -10,29 +10,20 @@ import (
10
caopts "github.com/ipfs/boxo/coreiface/options"
11
nsopts "github.com/ipfs/boxo/coreiface/options/namesys"
12
"github.com/ipfs/boxo/coreiface/path"
13
+ "github.com/ipfs/boxo/ipns"
14
)
15
16
type NameAPI HttpApi
17
18
type ipnsEntry struct {
18
- JName string `json:"Name"`
19
- JValue string `json:"Value"`
20
-
21
- path path.Path
22
-}
23
-
24
-func (e *ipnsEntry) Name() string {
25
- return e.JName
19
+ Name string `json:"Name"`
20
+ Value string `json:"Value"`
21
}
22
28
-func (e *ipnsEntry) Value() path.Path {
29
- return e.path
30
-}
31
-
32
-func (api *NameAPI) Publish(ctx context.Context, p path.Path, opts ...caopts.NamePublishOption) (iface.IpnsEntry, error) {
23
+func (api *NameAPI) Publish(ctx context.Context, p path.Path, opts ...caopts.NamePublishOption) (ipns.Name, error) {
24
options, err := caopts.NamePublishOptions(opts...)
25
if err != nil {
35
- return nil, err
26
+ return ipns.Name{}, err
27
}
28
29
req := api.core().Request("name/publish", p.String()).
@@ -47,10 +38,9 @@ func (api *NameAPI) Publish(ctx context.Context, p path.Path, opts ...caopts.Nam
38
39
var out ipnsEntry
40
if err := req.Exec(ctx, &out); err != nil {
50
- return nil, err
41
+ return ipns.Name{}, err
42
}
52
- out.path = path.New(out.JValue)
53
- return &out, out.path.IsValid()
43
+ return ipns.NameFromString(out.Name)
44
}
45
46
func (api *NameAPI) Search(ctx context.Context, name string, opts ...caopts.NameResolveOption) (<-chan iface.IpnsResult, error) {
config/routing.go
+1
-10
@@ -28,7 +28,7 @@ type Router struct {
28
Type RouterType
29
30
// Parameters are extra configuration that this router might need.
31
- // A common one for reframe router is "Endpoint".
31
+ // A common one for HTTP router is "Endpoint".
32
Parameters interface{}
33
}
34
@@ -81,8 +81,6 @@ func (r *RouterParser) UnmarshalJSON(b []byte) error {
81
switch out.Type {
82
case RouterTypeHTTP:
83
p = &HTTPRouterParams{}
84
- case RouterTypeReframe:
85
- p = &ReframeRouterParams{}
84
case RouterTypeDHT:
85
p = &DHTRouterParams{}
86
case RouterTypeSequential:
@@ -106,7 +104,6 @@ func (r *RouterParser) UnmarshalJSON(b []byte) error {
104
type RouterType string
105
106
const (
109
- RouterTypeReframe RouterType = "reframe" // More info here: https://github.com/ipfs/specs/tree/main/reframe . Actually deprecated.
107
RouterTypeHTTP RouterType = "http" // HTTP JSON API for delegated routing systems (IPIP-337).
108
RouterTypeDHT RouterType = "dht" // DHT router.
109
RouterTypeSequential RouterType = "sequential" // Router helper to execute several routers sequentially.
@@ -133,12 +130,6 @@ const (
130
131
var MethodNameList = []MethodName{MethodNameProvide, MethodNameFindPeers, MethodNameFindProviders, MethodNameGetIPNS, MethodNamePutIPNS}
132
136
-type ReframeRouterParams struct {
137
- // Endpoint is the URL where the routing implementation will point to get the information.
138
- // Usually used for reframe Routers.
139
- Endpoint string
140
-}
141
-
133
type HTTPRouterParams struct {
134
// Endpoint is the URL where the routing implementation will point to get the information.
135
Endpoint string
config/routing_test.go
+12
-65
@@ -23,12 +23,6 @@ func TestRouterParameters(t *testing.T) {
23
PublicIPNetwork: false,
24
},
25
}},
26
- "router-reframe": {Router{
27
- Type: RouterTypeReframe,
28
- Parameters: ReframeRouterParams{
29
- Endpoint: "reframe-endpoint",
30
- },
31
- }},
26
"router-parallel": {Router{
27
Type: RouterTypeParallel,
28
Parameters: ComposableRouterParams{
@@ -39,7 +33,7 @@ func TestRouterParameters(t *testing.T) {
33
IgnoreErrors: true,
34
},
35
{
42
- RouterName: "router-reframe",
36
+ RouterName: "router-dht",
37
Timeout: Duration{10 * time.Second},
38
IgnoreErrors: false,
39
ExecuteAfter: &OptionalDuration{&sec},
@@ -58,7 +52,7 @@ func TestRouterParameters(t *testing.T) {
52
IgnoreErrors: true,
53
},
54
{
61
- RouterName: "router-reframe",
55
+ RouterName: "router-dht",
56
Timeout: Duration{10 * time.Second},
57
IgnoreErrors: false,
58
},
@@ -69,7 +63,7 @@ func TestRouterParameters(t *testing.T) {
63
},
64
Methods: Methods{
65
MethodNameFindPeers: {
72
- RouterName: "router-reframe",
66
+ RouterName: "router-dht",
67
},
68
MethodNameFindProviders: {
69
RouterName: "router-dht",
@@ -99,9 +93,6 @@ func TestRouterParameters(t *testing.T) {
93
dhtp := r2.Routers["router-dht"].Parameters
94
require.IsType(&DHTRouterParams{}, dhtp)
95
102
- rp := r2.Routers["router-reframe"].Parameters
103
- require.IsType(&ReframeRouterParams{}, rp)
104
-
96
sp := r2.Routers["router-sequential"].Parameters
97
require.IsType(&ComposableRouterParams{}, sp)
98
@@ -109,68 +100,24 @@ func TestRouterParameters(t *testing.T) {
100
require.IsType(&ComposableRouterParams{}, pp)
101
}
102
112
-func TestRouterMissingParameters(t *testing.T) {
113
- require := require.New(t)
114
-
115
- r := Routing{
116
- Type: NewOptionalString("custom"),
117
- Routers: map[string]RouterParser{
118
- "router-wrong-reframe": {Router{
119
- Type: RouterTypeReframe,
120
- Parameters: DHTRouterParams{
121
- Mode: "auto",
122
- AcceleratedDHTClient: true,
123
- PublicIPNetwork: false,
124
- },
125
- }},
126
- },
127
- Methods: Methods{
128
- MethodNameFindPeers: {
129
- RouterName: "router-wrong-reframe",
130
- },
131
- MethodNameFindProviders: {
132
- RouterName: "router-wrong-reframe",
133
- },
134
- MethodNameGetIPNS: {
135
- RouterName: "router-wrong-reframe",
136
- },
137
- MethodNameProvide: {
138
- RouterName: "router-wrong-reframe",
139
- },
140
- MethodNamePutIPNS: {
141
- RouterName: "router-wrong-reframe",
142
- },
143
- },
144
- }
145
-
146
- out, err := json.Marshal(r)
147
- require.NoError(err)
148
-
149
- r2 := &Routing{}
150
-
151
- err = json.Unmarshal(out, r2)
152
- require.NoError(err)
153
- require.Empty(r2.Routers["router-wrong-reframe"].Parameters.(*ReframeRouterParams).Endpoint)
154
-}
155
-
103
func TestMethods(t *testing.T) {
104
require := require.New(t)
105
106
methodsOK := Methods{
107
MethodNameFindPeers: {
161
- RouterName: "router-wrong-reframe",
108
+ RouterName: "router-wrong",
109
},
110
MethodNameFindProviders: {
164
- RouterName: "router-wrong-reframe",
111
+ RouterName: "router-wrong",
112
},
113
MethodNameGetIPNS: {
167
- RouterName: "router-wrong-reframe",
114
+ RouterName: "router-wrong",
115
},
116
MethodNameProvide: {
170
- RouterName: "router-wrong-reframe",
117
+ RouterName: "router-wrong",
118
},
119
MethodNamePutIPNS: {
173
- RouterName: "router-wrong-reframe",
120
+ RouterName: "router-wrong",
121
},
122
}
123
@@ -178,16 +125,16 @@ func TestMethods(t *testing.T) {
125
126
methodsMissing := Methods{
127
MethodNameFindPeers: {
181
- RouterName: "router-wrong-reframe",
128
+ RouterName: "router-wrong",
129
},
130
MethodNameGetIPNS: {
184
- RouterName: "router-wrong-reframe",
131
+ RouterName: "router-wrong",
132
},
133
MethodNameProvide: {
187
- RouterName: "router-wrong-reframe",
134
+ RouterName: "router-wrong",
135
},
136
MethodNamePutIPNS: {
190
- RouterName: "router-wrong-reframe",
137
+ RouterName: "router-wrong",
138
},
139
}
140
core/commands/dht_test.go
+2
-2
@@ -12,7 +12,7 @@ import (
12
func TestKeyTranslation(t *testing.T) {
13
pid := test.RandPeerIDFatal(t)
14
pkname := namesys.PkKeyForID(pid)
15
- ipnsname := ipns.RecordKey(pid)
15
+ ipnsname := ipns.NameFromPeer(pid).RoutingKey()
16
17
pkk, err := escapeDhtKey("/pk/" + pid.Pretty())
18
if err != nil {
@@ -28,7 +28,7 @@ func TestKeyTranslation(t *testing.T) {
28
t.Fatal("keys didn't match!")
29
}
30
31
- if ipnsk != ipnsname {
31
+ if ipnsk != string(ipnsname) {
32
t.Fatal("keys didn't match!")
33
}
34
}
core/commands/name/name.go
+80
-79
@@ -2,23 +2,18 @@ package name
2
3
import (
4
"bytes"
5
- "encoding/json"
5
+ "encoding/hex"
6
"fmt"
7
"io"
8
- "strings"
8
"text/tabwriter"
9
"time"
10
12
- "github.com/gogo/protobuf/proto"
11
"github.com/ipfs/boxo/ipns"
12
ipns_pb "github.com/ipfs/boxo/ipns/pb"
13
+ "github.com/ipfs/boxo/path"
14
cmds "github.com/ipfs/go-ipfs-cmds"
15
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
- "github.com/libp2p/go-libp2p/core/peer"
21
- mbase "github.com/multiformats/go-multibase"
16
+ "google.golang.org/protobuf/proto"
17
)
18
19
type IpnsEntry struct {
@@ -84,28 +79,27 @@ Resolve the value of a dnslink:
79
}
80
81
type IpnsInspectValidation struct {
87
- Valid bool
88
- Reason string
89
- PublicKey peer.ID
82
+ Valid bool
83
+ Reason string
84
+ Name string
85
}
86
87
// IpnsInspectEntry contains the deserialized values from an IPNS Entry:
88
// https://github.com/ipfs/specs/blob/main/ipns/IPNS.md#record-serialization-format
89
type IpnsInspectEntry struct {
95
- Value string
96
- ValidityType *ipns_pb.IpnsEntry_ValidityType
90
+ Value *path.Path
91
+ ValidityType *ipns.ValidityType
92
Validity *time.Time
98
- Sequence uint64
99
- TTL *uint64
100
- PublicKey string
101
- SignatureV1 string
102
- SignatureV2 string
103
- Data interface{}
93
+ Sequence *uint64
94
+ TTL *time.Duration
95
}
96
97
type IpnsInspectResult struct {
107
- Entry IpnsInspectEntry
108
- Validation *IpnsInspectValidation
98
+ Entry IpnsInspectEntry
99
+ PbSize int
100
+ SignatureType string
101
+ HexDump string
102
+ Validation *IpnsInspectValidation
103
}
104
105
var IpnsInspectCmd = &cmds.Command{
@@ -136,6 +130,7 @@ Passing --verify will verify signature against provided public key.
130
},
131
Options: []cmds.Option{
132
cmds.StringOption("verify", "CID of the public IPNS key to validate against."),
133
+ cmds.BoolOption("dump", "Include a full hex dump of the raw Protobuf record.").WithDefault(true),
134
},
135
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
136
file, err := cmdenv.GetFileArg(req.Files.Entries())
@@ -151,71 +146,62 @@ Passing --verify will verify signature against provided public key.
146
return err
147
}
148
154
- var entry ipns_pb.IpnsEntry
155
- err = proto.Unmarshal(b.Bytes(), &entry)
149
+ rec, err := ipns.UnmarshalRecord(b.Bytes())
150
if err != nil {
151
return err
152
}
153
160
- encoder, err := mbase.EncoderByName("base64")
161
- if err != nil {
162
- return err
154
+ result := &IpnsInspectResult{
155
+ Entry: IpnsInspectEntry{},
156
}
157
165
- result := &IpnsInspectResult{
166
- Entry: IpnsInspectEntry{
167
- Value: string(entry.Value),
168
- ValidityType: entry.ValidityType,
169
- Sequence: *entry.Sequence,
170
- TTL: entry.Ttl,
171
- PublicKey: encoder.Encode(entry.PubKey),
172
- SignatureV1: encoder.Encode(entry.SignatureV1),
173
- SignatureV2: encoder.Encode(entry.SignatureV2),
174
- Data: nil,
175
- },
158
+ // Best effort to get the fields. Show everything we can.
159
+ if v, err := rec.Value(); err == nil {
160
+ result.Entry.Value = &v
161
}
162
178
- if len(entry.Data) != 0 {
179
- // This is hacky. The variable node (datamodel.Node) doesn't directly marshal
180
- // to JSON. Therefore, we need to first decode from DAG-CBOR, then encode in
181
- // DAG-JSON and finally unmarshal it from JSON. Since DAG-JSON is a subset
182
- // of JSON, that should work. Then, we can store the final value in the
183
- // result.Entry.Data for further inspection.
184
- node, err := ipld.Decode(entry.Data, dagcbor.Decode)
185
- if err != nil {
186
- return err
187
- }
163
+ if v, err := rec.ValidityType(); err == nil {
164
+ result.Entry.ValidityType = &v
165
+ }
166
189
- var buf bytes.Buffer
190
- err = dagjson.Encode(node, &buf)
191
- if err != nil {
192
- return err
193
- }
167
+ if v, err := rec.Validity(); err == nil {
168
+ result.Entry.Validity = &v
169
+ }
170
195
- err = json.Unmarshal(buf.Bytes(), &result.Entry.Data)
196
- if err != nil {
197
- return err
198
- }
171
+ if v, err := rec.Sequence(); err == nil {
172
+ result.Entry.Sequence = &v
173
+ }
174
+
175
+ if v, err := rec.TTL(); err == nil {
176
+ result.Entry.TTL = &v
177
}
178
201
- validity, err := ipns.GetEOL(&entry)
202
- if err == nil {
203
- result.Entry.Validity = &validity
179
+ // Here we need the raw protobuf just to decide the version.
180
+ var pbRecord ipns_pb.IpnsRecord
181
+ err = proto.Unmarshal(b.Bytes(), &pbRecord)
182
+ if err != nil {
183
+ return err
184
+ }
185
+ if len(pbRecord.SignatureV1) != 0 || len(pbRecord.Value) != 0 {
186
+ result.SignatureType = "V1+V2"
187
+ } else if pbRecord.Data != nil {
188
+ result.SignatureType = "V2"
189
+ } else {
190
+ result.SignatureType = "Unknown"
191
}
192
+ result.PbSize = proto.Size(&pbRecord)
193
206
- verify, ok := req.Options["verify"].(string)
207
- if ok {
208
- key := strings.TrimPrefix(verify, "/ipns/")
209
- id, err := peer.Decode(key)
194
+ if verify, ok := req.Options["verify"].(string); ok {
195
+ name, err := ipns.NameFromString(verify)
196
if err != nil {
197
return err
198
}
199
200
result.Validation = &IpnsInspectValidation{
215
- PublicKey: id,
201
+ Name: name.String(),
202
}
203
218
- err = ipns.ValidateWithPeerID(id, &entry)
204
+ err = ipns.ValidateWithName(rec, name)
205
if err == nil {
206
result.Validation.Valid = true
207
} else {
@@ -223,6 +209,10 @@ Passing --verify will verify signature against provided public key.
209
}
210
}
211
212
+ if dump, ok := req.Options["dump"].(bool); ok && dump {
213
+ result.HexDump = hex.Dump(b.Bytes())
214
+ }
215
+
216
return cmds.EmitOnce(res, result)
217
},
218
Type: IpnsInspectResult{},
@@ -231,24 +221,28 @@ Passing --verify will verify signature against provided public key.
221
tw := tabwriter.NewWriter(w, 0, 0, 1, ' ', 0)
222
defer tw.Flush()
223
234
- fmt.Fprintf(tw, "Value:\t%q\n", string(out.Entry.Value))
235
- fmt.Fprintf(tw, "Validity Type:\t%q\n", out.Entry.ValidityType)
224
+ if out.Entry.Value != nil {
225
+ fmt.Fprintf(tw, "Value:\t%q\n", out.Entry.Value.String())
226
+ }
227
+
228
+ if out.Entry.ValidityType != nil {
229
+ fmt.Fprintf(tw, "Validity Type:\t%q\n", *out.Entry.ValidityType)
230
+ }
231
+
232
if out.Entry.Validity != nil {
237
- fmt.Fprintf(tw, "Validity:\t%s\n", out.Entry.Validity.Format(time.RFC3339Nano))
233
+ fmt.Fprintf(tw, "Validity:\t%q\n", out.Entry.Validity.Format(time.RFC3339Nano))
234
}
239
- fmt.Fprintf(tw, "Sequence:\t%d\n", out.Entry.Sequence)
240
- if out.Entry.TTL != nil {
241
- fmt.Fprintf(tw, "TTL:\t%d\n", *out.Entry.TTL)
235
+
236
+ if out.Entry.Sequence != nil {
237
+ fmt.Fprintf(tw, "Sequence:\t%d\n", *out.Entry.Sequence)
238
}
243
- fmt.Fprintf(tw, "PublicKey:\t%q\n", out.Entry.PublicKey)
244
- fmt.Fprintf(tw, "Signature V1:\t%q\n", out.Entry.SignatureV1)
245
- fmt.Fprintf(tw, "Signature V2:\t%q\n", out.Entry.SignatureV2)
239
247
- data, err := json.Marshal(out.Entry.Data)
248
- if err != nil {
249
- return err
240
+ if out.Entry.TTL != nil {
241
+ fmt.Fprintf(tw, "TTL:\t%s\n", out.Entry.TTL.String())
242
}
251
- fmt.Fprintf(tw, "Data:\t%s\n", string(data))
243
+
244
+ fmt.Fprintf(tw, "Protobuf Size:\t%d\n", out.PbSize)
245
+ fmt.Fprintf(tw, "Signature Type:\t%s\n", out.SignatureType)
246
247
if out.Validation == nil {
248
tw.Flush()
@@ -261,7 +255,14 @@ Passing --verify will verify signature against provided public key.
255
if out.Validation.Reason != "" {
256
fmt.Fprintf(tw, "\tReason:\t%s\n", out.Validation.Reason)
257
}
264
- fmt.Fprintf(tw, "\tPublicKey:\t%s\n", out.Validation.PublicKey)
258
+ fmt.Fprintf(tw, "\tName:\t%s\n", out.Validation.Name)
259
+ }
260
+
261
+ if out.HexDump != "" {
262
+ tw.Flush()
263
+
264
+ fmt.Fprintf(w, "\nHex Dump:\n")
265
+ fmt.Fprintf(w, out.HexDump)
266
}
267
268
return nil
core/commands/name/publish.go
+7
-14
@@ -13,7 +13,6 @@ import (
13
path "github.com/ipfs/boxo/coreiface/path"
14
cmds "github.com/ipfs/go-ipfs-cmds"
15
ke "github.com/ipfs/kubo/core/commands/keyencode"
16
- peer "github.com/libp2p/go-libp2p/core/peer"
16
)
17
18
var (
@@ -28,6 +27,7 @@ const (
27
ttlOptionName = "ttl"
28
keyOptionName = "key"
29
quieterOptionName = "quieter"
30
+ v1compatOptionName = "v1compat"
31
)
32
33
var PublishCmd = &cmds.Command{
@@ -83,6 +83,7 @@ Alternatively, publish an <ipfs-path> using a valid PeerID (as listed by
83
cmds.StringOption(ttlOptionName, "Time duration this record should be cached for. Uses the same syntax as the lifetime option. (caution: experimental)"),
84
cmds.StringOption(keyOptionName, "k", "Name of the key to be used or a valid PeerID, as listed by 'ipfs key list -l'.").WithDefault("self"),
85
cmds.BoolOption(quieterOptionName, "Q", "Write only final hash."),
86
+ cmds.BoolOption(v1compatOptionName, "Produce a backward-compatible IPNS Record by including fields for both V1 and V2 signatures.").WithDefault(true),
87
ke.OptionIPNSBase,
88
},
89
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
@@ -90,12 +91,9 @@ Alternatively, publish an <ipfs-path> using a valid PeerID (as listed by
91
if err != nil {
92
return err
93
}
93
- keyEnc, err := ke.KeyEncoderFromString(req.Options[ke.OptionIPNSBase.Name()].(string))
94
- if err != nil {
95
- return err
96
- }
94
95
allowOffline, _ := req.Options[allowOfflineOptionName].(bool)
96
+ compatibleWithV1, _ := req.Options[v1compatOptionName].(bool)
97
kname, _ := req.Options[keyOptionName].(string)
98
99
validTimeOpt, _ := req.Options[lifeTimeOptionName].(string)
@@ -108,6 +106,7 @@ Alternatively, publish an <ipfs-path> using a valid PeerID (as listed by
106
options.Name.AllowOffline(allowOffline),
107
options.Name.Key(kname),
108
options.Name.ValidTime(validTime),
109
+ options.Name.CompatibleWithV1(compatibleWithV1),
110
}
111
112
if ttl, found := req.Options[ttlOptionName].(string); found {
@@ -128,7 +127,7 @@ Alternatively, publish an <ipfs-path> using a valid PeerID (as listed by
127
}
128
}
129
131
- out, err := api.Name().Publish(req.Context, p, opts...)
130
+ name, err := api.Name().Publish(req.Context, p, opts...)
131
if err != nil {
132
if err == iface.ErrOffline {
133
err = errAllowOffline
@@ -136,15 +135,9 @@ Alternatively, publish an <ipfs-path> using a valid PeerID (as listed by
135
return err
136
}
137
139
- // parse path, extract cid, re-base cid, reconstruct path
140
- pid, err := peer.Decode(out.Name())
141
- if err != nil {
142
- return err
143
- }
144
-
138
return cmds.EmitOnce(res, &IpnsEntry{
146
- Name: keyEnc.FormatID(pid),
147
- Value: out.Value().String(),
139
+ Name: name.String(),
140
+ Value: p.String(),
141
})
142
},
143
Encoders: cmds.EncoderMap{
core/core_test.go
-296
@@ -1,28 +1,14 @@
1
package core
2
3
import (
4
- "crypto/rand"
5
- "errors"
6
- "fmt"
7
- "net/http/httptest"
8
- "path"
4
"testing"
10
- "time"
5
6
context "context"
7
14
- "github.com/ipfs/boxo/ipns"
15
- "github.com/ipfs/go-cid"
16
- "github.com/ipfs/go-delegated-routing/client"
17
- "github.com/ipfs/kubo/core/node/libp2p"
8
"github.com/ipfs/kubo/repo"
19
- "github.com/libp2p/go-libp2p/core/crypto"
20
- peer "github.com/libp2p/go-libp2p/core/peer"
21
- "github.com/stretchr/testify/require"
9
10
datastore "github.com/ipfs/go-datastore"
11
syncds "github.com/ipfs/go-datastore/sync"
25
- drs "github.com/ipfs/go-delegated-routing/server"
12
config "github.com/ipfs/kubo/config"
13
)
14
@@ -79,285 +65,3 @@ var testIdentity = config.Identity{
65
PeerID: "QmNgdzLieYi8tgfo2WfTUzNVH5hQK9oAYGVf6dxN12NrHt",
66
PrivKey: "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",
67
}
82
-
83
-var errNotSupported = errors.New("method not supported")
84
-
85
-func TestDelegatedRoutingSingle(t *testing.T) {
86
- require := require.New(t)
87
-
88
- pID1, priv1, err := GeneratePeerID()
89
- require.NoError(err)
90
-
91
- pID2, _, err := GeneratePeerID()
92
- require.NoError(err)
93
-
94
- theID := path.Join("/ipns", string(pID1))
95
- theErrorID := path.Join("/ipns", string(pID2))
96
-
97
- d := &delegatedRoutingService{
98
- goodPeerID: pID1,
99
- badPeerID: pID2,
100
- pk1: priv1,
101
- }
102
-
103
- url := StartRoutingServer(t, d)
104
- n := GetNode(t, url)
105
-
106
- ctx := context.Background()
107
-
108
- v, err := n.Routing.GetValue(ctx, theID)
109
- require.NoError(err)
110
- require.NotNil(v)
111
- require.Contains(string(v), "RECORD FROM SERVICE 0")
112
-
113
- v, err = n.Routing.GetValue(ctx, theErrorID)
114
- require.Nil(v)
115
- require.Error(err)
116
-
117
- err = n.Routing.PutValue(ctx, theID, v)
118
- require.NoError(err)
119
-
120
-}
121
-
122
-func TestDelegatedRoutingMulti(t *testing.T) {
123
- require := require.New(t)
124
-
125
- pID1, priv1, err := GeneratePeerID()
126
- require.NoError(err)
127
-
128
- pID2, priv2, err := GeneratePeerID()
129
- require.NoError(err)
130
-
131
- theID1 := path.Join("/ipns", string(pID1))
132
- theID2 := path.Join("/ipns", string(pID2))
133
-
134
- d1 := &delegatedRoutingService{
135
- goodPeerID: pID1,
136
- badPeerID: pID2,
137
- pk1: priv1,
138
- serviceID: 1,
139
- }
140
-
141
- url1 := StartRoutingServer(t, d1)
142
-
143
- d2 := &delegatedRoutingService{
144
- goodPeerID: pID2,
145
- badPeerID: pID1,
146
- pk1: priv2,
147
- serviceID: 2,
148
- }
149
-
150
- url2 := StartRoutingServer(t, d2)
151
-
152
- n := GetNode(t, url1, url2)
153
-
154
- ctx := context.Background()
155
-
156
- v, err := n.Routing.GetValue(ctx, theID1)
157
- require.NoError(err)
158
- require.NotNil(v)
159
- require.Contains(string(v), "RECORD FROM SERVICE 1")
160
-
161
- v, err = n.Routing.GetValue(ctx, theID2)
162
- require.NoError(err)
163
- require.NotNil(v)
164
- require.Contains(string(v), "RECORD FROM SERVICE 2")
165
-}
166
-
167
-func StartRoutingServer(t *testing.T, d drs.DelegatedRoutingService) string {
168
- t.Helper()
169
-
170
- f := drs.DelegatedRoutingAsyncHandler(d)
171
- svr := httptest.NewServer(f)
172
- t.Cleanup(func() {
173
- svr.Close()
174
- })
175
-
176
- return svr.URL
177
-}
178
-
179
-func GetNode(t *testing.T, reframeURLs ...string) *IpfsNode {
180
- t.Helper()
181
-
182
- routers := make(config.Routers)
183
- var routerNames []string
184
- for i, ru := range reframeURLs {
185
- rn := fmt.Sprintf("reframe-%d", i)
186
- routerNames = append(routerNames, rn)
187
- routers[rn] =
188
- config.RouterParser{
189
- Router: config.Router{
190
- Type: config.RouterTypeReframe,
191
- Parameters: &config.ReframeRouterParams{
192
- Endpoint: ru,
193
- },
194
- },
195
- }
196
- }
197
-
198
- var crs []config.ConfigRouter
199
- for _, rn := range routerNames {
200
- crs = append(crs, config.ConfigRouter{
201
- RouterName: rn,
202
- IgnoreErrors: true,
203
- Timeout: config.Duration{Duration: time.Minute},
204
- })
205
- }
206
-
207
- const parallelRouterName = "parallel-router"
208
-
209
- routers[parallelRouterName] = config.RouterParser{
210
- Router: config.Router{
211
- Type: config.RouterTypeParallel,
212
- Parameters: &config.ComposableRouterParams{
213
- Routers: crs,
214
- },
215
- },
216
- }
217
- cfg := config.Config{
218
- Identity: testIdentity,
219
- Addresses: config.Addresses{
220
- Swarm: []string{"/ip4/0.0.0.0/tcp/0", "/ip4/0.0.0.0/udp/0/quic"},
221
- API: []string{"/ip4/127.0.0.1/tcp/0"},
222
- },
223
- Routing: config.Routing{
224
- Type: config.NewOptionalString("custom"),
225
- Routers: routers,
226
- Methods: config.Methods{
227
- config.MethodNameFindPeers: config.Method{
228
- RouterName: parallelRouterName,
229
- },
230
- config.MethodNameFindProviders: config.Method{
231
- RouterName: parallelRouterName,
232
- },
233
- config.MethodNameGetIPNS: config.Method{
234
- RouterName: parallelRouterName,
235
- },
236
- config.MethodNameProvide: config.Method{
237
- RouterName: parallelRouterName,
238
- },
239
- config.MethodNamePutIPNS: config.Method{
240
- RouterName: parallelRouterName,
241
- },
242
- },
243
- },
244
- }
245
-
246
- r := &repo.Mock{
247
- C: cfg,
248
- D: syncds.MutexWrap(datastore.NewMapDatastore()),
249
- }
250
-
251
- n, err := NewNode(context.Background(),
252
- &BuildCfg{
253
- Repo: r,
254
- Online: true,
255
- Routing: libp2p.ConstructDelegatedRouting(
256
- cfg.Routing.Routers,
257
- cfg.Routing.Methods,
258
- cfg.Identity.PeerID,
259
- cfg.Addresses,
260
- cfg.Identity.PrivKey,
261
- ),
262
- },
263
- )
264
- require.NoError(t, err)
265
-
266
- return n
267
-}
268
-
269
-func GeneratePeerID() (peer.ID, crypto.PrivKey, error) {
270
- priv, pk, err := crypto.GenerateEd25519Key(rand.Reader)
271
- if err != nil {
272
- return peer.ID(""), nil, err
273
- }
274
-
275
- pid, err := peer.IDFromPublicKey(pk)
276
- return pid, priv, err
277
-}
278
-
279
-type delegatedRoutingService struct {
280
- goodPeerID, badPeerID peer.ID
281
- pk1 crypto.PrivKey
282
- serviceID int
283
-}
284
-
285
-func (drs *delegatedRoutingService) FindProviders(ctx context.Context, key cid.Cid) (<-chan client.FindProvidersAsyncResult, error) {
286
- return nil, errNotSupported
287
-}
288
-
289
-func (drs *delegatedRoutingService) Provide(ctx context.Context, req *client.ProvideRequest) (<-chan client.ProvideAsyncResult, error) {
290
- return nil, errNotSupported
291
-}
292
-
293
-func (drs *delegatedRoutingService) GetIPNS(ctx context.Context, id []byte) (<-chan client.GetIPNSAsyncResult, error) {
294
- ctx, cancel := context.WithCancel(ctx)
295
- ch := make(chan client.GetIPNSAsyncResult)
296
- go func() {
297
- defer close(ch)
298
- defer cancel()
299
-
300
- var out client.GetIPNSAsyncResult
301
- switch peer.ID(id) {
302
- case drs.goodPeerID:
303
- ie, err := ipns.Create(drs.pk1, []byte(fmt.Sprintf("RECORD FROM SERVICE %d", drs.serviceID)), 0, time.Now().Add(10*time.Hour), 100*time.Hour)
304
- if err != nil {
305
- log.Fatal(err)
306
- }
307
- ieb, err := ie.Marshal()
308
- if err != nil {
309
- log.Fatal(err)
310
- }
311
-
312
- out = client.GetIPNSAsyncResult{
313
- Record: ieb,
314
- Err: nil,
315
- }
316
- case drs.badPeerID:
317
- out = client.GetIPNSAsyncResult{
318
- Record: nil,
319
- Err: errors.New("THE ERROR"),
320
- }
321
- default:
322
- return
323
- }
324
-
325
- select {
326
- case <-ctx.Done():
327
- return
328
- case ch <- out:
329
- }
330
- }()
331
-
332
- return ch, nil
333
-
334
-}
335
-
336
-func (drs *delegatedRoutingService) PutIPNS(ctx context.Context, id []byte, record []byte) (<-chan client.PutIPNSAsyncResult, error) {
337
- ctx, cancel := context.WithCancel(ctx)
338
- ch := make(chan client.PutIPNSAsyncResult)
339
- go func() {
340
- defer close(ch)
341
- defer cancel()
342
-
343
- var out client.PutIPNSAsyncResult
344
- switch peer.ID(id) {
345
- case drs.goodPeerID:
346
- out = client.PutIPNSAsyncResult{}
347
- case drs.badPeerID:
348
- out = client.PutIPNSAsyncResult{
349
- Err: fmt.Errorf("THE ERROR %d", drs.serviceID),
350
- }
351
- default:
352
- return
353
- }
354
-
355
- select {
356
- case <-ctx.Done():
357
- return
358
- case ch <- out:
359
- }
360
- }()
361
-
362
- return ch, nil
363
-}
core/coreapi/name.go
+11
-27
@@ -6,6 +6,7 @@ import (
6
"strings"
7
"time"
8
9
+ "github.com/ipfs/boxo/ipns"
10
keystore "github.com/ipfs/boxo/keystore"
11
"github.com/ipfs/boxo/namesys"
12
"github.com/ipfs/kubo/tracing"
@@ -23,33 +24,18 @@ import (
24
25
type NameAPI CoreAPI
26
26
-type ipnsEntry struct {
27
- name string
28
- value path.Path
29
-}
30
-
31
-// Name returns the ipnsEntry name.
32
-func (e *ipnsEntry) Name() string {
33
- return e.name
34
-}
35
-
36
-// Value returns the ipnsEntry value.
37
-func (e *ipnsEntry) Value() path.Path {
38
- return e.value
39
-}
40
-
27
// Publish announces new IPNS name and returns the new IPNS entry.
42
-func (api *NameAPI) Publish(ctx context.Context, p path.Path, opts ...caopts.NamePublishOption) (coreiface.IpnsEntry, error) {
28
+func (api *NameAPI) Publish(ctx context.Context, p path.Path, opts ...caopts.NamePublishOption) (ipns.Name, error) {
29
ctx, span := tracing.Span(ctx, "CoreAPI.NameAPI", "Publish", trace.WithAttributes(attribute.String("path", p.String())))
30
defer span.End()
31
32
if err := api.checkPublishAllowed(); err != nil {
47
- return nil, err
33
+ return ipns.Name{}, err
34
}
35
36
options, err := caopts.NamePublishOptions(opts...)
37
if err != nil {
52
- return nil, err
38
+ return ipns.Name{}, err
39
}
40
span.SetAttributes(
41
attribute.Bool("allowoffline", options.AllowOffline),
@@ -62,23 +48,24 @@ func (api *NameAPI) Publish(ctx context.Context, p path.Path, opts ...caopts.Nam
48
49
err = api.checkOnline(options.AllowOffline)
50
if err != nil {
65
- return nil, err
51
+ return ipns.Name{}, err
52
}
53
54
pth, err := ipath.ParsePath(p.String())
55
if err != nil {
70
- return nil, err
56
+ return ipns.Name{}, err
57
}
58
59
k, err := keylookup(api.privateKey, api.repo.Keystore(), options.Key)
60
if err != nil {
75
- return nil, err
61
+ return ipns.Name{}, err
62
}
63
64
eol := time.Now().Add(options.ValidTime)
65
66
publishOptions := []nsopts.PublishOption{
67
nsopts.PublishWithEOL(eol),
68
+ nsopts.PublishCompatibleWithV1(options.CompatibleWithV1),
69
}
70
71
if options.TTL != nil {
@@ -87,18 +74,15 @@ func (api *NameAPI) Publish(ctx context.Context, p path.Path, opts ...caopts.Nam
74
75
err = api.namesys.Publish(ctx, k, pth, publishOptions...)
76
if err != nil {
90
- return nil, err
77
+ return ipns.Name{}, err
78
}
79
80
pid, err := peer.IDFromPrivateKey(k)
81
if err != nil {
95
- return nil, err
82
+ return ipns.Name{}, err
83
}
84
98
- return &ipnsEntry{
99
- name: coreiface.FormatKeyID(pid),
100
- value: p,
101
- }, nil
85
+ return ipns.NameFromPeer(pid), nil
86
}
87
88
func (api *NameAPI) Search(ctx context.Context, name string, opts ...caopts.NameResolveOption) (<-chan coreiface.IpnsResult, error) {
docs/changelogs/v0.22.md
+10
@@ -6,6 +6,7 @@
6
7
- [Overview](#overview)
8
- [🔦 Highlights](#-highlights)
9
+ - [`ipfs name publish` now supports V2 only IPNS records](#ipfs-name-publish-now-supports-v2-only-ipns-records)
10
- [📝 Changelog](#-changelog)
11
- [👨👩👧👦 Contributors](#-contributors)
12
@@ -13,6 +14,15 @@
14
15
### 🔦 Highlights
16
17
+#### `ipfs name publish` now supports V2 only IPNS records
18
+
19
+When publishing an IPNS record, you are now able to create v2 only records
20
+by passing `--v1compat=false`. By default, we still create V1+V2 records, such
21
+that there is the highest chance of backwards compatibility. The goal is to move
22
+to V2 only in the future.
23
+
24
+**TODO**: add links to IPIP https://github.com/ipfs/specs/issues/376
25
+
26
### 📝 Changelog
27
28
### 👨👩👧👦 Contributors
docs/examples/kubo-as-a-library/go.mod
+1
-3
@@ -7,7 +7,7 @@ go 1.18
7
replace github.com/ipfs/kubo => ./../../..
8
9
require (
10
- github.com/ipfs/boxo v0.10.1
10
+ github.com/ipfs/boxo v0.10.2-0.20230620120822-417c5f7d61ff
11
github.com/ipfs/kubo v0.0.0-00010101000000-000000000000
12
github.com/libp2p/go-libp2p v0.27.7
13
github.com/multiformats/go-multiaddr v0.9.0
@@ -65,7 +65,6 @@ require (
65
github.com/ipfs/go-cid v0.4.1 // indirect
66
github.com/ipfs/go-cidutil v0.1.0 // indirect
67
github.com/ipfs/go-datastore v0.6.0 // indirect
68
- github.com/ipfs/go-delegated-routing v0.8.0 // indirect
68
github.com/ipfs/go-ds-badger v0.3.0 // indirect
69
github.com/ipfs/go-ds-flatfs v0.5.1 // indirect
70
github.com/ipfs/go-ds-leveldb v0.5.0 // indirect
@@ -88,7 +87,6 @@ require (
87
github.com/ipfs/go-metrics-interface v0.0.1 // indirect
88
github.com/ipfs/go-peertaskqueue v0.8.1 // indirect
89
github.com/ipfs/go-unixfsnode v1.7.1 // indirect
91
- github.com/ipld/edelweiss v0.2.0 // indirect
90
github.com/ipld/go-codec-dagpb v1.6.0 // indirect
91
github.com/ipld/go-ipld-prime v0.20.0 // indirect
92
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
docs/examples/kubo-as-a-library/go.sum
+2
-6
@@ -320,8 +320,8 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:
320
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
321
github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs=
322
github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0=
323
-github.com/ipfs/boxo v0.10.1 h1:q0ZhbyN6iNZLipd6txt1xotCiP/icfvdAQ4YpUi+cL4=
324
-github.com/ipfs/boxo v0.10.1/go.mod h1:1qgKq45mPRCxf4ZPoJV2lnXxyxucigILMJOrQrVivv8=
323
+github.com/ipfs/boxo v0.10.2-0.20230620120822-417c5f7d61ff h1:QnYD2h1e55nX9lSl5k8YVij1VIOICR7lPJlhbKOQjNM=
324
+github.com/ipfs/boxo v0.10.2-0.20230620120822-417c5f7d61ff/go.mod h1:OGMmq97krQBiKx8LRGyf5DgWHeu+PDdIHNN2YnQlWjs=
325
github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA=
326
github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU=
327
github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY=
@@ -344,8 +344,6 @@ github.com/ipfs/go-datastore v0.1.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRV
344
github.com/ipfs/go-datastore v0.5.0/go.mod h1:9zhEApYMTl17C8YDp7JmU7sQZi2/wqiYh73hakZ90Bk=
345
github.com/ipfs/go-datastore v0.6.0 h1:JKyz+Gvz1QEZw0LsX1IBn+JFCJQH4SJVFtM4uWU0Myk=
346
github.com/ipfs/go-datastore v0.6.0/go.mod h1:rt5M3nNbSO/8q1t4LNkLyUwRs8HupMeN/8O4Vn9YAT8=
347
-github.com/ipfs/go-delegated-routing v0.8.0 h1:faiRi4k8YioTxU2x7+pnrLQjR7jIQhGWN2JvCwcQ/aU=
348
-github.com/ipfs/go-delegated-routing v0.8.0/go.mod h1:18Dds6ZoNTsff9S/7R49Nh2t2YNXIIKR/RLQmBZdjjY=
347
github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk=
348
github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps=
349
github.com/ipfs/go-ds-badger v0.0.7/go.mod h1:qt0/fWzZDoPW6jpQeqUjR5kBfhDNB65jd9YlmAvpQBk=
@@ -413,8 +411,6 @@ github.com/ipfs/go-unixfs v0.4.5 h1:wj8JhxvV1G6CD7swACwSKYa+NgtdWC1RUit+gFnymDU=
411
github.com/ipfs/go-unixfsnode v1.7.1 h1:RRxO2b6CSr5UQ/kxnGzaChTjp5LWTdf3Y4n8ANZgB/s=
412
github.com/ipfs/go-unixfsnode v1.7.1/go.mod h1:PVfoyZkX1B34qzT3vJO4nsLUpRCyhnMuHBznRcXirlk=
413
github.com/ipfs/go-verifcid v0.0.2 h1:XPnUv0XmdH+ZIhLGKg6U2vaPaRDXb9urMyNVCE7uvTs=
416
-github.com/ipld/edelweiss v0.2.0 h1:KfAZBP8eeJtrLxLhi7r3N0cBCo7JmwSRhOJp3WSpNjk=
417
-github.com/ipld/edelweiss v0.2.0/go.mod h1:FJAzJRCep4iI8FOFlRriN9n0b7OuX3T/S9++NpBDmA4=
414
github.com/ipld/go-car/v2 v2.9.1-0.20230325062757-fff0e4397a3d h1:22g+x1tgWSXK34i25qjs+afr7basaneEkHaglBshd2g=
415
github.com/ipld/go-codec-dagpb v1.6.0 h1:9nYazfyu9B1p3NAgfVdpRco3Fs2nFC72DqVsMj6rOcc=
416
github.com/ipld/go-codec-dagpb v1.6.0/go.mod h1:ANzFhfP2uMJxRBr8CE+WQWs5UsNa0pYtmKZ+agnUw9s=
go.mod
+4
-6
@@ -13,15 +13,13 @@ require (
13
github.com/elgris/jsondiff v0.0.0-20160530203242-765b5c24c302
14
github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5
15
github.com/fsnotify/fsnotify v1.6.0
16
- github.com/gogo/protobuf v1.3.2
16
github.com/google/uuid v1.3.0
17
github.com/hashicorp/go-multierror v1.1.1
19
- github.com/ipfs/boxo v0.10.1
18
+ github.com/ipfs/boxo v0.10.2-0.20230620120822-417c5f7d61ff
19
github.com/ipfs/go-block-format v0.1.2
20
github.com/ipfs/go-cid v0.4.1
21
github.com/ipfs/go-cidutil v0.1.0
22
github.com/ipfs/go-datastore v0.6.0
24
- github.com/ipfs/go-delegated-routing v0.8.0
23
github.com/ipfs/go-detect-race v0.0.1
24
github.com/ipfs/go-ds-badger v0.3.0
25
github.com/ipfs/go-ds-flatfs v0.5.1
@@ -86,6 +84,7 @@ require (
84
golang.org/x/mod v0.10.0
85
golang.org/x/sync v0.2.0
86
golang.org/x/sys v0.9.0
87
+ google.golang.org/protobuf v1.30.0
88
)
89
90
require (
@@ -116,6 +115,7 @@ require (
115
github.com/go-logr/stdr v1.2.2 // indirect
116
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
117
github.com/godbus/dbus/v5 v5.1.0 // indirect
118
+ github.com/gogo/protobuf v1.3.2 // indirect
119
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
120
github.com/golang/mock v1.6.0 // indirect
121
github.com/golang/protobuf v1.5.3 // indirect
@@ -140,7 +140,6 @@ require (
140
github.com/ipfs/go-ipld-cbor v0.0.6 // indirect
141
github.com/ipfs/go-libipfs v0.7.0 // indirect
142
github.com/ipfs/go-peertaskqueue v0.8.1 // indirect
143
- github.com/ipld/edelweiss v0.2.0 // indirect
143
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
144
github.com/klauspost/compress v1.16.5 // indirect
145
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
@@ -227,7 +226,6 @@ require (
226
google.golang.org/appengine v1.6.7 // indirect
227
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect
228
google.golang.org/grpc v1.55.0 // indirect
230
- google.golang.org/protobuf v1.30.0 // indirect
229
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
230
gopkg.in/yaml.v2 v2.4.0 // indirect
231
gopkg.in/yaml.v3 v3.0.1 // indirect
@@ -235,4 +233,4 @@ require (
233
nhooyr.io/websocket v1.8.7 // indirect
234
)
235
238
-go 1.18
236
+go 1.19
go.sum
+2
-6
@@ -355,8 +355,8 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:
355
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
356
github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs=
357
github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0=
358
-github.com/ipfs/boxo v0.10.1 h1:q0ZhbyN6iNZLipd6txt1xotCiP/icfvdAQ4YpUi+cL4=
359
-github.com/ipfs/boxo v0.10.1/go.mod h1:1qgKq45mPRCxf4ZPoJV2lnXxyxucigILMJOrQrVivv8=
358
+github.com/ipfs/boxo v0.10.2-0.20230620120822-417c5f7d61ff h1:QnYD2h1e55nX9lSl5k8YVij1VIOICR7lPJlhbKOQjNM=
359
+github.com/ipfs/boxo v0.10.2-0.20230620120822-417c5f7d61ff/go.mod h1:OGMmq97krQBiKx8LRGyf5DgWHeu+PDdIHNN2YnQlWjs=
360
github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA=
361
github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU=
362
github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY=
@@ -379,8 +379,6 @@ github.com/ipfs/go-datastore v0.1.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRV
379
github.com/ipfs/go-datastore v0.5.0/go.mod h1:9zhEApYMTl17C8YDp7JmU7sQZi2/wqiYh73hakZ90Bk=
380
github.com/ipfs/go-datastore v0.6.0 h1:JKyz+Gvz1QEZw0LsX1IBn+JFCJQH4SJVFtM4uWU0Myk=
381
github.com/ipfs/go-datastore v0.6.0/go.mod h1:rt5M3nNbSO/8q1t4LNkLyUwRs8HupMeN/8O4Vn9YAT8=
382
-github.com/ipfs/go-delegated-routing v0.8.0 h1:faiRi4k8YioTxU2x7+pnrLQjR7jIQhGWN2JvCwcQ/aU=
383
-github.com/ipfs/go-delegated-routing v0.8.0/go.mod h1:18Dds6ZoNTsff9S/7R49Nh2t2YNXIIKR/RLQmBZdjjY=
382
github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk=
383
github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps=
384
github.com/ipfs/go-ds-badger v0.0.7/go.mod h1:qt0/fWzZDoPW6jpQeqUjR5kBfhDNB65jd9YlmAvpQBk=
@@ -452,8 +450,6 @@ github.com/ipfs/go-unixfs v0.4.5 h1:wj8JhxvV1G6CD7swACwSKYa+NgtdWC1RUit+gFnymDU=
450
github.com/ipfs/go-unixfsnode v1.7.1 h1:RRxO2b6CSr5UQ/kxnGzaChTjp5LWTdf3Y4n8ANZgB/s=
451
github.com/ipfs/go-unixfsnode v1.7.1/go.mod h1:PVfoyZkX1B34qzT3vJO4nsLUpRCyhnMuHBznRcXirlk=
452
github.com/ipfs/go-verifcid v0.0.2 h1:XPnUv0XmdH+ZIhLGKg6U2vaPaRDXb9urMyNVCE7uvTs=
455
-github.com/ipld/edelweiss v0.2.0 h1:KfAZBP8eeJtrLxLhi7r3N0cBCo7JmwSRhOJp3WSpNjk=
456
-github.com/ipld/edelweiss v0.2.0/go.mod h1:FJAzJRCep4iI8FOFlRriN9n0b7OuX3T/S9++NpBDmA4=
453
github.com/ipld/go-car v0.5.0 h1:kcCEa3CvYMs0iE5BzD5sV7O2EwMiCIp3uF8tA6APQT8=
454
github.com/ipld/go-car/v2 v2.9.1-0.20230325062757-fff0e4397a3d h1:22g+x1tgWSXK34i25qjs+afr7basaneEkHaglBshd2g=
455
github.com/ipld/go-codec-dagpb v1.6.0 h1:9nYazfyu9B1p3NAgfVdpRco3Fs2nFC72DqVsMj6rOcc=
routing/delegated.go
-79
@@ -10,8 +10,6 @@ import (
10
drclient "github.com/ipfs/boxo/routing/http/client"
11
"github.com/ipfs/boxo/routing/http/contentrouter"
12
"github.com/ipfs/go-datastore"
13
- drc "github.com/ipfs/go-delegated-routing/client"
14
- drp "github.com/ipfs/go-delegated-routing/gen/proto"
13
logging "github.com/ipfs/go-log"
14
version "github.com/ipfs/kubo"
15
"github.com/ipfs/kubo/config"
@@ -25,7 +23,6 @@ import (
23
"github.com/libp2p/go-libp2p/core/peer"
24
"github.com/libp2p/go-libp2p/core/routing"
25
ma "github.com/multiformats/go-multiaddr"
28
- "github.com/multiformats/go-multicodec"
26
"go.opencensus.io/stats/view"
27
)
28
@@ -96,8 +93,6 @@ func parse(visited map[string]bool,
93
switch cfg.Type {
94
case config.RouterTypeHTTP:
95
router, err = httpRoutingFromConfig(cfg.Router, extraHTTP)
99
- case config.RouterTypeReframe:
100
- router, err = reframeRoutingFromConfig(cfg.Router, extraHTTP)
96
case config.RouterTypeDHT:
97
router, err = dhtRoutingFromConfig(cfg.Router, extraDHT)
98
case config.RouterTypeParallel:
@@ -232,67 +227,6 @@ func httpRoutingFromConfig(conf config.Router, extraHTTP *ExtraHTTPParams) (rout
227
}, nil
228
}
229
235
-func reframeRoutingFromConfig(conf config.Router, extraReframe *ExtraHTTPParams) (routing.Routing, error) {
236
- var dr drp.DelegatedRouting_Client
237
-
238
- params := conf.Parameters.(*config.ReframeRouterParams)
239
-
240
- if params.Endpoint == "" {
241
- return nil, NewParamNeededErr("Endpoint", conf.Type)
242
- }
243
-
244
- // Increase per-host connection pool since we are making lots of concurrent requests.
245
- transport := http.DefaultTransport.(*http.Transport).Clone()
246
- transport.MaxIdleConns = 500
247
- transport.MaxIdleConnsPerHost = 100
248
-
249
- delegateHTTPClient := &http.Client{
250
- Transport: transport,
251
- }
252
- dr, err := drp.New_DelegatedRouting_Client(params.Endpoint,
253
- drp.DelegatedRouting_Client_WithHTTPClient(delegateHTTPClient),
254
- )
255
- if err != nil {
256
- return nil, err
257
- }
258
-
259
- var c *drc.Client
260
-
261
- err = view.Register(drc.DefaultViews...)
262
- if err != nil {
263
- return nil, fmt.Errorf("registering delegated routing views: %w", err)
264
- }
265
-
266
- // this path is for tests only
267
- if extraReframe == nil {
268
- c, err = drc.NewClient(dr, nil, nil)
269
- if err != nil {
270
- return nil, err
271
- }
272
- } else {
273
- prov, err := createProvider(extraReframe.PeerID, extraReframe.Addrs)
274
- if err != nil {
275
- return nil, err
276
- }
277
-
278
- key, err := decodePrivKey(extraReframe.PrivKeyB64)
279
- if err != nil {
280
- return nil, err
281
- }
282
-
283
- c, err = drc.NewClient(dr, prov, key)
284
- if err != nil {
285
- return nil, err
286
- }
287
- }
288
-
289
- crc := drc.NewContentRoutingClient(c)
290
- return &reframeRoutingWrapper{
291
- Client: c,
292
- ContentRoutingClient: crc,
293
- }, nil
294
-}
295
-
230
func decodePrivKey(keyB64 string) (ic.PrivKey, error) {
231
pk, err := base64.StdEncoding.DecodeString(keyB64)
232
if err != nil {
@@ -324,19 +258,6 @@ func createAddrInfo(peerID string, addrs []string) (peer.AddrInfo, error) {
258
}, nil
259
}
260
327
-func createProvider(peerID string, addrs []string) (*drc.Provider, error) {
328
- addrInfo, err := createAddrInfo(peerID, addrs)
329
- if err != nil {
330
- return nil, err
331
- }
332
- return &drc.Provider{
333
- Peer: addrInfo,
334
- ProviderProto: []drc.TransferProtocol{
335
- {Codec: multicodec.TransportBitswap},
336
- },
337
- }, nil
338
-}
339
-
261
type ExtraDHTParams struct {
262
BootstrapPeers []peer.AddrInfo
263
Host host.Host
routing/delegated_test.go
+50
-62
@@ -1,68 +1,27 @@
1
package routing
2
3
import (
4
+ "crypto/rand"
5
"encoding/base64"
6
"testing"
7
8
"github.com/ipfs/kubo/config"
8
- crypto "github.com/libp2p/go-libp2p/core/crypto"
9
- peer "github.com/libp2p/go-libp2p/core/peer"
9
+ "github.com/libp2p/go-libp2p/core/crypto"
10
+ "github.com/libp2p/go-libp2p/core/peer"
11
"github.com/stretchr/testify/require"
12
)
13
13
-func TestReframeRoutingFromConfig(t *testing.T) {
14
+func TestParser(t *testing.T) {
15
require := require.New(t)
16
16
- r, err := reframeRoutingFromConfig(config.Router{
17
- Type: config.RouterTypeReframe,
18
- Parameters: &config.ReframeRouterParams{},
19
- }, nil)
20
-
21
- require.Nil(r)
22
- require.EqualError(err, "configuration param 'Endpoint' is needed for reframe delegated routing types")
23
-
24
- r, err = reframeRoutingFromConfig(config.Router{
25
- Type: config.RouterTypeReframe,
26
- Parameters: &config.ReframeRouterParams{
27
- Endpoint: "test",
28
- },
29
- }, nil)
30
-
31
- require.NoError(err)
32
- require.NotNil(r)
33
-
34
- priv, pub, err := crypto.GenerateKeyPair(crypto.RSA, 2048)
35
- require.NoError(err)
36
-
37
- id, err := peer.IDFromPublicKey(pub)
38
- require.NoError(err)
39
-
40
- privM, err := crypto.MarshalPrivateKey(priv)
17
+ pid, sk, err := generatePeerID()
18
require.NoError(err)
19
43
- r, err = reframeRoutingFromConfig(config.Router{
44
- Type: config.RouterTypeReframe,
45
- Parameters: &config.ReframeRouterParams{
46
- Endpoint: "test",
47
- },
48
- }, &ExtraHTTPParams{
49
- PeerID: id.String(),
50
- Addrs: []string{"/ip4/0.0.0.0/tcp/4001"},
51
- PrivKeyB64: base64.StdEncoding.EncodeToString(privM),
52
- })
53
-
54
- require.NotNil(r)
55
- require.NoError(err)
56
-}
57
-
58
-func TestParser(t *testing.T) {
59
- require := require.New(t)
60
-
20
router, err := Parse(config.Routers{
21
"r1": config.RouterParser{
22
Router: config.Router{
64
- Type: config.RouterTypeReframe,
65
- Parameters: &config.ReframeRouterParams{
23
+ Type: config.RouterTypeHTTP,
24
+ Parameters: &config.HTTPRouterParams{
25
Endpoint: "testEndpoint",
26
},
27
},
@@ -95,7 +54,10 @@ func TestParser(t *testing.T) {
54
config.MethodNameProvide: config.Method{
55
RouterName: "r2",
56
},
98
- }, &ExtraDHTParams{}, nil)
57
+ }, &ExtraDHTParams{}, &ExtraHTTPParams{
58
+ PeerID: string(pid),
59
+ PrivKeyB64: sk,
60
+ })
61
62
require.NoError(err)
63
@@ -109,27 +71,30 @@ func TestParser(t *testing.T) {
71
func TestParserRecursive(t *testing.T) {
72
require := require.New(t)
73
74
+ pid, sk, err := generatePeerID()
75
+ require.NoError(err)
76
+
77
router, err := Parse(config.Routers{
113
- "reframe1": config.RouterParser{
78
+ "http1": config.RouterParser{
79
Router: config.Router{
115
- Type: config.RouterTypeReframe,
116
- Parameters: &config.ReframeRouterParams{
80
+ Type: config.RouterTypeHTTP,
81
+ Parameters: &config.HTTPRouterParams{
82
Endpoint: "testEndpoint1",
83
},
84
},
85
},
121
- "reframe2": config.RouterParser{
86
+ "http2": config.RouterParser{
87
Router: config.Router{
123
- Type: config.RouterTypeReframe,
124
- Parameters: &config.ReframeRouterParams{
88
+ Type: config.RouterTypeHTTP,
89
+ Parameters: &config.HTTPRouterParams{
90
Endpoint: "testEndpoint2",
91
},
92
},
93
},
129
- "reframe3": config.RouterParser{
94
+ "http3": config.RouterParser{
95
Router: config.Router{
131
- Type: config.RouterTypeReframe,
132
- Parameters: &config.ReframeRouterParams{
96
+ Type: config.RouterTypeHTTP,
97
+ Parameters: &config.HTTPRouterParams{
98
Endpoint: "testEndpoint3",
99
},
100
},
@@ -140,10 +105,10 @@ func TestParserRecursive(t *testing.T) {
105
Parameters: &config.ComposableRouterParams{
106
Routers: []config.ConfigRouter{
107
{
143
- RouterName: "reframe1",
108
+ RouterName: "http1",
109
},
110
{
146
- RouterName: "reframe2",
111
+ RouterName: "http2",
112
},
113
},
114
},
@@ -158,7 +123,7 @@ func TestParserRecursive(t *testing.T) {
123
RouterName: "composable1",
124
},
125
{
161
- RouterName: "reframe3",
126
+ RouterName: "http3",
127
},
128
},
129
},
@@ -180,7 +145,10 @@ func TestParserRecursive(t *testing.T) {
145
config.MethodNameProvide: config.Method{
146
RouterName: "composable2",
147
},
183
- }, &ExtraDHTParams{}, nil)
148
+ }, &ExtraDHTParams{}, &ExtraHTTPParams{
149
+ PeerID: string(pid),
150
+ PrivKeyB64: sk,
151
+ })
152
153
require.NoError(err)
154
@@ -237,3 +205,23 @@ func TestParserRecursiveLoop(t *testing.T) {
205
206
require.ErrorContains(err, "dependency loop creating router with name \"composable2\"")
207
}
208
+
209
+func generatePeerID() (string, string, error) {
210
+ sk, pk, err := crypto.GenerateEd25519Key(rand.Reader)
211
+ if err != nil {
212
+ return "", "", err
213
+ }
214
+
215
+ bytes, err := crypto.MarshalPrivateKey(sk)
216
+ if err != nil {
217
+ return "", "", err
218
+ }
219
+
220
+ enc := base64.StdEncoding.EncodeToString(bytes)
221
+ if err != nil {
222
+ return "", "", err
223
+ }
224
+
225
+ pid, err := peer.IDFromPublicKey(pk)
226
+ return pid.String(), enc, err
227
+}
routing/wrapper.go
-28
@@ -3,39 +3,11 @@ package routing
3
import (
4
"context"
5
6
- "github.com/ipfs/go-cid"
7
- drc "github.com/ipfs/go-delegated-routing/client"
6
routinghelpers "github.com/libp2p/go-libp2p-routing-helpers"
7
"github.com/libp2p/go-libp2p/core/peer"
8
"github.com/libp2p/go-libp2p/core/routing"
9
)
10
13
-var _ routing.Routing = &reframeRoutingWrapper{}
14
-var _ routinghelpers.ProvideManyRouter = &reframeRoutingWrapper{}
15
-
16
-// reframeRoutingWrapper is a wrapper needed to construct the routing.Routing interface from
17
-// delegated-routing library.
18
-type reframeRoutingWrapper struct {
19
- *drc.Client
20
- *drc.ContentRoutingClient
21
-}
22
-
23
-func (c *reframeRoutingWrapper) Provide(ctx context.Context, id cid.Cid, announce bool) error {
24
- return c.ContentRoutingClient.Provide(ctx, id, announce)
25
-}
26
-
27
-func (c *reframeRoutingWrapper) FindProvidersAsync(ctx context.Context, cid cid.Cid, count int) <-chan peer.AddrInfo {
28
- return c.ContentRoutingClient.FindProvidersAsync(ctx, cid, count)
29
-}
30
-
31
-func (c *reframeRoutingWrapper) Bootstrap(ctx context.Context) error {
32
- return nil
33
-}
34
-
35
-func (c *reframeRoutingWrapper) FindPeer(ctx context.Context, id peer.ID) (peer.AddrInfo, error) {
36
- return peer.AddrInfo{}, routing.ErrNotSupported
37
-}
38
-
11
type ProvideManyRouter interface {
12
routinghelpers.ProvideManyRouter
13
routing.Routing
test/cli/fixtures/TestName.car
Binary files /dev/null and b/test/cli/fixtures/TestName.car differ
test/cli/name_test.go
new
+266
@@ -0,0 +1,266 @@
1
+package cli
2
+
3
+import (
4
+ "bytes"
5
+ "encoding/json"
6
+ "fmt"
7
+ "os"
8
+ "strings"
9
+ "testing"
10
+
11
+ "github.com/ipfs/boxo/ipns"
12
+ "github.com/ipfs/kubo/core/commands/name"
13
+ "github.com/ipfs/kubo/test/cli/harness"
14
+ "github.com/stretchr/testify/require"
15
+)
16
+
17
+func TestName(t *testing.T) {
18
+ const (
19
+ fixturePath = "fixtures/TestName.car"
20
+ fixtureCid = "bafybeidg3uxibfrt7uqh7zd5yaodetik7wjwi4u7rwv2ndbgj6ec7lsv2a"
21
+ dagCid = "bafyreidgts62p4rtg3rtmptmbv2dt46zjzin275fr763oku3wfod3quzay"
22
+ )
23
+
24
+ makeDaemon := func(t *testing.T, initArgs []string) *harness.Node {
25
+ node := harness.NewT(t).NewNode().Init(append([]string{"--profile=test"}, initArgs...)...)
26
+ r, err := os.Open(fixturePath)
27
+ require.Nil(t, err)
28
+ defer r.Close()
29
+ err = node.IPFSDagImport(r, fixtureCid)
30
+ require.NoError(t, err)
31
+ return node
32
+ }
33
+
34
+ testPublishingWithSelf := func(keyType string) {
35
+ t.Run("Publishing with self (keyType = "+keyType+")", func(t *testing.T) {
36
+ t.Parallel()
37
+
38
+ args := []string{}
39
+ if keyType != "default" {
40
+ args = append(args, "-a="+keyType)
41
+ }
42
+
43
+ node := makeDaemon(t, args)
44
+ name := ipns.NameFromPeer(node.PeerID())
45
+
46
+ t.Run("Publishing a CID", func(t *testing.T) {
47
+ publishPath := "/ipfs/" + fixtureCid
48
+
49
+ res := node.IPFS("name", "publish", "--allow-offline", publishPath)
50
+ require.Equal(t, fmt.Sprintf("Published to %s: %s\n", name.String(), publishPath), res.Stdout.String())
51
+
52
+ res = node.IPFS("name", "resolve", "/ipns/"+name.String())
53
+ require.Equal(t, publishPath+"\n", res.Stdout.String())
54
+ })
55
+
56
+ t.Run("Publishing a CID with -Q option", func(t *testing.T) {
57
+ publishPath := "/ipfs/" + fixtureCid
58
+
59
+ res := node.IPFS("name", "publish", "--allow-offline", "-Q", publishPath)
60
+ require.Equal(t, name.String()+"\n", res.Stdout.String())
61
+
62
+ res = node.IPFS("name", "resolve", "/ipns/"+name.String())
63
+ require.Equal(t, publishPath+"\n", res.Stdout.String())
64
+ })
65
+
66
+ t.Run("Publishing a CID+subpath", func(t *testing.T) {
67
+ publishPath := "/ipfs/" + fixtureCid + "/hello"
68
+
69
+ res := node.IPFS("name", "publish", "--allow-offline", publishPath)
70
+ require.Equal(t, fmt.Sprintf("Published to %s: %s\n", name.String(), publishPath), res.Stdout.String())
71
+
72
+ res = node.IPFS("name", "resolve", "/ipns/"+name.String())
73
+ require.Equal(t, publishPath+"\n", res.Stdout.String())
74
+ })
75
+
76
+ t.Run("Publishing nothing fails", func(t *testing.T) {
77
+ res := node.RunIPFS("name", "publish")
78
+ require.Error(t, res.Err)
79
+ require.Equal(t, 1, res.ExitCode())
80
+ require.Contains(t, res.Stderr.String(), `argument "ipfs-path" is required`)
81
+ })
82
+
83
+ t.Run("Publishing with IPLD works", func(t *testing.T) {
84
+ publishPath := "/ipld/" + dagCid + "/thing"
85
+ res := node.IPFS("name", "publish", "--allow-offline", publishPath)
86
+ require.Equal(t, fmt.Sprintf("Published to %s: %s\n", name.String(), publishPath), res.Stdout.String())
87
+
88
+ res = node.IPFS("name", "resolve", "/ipns/"+name.String())
89
+ require.Equal(t, publishPath+"\n", res.Stdout.String())
90
+ })
91
+
92
+ publishPath := "/ipfs/" + fixtureCid
93
+ res := node.IPFS("name", "publish", "--allow-offline", publishPath)
94
+ require.Equal(t, fmt.Sprintf("Published to %s: %s\n", name.String(), publishPath), res.Stdout.String())
95
+
96
+ t.Run("Resolving self offline succeeds (daemon off)", func(t *testing.T) {
97
+ res = node.IPFS("name", "resolve", "--offline", "/ipns/"+name.String())
98
+ require.Equal(t, publishPath+"\n", res.Stdout.String())
99
+
100
+ // Test without cache.
101
+ res = node.IPFS("name", "resolve", "--offline", "-n", "/ipns/"+name.String())
102
+ require.Equal(t, publishPath+"\n", res.Stdout.String())
103
+ })
104
+
105
+ node.StartDaemon()
106
+
107
+ t.Run("Resolving self offline succeeds (daemon on)", func(t *testing.T) {
108
+ res = node.IPFS("name", "resolve", "--offline", "/ipns/"+name.String())
109
+ require.Equal(t, publishPath+"\n", res.Stdout.String())
110
+
111
+ // Test without cache.
112
+ res = node.IPFS("name", "resolve", "--offline", "-n", "/ipns/"+name.String())
113
+ require.Equal(t, publishPath+"\n", res.Stdout.String())
114
+ })
115
+ })
116
+ }
117
+
118
+ testPublishingWithSelf("default")
119
+ testPublishingWithSelf("rsa")
120
+ testPublishingWithSelf("ed25519")
121
+
122
+ testPublishWithKey := func(name string, keyArgs ...string) {
123
+ t.Run(name, func(t *testing.T) {
124
+ t.Parallel()
125
+ node := makeDaemon(t, nil)
126
+
127
+ keyGenArgs := []string{"key", "gen"}
128
+ keyGenArgs = append(keyGenArgs, keyArgs...)
129
+ keyGenArgs = append(keyGenArgs, "key")
130
+
131
+ res := node.IPFS(keyGenArgs...)
132
+ key := strings.TrimSpace(res.Stdout.String())
133
+
134
+ publishPath := "/ipfs/" + fixtureCid
135
+ name, err := ipns.NameFromString(key)
136
+ require.NoError(t, err)
137
+
138
+ res = node.IPFS("name", "publish", "--allow-offline", "--key="+key, publishPath)
139
+ require.Equal(t, fmt.Sprintf("Published to %s: %s\n", name.String(), publishPath), res.Stdout.String())
140
+ })
141
+ }
142
+
143
+ testPublishWithKey("Publishing with RSA (with b58mh) Key", "--ipns-base=b58mh", "--type=rsa", "--size=2048")
144
+ testPublishWithKey("Publishing with ED25519 (with b58mh) Key", "--ipns-base=b58mh", "--type=ed25519")
145
+ testPublishWithKey("Publishing with ED25519 (with base36) Key", "--ipns-base=base36", "--type=ed25519")
146
+
147
+ t.Run("Fails to publish in offline mode", func(t *testing.T) {
148
+ t.Parallel()
149
+ node := makeDaemon(t, nil).StartDaemon("--offline")
150
+ res := node.RunIPFS("name", "publish", "/ipfs/"+fixtureCid)
151
+ require.Error(t, res.Err)
152
+ require.Equal(t, 1, res.ExitCode())
153
+ require.Contains(t, res.Stderr.String(), `can't publish while offline`)
154
+ })
155
+
156
+ t.Run("Publish V2-only record", func(t *testing.T) {
157
+ t.Parallel()
158
+
159
+ node := makeDaemon(t, nil).StartDaemon()
160
+ ipnsName := ipns.NameFromPeer(node.PeerID()).String()
161
+ ipnsPath := ipns.NamespacePrefix + ipnsName
162
+ publishPath := "/ipfs/" + fixtureCid
163
+
164
+ res := node.IPFS("name", "publish", "--ttl=30m", "--v1compat=false", publishPath)
165
+ require.Equal(t, fmt.Sprintf("Published to %s: %s\n", ipnsName, publishPath), res.Stdout.String())
166
+
167
+ res = node.IPFS("name", "resolve", ipnsPath)
168
+ require.Equal(t, publishPath+"\n", res.Stdout.String())
169
+
170
+ res = node.IPFS("routing", "get", ipnsPath)
171
+ record := res.Stdout.Bytes()
172
+
173
+ res = node.PipeToIPFS(bytes.NewReader(record), "name", "inspect")
174
+ out := res.Stdout.String()
175
+ require.Contains(t, out, "This record was not validated.")
176
+ require.Contains(t, out, publishPath)
177
+ require.Contains(t, out, "30m")
178
+
179
+ res = node.PipeToIPFS(bytes.NewReader(record), "name", "inspect", "--verify="+ipnsPath)
180
+ out = res.Stdout.String()
181
+ require.Contains(t, out, "Valid: true")
182
+ require.Contains(t, out, "Signature Type: V2")
183
+ require.Contains(t, out, fmt.Sprintf("Protobuf Size: %d", len(record)))
184
+ })
185
+
186
+ t.Run("Publish with TTL and inspect record", func(t *testing.T) {
187
+ t.Parallel()
188
+
189
+ node := makeDaemon(t, nil).StartDaemon()
190
+ ipnsPath := ipns.NamespacePrefix + ipns.NameFromPeer(node.PeerID()).String()
191
+ publishPath := "/ipfs/" + fixtureCid
192
+
193
+ _ = node.IPFS("name", "publish", "--ttl=30m", publishPath)
194
+ res := node.IPFS("routing", "get", ipnsPath)
195
+ record := res.Stdout.Bytes()
196
+
197
+ t.Run("Inspect record shows correct TTL and that it is not validated", func(t *testing.T) {
198
+ t.Parallel()
199
+ res = node.PipeToIPFS(bytes.NewReader(record), "name", "inspect")
200
+ out := res.Stdout.String()
201
+ require.Contains(t, out, "This record was not validated.")
202
+ require.Contains(t, out, publishPath)
203
+ require.Contains(t, out, "30m")
204
+ require.Contains(t, out, "Signature Type: V1+V2")
205
+ require.Contains(t, out, fmt.Sprintf("Protobuf Size: %d", len(record)))
206
+ })
207
+
208
+ t.Run("Inspect record shows valid with correct name", func(t *testing.T) {
209
+ t.Parallel()
210
+ res := node.PipeToIPFS(bytes.NewReader(record), "name", "inspect", "--enc=json", "--verify="+ipnsPath)
211
+ val := name.IpnsInspectResult{}
212
+ err := json.Unmarshal(res.Stdout.Bytes(), &val)
213
+ require.NoError(t, err)
214
+ require.True(t, val.Validation.Valid)
215
+ })
216
+
217
+ t.Run("Inspect record shows invalid with wrong name", func(t *testing.T) {
218
+ t.Parallel()
219
+ res := node.PipeToIPFS(bytes.NewReader(record), "name", "inspect", "--enc=json", "--verify=12D3KooWRirYjmmQATx2kgHBfky6DADsLP7ex1t7BRxJ6nqLs9WH")
220
+ val := name.IpnsInspectResult{}
221
+ err := json.Unmarshal(res.Stdout.Bytes(), &val)
222
+ require.NoError(t, err)
223
+ require.False(t, val.Validation.Valid)
224
+ })
225
+ })
226
+
227
+ t.Run("Inspect with verification using wrong RSA key errors", func(t *testing.T) {
228
+ t.Parallel()
229
+ node := makeDaemon(t, nil).StartDaemon()
230
+
231
+ // Prepare RSA Key 1
232
+ res := node.IPFS("key", "gen", "--type=rsa", "--size=4096", "key1")
233
+ key1 := strings.TrimSpace(res.Stdout.String())
234
+ name1, err := ipns.NameFromString(key1)
235
+ require.NoError(t, err)
236
+
237
+ // Prepare RSA Key 2
238
+ res = node.IPFS("key", "gen", "--type=rsa", "--size=4096", "key2")
239
+ key2 := strings.TrimSpace(res.Stdout.String())
240
+ name2, err := ipns.NameFromString(key2)
241
+ require.NoError(t, err)
242
+
243
+ // Publish using Key 1
244
+ publishPath := "/ipfs/" + fixtureCid
245
+ res = node.IPFS("name", "publish", "--allow-offline", "--key="+key1, publishPath)
246
+ require.Equal(t, fmt.Sprintf("Published to %s: %s\n", name1.String(), publishPath), res.Stdout.String())
247
+
248
+ // Get IPNS Record
249
+ res = node.IPFS("routing", "get", ipns.NamespacePrefix+name1.String())
250
+ record := res.Stdout.Bytes()
251
+
252
+ // Validate with correct key succeeds
253
+ res = node.PipeToIPFS(bytes.NewReader(record), "name", "inspect", "--verify="+name1.String(), "--enc=json")
254
+ val := name.IpnsInspectResult{}
255
+ err = json.Unmarshal(res.Stdout.Bytes(), &val)
256
+ require.NoError(t, err)
257
+ require.True(t, val.Validation.Valid)
258
+
259
+ // Validate with wrong key fails
260
+ res = node.PipeToIPFS(bytes.NewReader(record), "name", "inspect", "--verify="+name2.String(), "--enc=json")
261
+ val = name.IpnsInspectResult{}
262
+ err = json.Unmarshal(res.Stdout.Bytes(), &val)
263
+ require.NoError(t, err)
264
+ require.False(t, val.Validation.Valid)
265
+ })
266
+}
test/dependencies/go.mod
+1
-1
@@ -7,7 +7,7 @@ replace github.com/ipfs/kubo => ../../
7
require (
8
github.com/Kubuxu/gocovmerge v0.0.0-20161216165753-7ecaa51963cd
9
github.com/golangci/golangci-lint v1.49.0
10
- github.com/ipfs/boxo v0.10.1
10
+ github.com/ipfs/boxo v0.10.2-0.20230620120822-417c5f7d61ff
11
github.com/ipfs/go-cid v0.4.1
12
github.com/ipfs/go-cidutil v0.1.0
13
github.com/ipfs/go-datastore v0.6.0
test/dependencies/go.sum
+2
-2
@@ -413,8 +413,8 @@ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NH
413
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
414
github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs=
415
github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0=
416
-github.com/ipfs/boxo v0.10.1 h1:q0ZhbyN6iNZLipd6txt1xotCiP/icfvdAQ4YpUi+cL4=
417
-github.com/ipfs/boxo v0.10.1/go.mod h1:1qgKq45mPRCxf4ZPoJV2lnXxyxucigILMJOrQrVivv8=
416
+github.com/ipfs/boxo v0.10.2-0.20230620120822-417c5f7d61ff h1:QnYD2h1e55nX9lSl5k8YVij1VIOICR7lPJlhbKOQjNM=
417
+github.com/ipfs/boxo v0.10.2-0.20230620120822-417c5f7d61ff/go.mod h1:OGMmq97krQBiKx8LRGyf5DgWHeu+PDdIHNN2YnQlWjs=
418
github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA=
419
github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU=
420
github.com/ipfs/go-block-format v0.1.2 h1:GAjkfhVx1f4YTODS6Esrj1wt2HhrtwTnhEr+DyPUaJo=
test/sharness/t0100-name.sh
deleted
-345
@@ -1,345 +0,0 @@
1
-#!/usr/bin/env bash
2
-#
3
-# Copyright (c) 2014 Jeromy Johnson
4
-# MIT Licensed; see the LICENSE file in this repository.
5
-#
6
-
7
-test_description="Test ipfs repo operations"
8
-
9
-. lib/test-lib.sh
10
-
11
-test_name_with_self() {
12
- SELF_ALG=$1
13
-
14
- test_expect_success "ipfs init (variant self $SELF_ALG)" '
15
- export IPFS_PATH="$(pwd)/.ipfs" &&
16
- case $SELF_ALG in
17
- default)
18
- ipfs init --empty-repo=false --profile=test > /dev/null
19
- ;;
20
- rsa)
21
- ipfs init --empty-repo=false --profile=test -a=rsa > /dev/null
22
- ;;
23
- ed25519)
24
- ipfs init --empty-repo=false --profile=test -a=ed25519 > /dev/null
25
- ;;
26
- esac &&
27
- export PEERID=`ipfs key list --ipns-base=base36 -l | grep self | cut -d " " -f1` &&
28
- test_check_peerid "${PEERID}"
29
- '
30
-
31
- # test publishing a hash
32
-
33
- test_expect_success "'ipfs name publish --allow-offline' succeeds" '
34
- ipfs name publish --allow-offline "/ipfs/$HASH_WELCOME_DOCS" >publish_out
35
- '
36
-
37
- test_expect_success "publish output looks good" '
38
- echo "Published to ${PEERID}: /ipfs/$HASH_WELCOME_DOCS" >expected1 &&
39
- test_cmp expected1 publish_out
40
- '
41
-
42
- test_expect_success "'ipfs name resolve' succeeds" '
43
- ipfs name resolve "$PEERID" >output
44
- '
45
-
46
- test_expect_success "resolve output looks good" '
47
- printf "/ipfs/%s\n" "$HASH_WELCOME_DOCS" >expected2 &&
48
- test_cmp expected2 output
49
- '
50
-
51
- # test publishing with -Q option
52
-
53
- test_expect_success "'ipfs name publish --quieter' succeeds" '
54
- ipfs name publish --allow-offline -Q "/ipfs/$HASH_WELCOME_DOCS" >publish_out
55
- '
56
-
57
- test_expect_success "publish --quieter output looks good" '
58
- echo "${PEERID}" >expected1 &&
59
- test_cmp expected1 publish_out
60
- '
61
-
62
- test_expect_success "'ipfs name resolve' succeeds" '
63
- ipfs name resolve "$PEERID" >output
64
- '
65
-
66
- test_expect_success "resolve output looks good" '
67
- printf "/ipfs/%s\n" "$HASH_WELCOME_DOCS" >expected2 &&
68
- test_cmp expected2 output
69
- '
70
-
71
- # now test with a path
72
-
73
- test_expect_success "'ipfs name publish --allow-offline' succeeds" '
74
- ipfs name publish --allow-offline "/ipfs/$HASH_WELCOME_DOCS/help" >publish_out
75
- '
76
-
77
- test_expect_success "publish a path looks good" '
78
- echo "Published to ${PEERID}: /ipfs/$HASH_WELCOME_DOCS/help" >expected3 &&
79
- test_cmp expected3 publish_out
80
- '
81
-
82
- test_expect_success "'ipfs name resolve' succeeds" '
83
- ipfs name resolve "$PEERID" >output
84
- '
85
-
86
- test_expect_success "resolve output looks good" '
87
- printf "/ipfs/%s/help\n" "$HASH_WELCOME_DOCS" >expected4 &&
88
- test_cmp expected4 output
89
- '
90
-
91
- test_expect_success "ipfs cat on published content succeeds" '
92
- ipfs cat "/ipfs/$HASH_WELCOME_DOCS/help" >expected &&
93
- ipfs cat "/ipns/$PEERID" >actual &&
94
- test_cmp expected actual
95
- '
96
-
97
- # publish with an explicit node ID
98
-
99
- test_expect_failure "'ipfs name publish --allow-offline <local-id> <hash>' succeeds" '
100
- echo ipfs name publish --allow-offline "${PEERID}" "/ipfs/$HASH_WELCOME_DOCS" &&
101
- ipfs name publish --allow-offline "${PEERID}" "/ipfs/$HASH_WELCOME_DOCS" >actual_node_id_publish
102
- '
103
-
104
- test_expect_failure "publish with our explicit node ID looks good" '
105
- echo "Published to ${PEERID}: /ipfs/$HASH_WELCOME_DOCS" >expected_node_id_publish &&
106
- test_cmp expected_node_id_publish actual_node_id_publish
107
- '
108
-
109
- # test publishing with B36CID and B58MH resolve to the same B36CID
110
-
111
- test_expect_success "verify self key output" '
112
- B58MH_ID=`ipfs key list --ipns-base=b58mh -l | grep self | cut -d " " -f1` &&
113
- B36CID_ID=`ipfs key list --ipns-base=base36 -l | grep self | cut -d " " -f1` &&
114
- test_check_peerid "${B58MH_ID}" &&
115
- test_check_peerid "${B36CID_ID}"
116
- '
117
-
118
- test_expect_success "'ipfs name publish --allow-offline --key=<peer-id> <hash>' succeeds" '
119
- ipfs name publish --allow-offline --key=${B58MH_ID} "/ipfs/$HASH_WELCOME_DOCS" >b58mh_published_id_base36 &&
120
- ipfs name publish --allow-offline --key=${B36CID_ID} "/ipfs/$HASH_WELCOME_DOCS" >base36_published_id_base36 &&
121
- ipfs name publish --allow-offline --key=${B58MH_ID} --ipns-base=b58mh "/ipfs/$HASH_WELCOME_DOCS" >b58mh_published_id_b58mh &&
122
- ipfs name publish --allow-offline --key=${B36CID_ID} --ipns-base=b58mh "/ipfs/$HASH_WELCOME_DOCS" >base36_published_id_b58mh
123
- '
124
-
125
- test_expect_success "publish an explicit node ID as two key in B58MH and B36CID, name looks good" '
126
- echo "Published to ${B36CID_ID}: /ipfs/$HASH_WELCOME_DOCS" >expected_published_id_base36 &&
127
- echo "Published to ${B58MH_ID}: /ipfs/$HASH_WELCOME_DOCS" >expected_published_id_b58mh &&
128
- test_cmp expected_published_id_base36 b58mh_published_id_base36 &&
129
- test_cmp expected_published_id_base36 base36_published_id_base36 &&
130
- test_cmp expected_published_id_b58mh b58mh_published_id_b58mh &&
131
- test_cmp expected_published_id_b58mh base36_published_id_b58mh
132
- '
133
-
134
- test_expect_success "'ipfs name resolve' succeeds" '
135
- ipfs name resolve "$B36CID_ID" >output
136
- '
137
-
138
- test_expect_success "resolve output looks good" '
139
- printf "/ipfs/%s\n" "$HASH_WELCOME_DOCS" >expected2 &&
140
- test_cmp expected2 output
141
- '
142
-
143
- # test IPNS + IPLD
144
-
145
- test_expect_success "'ipfs dag put' succeeds" '
146
- HELLO_HASH="$(echo "\"hello world\"" | ipfs dag put)" &&
147
- OBJECT_HASH="$(echo "{\"thing\": {\"/\": \"${HELLO_HASH}\" }}" | ipfs dag put)"
148
- '
149
- test_expect_success "'ipfs name publish --allow-offline /ipld/...' succeeds" '
150
- test_check_peerid "${PEERID}" &&
151
- ipfs name publish --allow-offline "/ipld/$OBJECT_HASH/thing" >publish_out
152
- '
153
- test_expect_success "publish a path looks good" '
154
- echo "Published to ${PEERID}: /ipld/$OBJECT_HASH/thing" >expected3 &&
155
- test_cmp expected3 publish_out
156
- '
157
- test_expect_success "'ipfs name resolve' succeeds" '
158
- ipfs name resolve "$PEERID" >output
159
- '
160
- test_expect_success "resolve output looks good (IPNS + IPLD)" '
161
- printf "/ipld/%s/thing\n" "$OBJECT_HASH" >expected4 &&
162
- test_cmp expected4 output
163
- '
164
-
165
- # test publishing nothing
166
-
167
- test_expect_success "'ipfs name publish' fails" '
168
- printf '' | test_expect_code 1 ipfs name publish --allow-offline >publish_out 2>&1
169
- '
170
-
171
- test_expect_success "publish output has the correct error" '
172
- grep "argument \"ipfs-path\" is required" publish_out
173
- '
174
-
175
- test_expect_success "'ipfs name publish' fails" '
176
- printf '' | test_expect_code 1 ipfs name publish -Q --allow-offline >publish_out 2>&1
177
- '
178
-
179
- test_expect_success "publish output has the correct error" '
180
- grep "argument \"ipfs-path\" is required" publish_out
181
- '
182
-
183
- test_expect_success "'ipfs name publish --help' succeeds" '
184
- ipfs name publish --help
185
- '
186
-
187
- # test offline resolve
188
-
189
- test_expect_success "'ipfs name resolve --offline' succeeds" '
190
- ipfs name resolve --offline "$PEERID" >output
191
- '
192
- test_expect_success "resolve output looks good (offline resolve)" '
193
- printf "/ipld/%s/thing\n" "$OBJECT_HASH" >expected4 &&
194
- test_cmp expected4 output
195
- '
196
-
197
- test_expect_success "'ipfs name resolve --offline -n' succeeds" '
198
- ipfs name resolve --offline -n "$PEERID" >output
199
- '
200
- test_expect_success "resolve output looks good (offline resolve, -n)" '
201
- printf "/ipld/%s/thing\n" "$OBJECT_HASH" >expected4 &&
202
- test_cmp expected4 output
203
- '
204
-
205
- test_launch_ipfs_daemon
206
-
207
- test_expect_success "'ipfs name resolve --offline' succeeds" '
208
- ipfs name resolve --offline "$PEERID" >output
209
- '
210
- test_expect_success "resolve output looks good (with daemon)" '
211
- printf "/ipld/%s/thing\n" "$OBJECT_HASH" >expected4 &&
212
- test_cmp expected4 output
213
- '
214
-
215
- test_expect_success "'ipfs name resolve --offline -n' succeeds" '
216
- ipfs name resolve --offline -n "$PEERID" >output
217
- '
218
- test_expect_success "resolve output looks good (with daemon, -n)" '
219
- printf "/ipld/%s/thing\n" "$OBJECT_HASH" >expected4 &&
220
- test_cmp expected4 output
221
- '
222
-
223
- test_expect_success "empty request to name publish doesn't panic and returns error" '
224
- curl -X POST "http://$API_ADDR/api/v0/name/publish" > curl_out || true &&
225
- grep "argument \"ipfs-path\" is required" curl_out
226
- '
227
-
228
- # Test Publishing with TTL and Inspecting Records
229
- test_expect_success "'ipfs name publish --ttl=30m' succeeds" '
230
- ipfs name publish --ttl=30m --allow-offline "/ipfs/$HASH_WELCOME_DOCS"
231
- '
232
-
233
- test_expect_success "retrieve IPNS key for further inspection" '
234
- ipfs routing get "/ipns/$PEERID" > ipns_record
235
- '
236
-
237
- test_expect_success "'ipfs name inspect' has correct TTL (30m)" '
238
- ipfs name inspect < ipns_record > verify_output &&
239
- test_should_contain "This record was not validated." verify_output &&
240
- test_should_contain "$HASH_WELCOME_DOCS" verify_output &&
241
- test_should_contain "1800000000000" verify_output
242
- '
243
-
244
- test_expect_success "'ipfs name inspect --verify' has '.Validation.Validity' set to 'true' with correct Peer ID" '
245
- ipfs name inspect --verify $PEERID --enc json < ipns_record | jq -e ".Validation.Valid == true and .Entry.TTL == .Entry.Data.TTL"
246
- '
247
-
248
- test_expect_success "'ipfs name inspect --verify' has '.Validation.Validity' set to 'false' with incorrect Peer ID" '
249
- ipfs name inspect --verify 12D3KooWRirYjmmQATx2kgHBfky6DADsLP7ex1t7BRxJ6nqLs9WH --enc json < ipns_record | jq -e ".Validation.Valid == false"
250
- '
251
-
252
- test_kill_ipfs_daemon
253
-
254
- # Test daemon in offline mode
255
- test_launch_ipfs_daemon_without_network
256
-
257
- test_expect_success "'ipfs name publish' fails offline mode" '
258
- test_expect_code 1 ipfs name publish "/ipfs/$HASH_WELCOME_DOCS"
259
- '
260
-
261
- test_kill_ipfs_daemon
262
-
263
- test_expect_success "clean up ipfs dir" '
264
- rm -rf "$IPFS_PATH"
265
- '
266
-}
267
-test_name_with_self 'default'
268
-test_name_with_self 'rsa'
269
-test_name_with_self 'ed25519'
270
-
271
-test_name_with_key() {
272
- GEN_ALG=$1
273
-
274
- test_expect_success "ipfs init (key variant $GEN_ALG)" '
275
- export IPFS_PATH="$(pwd)/.ipfs" &&
276
- ipfs init --empty-repo=false --profile=test > /dev/null
277
- '
278
-
279
- test_expect_success "'prepare keys" '
280
- case $GEN_ALG in
281
- rsa)
282
- export KEY=`ipfs key gen --ipns-base=b58mh --type=rsa --size=2048 key` &&
283
- export KEY_B36CID=`ipfs key list --ipns-base=base36 -l | grep key | cut -d " " -f1`
284
- ;;
285
- ed25519_b58)
286
- export KEY=`ipfs key gen --ipns-base=b58mh --type=ed25519 key`
287
- export KEY_B36CID=`ipfs key list --ipns-base=base36 -l | grep key | cut -d " " -f1`
288
- ;;
289
- ed25519_b36)
290
- export KEY=`ipfs key gen --ipns-base=base36 --type=ed25519 key`
291
- export KEY_B36CID=$KEY
292
- ;;
293
- esac &&
294
- test_check_peerid "${KEY}"
295
- '
296
-
297
- # publish with an explicit node ID as key name
298
-
299
- test_expect_success "'ipfs name publish --allow-offline --key=<peer-id> <hash>' succeeds" '
300
- ipfs name publish --allow-offline --key=${KEY} "/ipfs/$HASH_WELCOME_DOCS" >actual_node_id_publish
301
- '
302
-
303
- test_expect_success "publish an explicit node ID as key name looks good" '
304
- echo "Published to ${KEY_B36CID}: /ipfs/$HASH_WELCOME_DOCS" >expected_node_id_publish &&
305
- test_cmp expected_node_id_publish actual_node_id_publish
306
- '
307
-
308
- # cleanup
309
- test_expect_success "clean up ipfs dir" '
310
- rm -rf "$IPFS_PATH"
311
- '
312
-}
313
-test_name_with_key 'rsa'
314
-test_name_with_key 'ed25519_b58'
315
-test_name_with_key 'ed25519_b36'
316
-
317
-
318
-# `ipfs name inspect --verify` using the wrong RSA key should not succeed
319
-
320
-test_init_ipfs --empty-repo=false
321
-test_launch_ipfs_daemon
322
-
323
-test_expect_success "prepare RSA keys" '
324
- export KEY_1=`ipfs key gen --type=rsa --size=4096 key1` &&
325
- export KEY_2=`ipfs key gen --type=rsa --size=4096 key2` &&
326
- export PEERID_1=`ipfs key list --ipns-base=base36 -l | grep key1 | cut -d " " -f1` &&
327
- export PEERID_2=`ipfs key list --ipns-base=base36 -l | grep key2 | cut -d " " -f1`
328
-'
329
-
330
-test_expect_success "ipfs name publish --allow-offline --key=<peer-id> <hash>' succeeds" '
331
- ipfs name publish --allow-offline --key=${KEY_1} "/ipfs/$( echo "helloworld" | ipfs add --inline -q )" &&
332
- ipfs routing get "/ipns/$PEERID_1" > ipns_record
333
-'
334
-
335
-test_expect_success "ipfs name inspect --verify' has '.Validation.Validity' set to 'true' with correct Peer ID" '
336
- ipfs name inspect --verify $PEERID_1 --enc json < ipns_record | jq -e ".Validation.Valid == true"
337
-'
338
-
339
-test_expect_success "ipfs name inspect --verify' has '.Validation.Validity' set to 'false' when we verify the wrong Peer ID" '
340
- ipfs name inspect --verify $PEERID_2 --enc json < ipns_record | jq -e ".Validation.Valid == false"
341
-'
342
-
343
-test_kill_ipfs_daemon
344
-
345
-test_done