@cryptotaxi247 / kubo / commits / 5156f2116

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