diff --git a/core/commands/block.go b/core/commands/block.go index e8e7890f1..c907a8593 100644 --- a/core/commands/block.go +++ b/core/commands/block.go @@ -2,7 +2,6 @@ package commands import ( "bytes" - "errors" "fmt" "io" "io/ioutil" @@ -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 diff --git a/core/commands/dag/dag.go b/core/commands/dag/dag.go new file mode 100644 index 000000000..34b1f1bb1 --- /dev/null +++ b/core/commands/dag/dag.go @@ -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 + } +} diff --git a/core/commands/root.go b/core/commands/root.go index 288090275..a034bd8b3 100644 --- a/core/commands/root.go +++ b/core/commands/root.go @@ -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" @@ -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, diff --git a/merkledag/merkledag.go b/merkledag/merkledag.go index 4867e583f..7b15fa4d5 100644 --- a/merkledag/merkledag.go +++ b/merkledag/merkledag.go @@ -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") @@ -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()) } diff --git a/package.json b/package.json index 829fb1527..21e9ec4a9 100644 --- a/package.json +++ b/package.json @@ -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",