Skip to content

Commit 6b797f1

Browse files
committed
Implement cbor ipld nodes and a first pass at the 'dag' command
License: MIT Signed-off-by: Jeromy <why@ipfs.io>
1 parent 1c6e84c commit 6b797f1

File tree

5 files changed

+229
-8
lines changed

5 files changed

+229
-8
lines changed

core/commands/block.go

-5
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package commands
22

33
import (
44
"bytes"
5-
"errors"
65
"fmt"
76
"io"
87
"io/ioutil"
@@ -168,10 +167,6 @@ func getBlockForKey(req cmds.Request, skey string) (blocks.Block, error) {
168167
return nil, err
169168
}
170169

171-
if !u.IsValidHash(skey) {
172-
return nil, errors.New("Not a valid hash")
173-
}
174-
175170
c, err := cid.Decode(skey)
176171
if err != nil {
177172
return nil, err

core/commands/dag/dag.go

+216
Original file line numberDiff line numberDiff line change
@@ -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
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"strings"
66

77
cmds "github.com/ipfs/go-ipfs/commands"
8+
dag "github.com/ipfs/go-ipfs/core/commands/dag"
89
files "github.com/ipfs/go-ipfs/core/commands/files"
910
ocmd "github.com/ipfs/go-ipfs/core/commands/object"
1011
unixfs "github.com/ipfs/go-ipfs/core/commands/unixfs"
@@ -86,6 +87,7 @@ var rootSubcommands = map[string]*cmds.Command{
8687
"cat": CatCmd,
8788
"commands": CommandsDaemonCmd,
8889
"config": ConfigCmd,
90+
"dag": dag.DagCmd,
8991
"dht": DhtCmd,
9092
"diag": DiagCmd,
9193
"dns": DNSCmd,

merkledag/merkledag.go

+7
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
logging "gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log"
1515
node "gx/ipfs/QmU7bFWQ793qmvNy7outdCaMfSDNk8uqhx4VNrxYj5fj5g/go-ipld-node"
1616
cid "gx/ipfs/QmXfiyr2RWEXpVDdaYnD2HNiBk6UBddsvEP4RPfXb6nGqY/go-cid"
17+
ipldcbor "gx/ipfs/QmYRzW9YDHVNCDbfFzbS7TEXAG1swE1yjq1basZ5WnJYH4/go-ipld-cbor"
1718
)
1819

1920
var log = logging.Logger("merkledag")
@@ -105,6 +106,12 @@ func decodeBlock(b blocks.Block) (node.Node, error) {
105106
return decnd, nil
106107
case cid.Raw:
107108
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+
*/
108115
default:
109116
return nil, fmt.Errorf("unrecognized object type: %s", c.Type())
110117
}

package.json

+4-3
Original file line numberDiff line numberDiff line change
@@ -277,9 +277,10 @@
277277
"version": "0.3.2"
278278
},
279279
{
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"
283284
}
284285
],
285286
"gxVersion": "0.4.0",

0 commit comments

Comments
 (0)