From fb9ecde17e4e6b0009454d1e7d0c6ac4d783e6fc Mon Sep 17 00:00:00 2001 From: Will Scott Date: Mon, 5 Sep 2022 16:15:29 +0200 Subject: [PATCH 1/2] Update provide to take an array of keys, per spec --- client/contentrouting.go | 21 +++- client/contentrouting_test.go | 4 +- client/findproviders.go | 6 +- client/provide.go | 24 +++-- gen/proto/proto_edelweiss.go | 182 ++++++++++++++++++++++++++++------ gen/routing.go | 2 +- test/provide_test.go | 4 +- 7 files changed, 197 insertions(+), 46 deletions(-) diff --git a/client/contentrouting.go b/client/contentrouting.go index 92ba4bb..8822634 100644 --- a/client/contentrouting.go +++ b/client/contentrouting.go @@ -7,6 +7,7 @@ import ( "github.com/ipfs/go-cid" "github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/routing" + "github.com/multiformats/go-multihash" ) type ContentRoutingClient struct { @@ -27,10 +28,28 @@ func (c *ContentRoutingClient) Provide(ctx context.Context, key cid.Cid, announc return nil } - _, err := c.client.Provide(ctx, key, 24*time.Hour) + _, err := c.client.Provide(ctx, []cid.Cid{key}, 24*time.Hour) return err } +func (c *ContentRoutingClient) ProvideMany(ctx context.Context, keys []multihash.Multihash) error { + keysAsCids := make([]cid.Cid, 0, len(keys)) + for _, m := range keys { + keysAsCids = append(keysAsCids, cid.NewCidV0(m)) + } + _, err := c.client.Provide(ctx, keysAsCids, 24*time.Hour) + return err +} + +// Ready is part of the existing `ProvideMany` interface, but can be used more generally to determine if the routing client +// has a working connection. +func (c *ContentRoutingClient) Ready() bool { + // TODO: currently codegen does not expose a way to access the state of the connection + // Once either that is exposed, or the `Identify` portion of the reframe spec is implemented, + // a more nuanced response for this method will be possible. + return true +} + func (c *ContentRoutingClient) FindProvidersAsync(ctx context.Context, key cid.Cid, numResults int) <-chan peer.AddrInfo { addrInfoCh := make(chan peer.AddrInfo) resultCh, err := c.client.FindProvidersAsync(ctx, key) diff --git a/client/contentrouting_test.go b/client/contentrouting_test.go index 436c412..dbe1937 100644 --- a/client/contentrouting_test.go +++ b/client/contentrouting_test.go @@ -46,11 +46,11 @@ func (t TestDelegatedRoutingClient) PutIPNSAsync(ctx context.Context, id []byte, panic("not supported") } -func (t TestDelegatedRoutingClient) ProvideAsync(ctx context.Context, key cid.Cid, ttl time.Duration) (<-chan time.Duration, error) { +func (t TestDelegatedRoutingClient) ProvideAsync(ctx context.Context, key []cid.Cid, ttl time.Duration) (<-chan time.Duration, error) { panic("not supported") } -func (t TestDelegatedRoutingClient) Provide(ctx context.Context, key cid.Cid, tl time.Duration) (time.Duration, error) { +func (t TestDelegatedRoutingClient) Provide(ctx context.Context, key []cid.Cid, tl time.Duration) (time.Duration, error) { panic("not supported") } diff --git a/client/findproviders.go b/client/findproviders.go index b8e3418..e4b5f5b 100644 --- a/client/findproviders.go +++ b/client/findproviders.go @@ -25,8 +25,8 @@ type DelegatedRoutingClient interface { GetIPNSAsync(ctx context.Context, id []byte) (<-chan GetIPNSAsyncResult, error) PutIPNS(ctx context.Context, id []byte, record []byte) error PutIPNSAsync(ctx context.Context, id []byte, record []byte) (<-chan PutIPNSAsyncResult, error) - Provide(ctx context.Context, key cid.Cid, ttl time.Duration) (time.Duration, error) - ProvideAsync(ctx context.Context, key cid.Cid, ttl time.Duration) (<-chan time.Duration, error) + Provide(ctx context.Context, key []cid.Cid, ttl time.Duration) (time.Duration, error) + ProvideAsync(ctx context.Context, key []cid.Cid, ttl time.Duration) (<-chan time.Duration, error) } type Client struct { @@ -174,7 +174,7 @@ func ParseNodeAddresses(n *proto.Peer) []peer.AddrInfo { func ToProtoPeer(ai peer.AddrInfo) *proto.Peer { p := proto.Peer{ ID: values.Bytes(ai.ID), - Multiaddresses: make(proto.AnonList20, 0), + Multiaddresses: make(proto.AnonList21, 0), } for _, addr := range ai.Addrs { diff --git a/client/provide.go b/client/provide.go index 0f62100..3137d03 100644 --- a/client/provide.go +++ b/client/provide.go @@ -100,7 +100,7 @@ func parseProtocol(tp *proto.TransferProtocol) (TransferProtocol, error) { // ProvideRequest is a message indicating a provider can provide a Key for a given TTL type ProvideRequest struct { - Key cid.Cid + Key []cid.Cid *Provider Timestamp int64 AdvisoryTTL time.Duration @@ -109,7 +109,7 @@ type ProvideRequest struct { var provideSchema, provideSchemaErr = ipld.LoadSchemaBytes([]byte(` type ProvideRequest struct { - Key &Any + Key [&Any] Provider Provider Timestamp Int AdvisoryTTL Int @@ -234,8 +234,12 @@ func ParseProvideRequest(req *proto.ProvideRequest) (*ProvideRequest, error) { if err != nil { return nil, err } + keys := make([]cid.Cid, 0, len(req.Key)) + for _, c := range req.Key { + keys = append(keys, cid.Cid(c)) + } pr := ProvideRequest{ - Key: cid.Cid(req.Key), + Key: keys, Provider: prov, AdvisoryTTL: time.Duration(req.AdvisoryTTL), Timestamp: int64(req.Timestamp), @@ -268,9 +272,9 @@ type ProvideAsyncResult struct { Err error } -func (fp *Client) Provide(ctx context.Context, key cid.Cid, ttl time.Duration) (time.Duration, error) { +func (fp *Client) Provide(ctx context.Context, keys []cid.Cid, ttl time.Duration) (time.Duration, error) { req := ProvideRequest{ - Key: key, + Key: keys, Provider: fp.provider, AdvisoryTTL: ttl, Timestamp: time.Now().Unix(), @@ -308,9 +312,9 @@ func (fp *Client) Provide(ctx context.Context, key cid.Cid, ttl time.Duration) ( return 0, err } -func (fp *Client) ProvideAsync(ctx context.Context, key cid.Cid, ttl time.Duration) (<-chan time.Duration, error) { +func (fp *Client) ProvideAsync(ctx context.Context, keys []cid.Cid, ttl time.Duration) (<-chan time.Duration, error) { req := ProvideRequest{ - Key: key, + Key: keys, Provider: fp.provider, AdvisoryTTL: ttl, Timestamp: time.Now().Unix(), @@ -352,8 +356,12 @@ func (fp *Client) ProvideSignedRecord(ctx context.Context, req *ProvideRequest) if req.Provider != nil { providerProto = *req.Provider.ToProto() } + keys := make(proto.AnonList14, 0, len(req.Key)) + for _, c := range req.Key { + keys = append(keys, proto.LinkToAny(c)) + } ch0, err := fp.client.Provide_Async(ctx, &proto.ProvideRequest{ - Key: proto.LinkToAny(req.Key), + Key: keys, Provider: providerProto, Timestamp: values.Int(req.Timestamp), AdvisoryTTL: values.Int(req.AdvisoryTTL), diff --git a/gen/proto/proto_edelweiss.go b/gen/proto/proto_edelweiss.go index feb04be..6b0dd7e 100644 --- a/gen/proto/proto_edelweiss.go +++ b/gen/proto/proto_edelweiss.go @@ -3152,10 +3152,134 @@ func (x PutIPNSResponse) Prototype() pd3.NodePrototype { return nil } +// -- protocol type AnonList14 -- + +type AnonList14 []LinkToAny + +func (v AnonList14) Node() pd3.Node { + return v +} + +func (v *AnonList14) Parse(n pd3.Node) error { + if n.Kind() == pd3.Kind_Null { + *v = nil + return nil + } + if n.Kind() != pd3.Kind_List { + return pd1.ErrNA + } else { + *v = make(AnonList14, n.Length()) + iter := n.ListIterator() + for !iter.Done() { + if i, n, err := iter.Next(); err != nil { + return pd1.ErrNA + } else if err = (*v)[i].Parse(n); err != nil { + return err + } + } + return nil + } +} + +func (AnonList14) Kind() pd3.Kind { + return pd3.Kind_List +} + +func (AnonList14) LookupByString(string) (pd3.Node, error) { + return nil, pd1.ErrNA +} + +func (AnonList14) LookupByNode(key pd3.Node) (pd3.Node, error) { + return nil, pd1.ErrNA +} + +func (v AnonList14) LookupByIndex(i int64) (pd3.Node, error) { + if i < 0 || i >= v.Length() { + return nil, pd1.ErrBounds + } else { + return v[i].Node(), nil + } +} + +func (v AnonList14) LookupBySegment(seg pd3.PathSegment) (pd3.Node, error) { + if i, err := seg.Index(); err != nil { + return nil, pd1.ErrNA + } else { + return v.LookupByIndex(i) + } +} + +func (AnonList14) MapIterator() pd3.MapIterator { + return nil +} + +func (v AnonList14) ListIterator() pd3.ListIterator { + return &AnonList14_ListIterator{v, 0} +} + +func (v AnonList14) Length() int64 { + return int64(len(v)) +} + +func (AnonList14) IsAbsent() bool { + return false +} + +func (AnonList14) IsNull() bool { + return false +} + +func (v AnonList14) AsBool() (bool, error) { + return false, pd1.ErrNA +} + +func (AnonList14) AsInt() (int64, error) { + return 0, pd1.ErrNA +} + +func (AnonList14) AsFloat() (float64, error) { + return 0, pd1.ErrNA +} + +func (AnonList14) AsString() (string, error) { + return "", pd1.ErrNA +} + +func (AnonList14) AsBytes() ([]byte, error) { + return nil, pd1.ErrNA +} + +func (AnonList14) AsLink() (pd3.Link, error) { + return nil, pd1.ErrNA +} + +func (AnonList14) Prototype() pd3.NodePrototype { + return nil // not needed +} + +type AnonList14_ListIterator struct { + list AnonList14 + at int64 +} + +func (iter *AnonList14_ListIterator) Next() (int64, pd3.Node, error) { + if iter.Done() { + return -1, nil, pd1.ErrBounds + } + v := iter.list[iter.at] + i := int64(iter.at) + iter.at++ + return i, v.Node(), nil +} + +func (iter *AnonList14_ListIterator) Done() bool { + return iter.at >= iter.list.Length() +} + // -- protocol type ProvideRequest -- type ProvideRequest struct { - Key LinkToAny + Key AnonList14 Provider Provider Timestamp pd1.Int AdvisoryTTL pd1.Int @@ -4117,15 +4241,15 @@ func (x Node) Prototype() pd3.NodePrototype { return nil } -// -- protocol type AnonList20 -- +// -- protocol type AnonList21 -- -type AnonList20 []pd1.Bytes +type AnonList21 []pd1.Bytes -func (v AnonList20) Node() pd3.Node { +func (v AnonList21) Node() pd3.Node { return v } -func (v *AnonList20) Parse(n pd3.Node) error { +func (v *AnonList21) Parse(n pd3.Node) error { if n.Kind() == pd3.Kind_Null { *v = nil return nil @@ -4133,7 +4257,7 @@ func (v *AnonList20) Parse(n pd3.Node) error { if n.Kind() != pd3.Kind_List { return pd1.ErrNA } else { - *v = make(AnonList20, n.Length()) + *v = make(AnonList21, n.Length()) iter := n.ListIterator() for !iter.Done() { if i, n, err := iter.Next(); err != nil { @@ -4146,19 +4270,19 @@ func (v *AnonList20) Parse(n pd3.Node) error { } } -func (AnonList20) Kind() pd3.Kind { +func (AnonList21) Kind() pd3.Kind { return pd3.Kind_List } -func (AnonList20) LookupByString(string) (pd3.Node, error) { +func (AnonList21) LookupByString(string) (pd3.Node, error) { return nil, pd1.ErrNA } -func (AnonList20) LookupByNode(key pd3.Node) (pd3.Node, error) { +func (AnonList21) LookupByNode(key pd3.Node) (pd3.Node, error) { return nil, pd1.ErrNA } -func (v AnonList20) LookupByIndex(i int64) (pd3.Node, error) { +func (v AnonList21) LookupByIndex(i int64) (pd3.Node, error) { if i < 0 || i >= v.Length() { return nil, pd1.ErrBounds } else { @@ -4166,7 +4290,7 @@ func (v AnonList20) LookupByIndex(i int64) (pd3.Node, error) { } } -func (v AnonList20) LookupBySegment(seg pd3.PathSegment) (pd3.Node, error) { +func (v AnonList21) LookupBySegment(seg pd3.PathSegment) (pd3.Node, error) { if i, err := seg.Index(); err != nil { return nil, pd1.ErrNA } else { @@ -4174,60 +4298,60 @@ func (v AnonList20) LookupBySegment(seg pd3.PathSegment) (pd3.Node, error) { } } -func (AnonList20) MapIterator() pd3.MapIterator { +func (AnonList21) MapIterator() pd3.MapIterator { return nil } -func (v AnonList20) ListIterator() pd3.ListIterator { - return &AnonList20_ListIterator{v, 0} +func (v AnonList21) ListIterator() pd3.ListIterator { + return &AnonList21_ListIterator{v, 0} } -func (v AnonList20) Length() int64 { +func (v AnonList21) Length() int64 { return int64(len(v)) } -func (AnonList20) IsAbsent() bool { +func (AnonList21) IsAbsent() bool { return false } -func (AnonList20) IsNull() bool { +func (AnonList21) IsNull() bool { return false } -func (v AnonList20) AsBool() (bool, error) { +func (v AnonList21) AsBool() (bool, error) { return false, pd1.ErrNA } -func (AnonList20) AsInt() (int64, error) { +func (AnonList21) AsInt() (int64, error) { return 0, pd1.ErrNA } -func (AnonList20) AsFloat() (float64, error) { +func (AnonList21) AsFloat() (float64, error) { return 0, pd1.ErrNA } -func (AnonList20) AsString() (string, error) { +func (AnonList21) AsString() (string, error) { return "", pd1.ErrNA } -func (AnonList20) AsBytes() ([]byte, error) { +func (AnonList21) AsBytes() ([]byte, error) { return nil, pd1.ErrNA } -func (AnonList20) AsLink() (pd3.Link, error) { +func (AnonList21) AsLink() (pd3.Link, error) { return nil, pd1.ErrNA } -func (AnonList20) Prototype() pd3.NodePrototype { +func (AnonList21) Prototype() pd3.NodePrototype { return nil // not needed } -type AnonList20_ListIterator struct { - list AnonList20 +type AnonList21_ListIterator struct { + list AnonList21 at int64 } -func (iter *AnonList20_ListIterator) Next() (int64, pd3.Node, error) { +func (iter *AnonList21_ListIterator) Next() (int64, pd3.Node, error) { if iter.Done() { return -1, nil, pd1.ErrBounds } @@ -4237,7 +4361,7 @@ func (iter *AnonList20_ListIterator) Next() (int64, pd3.Node, error) { return i, v.Node(), nil } -func (iter *AnonList20_ListIterator) Done() bool { +func (iter *AnonList21_ListIterator) Done() bool { return iter.at >= iter.list.Length() } @@ -4245,7 +4369,7 @@ func (iter *AnonList20_ListIterator) Done() bool { type Peer struct { ID pd1.Bytes - Multiaddresses AnonList20 + Multiaddresses AnonList21 } func (x Peer) Node() pd3.Node { diff --git a/gen/routing.go b/gen/routing.go index 5fc3863..3f4dbb7 100644 --- a/gen/routing.go +++ b/gen/routing.go @@ -123,7 +123,7 @@ var proto = defs.Defs{ Name: "ProvideRequest", Type: defs.Structure{ Fields: defs.Fields{ - defs.Field{Name: "Key", GoName: "Key", Type: defs.Ref{Name: "LinkToAny"}}, + defs.Field{Name: "Key", GoName: "Key", Type: defs.List{Element: defs.Ref{Name: "LinkToAny"}}}, defs.Field{Name: "Provider", GoName: "Provider", Type: defs.Ref{Name: "Provider"}}, defs.Field{Name: "Timestamp", GoName: "Timestamp", Type: defs.Int{}}, defs.Field{Name: "AdvisoryTTL", GoName: "AdvisoryTTL", Type: defs.Int{}}, diff --git a/test/provide_test.go b/test/provide_test.go index 8bcf5f1..8006687 100644 --- a/test/provide_test.go +++ b/test/provide_test.go @@ -30,7 +30,7 @@ func TestProvideRoundtrip(t *testing.T) { testMH, _ := multihash.Encode([]byte("test"), multihash.IDENTITY) testCid := cid.NewCidV1(cid.Raw, testMH) - if _, err = c1.Provide(context.Background(), testCid, time.Hour); err == nil { + if _, err = c1.Provide(context.Background(), []cid.Cid{testCid}, time.Hour); err == nil { t.Fatal("should get sync error on unsigned provide request.") } @@ -43,7 +43,7 @@ func TestProvideRoundtrip(t *testing.T) { }, priv) defer s.Close() - rc, err := c.Provide(context.Background(), testCid, 2*time.Hour) + rc, err := c.Provide(context.Background(), []cid.Cid{testCid}, 2*time.Hour) if err != nil { t.Fatal(err) } From 1c4fb0a985870535c734fa10616021798e041834 Mon Sep 17 00:00:00 2001 From: Will Scott Date: Mon, 5 Sep 2022 20:40:51 +0200 Subject: [PATCH 2/2] update to raw codec on cid --- client/contentrouting.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/contentrouting.go b/client/contentrouting.go index 8822634..2c6cb7b 100644 --- a/client/contentrouting.go +++ b/client/contentrouting.go @@ -35,7 +35,7 @@ func (c *ContentRoutingClient) Provide(ctx context.Context, key cid.Cid, announc func (c *ContentRoutingClient) ProvideMany(ctx context.Context, keys []multihash.Multihash) error { keysAsCids := make([]cid.Cid, 0, len(keys)) for _, m := range keys { - keysAsCids = append(keysAsCids, cid.NewCidV0(m)) + keysAsCids = append(keysAsCids, cid.NewCidV1(cid.Raw, m)) } _, err := c.client.Provide(ctx, keysAsCids, 24*time.Hour) return err