Skip to content

Commit

Permalink
Implement cbor ipld nodes and a first pass at the 'dag' command
Browse files Browse the repository at this point in the history
License: MIT
Signed-off-by: Jeromy <[email protected]>
  • Loading branch information
whyrusleeping committed Oct 25, 2016
1 parent 1c6e84c commit 6b797f1
Show file tree
Hide file tree
Showing 5 changed files with 229 additions and 8 deletions.
5 changes: 0 additions & 5 deletions core/commands/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package commands

import (
"bytes"
"errors"
"fmt"
"io"
"io/ioutil"
Expand Down Expand Up @@ -168,10 +167,6 @@ func getBlockForKey(req cmds.Request, skey string) (blocks.Block, error) {
return nil, err
}

if !u.IsValidHash(skey) {
return nil, errors.New("Not a valid hash")
}

c, err := cid.Decode(skey)
if err != nil {
return nil, err
Expand Down
216 changes: 216 additions & 0 deletions core/commands/dag/dag.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
package dagcmd

import (
"encoding/json"
"fmt"
"io"
"strings"

cmds "github.com/ipfs/go-ipfs/commands"

node "gx/ipfs/QmU7bFWQ793qmvNy7outdCaMfSDNk8uqhx4VNrxYj5fj5g/go-ipld-node"
cid "gx/ipfs/QmXfiyr2RWEXpVDdaYnD2HNiBk6UBddsvEP4RPfXb6nGqY/go-cid"
ipldcbor "gx/ipfs/QmYRzW9YDHVNCDbfFzbS7TEXAG1swE1yjq1basZ5WnJYH4/go-ipld-cbor"
)

var DagCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "Interact with ipld dag objects.",
ShortDescription: ``,
},

Subcommands: map[string]*cmds.Command{
"put": DagPutCmd,
"get": DagGetCmd,
},
}

type OutputObject struct {
Cid *cid.Cid
}

var DagPutCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "Add a dag node to ipfs.",
},
Arguments: []cmds.Argument{
cmds.FileArg("object data", true, false, "The object to put").EnableStdin(),
},
Options: []cmds.Option{
cmds.StringOption("format", "f", "Format that the object will be.").Default("cbor"),
cmds.StringOption("input-enc", "Format that the object will be.").Default("json"),
},
Run: func(req cmds.Request, res cmds.Response) {
n, err := req.InvocContext().GetNode()
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}

fi, err := req.Files().NextFile()
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}

ienc, _, _ := req.Option("input-enc").String()
format, _, _ := req.Option("format").String()
_ = format
switch ienc {
case "json":
var obj map[string]interface{}
err := json.NewDecoder(fi).Decode(&obj)
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}

nd, err := convertJsonToType(obj, format)
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}

c, err := n.DAG.Add(nd)
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}

res.SetOutput(&OutputObject{Cid: c})
return
/*
case "btc":
data, err := ioutil.ReadAll(fi)
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}
blk, err := ipldbtc.DecodeBlock(data)
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}
c, err := n.DAG.Add(blk)
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}
res.SetOutput(&OutputObject{Cid: c})
return
*/
}
},
Type: OutputObject{},
Marshalers: cmds.MarshalerMap{
cmds.Text: func(res cmds.Response) (io.Reader, error) {
oobj, ok := res.Output().(*OutputObject)
if !ok {
return nil, fmt.Errorf("expected a different object in marshaler")
}

return strings.NewReader(oobj.Cid.String()), nil
},
},
}

var DagGetCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "Get a dag node from ipfs.",
},
Arguments: []cmds.Argument{
cmds.StringArg("cid", true, false, "The cid of the object to get").EnableStdin(),
},
Run: func(req cmds.Request, res cmds.Response) {
n, err := req.InvocContext().GetNode()
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}

c, err := cid.Decode(req.Arguments()[0])
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}

obj, err := n.DAG.Get(req.Context(), c)
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}

res.SetOutput(obj)
},
}

func convertJsonToType(obj map[string]interface{}, format string) (node.Node, error) {
switch format {
case "cbor", "dag-cbor":
return convertJsonToCbor(obj)
case "dag-pb", "protobuf":
return nil, fmt.Errorf("protobuf handling in 'dag' command not yet implemented")
default:
return nil, fmt.Errorf("unknown target format: %s", format)
}
}

func convertJsonToCbor(from map[string]interface{}) (*ipldcbor.Node, error) {
out, err := convertMapSIToCbor(from)
if err != nil {
return nil, err
}

return ipldcbor.WrapMap(out)
}
func convertMapSIToCbor(from map[string]interface{}) (map[interface{}]interface{}, error) {
to := make(map[interface{}]interface{})
for k, v := range from {
out, err := convertToCborIshObj(v)
if err != nil {
return nil, err
}
to[k] = out
}

return to, nil
}

func convertToCborIshObj(i interface{}) (interface{}, error) {
switch v := i.(type) {
case map[string]interface{}:
if lnk, ok := v["/"]; ok && len(v) == 1 {
// special case for links
vstr, ok := lnk.(string)
if !ok {
return nil, fmt.Errorf("link should have been a string")
}

c, err := cid.Decode(vstr)
if err != nil {
return nil, err
}

return &ipldcbor.Link{Target: c}, nil
}

return convertMapSIToCbor(v)
case []interface{}:
var out []interface{}
for _, o := range v {
obj, err := convertToCborIshObj(o)
if err != nil {
return nil, err
}

out = append(out, obj)
}

return out, nil
default:
return v, nil
}
}
2 changes: 2 additions & 0 deletions core/commands/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"strings"

cmds "github.com/ipfs/go-ipfs/commands"
dag "github.com/ipfs/go-ipfs/core/commands/dag"
files "github.com/ipfs/go-ipfs/core/commands/files"
ocmd "github.com/ipfs/go-ipfs/core/commands/object"
unixfs "github.com/ipfs/go-ipfs/core/commands/unixfs"
Expand Down Expand Up @@ -86,6 +87,7 @@ var rootSubcommands = map[string]*cmds.Command{
"cat": CatCmd,
"commands": CommandsDaemonCmd,
"config": ConfigCmd,
"dag": dag.DagCmd,
"dht": DhtCmd,
"diag": DiagCmd,
"dns": DNSCmd,
Expand Down
7 changes: 7 additions & 0 deletions merkledag/merkledag.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
logging "gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log"
node "gx/ipfs/QmU7bFWQ793qmvNy7outdCaMfSDNk8uqhx4VNrxYj5fj5g/go-ipld-node"
cid "gx/ipfs/QmXfiyr2RWEXpVDdaYnD2HNiBk6UBddsvEP4RPfXb6nGqY/go-cid"
ipldcbor "gx/ipfs/QmYRzW9YDHVNCDbfFzbS7TEXAG1swE1yjq1basZ5WnJYH4/go-ipld-cbor"
)

var log = logging.Logger("merkledag")
Expand Down Expand Up @@ -105,6 +106,12 @@ func decodeBlock(b blocks.Block) (node.Node, error) {
return decnd, nil
case cid.Raw:
return NewRawNode(b.RawData()), nil
case cid.CBOR:
return ipldcbor.Decode(b.RawData())
/*
case cid.Bitcoin:
return ipldbtc.DecodeBlock(b.RawData())
*/
default:
return nil, fmt.Errorf("unrecognized object type: %s", c.Type())
}
Expand Down
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -277,9 +277,10 @@
"version": "0.3.2"
},
{
"hash": "QmQKEgGgYCDyk8VNY6A65FpuE4YwbspvjXHco1rdb75PVc",
"name": "go-libp2p-routing",
"version": "2.2.2"
"author": "whyrusleeping",
"hash": "QmYRzW9YDHVNCDbfFzbS7TEXAG1swE1yjq1basZ5WnJYH4",
"name": "go-ipld-cbor",
"version": "0.2.1"
}
],
"gxVersion": "0.4.0",
Expand Down

0 comments on commit 6b797f1

Please sign in to comment.