@@ -2,21 +2,17 @@ package name
2
2
3
3
import (
4
4
"bytes"
5
- "encoding/json "
5
+ "encoding/hex "
6
6
"fmt"
7
7
"io"
8
8
"text/tabwriter"
9
9
"time"
10
10
11
11
"github.com/ipfs/boxo/ipns"
12
12
ipns_pb "github.com/ipfs/boxo/ipns/pb"
13
+ "github.com/ipfs/boxo/path"
13
14
cmds "github.com/ipfs/go-ipfs-cmds"
14
15
cmdenv "github.com/ipfs/kubo/core/commands/cmdenv"
15
- "github.com/ipld/go-ipld-prime"
16
- "github.com/ipld/go-ipld-prime/codec/dagcbor"
17
- "github.com/ipld/go-ipld-prime/codec/dagjson"
18
- "github.com/libp2p/go-libp2p/core/crypto"
19
- mbase "github.com/multiformats/go-multibase"
20
16
"google.golang.org/protobuf/proto"
21
17
)
22
18
@@ -83,27 +79,25 @@ Resolve the value of a dnslink:
83
79
}
84
80
85
81
type IpnsInspectValidation struct {
86
- Valid bool
87
- Reason string
88
- PublicKey string
82
+ Valid bool
83
+ Reason string
84
+ Name string
89
85
}
90
86
91
87
// IpnsInspectEntry contains the deserialized values from an IPNS Entry:
92
88
// https://github.com/ipfs/specs/blob/main/ipns/IPNS.md#record-serialization-format
93
89
type IpnsInspectEntry struct {
94
- Value string
95
- ValidityType * ipns_pb. IpnsRecord_ValidityType
90
+ Value * path. Path
91
+ ValidityType * ipns. ValidityType
96
92
Validity * time.Time
97
- Sequence uint64
98
- TTL * uint64
99
- PublicKey string
100
- SignatureV1 string
101
- SignatureV2 string
102
- Data interface {}
93
+ Sequence * uint64
94
+ TTL * time.Duration
103
95
}
104
96
105
97
type IpnsInspectResult struct {
106
98
Entry IpnsInspectEntry
99
+ Version string
100
+ HexDump string
107
101
Validation * IpnsInspectValidation
108
102
}
109
103
@@ -135,6 +129,7 @@ Passing --verify will verify signature against provided public key.
135
129
},
136
130
Options : []cmds.Option {
137
131
cmds .StringOption ("verify" , "CID of the public IPNS key to validate against." ),
132
+ cmds .BoolOption ("verbose" , "Show a full hex dump of the raw Protobuf record." ),
138
133
},
139
134
Run : func (req * cmds.Request , res cmds.ResponseEmitter , env cmds.Environment ) error {
140
135
file , err := cmdenv .GetFileArg (req .Files .Entries ())
@@ -150,96 +145,76 @@ Passing --verify will verify signature against provided public key.
150
145
return err
151
146
}
152
147
153
- // Here we use the old school raw Protobuf pbRecord because we want to inspect it,
154
- // aka, we need to be able to see all of its contents inside. While the boxo/ipns
155
- // provides a good abstraction over the Record type, it doesn't allow for introspection
156
- // of the raw value of the IpnsEntry.
157
- var pbRecord ipns_pb.IpnsRecord
158
- err = proto .Unmarshal (b .Bytes (), & pbRecord )
159
- if err != nil {
160
- return err
161
- }
162
-
163
148
rec , err := ipns .UnmarshalRecord (b .Bytes ())
164
149
if err != nil {
165
150
return err
166
151
}
167
152
168
- encoder , err := mbase .EncoderByName ("base64" )
169
- if err != nil {
170
- return err
171
- }
172
-
173
153
result := & IpnsInspectResult {
174
- Entry : IpnsInspectEntry {
175
- Value : string (pbRecord .Value ),
176
- ValidityType : pbRecord .ValidityType ,
177
- Sequence : * pbRecord .Sequence ,
178
- TTL : pbRecord .Ttl ,
179
- PublicKey : encoder .Encode (pbRecord .PubKey ),
180
- SignatureV1 : encoder .Encode (pbRecord .SignatureV1 ),
181
- SignatureV2 : encoder .Encode (pbRecord .SignatureV2 ),
182
- Data : nil ,
183
- },
154
+ Entry : IpnsInspectEntry {},
184
155
}
185
156
186
- if len (pbRecord .Data ) != 0 {
187
- // This is hacky. The variable node (datamodel.Node) doesn't directly marshal
188
- // to JSON. Therefore, we need to first decode from DAG-CBOR, then encode in
189
- // DAG-JSON and finally unmarshal it from JSON. Since DAG-JSON is a subset
190
- // of JSON, that should work. Then, we can store the final value in the
191
- // result.Entry.Data for further inspection.
192
- node , err := ipld .Decode (pbRecord .Data , dagcbor .Decode )
193
- if err != nil {
194
- return err
195
- }
157
+ // Best effort to get the fields. Show everything we can.
158
+ if v , err := rec .Value (); err == nil {
159
+ result .Entry .Value = & v
160
+ }
196
161
197
- var buf bytes.Buffer
198
- err = dagjson .Encode (node , & buf )
199
- if err != nil {
200
- return err
201
- }
162
+ if v , err := rec .ValidityType (); err == nil {
163
+ result .Entry .ValidityType = & v
164
+ }
202
165
203
- err = json .Unmarshal (buf .Bytes (), & result .Entry .Data )
204
- if err != nil {
205
- return err
206
- }
166
+ if v , err := rec .Validity (); err == nil {
167
+ result .Entry .Validity = & v
207
168
}
208
169
209
- validity , err := rec .Validity ()
210
- if err == nil {
211
- result .Entry .Validity = & validity
170
+ if v , err := rec .Sequence (); err == nil {
171
+ result .Entry .Sequence = & v
212
172
}
213
173
214
- verify , ok := req .Options ["verify" ].(string )
215
- if ok {
216
- name , err := ipns .NameFromString (verify )
217
- if err != nil {
218
- return err
219
- }
174
+ if v , err := rec .TTL (); err == nil {
175
+ result .Entry .TTL = & v
176
+ }
220
177
221
- pk , err := ipns .ExtractPublicKey (rec , name )
222
- if err != nil {
223
- return err
178
+ // Here we need the raw protobuf just to decide the version.
179
+ var pbRecord ipns_pb.IpnsRecord
180
+ err = proto .Unmarshal (b .Bytes (), & pbRecord )
181
+ if err != nil {
182
+ return err
183
+ }
184
+ if pbRecord .SignatureV1 != nil || pbRecord .Value != nil {
185
+ if pbRecord .Data != nil {
186
+ result .Version = "V1+V2"
187
+ } else {
188
+ result .Version = "V2"
224
189
}
190
+ } else if pbRecord .Data != nil {
191
+ result .Version = "V2"
192
+ } else {
193
+ result .Version = "Unknown"
194
+ }
225
195
226
- bytes , err := crypto .MarshalPublicKey (pk )
196
+ if verify , ok := req .Options ["verify" ].(string ); ok {
197
+ name , err := ipns .NameFromString (verify )
227
198
if err != nil {
228
199
return err
229
200
}
230
201
231
202
result .Validation = & IpnsInspectValidation {
232
- PublicKey : encoder . Encode ( bytes ),
203
+ Name : name . String ( ),
233
204
}
234
205
235
- err = ipns .Validate (rec , pk )
206
+ err = ipns .ValidateWithName (rec , name )
236
207
if err == nil {
237
208
result .Validation .Valid = true
238
209
} else {
239
210
result .Validation .Reason = err .Error ()
240
211
}
241
212
}
242
213
214
+ if verbose , ok := req .Options ["verbose" ].(bool ); ok && verbose {
215
+ result .HexDump = hex .Dump (b .Bytes ())
216
+ }
217
+
243
218
return cmds .EmitOnce (res , result )
244
219
},
245
220
Type : IpnsInspectResult {},
@@ -248,24 +223,25 @@ Passing --verify will verify signature against provided public key.
248
223
tw := tabwriter .NewWriter (w , 0 , 0 , 1 , ' ' , 0 )
249
224
defer tw .Flush ()
250
225
251
- fmt .Fprintf (tw , "Value:\t %q\n " , string (out .Entry .Value ))
252
- fmt .Fprintf (tw , "Validity Type:\t %q\n " , out .Entry .ValidityType )
226
+ if out .Entry .Value != nil {
227
+ fmt .Fprintf (tw , "Value:\t %q\n " , out .Entry .Value .String ())
228
+ }
229
+
230
+ if out .Entry .ValidityType != nil {
231
+ fmt .Fprintf (tw , "Validity Type:\t %q\n " , * out .Entry .ValidityType )
232
+ }
233
+
253
234
if out .Entry .Validity != nil {
254
- fmt .Fprintf (tw , "Validity:\t %s \n " , out .Entry .Validity .Format (time .RFC3339Nano ))
235
+ fmt .Fprintf (tw , "Validity:\t %q \n " , out .Entry .Validity .Format (time .RFC3339 ))
255
236
}
256
- fmt . Fprintf ( tw , "Sequence: \t %d \n " , out . Entry . Sequence )
257
- if out .Entry .TTL != nil {
258
- fmt .Fprintf (tw , "TTL :\t %d\n " , * out .Entry .TTL )
237
+
238
+ if out .Entry .Sequence != nil {
239
+ fmt .Fprintf (tw , "Sequence :\t %d\n " , * out .Entry .Sequence )
259
240
}
260
- fmt .Fprintf (tw , "PublicKey:\t %q\n " , out .Entry .PublicKey )
261
- fmt .Fprintf (tw , "Signature V1:\t %q\n " , out .Entry .SignatureV1 )
262
- fmt .Fprintf (tw , "Signature V2:\t %q\n " , out .Entry .SignatureV2 )
263
241
264
- data , err := json .Marshal (out .Entry .Data )
265
- if err != nil {
266
- return err
242
+ if out .Entry .TTL != nil {
243
+ fmt .Fprintf (tw , "TTL:\t %s\n " , out .Entry .TTL .String ())
267
244
}
268
- fmt .Fprintf (tw , "Data:\t %s\n " , string (data ))
269
245
270
246
if out .Validation == nil {
271
247
tw .Flush ()
@@ -278,7 +254,14 @@ Passing --verify will verify signature against provided public key.
278
254
if out .Validation .Reason != "" {
279
255
fmt .Fprintf (tw , "\t Reason:\t %s\n " , out .Validation .Reason )
280
256
}
281
- fmt .Fprintf (tw , "\t PublicKey:\t %s\n " , out .Validation .PublicKey )
257
+ fmt .Fprintf (tw , "\t Name:\t %s\n " , out .Validation .Name )
258
+ }
259
+
260
+ if out .HexDump != "" {
261
+ tw .Flush ()
262
+
263
+ fmt .Fprintf (w , "\n Hex Dump:\n " )
264
+ fmt .Fprintf (w , out .HexDump )
282
265
}
283
266
284
267
return nil
0 commit comments