diff --git a/announce/p2psender/option.go b/announce/p2psender/option.go index eeae2fc..ae9046b 100644 --- a/announce/p2psender/option.go +++ b/announce/p2psender/option.go @@ -6,7 +6,7 @@ import ( pubsub "github.com/libp2p/go-libp2p-pubsub" ) -// config contains all options for configuring dtsync.publisher. +// config contains all options for configuring ipnisync.publisher. type config struct { topic *pubsub.Topic extraData []byte diff --git a/dagsync/README.md b/dagsync/README.md index 0ae2698..cf3b7ec 100644 --- a/dagsync/README.md +++ b/dagsync/README.md @@ -1,8 +1,6 @@ ## dagsync -dagsync is an interface for [go-data-transfer](https://github.com/filecoin-project/go-data-transfer), -providing a 1:1 mechanism for maintaining a synchronized [IPLD dag](https://docs.ipld.io/) of data between -a publisher and a subscriber's current state for that publisher. +dagsync is an interface for maintaining a synchronized [IPLD dag](https://docs.ipld.io/) of IPNI advertisements between a publisher and a subscriber's current state for that publisher. ## Usage @@ -10,16 +8,40 @@ Typically an application will be either a provider or a subscriber, but may be b ### Publisher -Create a dagsync publisher. Update its root to cause it to publish. +Create a dagsync publisher. Update its root to publish a new advertisement. Send announcement messages to inform indexers a new advertisement is available. ```golang -pub, err := NewPublisher(host, dsstore, lsys, "/dagsync/topic") +publisher, err := ipnisync.NewPublisher(linkSys, privKey, + ipnisync.WithHTTPListenAddrs("http://127.0.0.1:0"), + ipnisync.WithStreamHost(publisherStreamHost), +) if err != nil { panic(err) } -... + +// Create announcement senders to send advertisement announcements to indexers. +var senders []announce.Sender +httpSender, err := httpsender.New(announceURLs, id) +if err != nil { + panic(err) +} +senders = append(senders, httpSender) +p2pSender, err := p2psender.New(publisherStreamHost, pubTopicName) +if err != nil { + panic(err) +} +senders = append(senders, p2pSender) + +// ... + // Publish updated root. -err = publisher.UpdateRoot(ctx, lnk.(cidlink.Link).Cid) +adCid := lnk.(cidlink.Link).Cid +err = publisher.SetRoot(adCid) +if err != nil { + panic(err) +} +// Announce new advertisement. +err := announce.Send(ctx, adCid, adsPublishedHereAddrs, senders...) if err != nil { panic(err) } @@ -27,12 +49,12 @@ if err != nil { ### Subscriber -The `Subscriber` handles subscribing to a topic, reading messages from the topic and tracking the state of each publisher. +The `Subscriber` reads advertisement chains from index-providers. Its announcement receiver receives libp2p pubsub messages from a topic and direct HTTP announcements. The Subscriber reads advertisements is response to announcement messages. Create a `Subscriber`: ```golang -sub, err := dagsync.NewSubscriber(dstHost, dstStore, dstLnkS, "/dagsync/topic", nil) +sub, err := dagsync.NewSubscriber(dstHost, dstLinkSys, dagsync.RecvAnnounce(pubTopicName)) if err != nil { panic(err) } @@ -46,34 +68,31 @@ defer cancelWatcher() go watch(watcher) func watch(notifications <-chan dagsync.SyncFinished) { - for { - syncFinished := <-notifications - // newHead is now available in the local dataStore - } + for { + syncFinished := <-notifications + // newHead is now available in the local dataStore + } } ``` To shutdown a `Subscriber`, call its `Close()` method. -A `Subscriber` can be created with a function that determines if the `Subscriber` accepts or rejects messages from a publisher. Use the `AllowPeer` option to specify the function. +A `Subscriber` can be created with announce receive options that include a function that determines if the `Subscriber` accepts or rejects announcements from a publisher. ```golang -sub, err := dagsync.NewSubscriber(dstHost, dstStore, dstLnkS, "/dagsync/topic", nil, dagsync.AllowPeer(allowPeer)) +sub, err := dagsync.NewSubscriber(dstHost, dstLinkSys, + dagsync.RecvAnnounce(pubTopicName, announce.WithALlowPeer(allowPeer)), +) + ``` The `Subscriber` keeps track of the latest head for each publisher that it has synced. This avoids exchanging the whole DAG from scratch in every update and instead downloads only the part that has not been synced. This value is not persisted as part of the library. If you want to start a `Subscriber` which has already partially synced with a provider you can use the `SetLatestSync` method: ```golang -sub, err := dagsync.NewSubscriber(dstHost, dstStore, dstLnkS, "/dagsync/topic", nil) +sub, err := dagsync.NewSubscriber(dstHost, dstLinkSys) if err != nil { panic(err) } // Set up partially synced publishers -if err = sub.SetLatestSync(peerID1, lastSync1) ; err != nil { - panic(err) -} -if err = sub.SetLatestSync(peerID2, lastSync2) ; err != nil { - panic(err) -} -if err = sub.SetLatestSync(peerID3, lastSync3) ; err != nil { - panic(err) -} +sub.SetLatestSync(peerID1, lastSync1) +sub.SetLatestSync(peerID2, lastSync2) +sub.SetLatestSync(peerID3, lastSync3) ``` diff --git a/dagsync/announce_test.go b/dagsync/announce_test.go index b262be5..1740a0d 100644 --- a/dagsync/announce_test.go +++ b/dagsync/announce_test.go @@ -2,7 +2,6 @@ package dagsync_test import ( "context" - "sync" "testing" "time" @@ -17,7 +16,6 @@ import ( "github.com/ipni/go-libipni/announce" "github.com/ipni/go-libipni/announce/p2psender" "github.com/ipni/go-libipni/dagsync" - "github.com/ipni/go-libipni/dagsync/dtsync" "github.com/ipni/go-libipni/dagsync/ipnisync" "github.com/ipni/go-libipni/dagsync/test" "github.com/libp2p/go-libp2p/core/host" @@ -35,7 +33,7 @@ func TestAnnounceReplace(t *testing.T) { blocksSeenByHook[c] = struct{}{} } - sub, err := dagsync.NewSubscriber(dstHost, dstStore, dstLnkS, testTopic, dagsync.RecvAnnounce(), + sub, err := dagsync.NewSubscriber(dstHost, dstLnkS, dagsync.RecvAnnounce(testTopic), dagsync.BlockHook(blockHook)) require.NoError(t, err) defer sub.Close() @@ -172,7 +170,7 @@ func TestAnnounce_LearnsHttpPublisherAddr(t *testing.T) { subh := test.MkTestHost(t) subds := dssync.MutexWrap(datastore.NewMapDatastore()) subls := test.MkLinkSystem(subds) - sub, err := dagsync.NewSubscriber(subh, subds, subls, testTopic, dagsync.RecvAnnounce(), dagsync.StrictAdsSelector(false)) + sub, err := dagsync.NewSubscriber(subh, subls, dagsync.RecvAnnounce(testTopic), dagsync.StrictAdsSelector(false)) require.NoError(t, err) defer sub.Close() @@ -226,13 +224,13 @@ func TestAnnounceRepublish(t *testing.T) { topics := test.WaitForMeshWithMessage(t, testTopic, dstHost, dstHost2) - sub2, err := dagsync.NewSubscriber(dstHost2, dstStore2, dstLnkS2, testTopic, - dagsync.RecvAnnounce(announce.WithTopic(topics[1])), dagsync.StrictAdsSelector(false)) + sub2, err := dagsync.NewSubscriber(dstHost2, dstLnkS2, + dagsync.RecvAnnounce("", announce.WithTopic(topics[1])), dagsync.StrictAdsSelector(false)) require.NoError(t, err) defer sub2.Close() - sub1, err := dagsync.NewSubscriber(dstHost, dstStore, dstLnkS, testTopic, - dagsync.RecvAnnounce(announce.WithTopic(topics[0]), announce.WithResend(true)), + sub1, err := dagsync.NewSubscriber(dstHost, dstLnkS, + dagsync.RecvAnnounce("", announce.WithTopic(topics[0]), announce.WithResend(true)), dagsync.StrictAdsSelector(false)) require.NoError(t, err) defer sub1.Close() @@ -344,84 +342,6 @@ func TestAllowPeerAllows(t *testing.T) { } } -func TestPublisherRejectsPeer(t *testing.T) { - t.Parallel() - // Init dagsync publisher and subscriber - srcStore := dssync.MutexWrap(datastore.NewMapDatastore()) - dstStore := dssync.MutexWrap(datastore.NewMapDatastore()) - - srcHost := test.MkTestHost(t) - dstHost := test.MkTestHost(t) - - topics := test.WaitForMeshWithMessage(t, testTopic, srcHost, dstHost) - - srcLnkS := test.MkLinkSystem(srcStore) - - blockID := dstHost.ID() - var blockMutex sync.Mutex - - allowPeer := func(peerID peer.ID) bool { - blockMutex.Lock() - defer blockMutex.Unlock() - return peerID != blockID - } - - p2pSender, err := p2psender.New(nil, "", p2psender.WithTopic(topics[0])) - require.NoError(t, err) - - pub, err := dtsync.NewPublisher(srcHost, srcStore, srcLnkS, testTopic, dtsync.WithAllowPeer(allowPeer)) - require.NoError(t, err) - defer pub.Close() - - srcHost.Peerstore().AddAddrs(dstHost.ID(), dstHost.Addrs(), time.Hour) - dstHost.Peerstore().AddAddrs(srcHost.ID(), srcHost.Addrs(), time.Hour) - dstLnkS := test.MkLinkSystem(dstStore) - - sub, err := dagsync.NewSubscriber(dstHost, dstStore, dstLnkS, testTopic, dagsync.RecvAnnounce(announce.WithTopic(topics[1]))) - require.NoError(t, err) - defer sub.Close() - - err = srcHost.Connect(context.Background(), dstHost.Peerstore().PeerInfo(dstHost.ID())) - require.NoError(t, err) - - require.NoError(t, test.WaitForP2PPublisher(pub, dstHost, testTopic)) - - watcher, cncl := sub.OnSyncFinished() - defer cncl() - - c := mkLnk(t, srcStore) - - // Update root with item - pub.SetRoot(c) - err = announce.Send(context.Background(), c, pub.Addrs(), p2pSender) - require.NoError(t, err) - - select { - case <-time.After(updateTimeout): - t.Log("publisher blocked") - case <-watcher: - t.Fatal("sync should not have happened with blocked ID") - } - - blockMutex.Lock() - blockID = peer.ID("") - blockMutex.Unlock() - - c = mkLnk(t, srcStore) - - // Update root with item - pub.SetRoot(c) - err = announce.Send(context.Background(), c, pub.Addrs(), p2pSender) - require.NoError(t, err) - - select { - case <-time.After(updateTimeout): - t.Fatal("timed out waiting for SyncFinished") - case <-watcher: - t.Log("synced with allowed ID") - } -} - func mkLnk(t *testing.T, srcStore datastore.Batching) cid.Cid { // Update root with item np := basicnode.Prototype__Any{} @@ -457,8 +377,8 @@ func initPubSub(t *testing.T, srcStore, dstStore datastore.Batching, allowPeer f dstHost.Peerstore().AddAddrs(srcHost.ID(), srcHost.Addrs(), time.Hour) dstLnkS := test.MkLinkSystem(dstStore) - sub, err := dagsync.NewSubscriber(dstHost, dstStore, dstLnkS, testTopic, - dagsync.RecvAnnounce(announce.WithTopic(topics[1]), announce.WithAllowPeer(allowPeer))) + sub, err := dagsync.NewSubscriber(dstHost, dstLnkS, + dagsync.RecvAnnounce(testTopic, announce.WithTopic(topics[1]), announce.WithAllowPeer(allowPeer))) require.NoError(t, err) err = srcHost.Connect(context.Background(), dstHost.Peerstore().PeerInfo(dstHost.ID())) diff --git a/dagsync/dtsync/head/head.go b/dagsync/dtsync/head/head.go deleted file mode 100644 index af2c10a..0000000 --- a/dagsync/dtsync/head/head.go +++ /dev/null @@ -1,176 +0,0 @@ -package head - -import ( - "context" - "errors" - "fmt" - "io" - "net" - "net/http" - "path" - "sync" - "time" - - "github.com/ipfs/go-cid" - logging "github.com/ipfs/go-log/v2" - "github.com/libp2p/go-libp2p/core/host" - "github.com/libp2p/go-libp2p/core/peer" - "github.com/libp2p/go-libp2p/core/protocol" - "github.com/libp2p/go-libp2p/p2p/net/gostream" - "github.com/multiformats/go-multistream" -) - -const closeTimeout = 30 * time.Second - -var log = logging.Logger("dagsync/head") - -type Publisher struct { - lock sync.Mutex - root cid.Cid - server *http.Server -} - -// NewPublisher creates a new head publisher. -func NewPublisher() *Publisher { - p := &Publisher{ - server: &http.Server{}, - } - p.server.Handler = http.Handler(p) - return p -} - -func protocolID(topic string) protocol.ID { - return protocol.ID(path.Join("/legs/head", topic, "0.0.1")) -} - -func previousProtocolID(topic string) protocol.ID { - return protocol.ID("/legs/head/" + topic + "/0.0.1") -} - -// Serve starts the server using the protocol ID derived from the topic name. -func (p *Publisher) Serve(host host.Host, topic string) error { - return p.serveProtocolID(protocolID(topic), host) -} - -// ServePrevious starts the server using the previous protocol ID derived from -// the topic name. This is used for testing, or for cases where it is necessary -// to support clients that do not surrort the current protocol ID> -func (p *Publisher) ServePrevious(host host.Host, topic string) error { - return p.serveProtocolID(previousProtocolID(topic), host) -} - -// serveProtocolID starts the server using the given protocol ID. -func (p *Publisher) serveProtocolID(pid protocol.ID, host host.Host) error { - l, err := gostream.Listen(host, pid) - if err != nil { - log.Errorw("Failed to listen to gostream with protocol", "host", host.ID(), "protocolID", pid) - return err - } - log.Infow("Serving gostream", "host", host.ID(), "protocolID", pid) - return p.server.Serve(l) -} - -// QueryRootCid queries a server, identified by peerID, for the root (most -// recent) CID. If the server does not support the current protocol ID, then an -// attempt is made to connect to the server using the previous protocol ID. -func QueryRootCid(ctx context.Context, host host.Host, topic string, peerID peer.ID) (cid.Cid, error) { - client := http.Client{ - Transport: &http.Transport{ - DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { - conn, err := gostream.Dial(ctx, host, peerID, protocolID(topic)) - if err != nil { - // If protocol ID is wrong, then try the previous protocol ID. - var errNoSupport multistream.ErrNotSupported[protocol.ID] - if errors.As(err, &errNoSupport) { - origErr := err - oldProtoID := previousProtocolID(topic) - conn, err = gostream.Dial(ctx, host, peerID, oldProtoID) - if err != nil { - return nil, origErr - } - log.Infow("Peer head CID server uses old protocol ID", "peer", peerID, "proto", oldProtoID) - } else { - return nil, err - } - } - return conn, err - }, - }, - } - - // The httpclient expects there to be a host here. `.invalid` is a reserved - // TLD for this purpose. See - // https://datatracker.ietf.org/doc/html/rfc2606#section-2 - resp, err := client.Get("http://unused.invalid/head") - if err != nil { - return cid.Undef, err - } - defer resp.Body.Close() - - cidStr, err := io.ReadAll(resp.Body) - if err != nil { - return cid.Undef, fmt.Errorf("cannot fully read response body: %w", err) - } - if len(cidStr) == 0 { - log.Debug("No head is set; returning cid.Undef") - return cid.Undef, nil - } - - cs := string(cidStr) - decode, err := cid.Decode(cs) - if err != nil { - return cid.Undef, fmt.Errorf("failed to decode CID %s: %w", cs, err) - } - - log.Debugw("Sucessfully queried latest head", "head", decode) - return decode, nil -} - -// ServeHTTP satisfies the http.Handler interface. -func (p *Publisher) ServeHTTP(w http.ResponseWriter, r *http.Request) { - base := path.Base(r.URL.Path) - if base != "head" { - log.Debug("Only head is supported; rejecting request with different base path") - http.Error(w, "", http.StatusNotFound) - return - } - - p.lock.Lock() - rootCid := p.root - p.lock.Unlock() - - var out []byte - if rootCid != cid.Undef { - currentHead := rootCid.String() - log.Debug("Found current head: %s", currentHead) - out = []byte(currentHead) - } else { - log.Debug("No head is set; responding with empty") - } - - _, err := w.Write(out) - if err != nil { - log.Errorw("Failed to write response", "err", err) - } -} - -// SetRoot sets the CID being published. -func (p *Publisher) SetRoot(c cid.Cid) { - p.lock.Lock() - p.root = c - p.lock.Unlock() -} - -// Close stops the server. -func (p *Publisher) Close() error { - ctx, cancel := context.WithTimeout(context.Background(), closeTimeout) - defer cancel() - return p.server.Shutdown(ctx) -} - -// Root returns the current root being publisher. -func (p *Publisher) Root() cid.Cid { - p.lock.Lock() - defer p.lock.Unlock() - return p.root -} diff --git a/dagsync/dtsync/head/head_test.go b/dagsync/dtsync/head/head_test.go deleted file mode 100644 index 6c7acc5..0000000 --- a/dagsync/dtsync/head/head_test.go +++ /dev/null @@ -1,99 +0,0 @@ -package head_test - -import ( - "context" - "strings" - "testing" - "time" - - "github.com/ipfs/go-cid" - "github.com/ipfs/go-datastore" - dssync "github.com/ipfs/go-datastore/sync" - _ "github.com/ipld/go-ipld-prime/codec/dagjson" - cidlink "github.com/ipld/go-ipld-prime/linking/cid" - "github.com/ipld/go-ipld-prime/node/basicnode" - "github.com/ipni/go-libipni/dagsync/dtsync/head" - "github.com/ipni/go-libipni/dagsync/test" - "github.com/libp2p/go-libp2p/core/protocol" - "github.com/multiformats/go-multiaddr" - multistream "github.com/multiformats/go-multistream" - "github.com/stretchr/testify/require" -) - -const testTopic = "/testtopic" - -func TestFetchLatestHead(t *testing.T) { - const ipPrefix = "/ip4/127.0.0.1/tcp/" - - publisher := test.MkTestHost(t) - client := test.MkTestHost(t) - - var addrs []multiaddr.Multiaddr - for _, a := range publisher.Addrs() { - // Change /ip4/127.0.0.1/tcp/ to /dns4/localhost/tcp/ to - // test that dns address works. - if strings.HasPrefix(a.String(), ipPrefix) { - addrStr := "/dns4/localhost/tcp/" + a.String()[len(ipPrefix):] - addr, err := multiaddr.NewMultiaddr(addrStr) - require.NoError(t, err) - addrs = append(addrs, addr) - break - } - } - - // Provide multiaddrs to connect to - client.Peerstore().AddAddrs(publisher.ID(), addrs, time.Hour) - - publisherStore := dssync.MutexWrap(datastore.NewMapDatastore()) - rootLnk, err := test.Store(publisherStore, basicnode.NewString("hello world")) - require.NoError(t, err) - - p := head.NewPublisher() - go p.Serve(publisher, testTopic) - defer p.Close() - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - // Check for expected error when querying with bad topic. - _, err = head.QueryRootCid(ctx, client, "/badtopic", publisher.ID()) - var errNoSupport multistream.ErrNotSupported[protocol.ID] - require.ErrorAs(t, err, &errNoSupport) - - c, err := head.QueryRootCid(ctx, client, testTopic, publisher.ID()) - require.NoError(t, err) - require.Equal(t, cid.Undef, c, "Expected cid undef because there is no root") - - p.SetRoot(rootLnk.(cidlink.Link).Cid) - - c, err = head.QueryRootCid(ctx, client, testTopic, publisher.ID()) - require.NoError(t, err) - - require.Equal(t, rootLnk.(cidlink.Link).Cid, c) -} - -func TestOldProtocolID(t *testing.T) { - publisher := test.MkTestHost(t) - client := test.MkTestHost(t) - - // Provide multiaddrs to connect to - client.Peerstore().AddAddrs(publisher.ID(), publisher.Addrs(), time.Hour) - - publisherStore := dssync.MutexWrap(datastore.NewMapDatastore()) - rootLnk, err := test.Store(publisherStore, basicnode.NewString("hello world")) - require.NoError(t, err) - - p := head.NewPublisher() - go p.ServePrevious(publisher, testTopic) - defer p.Close() - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - p.SetRoot(rootLnk.(cidlink.Link).Cid) - - c, err := head.QueryRootCid(ctx, client, testTopic, publisher.ID()) - require.NoError(t, err) - - require.Equal(t, rootLnk.(cidlink.Link).Cid, c) -} diff --git a/dagsync/dtsync/option.go b/dagsync/dtsync/option.go deleted file mode 100644 index b30770d..0000000 --- a/dagsync/dtsync/option.go +++ /dev/null @@ -1,55 +0,0 @@ -package dtsync - -import ( - "fmt" - - "github.com/libp2p/go-libp2p/core/peer" -) - -const ( - // Maximum number of in-prgress graphsync requests. - defaultGsMaxInRequests = 1024 - defaultGsMaxOutRequests = 1024 -) - -// config contains all options for configuring dtsync.publisher. -type config struct { - allowPeer func(peer.ID) bool - - gsMaxInRequests uint64 - gsMaxOutRequests uint64 -} - -// Option is a function that sets a value in a config. -type Option func(*config) error - -// getOpts creates a config and applies Options to it. -func getOpts(opts []Option) (config, error) { - cfg := config{ - gsMaxInRequests: defaultGsMaxInRequests, - gsMaxOutRequests: defaultGsMaxOutRequests, - } - for i, opt := range opts { - if err := opt(&cfg); err != nil { - return config{}, fmt.Errorf("option %d failed: %s", i, err) - } - } - return cfg, nil -} - -// WithAllowPeer sets the function that determines whether to allow or reject -// graphsync sessions from a peer. -func WithAllowPeer(allowPeer func(peer.ID) bool) Option { - return func(c *config) error { - c.allowPeer = allowPeer - return nil - } -} - -func WithMaxGraphsyncRequests(maxIn, maxOut uint64) Option { - return func(c *config) error { - c.gsMaxInRequests = maxIn - c.gsMaxOutRequests = maxOut - return nil - } -} diff --git a/dagsync/dtsync/publisher.go b/dagsync/dtsync/publisher.go deleted file mode 100644 index 692778a..0000000 --- a/dagsync/dtsync/publisher.go +++ /dev/null @@ -1,123 +0,0 @@ -package dtsync - -import ( - "context" - "fmt" - "net/http" - "sync" - - dt "github.com/filecoin-project/go-data-transfer/v2" - "github.com/hashicorp/go-multierror" - "github.com/ipfs/go-cid" - "github.com/ipfs/go-datastore" - "github.com/ipld/go-ipld-prime" - "github.com/ipni/go-libipni/dagsync/dtsync/head" - "github.com/libp2p/go-libp2p/core/host" - "github.com/libp2p/go-libp2p/core/peer" - "github.com/multiformats/go-multiaddr" -) - -// Publisher serves an advertisement over libp2p using data-transfer. -type Publisher struct { - closeOnce sync.Once - dtManager dt.Manager - dtClose dtCloseFunc - headPublisher *head.Publisher - host host.Host -} - -// NewPublisher creates a new dagsync publisher. -func NewPublisher(host host.Host, ds datastore.Batching, lsys ipld.LinkSystem, topicName string, options ...Option) (*Publisher, error) { - opts, err := getOpts(options) - if err != nil { - return nil, err - } - - dtManager, _, dtClose, err := makeDataTransfer(host, ds, lsys, opts.allowPeer, opts.gsMaxInRequests, opts.gsMaxOutRequests) - if err != nil { - return nil, err - } - - headPublisher := head.NewPublisher() - startHeadPublisher(host, topicName, headPublisher) - - return &Publisher{ - dtManager: dtManager, - dtClose: dtClose, - headPublisher: headPublisher, - host: host, - }, nil -} - -func startHeadPublisher(host host.Host, topicName string, headPublisher *head.Publisher) { - go func() { - log := log.With("topic", topicName, "host", host.ID()) - log.Infow("Starting head publisher for topic") - err := headPublisher.Serve(host, topicName) - if err != http.ErrServerClosed { - log.Errorw("Head publisher stopped serving on topic on host", "err", err) - } - log.Infow("Stopped head publisher") - }() -} - -// NewPublisherFromExisting instantiates publishing on an existing -// data transfer instance. -func NewPublisherFromExisting(dtManager dt.Manager, host host.Host, topicName string, lsys ipld.LinkSystem, options ...Option) (*Publisher, error) { - opts, err := getOpts(options) - if err != nil { - return nil, err - } - - err = configureDataTransferForDagsync(context.Background(), dtManager, lsys, opts.allowPeer) - if err != nil { - return nil, fmt.Errorf("cannot configure datatransfer: %w", err) - } - headPublisher := head.NewPublisher() - startHeadPublisher(host, topicName, headPublisher) - - return &Publisher{ - headPublisher: headPublisher, - host: host, - }, nil -} - -// Addrs returns the multiaddrs of the publisher's host. -func (p *Publisher) Addrs() []multiaddr.Multiaddr { - return p.host.Addrs() -} - -// ID returns the peer ID of the publisher's host. -func (p *Publisher) ID() peer.ID { - return p.host.ID() -} - -// Protocol returns the multihash protocol ID of the transport used by the -// publisher. -func (p *Publisher) Protocol() int { - return multiaddr.P_P2P -} - -// SetRoot sets the root CID of the advertisement chain. -func (p *Publisher) SetRoot(c cid.Cid) { - p.headPublisher.SetRoot(c) -} - -// Close closes the publisher. -func (p *Publisher) Close() error { - var errs error - p.closeOnce.Do(func() { - err := p.headPublisher.Close() - if err != nil { - errs = multierror.Append(errs, err) - } - - if p.dtClose != nil { - err = p.dtClose() - if err != nil { - errs = multierror.Append(errs, err) - } - } - }) - return errs -} diff --git a/dagsync/dtsync/sync.go b/dagsync/dtsync/sync.go deleted file mode 100644 index cece6a8..0000000 --- a/dagsync/dtsync/sync.go +++ /dev/null @@ -1,198 +0,0 @@ -package dtsync - -import ( - "errors" - "fmt" - "strings" - "sync" - - dt "github.com/filecoin-project/go-data-transfer/v2" - "github.com/ipfs/go-cid" - "github.com/ipfs/go-datastore" - "github.com/ipfs/go-graphsync" - logging "github.com/ipfs/go-log/v2" - "github.com/ipld/go-ipld-prime" - cidlink "github.com/ipld/go-ipld-prime/linking/cid" - "github.com/libp2p/go-libp2p/core/host" - "github.com/libp2p/go-libp2p/core/peer" -) - -var log = logging.Logger("dagsync/dtsync") - -type inProgressSyncKey struct { - c cid.Cid - peer peer.ID -} - -// Sync provides sync functionality for use with all datatransfer syncs. -type Sync struct { - dtManager dt.Manager - dtClose dtCloseFunc - host host.Host - ls *ipld.LinkSystem - unsubEvents dt.Unsubscribe - unregHook graphsync.UnregisterHookFunc - - // Used to signal CIDs that are found locally. - // Note, blockhook is called in 2 ways: - // 1. via graphsync hook registered here for blocks that are not found locally. - // 2. via Syncer.signalLocallyFoundCids for blockhooks thar are found locally. - blockHook func(peer.ID, cid.Cid) - - // Map of CID of in-progress sync to sync done channel. - syncDoneChans map[inProgressSyncKey]chan<- error - syncDoneMutex sync.Mutex -} - -// NewSync creates a new Sync with its own datatransfer.Manager. -func NewSync(host host.Host, ds datastore.Batching, lsys ipld.LinkSystem, blockHook func(peer.ID, cid.Cid), gsMaxInReq, gsMaxOutReq uint64) (*Sync, error) { - dtManager, gs, dtClose, err := makeDataTransfer(host, ds, lsys, nil, gsMaxInReq, gsMaxOutReq) - if err != nil { - return nil, err - } - - s := &Sync{ - host: host, - dtManager: dtManager, - ls: &lsys, - dtClose: dtClose, - blockHook: blockHook, - } - - if blockHook != nil { - s.unregHook = gs.RegisterIncomingBlockHook(addIncomingBlockHook(nil, blockHook)) - } - - s.unsubEvents = dtManager.SubscribeToEvents(s.onEvent) - return s, nil -} - -func addIncomingBlockHook(bFn graphsync.OnIncomingBlockHook, blockHook func(peer.ID, cid.Cid)) graphsync.OnIncomingBlockHook { - return func(p peer.ID, responseData graphsync.ResponseData, blockData graphsync.BlockData, hookActions graphsync.IncomingBlockHookActions) { - blockHook(peer.ID(p), blockData.Link().(cidlink.Link).Cid) - if bFn != nil { - bFn(p, responseData, blockData, hookActions) - } - } -} - -// Close unregisters datatransfer event notification. If this Sync owns the -// datatransfer.Manager then the Manager is stopped. -func (s *Sync) Close() error { - s.unsubEvents() - if s.unregHook != nil { - s.unregHook() - } - - err := s.dtClose() - - // Dismiss any handlers waiting completion of sync. - s.syncDoneMutex.Lock() - if len(s.syncDoneChans) != 0 { - log.Warnf("Closing datatransfer sync with %d syncs in progress", len(s.syncDoneChans)) - } - for _, ch := range s.syncDoneChans { - ch <- errors.New("sync closed") - close(ch) - } - s.syncDoneChans = nil - s.syncDoneMutex.Unlock() - - return err -} - -// NewSyncer creates a new Syncer to use for a single sync operation against a peer. -func (s *Sync) NewSyncer(peerID peer.ID, topicName string) *Syncer { - return &Syncer{ - peerID: peerID, - sync: s, - topicName: topicName, - ls: s.ls, - } -} - -// notifyOnSyncDone returns a channel that sync done notification is sent on. -func (s *Sync) notifyOnSyncDone(k inProgressSyncKey) <-chan error { - syncDone := make(chan error, 1) - - s.syncDoneMutex.Lock() - defer s.syncDoneMutex.Unlock() - - if s.syncDoneChans == nil { - s.syncDoneChans = make(map[inProgressSyncKey]chan<- error) - } - s.syncDoneChans[k] = syncDone - - return syncDone -} - -// signalSyncDone removes and closes the channel when the pending sync has -// completed. Returns true if a channel was found. -func (s *Sync) signalSyncDone(k inProgressSyncKey, err error) bool { - s.syncDoneMutex.Lock() - defer s.syncDoneMutex.Unlock() - - syncDone, ok := s.syncDoneChans[k] - if !ok { - return false - } - if len(s.syncDoneChans) == 1 { - s.syncDoneChans = nil - } else { - delete(s.syncDoneChans, k) - } - - if err != nil { - syncDone <- err - } - close(syncDone) - return true -} - -// signalLocallyFoundCids calls the syncer blockhook if present with any CIDs that are -// traversed during a sync but not transported using graphsync exchange. -func (s *Sync) signalLocallyFoundCids(id peer.ID, cids []cid.Cid) { - if s.blockHook != nil { - for _, c := range cids { - s.blockHook(id, c) - } - } -} - -// onEvent is called by the datatransfer manager to send events. -func (s *Sync) onEvent(event dt.Event, channelState dt.ChannelState) { - var err error - switch channelState.Status() { - case dt.Completed: - // Tell the waiting handler that the sync has finished successfully. - log.Debugw("datatransfer completed successfully", "cid", channelState.BaseCID(), "peer", channelState.OtherPeer()) - case dt.Cancelled: - // The request was canceled; inform waiting handler. - err = fmt.Errorf("datatransfer cancelled") - log.Warnw(err.Error(), "cid", channelState.BaseCID(), "peer", channelState.OtherPeer(), "message", channelState.Message()) - case dt.Failed: - // Communicate the error back to the waiting handler. - msg := channelState.Message() - log.Errorw("Datatransfer failed", "err", msg, "cid", channelState.BaseCID(), "peer", channelState.OtherPeer()) - if strings.Contains(msg, "content not found") { - err = fmt.Errorf("content not found: %w", ipld.ErrNotExists{}) - } else { - err = fmt.Errorf("datatransfer failed: %s", msg) - } - - default: - // Ignore non-terminal channel states. - return - } - - // Send the FinishTransfer signal to the handler. This will allow its - // handle goroutine to distribute the update and exit. - // - // It is not necessary to return the channelState CID, since we already - // know it is the correct on since it was used to look up this syncDone - // channel. - if !s.signalSyncDone(inProgressSyncKey{channelState.BaseCID(), peer.ID(channelState.OtherPeer())}, err) { - log.Errorw("Could not find channel for completed transfer notice", "cid", channelState.BaseCID()) - return - } -} diff --git a/dagsync/dtsync/syncer.go b/dagsync/dtsync/syncer.go deleted file mode 100644 index e8a8141..0000000 --- a/dagsync/dtsync/syncer.go +++ /dev/null @@ -1,119 +0,0 @@ -package dtsync - -import ( - "context" - "fmt" - "io" - - "github.com/ipfs/go-cid" - "github.com/ipld/go-ipld-prime" - "github.com/ipld/go-ipld-prime/datamodel" - cidlink "github.com/ipld/go-ipld-prime/linking/cid" - "github.com/ipld/go-ipld-prime/node/basicnode" - "github.com/ipld/go-ipld-prime/traversal" - "github.com/ipld/go-ipld-prime/traversal/selector" - "github.com/ipni/go-libipni/dagsync/dtsync/head" - "github.com/libp2p/go-libp2p/core/peer" -) - -// Syncer handles a single sync with a provider. -type Syncer struct { - peerID peer.ID - sync *Sync - ls *ipld.LinkSystem - topicName string -} - -// GetHead queries a provider for the latest CID. -func (s *Syncer) GetHead(ctx context.Context) (cid.Cid, error) { - return head.QueryRootCid(ctx, s.sync.host, s.topicName, s.peerID) -} - -// Sync opens a datatransfer data channel and uses the selector to pull data -// from the provider. -func (s *Syncer) Sync(ctx context.Context, nextCid cid.Cid, sel ipld.Node) error { - // See if we already have the requested data first. - // TODO: The check here is equivalent to "all or nothing": if a DAG is partially available - // The entire thing will be re-downloaded even if we are missing only a single link. - // Consider a further optimisation where we would only sync the portion of DAG that - // is absent. - // Hint: be careful with the selector; this can become tricky depending on what the - // given selector is after. We could accept arguments that ask the user to - // help with determining what the "next" CID would be if a DAG is partially - // present. Similar to what SegmentSyncActions does. - if cids, ok := s.has(ctx, nextCid, sel); ok { - s.sync.signalLocallyFoundCids(s.peerID, cids) - inProgressSyncK := inProgressSyncKey{nextCid, s.peerID} - s.sync.signalSyncDone(inProgressSyncK, nil) - return nil - } - - inProgressSyncK := inProgressSyncKey{nextCid, s.peerID} - syncDone := s.sync.notifyOnSyncDone(inProgressSyncK) - - log.Debugw("Starting data channel for message source", "cid", nextCid, "source_peer", s.peerID) - - v := Voucher{&nextCid} - // Do not pass cancelable context into OpenPullDataChannel because a - // canceled context causes it to hang. - _, err := s.sync.dtManager.OpenPullDataChannel(context.Background(), s.peerID, v.AsVoucher(), nextCid, sel) - if err != nil { - s.sync.signalSyncDone(inProgressSyncK, nil) - return fmt.Errorf("cannot open data channel: %w", err) - } - - // Wait for transfer finished signal. - select { - case err = <-syncDone: - case <-ctx.Done(): - s.sync.signalSyncDone(inProgressSyncK, ctx.Err()) - err = <-syncDone - } - return err -} - -// has determines if a given CID and selector is stored in the linksystem for a syncer already. -// -// If stored, returns true along with the list of CIDs that were encountered during traversal -// in order of traversal. Otherwise, returns false with no CIDs. -func (s *Syncer) has(ctx context.Context, nextCid cid.Cid, sel ipld.Node) ([]cid.Cid, bool) { - getMissingLs := cidlink.DefaultLinkSystem() - // trusted because it'll be hashed/verified on the way into the link system when fetched. - getMissingLs.TrustedStorage = true - - var traversed []cid.Cid - getMissingLs.StorageReadOpener = func(lc ipld.LinkContext, l ipld.Link) (io.Reader, error) { - r, err := s.ls.StorageReadOpener(lc, l) - if err != nil { - return nil, fmt.Errorf("not available locally: %w", err) - } - // Found block read opener, so return it. - traversed = append(traversed, l.(cidlink.Link).Cid) - return r, nil - } - - progress := traversal.Progress{ - Cfg: &traversal.Config{ - Ctx: ctx, - LinkSystem: getMissingLs, - LinkTargetNodePrototypeChooser: basicnode.Chooser, - }, - Path: datamodel.NewPath([]datamodel.PathSegment{}), - } - csel, err := selector.CompileSelector(sel) - if err != nil { - return nil, false - } - - // get the direct node. - rootNode, err := getMissingLs.Load(ipld.LinkContext{}, cidlink.Link{Cid: nextCid}, basicnode.Prototype.Any) - if err != nil { - return nil, false - } - if err := progress.WalkMatching(rootNode, csel, func(p traversal.Progress, n datamodel.Node) error { - return nil - }); err != nil { - return nil, false - } - return traversed, true -} diff --git a/dagsync/dtsync/syncer_test.go b/dagsync/dtsync/syncer_test.go deleted file mode 100644 index f0d79e6..0000000 --- a/dagsync/dtsync/syncer_test.go +++ /dev/null @@ -1,188 +0,0 @@ -package dtsync_test - -import ( - "context" - "testing" - - "github.com/ipfs/go-cid" - "github.com/ipfs/go-datastore" - dssync "github.com/ipfs/go-datastore/sync" - "github.com/ipld/go-ipld-prime" - "github.com/ipld/go-ipld-prime/fluent" - cidlink "github.com/ipld/go-ipld-prime/linking/cid" - "github.com/ipld/go-ipld-prime/node/basicnode" - "github.com/ipld/go-ipld-prime/storage/memstore" - selectorparse "github.com/ipld/go-ipld-prime/traversal/selector/parse" - "github.com/ipni/go-libipni/dagsync/dtsync" - "github.com/ipni/go-libipni/dagsync/test" - "github.com/libp2p/go-libp2p/core/host" - "github.com/libp2p/go-libp2p/core/peer" - "github.com/libp2p/go-libp2p/core/peerstore" - "github.com/multiformats/go-multicodec" - "github.com/stretchr/testify/require" -) - -func TestDTSync_CallsBlockHookWhenCIDsAreFullyFoundLocally(t *testing.T) { - const topic = "fish" - ctx := context.Background() - - // Create a linksystem and populate it with 3 nodes. - // The test uses the same linksystem store across both publisher and syncer. - // This is to simulate a scenario where the DAG being synced is present on syncer's side. - ls := cidlink.DefaultLinkSystem() - store := &memstore.Store{} - ls.SetReadStorage(store) - ls.SetWriteStorage(store) - lp := cidlink.LinkPrototype{ - Prefix: cid.Prefix{ - Version: 1, - Codec: uint64(multicodec.DagJson), - MhType: uint64(multicodec.Sha2_256), - MhLength: -1, - }, - } - - l1, err := ls.Store(ipld.LinkContext{Ctx: ctx}, lp, fluent.MustBuildMap(basicnode.Prototype.Map, 1, func(na fluent.MapAssembler) { - na.AssembleEntry("fish").AssignString("lobster") - })) - require.NoError(t, err) - - l2, err := ls.Store(ipld.LinkContext{Ctx: ctx}, lp, fluent.MustBuildMap(basicnode.Prototype.Map, 2, func(na fluent.MapAssembler) { - na.AssembleEntry("gogo").AssignString("barreleye") - na.AssembleEntry("next").AssignLink(l1) - })) - require.NoError(t, err) - - l3, err := ls.Store(ipld.LinkContext{Ctx: ctx}, lp, fluent.MustBuildMap(basicnode.Prototype.Map, 2, func(na fluent.MapAssembler) { - na.AssembleEntry("unda").AssignString("dasea") - na.AssembleEntry("next").AssignLink(l2) - })) - require.NoError(t, err) - - // Start a publisher to sync from. - pubh := test.MkTestHost(t) - pub, err := dtsync.NewPublisher(pubh, dssync.MutexWrap(datastore.NewMapDatastore()), ls, topic) - require.NoError(t, err) - t.Cleanup(func() { require.NoError(t, pub.Close()) }) - - // Set up a syncer. - subh := test.MkTestHost(t) - - subh.Peerstore().AddAddrs(pubh.ID(), pubh.Addrs(), peerstore.PermanentAddrTTL) - var gotCids []cid.Cid - testHook := func(id peer.ID, cid cid.Cid) { - gotCids = append(gotCids, cid) - } - - // Use the same linksystem as the publisher for the syncer; this is to assure all the blocks being - // synced are already present on the syncer side. - subject, err := dtsync.NewSync(subh, dssync.MutexWrap(datastore.NewMapDatastore()), ls, testHook, 0, 0) - require.NoError(t, err) - t.Cleanup(func() { require.NoError(t, subject.Close()) }) - - // Sync l3 from the publisher. - syncer := subject.NewSyncer(pubh.ID(), topic) - require.NoError(t, syncer.Sync(ctx, l3.(cidlink.Link).Cid, selectorparse.CommonSelector_ExploreAllRecursively)) - - // Assert there are three synced CIDs. - require.Len(t, gotCids, 3) - - // Assert that they are signalled in the right order. - require.Equal(t, l3.(cidlink.Link).Cid, gotCids[0]) - require.Equal(t, l2.(cidlink.Link).Cid, gotCids[1]) - require.Equal(t, l1.(cidlink.Link).Cid, gotCids[2]) -} - -func TestDTSync_CallsBlockHookWhenCIDsArePartiallyFoundLocally(t *testing.T) { - const topic = "fish" - ctx := context.Background() - - // Create a publisher that stores 3 nodes - var pubh host.Host - var l1, l2, l3 ipld.Link - substore := &memstore.Store{} - { - publs := cidlink.DefaultLinkSystem() - pubstore := &memstore.Store{} - publs.SetReadStorage(pubstore) - publs.SetWriteStorage(pubstore) - lp := cidlink.LinkPrototype{ - Prefix: cid.Prefix{ - Version: 1, - Codec: uint64(multicodec.DagJson), - MhType: uint64(multicodec.Sha2_256), - MhLength: -1, - }, - } - var err error - l1, err = publs.Store(ipld.LinkContext{Ctx: ctx}, lp, fluent.MustBuildMap(basicnode.Prototype.Map, 1, func(na fluent.MapAssembler) { - na.AssembleEntry("fish").AssignString("lobster") - })) - require.NoError(t, err) - - l2, err = publs.Store(ipld.LinkContext{Ctx: ctx}, lp, fluent.MustBuildMap(basicnode.Prototype.Map, 2, func(na fluent.MapAssembler) { - na.AssembleEntry("gogo").AssignString("barreleye") - na.AssembleEntry("next").AssignLink(l1) - })) - require.NoError(t, err) - - l3, err = publs.Store(ipld.LinkContext{Ctx: ctx}, lp, fluent.MustBuildMap(basicnode.Prototype.Map, 2, func(na fluent.MapAssembler) { - na.AssembleEntry("unda").AssignString("dasea") - na.AssembleEntry("next").AssignLink(l2) - })) - require.NoError(t, err) - - // Copy l1 and l3 but not l2. - // This is to simulate partial availability of a DAG on syncer side. - for k, v := range pubstore.Bag { - if k != l2.Binary() { - require.NoError(t, substore.Put(ctx, k, v)) - } - } - - // Start a publisher to sync from. - pubh = test.MkTestHost(t) - pub, err := dtsync.NewPublisher(pubh, dssync.MutexWrap(datastore.NewMapDatastore()), publs, topic) - require.NoError(t, err) - t.Cleanup(func() { require.NoError(t, pub.Close()) }) - - // Publish head. - pub.SetRoot(l3.(cidlink.Link).Cid) - } - - // Set up a syncer. - subh := test.MkTestHost(t) - subh.Peerstore().AddAddrs(pubh.ID(), pubh.Addrs(), peerstore.PermanentAddrTTL) - var gotCids []cid.Cid - testHook := func(id peer.ID, cid cid.Cid) { - gotCids = append(gotCids, cid) - } - - subls := cidlink.DefaultLinkSystem() - subls.SetReadStorage(substore) - subls.SetWriteStorage(substore) - - // Sanity check that syncer linksystem has l1 and l3 but not l2. - _, err := subls.Load(ipld.LinkContext{Ctx: ctx}, l1, basicnode.Prototype.Any) - require.NoError(t, err) - _, err = subls.Load(ipld.LinkContext{Ctx: ctx}, l3, basicnode.Prototype.Any) - require.NoError(t, err) - _, err = subls.Load(ipld.LinkContext{Ctx: ctx}, l2, basicnode.Prototype.Any) - require.Error(t, err) - - subject, err := dtsync.NewSync(subh, dssync.MutexWrap(datastore.NewMapDatastore()), subls, testHook, 0, 0) - require.NoError(t, err) - t.Cleanup(func() { require.NoError(t, subject.Close()) }) - - // Sync l3 from the publisher. - syncer := subject.NewSyncer(pubh.ID(), topic) - require.NoError(t, syncer.Sync(ctx, l3.(cidlink.Link).Cid, selectorparse.CommonSelector_ExploreAllRecursively)) - - // Assert there are three synced CIDs. - require.Len(t, gotCids, 3) - - // Assert that they are signalled in the right order. - require.Equal(t, l3.(cidlink.Link).Cid, gotCids[0]) - require.Equal(t, l2.(cidlink.Link).Cid, gotCids[1]) - require.Equal(t, l1.(cidlink.Link).Cid, gotCids[2]) -} diff --git a/dagsync/dtsync/util.go b/dagsync/dtsync/util.go deleted file mode 100644 index b7fa638..0000000 --- a/dagsync/dtsync/util.go +++ /dev/null @@ -1,158 +0,0 @@ -package dtsync - -import ( - "context" - "fmt" - "strings" - "time" - - dt "github.com/filecoin-project/go-data-transfer/v2" - "github.com/filecoin-project/go-data-transfer/v2/channelmonitor" - datatransfer "github.com/filecoin-project/go-data-transfer/v2/impl" - dtnetwork "github.com/filecoin-project/go-data-transfer/v2/network" - gstransport "github.com/filecoin-project/go-data-transfer/v2/transport/graphsync" - "github.com/ipfs/go-datastore" - "github.com/ipfs/go-graphsync" - gsimpl "github.com/ipfs/go-graphsync/impl" - gsnet "github.com/ipfs/go-graphsync/network" - "github.com/ipld/go-ipld-prime" - "github.com/libp2p/go-libp2p/core/host" - "github.com/libp2p/go-libp2p/core/peer" -) - -// Time to wait for datatransfer to gracefully stop before canceling. -const datatransferStopTimeout = time.Minute - -const ( - defaultGsMaxInReq = 1024 - defaultGsMaxOutReq = 1024 -) - -type dtCloseFunc func() error - -// configureDataTransferForDagsync configures an existing data transfer -// instance to serve dagsync requests from given linksystem (publisher only). -func configureDataTransferForDagsync(ctx context.Context, dtManager dt.Manager, lsys ipld.LinkSystem, allowPeer func(peer.ID) bool) error { - err := registerVoucher(dtManager, allowPeer) - if err != nil { - return err - } - lsc := dagsyncStorageConfiguration{lsys} - if err = dtManager.RegisterTransportConfigurer(LegsVoucherType, lsc.configureTransport); err != nil { - return fmt.Errorf("failed to register datatransfer TransportConfigurer: %w", err) - } - return nil -} - -type dagsyncStorageConfiguration struct { - linkSystem ipld.LinkSystem -} - -func (lsc dagsyncStorageConfiguration) configureTransport(_ dt.ChannelID, _ dt.TypedVoucher) []dt.TransportOption { - return []dt.TransportOption{gstransport.UseStore(lsc.linkSystem)} -} - -func registerVoucher(dtManager dt.Manager, allowPeer func(peer.ID) bool) error { - val := &dagsyncValidator{ - allowPeer: allowPeer, - } - err := dtManager.RegisterVoucherType(LegsVoucherType, val) - if err != nil { - // This can happen if a host is both a publisher and a subscriber. - if strings.Contains(err.Error(), "identifier already registered: "+string(LegsVoucherType)) { - // Matching the error string is the best we can do until datatransfer exposes some handles - // to either check for types or re-register vouchers. - log.Warn("voucher type already registered; skipping datatrasfer voucher registration", "type", LegsVoucherType) - return nil - } - return fmt.Errorf("failed to register dagsync validator voucher type: %w", err) - } - return nil -} - -func makeDataTransfer(host host.Host, ds datastore.Batching, lsys ipld.LinkSystem, allowPeer func(peer.ID) bool, gsMaxInReq, gsMaxOutReq uint64) (dt.Manager, graphsync.GraphExchange, dtCloseFunc, error) { - gsNet := gsnet.NewFromLibp2pHost(host) - ctx, cancel := context.WithCancel(context.Background()) - if gsMaxInReq == 0 { - gsMaxInReq = defaultGsMaxInReq - } - if gsMaxOutReq == 0 { - gsMaxOutReq = defaultGsMaxOutReq - } - gs := gsimpl.New(ctx, gsNet, lsys, gsimpl.MaxInProgressIncomingRequests(gsMaxInReq), gsimpl.MaxInProgressOutgoingRequests(gsMaxOutReq)) - - dtNet := dtnetwork.NewFromLibp2pHost(host) - tp := gstransport.NewTransport(host.ID(), gs) - - dtRestartConfig := datatransfer.ChannelRestartConfig(channelmonitor.Config{ - AcceptTimeout: 30 * time.Second, - CompleteTimeout: time.Minute, - - // When an error occurs, wait a little while until all related errors - // have fired before sending a restart message - RestartDebounce: 10 * time.Second, - // After sending a restart, wait at least this long before sending another - RestartBackoff: 30 * time.Second, - // After trying to restart this many times, give up and fail the transfer - MaxConsecutiveRestarts: 1, - }) - - dtManager, err := datatransfer.NewDataTransfer(ds, dtNet, tp, dtRestartConfig) - if err != nil { - cancel() - return nil, nil, nil, fmt.Errorf("failed to instantiate datatransfer: %w", err) - } - - err = registerVoucher(dtManager, allowPeer) - if err != nil { - cancel() - return nil, nil, nil, fmt.Errorf("failed to register voucher: %w", err) - } - - // Tell datatransfer to notify when ready. - dtReady := make(chan error) - dtManager.OnReady(func(e error) { - dtReady <- e - }) - - // Start datatransfer. The context passed in allows Start to be canceled - // if fsm migration takes too long. Timeout for dtManager.Start() is not - // handled here, so pass context.Background(). - if err = dtManager.Start(ctx); err != nil { - cancel() - return nil, nil, nil, fmt.Errorf("failed to start datatransfer: %w", err) - } - log.Info("Started data transfer manager successfully.") - - // Wait for datatransfer to be ready. - log.Info("Awaiting data transfer manager to become ready...") - err = <-dtReady - if err != nil { - log.Errorw("Failed while waiting for data transfer manager to become ready", "err", err) - cancel() - return nil, nil, nil, err - } - log.Info("Data transfer manager is ready.") - - closeFunc := func() error { - errCh := make(chan error, 1) - stopCtx, stopCancel := context.WithTimeout(context.Background(), datatransferStopTimeout) - go func() { - errCh <- dtManager.Stop(stopCtx) - }() - var err error - select { - case err = <-errCh: - if err != nil { - err = fmt.Errorf("failed to stop datatransfer manager: %w", err) - } - case <-stopCtx.Done(): - log.Errorw("Timeout waiting to stop datatransfer manager", "timeout", datatransferStopTimeout.String()) - } - stopCancel() - cancel() - return err - } - - return dtManager, gs, closeFunc, nil -} diff --git a/dagsync/dtsync/util_test.go b/dagsync/dtsync/util_test.go deleted file mode 100644 index 5415856..0000000 --- a/dagsync/dtsync/util_test.go +++ /dev/null @@ -1,20 +0,0 @@ -package dtsync - -import ( - "testing" - - "github.com/ipfs/go-datastore" - cidlink "github.com/ipld/go-ipld-prime/linking/cid" - "github.com/ipni/go-libipni/dagsync/test" - "github.com/stretchr/testify/require" -) - -func Test_registerVoucherHandlesAlreadyRegisteredGracefully(t *testing.T) { - h := test.MkTestHost(t) - dt, _, close, err := makeDataTransfer(h, datastore.NewMapDatastore(), cidlink.DefaultLinkSystem(), nil, 0, 0) - require.NoError(t, err) - t.Cleanup(func() { require.NoError(t, close()) }) - - require.NoError(t, registerVoucher(dt, nil)) - require.NoError(t, registerVoucher(dt, nil)) -} diff --git a/dagsync/dtsync/voucher.go b/dagsync/dtsync/voucher.go deleted file mode 100644 index be60d67..0000000 --- a/dagsync/dtsync/voucher.go +++ /dev/null @@ -1,156 +0,0 @@ -package dtsync - -import ( - // for voucher schema embed - _ "embed" - "errors" - "fmt" - - datatransfer "github.com/filecoin-project/go-data-transfer/v2" - "github.com/ipfs/go-cid" - "github.com/ipld/go-ipld-prime" - "github.com/ipld/go-ipld-prime/datamodel" - "github.com/ipld/go-ipld-prime/node/bindnode" - bindnoderegistry "github.com/ipld/go-ipld-prime/node/bindnode/registry" - "github.com/libp2p/go-libp2p/core/peer" - cborgen "github.com/whyrusleeping/cbor-gen" -) - -//go:generate go run -tags cbg ../tools - -//go:embed voucher.ipldsch -var embedSchema []byte - -var ( - _ datatransfer.RequestValidator = (*dagsyncValidator)(nil) - - _ cborgen.CBORMarshaler = (*Voucher)(nil) - _ cborgen.CBORUnmarshaler = (*Voucher)(nil) - - _ cborgen.CBORMarshaler = (*VoucherResult)(nil) - _ cborgen.CBORUnmarshaler = (*VoucherResult)(nil) -) - -// A Voucher is used to communicate a new DAG head -type Voucher struct { - Head *cid.Cid -} - -// reads a voucher from an ipld node -func VoucherFromNode(node datamodel.Node) (*Voucher, error) { - if node == nil { - return nil, fmt.Errorf("empty voucher") - } - dpIface, err := BindnodeRegistry.TypeFromNode(node, &Voucher{}) - if err != nil { - return nil, fmt.Errorf("invalid voucher: %w", err) - } - dp, _ := dpIface.(*Voucher) // safe to assume type - return dp, nil -} - -func (v *Voucher) AsVoucher() datatransfer.TypedVoucher { - return datatransfer.TypedVoucher{ - Type: LegsVoucherType, - Voucher: BindnodeRegistry.TypeToNode(v), - } -} - -const LegsVoucherType = datatransfer.TypeIdentifier("LegsVoucher") - -// A VoucherResult responds to a voucher -type VoucherResult struct { - Code uint64 -} - -const LegsVoucherResultType = datatransfer.TypeIdentifier("LegsVoucherResult") - -// reads a voucher from an ipld node -func VoucherResultFromNode(node datamodel.Node) (*VoucherResult, error) { - if node == nil { - return nil, fmt.Errorf("empty voucher result") - } - dpIface, err := BindnodeRegistry.TypeFromNode(node, &VoucherResult{}) - if err != nil { - return nil, fmt.Errorf("invalid voucher: %w", err) - } - dp, _ := dpIface.(*VoucherResult) // safe to assume type - return dp, nil -} - -func (vr *VoucherResult) AsVoucher() datatransfer.TypedVoucher { - return datatransfer.TypedVoucher{ - Type: LegsVoucherResultType, - Voucher: BindnodeRegistry.TypeToNode(vr), - } -} - -var BindnodeRegistry = bindnoderegistry.NewRegistry() - -func init() { - for _, r := range []struct { - typ interface{} - typName string - opts []bindnode.Option - }{ - {(*VoucherResult)(nil), "VoucherResult", nil}, - {(*Voucher)(nil), "Voucher", nil}, - } { - if err := BindnodeRegistry.RegisterType(r.typ, string(embedSchema), r.typName, r.opts...); err != nil { - panic(err.Error()) - } - } -} - -type dagsyncValidator struct { - //ctx context.Context - //ValidationsReceived chan receivedValidation - allowPeer func(peer.ID) bool -} - -func (vl *dagsyncValidator) ValidatePush( - _ datatransfer.ChannelID, - _ peer.ID, - _ datamodel.Node, - _ cid.Cid, - _ ipld.Node) (datatransfer.ValidationResult, error) { - - // This is a pull-only DT voucher. - return datatransfer.ValidationResult{}, errors.New("invalid") -} - -func (vl *dagsyncValidator) validate(peerID peer.ID, voucher datamodel.Node) (datatransfer.ValidationResult, error) { - - v, err := VoucherFromNode(voucher) - if err != nil { - return datatransfer.ValidationResult{}, err - } - if v.Head == nil { - return datatransfer.ValidationResult{}, errors.New("invalid") - } - - if vl.allowPeer != nil && !vl.allowPeer(peerID) { - return datatransfer.ValidationResult{}, errors.New("peer not allowed") - } - - vr := (&VoucherResult{}).AsVoucher() - return datatransfer.ValidationResult{ - Accepted: true, - VoucherResult: &vr, - }, nil - -} -func (vl *dagsyncValidator) ValidatePull( - _ datatransfer.ChannelID, - peerID peer.ID, - voucher datamodel.Node, - _ cid.Cid, - _ ipld.Node) (datatransfer.ValidationResult, error) { - return vl.validate(peerID, voucher) -} - -func (vl *dagsyncValidator) ValidateRestart( - _ datatransfer.ChannelID, - state datatransfer.ChannelState) (datatransfer.ValidationResult, error) { - return vl.validate(state.ChannelID().Initiator, state.Voucher().Voucher) -} diff --git a/dagsync/dtsync/voucher.ipldsch b/dagsync/dtsync/voucher.ipldsch deleted file mode 100644 index d547e49..0000000 --- a/dagsync/dtsync/voucher.ipldsch +++ /dev/null @@ -1,7 +0,0 @@ -type Voucher struct { - Head nullable &Any -} - -type VoucherResult struct { - Code Int -} \ No newline at end of file diff --git a/dagsync/dtsync/voucher_cbor_gen.go b/dagsync/dtsync/voucher_cbor_gen.go deleted file mode 100644 index 3d915af..0000000 --- a/dagsync/dtsync/voucher_cbor_gen.go +++ /dev/null @@ -1,208 +0,0 @@ -// Code generated by github.com/whyrusleeping/cbor-gen. DO NOT EDIT. - -package dtsync - -import ( - "fmt" - "io" - "math" - "sort" - - cid "github.com/ipfs/go-cid" - cbg "github.com/whyrusleeping/cbor-gen" - xerrors "golang.org/x/xerrors" -) - -var _ = xerrors.Errorf -var _ = cid.Undef -var _ = math.E -var _ = sort.Sort - -func (t *Voucher) MarshalCBOR(w io.Writer) error { - if t == nil { - _, err := w.Write(cbg.CborNull) - return err - } - if _, err := w.Write([]byte{161}); err != nil { - return err - } - - scratch := make([]byte, 9) - - // t.Head (cid.Cid) (struct) - if len("Head") > cbg.MaxLength { - return xerrors.Errorf("Value in field \"Head\" was too long") - } - - if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("Head"))); err != nil { - return err - } - if _, err := io.WriteString(w, string("Head")); err != nil { - return err - } - - if t.Head == nil { - if _, err := w.Write(cbg.CborNull); err != nil { - return err - } - } else { - if err := cbg.WriteCidBuf(scratch, w, *t.Head); err != nil { - return xerrors.Errorf("failed to write cid field t.Head: %w", err) - } - } - - return nil -} - -func (t *Voucher) UnmarshalCBOR(r io.Reader) error { - *t = Voucher{} - - br := cbg.GetPeeker(r) - scratch := make([]byte, 8) - - maj, extra, err := cbg.CborReadHeaderBuf(br, scratch) - if err != nil { - return err - } - if maj != cbg.MajMap { - return fmt.Errorf("cbor input should be of type map") - } - - if extra > cbg.MaxLength { - return fmt.Errorf("Voucher: map struct too large (%d)", extra) - } - - var name string - n := extra - - for i := uint64(0); i < n; i++ { - - { - sval, err := cbg.ReadString(br) - if err != nil { - return err - } - - name = string(sval) - } - - switch name { - // t.Head (cid.Cid) (struct) - case "Head": - - { - - b, err := br.ReadByte() - if err != nil { - return err - } - if b != cbg.CborNull[0] { - if err := br.UnreadByte(); err != nil { - return err - } - - c, err := cbg.ReadCid(br) - if err != nil { - return xerrors.Errorf("failed to read cid field t.Head: %w", err) - } - - t.Head = &c - } - - } - - default: - // Field doesn't exist on this type, so ignore it - cbg.ScanForLinks(r, func(cid.Cid) {}) - } - } - - return nil -} -func (t *VoucherResult) MarshalCBOR(w io.Writer) error { - if t == nil { - _, err := w.Write(cbg.CborNull) - return err - } - if _, err := w.Write([]byte{161}); err != nil { - return err - } - - scratch := make([]byte, 9) - - // t.Code (uint64) (uint64) - if len("Code") > cbg.MaxLength { - return xerrors.Errorf("Value in field \"Code\" was too long") - } - - if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("Code"))); err != nil { - return err - } - if _, err := io.WriteString(w, string("Code")); err != nil { - return err - } - - if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.Code)); err != nil { - return err - } - - return nil -} - -func (t *VoucherResult) UnmarshalCBOR(r io.Reader) error { - *t = VoucherResult{} - - br := cbg.GetPeeker(r) - scratch := make([]byte, 8) - - maj, extra, err := cbg.CborReadHeaderBuf(br, scratch) - if err != nil { - return err - } - if maj != cbg.MajMap { - return fmt.Errorf("cbor input should be of type map") - } - - if extra > cbg.MaxLength { - return fmt.Errorf("VoucherResult: map struct too large (%d)", extra) - } - - var name string - n := extra - - for i := uint64(0); i < n; i++ { - - { - sval, err := cbg.ReadString(br) - if err != nil { - return err - } - - name = string(sval) - } - - switch name { - // t.Code (uint64) (uint64) - case "Code": - - { - - maj, extra, err = cbg.CborReadHeaderBuf(br, scratch) - if err != nil { - return err - } - if maj != cbg.MajUnsignedInt { - return fmt.Errorf("wrong type for uint64 field") - } - t.Code = uint64(extra) - - } - - default: - // Field doesn't exist on this type, so ignore it - cbg.ScanForLinks(r, func(cid.Cid) {}) - } - } - - return nil -} diff --git a/dagsync/example_test.go b/dagsync/example_test.go index 1dfb0db..3d7abcc 100644 --- a/dagsync/example_test.go +++ b/dagsync/example_test.go @@ -68,16 +68,14 @@ func ExampleSubscriber() { srcHost.Peerstore().AddAddrs(dstHost.ID(), dstHost.Addrs(), time.Hour) dstHost.Peerstore().AddAddrs(srcHost.ID(), srcHost.Addrs(), time.Hour) - sub, err := dagsync.NewSubscriber(dstHost, dstStore, dstLnkSys, "/indexer/ingest/testnet") + sub, err := dagsync.NewSubscriber(dstHost, dstLnkSys, dagsync.RecvAnnounce("/indexer/ingest/testnet")) if err != nil { panic(err) } defer sub.Close() - // Connections must be made after Subscriber is created, because the - // gossip pubsub must be created before connections are made. Otherwise, - // the connecting hosts will not see the destination host has pubsub and - // messages will not get published. + // Connections are made after Subscriber is created, so that the connecting + // host sees that the destination host has pubsub. dstPeerInfo := dstHost.Peerstore().PeerInfo(dstHost.ID()) if err = srcHost.Connect(context.Background(), dstPeerInfo); err != nil { panic(err) diff --git a/dagsync/http_test.go b/dagsync/http_test.go index cd35c15..b281952 100644 --- a/dagsync/http_test.go +++ b/dagsync/http_test.go @@ -51,7 +51,7 @@ func setupPublisherSubscriber(t *testing.T, subscriberOptions []dagsync.Option) dstHost := test.MkTestHost(t) subscriberOptions = append(subscriberOptions, dagsync.StrictAdsSelector(false)) - sub, err := dagsync.NewSubscriber(dstHost, dstStore, dstLinkSys, testTopic, subscriberOptions...) + sub, err := dagsync.NewSubscriber(dstHost, dstLinkSys, subscriberOptions...) require.NoError(t, err) t.Cleanup(func() { sub.Close() diff --git a/dagsync/ipnisync/publisher_test.go b/dagsync/ipnisync/publisher_test.go index d77e355..93cf38a 100644 --- a/dagsync/ipnisync/publisher_test.go +++ b/dagsync/ipnisync/publisher_test.go @@ -141,7 +141,7 @@ func TestPublisherWithLibp2pHTTP(t *testing.T) { req.Equal(link.(cidlink.Link).Cid, headCid) - clientSyncer.Sync(ctx, headCid, selectorparse.CommonSelector_MatchPoint) + err = clientSyncer.Sync(ctx, headCid, selectorparse.CommonSelector_MatchPoint) require.NoError(t, err) // Assert that data is loadable from the link system. @@ -230,7 +230,7 @@ func TestExistingServerWithPublisher(t *testing.T) { req.NoError(err) req.Equal(link.(cidlink.Link).Cid, headCid) - clientSyncer.Sync(ctx, headCid, selectorparse.CommonSelector_MatchPoint) + err = clientSyncer.Sync(ctx, headCid, selectorparse.CommonSelector_MatchPoint) require.NoError(t, err) // Assert that data is loadable from the link system. @@ -437,7 +437,7 @@ func TestHandlerPath(t *testing.T) { req.NoError(err) req.Equal(link.(cidlink.Link).Cid, headCid) - clientSyncer.Sync(ctx, headCid, selectorparse.CommonSelector_MatchPoint) + err = clientSyncer.Sync(ctx, headCid, selectorparse.CommonSelector_MatchPoint) require.NoError(t, err) // Assert that data is loadable from the link system. diff --git a/dagsync/ipnisync/sync.go b/dagsync/ipnisync/sync.go index 8b4feed..82da23c 100644 --- a/dagsync/ipnisync/sync.go +++ b/dagsync/ipnisync/sync.go @@ -317,7 +317,7 @@ retry: case http.StatusOK: return cb(resp.Body) case http.StatusNotFound: - io.Copy(io.Discard, resp.Body) + _, _ = io.Copy(io.Discard, resp.Body) if s.plainHTTP && !s.noPath { // Try again with no path for legacy http. log.Warnw("Plain HTTP got not found response, retrying without IPNI path for legacy HTTP") @@ -331,7 +331,7 @@ retry: // being checked already. return fmt.Errorf("content not found: %w", ipld.ErrNotExists{}) case http.StatusForbidden: - io.Copy(io.Discard, resp.Body) + _, _ = io.Copy(io.Discard, resp.Body) if s.plainHTTP && !s.noPath { // Try again with no path for legacy http. log.Warnw("Plain HTTP got forbidden response, retrying without IPNI path for legacy HTTP") @@ -341,7 +341,7 @@ retry: } fallthrough default: - io.Copy(io.Discard, resp.Body) + _, _ = io.Copy(io.Discard, resp.Body) return fmt.Errorf("non success http fetch response at %s: %d", fetchURL.String(), resp.StatusCode) } } diff --git a/dagsync/option.go b/dagsync/option.go index 70dc044..0a9682f 100644 --- a/dagsync/option.go +++ b/dagsync/option.go @@ -21,9 +21,6 @@ const ( defaultIdleHandlerTTL = time.Hour // defaultSegDepthLimit disables (-1) segmented sync by default. defaultSegDepthLimit = -1 - // Maximum number of in-progress graphsync requests. - defaultGsMaxInRequests = 1024 - defaultGsMaxOutRequests = 1024 // defaultHttpTimeout is time limit for requests made by the HTTP client. defaultHttpTimeout = 10 * time.Second ) @@ -42,16 +39,14 @@ type config struct { lastKnownSync LastKnownSyncFunc maxAsyncSyncs int - hasRcvr bool - rcvrOpts []announce.Option + hasRcvr bool + rcvrOpts []announce.Option + rcvrTopic string adsDepthLimit int64 entriesDepthLimit int64 segDepthLimit int64 - gsMaxInRequests uint64 - gsMaxOutRequests uint64 - strictAdsSelSeq bool httpTimeout time.Duration @@ -66,13 +61,11 @@ type Option func(*config) error // getOpts creates a config and applies Options to it. func getOpts(opts []Option) (config, error) { cfg := config{ - addrTTL: defaultAddrTTL, - httpTimeout: defaultHttpTimeout, - idleHandlerTTL: defaultIdleHandlerTTL, - segDepthLimit: defaultSegDepthLimit, - gsMaxInRequests: defaultGsMaxInRequests, - gsMaxOutRequests: defaultGsMaxOutRequests, - strictAdsSelSeq: true, + addrTTL: defaultAddrTTL, + httpTimeout: defaultHttpTimeout, + idleHandlerTTL: defaultIdleHandlerTTL, + segDepthLimit: defaultSegDepthLimit, + strictAdsSelSeq: true, } for i, opt := range opts { @@ -187,10 +180,11 @@ func SegmentDepthLimit(depth int64) Option { } // RecvAnnounce enables an announcement message receiver. -func RecvAnnounce(opts ...announce.Option) Option { +func RecvAnnounce(topic string, opts ...announce.Option) Option { return func(c *config) error { c.hasRcvr = true c.rcvrOpts = opts + c.rcvrTopic = topic return nil } } @@ -210,16 +204,6 @@ func MaxAsyncConcurrency(n int) Option { } } -// WithMaxGraphsyncRequests sets the maximum number of in-progress inbound and -// outbound graphsync requests. -func WithMaxGraphsyncRequests(maxIn, maxOut uint64) Option { - return func(c *config) error { - c.gsMaxInRequests = maxIn - c.gsMaxOutRequests = maxOut - return nil - } -} - // WithLastKnownSync sets a function that returns the last known sync, when it // is not already known to dagsync. This will generally be some CID that is // known to have already been seen, so that there is no need to fetch portions diff --git a/dagsync/subscriber.go b/dagsync/subscriber.go index 7bf3914..8c5db3b 100644 --- a/dagsync/subscriber.go +++ b/dagsync/subscriber.go @@ -4,15 +4,12 @@ import ( "context" "errors" "fmt" - "strings" "sync" "sync/atomic" "time" "github.com/gammazero/channelqueue" "github.com/ipfs/go-cid" - "github.com/ipfs/go-datastore" - "github.com/ipfs/go-datastore/namespace" logging "github.com/ipfs/go-log/v2" "github.com/ipld/go-ipld-prime" cidlink "github.com/ipld/go-ipld-prime/linking/cid" @@ -20,7 +17,6 @@ import ( "github.com/ipld/go-ipld-prime/traversal/selector" "github.com/ipld/go-ipld-prime/traversal/selector/builder" "github.com/ipni/go-libipni/announce" - "github.com/ipni/go-libipni/dagsync/dtsync" "github.com/ipni/go-libipni/dagsync/ipnisync" "github.com/ipni/go-libipni/mautil" "github.com/libp2p/go-libp2p/core/host" @@ -39,11 +35,17 @@ const ( // BlockHookFunc is the signature of a function that is called when a received. type BlockHookFunc func(peer.ID, cid.Cid, SegmentSyncActions) -// Subscriber creates a single pubsub subscriber that receives messages from a -// gossip pubsub topic, and creates a stateful message handler for each message -// source peer. An optional externally-defined AllowPeerFunc determines whether -// to allow or deny messages from specific peers. +// Subscriber reads chains of advertisements from index-providers (publishers) +// and keeps track of the latest advertisement read from each publisher. +// Advertisements are read when explicitly requested, or in response to +// announcement messages if an announcement receiver is configured. // +// An announcement receiver can receive announcements that are broadcast over +// libp2p gossip pubsub, and sent directly over HTTP. A receiver can be given +// an optional externally-defined function to determines whether to allow or +// deny messages from specific peers. +// +// A stateful message handler is maintained for each advertisement source peer. // Messages from separate peers are handled concurrently, and multiple messages // from the same peer are handled serially. If a handler is busy handling a // message, and more messages arrive from the same peer, then the last message @@ -80,7 +82,6 @@ type Subscriber struct { watchDone chan struct{} asyncWG sync.WaitGroup - dtSync *dtsync.Sync ipniSync *ipnisync.Sync // A separate peerstore is used to store HTTP addresses. This is necessary @@ -101,8 +102,7 @@ type Subscriber struct { adsDepthLimit selector.RecursionLimit segDepthLimit int64 - receiver *announce.Receiver - topicName string + receiver *announce.Receiver // Track explicit Sync calls in progress and allow them to complete before // closing subscriber. @@ -161,8 +161,8 @@ type handler struct { expires time.Time } -// wrapBlockHook wraps a possibly nil block hook func to allow a for -// dispatching to a blockhook func that is scoped within a .Sync call. +// wrapBlockHook wraps a possibly nil block hook func to allow dispatching to a +// blockhook func that is scoped within a .Sync call. func wrapBlockHook() (*sync.RWMutex, map[peer.ID]func(peer.ID, cid.Cid), func(peer.ID, cid.Cid)) { var scopedBlockHookMutex sync.RWMutex scopedBlockHook := make(map[peer.ID]func(peer.ID, cid.Cid)) @@ -178,7 +178,7 @@ func wrapBlockHook() (*sync.RWMutex, map[peer.ID]func(peer.ID, cid.Cid), func(pe // NewSubscriber creates a new Subscriber that processes pubsub messages and // syncs dags advertised using the specified selector. -func NewSubscriber(host host.Host, ds datastore.Batching, lsys ipld.LinkSystem, topic string, options ...Option) (*Subscriber, error) { +func NewSubscriber(host host.Host, lsys ipld.LinkSystem, options ...Option) (*Subscriber, error) { opts, err := getOpts(options) if err != nil { return nil, err @@ -186,12 +186,6 @@ func NewSubscriber(host host.Host, ds datastore.Batching, lsys ipld.LinkSystem, scopedBlockHookMutex, scopedBlockHook, blockHook := wrapBlockHook() - dtds := namespace.Wrap(ds, datastore.NewKey("data-transfer-v2")) - dtSync, err := dtsync.NewSync(host, dtds, lsys, blockHook, opts.gsMaxInRequests, opts.gsMaxOutRequests) - if err != nil { - return nil, err - } - httpPeerstore, err := pstoremem.NewPeerstore() if err != nil { return nil, err @@ -217,7 +211,6 @@ func NewSubscriber(host host.Host, ds datastore.Batching, lsys ipld.LinkSystem, addEventChan: make(chan chan<- SyncFinished), rmEventChan: make(chan chan<- SyncFinished), - dtSync: dtSync, ipniSync: ipniSync, httpPeerstore: httpPeerstore, @@ -232,7 +225,6 @@ func NewSubscriber(host host.Host, ds datastore.Batching, lsys ipld.LinkSystem, adsDepthLimit: recursionLimit(opts.adsDepthLimit), segDepthLimit: opts.segDepthLimit, - topicName: topic, selectorOne: ssb.ExploreRecursive(selector.RecursionLimitDepth(0), all).Node(), selectorAll: ssb.ExploreRecursive(selector.RecursionLimitNone(), all).Node(), @@ -254,7 +246,7 @@ func NewSubscriber(host host.Host, ds datastore.Batching, lsys ipld.LinkSystem, if opts.maxAsyncSyncs > 0 { s.syncSem = make(chan struct{}, opts.maxAsyncSyncs) } - s.receiver, err = announce.NewReceiver(host, topic, opts.rcvrOpts...) + s.receiver, err = announce.NewReceiver(host, opts.rcvrTopic, opts.rcvrOpts...) if err != nil { return nil, fmt.Errorf("failed to create announcement receiver: %w", err) } @@ -320,11 +312,12 @@ func (s *Subscriber) doClose() error { // Wait for explicit Syncs calls to finish. s.expSyncWG.Wait() + var err error if s.receiver != nil { // Close receiver and wait for watch to exit. - err := s.receiver.Close() + err = s.receiver.Close() if err != nil { - log.Errorw("error closing receiver", "err", err) + err = fmt.Errorf("error closing receiver: %w", err) } <-s.watchDone } @@ -332,8 +325,6 @@ func (s *Subscriber) doClose() error { // Wait for any syncs to complete. s.asyncWG.Wait() - err := s.dtSync.Close() - // Stop the distribution goroutine. close(s.inEvents) @@ -486,8 +477,7 @@ func (s *Subscriber) SyncAdChain(ctx context.Context, peerInfo peer.AddrInfo, op segdl = opts.segDepthLimit } - // Check for an existing handler for the specified peer (publisher). If - // none, create one if allowed. + // Get existing or create new handler for the specified peer (publisher). hnd := s.getOrCreateHandler(peerInfo.ID) sel := ExploreRecursiveWithStopNode(depthLimit, s.adsSelectorSeq, stopLnk) @@ -571,8 +561,7 @@ func (s *Subscriber) syncEntries(ctx context.Context, peerInfo peer.AddrInfo, en log.Debugw("Start entries sync", "peer", peerInfo.ID, "cid", entCid) - // Check for an existing handler for the specified peer (publisher). If - // none, create one if allowed. + // Get existing or create new handler for the specified peer (publisher). hnd := s.getOrCreateHandler(peerInfo.ID) _, err = hnd.handle(ctx, entCid, sel, syncer, bh, segdl, cid.Undef) @@ -636,7 +625,8 @@ func (s *Subscriber) distributeEvents() { } } -// getOrCreateHandler creates a handler for a specific peer +// getOrCreateHandler returns an existing handler or creates a new one for the +// specified peer (publisher). func (s *Subscriber) getOrCreateHandler(peerID peer.ID) *handler { expires := time.Now().Add(s.idleHandlerTTL) @@ -771,7 +761,7 @@ func delNotPresent(peerStore peerstore.Peerstore, peerID peer.ID, addrs []multia func (s *Subscriber) makeSyncer(peerInfo peer.AddrInfo, doUpdate bool) (Syncer, func(), error) { // Check for an HTTP address in peerAddrs, or if not given, in the http - // peerstore. This gives a preference to use ipnisync over dtsync. + // peerstore. var httpAddrs []multiaddr.Multiaddr if len(peerInfo.Addrs) == 0 { httpAddrs = s.httpPeerstore.Addrs(peerInfo.ID) @@ -824,9 +814,7 @@ func (s *Subscriber) makeSyncer(peerInfo peer.AddrInfo, doUpdate bool) (Syncer, syncer, err := s.ipniSync.NewSyncer(peerInfo) if err != nil { if errors.Is(err, ipnisync.ErrNoHTTPServer) { - log.Warnw("Using data-transfer sync", "peer", peerInfo.ID, "reason", err.Error()) - // Publisher is libp2p without HTTP, so use the dtSync. - return s.dtSync.NewSyncer(peerInfo.ID, s.topicName), update, nil + err = fmt.Errorf("data-transfer sync is not supported: %w", err) } return nil, nil, fmt.Errorf("cannot create ipni-sync handler: %w", err) } @@ -873,12 +861,6 @@ func (h *handler) asyncSyncAdChain(ctx context.Context) { h.subscriber.receiver.UncacheCid(nextCid) } log.Errorw("Cannot process message", "err", err, "peer", h.peerID) - if strings.Contains(err.Error(), "response rejected") { - // A "response rejected" error happens when the indexer does not - // allow a provider. This is not an error with provider, so do not - // send an error event. - return - } h.subscriber.inEvents <- SyncFinished{ Cid: nextCid, PeerID: h.peerID, diff --git a/dagsync/subscriber_test.go b/dagsync/subscriber_test.go index 28db72c..6a01d7d 100644 --- a/dagsync/subscriber_test.go +++ b/dagsync/subscriber_test.go @@ -21,7 +21,6 @@ import ( "github.com/ipni/go-libipni/announce" "github.com/ipni/go-libipni/announce/p2psender" "github.com/ipni/go-libipni/dagsync" - "github.com/ipni/go-libipni/dagsync/dtsync" "github.com/ipni/go-libipni/dagsync/ipnisync" "github.com/ipni/go-libipni/dagsync/test" "github.com/libp2p/go-libp2p" @@ -65,7 +64,7 @@ func TestScopedBlockHook(t *testing.T) { subLsys := test.MkLinkSystem(subDS) var calledGeneralBlockHookTimes int64 - sub, err := dagsync.NewSubscriber(subHost, subDS, subLsys, testTopic, + sub, err := dagsync.NewSubscriber(subHost, subLsys, dagsync.BlockHook(func(i peer.ID, c cid.Cid, _ dagsync.SegmentSyncActions) { atomic.AddInt64(&calledGeneralBlockHookTimes, 1) }), @@ -129,7 +128,7 @@ func TestSyncedCidsReturned(t *testing.T) { subDS := dssync.MutexWrap(datastore.NewMapDatastore()) subLsys := test.MkLinkSystem(subDS) - sub, err := dagsync.NewSubscriber(subHost, subDS, subLsys, testTopic, dagsync.StrictAdsSelector(false)) + sub, err := dagsync.NewSubscriber(subHost, subLsys, dagsync.StrictAdsSelector(false)) require.NoError(t, err) onFinished, cancel := sub.OnSyncFinished() @@ -192,7 +191,7 @@ func TestConcurrentSync(t *testing.T) { subLsys := test.MkLinkSystem(subDS) var calledTimes int64 - sub, err := dagsync.NewSubscriber(subHost, subDS, subLsys, testTopic, + sub, err := dagsync.NewSubscriber(subHost, subLsys, dagsync.BlockHook(func(i peer.ID, c cid.Cid, _ dagsync.SegmentSyncActions) { atomic.AddInt64(&calledTimes, 1) }), @@ -419,8 +418,8 @@ func TestRoundTrip(t *testing.T) { t.Log("block hook got", c, "from", p) } - sub, err := dagsync.NewSubscriber(dstHost, dstStore, dstLnkS, testTopic, - dagsync.RecvAnnounce(announce.WithTopic(topics[2])), + sub, err := dagsync.NewSubscriber(dstHost, dstLnkS, + dagsync.RecvAnnounce("", announce.WithTopic(topics[2])), dagsync.BlockHook(blockHook), dagsync.StrictAdsSelector(false), ) @@ -624,8 +623,8 @@ func TestMaxAsyncSyncs(t *testing.T) { bhMutex.Unlock() } - sub, err := dagsync.NewSubscriber(dstHost, dstStore, dstLnkS, testTopic, - dagsync.RecvAnnounce(), + sub, err := dagsync.NewSubscriber(dstHost, dstLnkS, + dagsync.RecvAnnounce(testTopic), dagsync.BlockHook(blockHook), dagsync.StrictAdsSelector(false), // If this value is > 1, then test must fail. @@ -718,8 +717,8 @@ func TestMaxAsyncSyncs(t *testing.T) { dstLnkS, blocked = test.MkBlockedLinkSystem(dstStore) blocksSeenByHook = make(map[cid.Cid]struct{}) - sub, err = dagsync.NewSubscriber(dstHost, dstStore, dstLnkS, testTopic, - dagsync.RecvAnnounce(), + sub, err = dagsync.NewSubscriber(dstHost, dstLnkS, + dagsync.RecvAnnounce(testTopic), dagsync.BlockHook(blockHook), dagsync.StrictAdsSelector(false), dagsync.MaxAsyncConcurrency(2), @@ -779,7 +778,7 @@ func TestCloseSubscriber(t *testing.T) { lsys := test.MkLinkSystem(st) - sub, err := dagsync.NewSubscriber(sh, st, lsys, testTopic, dagsync.StrictAdsSelector(false)) + sub, err := dagsync.NewSubscriber(sh, lsys, dagsync.StrictAdsSelector(false)) require.NoError(t, err) watcher, cncl := sub.OnSyncFinished() @@ -850,7 +849,6 @@ func TestIdleHandlerCleaner(t *testing.T) { type dagsyncPubSubBuilder struct { IsHttp bool - IsDtSync bool P2PAnnounce bool } @@ -868,7 +866,6 @@ func newHostSystem(t *testing.T) hostSystem { return hostSystem{ privKey: privKey, host: test.MkTestHost(t, libp2p.Identity(privKey)), - ds: ds, lsys: test.MkLinkSystem(ds), } } @@ -886,17 +883,13 @@ func (b dagsyncPubSubBuilder) Build(t *testing.T, topicName string, pubSys hostS if b.IsHttp { pub, err = ipnisync.NewPublisher(pubSys.lsys, pubSys.privKey, ipnisync.WithHeadTopic(topicName), ipnisync.WithHTTPListenAddrs("127.0.0.1:0")) require.NoError(t, err) - } else if b.IsDtSync { - pub, err = dtsync.NewPublisher(pubSys.host, pubSys.ds, pubSys.lsys, topicName) - require.NoError(t, err) - require.NoError(t, test.WaitForP2PPublisher(pub, subSys.host, topicName)) } else { pub, err = ipnisync.NewPublisher(pubSys.lsys, pubSys.privKey, ipnisync.WithStreamHost(pubSys.host), ipnisync.WithHeadTopic(topicName)) require.NoError(t, err) } subOpts = append(subOpts, dagsync.StrictAdsSelector(false)) - sub, err := dagsync.NewSubscriber(subSys.host, subSys.ds, subSys.lsys, topicName, subOpts...) + sub, err := dagsync.NewSubscriber(subSys.host, subSys.lsys, subOpts...) require.NoError(t, err) return pub, sub, senders diff --git a/dagsync/sync_test.go b/dagsync/sync_test.go index f5606f6..f9e21ef 100644 --- a/dagsync/sync_test.go +++ b/dagsync/sync_test.go @@ -14,7 +14,6 @@ import ( "github.com/ipni/go-libipni/announce" "github.com/ipni/go-libipni/announce/p2psender" "github.com/ipni/go-libipni/dagsync" - "github.com/ipni/go-libipni/dagsync/dtsync" "github.com/ipni/go-libipni/dagsync/ipnisync" "github.com/ipni/go-libipni/dagsync/test" "github.com/libp2p/go-libp2p/core/peer" @@ -42,8 +41,8 @@ func TestLatestSyncSuccess(t *testing.T) { require.NoError(t, err) defer pub.Close() - sub, err := dagsync.NewSubscriber(dstHost, dstStore, dstLnkS, testTopic, - dagsync.RecvAnnounce(announce.WithTopic(topics[1])), + sub, err := dagsync.NewSubscriber(dstHost, dstLnkS, + dagsync.RecvAnnounce("", announce.WithTopic(topics[1])), dagsync.StrictAdsSelector(false)) require.NoError(t, err) defer sub.Close() @@ -87,9 +86,9 @@ func TestSyncFn(t *testing.T) { blocksSeenByHook[c] = struct{}{} } - sub, err := dagsync.NewSubscriber(dstHost, dstStore, dstLnkS, testTopic, + sub, err := dagsync.NewSubscriber(dstHost, dstLnkS, dagsync.BlockHook(blockHook), - dagsync.RecvAnnounce(announce.WithTopic(topics[1])), + dagsync.RecvAnnounce("", announce.WithTopic(topics[1])), dagsync.StrictAdsSelector(false)) require.NoError(t, err) defer sub.Close() @@ -198,8 +197,8 @@ func TestPartialSync(t *testing.T) { defer pub.Close() test.MkChain(srcLnkS, true) - sub, err := dagsync.NewSubscriber(dstHost, dstStore, dstLnkS, testTopic, - dagsync.RecvAnnounce(announce.WithTopic(topics[1])), + sub, err := dagsync.NewSubscriber(dstHost, dstLnkS, + dagsync.RecvAnnounce("", announce.WithTopic(topics[1])), dagsync.StrictAdsSelector(false)) require.NoError(t, err) defer sub.Close() @@ -252,8 +251,8 @@ func TestStepByStepSync(t *testing.T) { require.NoError(t, err) defer pub.Close() - sub, err := dagsync.NewSubscriber(dstHost, dstStore, dstLnkS, testTopic, - dagsync.RecvAnnounce(announce.WithTopic(topics[1])), + sub, err := dagsync.NewSubscriber(dstHost, dstLnkS, + dagsync.RecvAnnounce("", announce.WithTopic(topics[1])), dagsync.StrictAdsSelector(false)) require.NoError(t, err) defer sub.Close() @@ -292,8 +291,8 @@ func TestLatestSyncFailure(t *testing.T) { t.Log("source host:", srcHost.ID()) t.Log("targer host:", dstHost.ID()) - sub, err := dagsync.NewSubscriber(dstHost, dstStore, dstLnkS, testTopic, - dagsync.RecvAnnounce(), dagsync.StrictAdsSelector(false)) + sub, err := dagsync.NewSubscriber(dstHost, dstLnkS, + dagsync.RecvAnnounce(testTopic), dagsync.StrictAdsSelector(false)) require.NoError(t, err) defer sub.Close() @@ -326,9 +325,8 @@ func TestLatestSyncFailure(t *testing.T) { cncl() sub.Close() - dstStore = dssync.MutexWrap(datastore.NewMapDatastore()) - sub2, err := dagsync.NewSubscriber(dstHost, dstStore, dstLnkS, testTopic, - dagsync.RecvAnnounce(), dagsync.StrictAdsSelector(false)) + sub2, err := dagsync.NewSubscriber(dstHost, dstLnkS, + dagsync.RecvAnnounce(testTopic), dagsync.StrictAdsSelector(false)) require.NoError(t, err) defer sub2.Close() @@ -364,66 +362,28 @@ func TestLatestSyncFailure(t *testing.T) { } } -func TestSyncOnAnnounceDataTransfer(t *testing.T) { - dstStore := dssync.MutexWrap(datastore.NewMapDatastore()) - dstHost := test.MkTestHost(t) - dstLnkS := test.MkLinkSystem(dstStore) - - sub, err := dagsync.NewSubscriber(dstHost, dstStore, dstLnkS, testTopic, - dagsync.RecvAnnounce(), dagsync.StrictAdsSelector(false)) - require.NoError(t, err) - defer sub.Close() - - watcher, cncl := sub.OnSyncFinished() - defer cncl() - - srcHost := test.MkTestHost(t) - srcStore := dssync.MutexWrap(datastore.NewMapDatastore()) - srcLnkS := test.MkLinkSystem(srcStore) - pub, err := dtsync.NewPublisher(srcHost, srcStore, srcLnkS, testTopic) - require.NoError(t, err) - defer pub.Close() - require.NoError(t, test.WaitForP2PPublisher(pub, dstHost, testTopic)) - - srcHost.Peerstore().AddAddrs(dstHost.ID(), dstHost.Addrs(), time.Hour) - dstHost.Peerstore().AddAddrs(srcHost.ID(), srcHost.Addrs(), time.Hour) - - // Store the whole chain in source node - chainLnks := test.MkChain(srcLnkS, true) - - t.Log("Testing announce-sync with dtsync publisher at:", pub.Addrs()) - pubInfo := peer.AddrInfo{ - ID: pub.ID(), - Addrs: pub.Addrs(), - } - announceTest(t, pub, sub, dstStore, watcher, pubInfo, chainLnks[2]) - announceTest(t, pub, sub, dstStore, watcher, pubInfo, chainLnks[1]) - announceTest(t, pub, sub, dstStore, watcher, pubInfo, chainLnks[0]) -} - func TestUpdatePeerstoreAddr(t *testing.T) { dstStore := dssync.MutexWrap(datastore.NewMapDatastore()) - dstHost := test.MkTestHost(t) dstLnkS := test.MkLinkSystem(dstStore) - - sub, err := dagsync.NewSubscriber(dstHost, dstStore, dstLnkS, testTopic, - dagsync.RecvAnnounce(), dagsync.StrictAdsSelector(false)) + dstHost := test.MkTestHost(t) + sub, err := dagsync.NewSubscriber(dstHost, dstLnkS, + dagsync.RecvAnnounce(testTopic), dagsync.StrictAdsSelector(false)) require.NoError(t, err) defer sub.Close() watcher, cncl := sub.OnSyncFinished() defer cncl() - srcHost := test.MkTestHost(t) + srcHost, srcPrivKey := test.MkTestHostPK(t) srcStore := dssync.MutexWrap(datastore.NewMapDatastore()) srcLnkS := test.MkLinkSystem(srcStore) - pub, err := dtsync.NewPublisher(srcHost, srcStore, srcLnkS, testTopic) + pub, err := ipnisync.NewPublisher(srcLnkS, srcPrivKey, ipnisync.WithStreamHost(srcHost), ipnisync.WithHeadTopic(testTopic)) require.NoError(t, err) defer pub.Close() - require.NoError(t, test.WaitForP2PPublisher(pub, dstHost, testTopic)) srcHost.Peerstore().AddAddrs(dstHost.ID(), dstHost.Addrs(), time.Hour) dstHost.Peerstore().AddAddrs(srcHost.ID(), srcHost.Addrs(), time.Hour) + require.NoError(t, test.WaitForP2PPublisher(pub, dstHost, testTopic)) // Store the whole chain in source node chainLnks := test.MkChain(srcLnkS, true) @@ -449,8 +409,8 @@ func TestSyncOnAnnounceIPNI(t *testing.T) { dstHost := test.MkTestHost(t) dstLnkS := test.MkLinkSystem(dstStore) - sub, err := dagsync.NewSubscriber(dstHost, dstStore, dstLnkS, testTopic, - dagsync.RecvAnnounce(), dagsync.StrictAdsSelector(false)) + sub, err := dagsync.NewSubscriber(dstHost, dstLnkS, + dagsync.RecvAnnounce(testTopic), dagsync.StrictAdsSelector(false)) require.NoError(t, err) defer sub.Close() @@ -485,8 +445,8 @@ func TestSyncOnAnnounceHTTP(t *testing.T) { dstHost := test.MkTestHost(t) dstLnkS := test.MkLinkSystem(dstStore) - sub, err := dagsync.NewSubscriber(dstHost, dstStore, dstLnkS, testTopic, - dagsync.RecvAnnounce(), dagsync.StrictAdsSelector(false)) + sub, err := dagsync.NewSubscriber(dstHost, dstLnkS, + dagsync.RecvAnnounce(testTopic), dagsync.StrictAdsSelector(false)) require.NoError(t, err) defer sub.Close() @@ -528,7 +488,7 @@ func TestCancelDeadlock(t *testing.T) { require.NoError(t, err) defer pub.Close() - sub, err := dagsync.NewSubscriber(dstHost, dstStore, dstLnkS, testTopic, dagsync.StrictAdsSelector(false)) + sub, err := dagsync.NewSubscriber(dstHost, dstLnkS, dagsync.StrictAdsSelector(false)) require.NoError(t, err) defer sub.Close() diff --git a/dagsync/test/util.go b/dagsync/test/util.go index 154f972..8b50b8f 100644 --- a/dagsync/test/util.go +++ b/dagsync/test/util.go @@ -9,6 +9,7 @@ import ( "io" "net/http" "path" + "strings" "sync" "testing" "time" @@ -19,7 +20,6 @@ import ( "github.com/ipld/go-ipld-prime/fluent" cidlink "github.com/ipld/go-ipld-prime/linking/cid" basicnode "github.com/ipld/go-ipld-prime/node/basic" - "github.com/ipni/go-libipni/dagsync/dtsync/head" "github.com/ipni/go-libipni/dagsync/ipnisync" "github.com/ipni/go-libipni/ingest/schema" "github.com/ipni/go-libipni/maurl" @@ -309,12 +309,29 @@ func WaitForP2PPublisher(publisher TestPublisher, clientHost host.Host, topic st peerStore.AddAddrs(publisher.ID(), publisher.Addrs(), time.Minute+timeout) } + var lsys ipld.LinkSystem + sync := ipnisync.NewSync(lsys, nil, ipnisync.ClientStreamHost(clientHost)) + defer sync.Close() + pubInfo := peer.AddrInfo{ + ID: publisher.ID(), + Addrs: publisher.Addrs(), + } + syncer, err := sync.NewSyncer(pubInfo) + if err != nil { + panic(err) + //return err + } + for ctx.Err() == nil { - _, err := head.QueryRootCid(ctx, clientHost, topic, publisher.ID()) + _, err := syncer.GetHead(ctx) if err == nil { // Publisher ready return nil } + if strings.Contains(err.Error(), "204") { + // Success, but no head CID set yet. + return nil + } time.Sleep(100 * time.Millisecond) } return errors.New("timeout waiting for publilsher") diff --git a/dagsync/tools/main.go b/dagsync/tools/main.go deleted file mode 100644 index 3f39f6d..0000000 --- a/dagsync/tools/main.go +++ /dev/null @@ -1,29 +0,0 @@ -//go:build cbg -// +build cbg - -package main - -import ( - "os" - "path" - - "github.com/ipni/go-libipni/dagsync/dtsync" - cborgen "github.com/whyrusleeping/cbor-gen" -) - -func main() { - wd, err := os.Getwd() - if err != nil { - panic(err) - } - voucher_file := path.Clean(path.Join(wd, "..", "dtsync", "voucher_cbor_gen.go")) - err = cborgen.WriteMapEncodersToFile( - voucher_file, - "dtsync", - dtsync.Voucher{}, - dtsync.VoucherResult{}, - ) - if err != nil { - panic(err) - } -} diff --git a/go.mod b/go.mod index 0ae78f1..8718b46 100644 --- a/go.mod +++ b/go.mod @@ -3,13 +3,11 @@ module github.com/ipni/go-libipni go 1.20 require ( - github.com/filecoin-project/go-data-transfer/v2 v2.0.0-rc7 github.com/gammazero/channelqueue v0.2.1 github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/go-retryablehttp v0.7.4 github.com/ipfs/go-cid v0.4.1 github.com/ipfs/go-datastore v0.6.0 - github.com/ipfs/go-graphsync v0.16.0 github.com/ipfs/go-ipld-format v0.6.0 github.com/ipfs/go-log/v2 v2.5.1 github.com/ipld/go-ipld-prime v0.21.0 @@ -20,37 +18,27 @@ require ( github.com/multiformats/go-multiaddr v0.12.1 github.com/multiformats/go-multicodec v0.9.0 github.com/multiformats/go-multihash v0.2.3 - github.com/multiformats/go-multistream v0.5.0 github.com/multiformats/go-varint v0.0.7 github.com/stretchr/testify v1.8.4 github.com/whyrusleeping/cbor-gen v0.0.0-20230418232409-daab9ece03a0 golang.org/x/crypto v0.17.0 - golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 google.golang.org/protobuf v1.30.0 ) require ( github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/bep/debounce v1.2.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/containerd/cgroups v1.1.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/elastic/gosigar v0.14.2 // indirect - github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2 // indirect - github.com/filecoin-project/go-ds-versioning v0.1.2 // indirect - github.com/filecoin-project/go-statemachine v1.0.2-0.20220322104818-27f8fbb86dfd // indirect - github.com/filecoin-project/go-statestore v0.2.0 // indirect github.com/flynn/noise v1.0.0 // indirect github.com/francoispqt/gojay v1.2.13 // indirect github.com/gammazero/deque v0.2.1 // indirect - github.com/go-logr/logr v1.2.4 // indirect - github.com/go-logr/stdr v1.2.2 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect @@ -58,24 +46,17 @@ require ( github.com/google/gopacket v1.1.19 // indirect github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b // indirect github.com/google/uuid v1.3.0 // indirect + github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f // indirect github.com/gorilla/websocket v1.5.0 // indirect - github.com/hannahhoward/cbor-gen-for v0.0.0-20230214144701-5d17c9d5243c // indirect - github.com/hannahhoward/go-pubsub v0.0.0-20200423002714-8d62886cc36e // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/golang-lru/v2 v2.0.5 // indirect github.com/huin/goupnp v1.3.0 // indirect github.com/ipfs/go-block-format v0.1.2 // indirect - github.com/ipfs/go-ipfs-pq v0.0.3 // indirect github.com/ipfs/go-ipfs-util v0.0.2 // indirect - github.com/ipfs/go-ipld-cbor v0.0.6 // indirect - github.com/ipfs/go-log v1.0.5 // indirect - github.com/ipfs/go-peertaskqueue v0.8.1 // indirect - github.com/ipld/go-codec-dagpb v1.6.0 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect github.com/jbenet/goprocess v0.1.4 // indirect - github.com/jpillora/backoff v1.0.0 // indirect github.com/klauspost/compress v1.17.2 // indirect github.com/klauspost/cpuid/v2 v2.2.5 // indirect github.com/koron/go-ssdp v0.0.4 // indirect @@ -99,9 +80,9 @@ require ( github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect github.com/multiformats/go-multibase v0.2.0 // indirect + github.com/multiformats/go-multistream v0.5.0 // indirect github.com/onsi/ginkgo/v2 v2.13.0 // indirect github.com/opencontainers/runtime-spec v1.1.0 // indirect - github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect @@ -115,14 +96,8 @@ require ( github.com/quic-go/quic-go v0.39.4 // indirect github.com/quic-go/webtransport-go v0.6.0 // indirect github.com/raulk/go-watchdog v1.3.0 // indirect - github.com/russross/blackfriday/v2 v2.0.1 // indirect - github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect github.com/smartystreets/assertions v1.13.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect - github.com/urfave/cli/v2 v2.0.0 // indirect - go.opentelemetry.io/otel v1.13.0 // indirect - go.opentelemetry.io/otel/trace v1.13.0 // indirect - go.uber.org/atomic v1.11.0 // indirect go.uber.org/dig v1.17.1 // indirect go.uber.org/fx v1.20.1 // indirect go.uber.org/mock v0.3.0 // indirect @@ -135,6 +110,7 @@ require ( golang.org/x/sys v0.15.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.14.0 // indirect + golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect lukechampine.com/blake3 v1.2.1 // indirect ) diff --git a/go.sum b/go.sum index 5425a28..8ed9e13 100644 --- a/go.sum +++ b/go.sum @@ -2,29 +2,12 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -33,16 +16,10 @@ github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZx github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bep/debounce v1.2.0 h1:wXds8Kq8qRfwAOpAxHrJDbCXgC5aHSzgQb/0gKsHQqo= -github.com/bep/debounce v1.2.0/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= @@ -53,9 +30,7 @@ github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+ github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 h1:HVTnpeuvF6Owjd5mniCL8DEXo7uYXdQEmOP4FJbV5tg= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -71,20 +46,6 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= github.com/elastic/gosigar v0.14.2 h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/4= github.com/elastic/gosigar v0.14.2/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2 h1:av5fw6wmm58FYMgJeoB/lK9XXrgdugYiTqkdxjTy9k8= -github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2/go.mod h1:pqTiPHobNkOVM5thSRsHYjyQfq7O5QSCMhvuu9JoDlg= -github.com/filecoin-project/go-data-transfer/v2 v2.0.0-rc7 h1:v+zJS5B6pA3ptWZS4t8tbt1Hz9qENnN4nVr1w99aSWc= -github.com/filecoin-project/go-data-transfer/v2 v2.0.0-rc7/go.mod h1:V3Y4KbttaCwyg1gwkP7iai8CbQx4mZUGjd3h9GZWLKE= -github.com/filecoin-project/go-ds-versioning v0.1.2 h1:to4pTadv3IeV1wvgbCbN6Vqd+fu+7tveXgv/rCEZy6w= -github.com/filecoin-project/go-ds-versioning v0.1.2/go.mod h1:C9/l9PnB1+mwPa26BBVpCjG/XQCB0yj/q5CK2J8X1I4= -github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig= -github.com/filecoin-project/go-statemachine v1.0.2-0.20220322104818-27f8fbb86dfd h1:Ykxbz+LvSCUIl2zFaaPGmF8KHXTJu9T/PymgHr7IHjs= -github.com/filecoin-project/go-statemachine v1.0.2-0.20220322104818-27f8fbb86dfd/go.mod h1:jZdXXiHa61n4NmgWFG4w8tnqgvZVHYbJ3yW7+y8bF54= -github.com/filecoin-project/go-statestore v0.1.0/go.mod h1:LFc9hD+fRxPqiHiaqUEZOinUJB4WARkRfNl10O7kTnI= -github.com/filecoin-project/go-statestore v0.2.0 h1:cRRO0aPLrxKQCZ2UOQbzFGn4WDNdofHZoGPjfNaAo5Q= -github.com/filecoin-project/go-statestore v0.2.0/go.mod h1:8sjBYbS35HwPzct7iT4lIXjLlYyPor80aU7t7a/Kspo= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ= github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= @@ -98,15 +59,8 @@ github.com/gammazero/deque v0.2.1 h1:qSdsbG6pgp6nL7A0+K/B7s12mcCY/5l5SIUpMOl+dC0 github.com/gammazero/deque v0.2.1/go.mod h1:LFroj8x4cMYCukHJDbxFCkT+r9AndaJnFMuZDV34tuU= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= -github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0= @@ -115,31 +69,20 @@ github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -150,18 +93,12 @@ github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b h1:RMpPgZTSApbPf7xaVel+QkoGPRLFLrwFO89uDUHEGf0= github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f h1:KMlcu9X58lhTA/KrfX8Bi1LQSO4pzoVjTiL3h4Jk+Zk= github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -169,12 +106,6 @@ github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWm github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= -github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= -github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= -github.com/hannahhoward/cbor-gen-for v0.0.0-20230214144701-5d17c9d5243c h1:iiD+p+U0M6n/FsO6XIZuOgobnNa48FxtyYFfWwLttUQ= -github.com/hannahhoward/cbor-gen-for v0.0.0-20230214144701-5d17c9d5243c/go.mod h1:jvfsLIxk0fY/2BKSQ1xf2406AKA5dwMmKKv0ADcOfN8= -github.com/hannahhoward/go-pubsub v0.0.0-20200423002714-8d62886cc36e h1:3YKHER4nmd7b5qy5t0GWDTwSn4OyRgfAXSmo6VnryBY= -github.com/hannahhoward/go-pubsub v0.0.0-20200423002714-8d62886cc36e/go.mod h1:I8h3MITA53gN9OnWGCgaMa0JWVRdXthWw4M3CPM54OY= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -186,97 +117,39 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-retryablehttp v0.7.4 h1:ZQgVdpTdAL7WpMIwLzCfbalOcSUdkDZnpUv3/+BxzFA= github.com/hashicorp/go-retryablehttp v0.7.4/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru/v2 v2.0.5 h1:wW7h1TG88eUIJ2i69gaE3uNVtEPIagzhGvHgwfx2Vm4= github.com/hashicorp/golang-lru/v2 v2.0.5/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs= -github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA= -github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY= github.com/ipfs/go-block-format v0.1.2 h1:GAjkfhVx1f4YTODS6Esrj1wt2HhrtwTnhEr+DyPUaJo= github.com/ipfs/go-block-format v0.1.2/go.mod h1:mACVcrxarQKstUU3Yf/RdwbC4DzPV6++rO2a3d+a/KE= -github.com/ipfs/go-blockservice v0.5.0 h1:B2mwhhhVQl2ntW2EIpaWPwSCxSuqr5fFA93Ms4bYLEY= -github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= -github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= -github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= -github.com/ipfs/go-cid v0.0.4-0.20191112011718-79e75dffeb10/go.mod h1:/BYOuUoxkE+0f6tGzlzMvycuN+5l35VOR4Bpg2sCmds= github.com/ipfs/go-cid v0.0.6/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I= github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= -github.com/ipfs/go-datastore v0.1.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw= -github.com/ipfs/go-datastore v0.5.0/go.mod h1:9zhEApYMTl17C8YDp7JmU7sQZi2/wqiYh73hakZ90Bk= -github.com/ipfs/go-datastore v0.5.1/go.mod h1:9zhEApYMTl17C8YDp7JmU7sQZi2/wqiYh73hakZ90Bk= github.com/ipfs/go-datastore v0.6.0 h1:JKyz+Gvz1QEZw0LsX1IBn+JFCJQH4SJVFtM4uWU0Myk= github.com/ipfs/go-datastore v0.6.0/go.mod h1:rt5M3nNbSO/8q1t4LNkLyUwRs8HupMeN/8O4Vn9YAT8= github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= -github.com/ipfs/go-graphsync v0.16.0 h1:0BX7whXlV13Y9FZ/jRg+xaGHaGYbtGxGppKD6tncw6k= -github.com/ipfs/go-graphsync v0.16.0/go.mod h1:WfbMW3hhmX5GQEQ+KJxsFzVJVBKgC5szfrYK7Zc7xIM= -github.com/ipfs/go-ipfs-blockstore v1.2.0 h1:n3WTeJ4LdICWs/0VSfjHrlqpPpl6MZ+ySd3j8qz0ykw= -github.com/ipfs/go-ipfs-blocksutil v0.0.1 h1:Eh/H4pc1hsvhzsQoMEP3Bke/aW5P5rVM1IWFJMcGIPQ= -github.com/ipfs/go-ipfs-chunker v0.0.5 h1:ojCf7HV/m+uS2vhUGWcogIIxiO5ubl5O57Q7NapWLY8= -github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= -github.com/ipfs/go-ipfs-ds-help v1.1.0 h1:yLE2w9RAsl31LtfMt91tRZcrx+e61O5mDxFRR994w4Q= -github.com/ipfs/go-ipfs-exchange-interface v0.2.0 h1:8lMSJmKogZYNo2jjhUs0izT+dck05pqUw4mWNW9Pw6Y= -github.com/ipfs/go-ipfs-exchange-offline v0.3.0 h1:c/Dg8GDPzixGd0MC8Jh6mjOwU57uYokgWRFidfvEkuA= -github.com/ipfs/go-ipfs-posinfo v0.0.1 h1:Esoxj+1JgSjX0+ylc0hUmJCOv6V2vFoZiETLR6OtpRs= -github.com/ipfs/go-ipfs-pq v0.0.3 h1:YpoHVJB+jzK15mr/xsWC574tyDLkezVrDNeaalQBsTE= -github.com/ipfs/go-ipfs-pq v0.0.3/go.mod h1:btNw5hsHBpRcSSgZtiNm/SLj5gYIZ18AKtv3kERkRb4= -github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyBCNzQxlJBc= github.com/ipfs/go-ipfs-util v0.0.2 h1:59Sswnk1MFaiq+VcaknX7aYEyGyGDAA73ilhEK2POp8= github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ= -github.com/ipfs/go-ipld-cbor v0.0.3/go.mod h1:wTBtrQZA3SoFKMVkp6cn6HMRteIB1VsmHA0AQFOn7Nc= -github.com/ipfs/go-ipld-cbor v0.0.6 h1:pYuWHyvSpIsOOLw4Jy7NbBkCyzLDcl64Bf/LZW7eBQ0= -github.com/ipfs/go-ipld-cbor v0.0.6/go.mod h1:ssdxxaLJPXH7OjF5V4NSjBbcfh+evoR4ukuru0oPXMA= -github.com/ipfs/go-ipld-format v0.0.1/go.mod h1:kyJtbkDALmFHv3QR6et67i35QzO3S0dCDnkOJhcZkms= -github.com/ipfs/go-ipld-format v0.0.2/go.mod h1:4B6+FM2u9OJ9zCV+kSbgFAZlOrv1Hqbf0INGQgiKf9k= github.com/ipfs/go-ipld-format v0.6.0 h1:VEJlA2kQ3LqFSIm5Vu6eIlSxD/Ze90xtc4Meten1F5U= github.com/ipfs/go-ipld-format v0.6.0/go.mod h1:g4QVMTn3marU3qXchwjpKPKgJv+zF+OlaKMyhJ4LHPg= -github.com/ipfs/go-ipld-legacy v0.1.1 h1:BvD8PEuqwBHLTKqlGFTHSwrwFOMkVESEvwIYwR2cdcc= -github.com/ipfs/go-libipfs v0.6.0 h1:3FuckAJEm+zdHbHbf6lAyk0QUzc45LsFcGw102oBCZM= -github.com/ipfs/go-log v1.0.0/go.mod h1:JO7RzlMK6rA+CIxFMLOuB6Wf5b81GDiKElL7UPSIKjA= -github.com/ipfs/go-log v1.0.1/go.mod h1:HuWlQttfN6FWNHRhlY5yMk/lW7evQC0HHGOxEwMRR8I= -github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8= -github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo= -github.com/ipfs/go-log/v2 v2.0.1/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBWFaa9+0= -github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Axpmri6g= github.com/ipfs/go-log/v2 v2.5.1 h1:1XdUzF7048prq4aBjDQQ4SL5RxftpRGdXhNRwKSAlcY= github.com/ipfs/go-log/v2 v2.5.1/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI= -github.com/ipfs/go-merkledag v0.10.0 h1:IUQhj/kzTZfam4e+LnaEpoiZ9vZF6ldimVlby+6OXL4= -github.com/ipfs/go-metrics-interface v0.0.1 h1:j+cpbjYvu4R8zbleSs36gvB7jR+wsL2fGD6n0jO4kdg= -github.com/ipfs/go-peertaskqueue v0.8.1 h1:YhxAs1+wxb5jk7RvS0LHdyiILpNmRIRnZVztekOF0pg= -github.com/ipfs/go-peertaskqueue v0.8.1/go.mod h1:Oxxd3eaK279FxeydSPPVGHzbwVeHjatZ2GA8XD+KbPU= -github.com/ipfs/go-unixfs v0.4.4 h1:D/dLBOJgny5ZLIur2vIXVQVW0EyDHdOMBDEhgHrt6rY= -github.com/ipfs/go-unixfsnode v1.7.4 h1:iLvKyAVKUYOIAW2t4kDYqsT7VLGj31eXJE2aeqGfbwA= -github.com/ipfs/go-verifcid v0.0.2 h1:XPnUv0XmdH+ZIhLGKg6U2vaPaRDXb9urMyNVCE7uvTs= -github.com/ipld/go-codec-dagpb v1.6.0 h1:9nYazfyu9B1p3NAgfVdpRco3Fs2nFC72DqVsMj6rOcc= -github.com/ipld/go-codec-dagpb v1.6.0/go.mod h1:ANzFhfP2uMJxRBr8CE+WQWs5UsNa0pYtmKZ+agnUw9s= github.com/ipld/go-ipld-prime v0.21.0 h1:n4JmcpOlPDIxBcY037SVfpd1G+Sj1nKZah0m6QH9C2E= github.com/ipld/go-ipld-prime v0.21.0/go.mod h1:3RLqy//ERg/y5oShXXdx5YIp50cFGOanyMctpPjsvxQ= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= -github.com/jbenet/go-random v0.0.0-20190219211222-123a90aedc0c h1:uUx61FiAa1GI6ZmVd2wf2vULeQZIKG66eybjNXKYCz4= github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= -github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY= -github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o= github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= -github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= @@ -287,7 +160,6 @@ github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZY github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0= github.com/koron/go-ssdp v0.0.4/go.mod h1:oDXq+E5IL5q0U8uSBcoAXzTzInwy5lEgC91HoKtbmZk= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -338,9 +210,7 @@ github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b/go.mod h1:lxPUiZwKo github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdnNMiD9ZejrlswWrCpBEZgWOiTrc= github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4SxOuR/czcZ/E2RSJ3sfHs8FpHhQ5CWMf9s= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= -github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= -github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -364,16 +234,12 @@ github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2 github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk= github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= -github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc= github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk= github.com/multiformats/go-multicodec v0.9.0 h1:pb/dlPnzee/Sxv/j4PmkDRxCOi3hXTz3IbPKOXWJkmg= github.com/multiformats/go-multicodec v0.9.0/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI16i14xuaojr/H7Ai54k= -github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= -github.com/multiformats/go-multihash v0.0.9/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= -github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U= github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM= @@ -391,9 +257,6 @@ github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg= github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= -github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= @@ -402,15 +265,12 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/polydawn/refmt v0.0.0-20190221155625-df39d6c2d992/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= -github.com/polydawn/refmt v0.0.0-20190809202753-05966cbd336a/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= github.com/polydawn/refmt v0.89.0 h1:ADJTApkvkeBZsN0tBTx8QjpD9JkmxbKp0cxfr9qszm4= github.com/polydawn/refmt v0.89.0/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw= github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= @@ -429,12 +289,9 @@ github.com/quic-go/webtransport-go v0.6.0 h1:CvNsKqc4W2HljHJnoT+rMmbRJybShZ0YPFD github.com/quic-go/webtransport-go v0.6.0/go.mod h1:9KjU4AEBqEQidGHNDkZrb8CAa1abRaosM2yGOyiikEc= github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk= github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= @@ -456,18 +313,13 @@ github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= github.com/smartystreets/assertions v1.13.0 h1:Dx1kYM01xsSqKPno3aqLnrwac2LetPvN23diwyr69Qs= github.com/smartystreets/assertions v1.13.0/go.mod h1:wDmR7qL282YbGsPy6H/yAsesrxfxaaSlJazyFLYVFx8= -github.com/smartystreets/goconvey v0.0.0-20190222223459-a17d461953aa/go.mod h1:2RVY1rIf+2J2o/IM9+vPq9RzmHDSseB7FoXiSNIUsoU= -github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg= github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM= github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= @@ -478,7 +330,6 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= @@ -486,41 +337,19 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli/v2 v2.0.0 h1:+HU9SCbu8GnEUFtIBfuUNXN39ofWViIEJIp6SURMpCg= -github.com/urfave/cli/v2 v2.0.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= github.com/warpfork/go-testmark v0.12.1 h1:rMgCpJfwy1sJ50x0M0NgyphxYYPMOODIJHhsXyEHU0s= -github.com/warpfork/go-wish v0.0.0-20180510122957-5ad1f5abf436/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= -github.com/warpfork/go-wish v0.0.0-20190328234359-8b3e70f8e830/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ= github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= -github.com/whyrusleeping/cbor-gen v0.0.0-20191216205031-b047b6acb3c0/go.mod h1:xdlJQaiqipF0HW+Mzpg7XRM3fWbGvfgFlcppuvlkIvY= -github.com/whyrusleeping/cbor-gen v0.0.0-20200123233031-1cdf64d27158/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI= -github.com/whyrusleeping/cbor-gen v0.0.0-20200710004633-5379fc63235d/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= -github.com/whyrusleeping/cbor-gen v0.0.0-20200826160007-0b9f6c5fb163/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20230418232409-daab9ece03a0 h1:XYEgH2nJgsrcrj32p+SAbx6T3s/6QknOXezXtz7kzbg= github.com/whyrusleeping/cbor-gen v0.0.0-20230418232409-daab9ece03a0/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= -github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opentelemetry.io/otel v1.13.0 h1:1ZAKnNQKwBBxFtww/GwxNUyTf0AxkZzrukO8MeXqe4Y= -go.opentelemetry.io/otel v1.13.0/go.mod h1:FH3RtdZCzRkJYFTCsAKDy9l/XYjMdNv6QrkFFB8DvVg= -go.opentelemetry.io/otel/sdk v1.2.0 h1:wKN260u4DesJYhyjxDa7LRFkuhH7ncEVKU37LWcyNIo= -go.opentelemetry.io/otel/trace v1.13.0 h1:CBgRZ6ntv+Amuj1jDsMhZtlAPT6gbyIRdaIzFhfBSdY= -go.opentelemetry.io/otel/trace v1.13.0/go.mod h1:muCvmmO9KKpvuXSf3KKAXXB2ygNYHQ+ZfI5X08d3tds= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= -go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/dig v1.17.1 h1:Tga8Lz8PcYNsWsyHMZ1Vm0OQOUaJNDyvPImgbAu9YSc= go.uber.org/dig v1.17.1/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE= go.uber.org/fx v1.20.1 h1:zVwVQGS8zYvhh9Xxcu4w1M6ESyeMzebzj2NbSayZ4Mk= @@ -529,28 +358,17 @@ go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpK go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo= go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= -go4.org v0.0.0-20200411211856-f5505b9728dd h1:BNJlw5kRTzdmyfh5U8F93HA2OwkP7ZGwA51eJ/0wKOU= -go4.org v0.0.0-20200411211856-f5505b9728dd/go.mod h1:CIiUVy99QCPfoE13bO4EZaz5GZMZXMSBGhxRdsvzbkg= golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -559,32 +377,13 @@ golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -601,14 +400,7 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -620,9 +412,6 @@ golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAG golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -639,22 +428,10 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -667,17 +444,13 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -685,29 +458,9 @@ golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= @@ -722,81 +475,41 @@ golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNq google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= -gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=