From 35984c2c884ddcb676abd142e58c8b80301398b8 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 11 Jul 2017 20:27:22 -0700 Subject: [PATCH] Change IPFS to use the new pluggable Block to IPLD decoding framework. Later, we should: 1. Pull the other node formats out of IPFS (at least the raw one). 2. Pull out the decoder registration/management into a `go-ipld` library. License: MIT Signed-off-by: Steven Allen --- merkledag/coding.go | 27 +++++++++++++++++++++++++++ merkledag/merkledag.go | 41 ++++++++++++----------------------------- merkledag/raw.go | 12 ++++++++++++ 3 files changed, 51 insertions(+), 29 deletions(-) diff --git a/merkledag/coding.go b/merkledag/coding.go index c66bb889a47..39da14a099d 100644 --- a/merkledag/coding.go +++ b/merkledag/coding.go @@ -3,6 +3,9 @@ package merkledag import ( "fmt" "sort" + "strings" + + "gx/ipfs/QmVA4mafxbfH5aEvNz8fyoxC6J1xhAtw88B4GerPznSZBg/go-block-format" pb "github.com/ipfs/go-ipfs/merkledag/pb" @@ -108,3 +111,27 @@ func DecodeProtobuf(encoded []byte) (*ProtoNode, error) { } return n, nil } + +// DecodeProtobufBlock is a block decoder for protobuf IPLD nodes conforming to +// node.DecodeBlockFunc +func DecodeProtobufBlock(b blocks.Block) (node.Node, error) { + c := b.Cid() + if c.Type() != cid.DagProtobuf { + return nil, fmt.Errorf("this function can only decode protobuf nodes") + } + + decnd, err := DecodeProtobuf(b.RawData()) + if err != nil { + if strings.Contains(err.Error(), "Unmarshal failed") { + return nil, fmt.Errorf("The block referred to by '%s' was not a valid merkledag node", c) + } + return nil, fmt.Errorf("Failed to decode Protocol Buffers: %v", err) + } + + decnd.cached = c + decnd.Prefix = c.Prefix() + return decnd, nil +} + +// Type assertion +var _ node.DecodeBlockFunc = DecodeProtobufBlock diff --git a/merkledag/merkledag.go b/merkledag/merkledag.go index b033af405f8..82b1693ae6c 100644 --- a/merkledag/merkledag.go +++ b/merkledag/merkledag.go @@ -4,7 +4,6 @@ package merkledag import ( "context" "fmt" - "strings" "sync" bserv "github.com/ipfs/go-ipfs/blockservice" @@ -16,6 +15,15 @@ import ( ipldcbor "gx/ipfs/QmemYymP73eVdTUUMZEiSpiHeZQKNJdT5dP2iuHssZh1sR/go-ipld-cbor" ) +// TODO: We should move these registrations elsewhere. Really, most of the IPLD +// functionality should go in a `go-ipld` repo but that will take a lot of work +// and design. +func init() { + node.Register(cid.DagProtobuf, DecodeProtobufBlock) + node.Register(cid.Raw, DecodeRawBlock) + node.Register(cid.DagCBOR, ipldcbor.DecodeBlock) +} + var ErrNotFound = fmt.Errorf("merkledag: not found") // DAGService is an IPFS Merkle DAG service. @@ -94,32 +102,7 @@ func (n *dagService) Get(ctx context.Context, c *cid.Cid) (node.Node, error) { return nil, fmt.Errorf("Failed to get block for %s: %v", c, err) } - return decodeBlock(b) -} - -func decodeBlock(b blocks.Block) (node.Node, error) { - c := b.Cid() - - switch c.Type() { - case cid.DagProtobuf: - decnd, err := DecodeProtobuf(b.RawData()) - if err != nil { - if strings.Contains(err.Error(), "Unmarshal failed") { - return nil, fmt.Errorf("The block referred to by '%s' was not a valid merkledag node", c) - } - return nil, fmt.Errorf("Failed to decode Protocol Buffers: %v", err) - } - - decnd.cached = b.Cid() - decnd.Prefix = b.Cid().Prefix() - return decnd, nil - case cid.Raw: - return NewRawNodeWPrefix(b.RawData(), b.Cid().Prefix()) - case cid.DagCBOR: - return ipldcbor.Decode(b.RawData()) - default: - return nil, fmt.Errorf("unrecognized object type: %s", c.Type()) - } + return node.Decode(b) } // GetLinks return the links for the node, the node doesn't necessarily have @@ -174,7 +157,7 @@ func (sg *sesGetter) Get(ctx context.Context, c *cid.Cid) (node.Node, error) { return nil, err } - return decodeBlock(blk) + return node.Decode(blk) } // FetchGraph fetches all nodes that are children of the given node @@ -235,7 +218,7 @@ func (ds *dagService) GetMany(ctx context.Context, keys []*cid.Cid) <-chan *Node return } - nd, err := decodeBlock(b) + nd, err := node.Decode(b) if err != nil { out <- &NodeOption{Err: err} return diff --git a/merkledag/raw.go b/merkledag/raw.go index 9d1e18671e3..856a407fccc 100644 --- a/merkledag/raw.go +++ b/merkledag/raw.go @@ -1,6 +1,7 @@ package merkledag import ( + "fmt" "gx/ipfs/QmVA4mafxbfH5aEvNz8fyoxC6J1xhAtw88B4GerPznSZBg/go-block-format" u "gx/ipfs/QmSU6eubNdhXjFBJBSksTp8kv8YRub8mGAPv8tVJHmL2EU/go-ipfs-util" @@ -22,6 +23,17 @@ func NewRawNode(data []byte) *RawNode { return &RawNode{blk} } +// DecodeRawBlock is a block decoder for raw IPLD nodes conforming to `node.DecodeBlockFunc`. +func DecodeRawBlock(block blocks.Block) (node.Node, error) { + if block.Cid().Type() != cid.Raw { + return nil, fmt.Errorf("raw nodes cannot be decoded from non-raw blocks: %d", block.Cid().Type()) + } + // Once you "share" a block, it should be immutable. Therefore, we can just use this block as-is. + return &RawNode{block}, nil +} + +var _ node.DecodeBlockFunc = DecodeRawBlock + // NewRawNodeWPrefix creates a RawNode with the hash function // specified in prefix. func NewRawNodeWPrefix(data []byte, prefix cid.Prefix) (*RawNode, error) {