Skip to content

Commit

Permalink
Use concrete multicodec codes as indexing metadata protocol ID
Browse files Browse the repository at this point in the history
Refactor metadata package to: 1) use concrete multicodec codes defined
in the lookup table, and 2) simplify the datatransfer metadata
implementation since dynamic protocol ID range no longer makes sense
when using concrete multicodec codes.

Relates to:
 - multiformats/multicodec#260
  • Loading branch information
masih committed Mar 3, 2022
1 parent 904fe05 commit fa696c2
Show file tree
Hide file tree
Showing 14 changed files with 168 additions and 291 deletions.
8 changes: 2 additions & 6 deletions cardatatransfer/cardatatransfer.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,12 @@ func MetadataFromContextID(contextID []byte) (stiapi.Metadata, error) {
if err != nil {
return stiapi.Metadata{}, err
}
filecoinV1Metadata := &metadata.FilecoinV1Data{
filecoinV1Metadata := &metadata.GraphsyncFilecoinV1Metadata{
PieceCID: pieceCid,
VerifiedDeal: true,
FastRetrieval: true,
}
dataTransferMetadata, err := filecoinV1Metadata.Encode(metadata.GraphSyncV1)
if err != nil {
return stiapi.Metadata{}, err
}
return dataTransferMetadata.ToIndexerMetadata(), nil
return filecoinV1Metadata.ToIndexerMetadata()
}

// ValidatePush validates a push request received from the peer that will send data
Expand Down
7 changes: 3 additions & 4 deletions cardatatransfer/cardatatransfer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,11 +233,10 @@ func (fs *fakeSupplier) ReadOnlyBlockstore(contextID []byte) (supplier.ClosableB
func pieceCIDFromContextID(t *testing.T, contextID []byte) cid.Cid {
md, err := cardatatransfer.MetadataFromContextID(contextID)
require.NoError(t, err)
dtm, err := metadata.FromIndexerMetadata(md)
dtm := &metadata.GraphsyncFilecoinV1Metadata{}
err = dtm.FromIndexerMetadata(md)
require.NoError(t, err)
fv1, err := metadata.DecodeFilecoinV1Data(dtm)
require.NoError(t, err)
return fv1.PieceCID
return dtm.PieceCID
}

func copySelectorOutputToBlockstore(t *testing.T, sourceBs bstore.Blockstore, root cid.Cid, selectorNode datamodel.Node, np datamodel.NodePrototype) (bstore.Blockstore, int) {
Expand Down
2 changes: 1 addition & 1 deletion cmd/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ require (
github.com/libp2p/go-libp2p-core v0.14.0
github.com/mitchellh/go-homedir v1.1.0
github.com/multiformats/go-multiaddr v0.5.0
github.com/multiformats/go-multicodec v0.4.0
github.com/multiformats/go-multicodec v0.4.1
github.com/multiformats/go-multihash v0.1.0
github.com/rogpeppe/go-internal v1.8.0
github.com/stretchr/testify v1.7.0
Expand Down
3 changes: 2 additions & 1 deletion cmd/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1188,8 +1188,9 @@ github.com/multiformats/go-multicodec v0.2.0/go.mod h1:/y4YVwkfMyry5kFbMTbLJKErh
github.com/multiformats/go-multicodec v0.3.0/go.mod h1:qGGaQmioCDh+TeFOnxrbU0DaIPw8yFgAZgFG0V7p1qQ=
github.com/multiformats/go-multicodec v0.3.1-0.20210902112759-1539a079fd61/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ=
github.com/multiformats/go-multicodec v0.3.1-0.20211210143421-a526f306ed2c/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ=
github.com/multiformats/go-multicodec v0.4.0 h1:fbqb6ky7erjdD+/zaEBJgZWu1i8D6i/wmPywGK7sdow=
github.com/multiformats/go-multicodec v0.4.0/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ=
github.com/multiformats/go-multicodec v0.4.1 h1:BSJbf+zpghcZMZrwTYBGwy0CPcVZGWiC72Cp8bBd4R4=
github.com/multiformats/go-multicodec v0.4.1/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ=
github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U=
github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po=
github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
Expand Down
7 changes: 3 additions & 4 deletions e2e_retrieve_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,16 +133,15 @@ func testRetrievalRoundTripWithTestCase(t *testing.T, tc testCase) {
var receivedMd stiapi.Metadata
err = receivedMd.UnmarshalBinary(mdb)
require.NoError(t, err)
dtm, err := metadata.FromIndexerMetadata(receivedMd)
require.NoError(t, err)
fv1, err := metadata.DecodeFilecoinV1Data(dtm)
dtm := &metadata.GraphsyncFilecoinV1Metadata{}
err = dtm.FromIndexerMetadata(receivedMd)
require.NoError(t, err)

proposal := &cardatatransfer.DealProposal{
PayloadCID: roots[0],
ID: 1,
Params: cardatatransfer.Params{
PieceCID: &fv1.PieceCID,
PieceCID: &dtm.PieceCID,
},
}
done := make(chan bool, 1)
Expand Down
3 changes: 2 additions & 1 deletion engine/engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,14 @@ import (
"github.com/libp2p/go-libp2p-core/host"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/libp2p/go-libp2p-core/test"
"github.com/multiformats/go-multicodec"
mh "github.com/multiformats/go-multihash"
"github.com/stretchr/testify/require"
)

const (
testTopic = "indexer/test"
protocolID = 0x300000
protocolID = multicodec.TransportGraphsyncFilecoinv1
)

var _ provider.MultihashIterator = (*sliceMhIterator)(nil)
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ require (
github.com/libp2p/go-libp2p-pubsub v0.6.1
github.com/mitchellh/go-homedir v1.1.0
github.com/multiformats/go-multiaddr v0.5.0
github.com/multiformats/go-multicodec v0.4.0
github.com/multiformats/go-multicodec v0.4.1
github.com/multiformats/go-multihash v0.1.0
github.com/stretchr/testify v1.7.0
github.com/whyrusleeping/cbor-gen v0.0.0-20220224212727-7a699437a831
Expand Down
3 changes: 2 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1180,8 +1180,9 @@ github.com/multiformats/go-multicodec v0.2.0/go.mod h1:/y4YVwkfMyry5kFbMTbLJKErh
github.com/multiformats/go-multicodec v0.3.0/go.mod h1:qGGaQmioCDh+TeFOnxrbU0DaIPw8yFgAZgFG0V7p1qQ=
github.com/multiformats/go-multicodec v0.3.1-0.20210902112759-1539a079fd61/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ=
github.com/multiformats/go-multicodec v0.3.1-0.20211210143421-a526f306ed2c/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ=
github.com/multiformats/go-multicodec v0.4.0 h1:fbqb6ky7erjdD+/zaEBJgZWu1i8D6i/wmPywGK7sdow=
github.com/multiformats/go-multicodec v0.4.0/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ=
github.com/multiformats/go-multicodec v0.4.1 h1:BSJbf+zpghcZMZrwTYBGwy0CPcVZGWiC72Cp8bBd4R4=
github.com/multiformats/go-multicodec v0.4.1/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ=
github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U=
github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po=
github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
Expand Down
11 changes: 3 additions & 8 deletions metadata/bitswap.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,10 @@ package metadata

import (
stiapi "github.com/filecoin-project/storetheindex/api/v0"
"github.com/multiformats/go-multicodec"
)

const (
// BitswapMetadataV1 is the 2021-era ipfs-bitswap transport protocol
BitswapMetadataV1 = 0x3E0000
)

// BitswapMetadata is a signalling indicator for the bitswap transport
// BitswapMetadata represents the indexing metadata that uses multicodec.TransportBitswap.
var BitswapMetadata = stiapi.Metadata{
ProtocolID: BitswapMetadataV1,
Data: []byte{},
ProtocolID: multicodec.TransportBitswap,
}
9 changes: 5 additions & 4 deletions metadata/doc.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
// Package metadata captures the metadata types known by the index-provider.
//
// The metadata is used to provide information about how to retrieve data blocks associated to
// multihashes from a provider.
// It is represented as an array of bytes in the indexer protocol, starting with a varint ProtocolID
// that defines how to decode the remaining bytes.
// multihashes advertised by a provider. It is represented as an array of bytes in the indexer
// protocol, starting with a varint ProtocolID that defines how to decode the remaining bytes.
//
// Two metadata types are currently represented here: BitswapMetadata and DataTransferMetadata.
// Two metadata types are currently represented here: BitswapMetadata and
// GraphsyncFilecoinV1Metadata.
package metadata
87 changes: 87 additions & 0 deletions metadata/graphsync_filecoinv1.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package metadata

import (
"bytes"
"fmt"

stiapi "github.com/filecoin-project/storetheindex/api/v0"
"github.com/ipfs/go-cid"
"github.com/ipld/go-ipld-prime/codec/dagcbor"
"github.com/ipld/go-ipld-prime/node/bindnode"
"github.com/ipld/go-ipld-prime/schema"
"github.com/multiformats/go-multicodec"
)

// GraphsyncFilecoinV1Metadata represents the indexing metadata for multicodec.TransportGraphsyncFilecoinv1.
type GraphsyncFilecoinV1Metadata struct {
// PieceCID identifies the piece this data can be found in
PieceCID cid.Cid
// VerifiedDeal indicates if the deal is verified
VerifiedDeal bool
// FastRetrieval indicates whether the provider claims there is an unsealed copy
FastRetrieval bool
}

var graphSyncfilecoinV1SchemaType schema.Type

func init() {
ts := schema.TypeSystem{}
ts.Init()
ts.Accumulate(schema.SpawnLink("Link"))
ts.Accumulate(schema.SpawnBool("Bool"))
ts.Accumulate(schema.SpawnStruct("GraphsyncFilecoinV1Metadata",
[]schema.StructField{
schema.SpawnStructField("PieceCID", "Link", false, false),
schema.SpawnStructField("VerifiedDeal", "Bool", false, false),
schema.SpawnStructField("FastRetrieval", "Bool", false, false),
},
schema.SpawnStructRepresentationMap(nil),
))
graphSyncfilecoinV1SchemaType = ts.TypeByName("GraphsyncFilecoinV1Metadata")
}

// ToIndexerMetadata converts GraphsyncFilecoinV1Metadata into indexer Metadata format.
func (dtm *GraphsyncFilecoinV1Metadata) ToIndexerMetadata() (stiapi.Metadata, error) {
nd := bindnode.Wrap(dtm, graphSyncfilecoinV1SchemaType)
buf := new(bytes.Buffer)
err := dagcbor.Encode(nd, buf)
if err != nil {
return stiapi.Metadata{}, err
}
return stiapi.Metadata{
ProtocolID: multicodec.TransportGraphsyncFilecoinv1,
Data: buf.Bytes(),
}, nil
}

// FromIndexerMetadata decodes the indexer metadata format into GraphsyncFilecoinV1Metadata
// if the protocol ID of the given metadata matches multicodec.TransportGraphsyncFilecoinv1.
// Otherwise, ErrNotGraphsyncFilecoinV1 error is returned.
func (dtm *GraphsyncFilecoinV1Metadata) FromIndexerMetadata(m stiapi.Metadata) error {
if m.ProtocolID != multicodec.TransportGraphsyncFilecoinv1 {
return ErrNotGraphsyncFilecoinV1{m.ProtocolID}
}
r := bytes.NewBuffer(m.Data)
proto := bindnode.Prototype((*GraphsyncFilecoinV1Metadata)(nil), graphSyncfilecoinV1SchemaType)
nb := proto.NewBuilder()
err := dagcbor.Decode(nb, r)
if err != nil {
return err
}
nd := nb.Build()
gm := bindnode.Unwrap(nd).(*GraphsyncFilecoinV1Metadata)
dtm.VerifiedDeal = gm.VerifiedDeal
dtm.FastRetrieval = gm.FastRetrieval
dtm.PieceCID = gm.PieceCID
return nil
}

// ErrNotGraphsyncFilecoinV1 indicates a protocol does not use graphsync filecoin v1 transport.
// See: multicodec.TransportGraphsyncFilecoinv1.
type ErrNotGraphsyncFilecoinV1 struct {
incorrectProtocol multicodec.Code
}

func (e ErrNotGraphsyncFilecoinV1) Error() string {
return fmt.Sprintf("protocol 0x%X does not use the FilecoinV1 exchange format", uint64(e.incorrectProtocol))
}
57 changes: 57 additions & 0 deletions metadata/graphsync_filecoinv1_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package metadata_test

import (
stiapi "github.com/filecoin-project/storetheindex/api/v0"
"testing"

"github.com/filecoin-project/index-provider/metadata"
"github.com/filecoin-project/index-provider/testutil"
"github.com/multiformats/go-multicodec"
"github.com/stretchr/testify/require"
)

func TestRoundTripDataTransferFilecoin(t *testing.T) {
cids := testutil.GenerateCids(4)
filecoinV1Datas := []*metadata.GraphsyncFilecoinV1Metadata{
{
PieceCID: cids[0],
VerifiedDeal: false,
FastRetrieval: false,
},
{
PieceCID: cids[1],
VerifiedDeal: false,
FastRetrieval: true,
},
{
PieceCID: cids[2],
VerifiedDeal: true,
FastRetrieval: true,
},
{
PieceCID: cids[3],
VerifiedDeal: true,
FastRetrieval: true,
},
}
for _, src := range filecoinV1Datas {
imd, err := src.ToIndexerMetadata()
require.NoError(t, err)
require.Equal(t, multicodec.TransportGraphsyncFilecoinv1, imd.ProtocolID)

dst := &metadata.GraphsyncFilecoinV1Metadata{}
err = dst.FromIndexerMetadata(imd)
require.NoError(t, err)
require.Equal(t, src, dst)
}
}

func TestGraphsyncFilecoinV1Metadata_FromIndexerMetadataErr(t *testing.T) {
imd := stiapi.Metadata{
ProtocolID: multicodec.TransportBitswap,
}
dst := &metadata.GraphsyncFilecoinV1Metadata{}
err := dst.FromIndexerMetadata(imd)
require.IsType(t, metadata.ErrNotGraphsyncFilecoinV1{}, err)
require.Equal(t, "protocol 0x900 does not use the FilecoinV1 exchange format", err.Error())
}
Loading

0 comments on commit fa696c2

Please sign in to comment.