Skip to content

Commit

Permalink
Merge pull request #4060 from ipfs/feat/pluggable-ipld-decoding
Browse files Browse the repository at this point in the history
Change IPFS to use the new pluggable Block to IPLD decoding framework.
  • Loading branch information
whyrusleeping authored Jul 12, 2017
2 parents 636a71e + 35984c2 commit 06c567d
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 29 deletions.
27 changes: 27 additions & 0 deletions merkledag/coding.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ package merkledag
import (
"fmt"
"sort"
"strings"

"gx/ipfs/QmVA4mafxbfH5aEvNz8fyoxC6J1xhAtw88B4GerPznSZBg/go-block-format"

pb "github.com/ipfs/go-ipfs/merkledag/pb"

Expand Down Expand Up @@ -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
41 changes: 12 additions & 29 deletions merkledag/merkledag.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ package merkledag
import (
"context"
"fmt"
"strings"
"sync"

bserv "github.com/ipfs/go-ipfs/blockservice"
Expand All @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
12 changes: 12 additions & 0 deletions merkledag/raw.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package merkledag

import (
"fmt"
"gx/ipfs/QmVA4mafxbfH5aEvNz8fyoxC6J1xhAtw88B4GerPznSZBg/go-block-format"

u "gx/ipfs/QmSU6eubNdhXjFBJBSksTp8kv8YRub8mGAPv8tVJHmL2EU/go-ipfs-util"
Expand All @@ -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) {
Expand Down

0 comments on commit 06c567d

Please sign in to comment.