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 <steven@stebalien.com>
Steven Allen committed
Jul 11, 2017 at 20:27 UTC
35984c2c884ddcb676abd142e58c8b80301398b8
3 files changed
+51
-29
merkledag/coding.go
+27
@@ -3,6 +3,9 @@ package merkledag
3
import (
4
"fmt"
5
"sort"
6
+ "strings"
7
+
8
+ "gx/ipfs/QmVA4mafxbfH5aEvNz8fyoxC6J1xhAtw88B4GerPznSZBg/go-block-format"
9
10
pb "github.com/ipfs/go-ipfs/merkledag/pb"
11
@@ -108,3 +111,27 @@ func DecodeProtobuf(encoded []byte) (*ProtoNode, error) {
111
}
112
return n, nil
113
}
114
+
115
+// DecodeProtobufBlock is a block decoder for protobuf IPLD nodes conforming to
116
+// node.DecodeBlockFunc
117
+func DecodeProtobufBlock(b blocks.Block) (node.Node, error) {
118
+ c := b.Cid()
119
+ if c.Type() != cid.DagProtobuf {
120
+ return nil, fmt.Errorf("this function can only decode protobuf nodes")
121
+ }
122
+
123
+ decnd, err := DecodeProtobuf(b.RawData())
124
+ if err != nil {
125
+ if strings.Contains(err.Error(), "Unmarshal failed") {
126
+ return nil, fmt.Errorf("The block referred to by '%s' was not a valid merkledag node", c)
127
+ }
128
+ return nil, fmt.Errorf("Failed to decode Protocol Buffers: %v", err)
129
+ }
130
+
131
+ decnd.cached = c
132
+ decnd.Prefix = c.Prefix()
133
+ return decnd, nil
134
+}
135
+
136
+// Type assertion
137
+var _ node.DecodeBlockFunc = DecodeProtobufBlock
merkledag/merkledag.go
+12
-29
@@ -4,7 +4,6 @@ package merkledag
4
import (
5
"context"
6
"fmt"
7
- "strings"
7
"sync"
8
9
bserv "github.com/ipfs/go-ipfs/blockservice"
@@ -16,6 +15,15 @@ import (
15
ipldcbor "gx/ipfs/QmemYymP73eVdTUUMZEiSpiHeZQKNJdT5dP2iuHssZh1sR/go-ipld-cbor"
16
)
17
18
+// TODO: We should move these registrations elsewhere. Really, most of the IPLD
19
+// functionality should go in a `go-ipld` repo but that will take a lot of work
20
+// and design.
21
+func init() {
22
+ node.Register(cid.DagProtobuf, DecodeProtobufBlock)
23
+ node.Register(cid.Raw, DecodeRawBlock)
24
+ node.Register(cid.DagCBOR, ipldcbor.DecodeBlock)
25
+}
26
+
27
var ErrNotFound = fmt.Errorf("merkledag: not found")
28
29
// DAGService is an IPFS Merkle DAG service.
@@ -94,32 +102,7 @@ func (n *dagService) Get(ctx context.Context, c *cid.Cid) (node.Node, error) {
102
return nil, fmt.Errorf("Failed to get block for %s: %v", c, err)
103
}
104
97
- return decodeBlock(b)
98
-}
99
-
100
-func decodeBlock(b blocks.Block) (node.Node, error) {
101
- c := b.Cid()
102
-
103
- switch c.Type() {
104
- case cid.DagProtobuf:
105
- decnd, err := DecodeProtobuf(b.RawData())
106
- if err != nil {
107
- if strings.Contains(err.Error(), "Unmarshal failed") {
108
- return nil, fmt.Errorf("The block referred to by '%s' was not a valid merkledag node", c)
109
- }
110
- return nil, fmt.Errorf("Failed to decode Protocol Buffers: %v", err)
111
- }
112
-
113
- decnd.cached = b.Cid()
114
- decnd.Prefix = b.Cid().Prefix()
115
- return decnd, nil
116
- case cid.Raw:
117
- return NewRawNodeWPrefix(b.RawData(), b.Cid().Prefix())
118
- case cid.DagCBOR:
119
- return ipldcbor.Decode(b.RawData())
120
- default:
121
- return nil, fmt.Errorf("unrecognized object type: %s", c.Type())
122
- }
105
+ return node.Decode(b)
106
}
107
108
// 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) {
157
return nil, err
158
}
159
177
- return decodeBlock(blk)
160
+ return node.Decode(blk)
161
}
162
163
// 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
218
return
219
}
220
238
- nd, err := decodeBlock(b)
221
+ nd, err := node.Decode(b)
222
if err != nil {
223
out <- &NodeOption{Err: err}
224
return
merkledag/raw.go
+12
@@ -1,6 +1,7 @@
1
package merkledag
2
3
import (
4
+ "fmt"
5
"gx/ipfs/QmVA4mafxbfH5aEvNz8fyoxC6J1xhAtw88B4GerPznSZBg/go-block-format"
6
7
u "gx/ipfs/QmSU6eubNdhXjFBJBSksTp8kv8YRub8mGAPv8tVJHmL2EU/go-ipfs-util"
@@ -22,6 +23,17 @@ func NewRawNode(data []byte) *RawNode {
23
return &RawNode{blk}
24
}
25
26
+// DecodeRawBlock is a block decoder for raw IPLD nodes conforming to `node.DecodeBlockFunc`.
27
+func DecodeRawBlock(block blocks.Block) (node.Node, error) {
28
+ if block.Cid().Type() != cid.Raw {
29
+ return nil, fmt.Errorf("raw nodes cannot be decoded from non-raw blocks: %d", block.Cid().Type())
30
+ }
31
+ // Once you "share" a block, it should be immutable. Therefore, we can just use this block as-is.
32
+ return &RawNode{block}, nil
33
+}
34
+
35
+var _ node.DecodeBlockFunc = DecodeRawBlock
36
+
37
// NewRawNodeWPrefix creates a RawNode with the hash function
38
// specified in prefix.
39
func NewRawNodeWPrefix(data []byte, prefix cid.Prefix) (*RawNode, error) {