go-waku: RequestAllHistoricMessages (#2258)

* feat: update wakuv2 store

* check online using waku version for now

* fix peerId and from/to multiplier

* fix: lint

* fix: handle waku2 cursors

* fix: code review

* fix: code review 2

* update go-waku version

* update vendor folder
This commit is contained in:
RichΛrd 2021-07-21 15:02:50 -04:00 committed by GitHub
parent 6c2e9652d0
commit bfdc000bbc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
48 changed files with 1131 additions and 1996 deletions

View File

@ -5,8 +5,6 @@ import (
"errors" "errors"
"time" "time"
"github.com/status-im/go-waku/waku/v2/protocol/store"
"github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/waku" "github.com/status-im/status-go/waku"
wakucommon "github.com/status-im/status-go/waku/common" wakucommon "github.com/status-im/status-go/waku/common"
@ -36,6 +34,10 @@ func (w *gethWakuWrapper) PublicWakuAPI() types.PublicWakuAPI {
return NewGethPublicWakuAPIWrapper(waku.NewPublicWakuAPI(w.waku)) return NewGethPublicWakuAPIWrapper(waku.NewPublicWakuAPI(w.waku))
} }
func (w *gethWakuWrapper) Version() uint {
return 1
}
// MinPow returns the PoW value required by this node. // MinPow returns the PoW value required by this node.
func (w *gethWakuWrapper) MinPow() float64 { func (w *gethWakuWrapper) MinPow() float64 {
return w.waku.MinPow() return w.waku.MinPow()
@ -183,8 +185,8 @@ func (w *gethWakuWrapper) RequestHistoricMessagesWithTimeout(peerID []byte, enve
return w.waku.RequestHistoricMessagesWithTimeout(peerID, envelope.Unwrap().(*wakucommon.Envelope), timeout) return w.waku.RequestHistoricMessagesWithTimeout(peerID, envelope.Unwrap().(*wakucommon.Envelope), timeout)
} }
func (w *gethWakuWrapper) RequestStoreMessages(topics []types.TopicType, from uint64, to uint64, options []store.HistoryRequestOption) error { func (w *gethWakuWrapper) RequestStoreMessages(peerID []byte, r types.MessagesRequest) (*types.StoreRequestCursor, error) {
return errors.New("Not implemented") return nil, errors.New("not implemented")
} }
type wakuFilterWrapper struct { type wakuFilterWrapper struct {

View File

@ -5,6 +5,8 @@ import (
"errors" "errors"
"time" "time"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/status-im/go-waku/waku/v2/protocol/pb"
"github.com/status-im/go-waku/waku/v2/protocol/store" "github.com/status-im/go-waku/waku/v2/protocol/store"
"github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/eth-node/types"
@ -36,6 +38,10 @@ func (w *gethWakuV2Wrapper) PublicWakuAPI() types.PublicWakuAPI {
return NewGethPublicWakuV2APIWrapper(wakuv2.NewPublicWakuAPI(w.waku)) return NewGethPublicWakuV2APIWrapper(wakuv2.NewPublicWakuAPI(w.waku))
} }
func (w *gethWakuV2Wrapper) Version() uint {
return 2
}
// MinPow returns the PoW value required by this node. // MinPow returns the PoW value required by this node.
func (w *gethWakuV2Wrapper) MinPow() float64 { func (w *gethWakuV2Wrapper) MinPow() float64 {
return 0 return 0
@ -164,6 +170,47 @@ func (w *gethWakuV2Wrapper) SendMessagesRequest(peerID []byte, r types.MessagesR
return errors.New("DEPRECATED") return errors.New("DEPRECATED")
} }
func (w *gethWakuV2Wrapper) RequestStoreMessages(peerID []byte, r types.MessagesRequest) (*types.StoreRequestCursor, error) {
var options []store.HistoryRequestOption
peer, err := peer.Decode(string(peerID))
if err != nil {
return nil, err
}
options = []store.HistoryRequestOption{
store.WithPeer(peer),
store.WithPaging(false, uint64(r.Limit)),
}
if r.Cursor != nil {
options = append(options, store.WithCursor(&pb.Index{
Digest: r.StoreCursor.Digest,
ReceiverTime: r.StoreCursor.ReceiverTime,
SenderTime: r.StoreCursor.SenderTime,
}))
}
var topics []types.TopicType
for _, topic := range r.Topics {
topics = append(topics, types.BytesToTopic(topic))
}
pbCursor, err := w.waku.Query(topics, uint64(r.From), uint64(r.To), options)
if err != nil {
return nil, err
}
if pbCursor != nil {
return &types.StoreRequestCursor{
Digest: pbCursor.Digest,
ReceiverTime: pbCursor.ReceiverTime,
SenderTime: pbCursor.SenderTime,
}, nil
}
return nil, nil
}
// RequestHistoricMessages sends a message with p2pRequestCode to a specific peer, // RequestHistoricMessages sends a message with p2pRequestCode to a specific peer,
// which is known to implement MailServer interface, and is supposed to process this // which is known to implement MailServer interface, and is supposed to process this
// request and respond with a number of peer-to-peer messages (possibly expired), // request and respond with a number of peer-to-peer messages (possibly expired),
@ -173,10 +220,6 @@ func (w *gethWakuV2Wrapper) RequestHistoricMessagesWithTimeout(peerID []byte, en
return errors.New("DEPRECATED") return errors.New("DEPRECATED")
} }
func (w *gethWakuV2Wrapper) RequestStoreMessages(topics []types.TopicType, from uint64, to uint64, options []store.HistoryRequestOption) error {
return w.waku.Query(topics, from, to, options)
}
type wakuV2FilterWrapper struct { type wakuV2FilterWrapper struct {
filter *wakucommon.Filter filter *wakucommon.Filter
id string id string

View File

@ -24,6 +24,8 @@ type MessagesRequest struct {
Limit uint32 `json:"limit"` Limit uint32 `json:"limit"`
// Cursor is used as starting point for paginated requests. // Cursor is used as starting point for paginated requests.
Cursor []byte `json:"cursor"` Cursor []byte `json:"cursor"`
// StoreCursor is used as starting point for WAKUV2 paginatedRequests
StoreCursor *StoreRequestCursor `json:"storeCursor"`
// Bloom is a filter to match requested messages. // Bloom is a filter to match requested messages.
Bloom []byte `json:"bloom"` Bloom []byte `json:"bloom"`
@ -32,6 +34,12 @@ type MessagesRequest struct {
Topics [][]byte `json:"topics"` Topics [][]byte `json:"topics"`
} }
type StoreRequestCursor struct {
Digest []byte `json:"digest"`
ReceiverTime float64 `json:"receiverTime"`
SenderTime float64 `json:"senderTime"`
}
// SetDefaults sets the From and To defaults // SetDefaults sets the From and To defaults
func (r *MessagesRequest) SetDefaults(now time.Time) { func (r *MessagesRequest) SetDefaults(now time.Time) {
// set From and To defaults // set From and To defaults

View File

@ -3,8 +3,6 @@ package types
import ( import (
"crypto/ecdsa" "crypto/ecdsa"
"time" "time"
"github.com/status-im/go-waku/waku/v2/protocol/store"
) )
// Whisper represents a dark communication interface through the Ethereum // Whisper represents a dark communication interface through the Ethereum
@ -12,6 +10,9 @@ import (
type Waku interface { type Waku interface {
PublicWakuAPI() PublicWakuAPI PublicWakuAPI() PublicWakuAPI
// Waku protocol version
Version() uint
// MinPow returns the PoW value required by this node. // MinPow returns the PoW value required by this node.
MinPow() float64 MinPow() float64
// BloomFilter returns the aggregated bloom filter for all the topics of interest. // BloomFilter returns the aggregated bloom filter for all the topics of interest.
@ -56,5 +57,5 @@ type Waku interface {
SendMessagesRequest(peerID []byte, request MessagesRequest) error SendMessagesRequest(peerID []byte, request MessagesRequest) error
// RequestStoreMessages uses the WAKU2-STORE protocol to request historic messages // RequestStoreMessages uses the WAKU2-STORE protocol to request historic messages
RequestStoreMessages(topics []TopicType, from uint64, to uint64, options []store.HistoryRequestOption) error RequestStoreMessages(peerID []byte, request MessagesRequest) (*StoreRequestCursor, error)
} }

9
go.mod
View File

@ -18,8 +18,7 @@ require (
github.com/ethereum/go-ethereum v1.10.4 github.com/ethereum/go-ethereum v1.10.4
github.com/go-playground/universal-translator v0.17.0 // indirect github.com/go-playground/universal-translator v0.17.0 // indirect
github.com/golang-migrate/migrate/v4 v4.8.0 // indirect github.com/golang-migrate/migrate/v4 v4.8.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/mock v1.4.4
github.com/golang/mock v1.4.1
github.com/golang/protobuf v1.5.2 github.com/golang/protobuf v1.5.2
github.com/google/uuid v1.2.0 github.com/google/uuid v1.2.0
github.com/ipfs/go-log v1.0.4 github.com/ipfs/go-log v1.0.4
@ -42,13 +41,13 @@ require (
github.com/oliamb/cutter v0.2.2 github.com/oliamb/cutter v0.2.2
github.com/pborman/uuid v1.2.0 github.com/pborman/uuid v1.2.0
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.9.0 github.com/prometheus/client_golang v1.11.0
github.com/russolsen/ohyeah v0.0.0-20160324131710-f4938c005315 // indirect github.com/russolsen/ohyeah v0.0.0-20160324131710-f4938c005315 // indirect
github.com/russolsen/same v0.0.0-20160222130632-f089df61f51d // indirect github.com/russolsen/same v0.0.0-20160222130632-f089df61f51d // indirect
github.com/russolsen/transit v0.0.0-20180705123435-0794b4c4505a github.com/russolsen/transit v0.0.0-20180705123435-0794b4c4505a
github.com/status-im/doubleratchet v3.0.0+incompatible github.com/status-im/doubleratchet v3.0.0+incompatible
github.com/status-im/go-waku v0.0.0-20210624095504-4133155590da github.com/status-im/go-waku v0.0.0-20210711181138-a2ff7f3df962
github.com/status-im/go-wakurelay-pubsub v0.4.2 github.com/status-im/go-wakurelay-pubsub v0.4.3-0.20210711180556-9afd35dadd3f
github.com/status-im/markdown v0.0.0-20201022101546-c0cbdd5763bf github.com/status-im/markdown v0.0.0-20201022101546-c0cbdd5763bf
github.com/status-im/migrate/v4 v4.6.2-status.2 github.com/status-im/migrate/v4 v4.6.2-status.2
github.com/status-im/rendezvous v1.3.2 github.com/status-im/rendezvous v1.3.2

166
go.sum
View File

@ -9,16 +9,34 @@ cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTj
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= 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.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw= cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= 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/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/bigtable v1.2.0/go.mod h1:JcVAOl45lrTmQfLj7T6TxyMzIN/3FGGcFm+2xVAli2o= cloud.google.com/go/bigtable v1.2.0/go.mod h1:JcVAOl45lrTmQfLj7T6TxyMzIN/3FGGcFm+2xVAli2o=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= 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/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= 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= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE= collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE=
contrib.go.opencensus.io/exporter/prometheus v0.3.0/go.mod h1:rpCPVQKhiyH8oomWgm34ZmgIdZa8OVYO5WAIygPbBBE=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
@ -263,10 +281,12 @@ github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1T
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= 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-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo= github.com/go-kit/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo=
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4=
@ -308,13 +328,19 @@ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4er
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 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.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.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1 h1:ocYkMQY5RrXTYgXl7ICpV0IXwlEQGwKIsery4gyXa1U= github.com/golang/mock v1.4.1 h1:ocYkMQY5RrXTYgXl7ICpV0IXwlEQGwKIsery4gyXa1U=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
github.com/golang/protobuf v1.3.1/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.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.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
@ -340,6 +366,8 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
@ -350,12 +378,18 @@ github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6
github.com/google/gopacket v1.1.17 h1:rMrlX2ZY2UbvT+sdz3+6J+pp2z+msCq9MxTU6ymxbBY= github.com/google/gopacket v1.1.17 h1:rMrlX2ZY2UbvT+sdz3+6J+pp2z+msCq9MxTU6ymxbBY=
github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 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-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@ -442,6 +476,7 @@ github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqg
github.com/ipfs/go-datastore v0.0.1/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= github.com/ipfs/go-datastore v0.0.1/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE=
github.com/ipfs/go-datastore v0.4.0/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= github.com/ipfs/go-datastore v0.4.0/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA=
github.com/ipfs/go-datastore v0.4.1/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= github.com/ipfs/go-datastore v0.4.1/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA=
github.com/ipfs/go-datastore v0.4.4 h1:rjvQ9+muFaJ+QZ7dN5B1MSDNQ0JVZKkkES/rMZmA8X8=
github.com/ipfs/go-datastore v0.4.4/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= github.com/ipfs/go-datastore v0.4.4/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA=
github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= 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-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps=
@ -452,6 +487,7 @@ github.com/ipfs/go-ds-badger v0.2.3/go.mod h1:pEYw0rgg3FIrywKKnL+Snr+w/LjJZVMTBR
github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc= github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc=
github.com/ipfs/go-ds-leveldb v0.4.1/go.mod h1:jpbku/YqBSsBc1qgME8BkWS4AxzF2cEu1Ii2r79Hh9s= github.com/ipfs/go-ds-leveldb v0.4.1/go.mod h1:jpbku/YqBSsBc1qgME8BkWS4AxzF2cEu1Ii2r79Hh9s=
github.com/ipfs/go-ds-leveldb v0.4.2/go.mod h1:jpbku/YqBSsBc1qgME8BkWS4AxzF2cEu1Ii2r79Hh9s= github.com/ipfs/go-ds-leveldb v0.4.2/go.mod h1:jpbku/YqBSsBc1qgME8BkWS4AxzF2cEu1Ii2r79Hh9s=
github.com/ipfs/go-ds-sql v0.2.0 h1:ZUHUbU5IydNuBWzcRMOZYkBUwTg+L56o23fEVcbWC7o=
github.com/ipfs/go-ds-sql v0.2.0/go.mod h1:/c47NpRiHobwn+8F8EpW0yBy8d3Mx/j/tIlrVN1e1Ec= github.com/ipfs/go-ds-sql v0.2.0/go.mod h1:/c47NpRiHobwn+8F8EpW0yBy8d3Mx/j/tIlrVN1e1Ec=
github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw=
github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyBCNzQxlJBc= github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyBCNzQxlJBc=
@ -499,7 +535,9 @@ github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlT
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= 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/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jsternberg/zap-logfmt v1.0.0/go.mod h1:uvPs/4X51zdkcm5jXl5SYoN+4RK21K8mysFmDaM/h+o= github.com/jsternberg/zap-logfmt v1.0.0/go.mod h1:uvPs/4X51zdkcm5jXl5SYoN+4RK21K8mysFmDaM/h+o=
@ -746,6 +784,7 @@ github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.4 h1:8KGKTcQQGm0Kv7vEbKFErAoAOFyyacLStRtQSeYtvkY=
github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mat/besticon v0.0.0-20210314201728-1579f269edb7 h1:nxEXqXZcqWABJ8BudZJwrkdfKqCsSsGeo5IPQCbDKTw= github.com/mat/besticon v0.0.0-20210314201728-1579f269edb7 h1:nxEXqXZcqWABJ8BudZJwrkdfKqCsSsGeo5IPQCbDKTw=
@ -800,6 +839,7 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@ -928,6 +968,7 @@ github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChl
github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM=
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
@ -953,9 +994,12 @@ github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
github.com/prometheus/client_golang v1.6.0/go.mod h1:ZLOG9ck3JLRdB5MgO8f+lLTe83AXG6ro35rLTxvnIl4=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.9.0 h1:Rrch9mh17XcxvEu9D9DEpb4isxjGBtcevQjKvxPRQIU= github.com/prometheus/client_golang v1.9.0 h1:Rrch9mh17XcxvEu9D9DEpb4isxjGBtcevQjKvxPRQIU=
github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU= github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU=
github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ=
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@ -970,20 +1014,28 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
github.com/prometheus/common v0.18.0 h1:WCVKW7aL6LEe1uryfI9dnEc2ZqNB1Fn0ok930v0iL1Y= github.com/prometheus/common v0.18.0 h1:WCVKW7aL6LEe1uryfI9dnEc2ZqNB1Fn0ok930v0iL1Y=
github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
github.com/prometheus/common v0.28.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/common v0.29.0 h1:3jqPBvKT4OHAbje2Ql7KeaaSicDBCxMYwEJU1zRJceE=
github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/statsd_exporter v0.20.0/go.mod h1:YL3FWCG8JBBtaUSxAg4Gz2ZYu22bS84XM89ZQXXTWmQ=
github.com/prometheus/statsd_exporter v0.21.0/go.mod h1:rbT83sZq2V+p73lHhPZfMc3MLCHmSHelCh9hSGYNLTQ=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic= github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic=
github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4= github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4=
@ -1037,19 +1089,25 @@ github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.5.1 h1:VHu76Lk0LSP1x254maIu2bplkWpfBWI+B+6fdoZprcg=
github.com/spf13/afero v1.5.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.5.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M=
github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk=
github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc= github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc=
github.com/status-im/doubleratchet v3.0.0+incompatible h1:aJ1ejcSERpSzmWZBgtfYtiU2nF0Q8ZkGyuEPYETXkCY= github.com/status-im/doubleratchet v3.0.0+incompatible h1:aJ1ejcSERpSzmWZBgtfYtiU2nF0Q8ZkGyuEPYETXkCY=
@ -1058,10 +1116,10 @@ github.com/status-im/go-ethereum v1.10.4-status.1 h1:wQOcLgvJIhiB0rxnGQtFOBiy4hO
github.com/status-im/go-ethereum v1.10.4-status.1/go.mod h1:GvIhpdCOgMHI6i5xVPEZOrv/qSMeOFHbZh77AoyZUoE= github.com/status-im/go-ethereum v1.10.4-status.1/go.mod h1:GvIhpdCOgMHI6i5xVPEZOrv/qSMeOFHbZh77AoyZUoE=
github.com/status-im/go-multiaddr-ethv4 v1.2.0 h1:OT84UsUzTCwguqCpJqkrCMiL4VZ1SvUtH9a5MsZupBk= github.com/status-im/go-multiaddr-ethv4 v1.2.0 h1:OT84UsUzTCwguqCpJqkrCMiL4VZ1SvUtH9a5MsZupBk=
github.com/status-im/go-multiaddr-ethv4 v1.2.0/go.mod h1:2VQ3C+9zEurcceasz12gPAtmEzCeyLUGPeKLSXYQKHo= github.com/status-im/go-multiaddr-ethv4 v1.2.0/go.mod h1:2VQ3C+9zEurcceasz12gPAtmEzCeyLUGPeKLSXYQKHo=
github.com/status-im/go-waku v0.0.0-20210624095504-4133155590da h1:JKEFfCFWELd4UtlhzFbG4BqN4GljaDgsAyoIIeHR/V8= github.com/status-im/go-waku v0.0.0-20210711181138-a2ff7f3df962 h1:z1v+E3hRUajYxUcOVu60DOlNCcSmD0HKQQTIUdKeLos=
github.com/status-im/go-waku v0.0.0-20210624095504-4133155590da/go.mod h1:8MTfE7cM2Zj7yx+CFtLxNfTQizfGZKiZG/9bPpgL01w= github.com/status-im/go-waku v0.0.0-20210711181138-a2ff7f3df962/go.mod h1:5FwivzCf7JsJDiAEfJ4KMukZLzoIWkxaQkUKrDbw/LI=
github.com/status-im/go-wakurelay-pubsub v0.4.2 h1:F4UGcP80H0PGaeJ0mRMzA1Ux3DKYiyv/qu3bOR/efTg= github.com/status-im/go-wakurelay-pubsub v0.4.3-0.20210711180556-9afd35dadd3f h1:/KXMnxtAe0ZrbErvgZPkKilpLCmd7g1CIKQ4x17Al5I=
github.com/status-im/go-wakurelay-pubsub v0.4.2/go.mod h1:LSCVYR7mnBBsxVJghrGpQ3yJAAATEe6XeQQqGCZhwrE= github.com/status-im/go-wakurelay-pubsub v0.4.3-0.20210711180556-9afd35dadd3f/go.mod h1:LSCVYR7mnBBsxVJghrGpQ3yJAAATEe6XeQQqGCZhwrE=
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969 h1:Oo2KZNP70KE0+IUJSidPj/BFS/RXNHmKIJOdckzml2E= github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969 h1:Oo2KZNP70KE0+IUJSidPj/BFS/RXNHmKIJOdckzml2E=
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
@ -1145,6 +1203,9 @@ github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQ
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE= gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
@ -1160,6 +1221,8 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4 h1:LYy1Hy3MJdrCdMwwzxA/dRok4ejH+RwNGbuoD9fCjto= go.opencensus.io v0.22.4 h1:LYy1Hy3MJdrCdMwwzxA/dRok4ejH+RwNGbuoD9fCjto=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= 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.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
@ -1219,6 +1282,9 @@ golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm0
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= 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-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-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/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-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= 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/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
@ -1233,11 +1299,16 @@ golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/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 h1:J5lckAjkw6qYlOZNj90mLYNTEKDvWeuc1yieZ8qUzUE= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f h1:J5lckAjkw6qYlOZNj90mLYNTEKDvWeuc1yieZ8qUzUE=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= 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 h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k=
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-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/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.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.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.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/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= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
@ -1265,17 +1336,31 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/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-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/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-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/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-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-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q= golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@ -1285,6 +1370,7 @@ golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4Iltr
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/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-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 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= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -1292,6 +1378,7 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
@ -1328,6 +1415,7 @@ golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191025090151-53bf42e6b339/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191025090151-53bf42e6b339/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -1339,13 +1427,23 @@ golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/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-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/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= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -1358,6 +1456,7 @@ golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -1411,11 +1510,30 @@ golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/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-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-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 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-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200108203644-89082a384178/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200108203644-89082a384178/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/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-20200204074204-1cc6d1ef6c74/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-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY= golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -1438,6 +1556,15 @@ google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEn
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 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.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.15.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/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 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.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.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@ -1445,6 +1572,7 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
google.golang.org/appengine v1.5.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.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/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-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-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
@ -1462,8 +1590,25 @@ google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvx
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/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-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200108215221-bd8f9a0ef82f/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200108215221-bd8f9a0ef82f/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987 h1:PDIOdWxZ8eRizhKa1AAvY53xsvLB1cWorMjslvY3VA8=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= 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.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
@ -1476,9 +1621,16 @@ google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 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.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.1 h1:SfXqXS5hkufcdZ/mHtYCh53P2b+92WQq/DZcKLgsFRs= google.golang.org/grpc v1.31.1 h1:SfXqXS5hkufcdZ/mHtYCh53P2b+92WQq/DZcKLgsFRs=
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@ -1487,6 +1639,7 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
@ -1506,6 +1659,7 @@ gopkg.in/go-playground/validator.v9 v9.31.0 h1:bmXmP2RSNtFES+bn4uYuHT7iJFJv7Vj+a
gopkg.in/go-playground/validator.v9 v9.31.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= gopkg.in/go-playground/validator.v9 v9.31.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
@ -1541,6 +1695,8 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/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.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.1.3 h1:qTakTkI6ni6LFD5sBwwsdSO+AQqbSIxOauHTTQKZ/7o= honnef.co/go/tools v0.1.3 h1:qTakTkI6ni6LFD5sBwwsdSO+AQqbSIxOauHTTQKZ/7o=
honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
modernc.org/b v1.0.0/go.mod h1:uZWcZfRj1BpYzfN9JTerzlNUnnPsV9O2ZA8JsRcubNg= modernc.org/b v1.0.0/go.mod h1:uZWcZfRj1BpYzfN9JTerzlNUnnPsV9O2ZA8JsRcubNg=

View File

@ -515,6 +515,10 @@ func (m *Messenger) handleConnectionChange(online bool) {
} }
func (m *Messenger) online() bool { func (m *Messenger) online() bool {
// TODO: we are still missing peer management in wakuv2
if m.transport.WakuVersion() == 2 {
return true
}
return m.node.PeersCount() > 0 return m.node.PeersCount() > 0
} }
@ -3033,12 +3037,13 @@ func (m *Messenger) RequestHistoricMessages(
ctx context.Context, ctx context.Context,
from, to uint32, from, to uint32,
cursor []byte, cursor []byte,
storeCursor *types.StoreRequestCursor,
waitForResponse bool, waitForResponse bool,
) ([]byte, error) { ) ([]byte, *types.StoreRequestCursor, error) {
if m.mailserver == nil { if m.mailserver == nil {
return nil, errors.New("no mailserver selected") return nil, nil, errors.New("no mailserver selected")
} }
return m.transport.SendMessagesRequest(ctx, m.mailserver, from, to, cursor, waitForResponse) return m.transport.SendMessagesRequest(ctx, m.mailserver, from, to, cursor, storeCursor, waitForResponse)
} }
func (m *Messenger) MessageByID(id string) (*common.Message, error) { func (m *Messenger) MessageByID(id string) (*common.Message, error) {

View File

@ -668,10 +668,11 @@ func (m *Messenger) RequestCommunityInfoFromMailserver(communityID string) error
now := uint32(m.transport.GetCurrentTime() / 1000) now := uint32(m.transport.GetCurrentTime() / 1000)
monthAgo := now - (86400 * 30) monthAgo := now - (86400 * 30)
_, err := m.RequestHistoricMessagesForFilter(context.Background(), _, _, err := m.RequestHistoricMessagesForFilter(context.Background(),
monthAgo, monthAgo,
now, now,
nil, nil,
nil,
filter, filter,
false) false)

View File

@ -349,14 +349,14 @@ func (m *Messenger) calculateGapForChat(chat *Chat, from uint32) (*common.Messag
func (m *Messenger) processMailserverBatch(batch MailserverBatch) error { func (m *Messenger) processMailserverBatch(batch MailserverBatch) error {
m.logger.Info("syncing topic", zap.Any("topic", batch.Topics), zap.Int64("from", int64(batch.From)), zap.Int64("to", int64(batch.To))) m.logger.Info("syncing topic", zap.Any("topic", batch.Topics), zap.Int64("from", int64(batch.From)), zap.Int64("to", int64(batch.To)))
cursor, err := m.transport.SendMessagesRequestForTopics(context.Background(), m.mailserver, batch.From, batch.To, nil, batch.Topics, true) cursor, storeCursor, err := m.transport.SendMessagesRequestForTopics(context.Background(), m.mailserver, batch.From, batch.To, nil, nil, batch.Topics, true)
if err != nil { if err != nil {
return err return err
} }
for len(cursor) != 0 { for len(cursor) != 0 || storeCursor != nil {
m.logger.Info("retrieved cursor", zap.Any("cursor", cursor)) m.logger.Info("retrieved cursor", zap.Any("cursor", cursor))
cursor, err = m.transport.SendMessagesRequest(context.Background(), m.mailserver, batch.From, batch.To, cursor, true) cursor, storeCursor, err = m.transport.SendMessagesRequest(context.Background(), m.mailserver, batch.From, batch.To, cursor, storeCursor, true)
if err != nil { if err != nil {
return err return err
} }
@ -377,14 +377,15 @@ func (m *Messenger) RequestHistoricMessagesForFilter(
ctx context.Context, ctx context.Context,
from, to uint32, from, to uint32,
cursor []byte, cursor []byte,
previousStoreCursor *types.StoreRequestCursor,
filter *transport.Filter, filter *transport.Filter,
waitForResponse bool, waitForResponse bool,
) ([]byte, error) { ) ([]byte, *types.StoreRequestCursor, error) {
if m.mailserver == nil { if m.mailserver == nil {
return nil, errors.New("no mailserver selected") return nil, nil, errors.New("no mailserver selected")
} }
return m.transport.SendMessagesRequestForFilter(ctx, m.mailserver, from, to, cursor, filter, waitForResponse) return m.transport.SendMessagesRequestForFilter(ctx, m.mailserver, from, to, cursor, previousStoreCursor, filter, waitForResponse)
} }
func (m *Messenger) SyncChatFromSyncedFrom(chatID string) (uint32, error) { func (m *Messenger) SyncChatFromSyncedFrom(chatID string) (uint32, error) {

View File

@ -6,6 +6,7 @@ import (
"crypto/ecdsa" "crypto/ecdsa"
"database/sql" "database/sql"
"encoding/hex" "encoding/hex"
"fmt"
"sync" "sync"
"time" "time"
@ -405,7 +406,11 @@ func (t *Transport) cleanFiltersLoop() {
}() }()
} }
func (t *Transport) SendMessagesRequestForTopics( func (t *Transport) WakuVersion() uint {
return t.waku.Version()
}
func (t *Transport) createMessagesRequestV1(
ctx context.Context, ctx context.Context,
peerID []byte, peerID []byte,
from, to uint32, from, to uint32,
@ -413,8 +418,7 @@ func (t *Transport) SendMessagesRequestForTopics(
topics []types.TopicType, topics []types.TopicType,
waitForResponse bool, waitForResponse bool,
) (cursor []byte, err error) { ) (cursor []byte, err error) {
r := createMessagesRequest(from, to, previousCursor, nil, topics)
r := createMessagesRequest(from, to, previousCursor, topics)
events := make(chan types.EnvelopeEvent, 10) events := make(chan types.EnvelopeEvent, 10)
sub := t.waku.SubscribeEnvelopeEvents(events) sub := t.waku.SubscribeEnvelopeEvents(events)
@ -429,12 +433,48 @@ func (t *Transport) SendMessagesRequestForTopics(
return return
} }
resp, err := t.waitForRequestCompleted(ctx, r.ID, events) var resp *types.MailServerResponse
resp, err = t.waitForRequestCompleted(ctx, r.ID, events)
if err == nil && resp != nil && resp.Error != nil { if err == nil && resp != nil && resp.Error != nil {
err = resp.Error err = resp.Error
} else if err == nil && resp != nil { } else if err == nil && resp != nil {
cursor = resp.Cursor cursor = resp.Cursor
} }
return
}
func (t *Transport) createMessagesRequestV2(
peerID []byte,
from, to uint32,
previousStoreCursor *types.StoreRequestCursor,
topics []types.TopicType,
) (storeCursor *types.StoreRequestCursor, err error) {
r := createMessagesRequest(from, to, nil, previousStoreCursor, topics)
storeCursor, err = t.waku.RequestStoreMessages(peerID, r)
if err != nil {
return
}
return
}
func (t *Transport) SendMessagesRequestForTopics(
ctx context.Context,
peerID []byte,
from, to uint32,
previousCursor []byte,
previousStoreCursor *types.StoreRequestCursor,
topics []types.TopicType,
waitForResponse bool,
) (cursor []byte, storeCursor *types.StoreRequestCursor, err error) {
switch t.waku.Version() {
case 2:
storeCursor, err = t.createMessagesRequestV2(peerID, from, to, previousStoreCursor, topics)
case 1:
cursor, err = t.createMessagesRequestV1(ctx, peerID, from, to, previousCursor, topics, waitForResponse)
default:
err = fmt.Errorf("unsupported version %d", t.waku.Version())
}
return return
} }
@ -444,15 +484,16 @@ func (t *Transport) SendMessagesRequest(
peerID []byte, peerID []byte,
from, to uint32, from, to uint32,
previousCursor []byte, previousCursor []byte,
previousStoreCursor *types.StoreRequestCursor,
waitForResponse bool, waitForResponse bool,
) (cursor []byte, err error) { ) (cursor []byte, storeCursor *types.StoreRequestCursor, err error) {
topics := make([]types.TopicType, len(t.Filters())) topics := make([]types.TopicType, len(t.Filters()))
for _, f := range t.Filters() { for _, f := range t.Filters() {
topics = append(topics, f.Topic) topics = append(topics, f.Topic)
} }
return t.SendMessagesRequestForTopics(ctx, peerID, from, to, previousCursor, topics, waitForResponse) return t.SendMessagesRequestForTopics(ctx, peerID, from, to, previousCursor, previousStoreCursor, topics, waitForResponse)
} }
func (t *Transport) SendMessagesRequestForFilter( func (t *Transport) SendMessagesRequestForFilter(
@ -460,17 +501,18 @@ func (t *Transport) SendMessagesRequestForFilter(
peerID []byte, peerID []byte,
from, to uint32, from, to uint32,
previousCursor []byte, previousCursor []byte,
previousStoreCursor *types.StoreRequestCursor,
filter *Filter, filter *Filter,
waitForResponse bool, waitForResponse bool,
) (cursor []byte, err error) { ) (cursor []byte, storeCursor *types.StoreRequestCursor, err error) {
topics := make([]types.TopicType, len(t.Filters())) topics := make([]types.TopicType, len(t.Filters()))
topics = append(topics, filter.Topic) topics = append(topics, filter.Topic)
return t.SendMessagesRequestForTopics(ctx, peerID, from, to, previousCursor, topics, waitForResponse) return t.SendMessagesRequestForTopics(ctx, peerID, from, to, previousCursor, previousStoreCursor, topics, waitForResponse)
} }
func createMessagesRequest(from, to uint32, cursor []byte, topics []types.TopicType) types.MessagesRequest { func createMessagesRequest(from, to uint32, cursor []byte, storeCursor *types.StoreRequestCursor, topics []types.TopicType) types.MessagesRequest {
aUUID := uuid.New() aUUID := uuid.New()
// uuid is 16 bytes, converted to hex it's 32 bytes as expected by types.MessagesRequest // uuid is 16 bytes, converted to hex it's 32 bytes as expected by types.MessagesRequest
id := []byte(hex.EncodeToString(aUUID[:])) id := []byte(hex.EncodeToString(aUUID[:]))
@ -479,12 +521,13 @@ func createMessagesRequest(from, to uint32, cursor []byte, topics []types.TopicT
topicBytes = append(topicBytes, topics[idx][:]) topicBytes = append(topicBytes, topics[idx][:])
} }
return types.MessagesRequest{ return types.MessagesRequest{
ID: id, ID: id,
From: from, From: from,
To: to, To: to,
Limit: 1000, Limit: 1000,
Cursor: cursor, Cursor: cursor,
Topics: topicBytes, Topics: topicBytes,
StoreCursor: storeCursor,
} }
} }

View File

@ -69,6 +69,9 @@ type MessagesRequest struct {
// Cursor is used as starting point for paginated requests // Cursor is used as starting point for paginated requests
Cursor string `json:"cursor"` Cursor string `json:"cursor"`
// StoreCursor is used as starting point for WAKUV2 paginatedRequests
StoreCursor *StoreRequestCursor `json:"storeCursor"`
// Topic is a regular Whisper topic. // Topic is a regular Whisper topic.
// DEPRECATED // DEPRECATED
Topic types.TopicType `json:"topic"` Topic types.TopicType `json:"topic"`
@ -88,40 +91,6 @@ type MessagesRequest struct {
Force bool `json:"force"` Force bool `json:"force"`
} }
// StoreRequest is a WakuV2 RequestMessages() request payload.
type StoreRequest struct {
// MailServerPeer is MailServer's libp2p peer address.
MailServerPeer string `json:"mailServerPeer"`
// From is a lower bound of time range (optional).
// Default is 24 hours back from now.
From uint64 `json:"from"`
// To is a upper bound of time range (optional).
// Default is now.
To uint64 `json:"to"`
// PageSize determines the number of messages sent by the mail server
// for the current paginated request
PageSize uint64 `json:"pageSize"`
// Asc indicates if the ordering of the messages is ascending or descending (ordered by timestamp)
Asc bool `json:"asc"`
// Cursor is used as starting point for paginated requests
Cursor *StoreRequestCursor `json:"cursor"`
// Topics is a list of Whisper topics.
Topics []types.TopicType `json:"topics"`
// Timeout is the time to live of the request specified in seconds.
// Default is 10 seconds
Timeout time.Duration `json:"timeout"`
// Force ensures that requests will bypass enforced delay.
Force bool `json:"force"`
}
type StoreRequestCursor struct { type StoreRequestCursor struct {
Digest []byte `json:"digest"` Digest []byte `json:"digest"`
ReceivedTime float64 `json:"receivedTime"` ReceivedTime float64 `json:"receivedTime"`
@ -147,30 +116,6 @@ func (r *MessagesRequest) SetDefaults(now time.Time) {
} }
} }
func (r *StoreRequest) SetDefaults(now time.Time) {
// set From and To defaults
if r.To == 0 {
r.To = uint64(now.UTC().Unix())
}
if r.From == 0 {
oneDay := uint64(86400) // -24 hours
if r.To < oneDay {
r.From = 0
} else {
r.From = r.To - oneDay
}
}
if r.Timeout == 0 {
r.Timeout = defaultRequestTimeout
}
if r.PageSize == 0 {
r.PageSize = 100
}
}
// MessagesResponse is a response for requestMessages2 method. // MessagesResponse is a response for requestMessages2 method.
type MessagesResponse struct { type MessagesResponse struct {
// Cursor from the response can be used to retrieve more messages // Cursor from the response can be used to retrieve more messages
@ -668,6 +613,12 @@ func (api *PublicAPI) UpdateMailservers(enodes []string) error {
return api.service.UpdateMailservers(nodes) return api.service.UpdateMailservers(nodes)
} }
// Used in WakuV2 - Once proper peer management is added, we should probably remove this, or at least
// change mailserver so we use a peer.ID instead of a string / []byte
func (api *PublicAPI) SetMailserver(peer string) {
api.service.SetMailserver([]byte(peer))
}
// PushNotifications server endpoints // PushNotifications server endpoints
func (api *PublicAPI) StartPushNotificationsServer() error { func (api *PublicAPI) StartPushNotificationsServer() error {

View File

@ -318,6 +318,10 @@ func (s *Service) UpdateMailservers(nodes []*enode.Node) error {
return nil return nil
} }
func (s *Service) SetMailserver(peer []byte) {
s.messenger.SetMailserver(peer)
}
// Protocols returns a new protocols list. In this case, there are none. // Protocols returns a new protocols list. In this case, there are none.
func (s *Service) Protocols() []p2p.Protocol { func (s *Service) Protocols() []p2p.Protocol {
return []p2p.Protocol{} return []p2p.Protocol{}

View File

@ -1,14 +1,6 @@
package wakuv2ext package wakuv2ext
import ( import (
"context"
"fmt"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/status-im/go-waku/waku/v2/protocol"
"github.com/status-im/go-waku/waku/v2/protocol/pb"
"github.com/status-im/go-waku/waku/v2/protocol/store"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/services/ext" "github.com/status-im/status-go/services/ext"
@ -31,46 +23,3 @@ func NewPublicAPI(s *Service) *PublicAPI {
log: log.New("package", "status-go/services/wakuext.PublicAPI"), log: log.New("package", "status-go/services/wakuext.PublicAPI"),
} }
} }
// RequestMessages sends a request for historic messages to a MailServer.
func (api *PublicAPI) RequestMessages(_ context.Context, r ext.StoreRequest) (types.HexBytes, error) {
api.log.Info("RequestMessages", "request", r)
now := api.service.w.GetCurrentTime()
r.SetDefaults(now)
if r.From > r.To {
return nil, fmt.Errorf("Query range is invalid: from > to (%d > %d)", r.From, r.To)
}
h := protocol.GenerateRequestId()
mailserver, err := peer.Decode(r.MailServerPeer)
if err != nil {
return nil, err
}
options := []store.HistoryRequestOption{
store.WithRequestId(h),
store.WithPeer(mailserver),
store.WithPaging(r.Asc, r.PageSize),
}
// TODO: timeout
if r.Cursor != nil {
options = append(options, store.WithCursor(&pb.Index{
Digest: r.Cursor.Digest,
ReceivedTime: r.Cursor.ReceivedTime,
}))
}
var hash types.Hash
copy(hash[:], h[:types.HashLength])
if err := api.service.w.RequestStoreMessages(r.Topics, r.From, r.To, options); err != nil {
return nil, err
}
return hash[:], nil
}

View File

@ -1,29 +0,0 @@
// Copyright 2019 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build go1.12
package prometheus
import "runtime/debug"
// readBuildInfo is a wrapper around debug.ReadBuildInfo for Go 1.12+.
func readBuildInfo() (path, version, sum string) {
path, version, sum = "unknown", "unknown", "unknown"
if bi, ok := debug.ReadBuildInfo(); ok {
path = bi.Main.Path
version = bi.Main.Version
sum = bi.Main.Sum
}
return
}

View File

@ -1,22 +0,0 @@
// Copyright 2019 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build !go1.12
package prometheus
// readBuildInfo is a wrapper around debug.ReadBuildInfo for Go versions before
// 1.12. Remove this whole file once the minimum supported Go version is 1.12.
func readBuildInfo() (path, version, sum string) {
return "unknown", "unknown", "unknown"
}

View File

@ -20,7 +20,7 @@ import (
"strings" "strings"
"github.com/cespare/xxhash/v2" "github.com/cespare/xxhash/v2"
//lint:ignore SA1019 Need to keep deprecated package for compatibility. //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
"github.com/prometheus/common/model" "github.com/prometheus/common/model"

View File

@ -22,43 +22,10 @@ type expvarCollector struct {
exports map[string]*Desc exports map[string]*Desc
} }
// NewExpvarCollector returns a newly allocated expvar Collector that still has // NewExpvarCollector is the obsolete version of collectors.NewExpvarCollector.
// to be registered with a Prometheus registry. // See there for documentation.
// //
// An expvar Collector collects metrics from the expvar interface. It provides a // Deprecated: Use collectors.NewExpvarCollector instead.
// quick way to expose numeric values that are already exported via expvar as
// Prometheus metrics. Note that the data models of expvar and Prometheus are
// fundamentally different, and that the expvar Collector is inherently slower
// than native Prometheus metrics. Thus, the expvar Collector is probably great
// for experiments and prototying, but you should seriously consider a more
// direct implementation of Prometheus metrics for monitoring production
// systems.
//
// The exports map has the following meaning:
//
// The keys in the map correspond to expvar keys, i.e. for every expvar key you
// want to export as Prometheus metric, you need an entry in the exports
// map. The descriptor mapped to each key describes how to export the expvar
// value. It defines the name and the help string of the Prometheus metric
// proxying the expvar value. The type will always be Untyped.
//
// For descriptors without variable labels, the expvar value must be a number or
// a bool. The number is then directly exported as the Prometheus sample
// value. (For a bool, 'false' translates to 0 and 'true' to 1). Expvar values
// that are not numbers or bools are silently ignored.
//
// If the descriptor has one variable label, the expvar value must be an expvar
// map. The keys in the expvar map become the various values of the one
// Prometheus label. The values in the expvar map must be numbers or bools again
// as above.
//
// For descriptors with more than one variable label, the expvar must be a
// nested expvar map, i.e. where the values of the topmost map are maps again
// etc. until a depth is reached that corresponds to the number of labels. The
// leaves of that structure must be numbers or bools as above to serve as the
// sample values.
//
// Anything that does not fit into the scheme above is silently ignored.
func NewExpvarCollector(exports map[string]*Desc) Collector { func NewExpvarCollector(exports map[string]*Desc) Collector {
return &expvarCollector{ return &expvarCollector{
exports: exports, exports: exports,

View File

@ -36,32 +36,10 @@ type goCollector struct {
msMaxAge time.Duration // Maximum allowed age of old memstats. msMaxAge time.Duration // Maximum allowed age of old memstats.
} }
// NewGoCollector returns a collector that exports metrics about the current Go // NewGoCollector is the obsolete version of collectors.NewGoCollector.
// process. This includes memory stats. To collect those, runtime.ReadMemStats // See there for documentation.
// is called. This requires to “stop the world”, which usually only happens for
// garbage collection (GC). Take the following implications into account when
// deciding whether to use the Go collector:
// //
// 1. The performance impact of stopping the world is the more relevant the more // Deprecated: Use collectors.NewGoCollector instead.
// frequently metrics are collected. However, with Go1.9 or later the
// stop-the-world time per metrics collection is very short (~25µs) so that the
// performance impact will only matter in rare cases. However, with older Go
// versions, the stop-the-world duration depends on the heap size and can be
// quite significant (~1.7 ms/GiB as per
// https://go-review.googlesource.com/c/go/+/34937).
//
// 2. During an ongoing GC, nothing else can stop the world. Therefore, if the
// metrics collection happens to coincide with GC, it will only complete after
// GC has finished. Usually, GC is fast enough to not cause problems. However,
// with a very large heap, GC might take multiple seconds, which is enough to
// cause scrape timeouts in common setups. To avoid this problem, the Go
// collector will use the memstats from a previous collection if
// runtime.ReadMemStats takes more than 1s. However, if there are no previously
// collected memstats, or their collection is more than 5m ago, the collection
// will block until runtime.ReadMemStats succeeds.
//
// NOTE: The problem is solved in Go 1.15, see
// https://github.com/golang/go/issues/19812 for the related Go issue.
func NewGoCollector() Collector { func NewGoCollector() Collector {
return &goCollector{ return &goCollector{
goroutinesDesc: NewDesc( goroutinesDesc: NewDesc(
@ -366,25 +344,17 @@ type memStatsMetrics []struct {
valType ValueType valType ValueType
} }
// NewBuildInfoCollector returns a collector collecting a single metric // NewBuildInfoCollector is the obsolete version of collectors.NewBuildInfoCollector.
// "go_build_info" with the constant value 1 and three labels "path", "version", // See there for documentation.
// and "checksum". Their label values contain the main module path, version, and
// checksum, respectively. The labels will only have meaningful values if the
// binary is built with Go module support and from source code retrieved from
// the source repository (rather than the local file system). This is usually
// accomplished by building from outside of GOPATH, specifying the full address
// of the main package, e.g. "GO111MODULE=on go run
// github.com/prometheus/client_golang/examples/random". If built without Go
// module support, all label values will be "unknown". If built with Go module
// support but using the source code from the local file system, the "path" will
// be set appropriately, but "checksum" will be empty and "version" will be
// "(devel)".
// //
// This collector uses only the build information for the main module. See // Deprecated: Use collectors.NewBuildInfoCollector instead.
// https://github.com/povilasv/prommod for an example of a collector for the
// module dependencies.
func NewBuildInfoCollector() Collector { func NewBuildInfoCollector() Collector {
path, version, sum := readBuildInfo() path, version, sum := "unknown", "unknown", "unknown"
if bi, ok := debug.ReadBuildInfo(); ok {
path = bi.Main.Path
version = bi.Main.Version
sum = bi.Main.Sum
}
c := &selfCollector{MustNewConstMetric( c := &selfCollector{MustNewConstMetric(
NewDesc( NewDesc(
"go_build_info", "go_build_info",

View File

@ -22,7 +22,7 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
//lint:ignore SA1019 Need to keep deprecated package for compatibility. //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
dto "github.com/prometheus/client_model/go" dto "github.com/prometheus/client_model/go"
@ -47,7 +47,12 @@ type Histogram interface {
Metric Metric
Collector Collector
// Observe adds a single observation to the histogram. // Observe adds a single observation to the histogram. Observations are
// usually positive or zero. Negative observations are accepted but
// prevent current versions of Prometheus from properly detecting
// counter resets in the sum of observations. See
// https://prometheus.io/docs/practices/histograms/#count-and-sum-of-observations
// for details.
Observe(float64) Observe(float64)
} }

View File

@ -17,7 +17,7 @@ import (
"strings" "strings"
"time" "time"
//lint:ignore SA1019 Need to keep deprecated package for compatibility. //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
"github.com/prometheus/common/model" "github.com/prometheus/common/model"
@ -58,7 +58,7 @@ type Metric interface {
} }
// Opts bundles the options for creating most Metric types. Each metric // Opts bundles the options for creating most Metric types. Each metric
// implementation XXX has its own XXXOpts type, but in most cases, it is just be // implementation XXX has its own XXXOpts type, but in most cases, it is just
// an alias of this type (which might change when the requirement arises.) // an alias of this type (which might change when the requirement arises.)
// //
// It is mandatory to set Name to a non-empty string. All other fields are // It is mandatory to set Name to a non-empty string. All other fields are

View File

@ -54,16 +54,10 @@ type ProcessCollectorOpts struct {
ReportErrors bool ReportErrors bool
} }
// NewProcessCollector returns a collector which exports the current state of // NewProcessCollector is the obsolete version of collectors.NewProcessCollector.
// process metrics including CPU, memory and file descriptor usage as well as // See there for documentation.
// the process start time. The detailed behavior is defined by the provided
// ProcessCollectorOpts. The zero value of ProcessCollectorOpts creates a
// collector for the current process with an empty namespace string and no error
// reporting.
// //
// The collector only works on operating systems with a Linux-style proc // Deprecated: Use collectors.NewProcessCollector instead.
// filesystem and on Microsoft Windows. On other operating systems, it will not
// collect any metrics.
func NewProcessCollector(opts ProcessCollectorOpts) Collector { func NewProcessCollector(opts ProcessCollectorOpts) Collector {
ns := "" ns := ""
if len(opts.Namespace) > 0 { if len(opts.Namespace) > 0 {

View File

@ -83,8 +83,7 @@ type readerFromDelegator struct{ *responseWriterDelegator }
type pusherDelegator struct{ *responseWriterDelegator } type pusherDelegator struct{ *responseWriterDelegator }
func (d closeNotifierDelegator) CloseNotify() <-chan bool { func (d closeNotifierDelegator) CloseNotify() <-chan bool {
//lint:ignore SA1019 http.CloseNotifier is deprecated but we don't want to //nolint:staticcheck // Ignore SA1019. http.CloseNotifier is deprecated but we keep it here to not break existing users.
//remove support from client_golang yet.
return d.ResponseWriter.(http.CloseNotifier).CloseNotify() return d.ResponseWriter.(http.CloseNotifier).CloseNotify()
} }
func (d flusherDelegator) Flush() { func (d flusherDelegator) Flush() {
@ -348,8 +347,7 @@ func newDelegator(w http.ResponseWriter, observeWriteHeaderFunc func(int)) deleg
} }
id := 0 id := 0
//lint:ignore SA1019 http.CloseNotifier is deprecated but we don't want to //nolint:staticcheck // Ignore SA1019. http.CloseNotifier is deprecated but we keep it here to not break existing users.
//remove support from client_golang yet.
if _, ok := w.(http.CloseNotifier); ok { if _, ok := w.(http.CloseNotifier); ok {
id += closeNotifier id += closeNotifier
} }

View File

@ -26,7 +26,7 @@ import (
"unicode/utf8" "unicode/utf8"
"github.com/cespare/xxhash/v2" "github.com/cespare/xxhash/v2"
//lint:ignore SA1019 Need to keep deprecated package for compatibility. //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
"github.com/prometheus/common/expfmt" "github.com/prometheus/common/expfmt"

View File

@ -23,7 +23,7 @@ import (
"time" "time"
"github.com/beorn7/perks/quantile" "github.com/beorn7/perks/quantile"
//lint:ignore SA1019 Need to keep deprecated package for compatibility. //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
dto "github.com/prometheus/client_model/go" dto "github.com/prometheus/client_model/go"
@ -55,7 +55,12 @@ type Summary interface {
Metric Metric
Collector Collector
// Observe adds a single observation to the summary. // Observe adds a single observation to the summary. Observations are
// usually positive or zero. Negative observations are accepted but
// prevent current versions of Prometheus from properly detecting
// counter resets in the sum of observations. See
// https://prometheus.io/docs/practices/histograms/#count-and-sum-of-observations
// for details.
Observe(float64) Observe(float64)
} }
@ -121,7 +126,9 @@ type SummaryOpts struct {
Objectives map[float64]float64 Objectives map[float64]float64
// MaxAge defines the duration for which an observation stays relevant // MaxAge defines the duration for which an observation stays relevant
// for the summary. Must be positive. The default value is DefMaxAge. // for the summary. Only applies to pre-calculated quantiles, does not
// apply to _sum and _count. Must be positive. The default value is
// DefMaxAge.
MaxAge time.Duration MaxAge time.Duration
// AgeBuckets is the number of buckets used to exclude observations that // AgeBuckets is the number of buckets used to exclude observations that

View File

@ -19,7 +19,7 @@ import (
"time" "time"
"unicode/utf8" "unicode/utf8"
//lint:ignore SA1019 Need to keep deprecated package for compatibility. //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
"github.com/golang/protobuf/ptypes" "github.com/golang/protobuf/ptypes"

View File

@ -167,8 +167,8 @@ func (m *MetricVec) CurryWith(labels Labels) (*MetricVec, error) {
// calling the newMetric function provided during construction of the // calling the newMetric function provided during construction of the
// MetricVec). // MetricVec).
// //
// It is possible to call this method without using the returned Metry to only // It is possible to call this method without using the returned Metric to only
// create the new Metric but leave it in its intitial state. // create the new Metric but leave it in its initial state.
// //
// Keeping the Metric for later use is possible (and should be considered if // Keeping the Metric for later use is possible (and should be considered if
// performance is critical), but keep in mind that Reset, DeleteLabelValues and // performance is critical), but keep in mind that Reset, DeleteLabelValues and

View File

@ -17,7 +17,7 @@ import (
"fmt" "fmt"
"sort" "sort"
//lint:ignore SA1019 Need to keep deprecated package for compatibility. //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
dto "github.com/prometheus/client_model/go" dto "github.com/prometheus/client_model/go"

View File

@ -45,6 +45,14 @@ const (
// scrape a target. // scrape a target.
MetricsPathLabel = "__metrics_path__" MetricsPathLabel = "__metrics_path__"
// ScrapeIntervalLabel is the name of the label that holds the scrape interval
// used to scrape a target.
ScrapeIntervalLabel = "__scrape_interval__"
// ScrapeTimeoutLabel is the name of the label that holds the scrape
// timeout used to scrape a target.
ScrapeTimeoutLabel = "__scrape_timeout__"
// ReservedLabelPrefix is a prefix which is not legal in user-supplied // ReservedLabelPrefix is a prefix which is not legal in user-supplied
// label names. // label names.
ReservedLabelPrefix = "__" ReservedLabelPrefix = "__"

View File

@ -14,6 +14,8 @@
package model package model
import ( import (
"encoding/json"
"errors"
"fmt" "fmt"
"math" "math"
"regexp" "regexp"
@ -201,13 +203,23 @@ func ParseDuration(durationStr string) (Duration, error) {
// Parse the match at pos `pos` in the regex and use `mult` to turn that // Parse the match at pos `pos` in the regex and use `mult` to turn that
// into ms, then add that value to the total parsed duration. // into ms, then add that value to the total parsed duration.
var overflowErr error
m := func(pos int, mult time.Duration) { m := func(pos int, mult time.Duration) {
if matches[pos] == "" { if matches[pos] == "" {
return return
} }
n, _ := strconv.Atoi(matches[pos]) n, _ := strconv.Atoi(matches[pos])
// Check if the provided duration overflows time.Duration (> ~ 290years).
if n > int((1<<63-1)/mult/time.Millisecond) {
overflowErr = errors.New("duration out of range")
}
d := time.Duration(n) * time.Millisecond d := time.Duration(n) * time.Millisecond
dur += d * mult dur += d * mult
if dur < 0 {
overflowErr = errors.New("duration out of range")
}
} }
m(2, 1000*60*60*24*365) // y m(2, 1000*60*60*24*365) // y
@ -218,7 +230,7 @@ func ParseDuration(durationStr string) (Duration, error) {
m(12, 1000) // s m(12, 1000) // s
m(14, 1) // ms m(14, 1) // ms
return Duration(dur), nil return Duration(dur), overflowErr
} }
func (d Duration) String() string { func (d Duration) String() string {
@ -254,6 +266,25 @@ func (d Duration) String() string {
return r return r
} }
// MarshalJSON implements the json.Marshaler interface.
func (d Duration) MarshalJSON() ([]byte, error) {
return json.Marshal(d.String())
}
// UnmarshalJSON implements the json.Unmarshaler interface.
func (d *Duration) UnmarshalJSON(bytes []byte) error {
var s string
if err := json.Unmarshal(bytes, &s); err != nil {
return err
}
dur, err := ParseDuration(s)
if err != nil {
return err
}
*d = dur
return nil
}
// MarshalText implements the encoding.TextMarshaler interface. // MarshalText implements the encoding.TextMarshaler interface.
func (d *Duration) MarshalText() ([]byte, error) { func (d *Duration) MarshalText() ([]byte, error) {
return []byte(d.String()), nil return []byte(d.String()), nil

View File

@ -0,0 +1,49 @@
package metrics
import (
"go.opencensus.io/stats"
"go.opencensus.io/stats/view"
"go.opencensus.io/tag"
)
var (
Messages = stats.Int64("messages", "Number of messages received", stats.UnitDimensionless)
StoreMessages = stats.Int64("store_messages", "Number of historical messages", stats.UnitDimensionless)
FilterSubscriptions = stats.Int64("filter_subscriptions", "Number of filter subscriptions", stats.UnitDimensionless)
Errors = stats.Int64("errors", "Number of errors", stats.UnitDimensionless)
)
var (
KeyType, _ = tag.NewKey("type")
KeyStoreErrorType, _ = tag.NewKey("store_error_type")
)
var (
MessageTypeView = &view.View{
Name: "messages",
Measure: Messages,
Description: "The distribution of the messages received",
Aggregation: view.Count(),
TagKeys: []tag.Key{KeyType},
}
StoreMessageTypeView = &view.View{
Name: "store_messages",
Measure: StoreMessages,
Description: "The distribution of the store protocol messages",
Aggregation: view.LastValue(),
TagKeys: []tag.Key{KeyType},
}
FilterSubscriptionsView = &view.View{
Name: "filter_subscriptions",
Measure: FilterSubscriptions,
Description: "The number of content filter subscriptions",
Aggregation: view.LastValue(),
}
StoreErrorTypesView = &view.View{
Name: "store_errors",
Measure: Errors,
Description: "The distribution of the store protocol errors",
Aggregation: view.Count(),
TagKeys: []tag.Key{KeyType},
}
)

View File

@ -10,10 +10,17 @@ import (
proto "github.com/golang/protobuf/proto" proto "github.com/golang/protobuf/proto"
logging "github.com/ipfs/go-log" logging "github.com/ipfs/go-log"
"github.com/libp2p/go-libp2p" "github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p-core/event"
"github.com/libp2p/go-libp2p-core/host" "github.com/libp2p/go-libp2p-core/host"
"github.com/libp2p/go-libp2p-core/network"
"github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peer"
peerstore "github.com/libp2p/go-libp2p-peerstore"
"github.com/libp2p/go-libp2p/p2p/protocol/ping"
ma "github.com/multiformats/go-multiaddr" ma "github.com/multiformats/go-multiaddr"
"go.opencensus.io/stats"
"go.opencensus.io/tag"
"github.com/status-im/go-waku/waku/v2/metrics"
"github.com/status-im/go-waku/waku/v2/protocol" "github.com/status-im/go-waku/waku/v2/protocol"
"github.com/status-im/go-waku/waku/v2/protocol/filter" "github.com/status-im/go-waku/waku/v2/protocol/filter"
"github.com/status-im/go-waku/waku/v2/protocol/lightpush" "github.com/status-im/go-waku/waku/v2/protocol/lightpush"
@ -25,11 +32,16 @@ import (
var log = logging.Logger("wakunode") var log = logging.Logger("wakunode")
// Default clientId
const clientId string = "Go Waku v2 node"
type Message []byte type Message []byte
// A map of peer IDs to supported protocols
type PeerStats map[peer.ID][]string
type ConnStatus struct {
IsOnline bool
HasHistory bool
}
type WakuNode struct { type WakuNode struct {
host host.Host host host.Host
opts *WakuNodeParameters opts *WakuNodeParameters
@ -38,6 +50,8 @@ type WakuNode struct {
filter *filter.WakuFilter filter *filter.WakuFilter
lightPush *lightpush.WakuLightPush lightPush *lightpush.WakuLightPush
ping *ping.PingService
subscriptions map[relay.Topic][]*Subscription subscriptions map[relay.Topic][]*Subscription
subscriptionsMutex sync.Mutex subscriptionsMutex sync.Mutex
@ -45,8 +59,95 @@ type WakuNode struct {
filters filter.Filters filters filter.Filters
connectednessEventSub event.Subscription
protocolEventSub event.Subscription
identificationEventSub event.Subscription
ctx context.Context ctx context.Context
cancel context.CancelFunc cancel context.CancelFunc
quit chan struct{}
// Map of peers and their supported protocols
peers PeerStats
// Internal protocol implementations that wish
// to listen to peer added/removed events (e.g. Filter)
peerListeners []chan *event.EvtPeerConnectednessChanged
// Channel passed to WakuNode constructor
// receiving connection status notifications
connStatusChan chan ConnStatus
}
func (w *WakuNode) connectednessListener() {
for {
isOnline := w.IsOnline()
hasHistory := w.HasHistory()
select {
case e := <-w.connectednessEventSub.Out():
if e == nil {
break
}
ev := e.(event.EvtPeerConnectednessChanged)
log.Info("### EvtPeerConnectednessChanged ", w.Host().ID(), " to ", ev.Peer, " : ", ev.Connectedness)
if ev.Connectedness == network.Connected {
_, ok := w.peers[ev.Peer]
if !ok {
peerProtocols, _ := w.host.Peerstore().GetProtocols(ev.Peer)
log.Info("protocols found for peer: ", ev.Peer, ", protocols: ", peerProtocols)
w.peers[ev.Peer] = peerProtocols
} else {
log.Info("### Peer already exists")
}
} else if ev.Connectedness == network.NotConnected {
log.Info("Peer down: ", ev.Peer)
delete(w.peers, ev.Peer)
for _, pl := range w.peerListeners {
pl <- &ev
}
// TODO
// There seems to be no proper way to
// remove a dropped peer from Host's Peerstore
// https://github.com/libp2p/go-libp2p-host/issues/13
//w.Host().Network().ClosePeer(ev.Peer)
}
case e := <-w.protocolEventSub.Out():
if e == nil {
break
}
ev := e.(event.EvtPeerProtocolsUpdated)
log.Info("### EvtPeerProtocolsUpdated ", w.Host().ID(), " to ", ev.Peer, " added: ", ev.Added, ", removed: ", ev.Removed)
_, ok := w.peers[ev.Peer]
if ok {
peerProtocols, _ := w.host.Peerstore().GetProtocols(ev.Peer)
log.Info("updated protocols found for peer: ", ev.Peer, ", protocols: ", peerProtocols)
w.peers[ev.Peer] = peerProtocols
}
case e := <-w.identificationEventSub.Out():
if e == nil {
break
}
ev := e.(event.EvtPeerIdentificationCompleted)
log.Info("### EvtPeerIdentificationCompleted ", w.Host().ID(), " to ", ev.Peer)
peerProtocols, _ := w.host.Peerstore().GetProtocols(ev.Peer)
log.Info("identified protocols found for peer: ", ev.Peer, ", protocols: ", peerProtocols)
_, ok := w.peers[ev.Peer]
if ok {
peerProtocols, _ := w.host.Peerstore().GetProtocols(ev.Peer)
w.peers[ev.Peer] = peerProtocols
}
}
newIsOnline := w.IsOnline()
newHasHistory := w.HasHistory()
if w.connStatusChan != nil &&
(isOnline != newIsOnline || hasHistory != newHasHistory) {
w.connStatusChan <- ConnStatus{IsOnline: newIsOnline, HasHistory: newHasHistory}
}
}
} }
func New(ctx context.Context, opts ...WakuNodeOption) (*WakuNode, error) { func New(ctx context.Context, opts ...WakuNodeOption) (*WakuNode, error) {
@ -84,12 +185,28 @@ func New(ctx context.Context, opts ...WakuNodeOption) (*WakuNode, error) {
w.ctx = ctx w.ctx = ctx
w.subscriptions = make(map[relay.Topic][]*Subscription) w.subscriptions = make(map[relay.Topic][]*Subscription)
w.opts = params w.opts = params
w.quit = make(chan struct{})
w.peers = make(PeerStats)
if params.enableRelay { // Subscribe to Connectedness events
err := w.mountRelay(params.wOpts...) log.Info("### host.ID(): ", host.ID())
if err != nil {
return nil, err connectednessEventSub, _ := host.EventBus().Subscribe(new(event.EvtPeerConnectednessChanged))
} w.connectednessEventSub = connectednessEventSub
protocolEventSub, _ := host.EventBus().Subscribe(new(event.EvtPeerProtocolsUpdated))
w.protocolEventSub = protocolEventSub
identificationEventSub, _ := host.EventBus().Subscribe(new(event.EvtPeerIdentificationCompleted))
w.identificationEventSub = identificationEventSub
if params.connStatusChan != nil {
w.connStatusChan = params.connStatusChan
}
go w.connectednessListener()
if params.enableStore {
w.startStore()
} }
if params.enableFilter { if params.enableFilter {
@ -100,17 +217,19 @@ func New(ctx context.Context, opts ...WakuNodeOption) (*WakuNode, error) {
} }
} }
if params.enableStore { err = w.mountRelay(params.enableRelay, params.wOpts...)
err := w.startStore() if err != nil {
if err != nil { return nil, err
return nil, err
}
} }
if params.enableLightPush { if params.enableLightPush {
w.mountLightPush() w.mountLightPush()
} }
if params.keepAliveInterval > time.Duration(0) {
w.startKeepAlive(params.keepAliveInterval)
}
for _, addr := range w.ListenAddresses() { for _, addr := range w.ListenAddresses() {
log.Info("Listening on ", addr) log.Info("Listening on ", addr)
} }
@ -123,6 +242,11 @@ func (w *WakuNode) Stop() {
defer w.subscriptionsMutex.Unlock() defer w.subscriptionsMutex.Unlock()
defer w.cancel() defer w.cancel()
close(w.quit)
defer w.connectednessEventSub.Close()
defer w.protocolEventSub.Close()
defer w.identificationEventSub.Close()
for _, topic := range w.relay.Topics() { for _, topic := range w.relay.Topics() {
for _, sub := range w.subscriptions[topic] { for _, sub := range w.subscriptions[topic] {
sub.Unsubscribe() sub.Unsubscribe()
@ -140,6 +264,49 @@ func (w *WakuNode) ID() string {
return w.host.ID().Pretty() return w.host.ID().Pretty()
} }
func (w *WakuNode) GetPeerStats() PeerStats {
return w.peers
}
func (w *WakuNode) IsOnline() bool {
hasRelay := false
hasLightPush := false
hasStore := false
hasFilter := false
for _, v := range w.peers {
for _, protocol := range v {
if !hasRelay && protocol == string(wakurelay.WakuRelayID_v200) {
hasRelay = true
}
if !hasLightPush && protocol == string(lightpush.WakuLightPushProtocolId) {
hasLightPush = true
}
if !hasStore && protocol == string(store.WakuStoreProtocolId) {
hasStore = true
}
if !hasFilter && protocol == string(filter.WakuFilterProtocolId) {
hasFilter = true
}
if hasRelay || hasLightPush && (hasStore || hasFilter) {
return true
}
}
}
return false
}
func (w *WakuNode) HasHistory() bool {
for _, v := range w.peers {
for _, protocol := range v {
if protocol == string(store.WakuStoreProtocolId) {
return true
}
}
}
return false
}
func (w *WakuNode) ListenAddresses() []string { func (w *WakuNode) ListenAddresses() []string {
hostInfo, _ := ma.NewMultiaddr(fmt.Sprintf("/p2p/%s", w.host.ID().Pretty())) hostInfo, _ := ma.NewMultiaddr(fmt.Sprintf("/p2p/%s", w.host.ID().Pretty()))
var result []string var result []string
@ -157,10 +324,17 @@ func (w *WakuNode) Filter() *filter.WakuFilter {
return w.filter return w.filter
} }
func (w *WakuNode) mountRelay(opts ...wakurelay.Option) error { func (w *WakuNode) mountRelay(shouldRelayMessages bool, opts ...wakurelay.Option) error {
var err error var err error
w.relay, err = relay.NewWakuRelay(w.ctx, w.host, opts...) w.relay, err = relay.NewWakuRelay(w.ctx, w.host, opts...)
if shouldRelayMessages {
_, err := w.Subscribe(nil)
if err != nil {
return err
}
}
// TODO: rlnRelay // TODO: rlnRelay
return err return err
@ -172,7 +346,9 @@ func (w *WakuNode) mountFilter() error {
w.filters.Notify(message, requestId) // Trigger filter handlers on a light node w.filters.Notify(message, requestId) // Trigger filter handlers on a light node
} }
} }
w.filter = filter.NewWakuFilter(w.ctx, w.host, filterHandler) peerChan := make(chan *event.EvtPeerConnectednessChanged)
w.filter = filter.NewWakuFilter(w.ctx, w.host, filterHandler, peerChan)
w.peerListeners = append(w.peerListeners, peerChan)
return nil return nil
@ -181,12 +357,14 @@ func (w *WakuNode) mountLightPush() {
w.lightPush = lightpush.NewWakuLightPush(w.ctx, w.host, w.relay) w.lightPush = lightpush.NewWakuLightPush(w.ctx, w.host, w.relay)
} }
func (w *WakuNode) startStore() error { func (w *WakuNode) AddPeer(p peer.ID, addrs []ma.Multiaddr, protocolId string) error {
w.opts.store.Start(w.host) log.Info("AddPeer: ", protocolId)
w.opts.store.Resume(w.ctx, string(relay.GetTopic(nil)), nil) for _, addr := range addrs {
w.host.Peerstore().AddAddr(p, addr, peerstore.PermanentAddrTTL)
}
err := w.host.Peerstore().AddProtocols(p, protocolId)
_, err := w.Subscribe(nil)
if err != nil { if err != nil {
return err return err
} }
@ -194,6 +372,14 @@ func (w *WakuNode) startStore() error {
return nil return nil
} }
func (w *WakuNode) startStore() {
peerChan := make(chan *event.EvtPeerConnectednessChanged)
w.opts.store.Start(w.ctx, w.host, peerChan)
w.peerListeners = append(w.peerListeners, peerChan)
w.opts.store.Resume(string(relay.GetTopic(nil)), nil)
}
func (w *WakuNode) AddStorePeer(address string) (*peer.ID, error) { func (w *WakuNode) AddStorePeer(address string) (*peer.ID, error) {
if w.opts.store == nil { if w.opts.store == nil {
return nil, errors.New("WakuStore is not set") return nil, errors.New("WakuStore is not set")
@ -210,7 +396,7 @@ func (w *WakuNode) AddStorePeer(address string) (*peer.ID, error) {
return nil, err return nil, err
} }
return &info.ID, w.opts.store.AddPeer(info.ID, info.Addrs) return &info.ID, w.AddPeer(info.ID, info.Addrs, string(store.WakuStoreProtocolId))
} }
// TODO Remove code duplication // TODO Remove code duplication
@ -230,7 +416,27 @@ func (w *WakuNode) AddFilterPeer(address string) (*peer.ID, error) {
return nil, err return nil, err
} }
return &info.ID, w.filter.AddPeer(info.ID, info.Addrs) return &info.ID, w.AddPeer(info.ID, info.Addrs, string(filter.WakuFilterProtocolId))
}
// TODO Remove code duplication
func (w *WakuNode) AddLightPushPeer(address string) (*peer.ID, error) {
if w.filter == nil {
return nil, errors.New("WakuFilter is not set")
}
lightPushPeer, err := ma.NewMultiaddr(address)
if err != nil {
return nil, err
}
// Extract the peer ID from the multiaddr.
info, err := peer.AddrInfoFromP2pAddr(lightPushPeer)
if err != nil {
return nil, err
}
return &info.ID, w.AddPeer(info.ID, info.Addrs, string(lightpush.WakuLightPushProtocolId))
} }
func (w *WakuNode) Query(ctx context.Context, contentTopics []string, startTime float64, endTime float64, opts ...store.HistoryRequestOption) (*pb.HistoryResponse, error) { func (w *WakuNode) Query(ctx context.Context, contentTopics []string, startTime float64, endTime float64, opts ...store.HistoryRequestOption) (*pb.HistoryResponse, error) {
@ -259,7 +465,7 @@ func (w *WakuNode) Resume(ctx context.Context, peerList []peer.ID) error {
return errors.New("WakuStore is not set") return errors.New("WakuStore is not set")
} }
result, err := w.opts.store.Resume(ctx, string(relay.DefaultWakuTopic), peerList) result, err := w.opts.store.Resume(string(relay.DefaultWakuTopic), peerList)
if err != nil { if err != nil {
return err return err
} }
@ -273,7 +479,7 @@ func (node *WakuNode) Subscribe(topic *relay.Topic) (*Subscription, error) {
// Subscribes to a PubSub topic. // Subscribes to a PubSub topic.
// NOTE The data field SHOULD be decoded as a WakuMessage. // NOTE The data field SHOULD be decoded as a WakuMessage.
if node.relay == nil { if node.relay == nil {
return nil, errors.New("WakuRelay hasn't been set.") return nil, errors.New("WakuRelay hasn't been set")
} }
t := relay.GetTopic(topic) t := relay.GetTopic(topic)
@ -312,6 +518,12 @@ func (node *WakuNode) Subscribe(topic *relay.Topic) (*Subscription, error) {
nextMsgTicker := time.NewTicker(time.Millisecond * 10) nextMsgTicker := time.NewTicker(time.Millisecond * 10)
defer nextMsgTicker.Stop() defer nextMsgTicker.Stop()
ctx, err := tag.New(node.ctx, tag.Insert(metrics.KeyType, "relay"))
if err != nil {
log.Error(err)
return
}
for { for {
select { select {
case <-subscription.quit: case <-subscription.quit:
@ -330,6 +542,8 @@ func (node *WakuNode) Subscribe(topic *relay.Topic) (*Subscription, error) {
return return
} }
stats.Record(ctx, metrics.Messages.M(1))
wakuMessage := &pb.WakuMessage{} wakuMessage := &pb.WakuMessage{}
if err := proto.Unmarshal(msg.Data, wakuMessage); err != nil { if err := proto.Unmarshal(msg.Data, wakuMessage); err != nil {
log.Error("could not decode message", err) log.Error("could not decode message", err)
@ -348,7 +562,7 @@ func (node *WakuNode) Subscribe(topic *relay.Topic) (*Subscription, error) {
// Wrapper around WakuFilter.Subscribe // Wrapper around WakuFilter.Subscribe
// that adds a Filter object to node.filters // that adds a Filter object to node.filters
func (node *WakuNode) SubscribeFilter(ctx context.Context, request pb.FilterRequest, ch filter.ContentFilterChan) { func (node *WakuNode) SubscribeFilter(ctx context.Context, request pb.FilterRequest, ch filter.ContentFilterChan) error {
// Registers for messages that match a specific filter. Triggers the handler whenever a message is received. // Registers for messages that match a specific filter. Triggers the handler whenever a message is received.
// ContentFilterChan takes MessagePush structs // ContentFilterChan takes MessagePush structs
@ -360,20 +574,28 @@ func (node *WakuNode) SubscribeFilter(ctx context.Context, request pb.FilterRequ
log.Info("SubscribeFilter, request: ", request) log.Info("SubscribeFilter, request: ", request)
var id string var id string
var err error
if node.filter != nil { if node.filter == nil {
id, err := node.filter.Subscribe(ctx, request) return errors.New("WakuFilter is not set")
}
if id == "" || err != nil { id, err = node.filter.Subscribe(ctx, request)
// Failed to subscribe if id == "" || err != nil {
log.Error("remote subscription to filter failed", request) // Failed to subscribe
//waku_node_errors.inc(labelValues = ["subscribe_filter_failure"]) log.Error("remote subscription to filter failed", request)
id = string(protocol.GenerateRequestId()) //waku_node_errors.inc(labelValues = ["subscribe_filter_failure"])
} return err
} }
// Register handler for filter, whether remote subscription succeeded or not // Register handler for filter, whether remote subscription succeeded or not
node.filters[id] = filter.Filter{ContentFilters: request.ContentFilters, Chan: ch} node.filters[id] = filter.Filter{
Topic: request.Topic,
ContentFilters: request.ContentFilters,
Chan: ch,
}
return nil
} }
func (node *WakuNode) UnsubscribeFilter(ctx context.Context, request pb.FilterRequest) { func (node *WakuNode) UnsubscribeFilter(ctx context.Context, request pb.FilterRequest) {
@ -416,24 +638,27 @@ func (node *WakuNode) UnsubscribeFilter(ctx context.Context, request pb.FilterRe
func (node *WakuNode) Publish(ctx context.Context, message *pb.WakuMessage, topic *relay.Topic) ([]byte, error) { func (node *WakuNode) Publish(ctx context.Context, message *pb.WakuMessage, topic *relay.Topic) ([]byte, error) {
if node.relay == nil { if node.relay == nil {
return nil, errors.New("WakuRelay hasn't been set.") return nil, errors.New("WakuRelay hasn't been set")
} }
if message == nil { if message == nil {
return nil, errors.New("message can't be null") return nil, errors.New("message can't be null")
} }
if node.lightPush != nil {
return node.LightPush(ctx, message, topic)
}
hash, err := node.relay.Publish(ctx, message, topic) hash, err := node.relay.Publish(ctx, message, topic)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return hash, nil return hash, nil
} }
func (node *WakuNode) LightPush(ctx context.Context, message *pb.WakuMessage, topic *relay.Topic, opts ...lightpush.LightPushOption) ([]byte, error) { func (node *WakuNode) LightPush(ctx context.Context, message *pb.WakuMessage, topic *relay.Topic, opts ...lightpush.LightPushOption) ([]byte, error) {
if node.lightPush == nil { if node.lightPush == nil {
return nil, errors.New("WakuLightPush hasn't been set.") return nil, errors.New("WakuLightPush hasn't been set")
} }
if message == nil { if message == nil {
@ -495,3 +720,25 @@ func (w *WakuNode) ClosePeerById(id peer.ID) error {
func (w *WakuNode) PeerCount() int { func (w *WakuNode) PeerCount() int {
return len(w.host.Network().Peers()) return len(w.host.Network().Peers())
} }
func (w *WakuNode) startKeepAlive(t time.Duration) {
log.Info("Setting up ping protocol with duration of", t)
w.ping = ping.NewPingService(w.host)
ticker := time.NewTicker(t)
go func() {
for {
select {
case <-ticker.C:
for _, peer := range w.host.Network().Peers() {
log.Info("Pinging", peer)
w.ping.Ping(w.ctx, peer)
}
case <-w.quit:
ticker.Stop()
return
}
}
}()
}

View File

@ -3,6 +3,7 @@ package node
import ( import (
"crypto/ecdsa" "crypto/ecdsa"
"net" "net"
"time"
"github.com/libp2p/go-libp2p" "github.com/libp2p/go-libp2p"
connmgr "github.com/libp2p/go-libp2p-connmgr" connmgr "github.com/libp2p/go-libp2p-connmgr"
@ -14,6 +15,9 @@ import (
wakurelay "github.com/status-im/go-wakurelay-pubsub" wakurelay "github.com/status-im/go-wakurelay-pubsub"
) )
// Default clientId
const clientId string = "Go Waku v2 node"
type WakuNodeParameters struct { type WakuNodeParameters struct {
multiAddr []ma.Multiaddr multiAddr []ma.Multiaddr
privKey *crypto.PrivKey privKey *crypto.PrivKey
@ -28,7 +32,11 @@ type WakuNodeParameters struct {
store *store.WakuStore store *store.WakuStore
filter *filter.WakuFilter filter *filter.WakuFilter
keepAliveInterval time.Duration
enableLightPush bool enableLightPush bool
connStatusChan chan ConnStatus
} }
type WakuNodeOption func(*WakuNodeParameters) error type WakuNodeOption func(*WakuNodeParameters) error
@ -130,9 +138,24 @@ func WithLightPush() WakuNodeOption {
} }
} }
func WithKeepAlive(t time.Duration) WakuNodeOption {
return func(params *WakuNodeParameters) error {
params.keepAliveInterval = t
return nil
}
}
func WithConnStatusChan(connStatusChan chan ConnStatus) WakuNodeOption {
return func(params *WakuNodeParameters) error {
params.connStatusChan = connStatusChan
return nil
}
}
// Default options used in the libp2p node // Default options used in the libp2p node
var DefaultLibP2POptions = []libp2p.Option{ var DefaultLibP2POptions = []libp2p.Option{
libp2p.DefaultTransports, libp2p.DefaultTransports,
libp2p.UserAgent(clientId),
libp2p.NATPortMap(), // Attempt to open ports using uPNP for NATed hosts. libp2p.NATPortMap(), // Attempt to open ports using uPNP for NATed hosts.
libp2p.EnableNATService(), // TODO: is this needed?) libp2p.EnableNATService(), // TODO: is this needed?)
libp2p.ConnectionManager(connmgr.NewConnManager(200, 300, 0)), libp2p.ConnectionManager(connmgr.NewConnManager(200, 300, 0)),

View File

@ -6,24 +6,27 @@ import (
"fmt" "fmt"
logging "github.com/ipfs/go-log" logging "github.com/ipfs/go-log"
"github.com/libp2p/go-libp2p-core/event"
"github.com/libp2p/go-libp2p-core/host" "github.com/libp2p/go-libp2p-core/host"
"github.com/libp2p/go-libp2p-core/network" "github.com/libp2p/go-libp2p-core/network"
"github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peer"
libp2pProtocol "github.com/libp2p/go-libp2p-core/protocol" libp2pProtocol "github.com/libp2p/go-libp2p-core/protocol"
peerstore "github.com/libp2p/go-libp2p-peerstore"
"github.com/libp2p/go-msgio/protoio" "github.com/libp2p/go-msgio/protoio"
ma "github.com/multiformats/go-multiaddr" "github.com/status-im/go-waku/waku/v2/metrics"
"github.com/status-im/go-waku/waku/v2/protocol" "github.com/status-im/go-waku/waku/v2/protocol"
"github.com/status-im/go-waku/waku/v2/protocol/pb" "github.com/status-im/go-waku/waku/v2/protocol/pb"
"github.com/status-im/go-waku/waku/v2/utils"
"go.opencensus.io/stats"
"go.opencensus.io/tag"
) )
var log = logging.Logger("wakufilter") var log = logging.Logger("wakufilter")
type ( type (
ContentFilterChan chan *pb.WakuMessage ContentFilterChan chan *protocol.Envelope
Filter struct { Filter struct {
Topic string
ContentFilters []*pb.FilterRequest_ContentFilter ContentFilters []*pb.FilterRequest_ContentFilter
Chan ContentFilterChan Chan ContentFilterChan
} }
@ -44,6 +47,7 @@ type (
subscribers []Subscriber subscribers []Subscriber
pushHandler MessagePushHandler pushHandler MessagePushHandler
MsgC chan *protocol.Envelope MsgC chan *protocol.Envelope
peerChan chan *event.EvtPeerConnectednessChanged
} }
) )
@ -63,11 +67,13 @@ const (
func (filters *Filters) Notify(msg *pb.WakuMessage, requestId string) { func (filters *Filters) Notify(msg *pb.WakuMessage, requestId string) {
for key, filter := range *filters { for key, filter := range *filters {
envelope := protocol.NewEnvelope(msg, filter.Topic)
// We do this because the key for the filter is set to the requestId received from the filter protocol. // We do this because the key for the filter is set to the requestId received from the filter protocol.
// This means we do not need to check the content filter explicitly as all MessagePushs already contain // This means we do not need to check the content filter explicitly as all MessagePushs already contain
// the requestId of the coresponding filter. // the requestId of the coresponding filter.
if requestId != "" && requestId == key { if requestId != "" && requestId == key {
filter.Chan <- msg filter.Chan <- envelope
continue continue
} }
@ -75,43 +81,13 @@ func (filters *Filters) Notify(msg *pb.WakuMessage, requestId string) {
// or we should not allow such filter to exist in the first place. // or we should not allow such filter to exist in the first place.
for _, contentFilter := range filter.ContentFilters { for _, contentFilter := range filter.ContentFilters {
if msg.ContentTopic == contentFilter.ContentTopic { if msg.ContentTopic == contentFilter.ContentTopic {
filter.Chan <- msg filter.Chan <- envelope
break break
} }
} }
} }
} }
func (wf *WakuFilter) selectPeer() *peer.ID {
// @TODO We need to be more stratigic about which peers we dial. Right now we just set one on the service.
// Ideally depending on the query and our set of peers we take a subset of ideal peers.
// This will require us to check for various factors such as:
// - which topics they track
// - latency?
// - default store peer?
// Selects the best peer for a given protocol
var peers peer.IDSlice
for _, peer := range wf.h.Peerstore().Peers() {
protocols, err := wf.h.Peerstore().SupportsProtocols(peer, string(WakuFilterProtocolId))
if err != nil {
log.Error("error obtaining the protocols supported by peers", err)
return nil
}
if len(protocols) > 0 {
peers = append(peers, peer)
}
}
if len(peers) >= 1 {
// TODO: proper heuristic here that compares peer scores and selects "best" one. For now the first peer for the given protocol is returned
return &peers[0]
}
return nil
}
func (wf *WakuFilter) onRequest(s network.Stream) { func (wf *WakuFilter) onRequest(s network.Stream) {
defer s.Close() defer s.Close()
@ -127,6 +103,8 @@ func (wf *WakuFilter) onRequest(s network.Stream) {
log.Info(fmt.Sprintf("%s: Received query from %s", s.Conn().LocalPeer(), s.Conn().RemotePeer())) log.Info(fmt.Sprintf("%s: Received query from %s", s.Conn().LocalPeer(), s.Conn().RemotePeer()))
stats.Record(wf.ctx, metrics.Messages.M(1))
if filterRPCRequest.Request != nil { if filterRPCRequest.Request != nil {
// We're on a full node. // We're on a full node.
// This is a filter request coming from a light node. // This is a filter request coming from a light node.
@ -134,6 +112,8 @@ func (wf *WakuFilter) onRequest(s network.Stream) {
subscriber := Subscriber{peer: string(s.Conn().RemotePeer()), requestId: filterRPCRequest.RequestId, filter: *filterRPCRequest.Request} subscriber := Subscriber{peer: string(s.Conn().RemotePeer()), requestId: filterRPCRequest.RequestId, filter: *filterRPCRequest.Request}
wf.subscribers = append(wf.subscribers, subscriber) wf.subscribers = append(wf.subscribers, subscriber)
log.Info("Full node, add a filter subscriber ", subscriber) log.Info("Full node, add a filter subscriber ", subscriber)
stats.Record(wf.ctx, metrics.FilterSubscriptions.M(int64(len(wf.subscribers))))
} else { } else {
peerId := string(s.Conn().RemotePeer()) peerId := string(s.Conn().RemotePeer())
log.Info("Full node, remove a filter subscriber ", peerId) log.Info("Full node, remove a filter subscriber ", peerId)
@ -174,6 +154,8 @@ func (wf *WakuFilter) onRequest(s network.Stream) {
} }
} }
} }
stats.Record(wf.ctx, metrics.FilterSubscriptions.M(int64(len(wf.subscribers))))
} }
} else if filterRPCRequest.Push != nil { } else if filterRPCRequest.Push != nil {
// We're on a light node. // We're on a light node.
@ -185,15 +167,41 @@ func (wf *WakuFilter) onRequest(s network.Stream) {
} }
func NewWakuFilter(ctx context.Context, host host.Host, handler MessagePushHandler) *WakuFilter { func (wf *WakuFilter) peerListener() {
for e := range wf.peerChan {
if e.Connectedness == network.NotConnected {
log.Info("Filter Notification received ", e.Peer)
i := 0
// Delete subscribers matching deleted peer
for _, s := range wf.subscribers {
if s.peer != string(e.Peer) {
wf.subscribers[i] = s
i++
}
}
log.Info("Filter, deleted subscribers: ", len(wf.subscribers)-i)
wf.subscribers = wf.subscribers[:i]
}
}
}
func NewWakuFilter(ctx context.Context, host host.Host, handler MessagePushHandler, peerChan chan *event.EvtPeerConnectednessChanged) *WakuFilter {
ctx, err := tag.New(ctx, tag.Insert(metrics.KeyType, "filter"))
if err != nil {
log.Error(err)
}
wf := new(WakuFilter) wf := new(WakuFilter)
wf.ctx = ctx wf.ctx = ctx
wf.MsgC = make(chan *protocol.Envelope) wf.MsgC = make(chan *protocol.Envelope)
wf.h = host wf.h = host
wf.pushHandler = handler wf.pushHandler = handler
wf.peerChan = peerChan
wf.h.SetStreamHandler(WakuFilterProtocolId, wf.onRequest) wf.h.SetStreamHandler(WakuFilterProtocolId, wf.onRequest)
go wf.FilterListener() go wf.FilterListener()
go wf.peerListener()
return wf return wf
} }
@ -203,8 +211,6 @@ func (wf *WakuFilter) FilterListener() {
// This function is invoked for each message received // This function is invoked for each message received
// on the full node in context of Waku2-Filter // on the full node in context of Waku2-Filter
handle := func(envelope *protocol.Envelope) error { // async handle := func(envelope *protocol.Envelope) error { // async
// trace "handle WakuFilter subscription", topic=topic, msg=msg
msg := envelope.Message() msg := envelope.Message()
topic := envelope.PubsubTopic() topic := envelope.PubsubTopic()
// Each subscriber is a light node that earlier on invoked // Each subscriber is a light node that earlier on invoked
@ -251,25 +257,12 @@ func (wf *WakuFilter) FilterListener() {
} }
// TODO Remove code duplication
func (wf *WakuFilter) AddPeer(p peer.ID, addrs []ma.Multiaddr) error {
for _, addr := range addrs {
wf.h.Peerstore().AddAddr(p, addr, peerstore.PermanentAddrTTL)
}
err := wf.h.Peerstore().AddProtocols(p, string(WakuFilterProtocolId))
if err != nil {
return err
}
return nil
}
// Having a FilterRequest struct, // Having a FilterRequest struct,
// select a peer with filter support, dial it, // select a peer with filter support, dial it,
// and submit FilterRequest wrapped in FilterRPC // and submit FilterRequest wrapped in FilterRPC
func (wf *WakuFilter) Subscribe(ctx context.Context, request pb.FilterRequest) (string, error) { //.async, gcsafe.} { func (wf *WakuFilter) Subscribe(ctx context.Context, request pb.FilterRequest) (string, error) { //.async, gcsafe.} {
peer := wf.selectPeer() peer, err := utils.SelectPeer(wf.h, string(WakuFilterProtocolId))
if err == nil {
if peer != nil {
conn, err := wf.h.NewStream(ctx, *peer, WakuFilterProtocolId) conn, err := wf.h.NewStream(ctx, *peer, WakuFilterProtocolId)
if conn != nil { if conn != nil {
@ -287,6 +280,8 @@ func (wf *WakuFilter) Subscribe(ctx context.Context, request pb.FilterRequest) (
//waku_filter_errors.inc(labelValues = [dialFailure]) //waku_filter_errors.inc(labelValues = [dialFailure])
return "", err return "", err
} }
} else {
log.Info("Error selecting peer: ", err)
} }
return "", nil return "", nil
@ -294,9 +289,8 @@ func (wf *WakuFilter) Subscribe(ctx context.Context, request pb.FilterRequest) (
func (wf *WakuFilter) Unsubscribe(ctx context.Context, request pb.FilterRequest) { func (wf *WakuFilter) Unsubscribe(ctx context.Context, request pb.FilterRequest) {
// @TODO: NO REAL REASON TO GENERATE REQUEST ID FOR UNSUBSCRIBE OTHER THAN CREATING SANE-LOOKING RPC. // @TODO: NO REAL REASON TO GENERATE REQUEST ID FOR UNSUBSCRIBE OTHER THAN CREATING SANE-LOOKING RPC.
peer := wf.selectPeer() peer, err := utils.SelectPeer(wf.h, string(WakuFilterProtocolId))
if err == nil {
if peer != nil {
conn, err := wf.h.NewStream(ctx, *peer, WakuFilterProtocolId) conn, err := wf.h.NewStream(ctx, *peer, WakuFilterProtocolId)
if conn != nil { if conn != nil {
@ -312,5 +306,7 @@ func (wf *WakuFilter) Unsubscribe(ctx context.Context, request pb.FilterRequest)
log.Error("failed to connect to remote peer", err) log.Error("failed to connect to remote peer", err)
//waku_filter_errors.inc(labelValues = [dialFailure]) //waku_filter_errors.inc(labelValues = [dialFailure])
} }
} else {
log.Info("Error selecting peer: ", err)
} }
} }

View File

@ -10,20 +10,17 @@ import (
"github.com/libp2p/go-libp2p-core/host" "github.com/libp2p/go-libp2p-core/host"
"github.com/libp2p/go-libp2p-core/network" "github.com/libp2p/go-libp2p-core/network"
"github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peer"
"github.com/libp2p/go-libp2p-core/peerstore"
libp2pProtocol "github.com/libp2p/go-libp2p-core/protocol" libp2pProtocol "github.com/libp2p/go-libp2p-core/protocol"
"github.com/libp2p/go-msgio/protoio" "github.com/libp2p/go-msgio/protoio"
ma "github.com/multiformats/go-multiaddr"
"github.com/status-im/go-waku/waku/v2/protocol" "github.com/status-im/go-waku/waku/v2/protocol"
"github.com/status-im/go-waku/waku/v2/protocol/relay"
"github.com/status-im/go-waku/waku/v2/protocol/pb" "github.com/status-im/go-waku/waku/v2/protocol/pb"
"github.com/status-im/go-waku/waku/v2/protocol/relay"
utils "github.com/status-im/go-waku/waku/v2/utils"
) )
var log = logging.Logger("waku_lightpush") var log = logging.Logger("waku_lightpush")
const WakuLightPushProtocolId = libp2pProtocol.ID("/vac/waku/lightpush/2.0.0-alpha1") const WakuLightPushProtocolId = libp2pProtocol.ID("/vac/waku/lightpush/2.0.0-beta1")
var ( var (
ErrNoPeersAvailable = errors.New("no suitable remote peers") ErrNoPeersAvailable = errors.New("no suitable remote peers")
@ -62,7 +59,7 @@ func (wakuLP *WakuLightPush) onRequest(s network.Stream) {
return return
} }
log.Info(fmt.Sprintf("%s: Received query from %s", s.Conn().LocalPeer(), s.Conn().RemotePeer())) log.Info(fmt.Sprintf("%s: lightpush message received from %s", s.Conn().LocalPeer(), s.Conn().RemotePeer()))
if requestPushRPC.Query != nil { if requestPushRPC.Query != nil {
log.Info("lightpush push request") log.Info("lightpush push request")
@ -79,10 +76,10 @@ func (wakuLP *WakuLightPush) onRequest(s network.Stream) {
response.Info = "Could not publish message" response.Info = "Could not publish message"
} else { } else {
response.IsSuccess = true response.IsSuccess = true
response.Info = "Totally" response.Info = "Totally" // TODO: ask about this
} }
} else { } else {
log.Debug("No relay protocol present, unsuccessful push") log.Debug("no relay protocol present, unsuccessful push")
response.IsSuccess = false response.IsSuccess = false
response.Info = "No relay protocol" response.Info = "No relay protocol"
} }
@ -96,7 +93,7 @@ func (wakuLP *WakuLightPush) onRequest(s network.Stream) {
log.Error("error writing response", err) log.Error("error writing response", err)
s.Reset() s.Reset()
} else { } else {
log.Info(fmt.Sprintf("%s: Response sent to %s", s.Conn().LocalPeer().String(), s.Conn().RemotePeer().String())) log.Info(fmt.Sprintf("%s: response sent to %s", s.Conn().LocalPeer().String(), s.Conn().RemotePeer().String()))
} }
} }
@ -109,41 +106,6 @@ func (wakuLP *WakuLightPush) onRequest(s network.Stream) {
} }
} }
// TODO: AddPeer and selectPeer are duplicated in wakustore too. Refactor this code
func (wakuLP *WakuLightPush) AddPeer(p peer.ID, addrs []ma.Multiaddr) error {
for _, addr := range addrs {
wakuLP.h.Peerstore().AddAddr(p, addr, peerstore.PermanentAddrTTL)
}
err := wakuLP.h.Peerstore().AddProtocols(p, string(WakuLightPushProtocolId))
if err != nil {
return err
}
return nil
}
func (wakuLP *WakuLightPush) selectPeer() *peer.ID {
var peers peer.IDSlice
for _, peer := range wakuLP.h.Peerstore().Peers() {
protocols, err := wakuLP.h.Peerstore().SupportsProtocols(peer, string(WakuLightPushProtocolId))
if err != nil {
log.Error("error obtaining the protocols supported by peers", err)
return nil
}
if len(protocols) > 0 {
peers = append(peers, peer)
}
}
if len(peers) >= 1 {
// TODO: proper heuristic here that compares peer scores and selects "best" one. For now the first peer for the given protocol is returned
return &peers[0]
}
return nil
}
type LightPushParameters struct { type LightPushParameters struct {
selectedPeer peer.ID selectedPeer peer.ID
requestId []byte requestId []byte
@ -161,8 +123,12 @@ func WithPeer(p peer.ID) LightPushOption {
func WithAutomaticPeerSelection() LightPushOption { func WithAutomaticPeerSelection() LightPushOption {
return func(params *LightPushParameters) { return func(params *LightPushParameters) {
p := params.lp.selectPeer() p, err := utils.SelectPeer(params.lp.h, string(WakuLightPushProtocolId))
params.selectedPeer = *p if err == nil {
params.selectedPeer = *p
} else {
log.Info("Error selecting peer: ", err)
}
} }
} }
@ -187,6 +153,7 @@ func DefaultOptions() []LightPushOption {
func (wakuLP *WakuLightPush) Request(ctx context.Context, req *pb.PushRequest, opts ...LightPushOption) (*pb.PushResponse, error) { func (wakuLP *WakuLightPush) Request(ctx context.Context, req *pb.PushRequest, opts ...LightPushOption) (*pb.PushResponse, error) {
params := new(LightPushParameters) params := new(LightPushParameters)
params.lp = wakuLP
optList := DefaultOptions() optList := DefaultOptions()
optList = append(optList, opts...) optList = append(optList, opts...)

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,8 @@ import "waku_message.proto";
message Index { message Index {
bytes digest = 1; bytes digest = 1;
double receivedTime = 2; double receiverTime = 2;
double senderTime = 3;
} }
message PagingInfo { message PagingInfo {

View File

@ -13,23 +13,25 @@ import (
"time" "time"
logging "github.com/ipfs/go-log" logging "github.com/ipfs/go-log"
"github.com/libp2p/go-libp2p-core/event"
"github.com/libp2p/go-libp2p-core/host" "github.com/libp2p/go-libp2p-core/host"
"github.com/libp2p/go-libp2p-core/network" "github.com/libp2p/go-libp2p-core/network"
"github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peer"
"github.com/libp2p/go-libp2p-core/peerstore"
libp2pProtocol "github.com/libp2p/go-libp2p-core/protocol" libp2pProtocol "github.com/libp2p/go-libp2p-core/protocol"
"github.com/libp2p/go-msgio/protoio" "github.com/libp2p/go-msgio/protoio"
"go.opencensus.io/stats"
"go.opencensus.io/tag"
ma "github.com/multiformats/go-multiaddr" "github.com/status-im/go-waku/waku/v2/metrics"
"github.com/status-im/go-waku/waku/v2/protocol" "github.com/status-im/go-waku/waku/v2/protocol"
"github.com/status-im/go-waku/waku/v2/protocol/pb" "github.com/status-im/go-waku/waku/v2/protocol/pb"
"github.com/status-im/go-waku/waku/v2/utils"
) )
var log = logging.Logger("wakustore") var log = logging.Logger("wakustore")
const WakuStoreProtocolId = libp2pProtocol.ID("/vac/waku/store/2.0.0-beta3") const WakuStoreProtocolId = libp2pProtocol.ID("/vac/waku/store/2.0.0-beta3")
const MaxPageSize = 100 // Maximum number of waku messages in each page const MaxPageSize = 100 // Maximum number of waku messages in each page
const ConnectionTimeout = 10 * time.Second
const DefaultContentTopic = "/waku/2/default-content/proto" const DefaultContentTopic = "/waku/2/default-content/proto"
var ( var (
@ -180,8 +182,15 @@ func (w *WakuStore) FindMessages(query *pb.HistoryQuery) *pb.HistoryResponse {
return result return result
} }
type StoredMessage struct {
ID []byte
PubsubTopic string
ReceiverTime int64
Message *pb.WakuMessage
}
type MessageProvider interface { type MessageProvider interface {
GetAll() ([]*protocol.Envelope, error) GetAll() ([]StoredMessage, error)
Put(cursor *pb.Index, pubsubTopic string, message *pb.WakuMessage) error Put(cursor *pb.Index, pubsubTopic string, message *pb.WakuMessage) error
Stop() Stop()
} }
@ -193,13 +202,18 @@ type IndexedWakuMessage struct {
} }
type WakuStore struct { type WakuStore struct {
MsgC chan *protocol.Envelope ctx context.Context
messages []IndexedWakuMessage MsgC chan *protocol.Envelope
messages []IndexedWakuMessage
messageSet map[[32]byte]struct{}
messagesMutex sync.Mutex messagesMutex sync.Mutex
storeMsgs bool storeMsgs bool
msgProvider MessageProvider msgProvider MessageProvider
h host.Host h host.Host
peerChan chan *event.EvtPeerConnectednessChanged
} }
func NewWakuStore(shouldStoreMessages bool, p MessageProvider) *WakuStore { func NewWakuStore(shouldStoreMessages bool, p MessageProvider) *WakuStore {
@ -215,8 +229,18 @@ func (store *WakuStore) SetMsgProvider(p MessageProvider) {
store.msgProvider = p store.msgProvider = p
} }
func (store *WakuStore) Start(h host.Host) { func (store *WakuStore) peerListener() {
for e := range store.peerChan {
if e.Connectedness == network.NotConnected {
log.Info("Notification received ", e.Peer)
}
}
}
func (store *WakuStore) Start(ctx context.Context, h host.Host, peerChan chan *event.EvtPeerConnectednessChanged) {
store.h = h store.h = h
store.ctx = ctx
store.peerChan = peerChan
if !store.storeMsgs { if !store.storeMsgs {
log.Info("Store protocol started (messages aren't stored)") log.Info("Store protocol started (messages aren't stored)")
@ -225,31 +249,48 @@ func (store *WakuStore) Start(h host.Host) {
store.h.SetStreamHandler(WakuStoreProtocolId, store.onRequest) store.h.SetStreamHandler(WakuStoreProtocolId, store.onRequest)
go store.storeIncomingMessages() go store.storeIncomingMessages(ctx)
if store.msgProvider == nil { if store.msgProvider == nil {
log.Info("Store protocol started (no message provider)") log.Info("Store protocol started (no message provider)")
return return
} }
envelopes, err := store.msgProvider.GetAll() storedMessages, err := store.msgProvider.GetAll()
if err != nil { if err != nil {
log.Error("could not load DBProvider messages") log.Error("could not load DBProvider messages")
stats.RecordWithTags(ctx, []tag.Mutator{tag.Insert(metrics.KeyStoreErrorType, "store_load_failure")}, metrics.Errors.M(1))
return return
} }
for _, env := range envelopes { for _, storedMessage := range storedMessages {
idx, err := computeIndex(env.Message()) idx := &pb.Index{
if err != nil { Digest: storedMessage.ID,
log.Error("could not calculate message index", err) ReceiverTime: float64(storedMessage.ReceiverTime),
continue
} }
store.messages = append(store.messages, IndexedWakuMessage{msg: env.Message(), index: idx, pubsubTopic: env.PubsubTopic()})
store.storeMessageWithIndex(storedMessage.PubsubTopic, idx, storedMessage.Message)
stats.RecordWithTags(ctx, []tag.Mutator{tag.Insert(metrics.KeyType, "stored")}, metrics.StoreMessages.M(int64(len(store.messages))))
} }
go store.peerListener()
log.Info("Store protocol started") log.Info("Store protocol started")
} }
func (store *WakuStore) storeMessageWithIndex(pubsubTopic string, idx *pb.Index, msg *pb.WakuMessage) {
var k [32]byte
copy(k[:], idx.Digest)
if _, ok := store.messageSet[k]; ok {
return
}
store.messageSet[k] = struct{}{}
store.messages = append(store.messages, IndexedWakuMessage{msg: msg, index: idx, pubsubTopic: pubsubTopic})
}
func (store *WakuStore) storeMessage(pubSubTopic string, msg *pb.WakuMessage) { func (store *WakuStore) storeMessage(pubSubTopic string, msg *pb.WakuMessage) {
index, err := computeIndex(msg) index, err := computeIndex(msg)
if err != nil { if err != nil {
@ -258,21 +299,26 @@ func (store *WakuStore) storeMessage(pubSubTopic string, msg *pb.WakuMessage) {
} }
store.messagesMutex.Lock() store.messagesMutex.Lock()
store.messages = append(store.messages, IndexedWakuMessage{msg: msg, index: index, pubsubTopic: pubSubTopic}) defer store.messagesMutex.Unlock()
store.messagesMutex.Unlock()
store.storeMessageWithIndex(pubSubTopic, index, msg)
if store.msgProvider == nil { if store.msgProvider == nil {
return return
} }
err = store.msgProvider.Put(index, pubSubTopic, msg) // Should the index be stored? err = store.msgProvider.Put(index, pubSubTopic, msg) // Should the index be stored?
if err != nil { if err != nil {
log.Error("could not store message", err) log.Error("could not store message", err)
stats.RecordWithTags(store.ctx, []tag.Mutator{tag.Insert(metrics.KeyStoreErrorType, "store_failure")}, metrics.Errors.M(1))
return return
} }
stats.RecordWithTags(store.ctx, []tag.Mutator{tag.Insert(metrics.KeyType, "stored")}, metrics.StoreMessages.M(int64(len(store.messages))))
} }
func (store *WakuStore) storeIncomingMessages() { func (store *WakuStore) storeIncomingMessages(ctx context.Context) {
for envelope := range store.MsgC { for envelope := range store.MsgC {
store.storeMessage(envelope.PubsubTopic(), envelope.Message()) store.storeMessage(envelope.PubsubTopic(), envelope.Message())
} }
@ -289,6 +335,7 @@ func (store *WakuStore) onRequest(s network.Stream) {
err := reader.ReadMsg(historyRPCRequest) err := reader.ReadMsg(historyRPCRequest)
if err != nil { if err != nil {
log.Error("error reading request", err) log.Error("error reading request", err)
stats.RecordWithTags(store.ctx, []tag.Mutator{tag.Insert(metrics.KeyStoreErrorType, "decodeRPCFailure")}, metrics.Errors.M(1))
return return
} }
@ -315,7 +362,8 @@ func computeIndex(msg *pb.WakuMessage) (*pb.Index, error) {
digest := sha256.Sum256(data) digest := sha256.Sum256(data)
return &pb.Index{ return &pb.Index{
Digest: digest[:], Digest: digest[:],
ReceivedTime: float64(time.Now().UnixNano()), ReceiverTime: float64(time.Now().UnixNano()),
SenderTime: msg.Timestamp,
}, nil }, nil
} }
@ -325,10 +373,10 @@ func indexComparison(x, y *pb.Index) int {
// returns -1 if x < y // returns -1 if x < y
// returns 1 if x > y // returns 1 if x > y
var timecmp int = 0 // TODO: ask waku team why Index ReceivedTime is is float? var timecmp int = 0
if x.ReceivedTime > y.ReceivedTime { if x.SenderTime > y.SenderTime {
timecmp = 1 timecmp = 1
} else if x.ReceivedTime < y.ReceivedTime { } else if x.SenderTime < y.SenderTime {
timecmp = -1 timecmp = -1
} }
@ -352,58 +400,16 @@ func findIndex(msgList []IndexedWakuMessage, index *pb.Index) int {
// returns the position of an IndexedWakuMessage in msgList whose index value matches the given index // returns the position of an IndexedWakuMessage in msgList whose index value matches the given index
// returns -1 if no match is found // returns -1 if no match is found
for i, indexedWakuMessage := range msgList { for i, indexedWakuMessage := range msgList {
if bytes.Compare(indexedWakuMessage.index.Digest, index.Digest) == 0 && indexedWakuMessage.index.ReceivedTime == index.ReceivedTime { if bytes.Equal(indexedWakuMessage.index.Digest, index.Digest) && indexedWakuMessage.index.ReceiverTime == index.ReceiverTime {
return i return i
} }
} }
return -1 return -1
} }
func (store *WakuStore) AddPeer(p peer.ID, addrs []ma.Multiaddr) error {
for _, addr := range addrs {
store.h.Peerstore().AddAddr(p, addr, peerstore.PermanentAddrTTL)
}
err := store.h.Peerstore().AddProtocols(p, string(WakuStoreProtocolId))
if err != nil {
return err
}
return nil
}
func (store *WakuStore) selectPeer() *peer.ID {
// @TODO We need to be more stratigic about which peers we dial. Right now we just set one on the service.
// Ideally depending on the query and our set of peers we take a subset of ideal peers.
// This will require us to check for various factors such as:
// - which topics they track
// - latency?
// - default store peer?
// Selects the best peer for a given protocol
var peers peer.IDSlice
for _, peer := range store.h.Peerstore().Peers() {
protocols, err := store.h.Peerstore().SupportsProtocols(peer, string(WakuStoreProtocolId))
if err != nil {
log.Error("error obtaining the protocols supported by peers", err)
return nil
}
if len(protocols) > 0 {
peers = append(peers, peer)
}
}
if len(peers) >= 1 {
// TODO: proper heuristic here that compares peer scores and selects "best" one. For now the first peer for the given protocol is returned
return &peers[0]
}
return nil
}
type HistoryRequestParameters struct { type HistoryRequestParameters struct {
selectedPeer peer.ID selectedPeer peer.ID
requestId []byte requestId []byte
timeout *time.Duration
cursor *pb.Index cursor *pb.Index
pageSize uint64 pageSize uint64
asc bool asc bool
@ -421,8 +427,12 @@ func WithPeer(p peer.ID) HistoryRequestOption {
func WithAutomaticPeerSelection() HistoryRequestOption { func WithAutomaticPeerSelection() HistoryRequestOption {
return func(params *HistoryRequestParameters) { return func(params *HistoryRequestParameters) {
p := params.s.selectPeer() p, err := utils.SelectPeer(params.s.h, string(WakuStoreProtocolId))
params.selectedPeer = *p if err == nil {
params.selectedPeer = *p
} else {
log.Info("Error selecting peer: ", err)
}
} }
} }
@ -484,9 +494,12 @@ func (store *WakuStore) queryFrom(ctx context.Context, q *pb.HistoryQuery, selec
err = reader.ReadMsg(historyResponseRPC) err = reader.ReadMsg(historyResponseRPC)
if err != nil { if err != nil {
log.Error("could not read response", err) log.Error("could not read response", err)
stats.RecordWithTags(store.ctx, []tag.Mutator{tag.Insert(metrics.KeyStoreErrorType, "decodeRPCFailure")}, metrics.Errors.M(1))
return nil, err return nil, err
} }
stats.RecordWithTags(store.ctx, []tag.Mutator{tag.Insert(metrics.KeyType, "retrieved")}, metrics.StoreMessages.M(int64(len(store.messages))))
return historyResponseRPC.Response, nil return historyResponseRPC.Response, nil
} }
@ -555,7 +568,7 @@ func (store *WakuStore) findLastSeen() float64 {
// if no peerList is passed, one of the peers in the underlying peer manager unit of the store protocol is picked randomly to fetch the history from. The history gets fetched successfully if the dialed peer has been online during the queried time window. // if no peerList is passed, one of the peers in the underlying peer manager unit of the store protocol is picked randomly to fetch the history from. The history gets fetched successfully if the dialed peer has been online during the queried time window.
// the resume proc returns the number of retrieved messages if no error occurs, otherwise returns the error string // the resume proc returns the number of retrieved messages if no error occurs, otherwise returns the error string
func (store *WakuStore) Resume(ctx context.Context, pubsubTopic string, peerList []peer.ID) (int, error) { func (store *WakuStore) Resume(pubsubTopic string, peerList []peer.ID) (int, error) {
currentTime := float64(time.Now().UnixNano()) currentTime := float64(time.Now().UnixNano())
lastSeenTime := store.findLastSeen() lastSeenTime := store.findLastSeen()
@ -577,20 +590,20 @@ func (store *WakuStore) Resume(ctx context.Context, pubsubTopic string, peerList
var response *pb.HistoryResponse var response *pb.HistoryResponse
if len(peerList) > 0 { if len(peerList) > 0 {
var err error var err error
response, err = store.queryLoop(ctx, rpc, peerList) response, err = store.queryLoop(store.ctx, rpc, peerList)
if err != nil { if err != nil {
log.Error("failed to resume history", err) log.Error("failed to resume history", err)
return -1, ErrFailedToResumeHistory return -1, ErrFailedToResumeHistory
} }
} else { } else {
p := store.selectPeer() p, err := utils.SelectPeer(store.h, string(WakuStoreProtocolId))
if p == nil { if err != nil {
log.Info("Error selecting peer: ", err)
return -1, ErrNoPeersAvailable return -1, ErrNoPeersAvailable
} }
var err error response, err = store.queryFrom(store.ctx, rpc, *p, protocol.GenerateRequestId())
response, err = store.queryFrom(ctx, rpc, *p, protocol.GenerateRequestId())
if err != nil { if err != nil {
log.Error("failed to resume history", err) log.Error("failed to resume history", err)
return -1, ErrFailedToResumeHistory return -1, ErrFailedToResumeHistory

View File

View File

@ -0,0 +1,42 @@
package utils
import (
"errors"
logging "github.com/ipfs/go-log"
"github.com/libp2p/go-libp2p-core/host"
"github.com/libp2p/go-libp2p-core/peer"
)
var log = logging.Logger("utils")
func SelectPeer(host host.Host, protocolId string) (*peer.ID, error) {
// @TODO We need to be more strategic about which peers we dial. Right now we just set one on the service.
// Ideally depending on the query and our set of peers we take a subset of ideal peers.
// This will require us to check for various factors such as:
// - which topics they track
// - latency?
// - default store peer?
// Selects the best peer for a given protocol
var peers peer.IDSlice
for _, peer := range host.Peerstore().Peers() {
protocols, err := host.Peerstore().SupportsProtocols(peer, protocolId)
if err != nil {
log.Error("error obtaining the protocols supported by peers", err)
return nil, err
}
if len(protocols) > 0 {
peers = append(peers, peer)
}
}
if len(peers) >= 1 {
// TODO: proper heuristic here that compares peer scores and selects "best" one. For now the first peer for the given protocol is returned
return &peers[0], nil
}
return nil, errors.New("No suitable peers found")
}

View File

@ -14,6 +14,7 @@ import (
"github.com/libp2p/go-libp2p-core/crypto" "github.com/libp2p/go-libp2p-core/crypto"
"github.com/libp2p/go-libp2p-core/discovery" "github.com/libp2p/go-libp2p-core/discovery"
"github.com/libp2p/go-libp2p-core/event"
"github.com/libp2p/go-libp2p-core/host" "github.com/libp2p/go-libp2p-core/host"
"github.com/libp2p/go-libp2p-core/network" "github.com/libp2p/go-libp2p-core/network"
"github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peer"
@ -472,6 +473,8 @@ func WithMaxMessageSize(maxMessageSize int) Option {
// processLoop handles all inputs arriving on the channels // processLoop handles all inputs arriving on the channels
func (p *PubSub) processLoop(ctx context.Context) { func (p *PubSub) processLoop(ctx context.Context) {
em, _ := p.host.EventBus().Emitter(new(event.EvtPeerConnectednessChanged))
defer func() { defer func() {
// Clean up go routines. // Clean up go routines.
for _, ch := range p.peers { for _, ch := range p.peers {
@ -479,6 +482,7 @@ func (p *PubSub) processLoop(ctx context.Context) {
} }
p.peers = nil p.peers = nil
p.topics = nil p.topics = nil
em.Close() // MUST call this after being done with the emitter
}() }()
for { for {
@ -499,6 +503,8 @@ func (p *PubSub) processLoop(ctx context.Context) {
go p.handleNewPeer(ctx, pid, messages) go p.handleNewPeer(ctx, pid, messages)
p.peers[pid] = messages p.peers[pid] = messages
em.Emit(event.EvtPeerConnectednessChanged{Peer: pid, Connectedness: network.Connected})
case s := <-p.newPeerStream: case s := <-p.newPeerStream:
pid := s.Conn().RemotePeer() pid := s.Conn().RemotePeer()
@ -520,6 +526,7 @@ func (p *PubSub) processLoop(ctx context.Context) {
case pid := <-p.newPeerError: case pid := <-p.newPeerError:
delete(p.peers, pid) delete(p.peers, pid)
em.Emit(event.EvtPeerConnectednessChanged{Peer: pid, Connectedness: network.NotConnected})
case pid := <-p.peerDead: case pid := <-p.peerDead:
ch, ok := p.peers[pid] ch, ok := p.peers[pid]
@ -549,6 +556,7 @@ func (p *PubSub) processLoop(ctx context.Context) {
} }
p.rt.RemovePeer(pid) p.rt.RemovePeer(pid)
em.Emit(event.EvtPeerConnectednessChanged{Peer: pid, Connectedness: network.NotConnected})
case treq := <-p.getTopics: case treq := <-p.getTopics:
var out []string var out []string

View File

@ -28,10 +28,10 @@ const (
// https://github.com/libp2p/specs/blob/master/pubsub/gossipsub/gossipsub-v1.1.md // https://github.com/libp2p/specs/blob/master/pubsub/gossipsub/gossipsub-v1.1.md
GossipSubID_v11 = protocol.ID("/meshsub/1.1.0") GossipSubID_v11 = protocol.ID("/meshsub/1.1.0")
// WakuRelayID_v200b2 is the protocol ID for version 2.0.0-beta2 of the WakuRelay protocol. // WakuRelayID_v200 is the protocol ID for version 2.0.0 of the WakuRelay protocol.
// See the spec for details about how v1.1.0 compares to v1.0.0: // See the spec for details about how v1.1.0 compares to v1.0.0:
// https://specs.vac.dev/specs/waku/v2/waku-relay // https://specs.vac.dev/specs/waku/v2/waku-relay
WakuRelayID_v200b2 = protocol.ID("/vac/waku/relay/2.0.0-beta2") WakuRelayID_v200 = protocol.ID("/vac/waku/relay/2.0.0")
) )
var ( var (
@ -419,7 +419,7 @@ type connectInfo struct {
} }
func (gs *WakuRelaySubRouter) Protocols() []protocol.ID { func (gs *WakuRelaySubRouter) Protocols() []protocol.ID {
return []protocol.ID{WakuRelayID_v200b2, GossipSubID_v11, GossipSubID_v10, FloodSubID} return []protocol.ID{WakuRelayID_v200, GossipSubID_v11, GossipSubID_v10, FloodSubID}
} }
func (gs *WakuRelaySubRouter) Attach(p *PubSub) { func (gs *WakuRelaySubRouter) Attach(p *PubSub) {
@ -1629,7 +1629,7 @@ func (gs *WakuRelaySubRouter) emitGossip(topic string, exclude map[peer.ID]struc
for p := range gs.p.topics[topic] { for p := range gs.p.topics[topic] {
_, inExclude := exclude[p] _, inExclude := exclude[p]
_, direct := gs.direct[p] _, direct := gs.direct[p]
if !inExclude && !direct && (gs.peers[p] == GossipSubID_v10 || gs.peers[p] == GossipSubID_v11 || gs.peers[p] == WakuRelayID_v200b2) && gs.score.Score(p) >= gs.gossipThreshold { if !inExclude && !direct && (gs.peers[p] == GossipSubID_v10 || gs.peers[p] == GossipSubID_v11 || gs.peers[p] == WakuRelayID_v200) && gs.score.Score(p) >= gs.gossipThreshold {
peers = append(peers, p) peers = append(peers, p)
} }
} }
@ -1797,7 +1797,7 @@ func (gs *WakuRelaySubRouter) getPeers(topic string, count int, filter func(peer
peers := make([]peer.ID, 0, len(tmap)) peers := make([]peer.ID, 0, len(tmap))
for p := range tmap { for p := range tmap {
if (gs.peers[p] == GossipSubID_v10 || gs.peers[p] == GossipSubID_v11 || gs.peers[p] == WakuRelayID_v200b2) && filter(p) { if (gs.peers[p] == GossipSubID_v10 || gs.peers[p] == GossipSubID_v11 || gs.peers[p] == WakuRelayID_v200) && filter(p) {
peers = append(peers, p) peers = append(peers, p)
} }
} }

View File

@ -15,6 +15,8 @@
package view package view
import "time"
// AggType represents the type of aggregation function used on a View. // AggType represents the type of aggregation function used on a View.
type AggType int type AggType int
@ -45,20 +47,20 @@ type Aggregation struct {
Type AggType // Type is the AggType of this Aggregation. Type AggType // Type is the AggType of this Aggregation.
Buckets []float64 // Buckets are the bucket endpoints if this Aggregation represents a distribution, see Distribution. Buckets []float64 // Buckets are the bucket endpoints if this Aggregation represents a distribution, see Distribution.
newData func() AggregationData newData func(time.Time) AggregationData
} }
var ( var (
aggCount = &Aggregation{ aggCount = &Aggregation{
Type: AggTypeCount, Type: AggTypeCount,
newData: func() AggregationData { newData: func(t time.Time) AggregationData {
return &CountData{} return &CountData{Start: t}
}, },
} }
aggSum = &Aggregation{ aggSum = &Aggregation{
Type: AggTypeSum, Type: AggTypeSum,
newData: func() AggregationData { newData: func(t time.Time) AggregationData {
return &SumData{} return &SumData{Start: t}
}, },
} }
) )
@ -103,8 +105,8 @@ func Distribution(bounds ...float64) *Aggregation {
Type: AggTypeDistribution, Type: AggTypeDistribution,
Buckets: bounds, Buckets: bounds,
} }
agg.newData = func() AggregationData { agg.newData = func(t time.Time) AggregationData {
return newDistributionData(agg) return newDistributionData(agg, t)
} }
return agg return agg
} }
@ -114,7 +116,7 @@ func Distribution(bounds ...float64) *Aggregation {
func LastValue() *Aggregation { func LastValue() *Aggregation {
return &Aggregation{ return &Aggregation{
Type: AggTypeLastValue, Type: AggTypeLastValue,
newData: func() AggregationData { newData: func(_ time.Time) AggregationData {
return &LastValueData{} return &LastValueData{}
}, },
} }

View File

@ -31,6 +31,7 @@ type AggregationData interface {
clone() AggregationData clone() AggregationData
equal(other AggregationData) bool equal(other AggregationData) bool
toPoint(t metricdata.Type, time time.Time) metricdata.Point toPoint(t metricdata.Type, time time.Time) metricdata.Point
StartTime() time.Time
} }
const epsilon = 1e-9 const epsilon = 1e-9
@ -40,6 +41,7 @@ const epsilon = 1e-9
// //
// Most users won't directly access count data. // Most users won't directly access count data.
type CountData struct { type CountData struct {
Start time.Time
Value int64 Value int64
} }
@ -50,7 +52,7 @@ func (a *CountData) addSample(_ float64, _ map[string]interface{}, _ time.Time)
} }
func (a *CountData) clone() AggregationData { func (a *CountData) clone() AggregationData {
return &CountData{Value: a.Value} return &CountData{Value: a.Value, Start: a.Start}
} }
func (a *CountData) equal(other AggregationData) bool { func (a *CountData) equal(other AggregationData) bool {
@ -59,7 +61,7 @@ func (a *CountData) equal(other AggregationData) bool {
return false return false
} }
return a.Value == a2.Value return a.Start.Equal(a2.Start) && a.Value == a2.Value
} }
func (a *CountData) toPoint(metricType metricdata.Type, t time.Time) metricdata.Point { func (a *CountData) toPoint(metricType metricdata.Type, t time.Time) metricdata.Point {
@ -71,11 +73,17 @@ func (a *CountData) toPoint(metricType metricdata.Type, t time.Time) metricdata.
} }
} }
// StartTime returns the start time of the data being aggregated by CountData.
func (a *CountData) StartTime() time.Time {
return a.Start
}
// SumData is the aggregated data for the Sum aggregation. // SumData is the aggregated data for the Sum aggregation.
// A sum aggregation processes data and sums up the recordings. // A sum aggregation processes data and sums up the recordings.
// //
// Most users won't directly access sum data. // Most users won't directly access sum data.
type SumData struct { type SumData struct {
Start time.Time
Value float64 Value float64
} }
@ -86,7 +94,7 @@ func (a *SumData) addSample(v float64, _ map[string]interface{}, _ time.Time) {
} }
func (a *SumData) clone() AggregationData { func (a *SumData) clone() AggregationData {
return &SumData{Value: a.Value} return &SumData{Value: a.Value, Start: a.Start}
} }
func (a *SumData) equal(other AggregationData) bool { func (a *SumData) equal(other AggregationData) bool {
@ -94,7 +102,7 @@ func (a *SumData) equal(other AggregationData) bool {
if !ok { if !ok {
return false return false
} }
return math.Pow(a.Value-a2.Value, 2) < epsilon return a.Start.Equal(a2.Start) && math.Pow(a.Value-a2.Value, 2) < epsilon
} }
func (a *SumData) toPoint(metricType metricdata.Type, t time.Time) metricdata.Point { func (a *SumData) toPoint(metricType metricdata.Type, t time.Time) metricdata.Point {
@ -108,6 +116,11 @@ func (a *SumData) toPoint(metricType metricdata.Type, t time.Time) metricdata.Po
} }
} }
// StartTime returns the start time of the data being aggregated by SumData.
func (a *SumData) StartTime() time.Time {
return a.Start
}
// DistributionData is the aggregated data for the // DistributionData is the aggregated data for the
// Distribution aggregation. // Distribution aggregation.
// //
@ -126,9 +139,10 @@ type DistributionData struct {
// an exemplar for the associated bucket, or nil. // an exemplar for the associated bucket, or nil.
ExemplarsPerBucket []*metricdata.Exemplar ExemplarsPerBucket []*metricdata.Exemplar
bounds []float64 // histogram distribution of the values bounds []float64 // histogram distribution of the values
Start time.Time
} }
func newDistributionData(agg *Aggregation) *DistributionData { func newDistributionData(agg *Aggregation, t time.Time) *DistributionData {
bucketCount := len(agg.Buckets) + 1 bucketCount := len(agg.Buckets) + 1
return &DistributionData{ return &DistributionData{
CountPerBucket: make([]int64, bucketCount), CountPerBucket: make([]int64, bucketCount),
@ -136,6 +150,7 @@ func newDistributionData(agg *Aggregation) *DistributionData {
bounds: agg.Buckets, bounds: agg.Buckets,
Min: math.MaxFloat64, Min: math.MaxFloat64,
Max: math.SmallestNonzeroFloat64, Max: math.SmallestNonzeroFloat64,
Start: t,
} }
} }
@ -226,7 +241,11 @@ func (a *DistributionData) equal(other AggregationData) bool {
return false return false
} }
} }
return a.Count == a2.Count && a.Min == a2.Min && a.Max == a2.Max && math.Pow(a.Mean-a2.Mean, 2) < epsilon && math.Pow(a.variance()-a2.variance(), 2) < epsilon return a.Start.Equal(a2.Start) &&
a.Count == a2.Count &&
a.Min == a2.Min &&
a.Max == a2.Max &&
math.Pow(a.Mean-a2.Mean, 2) < epsilon && math.Pow(a.variance()-a2.variance(), 2) < epsilon
} }
func (a *DistributionData) toPoint(metricType metricdata.Type, t time.Time) metricdata.Point { func (a *DistributionData) toPoint(metricType metricdata.Type, t time.Time) metricdata.Point {
@ -256,6 +275,11 @@ func (a *DistributionData) toPoint(metricType metricdata.Type, t time.Time) metr
} }
} }
// StartTime returns the start time of the data being aggregated by DistributionData.
func (a *DistributionData) StartTime() time.Time {
return a.Start
}
// LastValueData returns the last value recorded for LastValue aggregation. // LastValueData returns the last value recorded for LastValue aggregation.
type LastValueData struct { type LastValueData struct {
Value float64 Value float64
@ -291,3 +315,22 @@ func (l *LastValueData) toPoint(metricType metricdata.Type, t time.Time) metricd
panic("unsupported metricdata.Type") panic("unsupported metricdata.Type")
} }
} }
// StartTime returns an empty time value as start time is not recorded when using last value
// aggregation.
func (l *LastValueData) StartTime() time.Time {
return time.Time{}
}
// ClearStart clears the Start field from data if present. Useful for testing in cases where the
// start time will be nondeterministic.
func ClearStart(data AggregationData) {
switch data := data.(type) {
case *CountData:
data.Start = time.Time{}
case *SumData:
data.Start = time.Time{}
case *DistributionData:
data.Start = time.Time{}
}
}

View File

@ -35,7 +35,7 @@ type collector struct {
func (c *collector) addSample(s string, v float64, attachments map[string]interface{}, t time.Time) { func (c *collector) addSample(s string, v float64, attachments map[string]interface{}, t time.Time) {
aggregator, ok := c.signatures[s] aggregator, ok := c.signatures[s]
if !ok { if !ok {
aggregator = c.a.newData() aggregator = c.a.newData(t)
c.signatures[s] = aggregator c.signatures[s] = aggregator
} }
aggregator.addSample(v, attachments, t) aggregator.addSample(v, attachments, t)

View File

@ -119,20 +119,15 @@ func toLabelValues(row *Row, expectedKeys []metricdata.LabelKey) []metricdata.La
return labelValues return labelValues
} }
func rowToTimeseries(v *viewInternal, row *Row, now time.Time, startTime time.Time) *metricdata.TimeSeries { func rowToTimeseries(v *viewInternal, row *Row, now time.Time) *metricdata.TimeSeries {
return &metricdata.TimeSeries{ return &metricdata.TimeSeries{
Points: []metricdata.Point{row.Data.toPoint(v.metricDescriptor.Type, now)}, Points: []metricdata.Point{row.Data.toPoint(v.metricDescriptor.Type, now)},
LabelValues: toLabelValues(row, v.metricDescriptor.LabelKeys), LabelValues: toLabelValues(row, v.metricDescriptor.LabelKeys),
StartTime: startTime, StartTime: row.Data.StartTime(),
} }
} }
func viewToMetric(v *viewInternal, r *resource.Resource, now time.Time, startTime time.Time) *metricdata.Metric { func viewToMetric(v *viewInternal, r *resource.Resource, now time.Time) *metricdata.Metric {
if v.metricDescriptor.Type == metricdata.TypeGaugeInt64 ||
v.metricDescriptor.Type == metricdata.TypeGaugeFloat64 {
startTime = time.Time{}
}
rows := v.collectedRows() rows := v.collectedRows()
if len(rows) == 0 { if len(rows) == 0 {
return nil return nil
@ -140,7 +135,7 @@ func viewToMetric(v *viewInternal, r *resource.Resource, now time.Time, startTim
ts := []*metricdata.TimeSeries{} ts := []*metricdata.TimeSeries{}
for _, row := range rows { for _, row := range rows {
ts = append(ts, rowToTimeseries(v, row, now, startTime)) ts = append(ts, rowToTimeseries(v, row, now))
} }
m := &metricdata.Metric{ m := &metricdata.Metric{

View File

@ -41,9 +41,9 @@ type measureRef struct {
} }
type worker struct { type worker struct {
measures map[string]*measureRef measures map[string]*measureRef
views map[string]*viewInternal views map[string]*viewInternal
startTimes map[*viewInternal]time.Time viewStartTimes map[*viewInternal]time.Time
timer *time.Ticker timer *time.Ticker
c chan command c chan command
@ -244,13 +244,13 @@ func (w *worker) SetReportingPeriod(d time.Duration) {
// a single process. // a single process.
func NewMeter() Meter { func NewMeter() Meter {
return &worker{ return &worker{
measures: make(map[string]*measureRef), measures: make(map[string]*measureRef),
views: make(map[string]*viewInternal), views: make(map[string]*viewInternal),
startTimes: make(map[*viewInternal]time.Time), viewStartTimes: make(map[*viewInternal]time.Time),
timer: time.NewTicker(defaultReportingDuration), timer: time.NewTicker(defaultReportingDuration),
c: make(chan command, 1024), c: make(chan command, 1024),
quit: make(chan bool), quit: make(chan bool),
done: make(chan bool), done: make(chan bool),
exporters: make(map[Exporter]struct{}), exporters: make(map[Exporter]struct{}),
} }
@ -324,7 +324,7 @@ func (w *worker) tryRegisterView(v *View) (*viewInternal, error) {
return x, nil return x, nil
} }
w.views[vi.view.Name] = vi w.views[vi.view.Name] = vi
w.startTimes[vi] = time.Now() w.viewStartTimes[vi] = time.Now()
ref := w.getMeasureRef(vi.view.Measure.Name()) ref := w.getMeasureRef(vi.view.Measure.Name())
ref.views[vi] = struct{}{} ref.views[vi] = struct{}{}
return vi, nil return vi, nil
@ -334,7 +334,7 @@ func (w *worker) unregisterView(v *viewInternal) {
w.mu.Lock() w.mu.Lock()
defer w.mu.Unlock() defer w.mu.Unlock()
delete(w.views, v.view.Name) delete(w.views, v.view.Name)
delete(w.startTimes, v) delete(w.viewStartTimes, v)
if measure := w.measures[v.view.Measure.Name()]; measure != nil { if measure := w.measures[v.view.Measure.Name()]; measure != nil {
delete(measure.views, v) delete(measure.views, v)
} }
@ -347,7 +347,7 @@ func (w *worker) reportView(v *viewInternal) {
rows := v.collectedRows() rows := v.collectedRows()
viewData := &Data{ viewData := &Data{
View: v.view, View: v.view,
Start: w.startTimes[v], Start: w.viewStartTimes[v],
End: time.Now(), End: time.Now(),
Rows: rows, Rows: rows,
} }
@ -371,15 +371,7 @@ func (w *worker) toMetric(v *viewInternal, now time.Time) *metricdata.Metric {
return nil return nil
} }
var startTime time.Time return viewToMetric(v, w.r, now)
if v.metricDescriptor.Type == metricdata.TypeGaugeInt64 ||
v.metricDescriptor.Type == metricdata.TypeGaugeFloat64 {
startTime = time.Time{}
} else {
startTime = w.startTimes[v]
}
return viewToMetric(v, w.r, now, startTime)
} }
// Read reads all view data and returns them as metrics. // Read reads all view data and returns them as metrics.

14
vendor/modules.txt vendored
View File

@ -144,7 +144,7 @@ github.com/golang/groupcache/consistenthash
github.com/golang/groupcache/groupcachepb github.com/golang/groupcache/groupcachepb
github.com/golang/groupcache/lru github.com/golang/groupcache/lru
github.com/golang/groupcache/singleflight github.com/golang/groupcache/singleflight
# github.com/golang/mock v1.4.1 # github.com/golang/mock v1.4.4
github.com/golang/mock/gomock github.com/golang/mock/gomock
# github.com/golang/protobuf v1.5.2 # github.com/golang/protobuf v1.5.2
github.com/golang/protobuf/proto github.com/golang/protobuf/proto
@ -391,13 +391,13 @@ github.com/peterh/liner
github.com/pkg/errors github.com/pkg/errors
# github.com/pmezard/go-difflib v1.0.0 # github.com/pmezard/go-difflib v1.0.0
github.com/pmezard/go-difflib/difflib github.com/pmezard/go-difflib/difflib
# github.com/prometheus/client_golang v1.9.0 # github.com/prometheus/client_golang v1.11.0
github.com/prometheus/client_golang/prometheus github.com/prometheus/client_golang/prometheus
github.com/prometheus/client_golang/prometheus/internal github.com/prometheus/client_golang/prometheus/internal
github.com/prometheus/client_golang/prometheus/promhttp github.com/prometheus/client_golang/prometheus/promhttp
# github.com/prometheus/client_model v0.2.0 # github.com/prometheus/client_model v0.2.0
github.com/prometheus/client_model/go github.com/prometheus/client_model/go
# github.com/prometheus/common v0.18.0 # github.com/prometheus/common v0.29.0
github.com/prometheus/common/expfmt github.com/prometheus/common/expfmt
github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg
github.com/prometheus/common/model github.com/prometheus/common/model
@ -426,7 +426,8 @@ github.com/spacemonkeygo/spacelog
github.com/status-im/doubleratchet github.com/status-im/doubleratchet
# github.com/status-im/go-multiaddr-ethv4 v1.2.0 # github.com/status-im/go-multiaddr-ethv4 v1.2.0
github.com/status-im/go-multiaddr-ethv4 github.com/status-im/go-multiaddr-ethv4
# github.com/status-im/go-waku v0.0.0-20210624095504-4133155590da # github.com/status-im/go-waku v0.0.0-20210711181138-a2ff7f3df962
github.com/status-im/go-waku/waku/v2/metrics
github.com/status-im/go-waku/waku/v2/node github.com/status-im/go-waku/waku/v2/node
github.com/status-im/go-waku/waku/v2/protocol github.com/status-im/go-waku/waku/v2/protocol
github.com/status-im/go-waku/waku/v2/protocol/filter github.com/status-im/go-waku/waku/v2/protocol/filter
@ -434,7 +435,8 @@ github.com/status-im/go-waku/waku/v2/protocol/lightpush
github.com/status-im/go-waku/waku/v2/protocol/pb github.com/status-im/go-waku/waku/v2/protocol/pb
github.com/status-im/go-waku/waku/v2/protocol/relay github.com/status-im/go-waku/waku/v2/protocol/relay
github.com/status-im/go-waku/waku/v2/protocol/store github.com/status-im/go-waku/waku/v2/protocol/store
# github.com/status-im/go-wakurelay-pubsub v0.4.2 github.com/status-im/go-waku/waku/v2/utils
# github.com/status-im/go-wakurelay-pubsub v0.4.3-0.20210711180556-9afd35dadd3f
github.com/status-im/go-wakurelay-pubsub github.com/status-im/go-wakurelay-pubsub
github.com/status-im/go-wakurelay-pubsub/pb github.com/status-im/go-wakurelay-pubsub/pb
# github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969 # github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969
@ -521,7 +523,7 @@ github.com/xeipuuv/gojsonpointer
github.com/xeipuuv/gojsonreference github.com/xeipuuv/gojsonreference
# github.com/xeipuuv/gojsonschema v1.2.0 # github.com/xeipuuv/gojsonschema v1.2.0
github.com/xeipuuv/gojsonschema github.com/xeipuuv/gojsonschema
# go.opencensus.io v0.22.4 # go.opencensus.io v0.23.0
go.opencensus.io/internal/tagencoding go.opencensus.io/internal/tagencoding
go.opencensus.io/metric/metricdata go.opencensus.io/metric/metricdata
go.opencensus.io/metric/metricproducer go.opencensus.io/metric/metricproducer

View File

@ -526,8 +526,7 @@ func (w *Waku) Send(msg *pb.WakuMessage) ([]byte, error) {
return w.node.Publish(context.Background(), msg, nil) return w.node.Publish(context.Background(), msg, nil)
} }
func (w *Waku) Query(topics []types.TopicType, from uint64, to uint64, opts []store.HistoryRequestOption) error { func (w *Waku) Query(topics []types.TopicType, from uint64, to uint64, opts []store.HistoryRequestOption) (cursor *pb.Index, err error) {
// TODO: run into a go routine?
strTopics := make([]string, len(topics)) strTopics := make([]string, len(topics))
for i, t := range topics { for i, t := range topics {
strTopics[i] = t.String() strTopics[i] = t.String()
@ -536,14 +535,18 @@ func (w *Waku) Query(topics []types.TopicType, from uint64, to uint64, opts []st
result, err := w.node.Query(context.Background(), strTopics, float64(from), float64(to), opts...) result, err := w.node.Query(context.Background(), strTopics, float64(from), float64(to), opts...)
for _, msg := range result.Messages { for _, msg := range result.Messages {
envelope := wakuprotocol.NewEnvelope(msg, string(relay.DefaultWakuTopic)) // TODO: consider modifying go-waku to return envelopes instead of messages envelope := wakuprotocol.NewEnvelope(msg, string(relay.DefaultWakuTopic))
_, err = w.OnNewEnvelopes(envelope) _, err = w.OnNewEnvelopes(envelope)
if err != nil { if err != nil {
return err return nil, err
} }
} }
return err if len(result.Messages) != 0 {
cursor = result.PagingInfo.Cursor
}
return
} }
// Start implements node.Service, starting the background data propagation thread // Start implements node.Service, starting the background data propagation thread