Skip to content

Commit 8ef2008

Browse files
mvdanrvagg
authored andcommitted
feat(net): to/from ipld bindnode types, more cbor protoc improvements
1 parent caa4b58 commit 8ef2008

10 files changed

Lines changed: 604 additions & 425 deletions

File tree

go.mod

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ module github.com/ipfs/go-graphsync
33
go 1.16
44

55
require (
6-
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c // indirect
6+
github.com/google/go-cmp v0.5.6
77
github.com/google/uuid v1.3.0
8+
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c // indirect
89
github.com/hannahhoward/cbor-gen-for v0.0.0-20200817222906-ea96cece81f1
910
github.com/hannahhoward/go-pubsub v0.0.0-20200423002714-8d62886cc36e
1011
github.com/ipfs/go-block-format v0.0.3
@@ -48,5 +49,3 @@ require (
4849
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1
4950
google.golang.org/protobuf v1.27.1
5051
)
51-
52-
replace github.com/ipld/go-ipld-prime => ../../ipld/go-ipld-prime

message/bench_test.go

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1-
package message_test
1+
package message
22

33
import (
44
"bytes"
55
"math/rand"
6+
"reflect"
67
"testing"
78

9+
"github.com/google/go-cmp/cmp"
810
blocks "github.com/ipfs/go-block-format"
911
"github.com/ipfs/go-graphsync"
10-
"github.com/ipfs/go-graphsync/message"
12+
"github.com/ipfs/go-graphsync/message/ipldbind"
1113
"github.com/ipfs/go-graphsync/testutil"
1214
"github.com/ipld/go-ipld-prime/codec/dagcbor"
1315
"github.com/ipld/go-ipld-prime/node/basicnode"
@@ -21,16 +23,17 @@ func BenchmarkMessageEncodingRoundtrip(b *testing.B) {
2123
ssb := builder.NewSelectorSpecBuilder(basicnode.Prototype.Any)
2224
selector := ssb.Matcher().Node()
2325
extensionName := graphsync.ExtensionName("graphsync/awesome")
24-
extension := message.NamedExtension{
26+
extension := graphsync.ExtensionData{
2527
Name: extensionName,
26-
Data: basicnode.NewBytes(testutil.RandomBytes(100)),
28+
Data: testutil.RandomBytes(100),
2729
}
2830
id := graphsync.NewRequestID()
2931
priority := graphsync.Priority(rand.Int31())
3032
status := graphsync.RequestAcknowledged
3133

32-
builder := message.NewBuilder()
33-
builder.AddRequest(message.NewRequest(id, root, selector, priority, extension))
34+
builder := NewBuilder()
35+
builder.AddRequest(NewRequest(id, root, selector, priority, extension))
36+
builder.AddRequest(NewRequest(id, root, selector, priority))
3437
builder.AddResponseCode(id, status)
3538
builder.AddExtensionData(id, extension)
3639
builder.AddBlock(blocks.NewBlock([]byte("W")))
@@ -48,12 +51,17 @@ func BenchmarkMessageEncodingRoundtrip(b *testing.B) {
4851
for pb.Next() {
4952
buf.Reset()
5053

51-
err := message.NewMessageHandler().ToNet(gsm, buf)
54+
err := NewMessageHandler().ToNet(gsm, buf)
5255
require.NoError(b, err)
5356

54-
gsm2, err := message.NewMessageHandler().FromNet(buf)
57+
gsm2, err := NewMessageHandler().FromNet(buf)
5558
require.NoError(b, err)
56-
require.Equal(b, gsm, gsm2)
59+
60+
// Note that require.Equal doesn't seem to handle maps well.
61+
// It says they are non-equal simply because their order isn't deterministic.
62+
if diff := cmp.Diff(gsm, gsm2, cmp.Exporter(func(reflect.Type) bool { return true })); diff != "" {
63+
b.Fatal(diff)
64+
}
5765
}
5866
})
5967
})
@@ -65,16 +73,24 @@ func BenchmarkMessageEncodingRoundtrip(b *testing.B) {
6573
for pb.Next() {
6674
buf.Reset()
6775

68-
node := bindnode.Wrap(&gsm, message.Prototype.Message.Type())
69-
err := dagcbor.Encode(node.Representation(), buf)
76+
ipldGSM, err := gsm.ToIPLD()
77+
require.NoError(b, err)
78+
node := bindnode.Wrap(ipldGSM, ipldbind.Prototype.Message.Type())
79+
err = dagcbor.Encode(node.Representation(), buf)
7080
require.NoError(b, err)
7181

72-
builder := message.Prototype.Message.Representation().NewBuilder()
82+
builder := ipldbind.Prototype.Message.Representation().NewBuilder()
7383
err = dagcbor.Decode(builder, buf)
7484
require.NoError(b, err)
7585
node2 := builder.Build()
76-
gsm2 := *bindnode.Unwrap(node2).(*message.GraphSyncMessage)
77-
require.Equal(b, gsm, gsm2)
86+
ipldGSM2 := bindnode.Unwrap(node2).(*ipldbind.GraphSyncMessage)
87+
gsm2, err := messageFromIPLD(ipldGSM2)
88+
require.NoError(b, err)
89+
90+
// same as above.
91+
if diff := cmp.Diff(gsm, gsm2, cmp.Exporter(func(reflect.Type) bool { return true })); diff != "" {
92+
b.Fatal(diff)
93+
}
7894
}
7995
})
8096
})

message/builder.go

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@ package message
22

33
import (
44
blocks "github.com/ipfs/go-block-format"
5-
cid "github.com/ipfs/go-cid"
5+
"github.com/ipfs/go-cid"
66
"github.com/ipld/go-ipld-prime"
77
cidlink "github.com/ipld/go-ipld-prime/linking/cid"
8-
"github.com/ipld/go-ipld-prime/node/basicnode"
98

109
"github.com/ipfs/go-graphsync"
1110
"github.com/ipfs/go-graphsync/metadata"
@@ -19,7 +18,7 @@ type Builder struct {
1918
blkSize uint64
2019
completedResponses map[graphsync.RequestID]graphsync.ResponseStatusCode
2120
outgoingResponses map[graphsync.RequestID]metadata.Metadata
22-
extensions map[graphsync.RequestID][]NamedExtension
21+
extensions map[graphsync.RequestID][]graphsync.ExtensionData
2322
requests map[graphsync.RequestID]GraphSyncRequest
2423
}
2524

@@ -30,13 +29,13 @@ func NewBuilder() *Builder {
3029
outgoingBlocks: make(map[cid.Cid]blocks.Block),
3130
completedResponses: make(map[graphsync.RequestID]graphsync.ResponseStatusCode),
3231
outgoingResponses: make(map[graphsync.RequestID]metadata.Metadata),
33-
extensions: make(map[graphsync.RequestID][]NamedExtension),
32+
extensions: make(map[graphsync.RequestID][]graphsync.ExtensionData),
3433
}
3534
}
3635

3736
// AddRequest registers a new request to be added to the message.
3837
func (b *Builder) AddRequest(request GraphSyncRequest) {
39-
b.requests[request.ID] = request
38+
b.requests[request.ID()] = request
4039
}
4140

4241
// AddBlock adds the given block to the message.
@@ -46,7 +45,7 @@ func (b *Builder) AddBlock(block blocks.Block) {
4645
}
4746

4847
// AddExtensionData adds the given extension data to to the message
49-
func (b *Builder) AddExtensionData(requestID graphsync.RequestID, extension NamedExtension) {
48+
func (b *Builder) AddExtensionData(requestID graphsync.RequestID, extension graphsync.ExtensionData) {
5049
b.extensions[requestID] = append(b.extensions[requestID], extension)
5150
// make sure this extension goes out in next response even if no links are sent
5251
_, ok := b.outgoingResponses[requestID]
@@ -110,30 +109,21 @@ func (b *Builder) ScrubResponses(requestIDs []graphsync.RequestID) uint64 {
110109

111110
// Build assembles and encodes message data from the added requests, links, and blocks.
112111
func (b *Builder) Build() (GraphSyncMessage, error) {
113-
requests := make([]GraphSyncRequest, 0, len(b.requests))
114-
for _, request := range b.requests {
115-
requests = append(requests, request)
116-
}
117-
responses := make([]GraphSyncResponse, 0, len(b.outgoingResponses))
112+
responses := make(map[graphsync.RequestID]GraphSyncResponse, len(b.outgoingResponses))
118113
for requestID, linkMap := range b.outgoingResponses {
119114
mdRaw, err := metadata.EncodeMetadata(linkMap)
120115
if err != nil {
121116
return GraphSyncMessage{}, err
122117
}
123-
b.extensions[requestID] = append(b.extensions[requestID], NamedExtension{
118+
b.extensions[requestID] = append(b.extensions[requestID], graphsync.ExtensionData{
124119
Name: graphsync.ExtensionMetadata,
125-
Data: basicnode.NewBytes(mdRaw), // TODO: likely wrong
120+
Data: mdRaw,
126121
})
127122
status, isComplete := b.completedResponses[requestID]
128-
responses = append(responses, NewResponse(requestID, responseCode(status, isComplete), b.extensions[requestID]...))
129-
}
130-
blocks := make([]GraphSyncBlock, 0, len(b.outgoingBlocks))
131-
for _, block := range b.outgoingBlocks {
132-
blocks = append(blocks, FromBlockFormat(block))
123+
responses[requestID] = NewResponse(requestID, responseCode(status, isComplete), b.extensions[requestID]...)
133124
}
134-
// TODO: sort requests, responses, and blocks? map order is randomized
135125
return GraphSyncMessage{
136-
requests, responses, blocks,
126+
b.requests, responses, b.outgoingBlocks,
137127
}, nil
138128
}
139129

message/builder_test.go

Lines changed: 24 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,33 @@
11
package message
22

33
import (
4-
"bytes"
54
"io"
65
"testing"
76

87
"github.com/ipld/go-ipld-prime"
98
cidlink "github.com/ipld/go-ipld-prime/linking/cid"
10-
"github.com/ipld/go-ipld-prime/node/basicnode"
119
"github.com/stretchr/testify/require"
1210

1311
"github.com/ipfs/go-graphsync"
1412
"github.com/ipfs/go-graphsync/metadata"
1513
"github.com/ipfs/go-graphsync/testutil"
1614
)
1715

18-
// Like the funcs in testutil above, but using blocks at the protocol level.
19-
// We can't put them there right away, due to import cycles.
20-
// We need to refactor these tests to be external, i.e. "package message_test".
21-
22-
func ContainsGraphSyncBlock(blks []GraphSyncBlock, block GraphSyncBlock) bool {
23-
for _, blk := range blks {
24-
if bytes.Equal(blk.Prefix, block.Prefix) && bytes.Equal(blk.Data, block.Data) {
25-
return true
26-
}
27-
}
28-
return false
29-
}
30-
func AssertContainsGraphSyncBlock(t testing.TB, blks []GraphSyncBlock, block GraphSyncBlock) {
31-
t.Helper()
32-
require.True(t, ContainsGraphSyncBlock(blks, block), "given block should be in list")
33-
}
34-
func RefuteContainsGraphSyncBlock(t testing.TB, blks []GraphSyncBlock, block GraphSyncBlock) {
35-
t.Helper()
36-
require.False(t, ContainsGraphSyncBlock(blks, block), "given block should not be in list")
37-
}
38-
3916
func TestMessageBuilding(t *testing.T) {
4017
blocks := testutil.GenerateBlocksOfSize(3, 100)
4118
links := make([]ipld.Link, 0, len(blocks))
4219
for _, block := range blocks {
4320
links = append(links, cidlink.Link{Cid: block.Cid()})
4421
}
45-
extensionData1 := basicnode.NewBytes(testutil.RandomBytes(100))
22+
extensionData1 := testutil.RandomBytes(100)
4623
extensionName1 := graphsync.ExtensionName("AppleSauce/McGee")
47-
extension1 := NamedExtension{
24+
extension1 := graphsync.ExtensionData{
4825
Name: extensionName1,
4926
Data: extensionData1,
5027
}
51-
extensionData2 := basicnode.NewBytes(testutil.RandomBytes(100))
28+
extensionData2 := testutil.RandomBytes(100)
5229
extensionName2 := graphsync.ExtensionName("HappyLand/Happenstance")
53-
extension2 := NamedExtension{
30+
extension2 := graphsync.ExtensionData{
5431
Name: extensionName2,
5532
Data: extensionData2,
5633
}
@@ -97,12 +74,12 @@ func TestMessageBuilding(t *testing.T) {
9774
},
9875
checkMsg: func(t *testing.T, message GraphSyncMessage) {
9976

100-
responses := message.Responses
101-
sentBlocks := BlockFormatSlice(message.Blocks)
77+
responses := message.Responses()
78+
sentBlocks := message.Blocks()
10279
require.Len(t, responses, 4, "did not assemble correct number of responses")
10380

10481
response1 := findResponseForRequestID(t, responses, requestID1)
105-
require.Equal(t, graphsync.RequestCompletedPartial, response1.Status, "did not generate completed partial response")
82+
require.Equal(t, graphsync.RequestCompletedPartial, response1.Status(), "did not generate completed partial response")
10683
assertMetadata(t, response1, metadata.Metadata{
10784
metadata.Item{Link: links[0].(cidlink.Link).Cid, BlockPresent: true},
10885
metadata.Item{Link: links[1].(cidlink.Link).Cid, BlockPresent: false},
@@ -111,23 +88,23 @@ func TestMessageBuilding(t *testing.T) {
11188
assertExtension(t, response1, extension1)
11289

11390
response2 := findResponseForRequestID(t, responses, requestID2)
114-
require.Equal(t, graphsync.RequestCompletedFull, response2.Status, "did not generate completed full response")
91+
require.Equal(t, graphsync.RequestCompletedFull, response2.Status(), "did not generate completed full response")
11592
assertMetadata(t, response2, metadata.Metadata{
11693
metadata.Item{Link: links[1].(cidlink.Link).Cid, BlockPresent: true},
11794
metadata.Item{Link: links[2].(cidlink.Link).Cid, BlockPresent: true},
11895
metadata.Item{Link: links[1].(cidlink.Link).Cid, BlockPresent: true},
11996
})
12097

12198
response3 := findResponseForRequestID(t, responses, requestID3)
122-
require.Equal(t, graphsync.PartialResponse, response3.Status, "did not generate partial response")
99+
require.Equal(t, graphsync.PartialResponse, response3.Status(), "did not generate partial response")
123100
assertMetadata(t, response3, metadata.Metadata{
124101
metadata.Item{Link: links[0].(cidlink.Link).Cid, BlockPresent: true},
125102
metadata.Item{Link: links[1].(cidlink.Link).Cid, BlockPresent: true},
126103
})
127104
assertExtension(t, response3, extension2)
128105

129106
response4 := findResponseForRequestID(t, responses, requestID4)
130-
require.Equal(t, graphsync.RequestCompletedFull, response4.Status, "did not generate completed full response")
107+
require.Equal(t, graphsync.RequestCompletedFull, response4.Status(), "did not generate completed full response")
131108

132109
require.Equal(t, len(blocks), len(sentBlocks), "did not send all blocks")
133110

@@ -143,15 +120,15 @@ func TestMessageBuilding(t *testing.T) {
143120
},
144121
expectedSize: 0,
145122
checkMsg: func(t *testing.T, message GraphSyncMessage) {
146-
responses := message.Responses
123+
responses := message.Responses()
147124

148125
response1 := findResponseForRequestID(t, responses, requestID1)
149-
require.Equal(t, graphsync.PartialResponse, response1.Status, "did not generate partial response")
126+
require.Equal(t, graphsync.PartialResponse, response1.Status(), "did not generate partial response")
150127
assertMetadata(t, response1, nil)
151128
assertExtension(t, response1, extension1)
152129

153130
response2 := findResponseForRequestID(t, responses, requestID2)
154-
require.Equal(t, graphsync.PartialResponse, response2.Status, "did not generate partial response")
131+
require.Equal(t, graphsync.PartialResponse, response2.Status(), "did not generate partial response")
155132
assertMetadata(t, response2, nil)
156133
assertExtension(t, response2, extension2)
157134
},
@@ -184,27 +161,27 @@ func TestMessageBuilding(t *testing.T) {
184161
expectedSize: 200,
185162
checkMsg: func(t *testing.T, message GraphSyncMessage) {
186163

187-
responses := message.Responses
188-
sentBlocks := BlockFormatSlice(message.Blocks)
164+
responses := message.Responses()
165+
sentBlocks := message.Blocks()
189166
require.Len(t, responses, 3, "did not assemble correct number of responses")
190167

191168
response2 := findResponseForRequestID(t, responses, requestID2)
192-
require.Equal(t, graphsync.RequestCompletedFull, response2.Status, "did not generate completed full response")
169+
require.Equal(t, graphsync.RequestCompletedFull, response2.Status(), "did not generate completed full response")
193170
assertMetadata(t, response2, metadata.Metadata{
194171
metadata.Item{Link: links[1].(cidlink.Link).Cid, BlockPresent: true},
195172
metadata.Item{Link: links[2].(cidlink.Link).Cid, BlockPresent: true},
196173
metadata.Item{Link: links[1].(cidlink.Link).Cid, BlockPresent: true},
197174
})
198175

199176
response3 := findResponseForRequestID(t, responses, requestID3)
200-
require.Equal(t, graphsync.PartialResponse, response3.Status, "did not generate partial response")
177+
require.Equal(t, graphsync.PartialResponse, response3.Status(), "did not generate partial response")
201178
assertMetadata(t, response3, metadata.Metadata{
202179
metadata.Item{Link: links[1].(cidlink.Link).Cid, BlockPresent: true},
203180
})
204181
assertExtension(t, response3, extension2)
205182

206183
response4 := findResponseForRequestID(t, responses, requestID4)
207-
require.Equal(t, graphsync.RequestCompletedFull, response4.Status, "did not generate completed full response")
184+
require.Equal(t, graphsync.RequestCompletedFull, response4.Status(), "did not generate completed full response")
208185

209186
require.Equal(t, len(blocks)-1, len(sentBlocks), "did not send all blocks")
210187

@@ -242,12 +219,12 @@ func TestMessageBuilding(t *testing.T) {
242219
expectedSize: 100,
243220
checkMsg: func(t *testing.T, message GraphSyncMessage) {
244221

245-
responses := message.Responses
246-
sentBlocks := BlockFormatSlice(message.Blocks)
222+
responses := message.Responses()
223+
sentBlocks := message.Blocks()
247224
require.Len(t, responses, 1, "did not assemble correct number of responses")
248225

249226
response3 := findResponseForRequestID(t, responses, requestID3)
250-
require.Equal(t, graphsync.PartialResponse, response3.Status, "did not generate partial response")
227+
require.Equal(t, graphsync.PartialResponse, response3.Status(), "did not generate partial response")
251228
assertMetadata(t, response3, metadata.Metadata{
252229
metadata.Item{Link: links[1].(cidlink.Link).Cid, BlockPresent: true},
253230
})
@@ -273,25 +250,23 @@ func TestMessageBuilding(t *testing.T) {
273250

274251
func findResponseForRequestID(t *testing.T, responses []GraphSyncResponse, requestID graphsync.RequestID) GraphSyncResponse {
275252
for _, response := range responses {
276-
if response.ID == requestID {
253+
if response.RequestID() == requestID {
277254
return response
278255
}
279256
}
280257
require.FailNow(t, "Could not find request")
281258
return GraphSyncResponse{}
282259
}
283260

284-
func assertExtension(t *testing.T, response GraphSyncResponse, extension NamedExtension) {
261+
func assertExtension(t *testing.T, response GraphSyncResponse, extension graphsync.ExtensionData) {
285262
returnedExtensionData, found := response.Extension(extension.Name)
286263
require.True(t, found)
287264
require.Equal(t, extension.Data, returnedExtensionData, "did not encode extension")
288265
}
289266

290267
func assertMetadata(t *testing.T, response GraphSyncResponse, expectedMetadata metadata.Metadata) {
291-
responseMetadataNode, found := response.Extension(graphsync.ExtensionMetadata)
268+
responseMetadataRaw, found := response.Extension(graphsync.ExtensionMetadata)
292269
require.True(t, found, "Metadata should be included in response")
293-
responseMetadataRaw, err := responseMetadataNode.AsBytes()
294-
require.NoError(t, err)
295270
responseMetadata, err := metadata.DecodeMetadata(responseMetadataRaw)
296271
require.NoError(t, err)
297272
require.Equal(t, expectedMetadata, responseMetadata, "incorrect metadata included in response")

0 commit comments

Comments
 (0)