Commit 42208278 authored by Steven Allen's avatar Steven Allen

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: default avatarSteven Allen <steven@stebalien.com>
parent 285da113
...@@ -3,6 +3,9 @@ package merkledag ...@@ -3,6 +3,9 @@ package merkledag
import ( import (
"fmt" "fmt"
"sort" "sort"
"strings"
"gx/ipfs/QmVA4mafxbfH5aEvNz8fyoxC6J1xhAtw88B4GerPznSZBg/go-block-format"
pb "github.com/ipfs/go-ipfs/merkledag/pb" pb "github.com/ipfs/go-ipfs/merkledag/pb"
...@@ -108,3 +111,27 @@ func DecodeProtobuf(encoded []byte) (*ProtoNode, error) { ...@@ -108,3 +111,27 @@ func DecodeProtobuf(encoded []byte) (*ProtoNode, error) {
} }
return n, nil 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
...@@ -4,7 +4,6 @@ package merkledag ...@@ -4,7 +4,6 @@ package merkledag
import ( import (
"context" "context"
"fmt" "fmt"
"strings"
"sync" "sync"
bserv "github.com/ipfs/go-ipfs/blockservice" bserv "github.com/ipfs/go-ipfs/blockservice"
...@@ -16,6 +15,15 @@ import ( ...@@ -16,6 +15,15 @@ import (
ipldcbor "gx/ipfs/QmemYymP73eVdTUUMZEiSpiHeZQKNJdT5dP2iuHssZh1sR/go-ipld-cbor" 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") var ErrNotFound = fmt.Errorf("merkledag: not found")
// DAGService is an IPFS Merkle DAG service. // DAGService is an IPFS Merkle DAG service.
...@@ -94,32 +102,7 @@ func (n *dagService) Get(ctx context.Context, c *cid.Cid) (node.Node, error) { ...@@ -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 nil, fmt.Errorf("Failed to get block for %s: %v", c, err)
} }
return decodeBlock(b) return node.Decode(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())
}
} }
// GetLinks return the links for the node, the node doesn't necessarily have // 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) { ...@@ -174,7 +157,7 @@ func (sg *sesGetter) Get(ctx context.Context, c *cid.Cid) (node.Node, error) {
return nil, err return nil, err
} }
return decodeBlock(blk) return node.Decode(blk)
} }
// FetchGraph fetches all nodes that are children of the given node // 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 ...@@ -235,7 +218,7 @@ func (ds *dagService) GetMany(ctx context.Context, keys []*cid.Cid) <-chan *Node
return return
} }
nd, err := decodeBlock(b) nd, err := node.Decode(b)
if err != nil { if err != nil {
out <- &NodeOption{Err: err} out <- &NodeOption{Err: err}
return return
......
package merkledag package merkledag
import ( import (
"fmt"
"gx/ipfs/QmVA4mafxbfH5aEvNz8fyoxC6J1xhAtw88B4GerPznSZBg/go-block-format" "gx/ipfs/QmVA4mafxbfH5aEvNz8fyoxC6J1xhAtw88B4GerPznSZBg/go-block-format"
u "gx/ipfs/QmSU6eubNdhXjFBJBSksTp8kv8YRub8mGAPv8tVJHmL2EU/go-ipfs-util" u "gx/ipfs/QmSU6eubNdhXjFBJBSksTp8kv8YRub8mGAPv8tVJHmL2EU/go-ipfs-util"
...@@ -22,6 +23,17 @@ func NewRawNode(data []byte) *RawNode { ...@@ -22,6 +23,17 @@ func NewRawNode(data []byte) *RawNode {
return &RawNode{blk} 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 // NewRawNodeWPrefix creates a RawNode with the hash function
// specified in prefix. // specified in prefix.
func NewRawNodeWPrefix(data []byte, prefix cid.Prefix) (*RawNode, error) { func NewRawNodeWPrefix(data []byte, prefix cid.Prefix) (*RawNode, error) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment