Implement cbor ipld nodes and a first pass at the 'dag' command
License: MIT Signed-off-by: Jeromy <why@ipfs.io>
Jeromy committed
Oct 24, 2016 at 12:00 UTC
6b797f10a41002d7b9dfcba473e187b31e6ea0a1
5 files changed
+229
-8
core/commands/block.go
-5
@@ -2,7 +2,6 @@ package commands
2
3
import (
4
"bytes"
5
- "errors"
5
"fmt"
6
"io"
7
"io/ioutil"
@@ -168,10 +167,6 @@ func getBlockForKey(req cmds.Request, skey string) (blocks.Block, error) {
167
return nil, err
168
}
169
171
- if !u.IsValidHash(skey) {
172
- return nil, errors.New("Not a valid hash")
173
- }
174
-
170
c, err := cid.Decode(skey)
171
if err != nil {
172
return nil, err
core/commands/dag/dag.go
new
+216
@@ -0,0 +1,216 @@
1
+package dagcmd
2
+
3
+import (
4
+ "encoding/json"
5
+ "fmt"
6
+ "io"
7
+ "strings"
8
+
9
+ cmds "github.com/ipfs/go-ipfs/commands"
10
+
11
+ node "gx/ipfs/QmU7bFWQ793qmvNy7outdCaMfSDNk8uqhx4VNrxYj5fj5g/go-ipld-node"
12
+ cid "gx/ipfs/QmXfiyr2RWEXpVDdaYnD2HNiBk6UBddsvEP4RPfXb6nGqY/go-cid"
13
+ ipldcbor "gx/ipfs/QmYRzW9YDHVNCDbfFzbS7TEXAG1swE1yjq1basZ5WnJYH4/go-ipld-cbor"
14
+)
15
+
16
+var DagCmd = &cmds.Command{
17
+ Helptext: cmds.HelpText{
18
+ Tagline: "Interact with ipld dag objects.",
19
+ ShortDescription: ``,
20
+ },
21
+
22
+ Subcommands: map[string]*cmds.Command{
23
+ "put": DagPutCmd,
24
+ "get": DagGetCmd,
25
+ },
26
+}
27
+
28
+type OutputObject struct {
29
+ Cid *cid.Cid
30
+}
31
+
32
+var DagPutCmd = &cmds.Command{
33
+ Helptext: cmds.HelpText{
34
+ Tagline: "Add a dag node to ipfs.",
35
+ },
36
+ Arguments: []cmds.Argument{
37
+ cmds.FileArg("object data", true, false, "The object to put").EnableStdin(),
38
+ },
39
+ Options: []cmds.Option{
40
+ cmds.StringOption("format", "f", "Format that the object will be.").Default("cbor"),
41
+ cmds.StringOption("input-enc", "Format that the object will be.").Default("json"),
42
+ },
43
+ Run: func(req cmds.Request, res cmds.Response) {
44
+ n, err := req.InvocContext().GetNode()
45
+ if err != nil {
46
+ res.SetError(err, cmds.ErrNormal)
47
+ return
48
+ }
49
+
50
+ fi, err := req.Files().NextFile()
51
+ if err != nil {
52
+ res.SetError(err, cmds.ErrNormal)
53
+ return
54
+ }
55
+
56
+ ienc, _, _ := req.Option("input-enc").String()
57
+ format, _, _ := req.Option("format").String()
58
+ _ = format
59
+ switch ienc {
60
+ case "json":
61
+ var obj map[string]interface{}
62
+ err := json.NewDecoder(fi).Decode(&obj)
63
+ if err != nil {
64
+ res.SetError(err, cmds.ErrNormal)
65
+ return
66
+ }
67
+
68
+ nd, err := convertJsonToType(obj, format)
69
+ if err != nil {
70
+ res.SetError(err, cmds.ErrNormal)
71
+ return
72
+ }
73
+
74
+ c, err := n.DAG.Add(nd)
75
+ if err != nil {
76
+ res.SetError(err, cmds.ErrNormal)
77
+ return
78
+ }
79
+
80
+ res.SetOutput(&OutputObject{Cid: c})
81
+ return
82
+ /*
83
+ case "btc":
84
+ data, err := ioutil.ReadAll(fi)
85
+ if err != nil {
86
+ res.SetError(err, cmds.ErrNormal)
87
+ return
88
+ }
89
+
90
+ blk, err := ipldbtc.DecodeBlock(data)
91
+ if err != nil {
92
+ res.SetError(err, cmds.ErrNormal)
93
+ return
94
+ }
95
+
96
+ c, err := n.DAG.Add(blk)
97
+ if err != nil {
98
+ res.SetError(err, cmds.ErrNormal)
99
+ return
100
+ }
101
+
102
+ res.SetOutput(&OutputObject{Cid: c})
103
+ return
104
+ */
105
+ }
106
+ },
107
+ Type: OutputObject{},
108
+ Marshalers: cmds.MarshalerMap{
109
+ cmds.Text: func(res cmds.Response) (io.Reader, error) {
110
+ oobj, ok := res.Output().(*OutputObject)
111
+ if !ok {
112
+ return nil, fmt.Errorf("expected a different object in marshaler")
113
+ }
114
+
115
+ return strings.NewReader(oobj.Cid.String()), nil
116
+ },
117
+ },
118
+}
119
+
120
+var DagGetCmd = &cmds.Command{
121
+ Helptext: cmds.HelpText{
122
+ Tagline: "Get a dag node from ipfs.",
123
+ },
124
+ Arguments: []cmds.Argument{
125
+ cmds.StringArg("cid", true, false, "The cid of the object to get").EnableStdin(),
126
+ },
127
+ Run: func(req cmds.Request, res cmds.Response) {
128
+ n, err := req.InvocContext().GetNode()
129
+ if err != nil {
130
+ res.SetError(err, cmds.ErrNormal)
131
+ return
132
+ }
133
+
134
+ c, err := cid.Decode(req.Arguments()[0])
135
+ if err != nil {
136
+ res.SetError(err, cmds.ErrNormal)
137
+ return
138
+ }
139
+
140
+ obj, err := n.DAG.Get(req.Context(), c)
141
+ if err != nil {
142
+ res.SetError(err, cmds.ErrNormal)
143
+ return
144
+ }
145
+
146
+ res.SetOutput(obj)
147
+ },
148
+}
149
+
150
+func convertJsonToType(obj map[string]interface{}, format string) (node.Node, error) {
151
+ switch format {
152
+ case "cbor", "dag-cbor":
153
+ return convertJsonToCbor(obj)
154
+ case "dag-pb", "protobuf":
155
+ return nil, fmt.Errorf("protobuf handling in 'dag' command not yet implemented")
156
+ default:
157
+ return nil, fmt.Errorf("unknown target format: %s", format)
158
+ }
159
+}
160
+
161
+func convertJsonToCbor(from map[string]interface{}) (*ipldcbor.Node, error) {
162
+ out, err := convertMapSIToCbor(from)
163
+ if err != nil {
164
+ return nil, err
165
+ }
166
+
167
+ return ipldcbor.WrapMap(out)
168
+}
169
+func convertMapSIToCbor(from map[string]interface{}) (map[interface{}]interface{}, error) {
170
+ to := make(map[interface{}]interface{})
171
+ for k, v := range from {
172
+ out, err := convertToCborIshObj(v)
173
+ if err != nil {
174
+ return nil, err
175
+ }
176
+ to[k] = out
177
+ }
178
+
179
+ return to, nil
180
+}
181
+
182
+func convertToCborIshObj(i interface{}) (interface{}, error) {
183
+ switch v := i.(type) {
184
+ case map[string]interface{}:
185
+ if lnk, ok := v["/"]; ok && len(v) == 1 {
186
+ // special case for links
187
+ vstr, ok := lnk.(string)
188
+ if !ok {
189
+ return nil, fmt.Errorf("link should have been a string")
190
+ }
191
+
192
+ c, err := cid.Decode(vstr)
193
+ if err != nil {
194
+ return nil, err
195
+ }
196
+
197
+ return &ipldcbor.Link{Target: c}, nil
198
+ }
199
+
200
+ return convertMapSIToCbor(v)
201
+ case []interface{}:
202
+ var out []interface{}
203
+ for _, o := range v {
204
+ obj, err := convertToCborIshObj(o)
205
+ if err != nil {
206
+ return nil, err
207
+ }
208
+
209
+ out = append(out, obj)
210
+ }
211
+
212
+ return out, nil
213
+ default:
214
+ return v, nil
215
+ }
216
+}
core/commands/root.go
+2
@@ -5,6 +5,7 @@ import (
5
"strings"
6
7
cmds "github.com/ipfs/go-ipfs/commands"
8
+ dag "github.com/ipfs/go-ipfs/core/commands/dag"
9
files "github.com/ipfs/go-ipfs/core/commands/files"
10
ocmd "github.com/ipfs/go-ipfs/core/commands/object"
11
unixfs "github.com/ipfs/go-ipfs/core/commands/unixfs"
@@ -86,6 +87,7 @@ var rootSubcommands = map[string]*cmds.Command{
87
"cat": CatCmd,
88
"commands": CommandsDaemonCmd,
89
"config": ConfigCmd,
90
+ "dag": dag.DagCmd,
91
"dht": DhtCmd,
92
"diag": DiagCmd,
93
"dns": DNSCmd,
merkledag/merkledag.go
+7
@@ -14,6 +14,7 @@ import (
14
logging "gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log"
15
node "gx/ipfs/QmU7bFWQ793qmvNy7outdCaMfSDNk8uqhx4VNrxYj5fj5g/go-ipld-node"
16
cid "gx/ipfs/QmXfiyr2RWEXpVDdaYnD2HNiBk6UBddsvEP4RPfXb6nGqY/go-cid"
17
+ ipldcbor "gx/ipfs/QmYRzW9YDHVNCDbfFzbS7TEXAG1swE1yjq1basZ5WnJYH4/go-ipld-cbor"
18
)
19
20
var log = logging.Logger("merkledag")
@@ -105,6 +106,12 @@ func decodeBlock(b blocks.Block) (node.Node, error) {
106
return decnd, nil
107
case cid.Raw:
108
return NewRawNode(b.RawData()), nil
109
+ case cid.CBOR:
110
+ return ipldcbor.Decode(b.RawData())
111
+ /*
112
+ case cid.Bitcoin:
113
+ return ipldbtc.DecodeBlock(b.RawData())
114
+ */
115
default:
116
return nil, fmt.Errorf("unrecognized object type: %s", c.Type())
117
}
package.json
+4
-3
@@ -277,9 +277,10 @@
277
"version": "0.3.2"
278
},
279
{
280
- "hash": "QmQKEgGgYCDyk8VNY6A65FpuE4YwbspvjXHco1rdb75PVc",
281
- "name": "go-libp2p-routing",
282
- "version": "2.2.2"
280
+ "author": "whyrusleeping",
281
+ "hash": "QmYRzW9YDHVNCDbfFzbS7TEXAG1swE1yjq1basZ5WnJYH4",
282
+ "name": "go-ipld-cbor",
283
+ "version": "0.2.1"
284
}
285
],
286
"gxVersion": "0.4.0",