Skip to content

Commit

Permalink
id registry
Browse files Browse the repository at this point in the history
  • Loading branch information
Wondertan committed May 26, 2024
1 parent 0b9ce88 commit 7f218e2
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 103 deletions.
20 changes: 14 additions & 6 deletions share/shwap/p2p/bitswap/bitswap.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,45 @@ package bitswap
import (
"context"
"fmt"
"hash"
"sync"

"github.com/ipfs/boxo/exchange"
blocks "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid"
logger "github.com/ipfs/go-log/v2"

"github.com/celestiaorg/rsmt2d"
mh "github.com/multiformats/go-multihash"

"github.com/celestiaorg/celestia-node/share"
)

var log = logger.Logger("shwap/bitswap")

// TODO:
// * Generalize CIDs handling
// * Synchronization for GetContainers
// * Test with race and count 100
// * Hasher test
// * Coverage
// * godoc
// * document steps required to add new id/container type

// ID
// Must avoid duplication of computation and allocation
type ID[C any] interface {
String() string
CID() cid.Cid
BlockFromEDS(*rsmt2d.ExtendedDataSquare) (blocks.Block, error)
UnmarshalContainer(*share.Root, []byte) (C, error)
}

func RegisterID(mhcode, codec uint64, size int, bldrFn func(cid2 cid.Cid) (blockBuilder, error)) {
mh.Register(mhcode, func() hash.Hash {
return &hasher{IDSize: size}
})
specRegistry[mhcode] = idSpec{
size: size,
codec: codec,
builder: bldrFn,
}
}

// GetContainers
// Does not guarantee synchronization. Calling this func simultaneously with the same ID may cause
// issues. TODO: Describe motivation
Expand Down
32 changes: 9 additions & 23 deletions share/shwap/p2p/bitswap/bitswap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,31 +58,17 @@ func newTestBlockstore(eds *rsmt2d.ExtendedDataSquare) *testBlockstore {
}

func (b *testBlockstore) Get(_ context.Context, cid cid.Cid) (blocks.Block, error) {
switch cid.Type() {
case sampleCodec:
sid, err := SampleIDFromCID(cid)
if err != nil {
return nil, fmt.Errorf("while converting CID to SampleID: %w", err)
}

return sid.BlockFromEDS(b.eds)
case rowCodec:
rid, err := RowIDFromCID(cid)
if err != nil {
return nil, fmt.Errorf("while converting CID to RowID: %w", err)
}

return rid.BlockFromEDS(b.eds)
case rowNamespaceDataCodec:
did, err := RowNamespaceDataIDFromCID(cid)
if err != nil {
return nil, fmt.Errorf("while converting CID to DataID: %w", err)
}

return did.BlockFromEDS(b.eds)
default:
spec, ok := specRegistry[cid.Prefix().MhType]
if !ok {
return nil, fmt.Errorf("unsupported codec")
}

bldr, err := spec.builder(cid)
if err != nil {
return nil, err
}

return bldr.BlockFromEDS(b.eds)
}

func (b *testBlockstore) GetSize(ctx context.Context, cid cid.Cid) (int, error) {
Expand Down
43 changes: 0 additions & 43 deletions share/shwap/p2p/bitswap/hasher_test.go
Original file line number Diff line number Diff line change
@@ -1,44 +1 @@
package bitswap

// func TestHasher(t *testing.T) {
// const size = 8
// namespace := sharetest.RandV0Namespace()
// square, root := edstest.RandEDSWithNamespace(t, namespace, size*size, size)
//
// data, err := shwap.NamespacedDataFromEDS(square, namespace)
// require.NoError(t, err)
// // TODO(@Wondertan): Reconsider adding RowIdx to RowNamespaceData so that we don't guess it here
// did, err := shwap.NewRowNamespaceDataID(1, 0, namespace, root)
// require.NoError(t, err)
//
// rowData := data[0]
// err = rowData.Validate(root, namespace, int(did.RowIndex))
// require.NoError(t, err)
//
// blk := RowNamespaceDataBlock{RowNamespaceDataID: did, RowNamespaceData: rowData}
// proto := blk.Proto()
// bin, err := proto.Marshal()
// require.NoError(t, err)
//
// hasher, err := mh.GetHasher(rowNamespaceDataMultihashCode)
// require.NoError(t, err)
//
// _, err = hasher.Write([]byte("hello"))
// assert.Error(t, err)
//
// addRoot(did.Height, root)
// defer deleteRoot(did.Height)
//
// n, err := hasher.Write(bin)
// require.NoError(t, err)
// assert.EqualValues(t, len(bin), n)
//
// digest := hasher.Sum(nil)
// idBin, err := did.MarshalBinary()
// require.NoError(t, err)
// assert.EqualValues(t, idBin, digest)
//
// hasher.Reset()
// digest = hasher.Sum(nil)
// assert.NotEqualValues(t, digest, idBin)
// }
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,25 @@ import (
"encoding"
"fmt"

blocks "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid"
mh "github.com/multiformats/go-multihash"

"github.com/celestiaorg/celestia-node/share/shwap"
"github.com/celestiaorg/rsmt2d"
)

var specRegistry = make(map[uint64]idSpec)

type idSpec struct {
size int
codec uint64
builder func(cid.Cid) (blockBuilder, error)
}

type blockBuilder interface {
BlockFromEDS(*rsmt2d.ExtendedDataSquare) (blocks.Block, error)
}

// DefaultAllowlist keeps default list of multihashes allowed in the network.
// TODO(@Wondertan): Make it private and instead provide Blockservice constructor with injected
// allowlist
Expand All @@ -18,12 +31,9 @@ var DefaultAllowlist allowlist
type allowlist struct{}

func (a allowlist) IsAllowed(code uint64) bool {
// we disable all codes except home-baked
switch code {
case rowMultihashCode, sampleMultihashCode, rowNamespaceDataMultihashCode:
return true
}
return false
// we disable all codes except registered
_, ok := specRegistry[code]
return ok
}

func extractCID(cid cid.Cid) ([]byte, error) {
Expand Down Expand Up @@ -51,20 +61,17 @@ func encodeCID(bm encoding.BinaryMarshaler, mhcode, codec uint64) cid.Cid {

func validateCID(cid cid.Cid) error {
prefix := cid.Prefix()
if !DefaultAllowlist.IsAllowed(prefix.MhType) {
spec, ok := specRegistry[prefix.MhType]
if !ok {
return fmt.Errorf("unsupported multihash type %d", prefix.MhType)
}

switch prefix.Codec {
default:
return fmt.Errorf("unsupported codec %d", prefix.Codec)
case rowCodec, sampleCodec, rowNamespaceDataCodec:
if prefix.Codec != spec.codec {
return fmt.Errorf("invalid CID codec %d", prefix.Codec)
}

switch prefix.MhLength {
default:
return fmt.Errorf("unsupported multihash length %d", prefix.MhLength)
case shwap.RowIDSize, shwap.SampleIDSize, shwap.RowNamespaceDataIDSize:
if prefix.MhLength != spec.size {
return fmt.Errorf("invalid multihash length %d", prefix.MhLength)
}

return nil
Expand Down
13 changes: 8 additions & 5 deletions share/shwap/p2p/bitswap/row.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ package bitswap

import (
"fmt"
"hash"

blocks "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid"
mh "github.com/multiformats/go-multihash"

"github.com/celestiaorg/rsmt2d"

Expand All @@ -24,9 +22,14 @@ const (
)

func init() {
mh.Register(rowMultihashCode, func() hash.Hash {
return &hasher{IDSize: shwap.RowIDSize}
})
RegisterID(
rowMultihashCode,
rowCodec,
shwap.RowIDSize,
func(cid cid.Cid) (blockBuilder, error) {
return RowIDFromCID(cid)
},
)
}

type RowID shwap.RowID
Expand Down
13 changes: 8 additions & 5 deletions share/shwap/p2p/bitswap/row_namespace_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ package bitswap

import (
"fmt"
"hash"

blocks "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid"
mh "github.com/multiformats/go-multihash"

"github.com/celestiaorg/rsmt2d"

Expand All @@ -24,9 +22,14 @@ const (
)

func init() {
mh.Register(rowNamespaceDataMultihashCode, func() hash.Hash {
return &hasher{IDSize: shwap.RowNamespaceDataIDSize}
})
RegisterID(
rowNamespaceDataMultihashCode,
rowNamespaceDataCodec,
shwap.RowNamespaceDataIDSize,
func(cid cid.Cid) (blockBuilder, error) {
return RowNamespaceDataIDFromCID(cid)
},
)
}

type RowNamespaceDataID shwap.RowNamespaceDataID
Expand Down
13 changes: 8 additions & 5 deletions share/shwap/p2p/bitswap/sample.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ package bitswap

import (
"fmt"
"hash"

blocks "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid"
mh "github.com/multiformats/go-multihash"

"github.com/celestiaorg/rsmt2d"

Expand All @@ -25,9 +23,14 @@ const (
)

func init() {
mh.Register(sampleMultihashCode, func() hash.Hash {
return &hasher{IDSize: shwap.SampleIDSize}
})
RegisterID(
sampleMultihashCode,
sampleCodec,
shwap.SampleIDSize,
func(cid cid.Cid) (blockBuilder, error) {
return SampleIDFromCID(cid)
},
)
}

type SampleID shwap.SampleID
Expand Down

0 comments on commit 7f218e2

Please sign in to comment.