-
Notifications
You must be signed in to change notification settings - Fork 43
/
ipld.go
102 lines (90 loc) · 2.2 KB
/
ipld.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
package crdt
import (
"context"
"errors"
dag "github.com/ipfs/boxo/ipld/merkledag"
cid "github.com/ipfs/go-cid"
pb "github.com/ipfs/go-ds-crdt/pb"
ipld "github.com/ipfs/go-ipld-format"
"google.golang.org/protobuf/proto"
)
// IPLD related things
var _ ipld.NodeGetter = (*crdtNodeGetter)(nil)
// crdtNodeGetter wraps an ipld.NodeGetter with some additional utility methods
type crdtNodeGetter struct {
ipld.NodeGetter
}
func (ng *crdtNodeGetter) GetDelta(ctx context.Context, c cid.Cid) (ipld.Node, *pb.Delta, error) {
nd, err := ng.Get(ctx, c)
if err != nil {
return nil, nil, err
}
delta, err := extractDelta(nd)
return nd, delta, err
}
// GetHeight returns the height of a block
func (ng *crdtNodeGetter) GetPriority(ctx context.Context, c cid.Cid) (uint64, error) {
_, delta, err := ng.GetDelta(ctx, c)
if err != nil {
return 0, err
}
return delta.Priority, nil
}
type deltaOption struct {
delta *pb.Delta
node ipld.Node
err error
}
// GetDeltas uses GetMany to obtain many deltas.
func (ng *crdtNodeGetter) GetDeltas(ctx context.Context, cids []cid.Cid) <-chan *deltaOption {
deltaOpts := make(chan *deltaOption, 1)
go func() {
defer close(deltaOpts)
nodeOpts := ng.GetMany(ctx, cids)
for nodeOpt := range nodeOpts {
if nodeOpt.Err != nil {
deltaOpts <- &deltaOption{err: nodeOpt.Err}
continue
}
delta, err := extractDelta(nodeOpt.Node)
if err != nil {
deltaOpts <- &deltaOption{err: err}
continue
}
deltaOpts <- &deltaOption{
delta: delta,
node: nodeOpt.Node,
}
}
}()
return deltaOpts
}
func extractDelta(nd ipld.Node) (*pb.Delta, error) {
protonode, ok := nd.(*dag.ProtoNode)
if !ok {
return nil, errors.New("node is not a ProtoNode")
}
d := pb.Delta{}
err := proto.Unmarshal(protonode.Data(), &d)
return &d, err
}
func makeNode(delta *pb.Delta, heads []cid.Cid) (ipld.Node, error) {
var data []byte
var err error
if delta != nil {
data, err = proto.Marshal(delta)
if err != nil {
return nil, err
}
}
nd := dag.NodeWithData(data)
for _, h := range heads {
err = nd.AddRawLink("", &ipld.Link{Cid: h})
if err != nil {
return nil, err
}
}
// Ensure we work with CIDv1
nd.SetCidBuilder(dag.V1CidPrefix())
return nd, nil
}