diff --git a/cmd/node-canary/main.go b/cmd/node-canary/main.go
index ab1441b3d..fbd91425e 100644
--- a/cmd/node-canary/main.go
+++ b/cmd/node-canary/main.go
@@ -271,6 +271,7 @@ func makeNodeConfig() (*params.NodeConfig, error) {
nodeConfig.LogFile = *logFile
}
+ nodeConfig.EnableNTPSync = true
nodeConfig.NoDiscovery = true
nodeConfig.ListenAddr = ""
if *staticEnodeAddr != "" {
@@ -291,7 +292,6 @@ func whisperConfig(nodeConfig *params.NodeConfig) (*params.NodeConfig, error) {
whisperConfig.LightClient = true
whisperConfig.MinimumPoW = *minPow
whisperConfig.TTL = *ttl
- whisperConfig.EnableNTPSync = true
return nodeConfig, nil
}
diff --git a/eth-node/bridge/geth/envelope.go b/eth-node/bridge/geth/envelope.go
index 884760b06..64b9306bf 100644
--- a/eth-node/bridge/geth/envelope.go
+++ b/eth-node/bridge/geth/envelope.go
@@ -2,29 +2,102 @@ package gethbridge
import (
"github.com/status-im/status-go/eth-node/types"
+ "github.com/status-im/status-go/waku"
"github.com/status-im/status-go/whisper/v6"
)
-type gethEnvelopeWrapper struct {
- envelope *whisper.Envelope
+type whisperEnvelope struct {
+ env *whisper.Envelope
}
-// NewGethEnvelopeWrapper returns an object that wraps Geth's Envelope in a types interface
-func NewGethEnvelopeWrapper(e *whisper.Envelope) types.Envelope {
- return &gethEnvelopeWrapper{
- envelope: e,
+// NewWhisperEnvelope returns an object that wraps Geth's Whisper Envelope in a types interface.
+func NewWhisperEnvelope(e *whisper.Envelope) types.Envelope {
+ return &whisperEnvelope{env: e}
+}
+
+func UnwrapWhisperEnvelope(e types.Envelope) (*whisper.Envelope, bool) {
+ if env, ok := e.(*whisperEnvelope); ok {
+ return env.env, true
}
+ return nil, false
}
-// GetGethEnvelopeFrom retrieves the underlying whisper Envelope struct from a wrapped Envelope interface
-func GetGethEnvelopeFrom(f types.Envelope) *whisper.Envelope {
- return f.(*gethEnvelopeWrapper).envelope
+func MustUnwrapWhisperEnvelope(e types.Envelope) *whisper.Envelope {
+ return e.(*whisperEnvelope).env
}
-func (w *gethEnvelopeWrapper) Hash() types.Hash {
- return types.Hash(w.envelope.Hash())
+func (w *whisperEnvelope) Hash() types.Hash {
+ return types.Hash(w.env.Hash())
}
-func (w *gethEnvelopeWrapper) Bloom() []byte {
- return w.envelope.Bloom()
+func (w *whisperEnvelope) Bloom() []byte {
+ return w.env.Bloom()
+}
+
+func (w *whisperEnvelope) PoW() float64 {
+ return w.env.PoW()
+}
+
+func (w *whisperEnvelope) Expiry() uint32 {
+ return w.env.Expiry
+}
+
+func (w *whisperEnvelope) TTL() uint32 {
+ return w.env.TTL
+}
+
+func (w *whisperEnvelope) Topic() types.TopicType {
+ return types.TopicType(w.env.Topic)
+}
+
+func (w *whisperEnvelope) Size() int {
+ return len(w.env.Data)
+}
+
+type wakuEnvelope struct {
+ env *waku.Envelope
+}
+
+// NewWakuEnvelope returns an object that wraps Geth's Waku Envelope in a types interface.
+func NewWakuEnvelope(e *waku.Envelope) types.Envelope {
+ return &wakuEnvelope{env: e}
+}
+
+func UnwrapWakuEnvelope(e types.Envelope) (*waku.Envelope, bool) {
+ if env, ok := e.(*wakuEnvelope); ok {
+ return env.env, true
+ }
+ return nil, false
+}
+
+func MustUnwrapWakuEnvelope(e types.Envelope) *waku.Envelope {
+ return e.(*wakuEnvelope).env
+}
+
+func (w *wakuEnvelope) Hash() types.Hash {
+ return types.Hash(w.env.Hash())
+}
+
+func (w *wakuEnvelope) Bloom() []byte {
+ return w.env.Bloom()
+}
+
+func (w *wakuEnvelope) PoW() float64 {
+ return w.env.PoW()
+}
+
+func (w *wakuEnvelope) Expiry() uint32 {
+ return w.env.Expiry
+}
+
+func (w *wakuEnvelope) TTL() uint32 {
+ return w.env.TTL
+}
+
+func (w *wakuEnvelope) Topic() types.TopicType {
+ return types.TopicType(w.env.Topic)
+}
+
+func (w *wakuEnvelope) Size() int {
+ return len(w.env.Data)
}
diff --git a/eth-node/bridge/geth/whisper.go b/eth-node/bridge/geth/whisper.go
index 53e9bf005..8e64db81c 100644
--- a/eth-node/bridge/geth/whisper.go
+++ b/eth-node/bridge/geth/whisper.go
@@ -166,7 +166,7 @@ func (w *gethWhisperWrapper) SendMessagesRequest(peerID []byte, r types.Messages
// which are not supposed to be forwarded any further.
// The whisper protocol is agnostic of the format and contents of envelope.
func (w *gethWhisperWrapper) RequestHistoricMessagesWithTimeout(peerID []byte, envelope types.Envelope, timeout time.Duration) error {
- return w.whisper.RequestHistoricMessagesWithTimeout(peerID, GetGethEnvelopeFrom(envelope), timeout)
+ return w.whisper.RequestHistoricMessagesWithTimeout(peerID, MustUnwrapWhisperEnvelope(envelope), timeout)
}
// SyncMessages can be sent between two Mail Servers and syncs envelopes between them.
diff --git a/eth-node/go.mod b/eth-node/go.mod
index b007a0c3c..2edd418de 100644
--- a/eth-node/go.mod
+++ b/eth-node/go.mod
@@ -8,13 +8,16 @@ replace github.com/status-im/status-go/extkeys => ../extkeys
replace github.com/status-im/status-go/whisper/v6 => ../whisper
+replace github.com/status-im/status-go/waku => ../waku
+
require (
github.com/ethereum/go-ethereum v1.9.5
github.com/mattn/go-pointer v0.0.0-20190911064623-a0a44394634f
github.com/status-im/doubleratchet v3.0.0+incompatible
+ github.com/status-im/status-go/waku v1.0.0
github.com/status-im/status-go/whisper/v6 v6.0.1 // indirect
github.com/stretchr/testify v1.4.0
github.com/wealdtech/go-ens/v3 v3.0.9
go.uber.org/zap v1.13.0
- golang.org/x/crypto v0.0.0-20191119213627-4f8c1d86b1ba
+ golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c
)
diff --git a/eth-node/go.sum b/eth-node/go.sum
index 106d0dc88..f603ee835 100644
--- a/eth-node/go.sum
+++ b/eth-node/go.sum
@@ -1,9 +1,13 @@
bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/Azure/azure-pipeline-go v0.0.0-20180607212504-7571e8eb0876/go.mod h1:XA1kFWRVhSK+KNFiOhfv83Fv8L9achrP7OxIzeTn1Yg=
github.com/Azure/azure-storage-blob-go v0.0.0-20180712005634-eaae161d9d5e/go.mod h1:x2mtS6O3mnMEZOJp7d7oldh8IvatBrMfReiyQ+cKgKY=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/DataDog/zstd v1.3.6-0.20190409195224-796139022798/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
+github.com/Shopify/sarama v1.23.1/go.mod h1:XLH1GYJnLVE0XCr6KdJGVJRTwY30moWNJ4sERjXX6fs=
+github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
@@ -16,11 +20,15 @@ github.com/allegro/bigcache v1.1.0/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2uc
github.com/allegro/bigcache v1.2.0 h1:qDaE0QoF29wKBb3+pXFrJFy1ihe5OT9OiXhg1t85SxM=
github.com/allegro/bigcache v1.2.0/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
github.com/apilayer/freegeoip v3.5.0+incompatible/go.mod h1:CUfFqErhFhXneJendyQ/rRcuA8kH8JxHvYnbOozmlCU=
+github.com/aristanetworks/fsnotify v1.4.2/go.mod h1:D/rtu7LpjYM8tRJphJ0hUBYpjai8SfX+aSNsWDTq/Ks=
+github.com/aristanetworks/glog v0.0.0-20180419172825-c15b03b3054f/go.mod h1:KASm+qXFKs/xjSoWn30NrWBBvdTTQq+UjkhjEJHfSFA=
github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
github.com/aristanetworks/goarista v0.0.0-20181002214814-33151c4543a7 h1:6TQIK3K21/HnYLp+TAI6fjQ1YeH+KgLZbrFJwUjVrnQ=
github.com/aristanetworks/goarista v0.0.0-20181002214814-33151c4543a7/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
github.com/aristanetworks/goarista v0.0.0-20190219163901-728bce664cf5 h1:L0TwgZQo7Mga9im6FvKEZGIvyLE/VG/HI5loz5LpvC0=
github.com/aristanetworks/goarista v0.0.0-20190219163901-728bce664cf5/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
+github.com/aristanetworks/goarista v0.0.0-20191106175434-873d404c7f40/go.mod h1:Z4RTxGAuYhPzcq8+EdRM+R8M48Ssle2TsWtwRKa+vns=
+github.com/aristanetworks/splunk-hec-go v0.3.3/go.mod h1:1VHO9r17b0K7WmOlLb9nTk/2YanvOEnLMUgsFrxBROc=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
@@ -44,6 +52,7 @@ github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU=
github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -56,12 +65,16 @@ github.com/dgrijalva/jwt-go v0.0.0-20170201225849-2268707a8f08/go.mod h1:E3ru+11
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/docker/docker v0.0.0-20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v1.13.1/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
+github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
+github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw=
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/elastic/gosigar v0.0.0-20180330100440-37f05ff46ffa/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs=
github.com/elastic/gosigar v0.10.4 h1:6jfw75dsoflhBMRdO6QPzQUgLqUYTsQQQRkkcsHsuPo=
github.com/elastic/gosigar v0.10.4/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs=
+github.com/elastic/gosigar v0.10.5/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs=
github.com/ethereum/go-ethereum v1.9.2/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY=
github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
@@ -69,6 +82,7 @@ github.com/fjl/memsize v0.0.0-20180929194037-2a09253e352a h1:1znxn4+q2MrEdTk1eCk
github.com/fjl/memsize v0.0.0-20180929194037-2a09253e352a/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI=
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
github.com/gizak/termui v0.0.0-20170117222342-991cd3d38091/go.mod h1:PkJoWUt/zacQKysNfQtcw1RW+eK2SxkieVBtl+4ovLA=
@@ -83,6 +97,8 @@ github.com/go-stack/stack v1.5.4/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
@@ -93,6 +109,7 @@ github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pO
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
@@ -101,6 +118,7 @@ github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/graph-gophers/graphql-go v0.0.0-20190724201507-010347b5f9e6/go.mod h1:Au3iQ8DvDis8hZ4q2OzRcaKYlAsPt+fYvib5q4nIqu4=
+github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/golang-lru v0.0.0-20160813221303-0a025b7e63ad/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
@@ -113,9 +131,12 @@ github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7
github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
github.com/influxdata/influxdb v0.0.0-20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY=
github.com/influxdata/influxdb v1.7.7/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY=
+github.com/influxdata/influxdb1-client v0.0.0-20190809212627-fc22c7df067e/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/jackpal/go-nat-pmp v0.0.0-20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jackpal/go-nat-pmp v1.0.1 h1:i0LektDkO1QlrTm/cSuP+PyBCDnYvjPLGl4LdWEMiaA=
github.com/jackpal/go-nat-pmp v1.0.1/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
+github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
+github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
@@ -127,6 +148,8 @@ github.com/karalabe/usb v0.0.0-20190819132248-550797b1cad8 h1:VhnqxaTIudc9IWKx8u
github.com/karalabe/usb v0.0.0-20190819132248-550797b1cad8/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
+github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
+github.com/klauspost/reedsolomon v1.9.2/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
@@ -135,6 +158,7 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/maruel/panicparse v0.0.0-20160720141634-ad661195ed0e/go.mod h1:nty42YY5QByNC5MM7q/nj938VbgPU7avs45z6NClpxI=
github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg=
@@ -177,6 +201,8 @@ github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
+github.com/openconfig/gnmi v0.0.0-20190823184014-89b2bf29312c/go.mod h1:t+O9It+LKzfOAhKTT5O0ehDix+MTqbtT0T9t+7zzOvc=
+github.com/openconfig/reference v0.0.0-20190727015836-8dfd928c9696/go.mod h1:ym2A+zigScwkSEb/cVQB0/ZMpU3rqiH6X7WRRsxgOGw=
github.com/opentracing/opentracing-go v0.0.0-20180606204148-bd9c31933947/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/oschwald/maxminddb-golang v1.3.1/go.mod h1:3jhIUymTJ5VREKyIhWm66LJiQt04F0UCDdodShpjWsY=
@@ -184,27 +210,33 @@ github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7ir
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/peterh/liner v0.0.0-20170902204657-a37ad3984311/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
+github.com/pierrec/lz4 v0.0.0-20190327172049-315a67e90e41/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
github.com/pkg/errors v0.0.0-20171216070316-e881fd58d78e h1:+RHxT/gm0O3UF7nLJbdNzAmULvCFt4XfXHWzh3XI/zs=
github.com/pkg/errors v0.0.0-20171216070316-e881fd58d78e/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
+github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/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-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
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.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
+github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
github.com/prometheus/prometheus v0.0.0-20170814170113-3101606756c5/go.mod h1:oAIUtOny2rjMX0OWN5vPR5/q/twIROJvdqnQKDdil/s=
github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic=
github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4=
+github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho=
github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8=
github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM=
@@ -213,7 +245,9 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/cors v1.6.0 h1:G9tHG9lebljV9mfp9SNPDL36nCDxmo3zTlAf1YgvzmI=
github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
+github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ=
+github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
@@ -247,6 +281,9 @@ github.com/syndtr/goleveldb v0.0.0-20181128100959-b001fa50d6b2 h1:GnOzE5fEFN3b2z
github.com/syndtr/goleveldb v0.0.0-20181128100959-b001fa50d6b2/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
+github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU=
+github.com/templexxx/xor v0.0.0-20181023030647-4e92f724b73b/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4=
+github.com/tjfoc/gmsm v1.0.1/go.mod h1:XxO4hdhhrzAd+G4CjDqaOkd0hUzmtPR/d3EiBBMn/wc=
github.com/tsenart/tb v0.0.0-20181025101425-0d2499c8b6e9 h1:kjbwitOGH46vD01f2s3leBfrMnePQa3NSAIlW35MvY8=
github.com/tsenart/tb v0.0.0-20181025101425-0d2499c8b6e9/go.mod h1:EcGP24b8DY+bWHnpfJDP7fM+o8Nmz4fYH0l2xTtNr3I=
github.com/tyler-smith/go-bip39 v1.0.2 h1:+t3w+KwLXO6154GNJY+qUtIxLTmFjfUmpguQT1OlOT8=
@@ -261,6 +298,10 @@ github.com/wealdtech/go-string2eth v1.0.0 h1:jY6b1MVqU6k2Uw/kvcU1Y9/3dDyXfPzZrOF
github.com/wealdtech/go-string2eth v1.0.0/go.mod h1:UZA/snEybGcD6n+Pl+yoDjmexlEJ6dtoS9myfM83Ol4=
github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 h1:1cngl9mPEoITZG8s8cVcUy5CeIBYhEESkOB7m6Gmkrk=
github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees=
+github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
+github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
+github.com/xtaci/kcp-go v5.4.5+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE=
+github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE=
go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/multierr v1.3.0 h1:sFPn2GLc3poCkfrpIXGhBD2X0CMIo4Q/zSULXrj/+uc=
@@ -274,12 +315,15 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20190103213133-ff983b9c42bc h1:F5tKCVGp+MUAHhKp5MZtGqAlGX3+oCsiL1Q629FL90M=
golang.org/x/crypto v0.0.0-20190103213133-ff983b9c42bc/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf h1:fnPsqIDRbCSgumaMCRpoIoF2s4qxv0xSSS0BVZUE/ss=
golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20191119213627-4f8c1d86b1ba h1:9bFeDpN3gTqNanMVqNcoR/pJQuP5uroC3t1D7eXozTE=
golang.org/x/crypto v0.0.0-20191119213627-4f8c1d86b1ba/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
@@ -293,12 +337,15 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
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 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
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-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
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/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -306,22 +353,32 @@ golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190912141932-bc967efca4b8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190912185636-87d9f09c5d89/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
+gopkg.in/bsm/ratelimit.v1 v1.0.0-20160220154919-db14e161995a/go.mod h1:KF9sEfUPAXdG8Oev9e99iLGnl2uJMjc5B+4y3O7x610=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20161208181325-20d25e280405 h1:829vOVxxusYHC+IqBtkX5mbKtsY9fheQiQn0MZRVLfQ=
gopkg.in/check.v1 v1.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -330,11 +387,17 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
+gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo=
+gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q=
+gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4=
+gopkg.in/jcmturner/gokrb5.v7 v7.2.3/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM=
+gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8=
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU=
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c=
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20180302121509-abf0ba0be5d5/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns=
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190709231704-1e4459ed25ff h1:uuol9OUzSvZntY1v963NAbVd7A+PHLMz1FlCe3Lorcs=
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190709231704-1e4459ed25ff/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns=
+gopkg.in/redis.v4 v4.2.4/go.mod h1:8KREHdypkCEojGKQcjMqAODMICIVwZAONWq8RowTITA=
gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
@@ -344,5 +407,6 @@ gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+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 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
diff --git a/eth-node/types/envelopes.go b/eth-node/types/envelopes.go
index 997343330..7f1cb424f 100644
--- a/eth-node/types/envelopes.go
+++ b/eth-node/types/envelopes.go
@@ -5,6 +5,11 @@ package types
type Envelope interface {
Hash() Hash // Cached hash of the envelope to avoid rehashing every time.
Bloom() []byte
+ PoW() float64
+ Expiry() uint32
+ TTL() uint32
+ Topic() TopicType
+ Size() int
}
// EventType used to define known envelope events.
diff --git a/eth-node/types/hash.go b/eth-node/types/hash.go
index 2b5dec17c..5c9d7c0e8 100644
--- a/eth-node/types/hash.go
+++ b/eth-node/types/hash.go
@@ -50,7 +50,7 @@ func (h Hash) Bytes() []byte { return h[:] }
// String implements the stringer interface and is used also by the logger when
// doing full logging into a file.
-func (h *Hash) String() string {
+func (h Hash) String() string {
return h.Hex()
}
diff --git a/go.mod b/go.mod
index e15295cb2..d5ae49d7e 100644
--- a/go.mod
+++ b/go.mod
@@ -18,6 +18,8 @@ replace github.com/status-im/status-go/eth-node => ./eth-node
replace github.com/status-im/status-go/whisper/v6 => ./whisper
+replace github.com/status-im/status-go/waku => ./waku
+
require (
github.com/beevik/ntp v0.2.0
github.com/ethereum/go-ethereum v1.9.5
@@ -41,14 +43,14 @@ require (
github.com/status-im/status-go/eth-node v1.0.0
github.com/status-im/status-go/extkeys v1.0.0
github.com/status-im/status-go/protocol v1.0.1
+ github.com/status-im/status-go/waku v1.0.0
github.com/status-im/status-go/whisper/v6 v6.0.1
github.com/status-im/tcp-shaker v0.0.0-20191114194237-215893130501
github.com/stretchr/testify v1.4.0
github.com/syndtr/goleveldb v1.0.0
go.uber.org/zap v1.13.0
- golang.org/x/crypto v0.0.0-20191119213627-4f8c1d86b1ba
+ golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c
golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3 // indirect
- golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e // indirect
golang.org/x/tools v0.0.0-20191213032237-7093a17b0467 // indirect
gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
gopkg.in/go-playground/validator.v9 v9.29.1
diff --git a/go.sum b/go.sum
index 53a1d07fd..8742cc1d2 100644
--- a/go.sum
+++ b/go.sum
@@ -12,6 +12,7 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/DATA-DOG/go-sqlmock v1.3.3 h1:CWUqKXe0s8A2z6qCgkP4Kru7wC11YoAnoupUKFDnH08=
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
+github.com/DataDog/zstd v1.3.6-0.20190409195224-796139022798/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
github.com/Julusian/godocdown v0.0.0-20170816220326-6d19f8ff2df8/go.mod h1:INZr5t32rG59/5xeltqoCJoNY7e5x/3xoY9WSWVWg74=
github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y=
github.com/Microsoft/go-winio v0.4.11 h1:zoIOcVf0xPN1tnMVbTtEdI+P8OofVk3NObnwOQ6nK2Q=
@@ -19,23 +20,31 @@ github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcy
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
+github.com/Shopify/sarama v1.23.1/go.mod h1:XLH1GYJnLVE0XCr6KdJGVJRTwY30moWNJ4sERjXX6fs=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8=
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4 h1:Hs82Z41s6SdL1CELW+XaDYmOH4hkBN4/N9og/AsOv7E=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/allegro/bigcache v0.0.0-20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
github.com/allegro/bigcache v1.2.0 h1:qDaE0QoF29wKBb3+pXFrJFy1ihe5OT9OiXhg1t85SxM=
github.com/allegro/bigcache v1.2.0/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/apilayer/freegeoip v3.5.0+incompatible/go.mod h1:CUfFqErhFhXneJendyQ/rRcuA8kH8JxHvYnbOozmlCU=
+github.com/aristanetworks/fsnotify v1.4.2/go.mod h1:D/rtu7LpjYM8tRJphJ0hUBYpjai8SfX+aSNsWDTq/Ks=
+github.com/aristanetworks/glog v0.0.0-20180419172825-c15b03b3054f/go.mod h1:KASm+qXFKs/xjSoWn30NrWBBvdTTQq+UjkhjEJHfSFA=
github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
github.com/aristanetworks/goarista v0.0.0-20190219163901-728bce664cf5/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
github.com/aristanetworks/goarista v0.0.0-20190502180301-283422fc1708 h1:tS7jSmwRqSxTnonTRlDD1oHo6Q9YOK4xHS9/v4L56eg=
github.com/aristanetworks/goarista v0.0.0-20190502180301-283422fc1708/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
+github.com/aristanetworks/goarista v0.0.0-20191106175434-873d404c7f40 h1:ZdRuixFqR3mfx4FHzclG3COrRgWrYq0VhNgIoYoObcM=
+github.com/aristanetworks/goarista v0.0.0-20191106175434-873d404c7f40/go.mod h1:Z4RTxGAuYhPzcq8+EdRM+R8M48Ssle2TsWtwRKa+vns=
+github.com/aristanetworks/splunk-hec-go v0.3.3/go.mod h1:1VHO9r17b0K7WmOlLb9nTk/2YanvOEnLMUgsFrxBROc=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/beevik/ntp v0.2.0 h1:sGsd+kAXzT0bfVfzJfce04g+dSRfrs+tbQW8lweuYgw=
@@ -130,6 +139,8 @@ github.com/elastic/gosigar v0.0.0-20180330100440-37f05ff46ffa h1:o8OuEkracbk3qH6
github.com/elastic/gosigar v0.0.0-20180330100440-37f05ff46ffa/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs=
github.com/elastic/gosigar v0.10.4 h1:6jfw75dsoflhBMRdO6QPzQUgLqUYTsQQQRkkcsHsuPo=
github.com/elastic/gosigar v0.10.4/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs=
+github.com/elastic/gosigar v0.10.5 h1:GzPQ+78RaAb4J63unidA/JavQRKrB6s8IOzN6Ib59jo=
+github.com/elastic/gosigar v0.10.5/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs=
github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
github.com/ethereum/go-ethereum v1.8.20/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY=
github.com/ethereum/go-ethereum v1.9.2/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY=
@@ -141,6 +152,7 @@ github.com/fjl/memsize v0.0.0-20180929194037-2a09253e352a/go.mod h1:VvhXpOYNQvB+
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsouza/fake-gcs-server v1.7.0/go.mod h1:5XIRs4YvwNbNoz+1JF8j6KLAyDh7RHGAyAK3EP2EsNk=
+github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI=
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
github.com/gizak/termui v0.0.0-20170117222342-991cd3d38091/go.mod h1:PkJoWUt/zacQKysNfQtcw1RW+eK2SxkieVBtl+4ovLA=
@@ -169,6 +181,7 @@ github.com/gogo/protobuf v1.3.0 h1:G8O7TerXerS4F6sx9OV7/nRfJdnXgHZu/S/7F2SN+UE=
github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/golang-migrate/migrate/v4 v4.6.2 h1:LDDOHo/q1W5UDj6PbkxdCv7lv9yunyZHXvxuwDkGo3k=
github.com/golang-migrate/migrate/v4 v4.6.2/go.mod h1:JYi6reN3+Z734VZ0akNuyOJNcrg45ZL7LDBMW3WGJL0=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -216,6 +229,7 @@ github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/U
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
+github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/golang-lru v0.0.0-20160813221303-0a025b7e63ad/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
@@ -231,6 +245,7 @@ github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb v0.0.0-20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY=
github.com/influxdata/influxdb v1.7.7/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY=
+github.com/influxdata/influxdb1-client v0.0.0-20190809212627-fc22c7df067e/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
github.com/ipfs/go-cid v0.0.3 h1:UIAh32wymBpStoe83YCzwVQQ5Oy/H0FdxvUS6DJDzms=
@@ -253,6 +268,8 @@ github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQ
github.com/jackpal/go-nat-pmp v0.0.0-20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jackpal/go-nat-pmp v1.0.1 h1:i0LektDkO1QlrTm/cSuP+PyBCDnYvjPLGl4LdWEMiaA=
github.com/jackpal/go-nat-pmp v1.0.1/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
+github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
+github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jbenet/go-cienv v0.0.0-20150120210510-1bb1476777ec/go.mod h1:rGaEvXB4uRSZMmzKNLoXvTu1sfx+1kv/DojUlPrSZGs=
github.com/jbenet/go-cienv v0.1.0 h1:Vc/s0QbQtoxX8MwwSLWWh+xNNZvM3Lw7NsTcHrvvhMc=
github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA=
@@ -261,6 +278,7 @@ github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2/go.mod
github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY=
github.com/jbenet/goprocess v0.1.3 h1:YKyIEECS/XvcfHtBzxtjBBbWK+MbvA6dG8ASiqwvr10=
github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4=
+github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jinzhu/copier v0.0.0-20190625015134-976e0346caa8 h1:mGIXW/lubQ4B+3bXTLxcTMTjUNDqoF6T/HUW9LbFx9s=
@@ -282,6 +300,8 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
+github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
+github.com/klauspost/reedsolomon v1.9.2/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -295,6 +315,7 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kshvakov/clickhouse v1.3.5/go.mod h1:DMzX7FxRymoNkVgizH0DWAL8Cur7wHLgx3MUnGwJqpE=
+github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
@@ -496,9 +517,15 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w=
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo=
+github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
+github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
+github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
+github.com/openconfig/gnmi v0.0.0-20190823184014-89b2bf29312c/go.mod h1:t+O9It+LKzfOAhKTT5O0ehDix+MTqbtT0T9t+7zzOvc=
+github.com/openconfig/reference v0.0.0-20190727015836-8dfd928c9696/go.mod h1:ym2A+zigScwkSEb/cVQB0/ZMpU3rqiH6X7WRRsxgOGw=
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
@@ -515,17 +542,20 @@ 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/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/peterh/liner v0.0.0-20170902204657-a37ad3984311/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
+github.com/pierrec/lz4 v0.0.0-20190327172049-315a67e90e41/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.0.0-20171216070316-e881fd58d78e/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
+github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
github.com/prometheus/client_golang v1.2.1 h1:JnMpQc6ppsNgw9QPAGF6Dod479itz7lvlsMzzNayLOI=
github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
@@ -536,12 +566,14 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.2.0/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.7.0 h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLyCY=
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
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-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
+github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
github.com/prometheus/procfs v0.0.5 h1:3+auTFlqw+ZaQYJARz6ArODtkaIwtvBTx3N2NehQlL8=
github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
github.com/prometheus/prometheus v0.0.0-20170814170113-3101606756c5/go.mod h1:oAIUtOny2rjMX0OWN5vPR5/q/twIROJvdqnQKDdil/s=
@@ -558,6 +590,8 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/cors v1.6.0 h1:G9tHG9lebljV9mfp9SNPDL36nCDxmo3zTlAf1YgvzmI=
github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
+github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
+github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ=
github.com/russolsen/ohyeah v0.0.0-20160324131710-f4938c005315 h1:H3hCXwP92pH/hSgNrCLtjxvsKJ50sq26nICbZuoR1tQ=
github.com/russolsen/ohyeah v0.0.0-20160324131710-f4938c005315/go.mod h1:ZbKa3zlLnhGF1dAeJtMSoNtM5LgFQnqzq8eYH3uYYkU=
@@ -622,7 +656,10 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/syndtr/goleveldb v0.0.0-20181128100959-b001fa50d6b2/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
+github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU=
+github.com/templexxx/xor v0.0.0-20181023030647-4e92f724b73b/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4=
github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
+github.com/tjfoc/gmsm v1.0.1/go.mod h1:XxO4hdhhrzAd+G4CjDqaOkd0hUzmtPR/d3EiBBMn/wc=
github.com/tsenart/tb v0.0.0-20181025101425-0d2499c8b6e9 h1:kjbwitOGH46vD01f2s3leBfrMnePQa3NSAIlW35MvY8=
github.com/tsenart/tb v0.0.0-20181025101425-0d2499c8b6e9/go.mod h1:EcGP24b8DY+bWHnpfJDP7fM+o8Nmz4fYH0l2xTtNr3I=
github.com/tyler-smith/go-bip39 v1.0.2 h1:+t3w+KwLXO6154GNJY+qUtIxLTmFjfUmpguQT1OlOT8=
@@ -656,6 +693,8 @@ github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVT
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
+github.com/xtaci/kcp-go v5.4.5+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE=
+github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE=
gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE=
go.mongodb.org/mongo-driver v1.1.0/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
@@ -683,6 +722,7 @@ golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -692,6 +732,8 @@ golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
golang.org/x/crypto v0.0.0-20191119213627-4f8c1d86b1ba h1:9bFeDpN3gTqNanMVqNcoR/pJQuP5uroC3t1D7eXozTE=
golang.org/x/crypto v0.0.0-20191119213627-4f8c1d86b1ba/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c h1:/nJuwDLoL/zrqY6gf57vxC+Pi+pZ8bfhpPkicO5H7W4=
+golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@@ -719,6 +761,7 @@ golang.org/x/net v0.0.0-20190424112056-4829fb13d2c6/go.mod h1:t9HGtf8HONx5eT2rtn
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 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3 h1:6KET3Sqa7fkVfD63QnAM81ZeYg5n4HwApOJkufONnHA=
golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -745,11 +788,14 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190426135247-a129542de9ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190912141932-bc967efca4b8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191113165036-4c7a9d0fe056 h1:dHtDnRWQtSx0Hjq9kvKFpBh9uPPKfQN70NZZmvssGwk=
@@ -772,7 +818,9 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190425222832-ad9eeb80039a/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190912185636-87d9f09c5d89/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191109212701-97ad0ed33101 h1:LCmXVkvpQCDj724eX6irUTPCJP5GelFHxqGSWL2D1R0=
@@ -797,7 +845,11 @@ google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1 h1:Hz2g2wirWK7H0qIIhGIqRGTuMwTE8HEKFnDZZ7lm9NU=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
+google.golang.org/grpc v1.23.1 h1:q4XQuHFC6I28BKZpo6IYyb3mNO+l7lSOxRuYTCiDfXk=
+google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
+gopkg.in/bsm/ratelimit.v1 v1.0.0-20160220154919-db14e161995a/go.mod h1:KF9sEfUPAXdG8Oev9e99iLGnl2uJMjc5B+4y3O7x610=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
@@ -810,6 +862,11 @@ gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8
gopkg.in/go-playground/validator.v9 v9.29.1 h1:SvGtYmN60a5CVKTOzMSyfzWDeZRxRuGvRQyEAKbw1xc=
gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
+gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo=
+gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q=
+gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4=
+gopkg.in/jcmturner/gokrb5.v7 v7.2.3/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM=
+gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8=
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/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU=
@@ -818,6 +875,7 @@ gopkg.in/olebedev/go-duktape.v3 v3.0.0-20180302121509-abf0ba0be5d5 h1:VWXVtmkY4Y
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20180302121509-abf0ba0be5d5/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns=
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190709231704-1e4459ed25ff h1:uuol9OUzSvZntY1v963NAbVd7A+PHLMz1FlCe3Lorcs=
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190709231704-1e4459ed25ff/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns=
+gopkg.in/redis.v4 v4.2.4/go.mod h1:8KREHdypkCEojGKQcjMqAODMICIVwZAONWq8RowTITA=
gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8=
gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE=
@@ -833,5 +891,6 @@ gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
diff --git a/mailserver/cleaner_test.go b/mailserver/cleaner_test.go
index ce91d028b..a7b4c8d87 100644
--- a/mailserver/cleaner_test.go
+++ b/mailserver/cleaner_test.go
@@ -19,7 +19,7 @@ func TestCleaner(t *testing.T) {
now := time.Now()
server := setupTestServer(t)
defer server.Close()
- cleaner := newDBCleaner(server.db, time.Hour)
+ cleaner := newDBCleaner(server.ms.db, time.Hour)
archiveEnvelope(t, now.Add(-10*time.Second), server)
archiveEnvelope(t, now.Add(-3*time.Second), server)
@@ -27,9 +27,9 @@ func TestCleaner(t *testing.T) {
testMessagesCount(t, 3, server)
- testPrune(t, now.Add(-5*time.Second), 1, cleaner, server)
- testPrune(t, now.Add(-2*time.Second), 1, cleaner, server)
- testPrune(t, now, 1, cleaner, server)
+ testPrune(t, now.Add(-5*time.Second), 1, cleaner)
+ testPrune(t, now.Add(-2*time.Second), 1, cleaner)
+ testPrune(t, now, 1, cleaner)
testMessagesCount(t, 0, server)
}
@@ -39,7 +39,7 @@ func TestCleanerSchedule(t *testing.T) {
server := setupTestServer(t)
defer server.Close()
- cleaner := newDBCleaner(server.db, time.Hour)
+ cleaner := newDBCleaner(server.ms.db, time.Hour)
cleaner.period = time.Millisecond * 10
cleaner.Start()
defer cleaner.Stop()
@@ -60,7 +60,7 @@ func benchmarkCleanerPrune(b *testing.B, messages int, batchSize int) {
server := setupTestServer(t)
defer server.Close()
- cleaner := newDBCleaner(server.db, time.Hour)
+ cleaner := newDBCleaner(server.ms.db, time.Hour)
cleaner.batchSize = batchSize
for i := 0; i < messages; i++ {
@@ -68,7 +68,7 @@ func benchmarkCleanerPrune(b *testing.B, messages int, batchSize int) {
}
for i := 0; i < b.N; i++ {
- testPrune(t, now, 0, cleaner, server)
+ testPrune(t, now, 0, cleaner)
}
}
@@ -88,16 +88,19 @@ func BenchmarkCleanerPruneM100_000_B100(b *testing.B) {
benchmarkCleanerPrune(b, 100000, 100)
}
-func setupTestServer(t *testing.T) *WMailServer {
- var s WMailServer
+func setupTestServer(t *testing.T) *WhisperMailServer {
+ var s WhisperMailServer
db, _ := leveldb.Open(storage.NewMemStorage(), nil)
- s.db = &LevelDB{ldb: db}
- s.pow = powRequirement
+ s.ms = &mailServer{
+ db: &LevelDB{ldb: db},
+ adapter: &whisperAdapter{},
+ }
+ s.minRequestPoW = powRequirement
return &s
}
-func archiveEnvelope(t *testing.T, sentTime time.Time, server *WMailServer) *whisper.Envelope {
+func archiveEnvelope(t *testing.T, sentTime time.Time, server *WhisperMailServer) *whisper.Envelope {
env, err := generateEnvelope(sentTime)
require.NoError(t, err)
server.Archive(env)
@@ -105,14 +108,14 @@ func archiveEnvelope(t *testing.T, sentTime time.Time, server *WMailServer) *whi
return env
}
-func testPrune(t *testing.T, u time.Time, expected int, c *dbCleaner, s *WMailServer) {
+func testPrune(t *testing.T, u time.Time, expected int, c *dbCleaner) {
n, err := c.PruneEntriesOlderThan(u)
require.NoError(t, err)
require.Equal(t, expected, n)
}
-func testMessagesCount(t *testing.T, expected int, s *WMailServer) {
- count := countMessages(t, s.db)
+func testMessagesCount(t *testing.T, expected int, s *WhisperMailServer) {
+ count := countMessages(t, s.ms.db)
require.Equal(t, expected, count, fmt.Sprintf("expected %d message, got: %d", expected, count))
}
diff --git a/mailserver/mailserver.go b/mailserver/mailserver.go
index 174b0564d..f9e6bf2d2 100644
--- a/mailserver/mailserver.go
+++ b/mailserver/mailserver.go
@@ -17,29 +17,31 @@
package mailserver
import (
+ "crypto/ecdsa"
"encoding/binary"
"errors"
"fmt"
"math/rand"
+ "reflect"
"sync"
-
"time"
+ prom "github.com/prometheus/client_golang/prometheus"
+
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp"
-
+ gethbridge "github.com/status-im/status-go/eth-node/bridge/geth"
+ "github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/params"
+ "github.com/status-im/status-go/waku"
"github.com/status-im/status-go/whisper/v6"
-
- prom "github.com/prometheus/client_golang/prometheus"
)
const (
maxQueryRange = 24 * time.Hour
- defaultLimit = 2000
+ maxQueryLimit = 1000
// When we default the upper limit, we want to extend the range a bit
// to accommodate for envelopes with slightly higher timestamp, in seconds
whisperTTLSafeThreshold = 60
@@ -57,95 +59,136 @@ const (
processRequestTimeout = time.Minute
)
-// WMailServer whisper mailserver.
-type WMailServer struct {
- db DB
- w *whisper.Whisper
- pow float64
- symFilter *whisper.Filter
- asymFilter *whisper.Filter
-
- muRateLimiter sync.RWMutex
- rateLimiter *rateLimiter
-
- cleaner *dbCleaner // removes old envelopes
+type Config struct {
+ // DataDir points to a directory where mailserver's data is stored.
+ DataDir string
+ // Password is used to create a symmetric key to decrypt requests.
+ Password string
+ // AsymKey is an asymmetric key to decrypt requests.
+ AsymKey string
+ // MininumPoW is a minimum PoW for requests.
+ MinimumPoW float64
+ // RateLimit is a maximum number of requests per second from a peer.
+ RateLimit int
+ // DataRetention specifies a number of days an envelope should be stored for.
+ DataRetention int
+ PostgresEnabled bool
+ PostgresURI string
}
-var _ whisper.MailServer = (*WMailServer)(nil)
+// -----------------
+// WhisperMailServer
+// -----------------
-// Init initializes mailServer.
-func (s *WMailServer) Init(shh *whisper.Whisper, config *params.WhisperConfig) error {
- if len(config.DataDir) == 0 {
- return errDirectoryNotProvided
+type WhisperMailServer struct {
+ ms *mailServer
+ shh *whisper.Whisper
+ minRequestPoW float64
+
+ symFilter *whisper.Filter
+ asymFilter *whisper.Filter
+}
+
+func (s *WhisperMailServer) Init(shh *whisper.Whisper, cfg *params.WhisperConfig) error {
+ s.shh = shh
+ s.minRequestPoW = cfg.MinimumPoW
+
+ config := Config{
+ DataDir: cfg.DataDir,
+ Password: cfg.MailServerPassword,
+ AsymKey: cfg.MailServerAsymKey,
+ MinimumPoW: cfg.MinimumPoW,
+ DataRetention: cfg.MailServerDataRetention,
+ RateLimit: cfg.MailServerRateLimit,
+ PostgresEnabled: cfg.DatabaseConfig.PGConfig.Enabled,
+ PostgresURI: cfg.DatabaseConfig.PGConfig.URI,
}
-
- if len(config.MailServerPassword) == 0 && len(config.MailServerAsymKey) == 0 {
- return errDecryptionMethodNotProvided
- }
-
- s.w = shh
- s.pow = config.MinimumPoW
-
- if err := s.setupRequestMessageDecryptor(config); err != nil {
+ var err error
+ s.ms, err = newMailServer(
+ config,
+ &whisperAdapter{},
+ &whisperService{Whisper: shh},
+ )
+ if err != nil {
return err
}
- if config.MailServerRateLimit > 0 {
- s.setupRateLimiter(time.Duration(config.MailServerRateLimit) * time.Second)
- }
-
- // Open database in the last step in order not to init with error
- // and leave the database open by accident.
- if config.DatabaseConfig.PGConfig.Enabled {
- log.Info("Connecting to postgres database")
- database, err := NewPostgresDB(config)
- if err != nil {
- return fmt.Errorf("open DB: %s", err)
- }
- s.db = database
- log.Info("Connected to postgres database")
- } else {
- // Defaults to LevelDB
- database, err := NewLevelDB(config)
- if err != nil {
- return fmt.Errorf("open DB: %s", err)
- }
- s.db = database
- }
-
- if config.MailServerDataRetention > 0 {
- // MailServerDataRetention is a number of days.
- s.setupCleaner(time.Duration(config.MailServerDataRetention) * time.Hour * 24)
+ if err := s.setupDecryptor(config.Password, config.AsymKey); err != nil {
+ return err
}
return nil
}
-// setupRateLimiter in case limit is bigger than 0 it will setup an automated
-// limit db cleanup.
-func (s *WMailServer) setupRateLimiter(limit time.Duration) {
- s.rateLimiter = newRateLimiter(limit)
- s.rateLimiter.Start()
+func (s *WhisperMailServer) Close() {
+ if s.ms != nil {
+ s.ms.Close()
+ }
}
-func (s *WMailServer) setupCleaner(retention time.Duration) {
- s.cleaner = newDBCleaner(s.db, retention)
- s.cleaner.Start()
+func (s *WhisperMailServer) Archive(env *whisper.Envelope) {
+ s.ms.Archive(gethbridge.NewWhisperEnvelope(env))
}
-// setupRequestMessageDecryptor setup a Whisper filter to decrypt
-// incoming Whisper requests.
-func (s *WMailServer) setupRequestMessageDecryptor(config *params.WhisperConfig) error {
+// DEPRECATED; user Deliver instead
+func (s *WhisperMailServer) DeliverMail(peerID []byte, req *whisper.Envelope) {
+ payload, err := s.decodeRequest(peerID, req)
+ if err != nil {
+ log.Debug(
+ "[mailserver:DeliverMail] failed to decode request",
+ "err", err,
+ "peerID", peerID,
+ "requestID", req.Hash().String(),
+ )
+ payload, err = s.decompositeRequest(peerID, req)
+ }
+ if err != nil {
+ deliveryFailuresCounter.WithLabelValues("validation").Inc()
+ log.Error(
+ "[mailserver:DeliverMail] request failed validaton",
+ "peerID", peerID,
+ "requestID", req.Hash().String(),
+ "err", err,
+ )
+ s.ms.sendHistoricMessageErrorResponse(types.BytesToHash(peerID), types.Hash(req.Hash()), err)
+ return
+ }
+
+ s.ms.DeliverMail(types.BytesToHash(peerID), types.Hash(req.Hash()), payload)
+}
+
+func (s *WhisperMailServer) Deliver(peerID []byte, req whisper.MessagesRequest) {
+ s.ms.DeliverMail(types.BytesToHash(peerID), types.BytesToHash(req.ID), MessagesRequestPayload{
+ Lower: req.From,
+ Upper: req.To,
+ Bloom: req.Bloom,
+ Limit: req.Limit,
+ Cursor: req.Cursor,
+ Batch: true,
+ })
+}
+
+func (s *WhisperMailServer) SyncMail(peerID []byte, req whisper.SyncMailRequest) error {
+ return s.ms.SyncMail(types.BytesToHash(peerID), MessagesRequestPayload{
+ Lower: req.Lower,
+ Upper: req.Upper,
+ Bloom: req.Bloom,
+ Limit: req.Limit,
+ Cursor: req.Cursor,
+ })
+}
+
+func (s *WhisperMailServer) setupDecryptor(password, asymKey string) error {
s.symFilter = nil
s.asymFilter = nil
- if config.MailServerPassword != "" {
- keyID, err := s.w.AddSymKeyFromPassword(config.MailServerPassword)
+ if password != "" {
+ keyID, err := s.shh.AddSymKeyFromPassword(password)
if err != nil {
return fmt.Errorf("create symmetric key: %v", err)
}
- symKey, err := s.w.GetSymKey(keyID)
+ symKey, err := s.shh.GetSymKey(keyID)
if err != nil {
return fmt.Errorf("save symmetric key: %v", err)
}
@@ -153,8 +196,8 @@ func (s *WMailServer) setupRequestMessageDecryptor(config *params.WhisperConfig)
s.symFilter = &whisper.Filter{KeySym: symKey}
}
- if config.MailServerAsymKey != "" {
- keyAsym, err := crypto.HexToECDSA(config.MailServerAsymKey)
+ if asymKey != "" {
+ keyAsym, err := crypto.HexToECDSA(asymKey)
if err != nil {
return err
}
@@ -164,119 +207,544 @@ func (s *WMailServer) setupRequestMessageDecryptor(config *params.WhisperConfig)
return nil
}
-// Close the mailserver and its associated db connection.
-func (s *WMailServer) Close() {
- if s.db != nil {
- if err := s.db.Close(); err != nil {
- log.Error(fmt.Sprintf("s.db.Close failed: %s", err))
+func (s *WhisperMailServer) decodeRequest(peerID []byte, request *whisper.Envelope) (MessagesRequestPayload, error) {
+ var payload MessagesRequestPayload
+
+ if s.minRequestPoW > 0.0 && request.PoW() < s.minRequestPoW {
+ return payload, errors.New("PoW too low")
+ }
+
+ decrypted := s.openEnvelope(request)
+ if decrypted == nil {
+ log.Warn("Failed to decrypt p2p request")
+ return payload, errors.New("failed to decrypt p2p request")
+ }
+
+ if err := checkMsgSignature(decrypted.Src, peerID); err != nil {
+ log.Warn("Check message signature failed", "err", err.Error())
+ return payload, fmt.Errorf("check message signature failed: %v", err)
+ }
+
+ if err := rlp.DecodeBytes(decrypted.Payload, &payload); err != nil {
+ return payload, fmt.Errorf("failed to decode data: %v", err)
+ }
+
+ if payload.Upper == 0 {
+ payload.Upper = uint32(time.Now().Unix() + whisperTTLSafeThreshold)
+ }
+
+ if payload.Upper < payload.Lower {
+ log.Error("Query range is invalid: lower > upper", "lower", payload.Lower, "upper", payload.Upper)
+ return payload, errors.New("query range is invalid: lower > upper")
+ }
+
+ return payload, nil
+}
+
+// openEnvelope tries to decrypt an envelope, first based on asymmetric key (if
+// provided) and second on the symmetric key (if provided)
+func (s *WhisperMailServer) openEnvelope(request *whisper.Envelope) *whisper.ReceivedMessage {
+ if s.asymFilter != nil {
+ if d := request.Open(s.asymFilter); d != nil {
+ return d
}
}
- if s.rateLimiter != nil {
- s.rateLimiter.Stop()
+ if s.symFilter != nil {
+ if d := request.Open(s.symFilter); d != nil {
+ return d
+ }
}
- if s.cleaner != nil {
- s.cleaner.Stop()
+ return nil
+}
+
+func (s *WhisperMailServer) decompositeRequest(peerID []byte, request *whisper.Envelope) (MessagesRequestPayload, error) {
+ var (
+ payload MessagesRequestPayload
+ err error
+ )
+
+ if s.minRequestPoW > 0.0 && request.PoW() < s.minRequestPoW {
+ return payload, fmt.Errorf("PoW() is too low")
+ }
+
+ decrypted := s.openEnvelope(request)
+ if decrypted == nil {
+ return payload, fmt.Errorf("failed to decrypt p2p request")
+ }
+
+ if err := checkMsgSignature(decrypted.Src, peerID); err != nil {
+ return payload, err
+ }
+
+ payload.Bloom, err = s.bloomFromReceivedMessage(decrypted)
+ if err != nil {
+ return payload, err
+ }
+
+ payload.Lower = binary.BigEndian.Uint32(decrypted.Payload[:4])
+ payload.Upper = binary.BigEndian.Uint32(decrypted.Payload[4:8])
+
+ if payload.Upper < payload.Lower {
+ err := fmt.Errorf("query range is invalid: from > to (%d > %d)", payload.Lower, payload.Upper)
+ return payload, err
+ }
+
+ lowerTime := time.Unix(int64(payload.Lower), 0)
+ upperTime := time.Unix(int64(payload.Upper), 0)
+ if upperTime.Sub(lowerTime) > maxQueryRange {
+ err := fmt.Errorf("query range too big for peer %s", string(peerID))
+ return payload, err
+ }
+
+ if len(decrypted.Payload) >= requestTimeRangeLength+whisper.BloomFilterSize+requestLimitLength {
+ payload.Limit = binary.BigEndian.Uint32(decrypted.Payload[requestTimeRangeLength+whisper.BloomFilterSize:])
+ }
+
+ if len(decrypted.Payload) == requestTimeRangeLength+whisper.BloomFilterSize+requestLimitLength+DBKeyLength {
+ payload.Cursor = decrypted.Payload[requestTimeRangeLength+whisper.BloomFilterSize+requestLimitLength:]
+ }
+
+ return payload, nil
+}
+
+// bloomFromReceivedMessage for a given whisper.ReceivedMessage it extracts the
+// used bloom filter.
+func (s *WhisperMailServer) bloomFromReceivedMessage(msg *whisper.ReceivedMessage) ([]byte, error) {
+ payloadSize := len(msg.Payload)
+
+ if payloadSize < 8 {
+ return nil, errors.New("Undersized p2p request")
+ } else if payloadSize == 8 {
+ return whisper.MakeFullNodeBloom(), nil
+ } else if payloadSize < 8+whisper.BloomFilterSize {
+ return nil, errors.New("Undersized bloom filter in p2p request")
+ }
+
+ return msg.Payload[8 : 8+whisper.BloomFilterSize], nil
+}
+
+// --------------
+// WakuMailServer
+// --------------
+
+type WakuMailServer struct {
+ ms *mailServer
+ shh *waku.Waku
+ minRequestPoW float64
+
+ symFilter *waku.Filter
+ asymFilter *waku.Filter
+}
+
+func (s *WakuMailServer) Init(waku *waku.Waku, cfg *params.WakuConfig) error {
+ s.shh = waku
+ s.minRequestPoW = cfg.MinimumPoW
+
+ config := Config{
+ DataDir: cfg.DataDir,
+ Password: cfg.MailServerPassword,
+ MinimumPoW: cfg.MinimumPoW,
+ DataRetention: cfg.MailServerDataRetention,
+ RateLimit: cfg.MailServerRateLimit,
+ PostgresEnabled: cfg.DatabaseConfig.PGConfig.Enabled,
+ PostgresURI: cfg.DatabaseConfig.PGConfig.URI,
+ }
+ var err error
+ s.ms, err = newMailServer(
+ config,
+ &wakuAdapter{},
+ &wakuService{Waku: waku},
+ )
+ if err != nil {
+ return err
+ }
+
+ if err := s.setupDecryptor(config.Password, config.AsymKey); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (s *WakuMailServer) Close() {
+ s.ms.Close()
+}
+
+func (s *WakuMailServer) Archive(env *waku.Envelope) {
+ s.ms.Archive(gethbridge.NewWakuEnvelope(env))
+}
+
+func (s *WakuMailServer) Deliver(peerID []byte, req waku.MessagesRequest) {
+ s.ms.DeliverMail(types.BytesToHash(peerID), types.BytesToHash(req.ID), MessagesRequestPayload{
+ Lower: req.From,
+ Upper: req.To,
+ Bloom: req.Bloom,
+ Limit: req.Limit,
+ Cursor: req.Cursor,
+ Batch: true,
+ })
+}
+
+// DEPRECATED; user Deliver instead
+func (s *WakuMailServer) DeliverMail(peerID []byte, req *waku.Envelope) {
+ payload, err := s.decodeRequest(peerID, req)
+ if err != nil {
+ deliveryFailuresCounter.WithLabelValues("validation").Inc()
+ log.Error(
+ "[mailserver:DeliverMail] request failed validaton",
+ "peerID", peerID,
+ "requestID", req.Hash().String(),
+ "err", err,
+ )
+ s.ms.sendHistoricMessageErrorResponse(types.BytesToHash(peerID), types.Hash(req.Hash()), err)
+ return
+ }
+
+ s.ms.DeliverMail(types.BytesToHash(peerID), types.Hash(req.Hash()), payload)
+}
+
+func (s *WakuMailServer) setupDecryptor(password, asymKey string) error {
+ s.symFilter = nil
+ s.asymFilter = nil
+
+ if password != "" {
+ keyID, err := s.shh.AddSymKeyFromPassword(password)
+ if err != nil {
+ return fmt.Errorf("create symmetric key: %v", err)
+ }
+
+ symKey, err := s.shh.GetSymKey(keyID)
+ if err != nil {
+ return fmt.Errorf("save symmetric key: %v", err)
+ }
+
+ s.symFilter = &waku.Filter{KeySym: symKey}
+ }
+
+ if asymKey != "" {
+ keyAsym, err := crypto.HexToECDSA(asymKey)
+ if err != nil {
+ return err
+ }
+ s.asymFilter = &waku.Filter{KeyAsym: keyAsym}
+ }
+
+ return nil
+}
+
+// openEnvelope tries to decrypt an envelope, first based on asymetric key (if
+// provided) and second on the symetric key (if provided)
+func (s *WakuMailServer) openEnvelope(request *waku.Envelope) *waku.ReceivedMessage {
+ if s.asymFilter != nil {
+ if d := request.Open(s.asymFilter); d != nil {
+ return d
+ }
+ }
+ if s.symFilter != nil {
+ if d := request.Open(s.symFilter); d != nil {
+ return d
+ }
+ }
+ return nil
+}
+
+func (s *WakuMailServer) decodeRequest(peerID []byte, request *waku.Envelope) (MessagesRequestPayload, error) {
+ var payload MessagesRequestPayload
+
+ if s.minRequestPoW > 0.0 && request.PoW() < s.minRequestPoW {
+ return payload, errors.New("PoW too low")
+ }
+
+ decrypted := s.openEnvelope(request)
+ if decrypted == nil {
+ log.Warn("Failed to decrypt p2p request")
+ return payload, errors.New("failed to decrypt p2p request")
+ }
+
+ if err := checkMsgSignature(decrypted.Src, peerID); err != nil {
+ log.Warn("Check message signature failed", "err", err.Error())
+ return payload, fmt.Errorf("check message signature failed: %v", err)
+ }
+
+ if err := rlp.DecodeBytes(decrypted.Payload, &payload); err != nil {
+ return payload, fmt.Errorf("failed to decode data: %v", err)
+ }
+
+ if payload.Upper == 0 {
+ payload.Upper = uint32(time.Now().Unix() + whisperTTLSafeThreshold)
+ }
+
+ if payload.Upper < payload.Lower {
+ log.Error("Query range is invalid: lower > upper", "lower", payload.Lower, "upper", payload.Upper)
+ return payload, errors.New("query range is invalid: lower > upper")
+ }
+
+ return payload, nil
+}
+
+// -------
+// adapter
+// -------
+
+type adapter interface {
+ CreateRequestFailedPayload(reqID types.Hash, err error) []byte
+ CreateRequestCompletedPayload(reqID, lastEnvelopeHash types.Hash, cursor []byte) []byte
+ CreateSyncResponse(envelopes []types.Envelope, cursor []byte, final bool, err string) interface{}
+ CreateRawSyncResponse(envelopes []rlp.RawValue, cursor []byte, final bool, err string) interface{}
+}
+
+// --------------
+// whisperAdapter
+// --------------
+
+type whisperAdapter struct{}
+
+var _ adapter = (*whisperAdapter)(nil)
+
+func (whisperAdapter) CreateRequestFailedPayload(reqID types.Hash, err error) []byte {
+ return whisper.CreateMailServerRequestFailedPayload(common.Hash(reqID), err)
+}
+
+func (whisperAdapter) CreateRequestCompletedPayload(reqID, lastEnvelopeHash types.Hash, cursor []byte) []byte {
+ return whisper.CreateMailServerRequestCompletedPayload(common.Hash(reqID), common.Hash(lastEnvelopeHash), cursor)
+}
+
+func (whisperAdapter) CreateSyncResponse(envelopes []types.Envelope, cursor []byte, final bool, err string) interface{} {
+ whisperEnvelopes := make([]*whisper.Envelope, len(envelopes))
+ for i, env := range envelopes {
+ whisperEnvelopes[i] = gethbridge.MustUnwrapWhisperEnvelope(env)
+ }
+ return whisper.SyncResponse{
+ Envelopes: whisperEnvelopes,
+ Cursor: cursor,
+ Final: final,
+ Error: err,
}
}
-// Archive a whisper envelope.
-func (s *WMailServer) Archive(env *whisper.Envelope) {
- if err := s.db.SaveEnvelope(env); err != nil {
- log.Error("Could not save envelope", "hash", env.Hash())
+func (whisperAdapter) CreateRawSyncResponse(envelopes []rlp.RawValue, cursor []byte, final bool, err string) interface{} {
+ return whisper.RawSyncResponse{
+ Envelopes: envelopes,
+ Cursor: cursor,
+ Final: final,
+ Error: err,
}
}
-// DeliverMail sends mail to specified whisper peer.
-func (s *WMailServer) DeliverMail(peer *whisper.Peer, request *whisper.Envelope) {
+// -----------
+// wakuAdapter
+// -----------
+
+type wakuAdapter struct{}
+
+var _ adapter = (*wakuAdapter)(nil)
+
+func (wakuAdapter) CreateRequestFailedPayload(reqID types.Hash, err error) []byte {
+ return waku.CreateMailServerRequestFailedPayload(common.Hash(reqID), err)
+}
+
+func (wakuAdapter) CreateRequestCompletedPayload(reqID, lastEnvelopeHash types.Hash, cursor []byte) []byte {
+ return waku.CreateMailServerRequestCompletedPayload(common.Hash(reqID), common.Hash(lastEnvelopeHash), cursor)
+}
+
+func (wakuAdapter) CreateSyncResponse(_ []types.Envelope, _ []byte, _ bool, _ string) interface{} {
+ return nil
+}
+
+func (wakuAdapter) CreateRawSyncResponse(_ []rlp.RawValue, _ []byte, _ bool, _ string) interface{} {
+ return nil
+}
+
+// -------
+// service
+// -------
+
+type service interface {
+ SendHistoricMessageResponse(peerID []byte, payload []byte) error
+ SendRawP2PDirect(peerID []byte, envelopes ...rlp.RawValue) error
+ MaxMessageSize() uint32
+ SendRawSyncResponse(peerID []byte, data interface{}) error // optional
+ SendSyncResponse(peerID []byte, data interface{}) error // optional
+}
+
+// --------------
+// whisperService
+// --------------
+
+type whisperService struct {
+ *whisper.Whisper
+}
+
+func (s *whisperService) SendRawSyncResponse(peerID []byte, data interface{}) error {
+ resp, ok := data.(whisper.RawSyncResponse)
+ if !ok {
+ panic(fmt.Sprintf("invalid data type, got %s", reflect.TypeOf(data)))
+ }
+ return s.Whisper.SendRawSyncResponse(peerID, resp)
+}
+
+func (s *whisperService) SendSyncResponse(peerID []byte, data interface{}) error {
+ resp, ok := data.(whisper.SyncResponse)
+ if !ok {
+ panic(fmt.Sprintf("invalid data type, got %s", reflect.TypeOf(data)))
+ }
+ return s.Whisper.SendSyncResponse(peerID, resp)
+}
+
+// -----------
+// wakuService
+// -----------
+
+type wakuService struct {
+ *waku.Waku
+}
+
+func (s *wakuService) SendRawSyncResponse(peerID []byte, data interface{}) error {
+ return errors.New("syncing mailservers is not support by Waku")
+}
+
+func (s *wakuService) SendSyncResponse(peerID []byte, data interface{}) error {
+ return errors.New("syncing mailservers is not support by Waku")
+}
+
+// ----------
+// mailServer
+// ----------
+
+type mailServer struct {
+ adapter adapter
+ service service
+ db DB
+ cleaner *dbCleaner // removes old envelopes
+ muRateLimiter sync.RWMutex
+ rateLimiter *rateLimiter
+}
+
+func newMailServer(cfg Config, adapter adapter, service service) (*mailServer, error) {
+ if len(cfg.DataDir) == 0 {
+ return nil, errDirectoryNotProvided
+ }
+
+ // TODO: move out
+ if len(cfg.Password) == 0 && len(cfg.AsymKey) == 0 {
+ return nil, errDecryptionMethodNotProvided
+ }
+
+ s := mailServer{
+ adapter: adapter,
+ service: service,
+ }
+
+ if cfg.RateLimit > 0 {
+ s.setupRateLimiter(time.Duration(cfg.RateLimit) * time.Second)
+ }
+
+ // Open database in the last step in order not to init with error
+ // and leave the database open by accident.
+ if cfg.PostgresEnabled {
+ log.Info("Connecting to postgres database")
+ database, err := NewPostgresDB(cfg.PostgresURI)
+ if err != nil {
+ return nil, fmt.Errorf("open DB: %s", err)
+ }
+ s.db = database
+ log.Info("Connected to postgres database")
+ } else {
+ // Defaults to LevelDB
+ database, err := NewLevelDB(cfg.DataDir)
+ if err != nil {
+ return nil, fmt.Errorf("open DB: %s", err)
+ }
+ s.db = database
+ }
+
+ if cfg.DataRetention > 0 {
+ // MailServerDataRetention is a number of days.
+ s.setupCleaner(time.Duration(cfg.DataRetention) * time.Hour * 24)
+ }
+
+ return &s, nil
+}
+
+// setupRateLimiter in case limit is bigger than 0 it will setup an automated
+// limit db cleanup.
+func (s *mailServer) setupRateLimiter(limit time.Duration) {
+ s.rateLimiter = newRateLimiter(limit)
+ s.rateLimiter.Start()
+}
+
+func (s *mailServer) setupCleaner(retention time.Duration) {
+ s.cleaner = newDBCleaner(s.db, retention)
+ s.cleaner.Start()
+}
+
+func (s *mailServer) Archive(env types.Envelope) {
+ err := s.db.SaveEnvelope(env)
+ if err != nil {
+ log.Error("Could not save envelope", "hash", env.Hash().String())
+ }
+}
+
+func (s *mailServer) DeliverMail(peerID, reqID types.Hash, req MessagesRequestPayload) {
timer := prom.NewTimer(mailDeliveryDuration)
defer timer.ObserveDuration()
deliveryAttemptsCounter.Inc()
-
- if peer == nil {
- deliveryFailuresCounter.WithLabelValues("no_peer_set").Inc()
- log.Error("[mailserver:DeliverMail] peer is nil")
- return
- }
-
- requestID := types.Hash(request.Hash())
- peerID := peerIDString(peer)
-
- log.Info("[mailserver:DeliverMail] delivering mail",
- "peerID", peerID,
- "requestID", requestID.String())
-
- if s.exceedsPeerRequests(peer.ID()) {
- deliveryFailuresCounter.WithLabelValues("peer_req_limit").Inc()
- log.Error("[mailserver:DeliverMail] peer exceeded the limit",
- "peerID", peerID,
- "requestID", requestID.String())
- s.trySendHistoricMessageErrorResponse(peer, requestID, fmt.Errorf("rate limit exceeded"))
- return
- }
-
- var (
- lower, upper uint32
- bloom []byte
- limit uint32
- cursor []byte
- batch bool
- err error
+ log.Info(
+ "[mailserver:DeliverMail] delivering mail",
+ "peerID", peerID.String(),
+ "requestID", reqID.String(),
)
- payload, err := s.decodeRequest(peer.ID(), request)
- if err == nil {
- lower, upper = payload.Lower, payload.Upper
- bloom = payload.Bloom
- cursor = payload.Cursor
- limit = payload.Limit
- batch = payload.Batch
- } else {
- log.Debug("[mailserver:DeliverMail] failed to decode request",
+ req.SetDefaults()
+
+ if err := req.Validate(); err != nil {
+ syncFailuresCounter.WithLabelValues("req_invalid").Inc()
+ log.Error(
+ "[mailserver:DeliverMail] request invalid",
+ "peerID", peerID.String(),
+ "requestID", reqID.String(),
"err", err,
- "peerID", peerID,
- "requestID", requestID.String())
- lower, upper, bloom, limit, cursor, err = s.validateRequest(peer.ID(), request)
- }
-
- if limit == 0 {
- limit = defaultLimit
- }
-
- if err != nil {
- deliveryFailuresCounter.WithLabelValues("validation").Inc()
- log.Error("[mailserver:DeliverMail] request failed validaton",
- "peerID", peerID,
- "requestID", requestID.String(),
- "err", err)
- s.trySendHistoricMessageErrorResponse(peer, requestID, err)
+ )
+ s.sendHistoricMessageErrorResponse(peerID, reqID, fmt.Errorf("request is invalid: %v", err))
return
}
- log.Info("[mailserver:DeliverMail] processing request",
- "peerID", peerID,
- "requestID", requestID.String(),
- "lower", lower,
- "upper", upper,
- "bloom", bloom,
- "limit", limit,
- "cursor", cursor,
- "batch", batch,
- )
+ if s.exceedsPeerRequests(peerID) {
+ deliveryFailuresCounter.WithLabelValues("peer_req_limit").Inc()
+ log.Error(
+ "[mailserver:DeliverMail] peer exceeded the limit",
+ "peerID", peerID.String(),
+ "requestID", reqID.String(),
+ )
+ s.sendHistoricMessageErrorResponse(peerID, reqID, fmt.Errorf("rate limit exceeded"))
+ return
+ }
- if batch {
+ log.Info(
+ "[mailserver:DeliverMail] processing request",
+ "peerID", peerID.String(),
+ "requestID", reqID.String(),
+ "lower", req.Lower,
+ "upper", req.Upper,
+ "bloom", req.Bloom,
+ "limit", req.Limit,
+ "cursor", req.Cursor,
+ "batch", req.Batch,
+ )
+ if req.Batch {
requestsBatchedCounter.Inc()
}
- iter, err := s.createIterator(lower, upper, cursor, bloom, limit)
+ iter, err := s.createIterator(req)
if err != nil {
- log.Error("[mailserver:DeliverMail] request failed",
- "peerID", peerID,
- "requestID", requestID)
-
+ log.Error(
+ "[mailserver:DeliverMail] request failed",
+ "peerID", peerID.String(),
+ "requestID", reqID.String(),
+ )
return
}
-
defer iter.Release()
bundles := make(chan []rlp.RawValue, 5)
@@ -286,7 +754,7 @@ func (s *WMailServer) DeliverMail(peer *whisper.Peer, request *whisper.Envelope)
go func() {
counter := 0
for bundle := range bundles {
- if err := s.sendRawEnvelopes(peer, bundle, batch); err != nil {
+ if err := s.sendRawEnvelopes(peerID, bundle, req.Batch); err != nil {
close(cancelProcessing)
errCh <- err
break
@@ -294,18 +762,20 @@ func (s *WMailServer) DeliverMail(peer *whisper.Peer, request *whisper.Envelope)
counter++
}
close(errCh)
- log.Info("[mailserver:DeliverMail] finished sending bundles",
+ log.Info(
+ "[mailserver:DeliverMail] finished sending bundles",
"peerID", peerID,
- "requestID", requestID.String(),
- "counter", counter)
+ "requestID", reqID.String(),
+ "counter", counter,
+ )
}()
nextPageCursor, lastEnvelopeHash := s.processRequestInBundles(
iter,
- bloom,
- int(limit),
+ req.Bloom,
+ int(req.Limit),
processRequestTimeout,
- requestID.String(),
+ reqID.String(),
bundles,
cancelProcessing,
)
@@ -313,198 +783,62 @@ func (s *WMailServer) DeliverMail(peer *whisper.Peer, request *whisper.Envelope)
// Wait for the goroutine to finish the work. It may return an error.
if err := <-errCh; err != nil {
deliveryFailuresCounter.WithLabelValues("process").Inc()
- log.Error("[mailserver:DeliverMail] error while processing",
+ log.Error(
+ "[mailserver:DeliverMail] error while processing",
"err", err,
"peerID", peerID,
- "requestID", requestID)
- s.trySendHistoricMessageErrorResponse(peer, requestID, err)
+ "requestID", reqID,
+ )
+ s.sendHistoricMessageErrorResponse(peerID, reqID, err)
return
}
// Processing of the request could be finished earlier due to iterator error.
if err := iter.Error(); err != nil {
deliveryFailuresCounter.WithLabelValues("iterator").Inc()
- log.Error("[mailserver:DeliverMail] iterator failed",
+ log.Error(
+ "[mailserver:DeliverMail] iterator failed",
"err", err,
"peerID", peerID,
- "requestID", requestID)
- s.trySendHistoricMessageErrorResponse(peer, requestID, err)
- return
- }
-
- log.Info("[mailserver:DeliverMail] sending historic message response",
- "peerID", peerID,
- "requestID", requestID,
- "last", lastEnvelopeHash,
- "next", nextPageCursor)
-
- if err := s.sendHistoricMessageResponse(peer, requestID, lastEnvelopeHash, nextPageCursor); err != nil {
- deliveryFailuresCounter.WithLabelValues("historic_msg_resp").Inc()
- log.Error("[mailserver:DeliverMail] error sending historic message response",
- "err", err,
- "peerID", peerID,
- "requestID", requestID)
- // we still want to try to report error even it it is a p2p error and it is unlikely
- s.trySendHistoricMessageErrorResponse(peer, requestID, err)
- }
-}
-
-func (s *WMailServer) Deliver(peer *whisper.Peer, r whisper.MessagesRequest) {
- timer := prom.NewTimer(mailDeliveryDuration)
- defer timer.ObserveDuration()
-
- deliveryAttemptsCounter.Inc()
-
- var (
- requestIDHash = types.BytesToHash(r.ID)
- requestIDStr = requestIDHash.String()
- peerID = peerIDString(peer)
- err error
- )
-
- defer func() {
- if err != nil {
- log.Error("[mailserver:DeliverMail] failed to process",
- "err", err,
- "peerID", peerID,
- "requestID", requestIDStr,
- )
- s.trySendHistoricMessageErrorResponse(peer, requestIDHash, err)
- }
- }()
-
- log.Info("[mailserver:Deliver] delivering mail", "peerID", peerID, "requestID", requestIDStr)
-
- if peer == nil {
- deliveryFailuresCounter.WithLabelValues("no_peer_set").Inc()
- log.Error("[mailserver:Deliver] peer is nil")
- return
- }
-
- if s.exceedsPeerRequests(peer.ID()) {
- deliveryFailuresCounter.WithLabelValues("peer_req_limit").Inc()
- err = errors.New("exceeded the number of requests limit")
- return
- }
-
- err = r.Validate()
- if err != nil {
- deliveryFailuresCounter.WithLabelValues("validation").Inc()
- err = fmt.Errorf("invalid request: %v", err)
- return
- }
-
- var (
- lower, upper = r.From, r.To
- bloom = r.Bloom
- limit = r.Limit
- cursor = r.Cursor
- batch = true // batch requests are default
- )
-
- log.Info("[mailserver:Deliver] processing request",
- "peerID", peerID,
- "requestID", requestIDStr,
- "lower", lower,
- "upper", upper,
- "bloom", bloom,
- "limit", limit,
- "cursor", cursor,
- "batch", batch,
- )
- requestsBatchedCounter.Inc()
-
- iter, err := s.createIterator(lower, upper, cursor, bloom, limit)
- if err != nil {
- err = fmt.Errorf("failed to create an iterator: %v", err)
- return
- }
- defer iter.Release()
-
- bundles := make(chan []rlp.RawValue, 5)
- errCh := make(chan error, 1)
- cancelProcessing := make(chan struct{})
-
- go func() {
- counter := 0
- for bundle := range bundles {
- if err := s.sendRawEnvelopes(peer, bundle, batch); err != nil {
- close(cancelProcessing)
- errCh <- err
- break
- }
- counter++
- }
- close(errCh)
- log.Info("[mailserver:DeliverMail] finished sending bundles",
- "peerID", peerID,
- "requestID", requestIDStr,
- "counter", counter,
+ "requestID", reqID,
)
- }()
-
- nextPageCursor, lastEnvelopeHash := s.processRequestInBundles(
- iter,
- bloom,
- int(limit),
- processRequestTimeout,
- requestIDStr,
- bundles,
- cancelProcessing,
- )
-
- // Wait for the goroutine to finish the work. It may return an error.
- err = <-errCh
- if err != nil {
- deliveryFailuresCounter.WithLabelValues("process").Inc()
- err = fmt.Errorf("failed to send envelopes: %v", err)
+ s.sendHistoricMessageErrorResponse(peerID, reqID, err)
return
}
- // Processing of the request could be finished earlier due to iterator error.
- err = iter.Error()
- if err != nil {
- deliveryFailuresCounter.WithLabelValues("iterator").Inc()
- err = fmt.Errorf("failed to read all envelopes: %v", err)
- return
- }
-
- log.Info("[mailserver:Deliver] sending historic message response",
+ log.Info(
+ "[mailserver:DeliverMail] sending historic message response",
"peerID", peerID,
- "requestID", requestIDStr,
+ "requestID", reqID,
"last", lastEnvelopeHash,
"next", nextPageCursor,
)
- err = s.sendHistoricMessageResponse(peer, requestIDHash, lastEnvelopeHash, nextPageCursor)
- if err != nil {
- deliveryFailuresCounter.WithLabelValues("historic_msg_resp").Inc()
- err = fmt.Errorf("failed to send response: %v", err)
- return
- }
+ s.sendHistoricMessageResponse(peerID, reqID, lastEnvelopeHash, nextPageCursor)
}
-// SyncMail syncs mail servers between two Mail Servers.
-func (s *WMailServer) SyncMail(peer *whisper.Peer, request whisper.SyncMailRequest) error {
- log.Info("Started syncing envelopes", "peer", peerIDString(peer), "req", request)
+func (s *mailServer) SyncMail(peerID types.Hash, req MessagesRequestPayload) error {
+ log.Info("Started syncing envelopes", "peer", peerID.String(), "req", req)
requestID := fmt.Sprintf("%d-%d", time.Now().UnixNano(), rand.Intn(1000))
syncAttemptsCounter.Inc()
// Check rate limiting for a requesting peer.
- if s.exceedsPeerRequests(peer.ID()) {
+ if s.exceedsPeerRequests(peerID) {
syncFailuresCounter.WithLabelValues("req_per_sec_limit").Inc()
- log.Error("Peer exceeded request per seconds limit", "peerID", peerIDString(peer))
+ log.Error("Peer exceeded request per seconds limit", "peerID", peerID.String())
return fmt.Errorf("requests per seconds limit exceeded")
}
- if err := request.Validate(); err != nil {
+ req.SetDefaults()
+
+ if err := req.Validate(); err != nil {
syncFailuresCounter.WithLabelValues("req_invalid").Inc()
return fmt.Errorf("request is invalid: %v", err)
}
- iter, err := s.createIterator(request.Lower, request.Upper, request.Cursor, nil, 0)
+ iter, err := s.createIterator(req)
if err != nil {
syncFailuresCounter.WithLabelValues("iterator").Inc()
return err
@@ -517,8 +851,8 @@ func (s *WMailServer) SyncMail(peer *whisper.Peer, request whisper.SyncMailReque
go func() {
for bundle := range bundles {
- resp := whisper.RawSyncResponse{Envelopes: bundle}
- if err := s.w.SendRawSyncResponse(peer, resp); err != nil {
+ resp := s.adapter.CreateRawSyncResponse(bundle, nil, false, "")
+ if err := s.service.SendRawSyncResponse(peerID.Bytes(), resp); err != nil {
close(cancelProcessing)
errCh <- fmt.Errorf("failed to send sync response: %v", err)
break
@@ -529,8 +863,8 @@ func (s *WMailServer) SyncMail(peer *whisper.Peer, request whisper.SyncMailReque
nextCursor, _ := s.processRequestInBundles(
iter,
- request.Bloom,
- int(request.Limit),
+ req.Bloom,
+ int(req.Limit),
processRequestTimeout,
requestID,
bundles,
@@ -540,9 +874,9 @@ func (s *WMailServer) SyncMail(peer *whisper.Peer, request whisper.SyncMailReque
// Wait for the goroutine to finish the work. It may return an error.
if err := <-errCh; err != nil {
syncFailuresCounter.WithLabelValues("routine").Inc()
- _ = s.w.SendSyncResponse(
- peer,
- whisper.SyncResponse{Error: "failed to send a response"},
+ _ = s.service.SendSyncResponse(
+ peerID.Bytes(),
+ s.adapter.CreateSyncResponse(nil, nil, false, "failed to send a response"),
)
return err
}
@@ -550,19 +884,20 @@ func (s *WMailServer) SyncMail(peer *whisper.Peer, request whisper.SyncMailReque
// Processing of the request could be finished earlier due to iterator error.
if err := iter.Error(); err != nil {
syncFailuresCounter.WithLabelValues("iterator").Inc()
- _ = s.w.SendSyncResponse(
- peer,
- whisper.SyncResponse{Error: "failed to process all envelopes"},
+ _ = s.service.SendSyncResponse(
+ peerID.Bytes(),
+ s.adapter.CreateSyncResponse(nil, nil, false, "failed to process all envelopes"),
)
return fmt.Errorf("LevelDB iterator failed: %v", err)
}
- log.Info("Finished syncing envelopes", "peer", peerIDString(peer))
+ log.Info("Finished syncing envelopes", "peer", peerID.String())
- if err := s.w.SendSyncResponse(peer, whisper.SyncResponse{
- Cursor: nextCursor,
- Final: true,
- }); err != nil {
+ err = s.service.SendSyncResponse(
+ peerID.Bytes(),
+ s.adapter.CreateSyncResponse(nil, nextCursor, true, ""),
+ )
+ if err != nil {
syncFailuresCounter.WithLabelValues("response_send").Inc()
return fmt.Errorf("failed to send the final sync response: %v", err)
}
@@ -570,9 +905,22 @@ func (s *WMailServer) SyncMail(peer *whisper.Peer, request whisper.SyncMailReque
return nil
}
-// exceedsPeerRequests in case limit its been setup on the current server and limit
-// allows the query, it will store/update new query time for the current peer.
-func (s *WMailServer) exceedsPeerRequests(peer []byte) bool {
+// Close the mailserver and its associated db connection.
+func (s *mailServer) Close() {
+ if s.db != nil {
+ if err := s.db.Close(); err != nil {
+ log.Error("closing database failed", "err", err)
+ }
+ }
+ if s.rateLimiter != nil {
+ s.rateLimiter.Stop()
+ }
+ if s.cleaner != nil {
+ s.cleaner.Stop()
+ }
+}
+
+func (s *mailServer) exceedsPeerRequests(peerID types.Hash) bool {
s.muRateLimiter.RLock()
defer s.muRateLimiter.RUnlock()
@@ -580,39 +928,36 @@ func (s *WMailServer) exceedsPeerRequests(peer []byte) bool {
return false
}
- peerID := string(peer)
- if s.rateLimiter.IsAllowed(peerID) {
- s.rateLimiter.Add(peerID)
+ if s.rateLimiter.IsAllowed(peerID.String()) {
+ s.rateLimiter.Add(peerID.String())
return false
}
- log.Info("peerID exceeded the number of requests per second")
+ log.Info("peerID exceeded the number of requests per second", "peerID", peerID.String())
return true
}
-func (s *WMailServer) createIterator(lower, upper uint32, cursor []byte, bloom []byte, limit uint32) (Iterator, error) {
+func (s *mailServer) createIterator(req MessagesRequestPayload) (Iterator, error) {
var (
emptyHash types.Hash
emptyTopic types.TopicType
ku, kl *DBKey
)
- ku = NewDBKey(upper+1, emptyTopic, emptyHash)
- kl = NewDBKey(lower, emptyTopic, emptyHash)
+ ku = NewDBKey(req.Upper+1, emptyTopic, emptyHash)
+ kl = NewDBKey(req.Lower, emptyTopic, emptyHash)
query := CursorQuery{
start: kl.Bytes(),
end: ku.Bytes(),
- cursor: cursor,
- bloom: bloom,
- limit: limit,
+ cursor: req.Cursor,
+ bloom: req.Bloom,
+ limit: req.Limit,
}
return s.db.BuildIterator(query)
}
-// processRequestInBundles processes envelopes using an iterator and passes them
-// to the output channel in bundles.
-func (s *WMailServer) processRequestInBundles(
+func (s *mailServer) processRequestInBundles(
iter Iterator,
bloom []byte,
limit int,
@@ -634,9 +979,11 @@ func (s *WMailServer) processRequestInBundles(
lastEnvelopeHash types.Hash
)
- log.Info("[mailserver:processRequestInBundles] processing request",
+ log.Info(
+ "[mailserver:processRequestInBundles] processing request",
"requestID", requestID,
- "limit", limit)
+ "limit", limit,
+ )
// We iterate over the envelopes.
// We collect envelopes in batches.
@@ -645,25 +992,25 @@ func (s *WMailServer) processRequestInBundles(
// Otherwise publish what you have so far, reset the bundle to the
// current envelope, and leave if we hit the limit
for iter.Next() {
-
rawValue, err := iter.GetEnvelope(bloom)
-
if err != nil {
- log.Error("Failed to get envelope from iterator",
+ log.Error(
+ "[mailserver:processRequestInBundles]Failed to get envelope from iterator",
"err", err,
- "requestID", requestID)
+ "requestID", requestID,
+ )
continue
-
}
-
if rawValue == nil {
continue
}
key, err := iter.DBKey()
if err != nil {
- log.Error("[mailserver:processRequestInBundles] failed getting key",
- "requestID", requestID)
+ log.Error(
+ "[mailserver:processRequestInBundles] failed getting key",
+ "requestID", requestID,
+ )
break
}
@@ -677,7 +1024,7 @@ func (s *WMailServer) processRequestInBundles(
newSize := bundleSize + envelopeSize
// If we still have some room for messages, add and continue
- if !limitReached && newSize < s.w.MaxMessageSize() {
+ if !limitReached && newSize < s.service.MaxMessageSize() {
bundle = append(bundle, rawValue)
bundleSize = newSize
continue
@@ -706,12 +1053,14 @@ func (s *WMailServer) processRequestInBundles(
processedEnvelopesSize += int64(bundleSize)
}
- log.Info("[mailserver:processRequestInBundles] publishing envelopes",
+ log.Info(
+ "[mailserver:processRequestInBundles] publishing envelopes",
"requestID", requestID,
"batchesCount", len(batches),
"envelopeCount", processedEnvelopes,
"processedEnvelopesSize", processedEnvelopesSize,
- "cursor", nextCursor)
+ "cursor", nextCursor,
+ )
// Publish
batchLoop:
@@ -723,12 +1072,16 @@ batchLoop:
// the consumer of `output` channel exits prematurely.
// In such a case, we should stop pushing batches and exit.
case <-cancel:
- log.Info("[mailserver:processRequestInBundles] failed to push all batches",
- "requestID", requestID)
+ log.Info(
+ "[mailserver:processRequestInBundles] failed to push all batches",
+ "requestID", requestID,
+ )
break batchLoop
case <-time.After(timeout):
- log.Error("[mailserver:processRequestInBundles] timed out pushing a batch",
- "requestID", requestID)
+ log.Error(
+ "[mailserver:processRequestInBundles] timed out pushing a batch",
+ "requestID", requestID,
+ )
break batchLoop
}
}
@@ -736,23 +1089,25 @@ batchLoop:
envelopesCounter.Inc()
sentEnvelopeBatchSizeMeter.Observe(float64(processedEnvelopesSize))
- log.Info("[mailserver:processRequestInBundles] envelopes published",
- "requestID", requestID)
+ log.Info(
+ "[mailserver:processRequestInBundles] envelopes published",
+ "requestID", requestID,
+ )
close(output)
return nextCursor, lastEnvelopeHash
}
-func (s *WMailServer) sendRawEnvelopes(peer *whisper.Peer, envelopes []rlp.RawValue, batch bool) error {
+func (s *mailServer) sendRawEnvelopes(peerID types.Hash, envelopes []rlp.RawValue, batch bool) error {
timer := prom.NewTimer(sendRawEnvelopeDuration)
defer timer.ObserveDuration()
if batch {
- return s.w.SendRawP2PDirect(peer, envelopes...)
+ return s.service.SendRawP2PDirect(peerID.Bytes(), envelopes...)
}
for _, env := range envelopes {
- if err := s.w.SendRawP2PDirect(peer, env); err != nil {
+ if err := s.service.SendRawP2PDirect(peerID.Bytes(), env); err != nil {
return err
}
}
@@ -760,174 +1115,30 @@ func (s *WMailServer) sendRawEnvelopes(peer *whisper.Peer, envelopes []rlp.RawVa
return nil
}
-func (s *WMailServer) sendHistoricMessageResponse(peer *whisper.Peer, requestID, lastEnvelopeHash types.Hash, cursor []byte) error {
- payload := whisper.CreateMailServerRequestCompletedPayload(common.Hash(requestID), common.Hash(lastEnvelopeHash), cursor)
- return s.w.SendHistoricMessageResponse(peer, payload)
+func (s *mailServer) sendHistoricMessageResponse(peerID, reqID, lastEnvelopeHash types.Hash, cursor []byte) {
+ payload := s.adapter.CreateRequestCompletedPayload(reqID, lastEnvelopeHash, cursor)
+ err := s.service.SendHistoricMessageResponse(peerID.Bytes(), payload)
+ if err != nil {
+ deliveryFailuresCounter.WithLabelValues("historic_msg_resp").Inc()
+ log.Error(
+ "[mailserver:DeliverMail] error sending historic message response",
+ "err", err,
+ "peerID", peerID,
+ "requestID", reqID,
+ )
+ }
}
-// this method doesn't return an error because it is already in the error handling chain
-func (s *WMailServer) trySendHistoricMessageErrorResponse(peer *whisper.Peer, requestID types.Hash, errorToReport error) {
- payload := whisper.CreateMailServerRequestFailedPayload(common.Hash(requestID), errorToReport)
-
- err := s.w.SendHistoricMessageResponse(peer, payload)
+func (s *mailServer) sendHistoricMessageErrorResponse(peerID, reqID types.Hash, errorToReport error) {
+ payload := s.adapter.CreateRequestFailedPayload(reqID, errorToReport)
+ err := s.service.SendHistoricMessageResponse(peerID.Bytes(), payload)
// if we can't report an error, probably something is wrong with p2p connection,
// so we just print a log entry to document this sad fact
if err != nil {
- log.Error("Error while reporting error response", "err", err, "peerID", peerIDString(peer))
+ log.Error("Error while reporting error response", "err", err, "peerID", peerID.String())
}
}
-// openEnvelope tries to decrypt an envelope, first based on asymetric key (if
-// provided) and second on the symetric key (if provided)
-func (s *WMailServer) openEnvelope(request *whisper.Envelope) *whisper.ReceivedMessage {
- if s.asymFilter != nil {
- if d := request.Open(s.asymFilter); d != nil {
- return d
- }
- }
- if s.symFilter != nil {
- if d := request.Open(s.symFilter); d != nil {
- return d
- }
- }
- return nil
-}
-
-func (s *WMailServer) decodeRequest(peerID []byte, request *whisper.Envelope) (MessagesRequestPayload, error) {
- var payload MessagesRequestPayload
-
- if s.pow > 0.0 && request.PoW() < s.pow {
- return payload, errors.New("PoW too low")
- }
-
- decrypted := s.openEnvelope(request)
- if decrypted == nil {
- log.Warn("Failed to decrypt p2p request")
- return payload, errors.New("failed to decrypt p2p request")
- }
-
- if err := s.checkMsgSignature(decrypted, peerID); err != nil {
- log.Warn("Check message signature failed: %s", "err", err.Error())
- return payload, fmt.Errorf("check message signature failed: %v", err)
- }
-
- if err := rlp.DecodeBytes(decrypted.Payload, &payload); err != nil {
- return payload, fmt.Errorf("failed to decode data: %v", err)
- }
-
- if payload.Upper == 0 {
- payload.Upper = uint32(time.Now().Unix() + whisperTTLSafeThreshold)
- }
-
- if payload.Upper < payload.Lower {
- log.Error("Query range is invalid: lower > upper", "lower", payload.Lower, "upper", payload.Upper)
- return payload, errors.New("query range is invalid: lower > upper")
- }
-
- return payload, nil
-}
-
-// validateRequest runs different validations on the current request.
-// DEPRECATED
-func (s *WMailServer) validateRequest(
- peerID []byte,
- request *whisper.Envelope,
-) (uint32, uint32, []byte, uint32, []byte, error) {
- if s.pow > 0.0 && request.PoW() < s.pow {
- return 0, 0, nil, 0, nil, fmt.Errorf("PoW() is too low")
- }
-
- decrypted := s.openEnvelope(request)
- if decrypted == nil {
- return 0, 0, nil, 0, nil, fmt.Errorf("failed to decrypt p2p request")
- }
-
- if err := s.checkMsgSignature(decrypted, peerID); err != nil {
- return 0, 0, nil, 0, nil, err
- }
-
- bloom, err := s.bloomFromReceivedMessage(decrypted)
- if err != nil {
- return 0, 0, nil, 0, nil, err
- }
-
- lower := binary.BigEndian.Uint32(decrypted.Payload[:4])
- upper := binary.BigEndian.Uint32(decrypted.Payload[4:8])
-
- if upper < lower {
- err := fmt.Errorf("query range is invalid: from > to (%d > %d)", lower, upper)
- return 0, 0, nil, 0, nil, err
- }
-
- lowerTime := time.Unix(int64(lower), 0)
- upperTime := time.Unix(int64(upper), 0)
- if upperTime.Sub(lowerTime) > maxQueryRange {
- err := fmt.Errorf("query range too big for peer %s", string(peerID))
- return 0, 0, nil, 0, nil, err
- }
-
- var limit uint32
- if len(decrypted.Payload) >= requestTimeRangeLength+whisper.BloomFilterSize+requestLimitLength {
- limit = binary.BigEndian.Uint32(decrypted.Payload[requestTimeRangeLength+whisper.BloomFilterSize:])
- }
-
- var cursor []byte
- if len(decrypted.Payload) == requestTimeRangeLength+whisper.BloomFilterSize+requestLimitLength+DBKeyLength {
- cursor = decrypted.Payload[requestTimeRangeLength+whisper.BloomFilterSize+requestLimitLength:]
- }
-
- err = nil
- return lower, upper, bloom, limit, cursor, err
-}
-
-// checkMsgSignature returns an error in case the message is not correcly signed
-func (s *WMailServer) checkMsgSignature(msg *whisper.ReceivedMessage, id []byte) error {
- src := crypto.FromECDSAPub(msg.Src)
- if len(src)-len(id) == 1 {
- src = src[1:]
- }
-
- // if you want to check the signature, you can do it here. e.g.:
- // if !bytes.Equal(peerID, src) {
- if src == nil {
- return errors.New("Wrong signature of p2p request")
- }
-
- return nil
-}
-
-// bloomFromReceivedMessage for a given whisper.ReceivedMessage it extracts the
-// used bloom filter.
-func (s *WMailServer) bloomFromReceivedMessage(msg *whisper.ReceivedMessage) ([]byte, error) {
- payloadSize := len(msg.Payload)
-
- if payloadSize < 8 {
- return nil, errors.New("Undersized p2p request")
- } else if payloadSize == 8 {
- return whisper.MakeFullNodeBloom(), nil
- } else if payloadSize < 8+whisper.BloomFilterSize {
- return nil, errors.New("Undersized bloom filter in p2p request")
- }
-
- return msg.Payload[8 : 8+whisper.BloomFilterSize], nil
-}
-
-// peerWithID is a generalization of whisper.Peer.
-// whisper.Peer has all fields and methods, except for ID(), unexported.
-// It makes it impossible to create an instance of it
-// outside of whisper package and test properly.
-type peerWithID interface {
- ID() []byte
-}
-
-func peerIDString(peer peerWithID) string {
- return fmt.Sprintf("%x", peer.ID())
-}
-
-func peerIDBytesString(id []byte) string {
- return fmt.Sprintf("%x", id)
-}
-
func extractBloomFromEncodedEnvelope(rawValue rlp.RawValue) ([]byte, error) {
var envelope whisper.Envelope
decodeErr := rlp.DecodeBytes(rawValue, &envelope)
@@ -936,3 +1147,19 @@ func extractBloomFromEncodedEnvelope(rawValue rlp.RawValue) ([]byte, error) {
}
return envelope.Bloom(), nil
}
+
+// checkMsgSignature returns an error in case the message is not correctly signed.
+func checkMsgSignature(reqSrc *ecdsa.PublicKey, id []byte) error {
+ src := crypto.FromECDSAPub(reqSrc)
+ if len(src)-len(id) == 1 {
+ src = src[1:]
+ }
+
+ // if you want to check the signature, you can do it here. e.g.:
+ // if !bytes.Equal(peerID, src) {
+ if src == nil {
+ return errors.New("wrong signature of p2p request")
+ }
+
+ return nil
+}
diff --git a/mailserver/mailserver_db.go b/mailserver/mailserver_db.go
index 2be6172a0..b048ba19b 100644
--- a/mailserver/mailserver_db.go
+++ b/mailserver/mailserver_db.go
@@ -3,15 +3,15 @@ package mailserver
import (
"time"
- "github.com/status-im/status-go/whisper/v6"
+ "github.com/status-im/status-go/eth-node/types"
)
// DB is an interface to abstract interactions with the db so that the mailserver
-// is agnostic to the underlaying technology used
+// is agnostic to the underlying technology used
type DB interface {
Close() error
// SaveEnvelope stores an envelope
- SaveEnvelope(*whisper.Envelope) error // TODO: Migrate to types.Envelope
+ SaveEnvelope(types.Envelope) error
// GetEnvelope returns an rlp encoded envelope from the datastore
GetEnvelope(*DBKey) ([]byte, error)
// Prune removes envelopes older than time
diff --git a/mailserver/mailserver_db_leveldb.go b/mailserver/mailserver_db_leveldb.go
index 395547f37..17e33c58b 100644
--- a/mailserver/mailserver_db_leveldb.go
+++ b/mailserver/mailserver_db_leveldb.go
@@ -12,8 +12,8 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp"
+ gethbridge "github.com/status-im/status-go/eth-node/bridge/geth"
"github.com/status-im/status-go/eth-node/types"
- "github.com/status-im/status-go/params"
"github.com/status-im/status-go/whisper/v6"
)
@@ -58,12 +58,12 @@ func (i *LevelDBIterator) GetEnvelope(bloom []byte) ([]byte, error) {
}
-func NewLevelDB(config *params.WhisperConfig) (*LevelDB, error) {
+func NewLevelDB(dataDir string) (*LevelDB, error) {
// Open opens an existing leveldb database
- db, err := leveldb.OpenFile(config.DataDir, nil)
- if _, iscorrupted := err.(*errors.ErrCorrupted); iscorrupted {
- log.Info("database is corrupted trying to recover", "path", config.DataDir)
- db, err = leveldb.RecoverFile(config.DataDir, nil)
+ db, err := leveldb.OpenFile(dataDir, nil)
+ if _, corrupted := err.(*errors.ErrCorrupted); corrupted {
+ log.Info("database is corrupted trying to recover", "path", dataDir)
+ db, err = leveldb.RecoverFile(dataDir, nil)
}
return &LevelDB{ldb: db}, err
}
@@ -138,11 +138,22 @@ func (db *LevelDB) Prune(t time.Time, batchSize int) (int, error) {
}
// SaveEnvelope stores an envelope in leveldb and increments the metrics
-func (db *LevelDB) SaveEnvelope(env *whisper.Envelope) error {
+func (db *LevelDB) SaveEnvelope(env types.Envelope) error {
defer recoverLevelDBPanics("SaveEnvelope")
- key := NewDBKey(env.Expiry-env.TTL, types.TopicType(env.Topic), types.Hash(env.Hash()))
- rawEnvelope, err := rlp.EncodeToBytes(env)
+ key := NewDBKey(env.Expiry()-env.TTL(), env.Topic(), env.Hash())
+
+ var (
+ rawEnvelope []byte
+ err error
+ )
+ if whisperEnv, ok := gethbridge.UnwrapWhisperEnvelope(env); ok {
+ rawEnvelope, err = rlp.EncodeToBytes(whisperEnv)
+ } else if wakuEnv, ok := gethbridge.UnwrapWakuEnvelope(env); ok {
+ rawEnvelope, err = rlp.EncodeToBytes(wakuEnv)
+ } else {
+ return errors.New("unsupported underlying types.Envelope type")
+ }
if err != nil {
log.Error(fmt.Sprintf("rlp.EncodeToBytes failed: %s", err))
archivedErrorsCounter.Inc()
@@ -154,7 +165,7 @@ func (db *LevelDB) SaveEnvelope(env *whisper.Envelope) error {
archivedErrorsCounter.Inc()
}
archivedEnvelopesCounter.Inc()
- archivedEnvelopeSizeMeter.Observe(float64(whisper.EnvelopeHeaderLength + len(env.Data)))
+ archivedEnvelopeSizeMeter.Observe(float64(whisper.EnvelopeHeaderLength + env.Size()))
return err
}
diff --git a/mailserver/mailserver_db_postgres.go b/mailserver/mailserver_db_postgres.go
index 60b57d210..cfe4c2105 100644
--- a/mailserver/mailserver_db_postgres.go
+++ b/mailserver/mailserver_db_postgres.go
@@ -12,7 +12,6 @@ import (
bindata "github.com/status-im/migrate/v4/source/go_bindata"
"github.com/status-im/status-go/mailserver/migrations"
- "github.com/status-im/status-go/params"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp"
@@ -21,8 +20,8 @@ import (
"github.com/status-im/status-go/whisper/v6"
)
-func NewPostgresDB(config *params.WhisperConfig) (*PostgresDB, error) {
- db, err := sql.Open("postgres", config.DatabaseConfig.PGConfig.URI)
+func NewPostgresDB(uri string) (*PostgresDB, error) {
+ db, err := sql.Open("postgres", uri)
if err != nil {
return nil, err
}
@@ -179,9 +178,9 @@ func (i *PostgresDB) Prune(t time.Time, batch int) (int, error) {
return 0, nil
}
-func (i *PostgresDB) SaveEnvelope(env *whisper.Envelope) error {
- topic := types.TopicType(env.Topic)
- key := NewDBKey(env.Expiry-env.TTL, topic, types.Hash(env.Hash()))
+func (i *PostgresDB) SaveEnvelope(env types.Envelope) error {
+ topic := env.Topic()
+ key := NewDBKey(env.Expiry()-env.TTL(), topic, env.Hash())
rawEnvelope, err := rlp.EncodeToBytes(env)
if err != nil {
log.Error(fmt.Sprintf("rlp.EncodeToBytes failed: %s", err))
@@ -210,7 +209,7 @@ func (i *PostgresDB) SaveEnvelope(env *whisper.Envelope) error {
}
archivedEnvelopesCounter.Inc()
- archivedEnvelopeSizeMeter.Observe(float64(whisper.EnvelopeHeaderLength + len(env.Data)))
+ archivedEnvelopeSizeMeter.Observe(float64(whisper.EnvelopeHeaderLength + env.Size()))
return nil
}
diff --git a/mailserver/mailserver_test.go b/mailserver/mailserver_test.go
index 00a3c298b..49f3c7e77 100644
--- a/mailserver/mailserver_test.go
+++ b/mailserver/mailserver_test.go
@@ -27,8 +27,6 @@ import (
"testing"
"time"
- "github.com/stretchr/testify/require"
-
"github.com/stretchr/testify/suite"
"github.com/ethereum/go-ethereum/common"
@@ -61,16 +59,16 @@ func TestMailserverSuite(t *testing.T) {
type MailserverSuite struct {
suite.Suite
- server *WMailServer
+ server *WhisperMailServer
shh *whisper.Whisper
config *params.WhisperConfig
dataDir string
}
func (s *MailserverSuite) SetupTest() {
- s.server = &WMailServer{}
+ s.server = &WhisperMailServer{}
s.shh = whisper.New(&whisper.DefaultConfig)
- s.shh.RegisterServer(s.server)
+ s.shh.RegisterMailServer(s.server)
tmpDir, err := ioutil.TempDir("", "mailserver-test")
s.Require().NoError(err)
@@ -152,9 +150,9 @@ func (s *MailserverSuite) TestInit() {
for _, tc := range testCases {
s.T().Run(tc.info, func(*testing.T) {
- mailServer := &WMailServer{}
+ mailServer := &WhisperMailServer{}
shh := whisper.New(&whisper.DefaultConfig)
- shh.RegisterServer(mailServer)
+ shh.RegisterMailServer(mailServer)
err := mailServer.Init(shh, &tc.config)
s.Equal(tc.expectedError, err)
@@ -162,13 +160,13 @@ func (s *MailserverSuite) TestInit() {
// db should be open only if there was no error
if tc.expectedError == nil {
- s.NotNil(mailServer.db)
+ s.NotNil(mailServer.ms.db)
} else {
- s.Nil(mailServer.db)
+ s.Nil(mailServer.ms)
}
if tc.config.MailServerRateLimit > 0 {
- s.NotNil(mailServer.rateLimiter)
+ s.NotNil(mailServer.ms.rateLimiter)
}
})
}
@@ -228,7 +226,7 @@ func (s *MailserverSuite) TestOpenEnvelopeWithSymKey() {
}
func (s *MailserverSuite) TestOpenEnvelopeWithAsymKey() {
- // Setup the server with an asymetric key
+ // Setup the server with an asymmetric key
config := *s.config
config.MailServerPassword = "" // clear password field
s.NoError(s.server.Init(s.shh, &config))
@@ -239,7 +237,7 @@ func (s *MailserverSuite) TestOpenEnvelopeWithAsymKey() {
env, err := generateEnvelopeWithKeys(time.Now(), nil, &pubKey)
s.Require().NoError(err)
- // Test openEnvelope with a valid asymetric key
+ // Test openEnvelope with a valid asymmetric key
d := s.server.openEnvelope(env)
s.NotNil(d)
s.Equal(testPayload, d.Payload)
@@ -261,22 +259,24 @@ func (s *MailserverSuite) TestArchive() {
s.server.Archive(env)
key := NewDBKey(env.Expiry-env.TTL, types.TopicType(env.Topic), types.Hash(env.Hash()))
- archivedEnvelope, err := s.server.db.GetEnvelope(key)
+ archivedEnvelope, err := s.server.ms.db.GetEnvelope(key)
s.NoError(err)
s.Equal(rawEnvelope, archivedEnvelope)
}
func (s *MailserverSuite) TestManageLimits() {
- s.server.rateLimiter = newRateLimiter(time.Duration(5) * time.Millisecond)
- s.False(s.server.exceedsPeerRequests([]byte("peerID")))
- s.Equal(1, len(s.server.rateLimiter.db))
- firstSaved := s.server.rateLimiter.db["peerID"]
+ err := s.server.Init(s.shh, s.config)
+ s.NoError(err)
+ s.server.ms.rateLimiter = newRateLimiter(time.Duration(5) * time.Millisecond)
+ s.False(s.server.ms.exceedsPeerRequests(types.BytesToHash([]byte("peerID"))))
+ s.Equal(1, len(s.server.ms.rateLimiter.db))
+ firstSaved := s.server.ms.rateLimiter.db["peerID"]
// second call when limit is not accomplished does not store a new limit
- s.True(s.server.exceedsPeerRequests([]byte("peerID")))
- s.Equal(1, len(s.server.rateLimiter.db))
- s.Equal(firstSaved, s.server.rateLimiter.db["peerID"])
+ s.True(s.server.ms.exceedsPeerRequests(types.BytesToHash([]byte("peerID"))))
+ s.Equal(1, len(s.server.ms.rateLimiter.db))
+ s.Equal(firstSaved, s.server.ms.rateLimiter.db["peerID"])
}
func (s *MailserverSuite) TestDBKey() {
@@ -317,31 +317,28 @@ func (s *MailserverSuite) TestRequestPaginationLimit() {
reqLimit := uint32(6)
peerID, request, err := s.prepareRequest(sentEnvelopes, reqLimit)
s.NoError(err)
- lower, upper, bloom, limit, cursor, err := s.server.validateRequest(peerID, request)
+ payload, err := s.server.decompositeRequest(peerID, request)
s.NoError(err)
- s.Nil(cursor)
- s.Equal(reqLimit, limit)
+ s.Nil(payload.Cursor)
+ s.Equal(reqLimit, payload.Limit)
- receivedHashes, cursor, _ = processRequestAndCollectHashes(
- s.server, lower, upper, cursor, bloom, int(limit),
- )
+ receivedHashes, cursor, _ := processRequestAndCollectHashes(s.server, payload)
// 10 envelopes sent
s.Equal(count, uint32(len(sentEnvelopes)))
// 6 envelopes received
- s.Len(receivedHashes, int(limit))
+ s.Len(receivedHashes, int(payload.Limit))
// the 6 envelopes received should be in forward order
- s.Equal(sentHashes[:limit], receivedHashes)
+ s.Equal(sentHashes[:payload.Limit], receivedHashes)
// cursor should be the key of the last envelope of the last page
- s.Equal(archiveKeys[limit-1], fmt.Sprintf("%x", cursor))
+ s.Equal(archiveKeys[payload.Limit-1], fmt.Sprintf("%x", cursor))
// second page
- receivedHashes, cursor, _ = processRequestAndCollectHashes(
- s.server, lower, upper, cursor, bloom, int(limit),
- )
+ payload.Cursor = cursor
+ receivedHashes, cursor, _ = processRequestAndCollectHashes(s.server, payload)
// 4 envelopes received
- s.Equal(int(count-limit), len(receivedHashes))
+ s.Equal(int(count-payload.Limit), len(receivedHashes))
// cursor is nil because there are no other pages
s.Nil(cursor)
}
@@ -418,17 +415,17 @@ func (s *MailserverSuite) TestMailServer() {
s.T().Run(tc.info, func(*testing.T) {
request := s.createRequest(tc.params)
src := crypto.FromECDSAPub(&tc.params.key.PublicKey)
- lower, upper, bloom, limit, _, err := s.server.validateRequest(src, request)
+ payload, err := s.server.decompositeRequest(src, request)
s.Equal(tc.isOK, err == nil)
if err == nil {
- s.Equal(tc.params.low, lower)
- s.Equal(tc.params.upp, upper)
- s.Equal(tc.params.limit, limit)
- s.Equal(types.TopicToBloom(tc.params.topic), bloom)
- s.Equal(tc.expect, s.messageExists(env, tc.params.low, tc.params.upp, bloom, tc.params.limit))
+ s.Equal(tc.params.low, payload.Lower)
+ s.Equal(tc.params.upp, payload.Upper)
+ s.Equal(tc.params.limit, payload.Limit)
+ s.Equal(types.TopicToBloom(tc.params.topic), payload.Bloom)
+ s.Equal(tc.expect, s.messageExists(env, tc.params.low, tc.params.upp, payload.Bloom, tc.params.limit))
src[0]++
- _, _, _, _, _, err = s.server.validateRequest(src, request)
+ _, err = s.server.decompositeRequest(src, request)
s.True(err == nil)
}
})
@@ -509,7 +506,7 @@ func (s *MailserverSuite) TestProcessRequestDeadlockHandling() {
// Prepare a request.
peerID, request, err := s.prepareRequest(archievedEnvelopes, 5)
s.NoError(err)
- lower, upper, bloom, limit, cursor, err := s.server.validateRequest(peerID, request)
+ payload, err := s.server.decompositeRequest(peerID, request)
s.NoError(err)
testCases := []struct {
@@ -533,7 +530,7 @@ func (s *MailserverSuite) TestProcessRequestDeadlockHandling() {
processFinished := make(chan struct{})
go func() {
- s.server.processRequestInBundles(iter, bloom, int(limit), timeout, "req-01", bundles, done)
+ s.server.ms.processRequestInBundles(iter, payload.Bloom, int(payload.Limit), timeout, "req-01", bundles, done)
close(processFinished)
}()
go close(done)
@@ -557,7 +554,7 @@ func (s *MailserverSuite) TestProcessRequestDeadlockHandling() {
processFinished := make(chan struct{})
go func() {
- s.server.processRequestInBundles(iter, bloom, int(limit), time.Second, "req-01", bundles, done)
+ s.server.ms.processRequestInBundles(iter, payload.Bloom, int(payload.Limit), time.Second, "req-01", bundles, done)
close(processFinished)
}()
@@ -572,7 +569,7 @@ func (s *MailserverSuite) TestProcessRequestDeadlockHandling() {
for _, tc := range testCases {
s.T().Run(tc.Name, func(t *testing.T) {
- iter, err := s.server.createIterator(lower, upper, cursor, nil, 0)
+ iter, err := s.server.ms.createIterator(payload)
s.Require().NoError(err)
defer iter.Release()
@@ -587,9 +584,12 @@ func (s *MailserverSuite) TestProcessRequestDeadlockHandling() {
}
func (s *MailserverSuite) messageExists(envelope *whisper.Envelope, low, upp uint32, bloom []byte, limit uint32) bool {
- receivedHashes, _, _ := processRequestAndCollectHashes(
- s.server, low, upp, nil, bloom, int(limit),
- )
+ receivedHashes, _, _ := processRequestAndCollectHashes(s.server, MessagesRequestPayload{
+ Lower: low,
+ Upper: upp,
+ Bloom: bloom,
+ Limit: limit,
+ })
for _, hash := range receivedHashes {
if hash == envelope.Hash() {
return true
@@ -634,11 +634,11 @@ func (s *MailserverSuite) TestBloomFromReceivedMessage() {
}
}
-func (s *MailserverSuite) setupServer(server *WMailServer) {
+func (s *MailserverSuite) setupServer(server *WhisperMailServer) {
const password = "password_for_this_test"
s.shh = whisper.New(&whisper.DefaultConfig)
- s.shh.RegisterServer(server)
+ s.shh.RegisterMailServer(server)
err := server.Init(s.shh, ¶ms.WhisperConfig{
DataDir: s.dataDir,
@@ -770,10 +770,8 @@ func generateEnvelope(sentTime time.Time) (*whisper.Envelope, error) {
return generateEnvelopeWithKeys(sentTime, h[:], nil)
}
-func processRequestAndCollectHashes(
- server *WMailServer, lower, upper uint32, cursor []byte, bloom []byte, limit int,
-) ([]common.Hash, []byte, types.Hash) {
- iter, _ := server.createIterator(lower, upper, cursor, nil, 0)
+func processRequestAndCollectHashes(server *WhisperMailServer, payload MessagesRequestPayload) ([]common.Hash, []byte, types.Hash) {
+ iter, _ := server.ms.createIterator(payload)
defer iter.Release()
bundles := make(chan []rlp.RawValue, 10)
done := make(chan struct{})
@@ -782,34 +780,19 @@ func processRequestAndCollectHashes(
go func() {
for bundle := range bundles {
for _, rawEnvelope := range bundle {
-
var env *whisper.Envelope
if err := rlp.DecodeBytes(rawEnvelope, &env); err != nil {
panic(err)
}
-
hashes = append(hashes, env.Hash())
}
}
close(done)
}()
- cursor, lastHash := server.processRequestInBundles(iter, bloom, limit, time.Minute, "req-01", bundles, done)
+ cursor, lastHash := server.ms.processRequestInBundles(iter, payload.Bloom, int(payload.Limit), time.Minute, "req-01", bundles, done)
<-done
return hashes, cursor, lastHash
}
-
-// mockPeerWithID is a struct that conforms to peerWithID interface.
-type mockPeerWithID struct {
- id []byte
-}
-
-func (p mockPeerWithID) ID() []byte { return p.id }
-
-func TestPeerIDString(t *testing.T) {
- a := []byte{0x01, 0x02, 0x03}
- require.Equal(t, "010203", peerIDString(&mockPeerWithID{a}))
- require.Equal(t, "010203", peerIDBytesString(a))
-}
diff --git a/mailserver/request.go b/mailserver/request.go
index 9dbb76a50..903790200 100644
--- a/mailserver/request.go
+++ b/mailserver/request.go
@@ -1,5 +1,14 @@
package mailserver
+import (
+ "errors"
+ "time"
+)
+
+const (
+ maxMessagesRequestPayloadLimit = 1000
+)
+
// MessagesRequestPayload is a payload sent to the Mail Server.
type MessagesRequestPayload struct {
// Lower is a lower bound of time range for which messages are requested.
@@ -15,3 +24,29 @@ type MessagesRequestPayload struct {
// Batch set to true indicates that the client supports batched response.
Batch bool
}
+
+func (r *MessagesRequestPayload) SetDefaults() {
+ if r.Limit == 0 {
+ r.Limit = maxQueryLimit
+ }
+
+ if r.Upper == 0 {
+ r.Upper = uint32(time.Now().Unix() + whisperTTLSafeThreshold)
+ }
+}
+
+func (r MessagesRequestPayload) Validate() error {
+ if r.Upper < r.Lower {
+ return errors.New("query range is invalid: lower > upper")
+ }
+ if r.Upper-r.Lower > uint32(maxQueryRange.Seconds()) {
+ return errors.New("query range must be smaller or equal to 24 hours")
+ }
+ if len(r.Bloom) == 0 {
+ return errors.New("bloom filter is empty")
+ }
+ if r.Limit > maxMessagesRequestPayloadLimit {
+ return errors.New("limit exceeds the maximum allowed value")
+ }
+ return nil
+}
diff --git a/node/node.go b/node/node.go
index cda02b22d..153cb2dce 100644
--- a/node/node.go
+++ b/node/node.go
@@ -37,6 +37,7 @@ import (
"github.com/status-im/status-go/services/status"
"github.com/status-im/status-go/static"
"github.com/status-im/status-go/timesource"
+ "github.com/status-im/status-go/waku"
"github.com/status-im/status-go/whisper/v6"
)
@@ -44,6 +45,7 @@ import (
var (
ErrNodeMakeFailureFormat = "error creating p2p node: %s"
ErrWhisperServiceRegistrationFailure = errors.New("failed to register the Whisper service")
+ ErrWakuServiceRegistrationFailure = errors.New("failed to register the Waku service")
ErrLightEthRegistrationFailure = errors.New("failed to register the LES service")
ErrLightEthRegistrationFailureUpstreamEnabled = errors.New("failed to register the LES service, upstream is also configured")
ErrPersonalServiceRegistrationFailure = errors.New("failed to register the personal api service")
@@ -81,6 +83,14 @@ func MakeNode(config *params.NodeConfig, accs *accounts.Manager, db *leveldb.DB)
return nil, fmt.Errorf(ErrNodeMakeFailureFormat, err.Error())
}
+ if config.EnableNTPSync {
+ if err = stack.Register(func(*node.ServiceContext) (node.Service, error) {
+ return timesource.Default(), nil
+ }); err != nil {
+ return nil, fmt.Errorf("failed to register NTP time source: %v", err)
+ }
+ }
+
err = activateServices(stack, config, accs, db)
if err != nil {
return nil, err
@@ -119,11 +129,24 @@ func activateServices(stack *node.Node, config *params.NodeConfig, accs *account
}
func activateNodeServices(stack *node.Node, config *params.NodeConfig, db *leveldb.DB) error {
+ // Register eth-node node bridge
+ err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
+ return &nodebridge.NodeService{Node: gethbridge.NewNodeBridge(stack)}, nil
+ })
+ if err != nil {
+ return fmt.Errorf("failed to register NodeBridhe: %v", err)
+ }
+
// start Whisper service.
if err := activateShhService(stack, config, db); err != nil {
return fmt.Errorf("%v: %v", ErrWhisperServiceRegistrationFailure, err)
}
+ // start Waku service
+ if err := activateWakuService(stack, config, db); err != nil {
+ return fmt.Errorf("%v: %v", ErrWakuServiceRegistrationFailure, err)
+ }
+
// start incentivisation service
if err := activateIncentivisationService(stack, config); err != nil {
return fmt.Errorf("%v: %v", ErrIncentivisationServiceRegistrationFailure, err)
@@ -290,26 +313,26 @@ func activatePeerService(stack *node.Node) error {
})
}
-func registerMailServer(whisperService *whisper.Whisper, config *params.WhisperConfig) (err error) {
- var mailServer mailserver.WMailServer
- whisperService.RegisterServer(&mailServer)
+func registerWhisperMailServer(whisperService *whisper.Whisper, config *params.WhisperConfig) (err error) {
+ var mailServer mailserver.WhisperMailServer
+ whisperService.RegisterMailServer(&mailServer)
return mailServer.Init(whisperService, config)
}
+func registerWakuMailServer(wakuService *waku.Waku, config *params.WakuConfig) (err error) {
+ var mailServer mailserver.WakuMailServer
+ wakuService.RegisterMailServer(&mailServer)
+
+ return mailServer.Init(wakuService, config)
+}
+
// activateShhService configures Whisper and adds it to the given node.
func activateShhService(stack *node.Node, config *params.NodeConfig, db *leveldb.DB) (err error) {
if !config.WhisperConfig.Enabled {
logger.Info("SHH protocol is disabled")
return nil
}
- if config.WhisperConfig.EnableNTPSync {
- if err = stack.Register(func(*node.ServiceContext) (node.Service, error) {
- return timesource.Default(), nil
- }); err != nil {
- return
- }
- }
err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
return createShhService(ctx, &config.WhisperConfig, &config.ClusterConfig)
@@ -318,14 +341,6 @@ func activateShhService(stack *node.Node, config *params.NodeConfig, db *leveldb
return
}
- // Register eth-node node bridge
- err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
- return &nodebridge.NodeService{Node: gethbridge.NewNodeBridge(stack)}, nil
- })
- if err != nil {
- return
- }
-
// Register Whisper eth-node bridge
err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
var ethnode *nodebridge.NodeService
@@ -352,6 +367,25 @@ func activateShhService(stack *node.Node, config *params.NodeConfig, db *leveldb
})
}
+// activateWakuService configures Waku and adds it to the given node.
+func activateWakuService(stack *node.Node, config *params.NodeConfig, db *leveldb.DB) (err error) {
+ if !config.WakuConfig.Enabled {
+ logger.Info("Waku protocol is disabled")
+ return nil
+ }
+
+ err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
+ return createWakuService(ctx, &config.WakuConfig, &config.ClusterConfig)
+ })
+ if err != nil {
+ return
+ }
+
+ // TODO: what to do with shhext?
+
+ return nil
+}
+
func createShhService(ctx *node.ServiceContext, whisperConfig *params.WhisperConfig, clusterConfig *params.ClusterConfig) (*whisper.Whisper, error) {
whisperServiceConfig := &whisper.Config{
MaxMessageSize: whisper.DefaultMaxMessageSize,
@@ -372,17 +406,13 @@ func createShhService(ctx *node.ServiceContext, whisperConfig *params.WhisperCon
whisperService.SetRateLimiter(r)
}
- if whisperConfig.EnableNTPSync {
- timesource, err := whisperTimeSource(ctx)
- if err != nil {
- return nil, err
- }
+ if timesource, err := timeSource(ctx); err == nil {
whisperService.SetTimeSource(timesource)
}
// enable mail service
if whisperConfig.EnableMailServer {
- if err := registerMailServer(whisperService, whisperConfig); err != nil {
+ if err := registerWhisperMailServer(whisperService, whisperConfig); err != nil {
return nil, fmt.Errorf("failed to register MailServer: %v", err)
}
}
@@ -397,6 +427,48 @@ func createShhService(ctx *node.ServiceContext, whisperConfig *params.WhisperCon
return whisperService, nil
}
+func createWakuService(ctx *node.ServiceContext, wakuCfg *params.WakuConfig, clusterCfg *params.ClusterConfig) (*waku.Waku, error) {
+ cfg := &waku.Config{
+ MaxMessageSize: waku.DefaultMaxMessageSize,
+ MinimumAcceptedPoW: params.WakuMinimumPoW,
+ }
+
+ if wakuCfg.MaxMessageSize > 0 {
+ cfg.MaxMessageSize = wakuCfg.MaxMessageSize
+ }
+ if wakuCfg.MinimumPoW > 0 {
+ cfg.MinimumAcceptedPoW = wakuCfg.MinimumPoW
+ }
+
+ // TODO: provide a logger
+ w := waku.New(cfg, nil)
+
+ if wakuCfg.EnableRateLimiter {
+ r := wakuRateLimiter(wakuCfg, clusterCfg)
+ w.RegisterRateLimiter(r)
+ }
+
+ if timesource, err := timeSource(ctx); err == nil {
+ w.SetTimeSource(timesource)
+ }
+
+ // enable mail service
+ if wakuCfg.EnableMailServer {
+ if err := registerWakuMailServer(w, wakuCfg); err != nil {
+ return nil, fmt.Errorf("failed to register WakuMailServer: %v", err)
+ }
+ }
+
+ if wakuCfg.LightClient {
+ emptyBloomFilter := make([]byte, 64)
+ if err := w.SetBloomFilter(emptyBloomFilter); err != nil {
+ return nil, err
+ }
+ }
+
+ return w, nil
+}
+
// activateIncentivisationService configures Whisper and adds it to the given node.
func activateIncentivisationService(stack *node.Node, config *params.NodeConfig) (err error) {
if !config.WhisperConfig.Enabled {
@@ -478,8 +550,8 @@ func parseNodesToNodeID(enodes []string) []enode.ID {
return nodeIDs
}
-// whisperTimeSource get timeSource to be used by whisper
-func whisperTimeSource(ctx *node.ServiceContext) (func() time.Time, error) {
+// timeSource get timeSource to be used by whisper
+func timeSource(ctx *node.ServiceContext) (func() time.Time, error) {
var timeSource *timesource.NTPTimeSource
if err := ctx.Service(&timeSource); err != nil {
return nil, err
@@ -513,3 +585,30 @@ func whisperRateLimiter(whisperConfig *params.WhisperConfig, clusterConfig *para
},
)
}
+
+func wakuRateLimiter(wakuCfg *params.WakuConfig, clusterCfg *params.ClusterConfig) *waku.PeerRateLimiter {
+ enodes := append(
+ parseNodes(clusterCfg.StaticNodes),
+ parseNodes(clusterCfg.TrustedMailServers)...,
+ )
+ var (
+ ips []string
+ peerIDs []enode.ID
+ )
+ for _, item := range enodes {
+ ips = append(ips, item.IP().String())
+ peerIDs = append(peerIDs, item.ID())
+ }
+ return waku.NewPeerRateLimiter(
+ &waku.PeerRateLimiterConfig{
+ LimitPerSecIP: wakuCfg.RateLimitIP,
+ LimitPerSecPeerID: wakuCfg.RateLimitPeerID,
+ WhitelistedIPs: ips,
+ WhitelistedPeerIDs: peerIDs,
+ },
+ &whisper.MetricsRateLimiterHandler{},
+ &whisper.DropPeerRateLimiterHandler{
+ Tolerance: wakuCfg.RateLimitTolerance,
+ },
+ )
+}
diff --git a/node/node_api_test.go b/node/node_api_test.go
index 04c5e9a8c..6f809b668 100644
--- a/node/node_api_test.go
+++ b/node/node_api_test.go
@@ -13,6 +13,7 @@ import (
func TestWhisperLightModeEnabledSetsEmptyBloomFilter(t *testing.T) {
config := params.NodeConfig{
+ EnableNTPSync: true,
WhisperConfig: params.WhisperConfig{
Enabled: true,
LightClient: true,
@@ -35,6 +36,7 @@ func TestWhisperLightModeEnabledSetsEmptyBloomFilter(t *testing.T) {
func TestWhisperLightModeEnabledSetsNilBloomFilter(t *testing.T) {
config := params.NodeConfig{
+ EnableNTPSync: true,
WhisperConfig: params.WhisperConfig{
Enabled: true,
LightClient: false,
diff --git a/node/status_node_test.go b/node/status_node_test.go
index d0bb1ee6e..284b0458e 100644
--- a/node/status_node_test.go
+++ b/node/status_node_test.go
@@ -90,6 +90,7 @@ func TestStatusNodeWithDataDir(t *testing.T) {
func TestStatusNodeServiceGetters(t *testing.T) {
config := params.NodeConfig{
+ EnableNTPSync: true,
WhisperConfig: params.WhisperConfig{
Enabled: true,
},
diff --git a/params/config.go b/params/config.go
index 78e541309..29f736b42 100644
--- a/params/config.go
+++ b/params/config.go
@@ -43,6 +43,25 @@ type LightEthConfig struct {
MinTrustedFraction int
}
+// ----------
+// DatabaseConfig
+// ----------
+
+type DatabaseConfig struct {
+ PGConfig PGConfig
+}
+
+// ----------
+// PGConfig
+// ----------
+
+type PGConfig struct {
+ // Enabled whether we should use a Postgres instance
+ Enabled bool
+ // The URI of the server
+ URI string
+}
+
// ----------
// WhisperConfig
// ----------
@@ -81,9 +100,6 @@ type WhisperConfig struct {
// TTL time to live for messages, in seconds
TTL int
- // EnableNTPSync enables NTP synchronizations
- EnableNTPSync bool
-
// MaxMessageSize is a maximum size of a devp2p packet handled by the Whisper protocol,
// not only the size of envelopes sent in that packet.
MaxMessageSize uint32
@@ -108,23 +124,71 @@ type WhisperConfig struct {
RateLimitTolerance int64
}
-type DatabaseConfig struct {
- PGConfig PGConfig
-}
-
-type PGConfig struct {
- // Enabled whether we should use a Postgres instance
- Enabled bool
- // The URI of the server
- URI string
-}
-
// String dumps config object as nicely indented JSON
func (c *WhisperConfig) String() string {
data, _ := json.MarshalIndent(c, "", " ") // nolint: gas
return string(data)
}
+// ----------
+// WakuConfig
+// ----------
+
+// WakuConfig provides a configuration for Waku service.
+type WakuConfig struct {
+ // Enabled set to true enables Waku subprotocol.
+ Enabled bool
+
+ // LightClient should be true if the node should start with an empty bloom filter and not forward messages from other nodes
+ LightClient bool
+
+ // EnableMailServer is mode when node is capable of delivering expired messages on demand
+ EnableMailServer bool
+
+ // DataDir is the file system folder Whisper should use for any data storage needs.
+ // For instance, MailServer will use this directory to store its data.
+ DataDir string
+
+ // MinimumPoW minimum PoW for Whisper messages
+ MinimumPoW float64
+
+ // MailServerPassword for symmetric encryption of whisper message history requests.
+ // (if no account file selected, then this password is used for symmetric encryption).
+ MailServerPassword string
+
+ // MailServerRateLimit minimum time between queries to mail server per peer.
+ MailServerRateLimit int
+
+ // MailServerDataRetention is a number of days data should be stored by MailServer.
+ MailServerDataRetention int
+
+ // TTL time to live for messages, in seconds
+ TTL int
+
+ // MaxMessageSize is a maximum size of a devp2p packet handled by the Whisper protocol,
+ // not only the size of envelopes sent in that packet.
+ MaxMessageSize uint32
+
+ // DatabaseConfig is configuration for which data store we use.
+ DatabaseConfig DatabaseConfig
+
+ // EnableRateLimiter set to true enables IP and peer ID rate limiting.
+ EnableRateLimiter bool
+
+ // RateLimitIP sets the limit on the number of messages per second
+ // from a given IP.
+ RateLimitIP int64
+
+ // RateLimitPeerID sets the limit on the number of messages per second
+ // from a given peer ID.
+ RateLimitPeerID int64
+
+ // RateLimitTolerance is a number of how many a limit must be exceeded
+ // in order to drop a peer.
+ // If equal to 0, the peers are never dropped.
+ RateLimitTolerance int64
+}
+
// IncentivisationConfig holds incentivisation-related configuration
type IncentivisationConfig struct {
// Enabled flag specifies whether protocol is enabled
@@ -343,6 +407,9 @@ type NodeConfig struct {
// EnableStatusService should be true to enable methods under status namespace.
EnableStatusService bool
+ // EnableNTPSync enables NTP synchronizations
+ EnableNTPSync bool
+
// UpstreamConfig extra config for providing upstream infura server.
UpstreamConfig UpstreamRPCConfig `json:"UpstreamConfig"`
@@ -355,6 +422,9 @@ type NodeConfig struct {
// WhisperConfig extra configuration for SHH
WhisperConfig WhisperConfig `json:"WhisperConfig," validate:"structonly"`
+ // WakuConfig provides a configuration for Waku subprotocol.
+ WakuConfig WakuConfig `json:"WakuConfig" validate:"structonly"`
+
// IncentivisationConfig extra configuration for incentivisation service
IncentivisationConfig IncentivisationConfig `json:"IncentivisationConfig," validate:"structonly"`
@@ -505,8 +575,8 @@ func NewNodeConfigWithDefaults(dataDir string, networkID uint64, opts ...Option)
c.LogCompressRotated = true
c.LogMaxBackups = 3
c.LogToStderr = true
+ c.EnableNTPSync = true
c.WhisperConfig.Enabled = true
- c.WhisperConfig.EnableNTPSync = true
for _, opt := range opts {
if err := opt(c); err != nil {
@@ -591,6 +661,7 @@ func NewNodeConfig(dataDir string, networkID uint64) (*NodeConfig, error) {
LogFile: "",
LogLevel: "ERROR",
NoDiscovery: true,
+ EnableNTPSync: true,
UpstreamConfig: UpstreamRPCConfig{
URL: getUpstreamURL(networkID),
},
@@ -691,6 +762,10 @@ func (c *NodeConfig) Validate() error {
return err
}
+ if c.WhisperConfig.Enabled && c.WakuConfig.Enabled && c.WhisperConfig.DataDir == c.WakuConfig.DataDir {
+ return fmt.Errorf("both Whisper and Waku are enabled and use the same data dir")
+ }
+
// Whisper's data directory must be relative to the main data directory
// if EnableMailServer is true.
if c.WhisperConfig.Enabled && c.WhisperConfig.EnableMailServer {
diff --git a/params/config_test.go b/params/config_test.go
index fd5f99f6f..01329c208 100644
--- a/params/config_test.go
+++ b/params/config_test.go
@@ -29,10 +29,10 @@ func TestNewNodeConfigWithDefaults(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, "/some/data/path", c.DataDir)
assert.Equal(t, "/some/data/path/keystore", c.KeyStoreDir)
+ assert.Equal(t, true, c.EnableNTPSync)
// assert Whisper
assert.Equal(t, true, c.WhisperConfig.Enabled)
assert.Equal(t, "/some/data/path/wnode", c.WhisperConfig.DataDir)
- assert.Equal(t, true, c.WhisperConfig.EnableNTPSync)
// assert MailServer
assert.Equal(t, true, c.WhisperConfig.EnableMailServer)
assert.NotEmpty(t, c.WhisperConfig.MailServerPassword)
diff --git a/params/defaults.go b/params/defaults.go
index 811f943a4..1329bd807 100644
--- a/params/defaults.go
+++ b/params/defaults.go
@@ -27,6 +27,12 @@ const (
// WhisperTTL is time to live for messages, in seconds
WhisperTTL = 120
+ // WakuMinimumPoW amount of work for Whisper message to be added to sending queue
+ WakuMinimumPoW = 0.001
+
+ // WakuTTL is time to live for messages, in seconds
+ WakuTTL = 120
+
// MainnetEthereumNetworkURL is URL where the upstream ethereum network is loaded to
// allow us avoid syncing node.
MainnetEthereumNetworkURL = "https://mainnet.infura.io/nKmXgiFgc2KqtoQ8BCGJ"
diff --git a/protocol/go.sum b/protocol/go.sum
index 7886435ed..a146328d3 100644
--- a/protocol/go.sum
+++ b/protocol/go.sum
@@ -11,12 +11,14 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/DATA-DOG/go-sqlmock v1.3.3 h1:CWUqKXe0s8A2z6qCgkP4Kru7wC11YoAnoupUKFDnH08=
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
+github.com/DataDog/zstd v1.3.6-0.20190409195224-796139022798/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
github.com/Julusian/godocdown v0.0.0-20170816220326-6d19f8ff2df8/go.mod h1:INZr5t32rG59/5xeltqoCJoNY7e5x/3xoY9WSWVWg74=
github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y=
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
+github.com/Shopify/sarama v1.23.1/go.mod h1:XLH1GYJnLVE0XCr6KdJGVJRTwY30moWNJ4sERjXX6fs=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
@@ -30,12 +32,16 @@ github.com/allegro/bigcache v1.2.0 h1:qDaE0QoF29wKBb3+pXFrJFy1ihe5OT9OiXhg1t85Sx
github.com/allegro/bigcache v1.2.0/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/apilayer/freegeoip v3.5.0+incompatible/go.mod h1:CUfFqErhFhXneJendyQ/rRcuA8kH8JxHvYnbOozmlCU=
+github.com/aristanetworks/fsnotify v1.4.2/go.mod h1:D/rtu7LpjYM8tRJphJ0hUBYpjai8SfX+aSNsWDTq/Ks=
+github.com/aristanetworks/glog v0.0.0-20180419172825-c15b03b3054f/go.mod h1:KASm+qXFKs/xjSoWn30NrWBBvdTTQq+UjkhjEJHfSFA=
github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
github.com/aristanetworks/goarista v0.0.0-20181002214814-33151c4543a7/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
github.com/aristanetworks/goarista v0.0.0-20190219163901-728bce664cf5 h1:L0TwgZQo7Mga9im6FvKEZGIvyLE/VG/HI5loz5LpvC0=
github.com/aristanetworks/goarista v0.0.0-20190219163901-728bce664cf5/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
github.com/aristanetworks/goarista v0.0.0-20190502180301-283422fc1708 h1:tS7jSmwRqSxTnonTRlDD1oHo6Q9YOK4xHS9/v4L56eg=
github.com/aristanetworks/goarista v0.0.0-20190502180301-283422fc1708/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
+github.com/aristanetworks/goarista v0.0.0-20191106175434-873d404c7f40/go.mod h1:Z4RTxGAuYhPzcq8+EdRM+R8M48Ssle2TsWtwRKa+vns=
+github.com/aristanetworks/splunk-hec-go v0.3.3/go.mod h1:1VHO9r17b0K7WmOlLb9nTk/2YanvOEnLMUgsFrxBROc=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/beevik/ntp v0.2.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg=
@@ -137,6 +143,7 @@ github.com/fjl/memsize v0.0.0-20180929194037-2a09253e352a/go.mod h1:VvhXpOYNQvB+
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsouza/fake-gcs-server v1.7.0/go.mod h1:5XIRs4YvwNbNoz+1JF8j6KLAyDh7RHGAyAK3EP2EsNk=
+github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI=
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays=
@@ -209,6 +216,7 @@ github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/U
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
+github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/golang-lru v0.0.0-20160813221303-0a025b7e63ad/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
@@ -224,6 +232,7 @@ github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb v0.0.0-20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY=
github.com/influxdata/influxdb v1.7.7/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY=
+github.com/influxdata/influxdb1-client v0.0.0-20190809212627-fc22c7df067e/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
@@ -241,11 +250,13 @@ github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQ
github.com/jackpal/go-nat-pmp v0.0.0-20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jackpal/go-nat-pmp v1.0.1 h1:i0LektDkO1QlrTm/cSuP+PyBCDnYvjPLGl4LdWEMiaA=
github.com/jackpal/go-nat-pmp v1.0.1/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
+github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jbenet/go-cienv v0.0.0-20150120210510-1bb1476777ec/go.mod h1:rGaEvXB4uRSZMmzKNLoXvTu1sfx+1kv/DojUlPrSZGs=
github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA=
github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2/go.mod h1:8GXXJV31xl8whumTzdZsTt3RnUIiPqzkyf7mxToRCMs=
github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY=
github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4=
+github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jinzhu/copier v0.0.0-20190625015134-976e0346caa8 h1:mGIXW/lubQ4B+3bXTLxcTMTjUNDqoF6T/HUW9LbFx9s=
@@ -268,6 +279,8 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
+github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
+github.com/klauspost/reedsolomon v1.9.2/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk=
@@ -279,6 +292,7 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kshvakov/clickhouse v1.3.5/go.mod h1:DMzX7FxRymoNkVgizH0DWAL8Cur7wHLgx3MUnGwJqpE=
+github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
@@ -428,6 +442,8 @@ github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
+github.com/openconfig/gnmi v0.0.0-20190823184014-89b2bf29312c/go.mod h1:t+O9It+LKzfOAhKTT5O0ehDix+MTqbtT0T9t+7zzOvc=
+github.com/openconfig/reference v0.0.0-20190727015836-8dfd928c9696/go.mod h1:ym2A+zigScwkSEb/cVQB0/ZMpU3rqiH6X7WRRsxgOGw=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opentracing/opentracing-go v0.0.0-20180606204148-bd9c31933947/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
@@ -440,17 +456,20 @@ 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/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/peterh/liner v0.0.0-20170902204657-a37ad3984311/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
+github.com/pierrec/lz4 v0.0.0-20190327172049-315a67e90e41/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.0.0-20171216070316-e881fd58d78e/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
+github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
github.com/prometheus/client_golang v1.2.1 h1:JnMpQc6ppsNgw9QPAGF6Dod479itz7lvlsMzzNayLOI=
github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
@@ -461,12 +480,14 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.2.0/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.7.0 h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLyCY=
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
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-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
+github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
github.com/prometheus/procfs v0.0.5 h1:3+auTFlqw+ZaQYJARz6ArODtkaIwtvBTx3N2NehQlL8=
github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
github.com/prometheus/prometheus v0.0.0-20170814170113-3101606756c5/go.mod h1:oAIUtOny2rjMX0OWN5vPR5/q/twIROJvdqnQKDdil/s=
@@ -482,6 +503,7 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/cors v1.6.0 h1:G9tHG9lebljV9mfp9SNPDL36nCDxmo3zTlAf1YgvzmI=
github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
+github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ=
github.com/russolsen/ohyeah v0.0.0-20160324131710-f4938c005315 h1:H3hCXwP92pH/hSgNrCLtjxvsKJ50sq26nICbZuoR1tQ=
github.com/russolsen/ohyeah v0.0.0-20160324131710-f4938c005315/go.mod h1:ZbKa3zlLnhGF1dAeJtMSoNtM5LgFQnqzq8eYH3uYYkU=
@@ -531,6 +553,7 @@ github.com/status-im/status-go v0.37.3/go.mod h1:9qHQ2+8NS6ivPJS5YbsI3gWkr0t6DWm
github.com/status-im/status-go/extkeys v1.0.0 h1:Qyirsoi5Ye5UFfisgPtCjPb/RkBxyK+UsSiEcr2PVlM=
github.com/status-im/status-go/extkeys v1.0.0/go.mod h1:GdqJbrcpkNm5ZsSCpp+PdMxnXx+OcRBdm3PI0rs1FpU=
github.com/status-im/status-go/protocol v1.0.1/go.mod h1:LpA7BsaNmj6EOdq7BwuqncewjPqIRHCletZOb2wlWrY=
+github.com/status-im/status-go/waku v1.0.0/go.mod h1:1bjvQAL4cJYtxCsm6DnKdJbxcZwnvvZmxb6pmoUDtuY=
github.com/status-im/tcp-shaker v0.0.0-20191114194237-215893130501/go.mod h1:RYo/itke1oU5k/6sj9DNM3QAwtE5rZSgg5JnkOv83hk=
github.com/status-im/whisper v1.5.2 h1:26NgiKusmPic38eQdtXnaY+iaQ/LuQ3Dh0kCGYT/Uxs=
github.com/status-im/whisper v1.5.2/go.mod h1:emrOxzJme0k66QtbbQ2bdd3P8RCdLZ8sTD7SkwH1s2s=
@@ -553,7 +576,10 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/syndtr/goleveldb v0.0.0-20181128100959-b001fa50d6b2/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
+github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU=
+github.com/templexxx/xor v0.0.0-20181023030647-4e92f724b73b/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4=
github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
+github.com/tjfoc/gmsm v1.0.1/go.mod h1:XxO4hdhhrzAd+G4CjDqaOkd0hUzmtPR/d3EiBBMn/wc=
github.com/tsenart/tb v0.0.0-20181025101425-0d2499c8b6e9 h1:kjbwitOGH46vD01f2s3leBfrMnePQa3NSAIlW35MvY8=
github.com/tsenart/tb v0.0.0-20181025101425-0d2499c8b6e9/go.mod h1:EcGP24b8DY+bWHnpfJDP7fM+o8Nmz4fYH0l2xTtNr3I=
github.com/tyler-smith/go-bip39 v1.0.2 h1:+t3w+KwLXO6154GNJY+qUtIxLTmFjfUmpguQT1OlOT8=
@@ -583,6 +609,8 @@ github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVT
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
+github.com/xtaci/kcp-go v5.4.5+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE=
+github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE=
gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE=
go.mongodb.org/mongo-driver v1.1.0/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
@@ -609,6 +637,7 @@ golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -620,6 +649,7 @@ golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf h1:fnPsqIDRbCSgumaMCRpoIo
golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20191119213627-4f8c1d86b1ba h1:9bFeDpN3gTqNanMVqNcoR/pJQuP5uroC3t1D7eXozTE=
golang.org/x/crypto v0.0.0-20191119213627-4f8c1d86b1ba/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@@ -647,6 +677,7 @@ golang.org/x/net v0.0.0-20190424112056-4829fb13d2c6/go.mod h1:t9HGtf8HONx5eT2rtn
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 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3 h1:6KET3Sqa7fkVfD63QnAM81ZeYg5n4HwApOJkufONnHA=
golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -673,12 +704,15 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190426135247-a129542de9ae h1:mQLHiymj/JXKnnjc62tb7nD5pZLs940/sXJu+Xp3DBA=
golang.org/x/sys v0.0.0-20190426135247-a129542de9ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190912141932-bc967efca4b8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191113165036-4c7a9d0fe056 h1:dHtDnRWQtSx0Hjq9kvKFpBh9uPPKfQN70NZZmvssGwk=
@@ -700,7 +734,9 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190425222832-ad9eeb80039a/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190912185636-87d9f09c5d89/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191109212701-97ad0ed33101 h1:LCmXVkvpQCDj724eX6irUTPCJP5GelFHxqGSWL2D1R0=
@@ -721,7 +757,9 @@ google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRn
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
+google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
+gopkg.in/bsm/ratelimit.v1 v1.0.0-20160220154919-db14e161995a/go.mod h1:KF9sEfUPAXdG8Oev9e99iLGnl2uJMjc5B+4y3O7x610=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
@@ -733,6 +771,11 @@ gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8
gopkg.in/go-playground/validator.v9 v9.29.1 h1:SvGtYmN60a5CVKTOzMSyfzWDeZRxRuGvRQyEAKbw1xc=
gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
+gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo=
+gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q=
+gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4=
+gopkg.in/jcmturner/gokrb5.v7 v7.2.3/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM=
+gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8=
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/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU=
@@ -740,6 +783,7 @@ gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHN
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20180302121509-abf0ba0be5d5/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns=
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190709231704-1e4459ed25ff h1:uuol9OUzSvZntY1v963NAbVd7A+PHLMz1FlCe3Lorcs=
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190709231704-1e4459ed25ff/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns=
+gopkg.in/redis.v4 v4.2.4/go.mod h1:8KREHdypkCEojGKQcjMqAODMICIVwZAONWq8RowTITA=
gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8=
gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE=
@@ -754,5 +798,6 @@ gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
diff --git a/services/shhext/api.go b/services/shhext/api.go
index 22512d19f..e8371baf3 100644
--- a/services/shhext/api.go
+++ b/services/shhext/api.go
@@ -737,7 +737,7 @@ func makeEnvelop(
if err != nil {
return nil, err
}
- return gethbridge.NewGethEnvelopeWrapper(envelope), nil
+ return gethbridge.NewWhisperEnvelope(envelope), nil
}
// makeMessagesRequestPayload makes a specific payload for MailServer
diff --git a/services/shhext/history.go b/services/shhext/history.go
index 62f055261..60ce72af5 100644
--- a/services/shhext/history.go
+++ b/services/shhext/history.go
@@ -344,7 +344,7 @@ func (filter BloomFilterOption) ToMessagesRequestPayload() ([]byte, error) {
// Client must tell the MailServer if it supports batch responses.
// This can be removed in the future.
Batch: true,
- Limit: 10000,
+ Limit: 1000,
}
return rlp.EncodeToBytes(payload)
}
diff --git a/services/shhext/history_test.go b/services/shhext/history_test.go
index e7567045d..87b34a6d7 100644
--- a/services/shhext/history_test.go
+++ b/services/shhext/history_test.go
@@ -85,7 +85,7 @@ func TestBloomFilterToMessageRequestPayload(t *testing.T) {
Upper: end,
Bloom: filter,
Batch: true,
- Limit: 10000,
+ Limit: 1000,
}
bloomOption = BloomFilterOption{
Filter: filter,
diff --git a/services/shhext/service_test.go b/services/shhext/service_test.go
index b996d3329..8c354c577 100644
--- a/services/shhext/service_test.go
+++ b/services/shhext/service_test.go
@@ -566,7 +566,7 @@ type RequestWithTrackingHistorySuite struct {
localContext Context
mailSymKey string
- remoteMailserver *mailserver.WMailServer
+ remoteMailserver *mailserver.WhisperMailServer
remoteNode *enode.Node
remoteWhisper *whisper.Whisper
}
@@ -602,8 +602,8 @@ func (s *RequestWithTrackingHistorySuite) SetupTest() {
remoteSHH := whisper.New(conf)
s.remoteWhisper = remoteSHH
s.Require().NoError(remoteSHH.Start(nil))
- s.remoteMailserver = &mailserver.WMailServer{}
- remoteSHH.RegisterServer(s.remoteMailserver)
+ s.remoteMailserver = &mailserver.WhisperMailServer{}
+ remoteSHH.RegisterMailServer(s.remoteMailserver)
password := "test"
tmpdir, err = ioutil.TempDir("", "tracking-history-tests-")
s.Require().NoError(err)
diff --git a/t/e2e/whisper/whisper_mailbox_test.go b/t/e2e/whisper/whisper_mailbox_test.go
index af2bcfad0..e53f6b68f 100644
--- a/t/e2e/whisper/whisper_mailbox_test.go
+++ b/t/e2e/whisper/whisper_mailbox_test.go
@@ -488,10 +488,10 @@ func (s *WhisperMailboxSuite) TestSyncBetweenTwoMailServers() {
publicChatSymKey, err := mailboxWhisperService.GetSymKey(symKeyID)
s.Require().NoError(err)
- var mailServer mailserver.WMailServer
+ var mailServer mailserver.WhisperMailServer
err = mailServer.Init(mailboxWhisperService, &mailbox.StatusNode().Config().WhisperConfig)
s.Require().NoError(err)
- mailboxWhisperService.RegisterServer(&mailServer)
+ mailboxWhisperService.RegisterMailServer(&mailServer)
// envelopes to archive
envelopesCount := 5
@@ -548,7 +548,7 @@ func (s *WhisperMailboxSuite) TestSyncBetweenTwoMailServers() {
"shhext_syncMessages",
shhext.SyncMessagesRequest{
MailServerPeer: mailbox.StatusNode().Server().Self().URLv4(),
- From: 0,
+ From: uint32(time.Now().Add(-time.Hour).Unix()),
To: uint32(time.Now().Unix()),
Limit: 1,
},
@@ -567,7 +567,7 @@ func (s *WhisperMailboxSuite) TestSyncBetweenTwoMailServers() {
"shhext_syncMessages",
shhext.SyncMessagesRequest{
MailServerPeer: mailbox.StatusNode().Server().Self().URLv4(),
- From: 0,
+ From: uint32(time.Now().Add(-time.Hour).Unix()),
To: uint32(time.Now().Unix()),
Limit: 10,
Cursor: syncMessagesResponse.Cursor,
diff --git a/t/utils/utils.go b/t/utils/utils.go
index 73defd01d..af222a663 100644
--- a/t/utils/utils.go
+++ b/t/utils/utils.go
@@ -290,10 +290,10 @@ func MakeTestNodeConfigWithDataDir(name, dataDir string, networkID uint64) (*par
} else {
cfg.Name = name
}
+ cfg.EnableNTPSync = true
cfg.NoDiscovery = true
cfg.LightEthConfig.Enabled = false
cfg.WhisperConfig.Enabled = true
- cfg.WhisperConfig.EnableNTPSync = false
if dataDir != "" {
cfg.KeyStoreDir = path.Join(dataDir, "keystore")
cfg.WhisperConfig.DataDir = path.Join(dataDir, "wnode")
diff --git a/vendor/github.com/elastic/gosigar/CHANGELOG.md b/vendor/github.com/elastic/gosigar/CHANGELOG.md
index 9377542ab..ae848ffb1 100644
--- a/vendor/github.com/elastic/gosigar/CHANGELOG.md
+++ b/vendor/github.com/elastic/gosigar/CHANGELOG.md
@@ -12,6 +12,17 @@ This project adheres to [Semantic Versioning](http://semver.org/).
### Deprecated
+## [0.10.5]
+
+### Fixed
+
+- Fixed uptime calculation under Windows. #126
+- Fixed compilation issue for darwin/386. #128
+
+### Changed
+
+- Load DLLs only from Windows system directory. #132
+
## [0.10.4]
### Fixed
diff --git a/vendor/github.com/elastic/gosigar/README.md b/vendor/github.com/elastic/gosigar/README.md
index ecdfc1c3c..ca1854bf2 100644
--- a/vendor/github.com/elastic/gosigar/README.md
+++ b/vendor/github.com/elastic/gosigar/README.md
@@ -37,6 +37,7 @@ The features vary by operating system.
| ProcMem | X | X | X | | X |
| ProcState | X | X | X | | X |
| ProcTime | X | X | X | | X |
+| Rusage | X | | X | | |
| Swap | X | X | | X | X |
| Uptime | X | X | | X | X |
diff --git a/vendor/github.com/elastic/gosigar/sigar_darwin.go b/vendor/github.com/elastic/gosigar/sigar_darwin.go
index a90b998c2..4a8309521 100644
--- a/vendor/github.com/elastic/gosigar/sigar_darwin.go
+++ b/vendor/github.com/elastic/gosigar/sigar_darwin.go
@@ -40,18 +40,6 @@ func (self *LoadAverage) Get() error {
return nil
}
-func (self *Uptime) Get() error {
- tv := syscall.Timeval32{}
-
- if err := sysctlbyname("kern.boottime", &tv); err != nil {
- return err
- }
-
- self.Length = time.Since(time.Unix(int64(tv.Sec), int64(tv.Usec)*1000)).Seconds()
-
- return nil
-}
-
func (self *Mem) Get() error {
var vmstat C.vm_statistics_data_t
diff --git a/vendor/github.com/elastic/gosigar/sigar_darwin_386.go b/vendor/github.com/elastic/gosigar/sigar_darwin_386.go
new file mode 100644
index 000000000..92c7ff040
--- /dev/null
+++ b/vendor/github.com/elastic/gosigar/sigar_darwin_386.go
@@ -0,0 +1,18 @@
+package gosigar
+
+import (
+ "syscall"
+ "time"
+)
+
+func (self *Uptime) Get() error {
+ tv := syscall.Timeval{}
+
+ if err := sysctlbyname("kern.boottime", &tv); err != nil {
+ return err
+ }
+
+ self.Length = time.Since(time.Unix(int64(tv.Sec), int64(tv.Usec)*1000)).Seconds()
+
+ return nil
+}
diff --git a/vendor/github.com/elastic/gosigar/sigar_darwin_amd64.go b/vendor/github.com/elastic/gosigar/sigar_darwin_amd64.go
new file mode 100644
index 000000000..29e5b604a
--- /dev/null
+++ b/vendor/github.com/elastic/gosigar/sigar_darwin_amd64.go
@@ -0,0 +1,18 @@
+package gosigar
+
+import (
+ "syscall"
+ "time"
+)
+
+func (self *Uptime) Get() error {
+ tv := syscall.Timeval32{}
+
+ if err := sysctlbyname("kern.boottime", &tv); err != nil {
+ return err
+ }
+
+ self.Length = time.Since(time.Unix(int64(tv.Sec), int64(tv.Usec)*1000)).Seconds()
+
+ return nil
+}
diff --git a/vendor/github.com/elastic/gosigar/sigar_interface.go b/vendor/github.com/elastic/gosigar/sigar_interface.go
index df79ae08d..57501b969 100644
--- a/vendor/github.com/elastic/gosigar/sigar_interface.go
+++ b/vendor/github.com/elastic/gosigar/sigar_interface.go
@@ -4,6 +4,7 @@ import (
"time"
)
+// ErrNotImplemented is returned when a particular statistic isn't implemented on the host OS.
type ErrNotImplemented struct {
OS string
}
@@ -12,6 +13,7 @@ func (e ErrNotImplemented) Error() string {
return "not implemented on " + e.OS
}
+// IsNotImplemented returns true if the error is ErrNotImplemented
func IsNotImplemented(err error) bool {
switch err.(type) {
case ErrNotImplemented, *ErrNotImplemented:
@@ -21,6 +23,7 @@ func IsNotImplemented(err error) bool {
}
}
+// Sigar is an interface for gathering system host stats
type Sigar interface {
CollectCpuStats(collectionInterval time.Duration) (<-chan Cpu, chan<- struct{})
GetLoadAverage() (LoadAverage, error)
@@ -32,6 +35,7 @@ type Sigar interface {
GetRusage(who int) (Rusage, error)
}
+// Cpu contains CPU time stats
type Cpu struct {
User uint64
Nice uint64
@@ -43,11 +47,13 @@ type Cpu struct {
Stolen uint64
}
+// Total returns total CPU time
func (cpu *Cpu) Total() uint64 {
return cpu.User + cpu.Nice + cpu.Sys + cpu.Idle +
cpu.Wait + cpu.Irq + cpu.SoftIrq + cpu.Stolen
}
+// Delta returns the difference between two Cpu stat objects
func (cpu Cpu) Delta(other Cpu) Cpu {
return Cpu{
User: cpu.User - other.User,
@@ -61,14 +67,17 @@ func (cpu Cpu) Delta(other Cpu) Cpu {
}
}
+// LoadAverage reports standard load averages
type LoadAverage struct {
One, Five, Fifteen float64
}
+// Uptime reports system uptime
type Uptime struct {
Length float64
}
+// Mem contains host memory stats
type Mem struct {
Total uint64
Used uint64
@@ -77,12 +86,14 @@ type Mem struct {
ActualUsed uint64
}
+// Swap contains stats on swap space
type Swap struct {
Total uint64
Used uint64
Free uint64
}
+// HugeTLBPages contains HugePages stats
type HugeTLBPages struct {
Total uint64
Free uint64
@@ -92,16 +103,19 @@ type HugeTLBPages struct {
TotalAllocatedSize uint64
}
+// CpuList contains a list of CPUs on the host system
type CpuList struct {
List []Cpu
}
+// FDUsage contains stats on filesystem usage
type FDUsage struct {
Open uint64
Unused uint64
Max uint64
}
+// FileSystem contains basic information about a given mounted filesystem
type FileSystem struct {
DirName string
DevName string
@@ -111,10 +125,12 @@ type FileSystem struct {
Flags uint32
}
+// FileSystemList gets a list of mounted filesystems
type FileSystemList struct {
List []FileSystem
}
+// FileSystemUsage contains basic stats for the specified filesystem
type FileSystemUsage struct {
Total uint64
Used uint64
@@ -124,21 +140,30 @@ type FileSystemUsage struct {
FreeFiles uint64
}
+// ProcList contains a list of processes found on the host system
type ProcList struct {
List []int
}
+// RunState is a byte-long code used to specify the current runtime state of a process
type RunState byte
const (
- RunStateSleep = 'S'
- RunStateRun = 'R'
- RunStateStop = 'T'
- RunStateZombie = 'Z'
- RunStateIdle = 'D'
+ // RunStateSleep corresponds to a sleep state
+ RunStateSleep = 'S'
+ // RunStateRun corresponds to a running state
+ RunStateRun = 'R'
+ // RunStateStop corresponds to a stopped state
+ RunStateStop = 'T'
+ // RunStateZombie marks a zombie process
+ RunStateZombie = 'Z'
+ // RunStateIdle corresponds to an idle state
+ RunStateIdle = 'D'
+ // RunStateUnknown corresponds to a process in an unknown state
RunStateUnknown = '?'
)
+// ProcState contains basic metadata and process ownership info for the specified process
type ProcState struct {
Name string
Username string
@@ -151,6 +176,7 @@ type ProcState struct {
Processor int
}
+// ProcMem contains memory statistics for a specified process
type ProcMem struct {
Size uint64
Resident uint64
@@ -160,6 +186,7 @@ type ProcMem struct {
PageFaults uint64
}
+// ProcTime contains run time statistics for a specified process
type ProcTime struct {
StartTime uint64
User uint64
@@ -167,26 +194,31 @@ type ProcTime struct {
Total uint64
}
+// ProcArgs contains a list of args for a specified process
type ProcArgs struct {
List []string
}
+// ProcEnv contains a map of environment variables for specified process
type ProcEnv struct {
Vars map[string]string
}
+// ProcExe contains basic data about a specified process
type ProcExe struct {
Name string
Cwd string
Root string
}
+// ProcFDUsage contains data on file limits and usage
type ProcFDUsage struct {
Open uint64
SoftLimit uint64
HardLimit uint64
}
+// Rusage contains data on resource usage for a specified process
type Rusage struct {
Utime time.Duration
Stime time.Duration
diff --git a/vendor/github.com/elastic/gosigar/sigar_windows.go b/vendor/github.com/elastic/gosigar/sigar_windows.go
index fc868daf3..d1204b80e 100644
--- a/vendor/github.com/elastic/gosigar/sigar_windows.go
+++ b/vendor/github.com/elastic/gosigar/sigar_windows.go
@@ -8,7 +8,6 @@ import (
"path/filepath"
"runtime"
"strings"
- "sync"
"syscall"
"time"
@@ -24,11 +23,6 @@ var (
// 2003 and XP where PROCESS_QUERY_LIMITED_INFORMATION is unknown. For all newer
// OS versions it is set to PROCESS_QUERY_LIMITED_INFORMATION.
processQueryLimitedInfoAccess = windows.PROCESS_QUERY_LIMITED_INFORMATION
-
- // bootTime is the time when the OS was last booted. This value may be nil
- // on operating systems that do not support the WMI query used to obtain it.
- bootTime *time.Time
- bootTimeLock sync.Mutex
)
func init() {
@@ -63,19 +57,11 @@ func (self *Uptime) Get() error {
if !version.IsWindowsVistaOrGreater() {
return ErrNotImplemented{runtime.GOOS}
}
-
- bootTimeLock.Lock()
- defer bootTimeLock.Unlock()
- if bootTime == nil {
- uptime, err := windows.GetTickCount64()
- if err != nil {
- return errors.Wrap(err, "failed to get boot time using win32 api")
- }
- var boot = time.Unix(int64(uptime), 0)
- bootTime = &boot
+ uptimeMs, err := windows.GetTickCount64()
+ if err != nil {
+ return errors.Wrap(err, "failed to get boot time using GetTickCount64 api")
}
-
- self.Length = time.Since(*bootTime).Seconds()
+ self.Length = float64(time.Duration(uptimeMs)*time.Millisecond) / float64(time.Second)
return nil
}
diff --git a/vendor/github.com/elastic/gosigar/sys/windows/doc.go b/vendor/github.com/elastic/gosigar/sys/windows/doc.go
index dda57aa83..9dca12504 100644
--- a/vendor/github.com/elastic/gosigar/sys/windows/doc.go
+++ b/vendor/github.com/elastic/gosigar/sys/windows/doc.go
@@ -1,2 +1,8 @@
// Package windows contains various Windows system call.
package windows
+
+// Use "go generate -v -x ." to generate the source.
+
+// Add -trace to enable debug prints around syscalls.
+//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -systemdll=true -output zsyscall_windows.go syscall_windows.go
+//go:generate go run fix_generated.go -input zsyscall_windows.go
diff --git a/vendor/github.com/elastic/gosigar/sys/windows/syscall_windows.go b/vendor/github.com/elastic/gosigar/sys/windows/syscall_windows.go
index 0c11fda31..371eb256b 100644
--- a/vendor/github.com/elastic/gosigar/sys/windows/syscall_windows.go
+++ b/vendor/github.com/elastic/gosigar/sys/windows/syscall_windows.go
@@ -580,11 +580,6 @@ func GetTickCount64() (uptime uint64, err error) {
return uptime, nil
}
-// Use "GOOS=windows go generate -v -x ." to generate the source.
-
-// Add -trace to enable debug prints around syscalls.
-//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -systemdll=false -output zsyscall_windows.go syscall_windows.go
-
// Windows API calls
//sys _GlobalMemoryStatusEx(buffer *MemoryStatusEx) (err error) = kernel32.GlobalMemoryStatusEx
//sys _GetLogicalDriveStringsW(bufferLength uint32, buffer *uint16) (length uint32, err error) = kernel32.GetLogicalDriveStringsW
diff --git a/vendor/github.com/elastic/gosigar/sys/windows/zsyscall_windows.go b/vendor/github.com/elastic/gosigar/sys/windows/zsyscall_windows.go
index cd5d9ca32..75f19c0ea 100644
--- a/vendor/github.com/elastic/gosigar/sys/windows/zsyscall_windows.go
+++ b/vendor/github.com/elastic/gosigar/sys/windows/zsyscall_windows.go
@@ -5,6 +5,8 @@ package windows
import (
"syscall"
"unsafe"
+
+ "golang.org/x/sys/windows"
)
var _ unsafe.Pointer
@@ -35,10 +37,10 @@ func errnoErr(e syscall.Errno) error {
}
var (
- modkernel32 = syscall.NewLazyDLL("kernel32.dll")
- modpsapi = syscall.NewLazyDLL("psapi.dll")
- modntdll = syscall.NewLazyDLL("ntdll.dll")
- modadvapi32 = syscall.NewLazyDLL("advapi32.dll")
+ modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
+ modpsapi = windows.NewLazySystemDLL("psapi.dll")
+ modntdll = windows.NewLazySystemDLL("ntdll.dll")
+ modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
procGlobalMemoryStatusEx = modkernel32.NewProc("GlobalMemoryStatusEx")
procGetLogicalDriveStringsW = modkernel32.NewProc("GetLogicalDriveStringsW")
diff --git a/vendor/github.com/jackpal/go-nat-pmp/.travis.yml b/vendor/github.com/jackpal/go-nat-pmp/.travis.yml
index b939153f7..3f468e74b 100644
--- a/vendor/github.com/jackpal/go-nat-pmp/.travis.yml
+++ b/vendor/github.com/jackpal/go-nat-pmp/.travis.yml
@@ -1,7 +1,7 @@
language: go
go:
- - 1.6.2
+ - 1.13.4
- tip
allowed_failures:
@@ -11,10 +11,3 @@ install:
- go get -d -v ./... && go install -race -v ./...
script: go test -race -v ./...
-
-sudo: false
-
-addons:
- apt:
- packages:
- - iproute2
diff --git a/vendor/github.com/jackpal/go-nat-pmp/README.md b/vendor/github.com/jackpal/go-nat-pmp/README.md
index 3ca687f0b..cc45afe56 100644
--- a/vendor/github.com/jackpal/go-nat-pmp/README.md
+++ b/vendor/github.com/jackpal/go-nat-pmp/README.md
@@ -6,7 +6,7 @@ IP address of a firewall.
NAT-PMP is supported by Apple brand routers and open source routers like Tomato and DD-WRT.
-See http://tools.ietf.org/html/draft-cheshire-nat-pmp-03
+See https://tools.ietf.org/rfc/rfc6886.txt
[![Build Status](https://travis-ci.org/jackpal/go-nat-pmp.svg)](https://travis-ci.org/jackpal/go-nat-pmp)
@@ -14,27 +14,53 @@ See http://tools.ietf.org/html/draft-cheshire-nat-pmp-03
Get the package
---------------
+ # Get the go-nat-pmp package.
go get -u github.com/jackpal/go-nat-pmp
-
+
Usage
-----
+Get one more package, used by the example code:
+
+ go get -u github.com/jackpal/gateway
+
+ Create a directory:
+
+ cd ~/go
+ mkdir -p src/hello
+ cd src/hello
+
+Create a file hello.go with these contents:
+
+ package main
+
import (
+ "fmt"
+
"github.com/jackpal/gateway"
natpmp "github.com/jackpal/go-nat-pmp"
)
- gatewayIP, err = gateway.DiscoverGateway()
- if err != nil {
- return
+ func main() {
+ gatewayIP, err := gateway.DiscoverGateway()
+ if err != nil {
+ return
+ }
+
+ client := natpmp.NewClient(gatewayIP)
+ response, err := client.GetExternalAddress()
+ if err != nil {
+ return
+ }
+ fmt.Printf("External IP address: %v\n", response.ExternalIPAddress)
}
- client := natpmp.NewClient(gatewayIP)
- response, err := client.GetExternalAddress()
- if err != nil {
- return
- }
- print("External IP address:", response.ExternalIPAddress)
+Build the example
+
+ go build
+ ./hello
+
+ External IP address: [www xxx yyy zzz]
Clients
-------
diff --git a/vendor/github.com/jackpal/go-nat-pmp/natpmp.go b/vendor/github.com/jackpal/go-nat-pmp/natpmp.go
index e42065306..f296c817e 100644
--- a/vendor/github.com/jackpal/go-nat-pmp/natpmp.go
+++ b/vendor/github.com/jackpal/go-nat-pmp/natpmp.go
@@ -3,34 +3,43 @@ package natpmp
import (
"fmt"
"net"
+ "time"
)
// Implement the NAT-PMP protocol, typically supported by Apple routers and open source
// routers such as DD-WRT and Tomato.
//
-// See http://tools.ietf.org/html/draft-cheshire-nat-pmp-03
+// See https://tools.ietf.org/rfc/rfc6886.txt
//
// Usage:
//
// client := natpmp.NewClient(gatewayIP)
// response, err := client.GetExternalAddress()
-// The recommended mapping lifetime for AddPortMapping
+// The recommended mapping lifetime for AddPortMapping.
const RECOMMENDED_MAPPING_LIFETIME_SECONDS = 3600
// Interface used to make remote procedure calls.
type caller interface {
- call(msg []byte) (result []byte, err error)
+ call(msg []byte, timeout time.Duration) (result []byte, err error)
}
// Client is a NAT-PMP protocol client.
type Client struct {
- caller caller
+ caller caller
+ timeout time.Duration
}
// Create a NAT-PMP client for the NAT-PMP server at the gateway.
+// Uses default timeout which is around 128 seconds.
func NewClient(gateway net.IP) (nat *Client) {
- return &Client{&network{gateway}}
+ return &Client{&network{gateway}, 0}
+}
+
+// Create a NAT-PMP client for the NAT-PMP server at the gateway, with a timeout.
+// Timeout defines the total amount of time we will keep retrying before giving up.
+func NewClientWithTimeout(gateway net.IP, timeout time.Duration) (nat *Client) {
+ return &Client{&network{gateway}, timeout}
}
// Results of the NAT-PMP GetExternalAddress operation.
@@ -40,6 +49,8 @@ type GetExternalAddressResult struct {
}
// Get the external address of the router.
+//
+// Note that this call can take up to 128 seconds to return.
func (n *Client) GetExternalAddress() (result *GetExternalAddressResult, err error) {
msg := make([]byte, 2)
msg[0] = 0 // Version 0
@@ -62,7 +73,8 @@ type AddPortMappingResult struct {
PortMappingLifetimeInSeconds uint32
}
-// Add (or delete) a port mapping. To delete a mapping, set the requestedExternalPort and lifetime to 0
+// Add (or delete) a port mapping. To delete a mapping, set the requestedExternalPort and lifetime to 0.
+// Note that this call can take up to 128 seconds to return.
func (n *Client) AddPortMapping(protocol string, internalPort, requestedExternalPort int, lifetime int) (result *AddPortMappingResult, err error) {
var opcode byte
if protocol == "udp" {
@@ -76,6 +88,7 @@ func (n *Client) AddPortMapping(protocol string, internalPort, requestedExternal
msg := make([]byte, 12)
msg[0] = 0 // Version 0
msg[1] = opcode
+ // [2:3] is reserved.
writeNetworkOrderUint16(msg[4:6], uint16(internalPort))
writeNetworkOrderUint16(msg[6:8], uint16(requestedExternalPort))
writeNetworkOrderUint32(msg[8:12], uint32(lifetime))
@@ -92,7 +105,7 @@ func (n *Client) AddPortMapping(protocol string, internalPort, requestedExternal
}
func (n *Client) rpc(msg []byte, resultSize int) (result []byte, err error) {
- result, err = n.caller.call(msg)
+ result, err = n.caller.call(msg, n.timeout)
if err != nil {
return
}
diff --git a/vendor/github.com/jackpal/go-nat-pmp/network.go b/vendor/github.com/jackpal/go-nat-pmp/network.go
index 9def1acda..c42b4fee9 100644
--- a/vendor/github.com/jackpal/go-nat-pmp/network.go
+++ b/vendor/github.com/jackpal/go-nat-pmp/network.go
@@ -2,7 +2,6 @@ package natpmp
import (
"fmt"
- "log"
"net"
"time"
)
@@ -16,7 +15,7 @@ type network struct {
gateway net.IP
}
-func (n *network) call(msg []byte) (result []byte, err error) {
+func (n *network) call(msg []byte, timeout time.Duration) (result []byte, err error) {
var server net.UDPAddr
server.IP = n.gateway
server.Port = nAT_PMP_PORT
@@ -29,12 +28,18 @@ func (n *network) call(msg []byte) (result []byte, err error) {
// 16 bytes is the maximum result size.
result = make([]byte, 16)
+ var finalTimeout time.Time
+ if timeout != 0 {
+ finalTimeout = time.Now().Add(timeout)
+ }
+
needNewDeadline := true
var tries uint
- for tries = 0; tries < nAT_TRIES; {
+ for tries = 0; (tries < nAT_TRIES && finalTimeout.IsZero()) || time.Now().Before(finalTimeout); {
if needNewDeadline {
- err = conn.SetDeadline(time.Now().Add((nAT_INITIAL_MS << tries) * time.Millisecond))
+ nextDeadline := time.Now().Add((nAT_INITIAL_MS << tries) * time.Millisecond)
+ err = conn.SetDeadline(minTime(nextDeadline, finalTimeout))
if err != nil {
return
}
@@ -56,7 +61,6 @@ func (n *network) call(msg []byte) (result []byte, err error) {
return
}
if !remoteAddr.IP.Equal(n.gateway) {
- log.Printf("Ignoring packet because IPs differ:", remoteAddr, n.gateway)
// Ignore this packet.
// Continue without increasing retransmission timeout or deadline.
continue
@@ -70,3 +74,16 @@ func (n *network) call(msg []byte) (result []byte, err error) {
err = fmt.Errorf("Timed out trying to contact gateway")
return
}
+
+func minTime(a, b time.Time) time.Time {
+ if a.IsZero() {
+ return b
+ }
+ if b.IsZero() {
+ return a
+ }
+ if a.Before(b) {
+ return a
+ }
+ return b
+}
diff --git a/vendor/github.com/jackpal/go-nat-pmp/recorder.go b/vendor/github.com/jackpal/go-nat-pmp/recorder.go
index e70a3c65c..845703672 100644
--- a/vendor/github.com/jackpal/go-nat-pmp/recorder.go
+++ b/vendor/github.com/jackpal/go-nat-pmp/recorder.go
@@ -1,5 +1,7 @@
package natpmp
+import "time"
+
type callObserver interface {
observeCall(msg []byte, result []byte, err error)
}
@@ -10,8 +12,8 @@ type recorder struct {
observer callObserver
}
-func (n *recorder) call(msg []byte) (result []byte, err error) {
- result, err = n.child.call(msg)
+func (n *recorder) call(msg []byte, timeout time.Duration) (result []byte, err error) {
+ result, err = n.child.call(msg, timeout)
n.observer.observeCall(msg, result, err)
return
}
diff --git a/vendor/github.com/rs/cors/.travis.yml b/vendor/github.com/rs/cors/.travis.yml
index 17e5e50d5..9a68b5676 100644
--- a/vendor/github.com/rs/cors/.travis.yml
+++ b/vendor/github.com/rs/cors/.travis.yml
@@ -1,7 +1,8 @@
language: go
go:
-- 1.9
- "1.10"
+- "1.11"
+- "1.12"
- tip
matrix:
allow_failures:
diff --git a/vendor/github.com/rs/cors/cors.go b/vendor/github.com/rs/cors/cors.go
index d301ca724..273093463 100644
--- a/vendor/github.com/rs/cors/cors.go
+++ b/vendor/github.com/rs/cors/cors.go
@@ -5,8 +5,8 @@ as defined by http://www.w3.org/TR/cors/
You can configure it by passing an option struct to cors.New:
c := cors.New(cors.Options{
- AllowedOrigins: []string{"foo.com"},
- AllowedMethods: []string{"GET", "POST", "DELETE"},
+ AllowedOrigins: []string{"foo.com"},
+ AllowedMethods: []string{http.MethodGet, http.MethodPost, http.MethodDelete},
AllowCredentials: true,
})
@@ -69,10 +69,15 @@ type Options struct {
Debug bool
}
+// Logger generic interface for logger
+type Logger interface {
+ Printf(string, ...interface{})
+}
+
// Cors http handler
type Cors struct {
// Debug logger
- Log *log.Logger
+ Log Logger
// Normalized list of plain allowed origins
allowedOrigins []string
// List of allowed origins containing wildcards
@@ -106,7 +111,7 @@ func New(options Options) *Cors {
maxAge: options.MaxAge,
optionPassthrough: options.OptionsPassthrough,
}
- if options.Debug {
+ if options.Debug && c.Log == nil {
c.Log = log.New(os.Stdout, "[cors] ", log.LstdFlags)
}
@@ -161,7 +166,7 @@ func New(options Options) *Cors {
// Allowed Methods
if len(options.AllowedMethods) == 0 {
// Default is spec's "simple" methods
- c.allowedMethods = []string{"GET", "POST", "HEAD"}
+ c.allowedMethods = []string{http.MethodGet, http.MethodPost, http.MethodHead}
} else {
c.allowedMethods = convert(options.AllowedMethods, strings.ToUpper)
}
@@ -178,8 +183,15 @@ func Default() *Cors {
// origins with all standard methods with any header and credentials.
func AllowAll() *Cors {
return New(Options{
- AllowedOrigins: []string{"*"},
- AllowedMethods: []string{"HEAD", "GET", "POST", "PUT", "PATCH", "DELETE"},
+ AllowedOrigins: []string{"*"},
+ AllowedMethods: []string{
+ http.MethodHead,
+ http.MethodGet,
+ http.MethodPost,
+ http.MethodPut,
+ http.MethodPatch,
+ http.MethodDelete,
+ },
AllowedHeaders: []string{"*"},
AllowCredentials: false,
})
@@ -304,10 +316,6 @@ func (c *Cors) handleActualRequest(w http.ResponseWriter, r *http.Request) {
headers := w.Header()
origin := r.Header.Get("Origin")
- if r.Method == http.MethodOptions {
- c.logf(" Actual request no headers added: method == %s", r.Method)
- return
- }
// Always set Vary, see https://github.com/rs/cors/issues/10
headers.Add("Vary", "Origin")
if origin == "" {
@@ -342,7 +350,7 @@ func (c *Cors) handleActualRequest(w http.ResponseWriter, r *http.Request) {
c.logf(" Actual response added headers: %v", headers)
}
-// convenience method. checks if debugging is turned on before printing
+// convenience method. checks if a logger is set.
func (c *Cors) logf(format string, a ...interface{}) {
if c.Log != nil {
c.Log.Printf(format, a...)
diff --git a/vendor/github.com/rs/cors/utils.go b/vendor/github.com/rs/cors/utils.go
index 53ad9e9db..db83ac3ea 100644
--- a/vendor/github.com/rs/cors/utils.go
+++ b/vendor/github.com/rs/cors/utils.go
@@ -12,7 +12,7 @@ type wildcard struct {
}
func (w wildcard) match(s string) bool {
- return len(s) >= len(w.prefix+w.suffix) && strings.HasPrefix(s, w.prefix) && strings.HasSuffix(s, w.suffix)
+ return len(s) >= len(w.prefix)+len(w.suffix) && strings.HasPrefix(s, w.prefix) && strings.HasSuffix(s, w.suffix)
}
// convert converts a list of string using the passed converter function
diff --git a/vendor/github.com/status-im/status-go/eth-node/bridge/geth/envelope.go b/vendor/github.com/status-im/status-go/eth-node/bridge/geth/envelope.go
index 884760b06..64b9306bf 100644
--- a/vendor/github.com/status-im/status-go/eth-node/bridge/geth/envelope.go
+++ b/vendor/github.com/status-im/status-go/eth-node/bridge/geth/envelope.go
@@ -2,29 +2,102 @@ package gethbridge
import (
"github.com/status-im/status-go/eth-node/types"
+ "github.com/status-im/status-go/waku"
"github.com/status-im/status-go/whisper/v6"
)
-type gethEnvelopeWrapper struct {
- envelope *whisper.Envelope
+type whisperEnvelope struct {
+ env *whisper.Envelope
}
-// NewGethEnvelopeWrapper returns an object that wraps Geth's Envelope in a types interface
-func NewGethEnvelopeWrapper(e *whisper.Envelope) types.Envelope {
- return &gethEnvelopeWrapper{
- envelope: e,
+// NewWhisperEnvelope returns an object that wraps Geth's Whisper Envelope in a types interface.
+func NewWhisperEnvelope(e *whisper.Envelope) types.Envelope {
+ return &whisperEnvelope{env: e}
+}
+
+func UnwrapWhisperEnvelope(e types.Envelope) (*whisper.Envelope, bool) {
+ if env, ok := e.(*whisperEnvelope); ok {
+ return env.env, true
}
+ return nil, false
}
-// GetGethEnvelopeFrom retrieves the underlying whisper Envelope struct from a wrapped Envelope interface
-func GetGethEnvelopeFrom(f types.Envelope) *whisper.Envelope {
- return f.(*gethEnvelopeWrapper).envelope
+func MustUnwrapWhisperEnvelope(e types.Envelope) *whisper.Envelope {
+ return e.(*whisperEnvelope).env
}
-func (w *gethEnvelopeWrapper) Hash() types.Hash {
- return types.Hash(w.envelope.Hash())
+func (w *whisperEnvelope) Hash() types.Hash {
+ return types.Hash(w.env.Hash())
}
-func (w *gethEnvelopeWrapper) Bloom() []byte {
- return w.envelope.Bloom()
+func (w *whisperEnvelope) Bloom() []byte {
+ return w.env.Bloom()
+}
+
+func (w *whisperEnvelope) PoW() float64 {
+ return w.env.PoW()
+}
+
+func (w *whisperEnvelope) Expiry() uint32 {
+ return w.env.Expiry
+}
+
+func (w *whisperEnvelope) TTL() uint32 {
+ return w.env.TTL
+}
+
+func (w *whisperEnvelope) Topic() types.TopicType {
+ return types.TopicType(w.env.Topic)
+}
+
+func (w *whisperEnvelope) Size() int {
+ return len(w.env.Data)
+}
+
+type wakuEnvelope struct {
+ env *waku.Envelope
+}
+
+// NewWakuEnvelope returns an object that wraps Geth's Waku Envelope in a types interface.
+func NewWakuEnvelope(e *waku.Envelope) types.Envelope {
+ return &wakuEnvelope{env: e}
+}
+
+func UnwrapWakuEnvelope(e types.Envelope) (*waku.Envelope, bool) {
+ if env, ok := e.(*wakuEnvelope); ok {
+ return env.env, true
+ }
+ return nil, false
+}
+
+func MustUnwrapWakuEnvelope(e types.Envelope) *waku.Envelope {
+ return e.(*wakuEnvelope).env
+}
+
+func (w *wakuEnvelope) Hash() types.Hash {
+ return types.Hash(w.env.Hash())
+}
+
+func (w *wakuEnvelope) Bloom() []byte {
+ return w.env.Bloom()
+}
+
+func (w *wakuEnvelope) PoW() float64 {
+ return w.env.PoW()
+}
+
+func (w *wakuEnvelope) Expiry() uint32 {
+ return w.env.Expiry
+}
+
+func (w *wakuEnvelope) TTL() uint32 {
+ return w.env.TTL
+}
+
+func (w *wakuEnvelope) Topic() types.TopicType {
+ return types.TopicType(w.env.Topic)
+}
+
+func (w *wakuEnvelope) Size() int {
+ return len(w.env.Data)
}
diff --git a/vendor/github.com/status-im/status-go/eth-node/bridge/geth/whisper.go b/vendor/github.com/status-im/status-go/eth-node/bridge/geth/whisper.go
index 53e9bf005..8e64db81c 100644
--- a/vendor/github.com/status-im/status-go/eth-node/bridge/geth/whisper.go
+++ b/vendor/github.com/status-im/status-go/eth-node/bridge/geth/whisper.go
@@ -166,7 +166,7 @@ func (w *gethWhisperWrapper) SendMessagesRequest(peerID []byte, r types.Messages
// which are not supposed to be forwarded any further.
// The whisper protocol is agnostic of the format and contents of envelope.
func (w *gethWhisperWrapper) RequestHistoricMessagesWithTimeout(peerID []byte, envelope types.Envelope, timeout time.Duration) error {
- return w.whisper.RequestHistoricMessagesWithTimeout(peerID, GetGethEnvelopeFrom(envelope), timeout)
+ return w.whisper.RequestHistoricMessagesWithTimeout(peerID, MustUnwrapWhisperEnvelope(envelope), timeout)
}
// SyncMessages can be sent between two Mail Servers and syncs envelopes between them.
diff --git a/vendor/github.com/status-im/status-go/eth-node/types/envelopes.go b/vendor/github.com/status-im/status-go/eth-node/types/envelopes.go
index 997343330..7f1cb424f 100644
--- a/vendor/github.com/status-im/status-go/eth-node/types/envelopes.go
+++ b/vendor/github.com/status-im/status-go/eth-node/types/envelopes.go
@@ -5,6 +5,11 @@ package types
type Envelope interface {
Hash() Hash // Cached hash of the envelope to avoid rehashing every time.
Bloom() []byte
+ PoW() float64
+ Expiry() uint32
+ TTL() uint32
+ Topic() TopicType
+ Size() int
}
// EventType used to define known envelope events.
diff --git a/vendor/github.com/status-im/status-go/eth-node/types/hash.go b/vendor/github.com/status-im/status-go/eth-node/types/hash.go
index 2b5dec17c..5c9d7c0e8 100644
--- a/vendor/github.com/status-im/status-go/eth-node/types/hash.go
+++ b/vendor/github.com/status-im/status-go/eth-node/types/hash.go
@@ -50,7 +50,7 @@ func (h Hash) Bytes() []byte { return h[:] }
// String implements the stringer interface and is used also by the logger when
// doing full logging into a file.
-func (h *Hash) String() string {
+func (h Hash) String() string {
return h.Hex()
}
diff --git a/vendor/github.com/status-im/status-go/protocol/go.sum b/vendor/github.com/status-im/status-go/protocol/go.sum
index 7886435ed..a146328d3 100644
--- a/vendor/github.com/status-im/status-go/protocol/go.sum
+++ b/vendor/github.com/status-im/status-go/protocol/go.sum
@@ -11,12 +11,14 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/DATA-DOG/go-sqlmock v1.3.3 h1:CWUqKXe0s8A2z6qCgkP4Kru7wC11YoAnoupUKFDnH08=
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
+github.com/DataDog/zstd v1.3.6-0.20190409195224-796139022798/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
github.com/Julusian/godocdown v0.0.0-20170816220326-6d19f8ff2df8/go.mod h1:INZr5t32rG59/5xeltqoCJoNY7e5x/3xoY9WSWVWg74=
github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y=
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
+github.com/Shopify/sarama v1.23.1/go.mod h1:XLH1GYJnLVE0XCr6KdJGVJRTwY30moWNJ4sERjXX6fs=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
@@ -30,12 +32,16 @@ github.com/allegro/bigcache v1.2.0 h1:qDaE0QoF29wKBb3+pXFrJFy1ihe5OT9OiXhg1t85Sx
github.com/allegro/bigcache v1.2.0/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/apilayer/freegeoip v3.5.0+incompatible/go.mod h1:CUfFqErhFhXneJendyQ/rRcuA8kH8JxHvYnbOozmlCU=
+github.com/aristanetworks/fsnotify v1.4.2/go.mod h1:D/rtu7LpjYM8tRJphJ0hUBYpjai8SfX+aSNsWDTq/Ks=
+github.com/aristanetworks/glog v0.0.0-20180419172825-c15b03b3054f/go.mod h1:KASm+qXFKs/xjSoWn30NrWBBvdTTQq+UjkhjEJHfSFA=
github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
github.com/aristanetworks/goarista v0.0.0-20181002214814-33151c4543a7/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
github.com/aristanetworks/goarista v0.0.0-20190219163901-728bce664cf5 h1:L0TwgZQo7Mga9im6FvKEZGIvyLE/VG/HI5loz5LpvC0=
github.com/aristanetworks/goarista v0.0.0-20190219163901-728bce664cf5/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
github.com/aristanetworks/goarista v0.0.0-20190502180301-283422fc1708 h1:tS7jSmwRqSxTnonTRlDD1oHo6Q9YOK4xHS9/v4L56eg=
github.com/aristanetworks/goarista v0.0.0-20190502180301-283422fc1708/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
+github.com/aristanetworks/goarista v0.0.0-20191106175434-873d404c7f40/go.mod h1:Z4RTxGAuYhPzcq8+EdRM+R8M48Ssle2TsWtwRKa+vns=
+github.com/aristanetworks/splunk-hec-go v0.3.3/go.mod h1:1VHO9r17b0K7WmOlLb9nTk/2YanvOEnLMUgsFrxBROc=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/beevik/ntp v0.2.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg=
@@ -137,6 +143,7 @@ github.com/fjl/memsize v0.0.0-20180929194037-2a09253e352a/go.mod h1:VvhXpOYNQvB+
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsouza/fake-gcs-server v1.7.0/go.mod h1:5XIRs4YvwNbNoz+1JF8j6KLAyDh7RHGAyAK3EP2EsNk=
+github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI=
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays=
@@ -209,6 +216,7 @@ github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/U
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
+github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/golang-lru v0.0.0-20160813221303-0a025b7e63ad/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
@@ -224,6 +232,7 @@ github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb v0.0.0-20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY=
github.com/influxdata/influxdb v1.7.7/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY=
+github.com/influxdata/influxdb1-client v0.0.0-20190809212627-fc22c7df067e/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
@@ -241,11 +250,13 @@ github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQ
github.com/jackpal/go-nat-pmp v0.0.0-20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jackpal/go-nat-pmp v1.0.1 h1:i0LektDkO1QlrTm/cSuP+PyBCDnYvjPLGl4LdWEMiaA=
github.com/jackpal/go-nat-pmp v1.0.1/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
+github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jbenet/go-cienv v0.0.0-20150120210510-1bb1476777ec/go.mod h1:rGaEvXB4uRSZMmzKNLoXvTu1sfx+1kv/DojUlPrSZGs=
github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA=
github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2/go.mod h1:8GXXJV31xl8whumTzdZsTt3RnUIiPqzkyf7mxToRCMs=
github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY=
github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4=
+github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jinzhu/copier v0.0.0-20190625015134-976e0346caa8 h1:mGIXW/lubQ4B+3bXTLxcTMTjUNDqoF6T/HUW9LbFx9s=
@@ -268,6 +279,8 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
+github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
+github.com/klauspost/reedsolomon v1.9.2/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk=
@@ -279,6 +292,7 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kshvakov/clickhouse v1.3.5/go.mod h1:DMzX7FxRymoNkVgizH0DWAL8Cur7wHLgx3MUnGwJqpE=
+github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
@@ -428,6 +442,8 @@ github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
+github.com/openconfig/gnmi v0.0.0-20190823184014-89b2bf29312c/go.mod h1:t+O9It+LKzfOAhKTT5O0ehDix+MTqbtT0T9t+7zzOvc=
+github.com/openconfig/reference v0.0.0-20190727015836-8dfd928c9696/go.mod h1:ym2A+zigScwkSEb/cVQB0/ZMpU3rqiH6X7WRRsxgOGw=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opentracing/opentracing-go v0.0.0-20180606204148-bd9c31933947/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
@@ -440,17 +456,20 @@ 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/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/peterh/liner v0.0.0-20170902204657-a37ad3984311/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
+github.com/pierrec/lz4 v0.0.0-20190327172049-315a67e90e41/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.0.0-20171216070316-e881fd58d78e/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
+github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
github.com/prometheus/client_golang v1.2.1 h1:JnMpQc6ppsNgw9QPAGF6Dod479itz7lvlsMzzNayLOI=
github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
@@ -461,12 +480,14 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.2.0/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.7.0 h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLyCY=
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
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-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
+github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
github.com/prometheus/procfs v0.0.5 h1:3+auTFlqw+ZaQYJARz6ArODtkaIwtvBTx3N2NehQlL8=
github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
github.com/prometheus/prometheus v0.0.0-20170814170113-3101606756c5/go.mod h1:oAIUtOny2rjMX0OWN5vPR5/q/twIROJvdqnQKDdil/s=
@@ -482,6 +503,7 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/cors v1.6.0 h1:G9tHG9lebljV9mfp9SNPDL36nCDxmo3zTlAf1YgvzmI=
github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
+github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ=
github.com/russolsen/ohyeah v0.0.0-20160324131710-f4938c005315 h1:H3hCXwP92pH/hSgNrCLtjxvsKJ50sq26nICbZuoR1tQ=
github.com/russolsen/ohyeah v0.0.0-20160324131710-f4938c005315/go.mod h1:ZbKa3zlLnhGF1dAeJtMSoNtM5LgFQnqzq8eYH3uYYkU=
@@ -531,6 +553,7 @@ github.com/status-im/status-go v0.37.3/go.mod h1:9qHQ2+8NS6ivPJS5YbsI3gWkr0t6DWm
github.com/status-im/status-go/extkeys v1.0.0 h1:Qyirsoi5Ye5UFfisgPtCjPb/RkBxyK+UsSiEcr2PVlM=
github.com/status-im/status-go/extkeys v1.0.0/go.mod h1:GdqJbrcpkNm5ZsSCpp+PdMxnXx+OcRBdm3PI0rs1FpU=
github.com/status-im/status-go/protocol v1.0.1/go.mod h1:LpA7BsaNmj6EOdq7BwuqncewjPqIRHCletZOb2wlWrY=
+github.com/status-im/status-go/waku v1.0.0/go.mod h1:1bjvQAL4cJYtxCsm6DnKdJbxcZwnvvZmxb6pmoUDtuY=
github.com/status-im/tcp-shaker v0.0.0-20191114194237-215893130501/go.mod h1:RYo/itke1oU5k/6sj9DNM3QAwtE5rZSgg5JnkOv83hk=
github.com/status-im/whisper v1.5.2 h1:26NgiKusmPic38eQdtXnaY+iaQ/LuQ3Dh0kCGYT/Uxs=
github.com/status-im/whisper v1.5.2/go.mod h1:emrOxzJme0k66QtbbQ2bdd3P8RCdLZ8sTD7SkwH1s2s=
@@ -553,7 +576,10 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/syndtr/goleveldb v0.0.0-20181128100959-b001fa50d6b2/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
+github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU=
+github.com/templexxx/xor v0.0.0-20181023030647-4e92f724b73b/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4=
github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
+github.com/tjfoc/gmsm v1.0.1/go.mod h1:XxO4hdhhrzAd+G4CjDqaOkd0hUzmtPR/d3EiBBMn/wc=
github.com/tsenart/tb v0.0.0-20181025101425-0d2499c8b6e9 h1:kjbwitOGH46vD01f2s3leBfrMnePQa3NSAIlW35MvY8=
github.com/tsenart/tb v0.0.0-20181025101425-0d2499c8b6e9/go.mod h1:EcGP24b8DY+bWHnpfJDP7fM+o8Nmz4fYH0l2xTtNr3I=
github.com/tyler-smith/go-bip39 v1.0.2 h1:+t3w+KwLXO6154GNJY+qUtIxLTmFjfUmpguQT1OlOT8=
@@ -583,6 +609,8 @@ github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVT
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
+github.com/xtaci/kcp-go v5.4.5+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE=
+github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE=
gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE=
go.mongodb.org/mongo-driver v1.1.0/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
@@ -609,6 +637,7 @@ golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -620,6 +649,7 @@ golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf h1:fnPsqIDRbCSgumaMCRpoIo
golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20191119213627-4f8c1d86b1ba h1:9bFeDpN3gTqNanMVqNcoR/pJQuP5uroC3t1D7eXozTE=
golang.org/x/crypto v0.0.0-20191119213627-4f8c1d86b1ba/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@@ -647,6 +677,7 @@ golang.org/x/net v0.0.0-20190424112056-4829fb13d2c6/go.mod h1:t9HGtf8HONx5eT2rtn
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 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3 h1:6KET3Sqa7fkVfD63QnAM81ZeYg5n4HwApOJkufONnHA=
golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -673,12 +704,15 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190426135247-a129542de9ae h1:mQLHiymj/JXKnnjc62tb7nD5pZLs940/sXJu+Xp3DBA=
golang.org/x/sys v0.0.0-20190426135247-a129542de9ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190912141932-bc967efca4b8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191113165036-4c7a9d0fe056 h1:dHtDnRWQtSx0Hjq9kvKFpBh9uPPKfQN70NZZmvssGwk=
@@ -700,7 +734,9 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190425222832-ad9eeb80039a/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190912185636-87d9f09c5d89/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191109212701-97ad0ed33101 h1:LCmXVkvpQCDj724eX6irUTPCJP5GelFHxqGSWL2D1R0=
@@ -721,7 +757,9 @@ google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRn
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
+google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
+gopkg.in/bsm/ratelimit.v1 v1.0.0-20160220154919-db14e161995a/go.mod h1:KF9sEfUPAXdG8Oev9e99iLGnl2uJMjc5B+4y3O7x610=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
@@ -733,6 +771,11 @@ gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8
gopkg.in/go-playground/validator.v9 v9.29.1 h1:SvGtYmN60a5CVKTOzMSyfzWDeZRxRuGvRQyEAKbw1xc=
gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
+gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo=
+gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q=
+gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4=
+gopkg.in/jcmturner/gokrb5.v7 v7.2.3/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM=
+gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8=
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/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU=
@@ -740,6 +783,7 @@ gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHN
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20180302121509-abf0ba0be5d5/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns=
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190709231704-1e4459ed25ff h1:uuol9OUzSvZntY1v963NAbVd7A+PHLMz1FlCe3Lorcs=
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190709231704-1e4459ed25ff/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns=
+gopkg.in/redis.v4 v4.2.4/go.mod h1:8KREHdypkCEojGKQcjMqAODMICIVwZAONWq8RowTITA=
gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8=
gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE=
@@ -754,5 +798,6 @@ gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
diff --git a/vendor/github.com/status-im/status-go/waku/api.go b/vendor/github.com/status-im/status-go/waku/api.go
new file mode 100644
index 000000000..73712bf7a
--- /dev/null
+++ b/vendor/github.com/status-im/status-go/waku/api.go
@@ -0,0 +1,600 @@
+// Copyright 2019 The Waku Library Authors.
+//
+// The Waku library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The Waku library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty off
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the Waku library. If not, see .
+//
+// This software uses the go-ethereum library, which is licensed
+// under the GNU Lesser General Public Library, version 3 or any later.
+
+package waku
+
+import (
+ "context"
+ "crypto/ecdsa"
+ "errors"
+ "fmt"
+ "sync"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/log"
+ "github.com/ethereum/go-ethereum/p2p/enode"
+ "github.com/ethereum/go-ethereum/rpc"
+)
+
+// List of errors
+var (
+ ErrSymAsym = errors.New("specify either a symmetric or an asymmetric key")
+ ErrInvalidSymmetricKey = errors.New("invalid symmetric key")
+ ErrInvalidPublicKey = errors.New("invalid public key")
+ ErrInvalidSigningPubKey = errors.New("invalid signing public key")
+ ErrTooLowPoW = errors.New("message rejected, PoW too low")
+ ErrNoTopics = errors.New("missing topic(s)")
+)
+
+// PublicWakuAPI provides the waku RPC service that can be
+// use publicly without security implications.
+type PublicWakuAPI struct {
+ w *Waku
+
+ mu sync.Mutex
+ lastUsed map[string]time.Time // keeps track when a filter was polled for the last time.
+}
+
+// NewPublicWakuAPI create a new RPC waku service.
+func NewPublicWakuAPI(w *Waku) *PublicWakuAPI {
+ api := &PublicWakuAPI{
+ w: w,
+ lastUsed: make(map[string]time.Time),
+ }
+ return api
+}
+
+// Version returns the Waku sub-protocol version.
+func (api *PublicWakuAPI) Version(ctx context.Context) string {
+ return ProtocolVersionStr
+}
+
+// Info contains diagnostic information.
+type Info struct {
+ Messages int `json:"messages"` // Number of floating messages.
+ MinPow float64 `json:"minPow"` // Minimal accepted PoW
+ MaxMessageSize uint32 `json:"maxMessageSize"` // Maximum accepted message size
+}
+
+// Info returns diagnostic information about the waku node.
+func (api *PublicWakuAPI) Info(ctx context.Context) Info {
+ return Info{
+ Messages: len(api.w.msgQueue) + len(api.w.p2pMsgQueue),
+ MinPow: api.w.MinPow(),
+ MaxMessageSize: api.w.MaxMessageSize(),
+ }
+}
+
+// SetMaxMessageSize sets the maximum message size that is accepted.
+// Upper limit is defined by MaxMessageSize.
+func (api *PublicWakuAPI) SetMaxMessageSize(ctx context.Context, size uint32) (bool, error) {
+ return true, api.w.SetMaxMessageSize(size)
+}
+
+// SetMinPoW sets the minimum PoW, and notifies the peers.
+func (api *PublicWakuAPI) SetMinPoW(ctx context.Context, pow float64) (bool, error) {
+ return true, api.w.SetMinimumPoW(pow, true)
+}
+
+// SetBloomFilter sets the new value of bloom filter, and notifies the peers.
+func (api *PublicWakuAPI) SetBloomFilter(ctx context.Context, bloom hexutil.Bytes) (bool, error) {
+ return true, api.w.SetBloomFilter(bloom)
+}
+
+// MarkTrustedPeer marks a peer trusted, which will allow it to send historic (expired) messages.
+// Note: This function is not adding new nodes, the node needs to exists as a peer.
+func (api *PublicWakuAPI) MarkTrustedPeer(ctx context.Context, url string) (bool, error) {
+ n, err := enode.Parse(enode.ValidSchemes, url)
+ if err != nil {
+ return false, err
+ }
+ return true, api.w.AllowP2PMessagesFromPeer(n.ID().Bytes())
+}
+
+// NewKeyPair generates a new public and private key pair for message decryption and encryption.
+// It returns an ID that can be used to refer to the keypair.
+func (api *PublicWakuAPI) NewKeyPair(ctx context.Context) (string, error) {
+ return api.w.NewKeyPair()
+}
+
+// AddPrivateKey imports the given private key.
+func (api *PublicWakuAPI) AddPrivateKey(ctx context.Context, privateKey hexutil.Bytes) (string, error) {
+ key, err := crypto.ToECDSA(privateKey)
+ if err != nil {
+ return "", err
+ }
+ return api.w.AddKeyPair(key)
+}
+
+// DeleteKeyPair removes the key with the given key if it exists.
+func (api *PublicWakuAPI) DeleteKeyPair(ctx context.Context, key string) (bool, error) {
+ if ok := api.w.DeleteKeyPair(key); ok {
+ return true, nil
+ }
+ return false, fmt.Errorf("key pair %s not found", key)
+}
+
+// HasKeyPair returns an indication if the node has a key pair that is associated with the given id.
+func (api *PublicWakuAPI) HasKeyPair(ctx context.Context, id string) bool {
+ return api.w.HasKeyPair(id)
+}
+
+// GetPublicKey returns the public key associated with the given key. The key is the hex
+// encoded representation of a key in the form specified in section 4.3.6 of ANSI X9.62.
+func (api *PublicWakuAPI) GetPublicKey(ctx context.Context, id string) (hexutil.Bytes, error) {
+ key, err := api.w.GetPrivateKey(id)
+ if err != nil {
+ return hexutil.Bytes{}, err
+ }
+ return crypto.FromECDSAPub(&key.PublicKey), nil
+}
+
+// GetPrivateKey returns the private key associated with the given key. The key is the hex
+// encoded representation of a key in the form specified in section 4.3.6 of ANSI X9.62.
+func (api *PublicWakuAPI) GetPrivateKey(ctx context.Context, id string) (hexutil.Bytes, error) {
+ key, err := api.w.GetPrivateKey(id)
+ if err != nil {
+ return hexutil.Bytes{}, err
+ }
+ return crypto.FromECDSA(key), nil
+}
+
+// NewSymKey generate a random symmetric key.
+// It returns an ID that can be used to refer to the key.
+// Can be used encrypting and decrypting messages where the key is known to both parties.
+func (api *PublicWakuAPI) NewSymKey(ctx context.Context) (string, error) {
+ return api.w.GenerateSymKey()
+}
+
+// AddSymKey import a symmetric key.
+// It returns an ID that can be used to refer to the key.
+// Can be used encrypting and decrypting messages where the key is known to both parties.
+func (api *PublicWakuAPI) AddSymKey(ctx context.Context, key hexutil.Bytes) (string, error) {
+ return api.w.AddSymKeyDirect([]byte(key))
+}
+
+// GenerateSymKeyFromPassword derive a key from the given password, stores it, and returns its ID.
+func (api *PublicWakuAPI) GenerateSymKeyFromPassword(ctx context.Context, passwd string) (string, error) {
+ return api.w.AddSymKeyFromPassword(passwd)
+}
+
+// HasSymKey returns an indication if the node has a symmetric key associated with the given key.
+func (api *PublicWakuAPI) HasSymKey(ctx context.Context, id string) bool {
+ return api.w.HasSymKey(id)
+}
+
+// GetSymKey returns the symmetric key associated with the given id.
+func (api *PublicWakuAPI) GetSymKey(ctx context.Context, id string) (hexutil.Bytes, error) {
+ return api.w.GetSymKey(id)
+}
+
+// DeleteSymKey deletes the symmetric key that is associated with the given id.
+func (api *PublicWakuAPI) DeleteSymKey(ctx context.Context, id string) bool {
+ return api.w.DeleteSymKey(id)
+}
+
+// MakeLightClient turns the node into light client, which does not forward
+// any incoming messages, and sends only messages originated in this node.
+func (api *PublicWakuAPI) MakeLightClient(ctx context.Context) bool {
+ api.w.SetLightClientMode(true)
+ return api.w.LightClientMode()
+}
+
+// CancelLightClient cancels light client mode.
+func (api *PublicWakuAPI) CancelLightClient(ctx context.Context) bool {
+ api.w.SetLightClientMode(false)
+ return !api.w.LightClientMode()
+}
+
+//go:generate gencodec -type NewMessage -field-override newMessageOverride -out gen_newmessage_json.go
+
+// NewMessage represents a new waku message that is posted through the RPC.
+type NewMessage struct {
+ SymKeyID string `json:"symKeyID"`
+ PublicKey []byte `json:"pubKey"`
+ Sig string `json:"sig"`
+ TTL uint32 `json:"ttl"`
+ Topic TopicType `json:"topic"`
+ Payload []byte `json:"payload"`
+ Padding []byte `json:"padding"`
+ PowTime uint32 `json:"powTime"`
+ PowTarget float64 `json:"powTarget"`
+ TargetPeer string `json:"targetPeer"`
+}
+
+type newMessageOverride struct {
+ PublicKey hexutil.Bytes
+ Payload hexutil.Bytes
+ Padding hexutil.Bytes
+}
+
+// Post posts a message on the Waku network.
+// returns the hash of the message in case of success.
+func (api *PublicWakuAPI) Post(ctx context.Context, req NewMessage) (hexutil.Bytes, error) {
+ var (
+ symKeyGiven = len(req.SymKeyID) > 0
+ pubKeyGiven = len(req.PublicKey) > 0
+ err error
+ )
+
+ // user must specify either a symmetric or an asymmetric key
+ if (symKeyGiven && pubKeyGiven) || (!symKeyGiven && !pubKeyGiven) {
+ return nil, ErrSymAsym
+ }
+
+ params := &MessageParams{
+ TTL: req.TTL,
+ Payload: req.Payload,
+ Padding: req.Padding,
+ WorkTime: req.PowTime,
+ PoW: req.PowTarget,
+ Topic: req.Topic,
+ }
+
+ // Set key that is used to sign the message
+ if len(req.Sig) > 0 {
+ if params.Src, err = api.w.GetPrivateKey(req.Sig); err != nil {
+ return nil, err
+ }
+ }
+
+ // Set symmetric key that is used to encrypt the message
+ if symKeyGiven {
+ if params.Topic == (TopicType{}) { // topics are mandatory with symmetric encryption
+ return nil, ErrNoTopics
+ }
+ if params.KeySym, err = api.w.GetSymKey(req.SymKeyID); err != nil {
+ return nil, err
+ }
+ if !validateDataIntegrity(params.KeySym, aesKeyLength) {
+ return nil, ErrInvalidSymmetricKey
+ }
+ }
+
+ // Set asymmetric key that is used to encrypt the message
+ if pubKeyGiven {
+ if params.Dst, err = crypto.UnmarshalPubkey(req.PublicKey); err != nil {
+ return nil, ErrInvalidPublicKey
+ }
+ }
+
+ // encrypt and sent message
+ msg, err := NewSentMessage(params)
+ if err != nil {
+ return nil, err
+ }
+
+ var result []byte
+ env, err := msg.Wrap(params, api.w.CurrentTime())
+ if err != nil {
+ return nil, err
+ }
+
+ // send to specific node (skip PoW check)
+ if len(req.TargetPeer) > 0 {
+ n, err := enode.Parse(enode.ValidSchemes, req.TargetPeer)
+ if err != nil {
+ return nil, fmt.Errorf("failed to parse target peer: %s", err)
+ }
+ err = api.w.SendP2PMessages(n.ID().Bytes(), env)
+ if err == nil {
+ hash := env.Hash()
+ result = hash[:]
+ }
+ return result, err
+ }
+
+ // ensure that the message PoW meets the node's minimum accepted PoW
+ if req.PowTarget < api.w.MinPow() {
+ return nil, ErrTooLowPoW
+ }
+
+ err = api.w.Send(env)
+ if err == nil {
+ hash := env.Hash()
+ result = hash[:]
+ }
+ return result, err
+}
+
+// UninstallFilter is alias for Unsubscribe
+func (api *PublicWakuAPI) UninstallFilter(id string) {
+ api.w.Unsubscribe(id)
+}
+
+// Unsubscribe disables and removes an existing filter.
+func (api *PublicWakuAPI) Unsubscribe(id string) {
+ api.w.Unsubscribe(id)
+}
+
+//go:generate gencodec -type Criteria -field-override criteriaOverride -out gen_criteria_json.go
+
+// Criteria holds various filter options for inbound messages.
+type Criteria struct {
+ SymKeyID string `json:"symKeyID"`
+ PrivateKeyID string `json:"privateKeyID"`
+ Sig []byte `json:"sig"`
+ MinPow float64 `json:"minPow"`
+ Topics []TopicType `json:"topics"`
+ AllowP2P bool `json:"allowP2P"`
+}
+
+type criteriaOverride struct {
+ Sig hexutil.Bytes
+}
+
+// Messages set up a subscription that fires events when messages arrive that match
+// the given set of criteria.
+func (api *PublicWakuAPI) Messages(ctx context.Context, crit Criteria) (*rpc.Subscription, error) {
+ var (
+ symKeyGiven = len(crit.SymKeyID) > 0
+ pubKeyGiven = len(crit.PrivateKeyID) > 0
+ err error
+ )
+
+ // ensure that the RPC connection supports subscriptions
+ notifier, supported := rpc.NotifierFromContext(ctx)
+ if !supported {
+ return nil, rpc.ErrNotificationsUnsupported
+ }
+
+ // user must specify either a symmetric or an asymmetric key
+ if (symKeyGiven && pubKeyGiven) || (!symKeyGiven && !pubKeyGiven) {
+ return nil, ErrSymAsym
+ }
+
+ filter := Filter{
+ PoW: crit.MinPow,
+ Messages: NewMemoryMessageStore(),
+ AllowP2P: crit.AllowP2P,
+ }
+
+ if len(crit.Sig) > 0 {
+ if filter.Src, err = crypto.UnmarshalPubkey(crit.Sig); err != nil {
+ return nil, ErrInvalidSigningPubKey
+ }
+ }
+
+ for i, bt := range crit.Topics {
+ if len(bt) == 0 || len(bt) > 4 {
+ return nil, fmt.Errorf("subscribe: topic %d has wrong size: %d", i, len(bt))
+ }
+ filter.Topics = append(filter.Topics, bt[:])
+ }
+
+ // listen for message that are encrypted with the given symmetric key
+ if symKeyGiven {
+ if len(filter.Topics) == 0 {
+ return nil, ErrNoTopics
+ }
+ key, err := api.w.GetSymKey(crit.SymKeyID)
+ if err != nil {
+ return nil, err
+ }
+ if !validateDataIntegrity(key, aesKeyLength) {
+ return nil, ErrInvalidSymmetricKey
+ }
+ filter.KeySym = key
+ filter.SymKeyHash = crypto.Keccak256Hash(filter.KeySym)
+ }
+
+ // listen for messages that are encrypted with the given public key
+ if pubKeyGiven {
+ filter.KeyAsym, err = api.w.GetPrivateKey(crit.PrivateKeyID)
+ if err != nil || filter.KeyAsym == nil {
+ return nil, ErrInvalidPublicKey
+ }
+ }
+
+ id, err := api.w.Subscribe(&filter)
+ if err != nil {
+ return nil, err
+ }
+
+ // create subscription and start waiting for message events
+ rpcSub := notifier.CreateSubscription()
+ go func() {
+ // for now poll internally, refactor waku internal for channel support
+ ticker := time.NewTicker(250 * time.Millisecond)
+ defer ticker.Stop()
+
+ for {
+ select {
+ case <-ticker.C:
+ if filter := api.w.GetFilter(id); filter != nil {
+ for _, rpcMessage := range toMessage(filter.Retrieve()) {
+ if err := notifier.Notify(rpcSub.ID, rpcMessage); err != nil {
+ log.Error("Failed to send notification", "err", err)
+ }
+ }
+ }
+ case <-rpcSub.Err():
+ _ = api.w.Unsubscribe(id)
+ return
+ }
+ }
+ }()
+
+ return rpcSub, nil
+}
+
+//go:generate gencodec -type Message -field-override messageOverride -out gen_message_json.go
+
+// Message is the RPC representation of a waku message.
+type Message struct {
+ Sig []byte `json:"sig,omitempty"`
+ TTL uint32 `json:"ttl"`
+ Timestamp uint32 `json:"timestamp"`
+ Topic TopicType `json:"topic"`
+ Payload []byte `json:"payload"`
+ Padding []byte `json:"padding"`
+ PoW float64 `json:"pow"`
+ Hash []byte `json:"hash"`
+ Dst []byte `json:"recipientPublicKey,omitempty"`
+ P2P bool `json:"bool,omitempty"`
+}
+
+type messageOverride struct {
+ Sig hexutil.Bytes
+ Payload hexutil.Bytes
+ Padding hexutil.Bytes
+ Hash hexutil.Bytes
+ Dst hexutil.Bytes
+}
+
+// ToWakuMessage converts an internal message into an API version.
+func ToWakuMessage(message *ReceivedMessage) *Message {
+ msg := Message{
+ Payload: message.Payload,
+ Padding: message.Padding,
+ Timestamp: message.Sent,
+ TTL: message.TTL,
+ PoW: message.PoW,
+ Hash: message.EnvelopeHash.Bytes(),
+ Topic: message.Topic,
+ P2P: message.P2P,
+ }
+
+ if message.Dst != nil {
+ b := crypto.FromECDSAPub(message.Dst)
+ if b != nil {
+ msg.Dst = b
+ }
+ }
+
+ if isMessageSigned(message.Raw[0]) {
+ b := crypto.FromECDSAPub(message.SigToPubKey())
+ if b != nil {
+ msg.Sig = b
+ }
+ }
+
+ return &msg
+}
+
+// toMessage converts a set of messages to its RPC representation.
+func toMessage(messages []*ReceivedMessage) []*Message {
+ msgs := make([]*Message, len(messages))
+ for i, msg := range messages {
+ msgs[i] = ToWakuMessage(msg)
+ }
+ return msgs
+}
+
+// GetFilterMessages returns the messages that match the filter criteria and
+// are received between the last poll and now.
+func (api *PublicWakuAPI) GetFilterMessages(id string) ([]*Message, error) {
+ api.mu.Lock()
+ f := api.w.GetFilter(id)
+ if f == nil {
+ api.mu.Unlock()
+ return nil, fmt.Errorf("filter not found")
+ }
+ api.lastUsed[id] = time.Now()
+ api.mu.Unlock()
+
+ receivedMessages := f.Retrieve()
+ messages := make([]*Message, 0, len(receivedMessages))
+ for _, msg := range receivedMessages {
+ messages = append(messages, ToWakuMessage(msg))
+ }
+
+ return messages, nil
+}
+
+// DeleteMessageFilter deletes a filter.
+func (api *PublicWakuAPI) DeleteMessageFilter(id string) (bool, error) {
+ api.mu.Lock()
+ defer api.mu.Unlock()
+
+ delete(api.lastUsed, id)
+ return true, api.w.Unsubscribe(id)
+}
+
+// NewMessageFilter creates a new filter that can be used to poll for
+// (new) messages that satisfy the given criteria.
+func (api *PublicWakuAPI) NewMessageFilter(req Criteria) (string, error) {
+ var (
+ src *ecdsa.PublicKey
+ keySym []byte
+ keyAsym *ecdsa.PrivateKey
+ topics [][]byte
+
+ symKeyGiven = len(req.SymKeyID) > 0
+ asymKeyGiven = len(req.PrivateKeyID) > 0
+
+ err error
+ )
+
+ // user must specify either a symmetric or an asymmetric key
+ if (symKeyGiven && asymKeyGiven) || (!symKeyGiven && !asymKeyGiven) {
+ return "", ErrSymAsym
+ }
+
+ if len(req.Sig) > 0 {
+ if src, err = crypto.UnmarshalPubkey(req.Sig); err != nil {
+ return "", ErrInvalidSigningPubKey
+ }
+ }
+
+ if symKeyGiven {
+ if keySym, err = api.w.GetSymKey(req.SymKeyID); err != nil {
+ return "", err
+ }
+ if !validateDataIntegrity(keySym, aesKeyLength) {
+ return "", ErrInvalidSymmetricKey
+ }
+ }
+
+ if asymKeyGiven {
+ if keyAsym, err = api.w.GetPrivateKey(req.PrivateKeyID); err != nil {
+ return "", err
+ }
+ }
+
+ if len(req.Topics) > 0 {
+ topics = make([][]byte, len(req.Topics))
+ for i, topic := range req.Topics {
+ topics[i] = make([]byte, TopicLength)
+ copy(topics[i], topic[:])
+ }
+ }
+
+ f := &Filter{
+ Src: src,
+ KeySym: keySym,
+ KeyAsym: keyAsym,
+ PoW: req.MinPow,
+ AllowP2P: req.AllowP2P,
+ Topics: topics,
+ Messages: NewMemoryMessageStore(),
+ }
+
+ id, err := api.w.Subscribe(f)
+ if err != nil {
+ return "", err
+ }
+
+ api.mu.Lock()
+ api.lastUsed[id] = time.Now()
+ api.mu.Unlock()
+
+ return id, nil
+}
diff --git a/vendor/github.com/status-im/status-go/waku/config.go b/vendor/github.com/status-im/status-go/waku/config.go
new file mode 100644
index 000000000..2a82a5ffd
--- /dev/null
+++ b/vendor/github.com/status-im/status-go/waku/config.go
@@ -0,0 +1,35 @@
+// Copyright 2019 The Waku Library Authors.
+//
+// The Waku library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The Waku library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty off
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the Waku library. If not, see .
+//
+// This software uses the go-ethereum library, which is licensed
+// under the GNU Lesser General Public Library, version 3 or any later.
+
+package waku
+
+// Config represents the configuration state of a waku node.
+type Config struct {
+ MaxMessageSize uint32 `toml:",omitempty"`
+ MinimumAcceptedPoW float64 `toml:",omitempty"`
+ LightClient bool `toml:",omitempty"` // when true, it does not forward messages
+ FullNode bool `toml:",omitempty"` // when true, it forwards all messages
+ RestrictLightClientsConn bool `toml:",omitempty"` // when true, do not accept light client as peers if it is a light client itself
+ EnableConfirmations bool `toml:",omitempty"` // when true, sends message confirmations
+}
+
+var DefaultConfig = Config{
+ MaxMessageSize: DefaultMaxMessageSize,
+ MinimumAcceptedPoW: DefaultMinimumPoW,
+ RestrictLightClientsConn: true,
+}
diff --git a/vendor/github.com/status-im/status-go/waku/doc.go b/vendor/github.com/status-im/status-go/waku/doc.go
new file mode 100644
index 000000000..f31ccd76e
--- /dev/null
+++ b/vendor/github.com/status-im/status-go/waku/doc.go
@@ -0,0 +1,213 @@
+// Copyright 2019 The Waku Library Authors.
+//
+// The Waku library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The Waku library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty off
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the Waku library. If not, see .
+//
+// This software uses the go-ethereum library, which is licensed
+// under the GNU Lesser General Public Library, version 3 or any later.
+
+package waku
+
+import (
+ "errors"
+ "fmt"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/rlp"
+)
+
+// Waku protocol parameters
+const (
+ ProtocolVersion = uint64(0) // Protocol version number
+ ProtocolVersionStr = "0" // The same, as a string
+ ProtocolName = "waku" // Nickname of the protocol
+
+ // Waku protocol message codes, according to https://github.com/vacp2p/specs/blob/master/waku.md
+ statusCode = 0 // used in the handshake
+ messagesCode = 1 // regular message
+ powRequirementCode = 2 // node's PoW requirement
+ bloomFilterExCode = 3 // bloom filter exchange
+ batchAcknowledgedCode = 11 // confirmation that batch of envelopes was received
+ messageResponseCode = 12 // includes confirmation for delivery and information about errors
+ rateLimitingCode = 20 // includes peer's rate limiting settings
+ p2pRequestCompleteCode = 125 // peer-to-peer message, used by Dapp protocol
+ p2pRequestCode = 126 // peer-to-peer message, used by Dapp protocol
+ p2pMessageCode = 127 // peer-to-peer message (to be consumed by the peer, but not forwarded any further)
+ NumberOfMessageCodes = 128
+
+ SizeMask = byte(3) // mask used to extract the size of payload size field from the flags
+ signatureFlag = byte(4)
+
+ TopicLength = 4 // in bytes
+ signatureLength = crypto.SignatureLength // in bytes
+ aesKeyLength = 32 // in bytes
+ aesNonceLength = 12 // in bytes; for more info please see cipher.gcmStandardNonceSize & aesgcm.NonceSize()
+ keyIDSize = 32 // in bytes
+ BloomFilterSize = 64 // in bytes
+ flagsLength = 1
+
+ EnvelopeHeaderLength = 20
+
+ MaxMessageSize = uint32(10 * 1024 * 1024) // maximum accepted size of a message.
+ DefaultMaxMessageSize = uint32(1024 * 1024)
+ DefaultMinimumPoW = 0.2
+
+ padSizeLimit = 256 // just an arbitrary number, could be changed without breaking the protocol
+ messageQueueLimit = 1024
+
+ expirationCycle = time.Second
+ transmissionCycle = 300 * time.Millisecond
+
+ DefaultTTL = 50 // seconds
+ DefaultSyncAllowance = 10 // seconds
+
+ MaxLimitInSyncMailRequest = 1000
+
+ EnvelopeTimeNotSynced uint = iota + 1
+ EnvelopeOtherError
+
+ MaxLimitInMessagesRequest = 1000
+)
+
+// MailServer represents a mail server, capable of
+// archiving the old messages for subsequent delivery
+// to the peers. Any implementation must ensure that both
+// functions are thread-safe. Also, they must return ASAP.
+// DeliverMail should use p2pMessageCode for delivery,
+// in order to bypass the expiry checks.
+type MailServer interface {
+ Archive(env *Envelope)
+ DeliverMail(peerID []byte, request *Envelope) // DEPRECATED; use Deliver()
+ Deliver(peerID []byte, request MessagesRequest)
+}
+
+// MessagesRequest contains details of a request of historic messages.
+type MessagesRequest struct {
+ // ID of the request. The current implementation requires ID to be 32-byte array,
+ // however, it's not enforced for future implementation.
+ ID []byte `json:"id"`
+
+ // From is a lower bound of time range.
+ From uint32 `json:"from"`
+
+ // To is a upper bound of time range.
+ To uint32 `json:"to"`
+
+ // Limit determines the number of messages sent by the mail server
+ // for the current paginated request.
+ Limit uint32 `json:"limit"`
+
+ // Cursor is used as starting point for paginated requests.
+ Cursor []byte `json:"cursor"`
+
+ // Bloom is a filter to match requested messages.
+ Bloom []byte `json:"bloom"`
+}
+
+func (r MessagesRequest) Validate() error {
+ if len(r.ID) != common.HashLength {
+ return errors.New("invalid 'ID', expected a 32-byte slice")
+ }
+
+ if r.From > r.To {
+ return errors.New("invalid 'From' value which is greater than To")
+ }
+
+ if r.Limit > MaxLimitInMessagesRequest {
+ return fmt.Errorf("invalid 'Limit' value, expected value lower than %d", MaxLimitInMessagesRequest)
+ }
+
+ if len(r.Bloom) == 0 {
+ return errors.New("invalid 'Bloom' provided")
+ }
+
+ return nil
+}
+
+// MessagesResponse sent as a response after processing batch of envelopes.
+type MessagesResponse struct {
+ // Hash is a hash of all envelopes sent in the single batch.
+ Hash common.Hash
+ // Per envelope error.
+ Errors []EnvelopeError
+}
+
+// EnvelopeError code and optional description of the error.
+type EnvelopeError struct {
+ Hash common.Hash
+ Code uint
+ Description string
+}
+
+// MultiVersionResponse allows to decode response into chosen version.
+type MultiVersionResponse struct {
+ Version uint
+ Response rlp.RawValue
+}
+
+// DecodeResponse1 decodes response into first version of the messages response.
+func (m MultiVersionResponse) DecodeResponse1() (resp MessagesResponse, err error) {
+ return resp, rlp.DecodeBytes(m.Response, &resp)
+}
+
+// Version1MessageResponse first version of the message response.
+type Version1MessageResponse struct {
+ Version uint
+ Response MessagesResponse
+}
+
+// NewMessagesResponse returns instance of the version messages response.
+func NewMessagesResponse(batch common.Hash, errors []EnvelopeError) Version1MessageResponse {
+ return Version1MessageResponse{
+ Version: 1,
+ Response: MessagesResponse{
+ Hash: batch,
+ Errors: errors,
+ },
+ }
+}
+
+// ErrorToEnvelopeError converts common golang error into EnvelopeError with a code.
+func ErrorToEnvelopeError(hash common.Hash, err error) EnvelopeError {
+ code := EnvelopeOtherError
+ switch err.(type) {
+ case TimeSyncError:
+ code = EnvelopeTimeNotSynced
+ }
+ return EnvelopeError{
+ Hash: hash,
+ Code: code,
+ Description: err.Error(),
+ }
+}
+
+// MailServerResponse is the response payload sent by the mailserver.
+type MailServerResponse struct {
+ LastEnvelopeHash common.Hash
+ Cursor []byte
+ Error error
+}
+
+// RateLimits contains information about rate limit settings.
+// It is exchanged using rateLimitingCode packet or in the handshake.
+type RateLimits struct {
+ IPLimits uint64 // messages per second from a single IP (default 0, no limits)
+ PeerIDLimits uint64 // messages per second from a single peer ID (default 0, no limits)
+ TopicLimits uint64 // messages per second from a single topic (default 0, no limits)
+}
+
+func (r RateLimits) IsZero() bool {
+ return r == (RateLimits{})
+}
diff --git a/vendor/github.com/status-im/status-go/waku/envelope.go b/vendor/github.com/status-im/status-go/waku/envelope.go
new file mode 100644
index 000000000..e4972ed16
--- /dev/null
+++ b/vendor/github.com/status-im/status-go/waku/envelope.go
@@ -0,0 +1,272 @@
+// Copyright 2019 The Waku Library Authors.
+//
+// The Waku library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The Waku library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty off
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the Waku library. If not, see .
+//
+// This software uses the go-ethereum library, which is licensed
+// under the GNU Lesser General Public Library, version 3 or any later.
+
+package waku
+
+import (
+ "crypto/ecdsa"
+ "encoding/binary"
+ "fmt"
+ "math"
+ "math/big"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/crypto/ecies"
+ "github.com/ethereum/go-ethereum/rlp"
+)
+
+// Envelope represents a clear-text data packet to transmit through the Waku
+// network. Its contents may or may not be encrypted and signed.
+type Envelope struct {
+ Expiry uint32
+ TTL uint32
+ Topic TopicType
+ Data []byte
+ Nonce uint64
+
+ pow float64 // Message-specific PoW as described in the Waku specification.
+
+ // the following variables should not be accessed directly, use the corresponding function instead: Hash(), Bloom()
+ hash common.Hash // Cached hash of the envelope to avoid rehashing every time.
+ bloom []byte
+}
+
+// size returns the size of envelope as it is sent (i.e. public fields only)
+func (e *Envelope) size() int {
+ return EnvelopeHeaderLength + len(e.Data)
+}
+
+// rlpWithoutNonce returns the RLP encoded envelope contents, except the nonce.
+func (e *Envelope) rlpWithoutNonce() []byte {
+ res, _ := rlp.EncodeToBytes([]interface{}{e.Expiry, e.TTL, e.Topic, e.Data})
+ return res
+}
+
+// NewEnvelope wraps a Waku message with expiration and destination data
+// included into an envelope for network forwarding.
+func NewEnvelope(ttl uint32, topic TopicType, msg *sentMessage, now time.Time) *Envelope {
+ env := Envelope{
+ Expiry: uint32(now.Add(time.Second * time.Duration(ttl)).Unix()),
+ TTL: ttl,
+ Topic: topic,
+ Data: msg.Raw,
+ Nonce: 0,
+ }
+
+ return &env
+}
+
+// Seal closes the envelope by spending the requested amount of time as a proof
+// of work on hashing the data.
+func (e *Envelope) Seal(options *MessageParams) error {
+ if options.PoW == 0 {
+ // PoW is not required
+ return nil
+ }
+
+ var target, bestLeadingZeros int
+ if options.PoW < 0 {
+ // target is not set - the function should run for a period
+ // of time specified in WorkTime param. Since we can predict
+ // the execution time, we can also adjust Expiry.
+ e.Expiry += options.WorkTime
+ } else {
+ target = e.powToFirstBit(options.PoW)
+ }
+
+ rlp := e.rlpWithoutNonce()
+ buf := make([]byte, len(rlp)+8)
+ copy(buf, rlp)
+ asAnInt := new(big.Int)
+
+ finish := time.Now().Add(time.Duration(options.WorkTime) * time.Second).UnixNano()
+ for nonce := uint64(0); time.Now().UnixNano() < finish; {
+ for i := 0; i < 1024; i++ {
+ binary.BigEndian.PutUint64(buf[len(rlp):], nonce)
+ h := crypto.Keccak256(buf)
+ asAnInt.SetBytes(h)
+ leadingZeros := 256 - asAnInt.BitLen()
+ if leadingZeros > bestLeadingZeros {
+ e.Nonce, bestLeadingZeros = nonce, leadingZeros
+ if target > 0 && bestLeadingZeros >= target {
+ return nil
+ }
+ }
+ nonce++
+ }
+ }
+
+ if target > 0 && bestLeadingZeros < target {
+ return fmt.Errorf("failed to reach the PoW target, specified pow time (%d seconds) was insufficient", options.WorkTime)
+ }
+
+ return nil
+}
+
+// PoW computes (if necessary) and returns the proof of work target
+// of the envelope.
+func (e *Envelope) PoW() float64 {
+ if e.pow == 0 {
+ e.calculatePoW(0)
+ }
+ return e.pow
+}
+
+func (e *Envelope) calculatePoW(diff uint32) {
+ rlp := e.rlpWithoutNonce()
+ buf := make([]byte, len(rlp)+8)
+ copy(buf, rlp)
+ binary.BigEndian.PutUint64(buf[len(rlp):], e.Nonce)
+ powHash := new(big.Int).SetBytes(crypto.Keccak256(buf))
+ leadingZeroes := 256 - powHash.BitLen()
+ x := math.Pow(2, float64(leadingZeroes))
+ x /= float64(len(rlp))
+ x /= float64(e.TTL + diff)
+ e.pow = x
+}
+
+func (e *Envelope) powToFirstBit(pow float64) int {
+ x := pow
+ x *= float64(e.size())
+ x *= float64(e.TTL)
+ bits := math.Log2(x)
+ bits = math.Ceil(bits)
+ res := int(bits)
+ if res < 1 {
+ res = 1
+ }
+ return res
+}
+
+// Hash returns the SHA3 hash of the envelope, calculating it if not yet done.
+func (e *Envelope) Hash() common.Hash {
+ if (e.hash == common.Hash{}) {
+ encoded, _ := rlp.EncodeToBytes(e)
+ e.hash = crypto.Keccak256Hash(encoded)
+ }
+ return e.hash
+}
+
+// DecodeRLP decodes an Envelope from an RLP data stream.
+func (e *Envelope) DecodeRLP(s *rlp.Stream) error {
+ raw, err := s.Raw()
+ if err != nil {
+ return err
+ }
+ // The decoding of Envelope uses the struct fields but also needs
+ // to compute the hash of the whole RLP-encoded envelope. This
+ // type has the same structure as Envelope but is not an
+ // rlp.Decoder (does not implement DecodeRLP function).
+ // Only public members will be encoded.
+ type rlpenv Envelope
+ if err := rlp.DecodeBytes(raw, (*rlpenv)(e)); err != nil {
+ return err
+ }
+ e.hash = crypto.Keccak256Hash(raw)
+ return nil
+}
+
+// OpenAsymmetric tries to decrypt an envelope, potentially encrypted with a particular key.
+func (e *Envelope) OpenAsymmetric(key *ecdsa.PrivateKey) (*ReceivedMessage, error) {
+ message := &ReceivedMessage{Raw: e.Data}
+ err := message.decryptAsymmetric(key)
+ switch err {
+ case nil:
+ return message, nil
+ case ecies.ErrInvalidPublicKey: // addressed to somebody else
+ return nil, err
+ default:
+ return nil, fmt.Errorf("unable to open envelope, decrypt failed: %v", err)
+ }
+}
+
+// OpenSymmetric tries to decrypt an envelope, potentially encrypted with a particular key.
+func (e *Envelope) OpenSymmetric(key []byte) (msg *ReceivedMessage, err error) {
+ msg = &ReceivedMessage{Raw: e.Data}
+ err = msg.decryptSymmetric(key)
+ if err != nil {
+ msg = nil
+ }
+ return msg, err
+}
+
+// Open tries to decrypt an envelope, and populates the message fields in case of success.
+func (e *Envelope) Open(watcher *Filter) (msg *ReceivedMessage) {
+ if watcher == nil {
+ return nil
+ }
+
+ // The API interface forbids filters doing both symmetric and asymmetric encryption.
+ if watcher.expectsAsymmetricEncryption() && watcher.expectsSymmetricEncryption() {
+ return nil
+ }
+
+ if watcher.expectsAsymmetricEncryption() {
+ msg, _ = e.OpenAsymmetric(watcher.KeyAsym)
+ if msg != nil {
+ msg.Dst = &watcher.KeyAsym.PublicKey
+ }
+ } else if watcher.expectsSymmetricEncryption() {
+ msg, _ = e.OpenSymmetric(watcher.KeySym)
+ if msg != nil {
+ msg.SymKeyHash = crypto.Keccak256Hash(watcher.KeySym)
+ }
+ }
+
+ if msg != nil {
+ ok := msg.ValidateAndParse()
+ if !ok {
+ return nil
+ }
+ msg.Topic = e.Topic
+ msg.PoW = e.PoW()
+ msg.TTL = e.TTL
+ msg.Sent = e.Expiry - e.TTL
+ msg.EnvelopeHash = e.Hash()
+ }
+ return msg
+}
+
+// Bloom maps 4-bytes Topic into 64-byte bloom filter with 3 bits set (at most).
+func (e *Envelope) Bloom() []byte {
+ if e.bloom == nil {
+ e.bloom = TopicToBloom(e.Topic)
+ }
+ return e.bloom
+}
+
+// TopicToBloom converts the topic (4 bytes) to the bloom filter (64 bytes)
+func TopicToBloom(topic TopicType) []byte {
+ b := make([]byte, BloomFilterSize)
+ var index [3]int
+ for j := 0; j < 3; j++ {
+ index[j] = int(topic[j])
+ if (topic[3] & (1 << uint(j))) != 0 {
+ index[j] += 256
+ }
+ }
+
+ for j := 0; j < 3; j++ {
+ byteIndex := index[j] / 8
+ bitIndex := index[j] % 8
+ b[byteIndex] = (1 << uint(bitIndex))
+ }
+ return b
+}
diff --git a/vendor/github.com/status-im/status-go/waku/events.go b/vendor/github.com/status-im/status-go/waku/events.go
new file mode 100644
index 000000000..8c22e5fb9
--- /dev/null
+++ b/vendor/github.com/status-im/status-go/waku/events.go
@@ -0,0 +1,64 @@
+// Copyright 2019 The Waku Library Authors.
+//
+// The Waku library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The Waku library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty off
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the Waku library. If not, see .
+//
+// This software uses the go-ethereum library, which is licensed
+// under the GNU Lesser General Public Library, version 3 or any later.
+
+package waku
+
+import (
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/p2p/enode"
+)
+
+// EventType used to define known envelope events.
+type EventType string
+
+const (
+ // EventEnvelopeSent fires when envelope was sent to a peer.
+ EventEnvelopeSent EventType = "envelope.sent"
+ // EventEnvelopeExpired fires when envelop expired
+ EventEnvelopeExpired EventType = "envelope.expired"
+ // EventEnvelopeReceived is sent once envelope was received from a peer.
+ // EventEnvelopeReceived must be sent to the feed even if envelope was previously in the cache.
+ // And event, ideally, should contain information about peer that sent envelope to us.
+ EventEnvelopeReceived EventType = "envelope.received"
+ // EventBatchAcknowledged is sent when batch of envelopes was acknowleged by a peer.
+ EventBatchAcknowledged EventType = "batch.acknowleged"
+ // EventEnvelopeAvailable fires when envelop is available for filters
+ EventEnvelopeAvailable EventType = "envelope.available"
+ // EventMailServerRequestSent fires when such request is sent.
+ EventMailServerRequestSent EventType = "mailserver.request.sent"
+ // EventMailServerRequestCompleted fires after mailserver sends all the requested messages
+ EventMailServerRequestCompleted EventType = "mailserver.request.completed"
+ // EventMailServerRequestExpired fires after mailserver the request TTL ends.
+ // This event is independent and concurrent to EventMailServerRequestCompleted.
+ // Request should be considered as expired only if expiry event was received first.
+ EventMailServerRequestExpired EventType = "mailserver.request.expired"
+ // EventMailServerEnvelopeArchived fires after an envelope has been archived
+ EventMailServerEnvelopeArchived EventType = "mailserver.envelope.archived"
+ // EventMailServerSyncFinished fires when the sync of messages is finished.
+ EventMailServerSyncFinished EventType = "mailserver.sync.finished"
+)
+
+// EnvelopeEvent used for envelopes events.
+type EnvelopeEvent struct {
+ Event EventType
+ Topic TopicType
+ Hash common.Hash
+ Batch common.Hash
+ Peer enode.ID
+ Data interface{}
+}
diff --git a/vendor/github.com/status-im/status-go/waku/filter.go b/vendor/github.com/status-im/status-go/waku/filter.go
new file mode 100644
index 000000000..dfe3f60e5
--- /dev/null
+++ b/vendor/github.com/status-im/status-go/waku/filter.go
@@ -0,0 +1,296 @@
+// Copyright 2019 The Waku Library Authors.
+//
+// The Waku library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The Waku library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty off
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the Waku library. If not, see .
+//
+// This software uses the go-ethereum library, which is licensed
+// under the GNU Lesser General Public Library, version 3 or any later.
+
+package waku
+
+import (
+ "crypto/ecdsa"
+ "fmt"
+ "sync"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/log"
+)
+
+// MessageStore defines interface for temporary message store.
+type MessageStore interface {
+ Add(*ReceivedMessage) error
+ Pop() ([]*ReceivedMessage, error)
+}
+
+// NewMemoryMessageStore returns pointer to an instance of the MemoryMessageStore.
+func NewMemoryMessageStore() *MemoryMessageStore {
+ return &MemoryMessageStore{
+ messages: map[common.Hash]*ReceivedMessage{},
+ }
+}
+
+// MemoryMessageStore stores massages in memory hash table.
+type MemoryMessageStore struct {
+ mu sync.Mutex
+ messages map[common.Hash]*ReceivedMessage
+}
+
+// Add adds message to store.
+func (store *MemoryMessageStore) Add(msg *ReceivedMessage) error {
+ store.mu.Lock()
+ defer store.mu.Unlock()
+ if _, exist := store.messages[msg.EnvelopeHash]; !exist {
+ store.messages[msg.EnvelopeHash] = msg
+ }
+ return nil
+}
+
+// Pop returns all avaiable messages and cleans the store.
+func (store *MemoryMessageStore) Pop() ([]*ReceivedMessage, error) {
+ store.mu.Lock()
+ defer store.mu.Unlock()
+ all := make([]*ReceivedMessage, 0, len(store.messages))
+ for hash, msg := range store.messages {
+ delete(store.messages, hash)
+ all = append(all, msg)
+ }
+ return all, nil
+}
+
+// Filter represents a Waku message filter
+type Filter struct {
+ Src *ecdsa.PublicKey // Sender of the message
+ KeyAsym *ecdsa.PrivateKey // Private Key of recipient
+ KeySym []byte // Key associated with the Topic
+ Topics [][]byte // Topics to filter messages with
+ PoW float64 // Proof of work as described in the Waku spec
+ AllowP2P bool // Indicates whether this filter is interested in direct peer-to-peer messages
+ SymKeyHash common.Hash // The Keccak256Hash of the symmetric key, needed for optimization
+ id string // unique identifier
+
+ Messages MessageStore
+ mutex sync.RWMutex
+}
+
+// Filters represents a collection of filters
+type Filters struct {
+ watchers map[string]*Filter
+
+ topicMatcher map[TopicType]map[*Filter]struct{} // map a topic to the filters that are interested in being notified when a message matches that topic
+ allTopicsMatcher map[*Filter]struct{} // list all the filters that will be notified of a new message, no matter what its topic is
+
+ waku *Waku
+ mutex sync.RWMutex
+}
+
+// NewFilters returns a newly created filter collection
+func NewFilters(w *Waku) *Filters {
+ return &Filters{
+ watchers: make(map[string]*Filter),
+ topicMatcher: make(map[TopicType]map[*Filter]struct{}),
+ allTopicsMatcher: make(map[*Filter]struct{}),
+ waku: w,
+ }
+}
+
+// Install will add a new filter to the filter collection
+func (fs *Filters) Install(watcher *Filter) (string, error) {
+ if watcher.KeySym != nil && watcher.KeyAsym != nil {
+ return "", fmt.Errorf("filters must choose between symmetric and asymmetric keys")
+ }
+
+ id, err := GenerateRandomID()
+ if err != nil {
+ return "", err
+ }
+
+ fs.mutex.Lock()
+ defer fs.mutex.Unlock()
+
+ if fs.watchers[id] != nil {
+ return "", fmt.Errorf("failed to generate unique ID")
+ }
+
+ if watcher.expectsSymmetricEncryption() {
+ watcher.SymKeyHash = crypto.Keccak256Hash(watcher.KeySym)
+ }
+
+ watcher.id = id
+ fs.watchers[id] = watcher
+ fs.addTopicMatcher(watcher)
+ return id, err
+}
+
+// Uninstall will remove a filter whose id has been specified from
+// the filter collection
+func (fs *Filters) Uninstall(id string) bool {
+ fs.mutex.Lock()
+ defer fs.mutex.Unlock()
+ if fs.watchers[id] != nil {
+ fs.removeFromTopicMatchers(fs.watchers[id])
+ delete(fs.watchers, id)
+ return true
+ }
+ return false
+}
+
+// addTopicMatcher adds a filter to the topic matchers.
+// If the filter's Topics array is empty, it will be tried on every topic.
+// Otherwise, it will be tried on the topics specified.
+func (fs *Filters) addTopicMatcher(watcher *Filter) {
+ if len(watcher.Topics) == 0 {
+ fs.allTopicsMatcher[watcher] = struct{}{}
+ } else {
+ for _, t := range watcher.Topics {
+ topic := BytesToTopic(t)
+ if fs.topicMatcher[topic] == nil {
+ fs.topicMatcher[topic] = make(map[*Filter]struct{})
+ }
+ fs.topicMatcher[topic][watcher] = struct{}{}
+ }
+ }
+}
+
+// removeFromTopicMatchers removes a filter from the topic matchers
+func (fs *Filters) removeFromTopicMatchers(watcher *Filter) {
+ delete(fs.allTopicsMatcher, watcher)
+ for _, topic := range watcher.Topics {
+ delete(fs.topicMatcher[BytesToTopic(topic)], watcher)
+ }
+}
+
+// getWatchersByTopic returns a slice containing the filters that
+// match a specific topic
+func (fs *Filters) getWatchersByTopic(topic TopicType) []*Filter {
+ res := make([]*Filter, 0, len(fs.allTopicsMatcher))
+ for watcher := range fs.allTopicsMatcher {
+ res = append(res, watcher)
+ }
+ for watcher := range fs.topicMatcher[topic] {
+ res = append(res, watcher)
+ }
+ return res
+}
+
+// Get returns a filter from the collection with a specific ID
+func (fs *Filters) Get(id string) *Filter {
+ fs.mutex.RLock()
+ defer fs.mutex.RUnlock()
+ return fs.watchers[id]
+}
+
+// NotifyWatchers notifies any filter that has declared interest
+// for the envelope's topic.
+func (fs *Filters) NotifyWatchers(env *Envelope, p2pMessage bool) {
+ var msg *ReceivedMessage
+
+ fs.mutex.RLock()
+ defer fs.mutex.RUnlock()
+
+ candidates := fs.getWatchersByTopic(env.Topic)
+ for _, watcher := range candidates {
+ if p2pMessage && !watcher.AllowP2P {
+ log.Trace(fmt.Sprintf("msg [%x], filter [%s]: p2p messages are not allowed", env.Hash(), watcher.id))
+ continue
+ }
+
+ var match bool
+ if msg != nil {
+ match = watcher.MatchMessage(msg)
+ } else {
+ match = watcher.MatchEnvelope(env)
+ if match {
+ msg = env.Open(watcher)
+ if msg == nil {
+ log.Trace("processing message: failed to open", "message", env.Hash().Hex(), "filter", watcher.id)
+ }
+ } else {
+ log.Trace("processing message: does not match", "message", env.Hash().Hex(), "filter", watcher.id)
+ }
+ }
+
+ if match && msg != nil {
+ msg.P2P = p2pMessage
+ log.Trace("processing message: decrypted", "hash", env.Hash().Hex())
+ if watcher.Src == nil || IsPubKeyEqual(msg.Src, watcher.Src) {
+ watcher.Trigger(msg)
+ }
+ }
+ }
+}
+
+func (f *Filter) expectsAsymmetricEncryption() bool {
+ return f.KeyAsym != nil
+}
+
+func (f *Filter) expectsSymmetricEncryption() bool {
+ return f.KeySym != nil
+}
+
+// Trigger adds a yet-unknown message to the filter's list of
+// received messages.
+func (f *Filter) Trigger(msg *ReceivedMessage) {
+ err := f.Messages.Add(msg)
+ if err != nil {
+ log.Error("failed to add msg into the filters store", "hash", msg.EnvelopeHash, "error", err)
+ }
+}
+
+// Retrieve will return the list of all received messages associated
+// to a filter.
+func (f *Filter) Retrieve() []*ReceivedMessage {
+ msgs, err := f.Messages.Pop()
+ if err != nil {
+ log.Error("failed to retrieve messages from filter store", "error", err)
+ return nil
+ }
+ return msgs
+}
+
+// MatchMessage checks if the filter matches an already decrypted
+// message (i.e. a Message that has already been handled by
+// MatchEnvelope when checked by a previous filter).
+// Topics are not checked here, since this is done by topic matchers.
+func (f *Filter) MatchMessage(msg *ReceivedMessage) bool {
+ if f.PoW > 0 && msg.PoW < f.PoW {
+ return false
+ }
+
+ if f.expectsAsymmetricEncryption() && msg.isAsymmetricEncryption() {
+ return IsPubKeyEqual(&f.KeyAsym.PublicKey, msg.Dst)
+ } else if f.expectsSymmetricEncryption() && msg.isSymmetricEncryption() {
+ return f.SymKeyHash == msg.SymKeyHash
+ }
+ return false
+}
+
+// MatchEnvelope checks if it's worth decrypting the message. If
+// it returns `true`, client code is expected to attempt decrypting
+// the message and subsequently call MatchMessage.
+// Topics are not checked here, since this is done by topic matchers.
+func (f *Filter) MatchEnvelope(envelope *Envelope) bool {
+ return f.PoW <= 0 || envelope.pow >= f.PoW
+}
+
+// IsPubKeyEqual checks that two public keys are equal
+func IsPubKeyEqual(a, b *ecdsa.PublicKey) bool {
+ if !ValidatePublicKey(a) {
+ return false
+ } else if !ValidatePublicKey(b) {
+ return false
+ }
+ // the curve is always the same, just compare the points
+ return a.X.Cmp(b.X) == 0 && a.Y.Cmp(b.Y) == 0
+}
diff --git a/vendor/github.com/status-im/status-go/waku/go.mod b/vendor/github.com/status-im/status-go/waku/go.mod
new file mode 100644
index 000000000..dee45c4c4
--- /dev/null
+++ b/vendor/github.com/status-im/status-go/waku/go.mod
@@ -0,0 +1,24 @@
+module github.com/status-im/status-go/waku
+
+go 1.13
+
+replace github.com/ethereum/go-ethereum v1.9.5 => github.com/status-im/go-ethereum v1.9.5-status.6
+
+require (
+ github.com/aristanetworks/goarista v0.0.0-20191106175434-873d404c7f40 // indirect
+ github.com/deckarep/golang-set v1.7.1
+ github.com/elastic/gosigar v0.10.5 // indirect
+ github.com/ethereum/go-ethereum v1.9.5
+ github.com/gorilla/websocket v1.4.1 // indirect
+ github.com/huin/goupnp v1.0.0 // indirect
+ github.com/jackpal/go-nat-pmp v1.0.2 // indirect
+ github.com/prometheus/client_golang v1.2.1
+ github.com/prometheus/common v0.7.0
+ github.com/rs/cors v1.7.0 // indirect
+ github.com/stretchr/testify v1.4.0
+ github.com/syndtr/goleveldb v1.0.0 // indirect
+ github.com/tsenart/tb v0.0.0-20181025101425-0d2499c8b6e9
+ go.uber.org/zap v1.13.0
+ golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c
+ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e
+)
diff --git a/vendor/github.com/status-im/status-go/waku/go.sum b/vendor/github.com/status-im/status-go/waku/go.sum
new file mode 100644
index 000000000..e1e50ef6b
--- /dev/null
+++ b/vendor/github.com/status-im/status-go/waku/go.sum
@@ -0,0 +1,304 @@
+bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+github.com/Azure/azure-pipeline-go v0.0.0-20180607212504-7571e8eb0876/go.mod h1:XA1kFWRVhSK+KNFiOhfv83Fv8L9achrP7OxIzeTn1Yg=
+github.com/Azure/azure-storage-blob-go v0.0.0-20180712005634-eaae161d9d5e/go.mod h1:x2mtS6O3mnMEZOJp7d7oldh8IvatBrMfReiyQ+cKgKY=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/DataDog/zstd v1.3.6-0.20190409195224-796139022798/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
+github.com/Shopify/sarama v1.23.1/go.mod h1:XLH1GYJnLVE0XCr6KdJGVJRTwY30moWNJ4sERjXX6fs=
+github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
+github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
+github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
+github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
+github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4 h1:Hs82Z41s6SdL1CELW+XaDYmOH4hkBN4/N9og/AsOv7E=
+github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/allegro/bigcache v0.0.0-20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
+github.com/aristanetworks/fsnotify v1.4.2/go.mod h1:D/rtu7LpjYM8tRJphJ0hUBYpjai8SfX+aSNsWDTq/Ks=
+github.com/aristanetworks/glog v0.0.0-20180419172825-c15b03b3054f/go.mod h1:KASm+qXFKs/xjSoWn30NrWBBvdTTQq+UjkhjEJHfSFA=
+github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
+github.com/aristanetworks/goarista v0.0.0-20191106175434-873d404c7f40 h1:ZdRuixFqR3mfx4FHzclG3COrRgWrYq0VhNgIoYoObcM=
+github.com/aristanetworks/goarista v0.0.0-20191106175434-873d404c7f40/go.mod h1:Z4RTxGAuYhPzcq8+EdRM+R8M48Ssle2TsWtwRKa+vns=
+github.com/aristanetworks/splunk-hec-go v0.3.3/go.mod h1:1VHO9r17b0K7WmOlLb9nTk/2YanvOEnLMUgsFrxBROc=
+github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
+github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
+github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
+github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
+github.com/btcsuite/btcd v0.20.0-beta h1:DnZGUjFbRkpytojHWwy6nfUSA7vFrzWXDLpFNzt74ZA=
+github.com/btcsuite/btcd v0.20.0-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
+github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
+github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
+github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
+github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY=
+github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
+github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
+github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
+github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s=
+github.com/cespare/xxhash/v2 v2.1.0 h1:yTUvW7Vhb89inJ+8irsUqiWjh8iT6sQPZiQzI6ReGkA=
+github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
+github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
+github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ=
+github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
+github.com/dgrijalva/jwt-go v0.0.0-20170201225849-2268707a8f08/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
+github.com/docker/docker v0.0.0-20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
+github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
+github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
+github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
+github.com/elastic/gosigar v0.0.0-20180330100440-37f05ff46ffa/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs=
+github.com/elastic/gosigar v0.10.5 h1:GzPQ+78RaAb4J63unidA/JavQRKrB6s8IOzN6Ib59jo=
+github.com/elastic/gosigar v0.10.5/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs=
+github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
+github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
+github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
+github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
+github.com/gizak/termui v0.0.0-20170117222342-991cd3d38091/go.mod h1:PkJoWUt/zacQKysNfQtcw1RW+eK2SxkieVBtl+4ovLA=
+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-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-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
+github.com/go-stack/stack v1.5.4/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
+github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
+github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
+github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
+github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/hashicorp/golang-lru v0.0.0-20160813221303-0a025b7e63ad/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
+github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/huin/goupnp v0.0.0-20161224104101-679507af18f3/go.mod h1:MZ2ZmwcBpvOoJ22IJsc7va19ZwoheaBk43rKg12SKag=
+github.com/huin/goupnp v1.0.0 h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo=
+github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc=
+github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
+github.com/influxdata/influxdb v0.0.0-20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY=
+github.com/influxdata/influxdb1-client v0.0.0-20190809212627-fc22c7df067e/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
+github.com/jackpal/go-nat-pmp v0.0.0-20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
+github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
+github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
+github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
+github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
+github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
+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/julienschmidt/httprouter v0.0.0-20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
+github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
+github.com/karalabe/hid v0.0.0-20181128192157-d815e0c1a2e2/go.mod h1:YvbcH+3Wo6XPs9nkgTY3u19KXLauXW+J5nB7hEHuX0A=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
+github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
+github.com/klauspost/reedsolomon v1.9.2/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
+github.com/maruel/panicparse v0.0.0-20160720141634-ad661195ed0e/go.mod h1:nty42YY5QByNC5MM7q/nj938VbgPU7avs45z6NClpxI=
+github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
+github.com/mattn/go-isatty v0.0.0-20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
+github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
+github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
+github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
+github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
+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/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
+github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
+github.com/naoina/toml v0.0.0-20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E=
+github.com/nsf/termbox-go v0.0.0-20170211012700-3540b76b9c77/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ=
+github.com/olekukonko/tablewriter v0.0.0-20170128050532-febf2d34b54a/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
+github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo=
+github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
+github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
+github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
+github.com/openconfig/gnmi v0.0.0-20190823184014-89b2bf29312c/go.mod h1:t+O9It+LKzfOAhKTT5O0ehDix+MTqbtT0T9t+7zzOvc=
+github.com/openconfig/reference v0.0.0-20190727015836-8dfd928c9696/go.mod h1:ym2A+zigScwkSEb/cVQB0/ZMpU3rqiH6X7WRRsxgOGw=
+github.com/opentracing/opentracing-go v0.0.0-20180606204148-bd9c31933947/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
+github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34=
+github.com/peterh/liner v0.0.0-20170902204657-a37ad3984311/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
+github.com/pierrec/lz4 v0.0.0-20190327172049-315a67e90e41/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
+github.com/pkg/errors v0.0.0-20171216070316-e881fd58d78e/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
+github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
+github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
+github.com/prometheus/client_golang v1.2.1 h1:JnMpQc6ppsNgw9QPAGF6Dod479itz7lvlsMzzNayLOI=
+github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U=
+github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/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-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+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.7.0 h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLyCY=
+github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
+github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
+github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
+github.com/prometheus/procfs v0.0.5 h1:3+auTFlqw+ZaQYJARz6ArODtkaIwtvBTx3N2NehQlL8=
+github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
+github.com/prometheus/prometheus v0.0.0-20170814170113-3101606756c5/go.mod h1:oAIUtOny2rjMX0OWN5vPR5/q/twIROJvdqnQKDdil/s=
+github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
+github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho=
+github.com/robertkrimen/otto v0.0.0-20170205013659-6a77b7cbc37d/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY=
+github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
+github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
+github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
+github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ=
+github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
+github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
+github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
+github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
+github.com/status-im/extkeys v1.0.0/go.mod h1:wNx0pnvGTgyKz/S8hBNesAHKKKI9beF+BuVLIuBJuQI=
+github.com/status-im/go-ethereum v1.9.5-status.5 h1:d2RJC6ltNZJM2mrAW6kDWYdzewF8+us4qYaIH5gvyaM=
+github.com/status-im/go-ethereum v1.9.5-status.5/go.mod h1:g2+E89NWtyA+55p6XEl5Sdt7Mtez3V0T3+Y7mJNb+tI=
+github.com/status-im/go-ethereum v1.9.5-status.6 h1:ytuTO1yBIAuTVRtRQoc2mrdyngtP+XOQ9IHIibbz7/I=
+github.com/status-im/go-ethereum v1.9.5-status.6/go.mod h1:08JvQWE+IOnAFSe4UD4ACLNe2fDd9XmWMCq5Yzy9mk0=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
+github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v0.0.0-20170809224252-890a5c3458b4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/syndtr/goleveldb v0.0.0-20181128100959-b001fa50d6b2/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
+github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
+github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
+github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU=
+github.com/templexxx/xor v0.0.0-20181023030647-4e92f724b73b/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4=
+github.com/tjfoc/gmsm v1.0.1/go.mod h1:XxO4hdhhrzAd+G4CjDqaOkd0hUzmtPR/d3EiBBMn/wc=
+github.com/tsenart/tb v0.0.0-20181025101425-0d2499c8b6e9 h1:kjbwitOGH46vD01f2s3leBfrMnePQa3NSAIlW35MvY8=
+github.com/tsenart/tb v0.0.0-20181025101425-0d2499c8b6e9/go.mod h1:EcGP24b8DY+bWHnpfJDP7fM+o8Nmz4fYH0l2xTtNr3I=
+github.com/uber/jaeger-client-go v0.0.0-20180607151842-f7e0d4744fa6/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
+github.com/uber/jaeger-lib v0.0.0-20180615202729-a51202d6f4a7/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
+github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
+github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
+github.com/xtaci/kcp-go v5.4.5+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE=
+github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE=
+go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY=
+go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
+go.uber.org/multierr v1.3.0 h1:sFPn2GLc3poCkfrpIXGhBD2X0CMIo4Q/zSULXrj/+uc=
+go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
+go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
+go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU=
+go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
+golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
+golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c h1:/nJuwDLoL/zrqY6gf57vxC+Pi+pZ8bfhpPkicO5H7W4=
+golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
+golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+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-20190912160710-24e19bdeb0f2 h1:4dVFTC832rPn4pomLSz1vA+are2+dU19w1H8OngV7nc=
+golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+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-20181221193216-37e7f081c4d4/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 h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190912141932-bc967efca4b8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191010194322-b09406accb47 h1:/XfQ9z7ib8eEJX2hdgFTZJ/ntt0swNk5oYBziWeTCvY=
+golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190912185636-87d9f09c5d89/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
+gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
+gopkg.in/bsm/ratelimit.v1 v1.0.0-20160220154919-db14e161995a/go.mod h1:KF9sEfUPAXdG8Oev9e99iLGnl2uJMjc5B+4y3O7x610=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20161208181325-20d25e280405 h1:829vOVxxusYHC+IqBtkX5mbKtsY9fheQiQn0MZRVLfQ=
+gopkg.in/check.v1 v1.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
+gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
+gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo=
+gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q=
+gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4=
+gopkg.in/jcmturner/gokrb5.v7 v7.2.3/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM=
+gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8=
+gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU=
+gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c=
+gopkg.in/olebedev/go-duktape.v3 v3.0.0-20180302121509-abf0ba0be5d5/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns=
+gopkg.in/redis.v4 v4.2.4/go.mod h1:8KREHdypkCEojGKQcjMqAODMICIVwZAONWq8RowTITA=
+gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
+gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0=
+gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+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=
diff --git a/vendor/github.com/status-im/status-go/waku/mailserver_response.go b/vendor/github.com/status-im/status-go/waku/mailserver_response.go
new file mode 100644
index 000000000..fb1b9ad2a
--- /dev/null
+++ b/vendor/github.com/status-im/status-go/waku/mailserver_response.go
@@ -0,0 +1,158 @@
+// Copyright 2019 The Waku Library Authors.
+//
+// The Waku library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The Waku library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty off
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the Waku library. If not, see .
+//
+// This software uses the go-ethereum library, which is licensed
+// under the GNU Lesser General Public Library, version 3 or any later.
+
+package waku
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/p2p/enode"
+)
+
+const (
+ mailServerFailedPayloadPrefix = "ERROR="
+ cursorSize = 36
+)
+
+func invalidResponseSizeError(size int) error {
+ return fmt.Errorf("unexpected payload size: %d", size)
+}
+
+// CreateMailServerRequestCompletedPayload creates a payload representing
+// a successful request to mailserver
+func CreateMailServerRequestCompletedPayload(requestID, lastEnvelopeHash common.Hash, cursor []byte) []byte {
+ payload := make([]byte, len(requestID))
+ copy(payload, requestID[:])
+ payload = append(payload, lastEnvelopeHash[:]...)
+ payload = append(payload, cursor...)
+ return payload
+}
+
+// CreateMailServerRequestFailedPayload creates a payload representing
+// a failed request to a mailserver
+func CreateMailServerRequestFailedPayload(requestID common.Hash, err error) []byte {
+ payload := []byte(mailServerFailedPayloadPrefix)
+ payload = append(payload, requestID[:]...)
+ payload = append(payload, []byte(err.Error())...)
+ return payload
+}
+
+// CreateMailServerEvent returns EnvelopeEvent with correct data
+// if payload corresponds to any of the know mailserver events:
+// * request completed successfully
+// * request failed
+// If the payload is unknown/unparseable, it returns `nil`
+func CreateMailServerEvent(nodeID enode.ID, payload []byte) (*EnvelopeEvent, error) {
+ if len(payload) < common.HashLength {
+ return nil, invalidResponseSizeError(len(payload))
+ }
+
+ event, err := tryCreateMailServerRequestFailedEvent(nodeID, payload)
+ if err != nil {
+ return nil, err
+ } else if event != nil {
+ return event, nil
+ }
+
+ return tryCreateMailServerRequestCompletedEvent(nodeID, payload)
+}
+
+func tryCreateMailServerRequestFailedEvent(nodeID enode.ID, payload []byte) (*EnvelopeEvent, error) {
+ if len(payload) < common.HashLength+len(mailServerFailedPayloadPrefix) {
+ return nil, nil
+ }
+
+ prefix, remainder := extractPrefix(payload, len(mailServerFailedPayloadPrefix))
+
+ if !bytes.Equal(prefix, []byte(mailServerFailedPayloadPrefix)) {
+ return nil, nil
+ }
+
+ var (
+ requestID common.Hash
+ errorMsg string
+ )
+
+ requestID, remainder = extractHash(remainder)
+ errorMsg = string(remainder)
+
+ event := EnvelopeEvent{
+ Peer: nodeID,
+ Hash: requestID,
+ Event: EventMailServerRequestCompleted,
+ Data: &MailServerResponse{
+ Error: errors.New(errorMsg),
+ },
+ }
+
+ return &event, nil
+
+}
+
+func tryCreateMailServerRequestCompletedEvent(nodeID enode.ID, payload []byte) (*EnvelopeEvent, error) {
+ // check if payload is
+ // - requestID or
+ // - requestID + lastEnvelopeHash or
+ // - requestID + lastEnvelopeHash + cursor
+ // requestID is the hash of the request envelope.
+ // lastEnvelopeHash is the last envelope sent by the mail server
+ // cursor is the db key, 36 bytes: 4 for the timestamp + 32 for the envelope hash.
+ if len(payload) > common.HashLength*2+cursorSize {
+ return nil, invalidResponseSizeError(len(payload))
+ }
+
+ var (
+ requestID common.Hash
+ lastEnvelopeHash common.Hash
+ cursor []byte
+ )
+
+ requestID, remainder := extractHash(payload)
+
+ if len(remainder) >= common.HashLength {
+ lastEnvelopeHash, remainder = extractHash(remainder)
+ }
+
+ if len(remainder) >= cursorSize {
+ cursor = remainder
+ }
+
+ event := EnvelopeEvent{
+ Peer: nodeID,
+ Hash: requestID,
+ Event: EventMailServerRequestCompleted,
+ Data: &MailServerResponse{
+ LastEnvelopeHash: lastEnvelopeHash,
+ Cursor: cursor,
+ },
+ }
+
+ return &event, nil
+}
+
+func extractHash(payload []byte) (common.Hash, []byte) {
+ prefix, remainder := extractPrefix(payload, common.HashLength)
+ return common.BytesToHash(prefix), remainder
+}
+
+func extractPrefix(payload []byte, size int) ([]byte, []byte) {
+ return payload[:size], payload[size:]
+}
diff --git a/vendor/github.com/status-im/status-go/waku/message.go b/vendor/github.com/status-im/status-go/waku/message.go
new file mode 100644
index 000000000..b35953dea
--- /dev/null
+++ b/vendor/github.com/status-im/status-go/waku/message.go
@@ -0,0 +1,361 @@
+// Copyright 2019 The Waku Library Authors.
+//
+// The Waku library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The Waku library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty off
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the Waku library. If not, see .
+//
+// This software uses the go-ethereum library, which is licensed
+// under the GNU Lesser General Public Library, version 3 or any later.
+
+package waku
+
+import (
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/ecdsa"
+ crand "crypto/rand"
+ "encoding/binary"
+ "errors"
+ mrand "math/rand"
+ "strconv"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/crypto/ecies"
+ "github.com/ethereum/go-ethereum/log"
+)
+
+// MessageParams specifies the exact way a message should be wrapped
+// into an Envelope.
+type MessageParams struct {
+ TTL uint32
+ Src *ecdsa.PrivateKey
+ Dst *ecdsa.PublicKey
+ KeySym []byte
+ Topic TopicType
+ WorkTime uint32
+ PoW float64
+ Payload []byte
+ Padding []byte
+}
+
+// SentMessage represents an end-user data packet to transmit through the
+// Waku protocol. These are wrapped into Envelopes that need not be
+// understood by intermediate nodes, just forwarded.
+type sentMessage struct {
+ Raw []byte
+}
+
+// ReceivedMessage represents a data packet to be received through the
+// Waku protocol and successfully decrypted.
+type ReceivedMessage struct {
+ Raw []byte
+
+ Payload []byte
+ Padding []byte
+ Signature []byte
+ Salt []byte
+
+ PoW float64 // Proof of work as described in the Waku spec
+ Sent uint32 // Time when the message was posted into the network
+ TTL uint32 // Maximum time to live allowed for the message
+ Src *ecdsa.PublicKey // Message recipient (identity used to decode the message)
+ Dst *ecdsa.PublicKey // Message recipient (identity used to decode the message)
+ Topic TopicType
+
+ SymKeyHash common.Hash // The Keccak256Hash of the key
+ EnvelopeHash common.Hash // Message envelope hash to act as a unique id
+
+ P2P bool // is set to true if this message was received from mail server.
+}
+
+func isMessageSigned(flags byte) bool {
+ return (flags & signatureFlag) != 0
+}
+
+func (msg *ReceivedMessage) isSymmetricEncryption() bool {
+ return msg.SymKeyHash != common.Hash{}
+}
+
+func (msg *ReceivedMessage) isAsymmetricEncryption() bool {
+ return msg.Dst != nil
+}
+
+// NewSentMessage creates and initializes a non-signed, non-encrypted Waku message.
+func NewSentMessage(params *MessageParams) (*sentMessage, error) {
+ const payloadSizeFieldMaxSize = 4
+ msg := sentMessage{}
+ msg.Raw = make([]byte, 1,
+ flagsLength+payloadSizeFieldMaxSize+len(params.Payload)+len(params.Padding)+signatureLength+padSizeLimit)
+ msg.Raw[0] = 0 // set all the flags to zero
+ msg.addPayloadSizeField(params.Payload)
+ msg.Raw = append(msg.Raw, params.Payload...)
+ err := msg.appendPadding(params)
+ return &msg, err
+}
+
+// addPayloadSizeField appends the auxiliary field containing the size of payload
+func (msg *sentMessage) addPayloadSizeField(payload []byte) {
+ fieldSize := getSizeOfPayloadSizeField(payload)
+ field := make([]byte, 4)
+ binary.LittleEndian.PutUint32(field, uint32(len(payload)))
+ field = field[:fieldSize]
+ msg.Raw = append(msg.Raw, field...)
+ msg.Raw[0] |= byte(fieldSize)
+}
+
+// getSizeOfPayloadSizeField returns the number of bytes necessary to encode the size of payload
+func getSizeOfPayloadSizeField(payload []byte) int {
+ s := 1
+ for i := len(payload); i >= 256; i /= 256 {
+ s++
+ }
+ return s
+}
+
+// appendPadding appends the padding specified in params.
+// If no padding is provided in params, then random padding is generated.
+func (msg *sentMessage) appendPadding(params *MessageParams) error {
+ if len(params.Padding) != 0 {
+ // padding data was provided by the Dapp, just use it as is
+ msg.Raw = append(msg.Raw, params.Padding...)
+ return nil
+ }
+
+ rawSize := flagsLength + getSizeOfPayloadSizeField(params.Payload) + len(params.Payload)
+ if params.Src != nil {
+ rawSize += signatureLength
+ }
+ odd := rawSize % padSizeLimit
+ paddingSize := padSizeLimit - odd
+ pad := make([]byte, paddingSize)
+ _, err := crand.Read(pad)
+ if err != nil {
+ return err
+ }
+ if !validateDataIntegrity(pad, paddingSize) {
+ return errors.New("failed to generate random padding of size " + strconv.Itoa(paddingSize))
+ }
+ msg.Raw = append(msg.Raw, pad...)
+ return nil
+}
+
+// sign calculates and sets the cryptographic signature for the message,
+// also setting the sign flag.
+func (msg *sentMessage) sign(key *ecdsa.PrivateKey) error {
+ if isMessageSigned(msg.Raw[0]) {
+ // this should not happen, but no reason to panic
+ log.Error("failed to sign the message: already signed")
+ return nil
+ }
+
+ msg.Raw[0] |= signatureFlag // it is important to set this flag before signing
+ hash := crypto.Keccak256(msg.Raw)
+ signature, err := crypto.Sign(hash, key)
+ if err != nil {
+ msg.Raw[0] &= (0xFF ^ signatureFlag) // clear the flag
+ return err
+ }
+ msg.Raw = append(msg.Raw, signature...)
+ return nil
+}
+
+// encryptAsymmetric encrypts a message with a public key.
+func (msg *sentMessage) encryptAsymmetric(key *ecdsa.PublicKey) error {
+ if !ValidatePublicKey(key) {
+ return errors.New("invalid public key provided for asymmetric encryption")
+ }
+ encrypted, err := ecies.Encrypt(crand.Reader, ecies.ImportECDSAPublic(key), msg.Raw, nil, nil)
+ if err == nil {
+ msg.Raw = encrypted
+ }
+ return err
+}
+
+// encryptSymmetric encrypts a message with a topic key, using AES-GCM-256.
+// nonce size should be 12 bytes (see cipher.gcmStandardNonceSize).
+func (msg *sentMessage) encryptSymmetric(key []byte) (err error) {
+ if !validateDataIntegrity(key, aesKeyLength) {
+ return errors.New("invalid key provided for symmetric encryption, size: " + strconv.Itoa(len(key)))
+ }
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ return err
+ }
+ aesgcm, err := cipher.NewGCM(block)
+ if err != nil {
+ return err
+ }
+ salt, err := generateSecureRandomData(aesNonceLength) // never use more than 2^32 random nonces with a given key
+ if err != nil {
+ return err
+ }
+ encrypted := aesgcm.Seal(nil, salt, msg.Raw, nil)
+ msg.Raw = append(encrypted, salt...)
+ return nil
+}
+
+// generateSecureRandomData generates random data where extra security is required.
+// The purpose of this function is to prevent some bugs in software or in hardware
+// from delivering not-very-random data. This is especially useful for AES nonce,
+// where true randomness does not really matter, but it is very important to have
+// a unique nonce for every message.
+func generateSecureRandomData(length int) ([]byte, error) {
+ x := make([]byte, length)
+ y := make([]byte, length)
+ res := make([]byte, length)
+
+ _, err := crand.Read(x)
+ if err != nil {
+ return nil, err
+ } else if !validateDataIntegrity(x, length) {
+ return nil, errors.New("crypto/rand failed to generate secure random data")
+ }
+ _, err = mrand.Read(y)
+ if err != nil {
+ return nil, err
+ } else if !validateDataIntegrity(y, length) {
+ return nil, errors.New("math/rand failed to generate secure random data")
+ }
+ for i := 0; i < length; i++ {
+ res[i] = x[i] ^ y[i]
+ }
+ if !validateDataIntegrity(res, length) {
+ return nil, errors.New("failed to generate secure random data")
+ }
+ return res, nil
+}
+
+// Wrap bundles the message into an Envelope to transmit over the network.
+func (msg *sentMessage) Wrap(options *MessageParams, now time.Time) (envelope *Envelope, err error) {
+ if options.TTL == 0 {
+ options.TTL = DefaultTTL
+ }
+ if options.Src != nil {
+ if err = msg.sign(options.Src); err != nil {
+ return nil, err
+ }
+ }
+ if options.Dst != nil {
+ err = msg.encryptAsymmetric(options.Dst)
+ } else if options.KeySym != nil {
+ err = msg.encryptSymmetric(options.KeySym)
+ } else {
+ err = errors.New("unable to encrypt the message: neither symmetric nor assymmetric key provided")
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ envelope = NewEnvelope(options.TTL, options.Topic, msg, now)
+ if err = envelope.Seal(options); err != nil {
+ return nil, err
+ }
+ return envelope, nil
+}
+
+// decryptSymmetric decrypts a message with a topic key, using AES-GCM-256.
+// nonce size should be 12 bytes (see cipher.gcmStandardNonceSize).
+func (msg *ReceivedMessage) decryptSymmetric(key []byte) error {
+ // symmetric messages are expected to contain the 12-byte nonce at the end of the payload
+ if len(msg.Raw) < aesNonceLength {
+ return errors.New("missing salt or invalid payload in symmetric message")
+ }
+ salt := msg.Raw[len(msg.Raw)-aesNonceLength:]
+
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ return err
+ }
+ aesgcm, err := cipher.NewGCM(block)
+ if err != nil {
+ return err
+ }
+ decrypted, err := aesgcm.Open(nil, salt, msg.Raw[:len(msg.Raw)-aesNonceLength], nil)
+ if err != nil {
+ return err
+ }
+ msg.Raw = decrypted
+ msg.Salt = salt
+ return nil
+}
+
+// decryptAsymmetric decrypts an encrypted payload with a private key.
+func (msg *ReceivedMessage) decryptAsymmetric(key *ecdsa.PrivateKey) error {
+ decrypted, err := ecies.ImportECDSA(key).Decrypt(msg.Raw, nil, nil)
+ if err == nil {
+ msg.Raw = decrypted
+ }
+ return err
+}
+
+// ValidateAndParse checks the message validity and extracts the fields in case of success.
+func (msg *ReceivedMessage) ValidateAndParse() bool {
+ end := len(msg.Raw)
+ if end < 1 {
+ return false
+ }
+
+ if isMessageSigned(msg.Raw[0]) {
+ end -= signatureLength
+ if end <= 1 {
+ return false
+ }
+ msg.Signature = msg.Raw[end : end+signatureLength]
+ msg.Src = msg.SigToPubKey()
+ if msg.Src == nil {
+ return false
+ }
+ }
+
+ beg := 1
+ payloadSize := 0
+ sizeOfPayloadSizeField := int(msg.Raw[0] & SizeMask) // number of bytes indicating the size of payload
+ if sizeOfPayloadSizeField != 0 {
+ if end < beg+sizeOfPayloadSizeField {
+ return false
+ }
+ payloadSize = int(bytesToUintLittleEndian(msg.Raw[beg : beg+sizeOfPayloadSizeField]))
+ beg += sizeOfPayloadSizeField
+ if beg+payloadSize > end {
+ return false
+ }
+ msg.Payload = msg.Raw[beg : beg+payloadSize]
+ }
+
+ beg += payloadSize
+ msg.Padding = msg.Raw[beg:end]
+ return true
+}
+
+// SigToPubKey returns the public key associated to the message's
+// signature.
+func (msg *ReceivedMessage) SigToPubKey() *ecdsa.PublicKey {
+ defer func() { recover() }() // in case of invalid signature
+
+ pub, err := crypto.SigToPub(msg.hash(), msg.Signature)
+ if err != nil {
+ log.Error("failed to recover public key from signature", "err", err)
+ return nil
+ }
+ return pub
+}
+
+// hash calculates the SHA3 checksum of the message flags, payload size field, payload and padding.
+func (msg *ReceivedMessage) hash() []byte {
+ if isMessageSigned(msg.Raw[0]) {
+ sz := len(msg.Raw) - signatureLength
+ return crypto.Keccak256(msg.Raw[:sz])
+ }
+ return crypto.Keccak256(msg.Raw)
+}
diff --git a/vendor/github.com/status-im/status-go/waku/metrics.go b/vendor/github.com/status-im/status-go/waku/metrics.go
new file mode 100644
index 000000000..f1f08e131
--- /dev/null
+++ b/vendor/github.com/status-im/status-go/waku/metrics.go
@@ -0,0 +1,70 @@
+// Copyright 2019 The Waku Library Authors.
+//
+// The Waku library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The Waku library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty off
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the Waku library. If not, see .
+//
+// This software uses the go-ethereum library, which is licensed
+// under the GNU Lesser General Public Library, version 3 or any later.
+
+package waku
+
+import (
+ prom "github.com/prometheus/client_golang/prometheus"
+)
+
+var (
+ envelopesReceivedCounter = prom.NewCounter(prom.CounterOpts{
+ Name: "waku_envelopes_received_total",
+ Help: "Number of envelopes received.",
+ })
+ envelopesValidatedCounter = prom.NewCounter(prom.CounterOpts{
+ Name: "waku_envelopes_validated_total",
+ Help: "Number of envelopes processed successfully.",
+ })
+ envelopesRejectedCounter = prom.NewCounterVec(prom.CounterOpts{
+ Name: "waku_envelopes_rejected_total",
+ Help: "Number of envelopes rejected.",
+ }, []string{"reason"})
+ envelopesCacheFailedCounter = prom.NewCounterVec(prom.CounterOpts{
+ Name: "waku_envelopes_cache_failures_total",
+ Help: "Number of envelopes which failed to be cached.",
+ }, []string{"type"})
+ envelopesCachedCounter = prom.NewCounterVec(prom.CounterOpts{
+ Name: "waku_envelopes_cached_total",
+ Help: "Number of envelopes cached.",
+ }, []string{"cache"})
+ envelopesSizeMeter = prom.NewHistogram(prom.HistogramOpts{
+ Name: "waku_envelopes_size_bytes",
+ Help: "Size of processed Waku envelopes in bytes.",
+ Buckets: prom.ExponentialBuckets(256, 4, 10),
+ })
+ // rate limiter metrics
+ rateLimitsProcessed = prom.NewCounter(prom.CounterOpts{
+ Name: "waku_rate_limits_processed_total",
+ Help: "Number of packets Waku rate limiter processed.",
+ })
+ rateLimitsExceeded = prom.NewCounterVec(prom.CounterOpts{
+ Name: "waku_rate_limits_exceeded_total",
+ Help: "Number of times the Waku rate limits were exceeded",
+ }, []string{"type"})
+)
+
+func init() {
+ prom.MustRegister(envelopesReceivedCounter)
+ prom.MustRegister(envelopesRejectedCounter)
+ prom.MustRegister(envelopesCacheFailedCounter)
+ prom.MustRegister(envelopesCachedCounter)
+ prom.MustRegister(envelopesSizeMeter)
+ prom.MustRegister(rateLimitsProcessed)
+ prom.MustRegister(rateLimitsExceeded)
+}
diff --git a/vendor/github.com/status-im/status-go/waku/peer.go b/vendor/github.com/status-im/status-go/waku/peer.go
new file mode 100644
index 000000000..92506173e
--- /dev/null
+++ b/vendor/github.com/status-im/status-go/waku/peer.go
@@ -0,0 +1,321 @@
+// Copyright 2019 The Waku Library Authors.
+//
+// The Waku library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The Waku library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty off
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the Waku library. If not, see .
+//
+// This software uses the go-ethereum library, which is licensed
+// under the GNU Lesser General Public Library, version 3 or any later.
+
+package waku
+
+import (
+ "bytes"
+ "fmt"
+ "math"
+ "sync"
+ "time"
+
+ mapset "github.com/deckarep/golang-set"
+ "go.uber.org/zap"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/p2p"
+ "github.com/ethereum/go-ethereum/rlp"
+)
+
+// Peer represents a waku protocol peer connection.
+type Peer struct {
+ host *Waku
+ peer *p2p.Peer
+ ws p2p.MsgReadWriter
+ logger *zap.Logger
+
+ trusted bool
+ powRequirement float64
+ bloomMu sync.Mutex
+ bloomFilter []byte
+ fullNode bool
+ confirmationsEnabled bool
+ rateLimitsMu sync.Mutex
+ rateLimits RateLimits
+
+ known mapset.Set // Messages already known by the peer to avoid wasting bandwidth
+
+ quit chan struct{}
+}
+
+// newPeer creates a new waku peer object, but does not run the handshake itself.
+func newPeer(host *Waku, remote *p2p.Peer, rw p2p.MsgReadWriter, logger *zap.Logger) *Peer {
+ if logger == nil {
+ logger = zap.NewNop()
+ }
+
+ return &Peer{
+ host: host,
+ peer: remote,
+ ws: rw,
+ logger: logger,
+ trusted: false,
+ powRequirement: 0.0,
+ known: mapset.NewSet(),
+ quit: make(chan struct{}),
+ bloomFilter: MakeFullNodeBloom(),
+ fullNode: true,
+ }
+}
+
+// start initiates the peer updater, periodically broadcasting the waku packets
+// into the network.
+func (p *Peer) start() {
+ go p.update()
+ p.logger.Debug("starting peer", zap.Binary("peerID", p.ID()))
+}
+
+// stop terminates the peer updater, stopping message forwarding to it.
+func (p *Peer) stop() {
+ close(p.quit)
+ p.logger.Debug("stopping peer", zap.Binary("peerID", p.ID()))
+}
+
+// handshake sends the protocol initiation status message to the remote peer and
+// verifies the remote status too.
+func (p *Peer) handshake() error {
+ // Send the handshake status message asynchronously
+ errc := make(chan error, 1)
+ isLightNode := p.host.LightClientMode()
+ isRestrictedLightNodeConnection := p.host.LightClientModeConnectionRestricted()
+ go func() {
+ pow := p.host.MinPow()
+ powConverted := math.Float64bits(pow)
+ bloom := p.host.BloomFilter()
+ confirmationsEnabled := p.host.ConfirmationsEnabled()
+ rateLimits := p.host.RateLimits()
+
+ errc <- p2p.SendItems(p.ws, statusCode, ProtocolVersion, powConverted, bloom, isLightNode, confirmationsEnabled, rateLimits)
+ }()
+
+ // Fetch the remote status packet and verify protocol match
+ packet, err := p.ws.ReadMsg()
+ if err != nil {
+ return err
+ }
+ if packet.Code != statusCode {
+ return fmt.Errorf("p [%x] sent packet %x before status packet", p.ID(), packet.Code)
+ }
+ s := rlp.NewStream(packet.Payload, uint64(packet.Size))
+ _, err = s.List()
+ if err != nil {
+ return fmt.Errorf("p [%x] sent bad status message: %v", p.ID(), err)
+ }
+ peerVersion, err := s.Uint()
+ if err != nil {
+ return fmt.Errorf("p [%x] sent bad status message (unable to decode version): %v", p.ID(), err)
+ }
+ if peerVersion != ProtocolVersion {
+ return fmt.Errorf("p [%x]: protocol version mismatch %d != %d", p.ID(), peerVersion, ProtocolVersion)
+ }
+
+ // only version is mandatory, subsequent parameters are optional
+ powRaw, err := s.Uint()
+ if err == nil {
+ pow := math.Float64frombits(powRaw)
+ if math.IsInf(pow, 0) || math.IsNaN(pow) || pow < 0.0 {
+ return fmt.Errorf("p [%x] sent bad status message: invalid pow", p.ID())
+ }
+ p.powRequirement = pow
+
+ var bloom []byte
+ err = s.Decode(&bloom)
+ if err == nil {
+ sz := len(bloom)
+ if sz != BloomFilterSize && sz != 0 {
+ return fmt.Errorf("p [%x] sent bad status message: wrong bloom filter size %d", p.ID(), sz)
+ }
+ p.setBloomFilter(bloom)
+ }
+ }
+
+ isRemotePeerLightNode, _ := s.Bool()
+ if isRemotePeerLightNode && isLightNode && isRestrictedLightNodeConnection {
+ return fmt.Errorf("p [%x] is useless: two light client communication restricted", p.ID())
+ }
+ confirmationsEnabled, err := s.Bool()
+ if err != nil || !confirmationsEnabled {
+ p.logger.Info("confirmations are disabled for peer", zap.Binary("peer", p.ID()))
+ } else {
+ p.confirmationsEnabled = confirmationsEnabled
+ }
+
+ var rateLimits RateLimits
+ if err := s.Decode(&rateLimits); err != nil {
+ p.logger.Info("rate limiting is disabled for peer", zap.Binary("peer", p.ID()))
+ } else {
+ p.setRateLimits(rateLimits)
+ }
+
+ if err := <-errc; err != nil {
+ return fmt.Errorf("p [%x] failed to send status packet: %v", p.ID(), err)
+ }
+ return nil
+}
+
+// update executes periodic operations on the peer, including message transmission
+// and expiration.
+func (p *Peer) update() {
+ // Start the tickers for the updates
+ expire := time.NewTicker(expirationCycle)
+ transmit := time.NewTicker(transmissionCycle)
+
+ // Loop and transmit until termination is requested
+ for {
+ select {
+ case <-expire.C:
+ p.expire()
+
+ case <-transmit.C:
+ if err := p.broadcast(); err != nil {
+ p.logger.Debug("broadcasting failed", zap.Binary("peer", p.ID()), zap.Error(err))
+ return
+ }
+
+ case <-p.quit:
+ return
+ }
+ }
+}
+
+// mark marks an envelope known to the peer so that it won't be sent back.
+func (p *Peer) mark(envelope *Envelope) {
+ p.known.Add(envelope.Hash())
+}
+
+// marked checks if an envelope is already known to the remote peer.
+func (p *Peer) marked(envelope *Envelope) bool {
+ return p.known.Contains(envelope.Hash())
+}
+
+// expire iterates over all the known envelopes in the host and removes all
+// expired (unknown) ones from the known list.
+func (p *Peer) expire() {
+ unmark := make(map[common.Hash]struct{})
+ p.known.Each(func(v interface{}) bool {
+ if !p.host.isEnvelopeCached(v.(common.Hash)) {
+ unmark[v.(common.Hash)] = struct{}{}
+ }
+ return true
+ })
+ // Dump all known but no longer cached
+ for hash := range unmark {
+ p.known.Remove(hash)
+ }
+}
+
+// broadcast iterates over the collection of envelopes and transmits yet unknown
+// ones over the network.
+func (p *Peer) broadcast() error {
+ envelopes := p.host.Envelopes()
+ bundle := make([]*Envelope, 0, len(envelopes))
+ for _, envelope := range envelopes {
+ if !p.marked(envelope) && envelope.PoW() >= p.powRequirement && p.bloomMatch(envelope) {
+ bundle = append(bundle, envelope)
+ }
+ }
+
+ if len(bundle) == 0 {
+ return nil
+ }
+
+ batchHash, err := sendBundle(p.ws, bundle)
+ if err != nil {
+ p.logger.Debug("failed to deliver envelopes", zap.Binary("peer", p.ID()), zap.Error(err))
+ return err
+ }
+
+ // mark envelopes only if they were successfully sent
+ for _, e := range bundle {
+ p.mark(e)
+ event := EnvelopeEvent{
+ Event: EventEnvelopeSent,
+ Hash: e.Hash(),
+ Peer: p.peer.ID(),
+ }
+ if p.confirmationsEnabled {
+ event.Batch = batchHash
+ }
+ p.host.envelopeFeed.Send(event)
+ }
+ p.logger.Debug("broadcasted bundles successfully", zap.Binary("peer", p.ID()), zap.Int("count", len(bundle)))
+ return nil
+}
+
+// ID returns a peer's id
+func (p *Peer) ID() []byte {
+ id := p.peer.ID()
+ return id[:]
+}
+
+func (p *Peer) notifyAboutPowRequirementChange(pow float64) error {
+ i := math.Float64bits(pow)
+ return p2p.Send(p.ws, powRequirementCode, i)
+}
+
+func (p *Peer) notifyAboutBloomFilterChange(bloom []byte) error {
+ return p2p.Send(p.ws, bloomFilterExCode, bloom)
+}
+
+func (p *Peer) bloomMatch(env *Envelope) bool {
+ p.bloomMu.Lock()
+ defer p.bloomMu.Unlock()
+ return p.fullNode || BloomFilterMatch(p.bloomFilter, env.Bloom())
+}
+
+func (p *Peer) setBloomFilter(bloom []byte) {
+ p.bloomMu.Lock()
+ defer p.bloomMu.Unlock()
+ p.bloomFilter = bloom
+ p.fullNode = isFullNode(bloom)
+ if p.fullNode && p.bloomFilter == nil {
+ p.bloomFilter = MakeFullNodeBloom()
+ }
+}
+
+func (p *Peer) setRateLimits(r RateLimits) {
+ p.rateLimitsMu.Lock()
+ p.rateLimits = r
+ p.rateLimitsMu.Unlock()
+}
+
+func MakeFullNodeBloom() []byte {
+ bloom := make([]byte, BloomFilterSize)
+ for i := 0; i < BloomFilterSize; i++ {
+ bloom[i] = 0xFF
+ }
+ return bloom
+}
+
+func sendBundle(rw p2p.MsgWriter, bundle []*Envelope) (rst common.Hash, err error) {
+ data, err := rlp.EncodeToBytes(bundle)
+ if err != nil {
+ return
+ }
+ err = rw.WriteMsg(p2p.Msg{
+ Code: messagesCode,
+ Size: uint32(len(data)),
+ Payload: bytes.NewBuffer(data),
+ })
+ if err != nil {
+ return
+ }
+ return crypto.Keccak256Hash(data), nil
+}
diff --git a/vendor/github.com/status-im/status-go/waku/rate_limiter.go b/vendor/github.com/status-im/status-go/waku/rate_limiter.go
new file mode 100644
index 000000000..2ea260f80
--- /dev/null
+++ b/vendor/github.com/status-im/status-go/waku/rate_limiter.go
@@ -0,0 +1,236 @@
+// Copyright 2019 The Waku Library Authors.
+//
+// The Waku library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The Waku library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty off
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the Waku library. If not, see .
+//
+// This software uses the go-ethereum library, which is licensed
+// under the GNU Lesser General Public Library, version 3 or any later.
+
+package waku
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "time"
+
+ "github.com/tsenart/tb"
+
+ "github.com/ethereum/go-ethereum/p2p"
+ "github.com/ethereum/go-ethereum/p2p/enode"
+)
+
+type runLoop func(p *Peer, rw p2p.MsgReadWriter) error
+
+type RateLimiterHandler interface {
+ ExceedPeerLimit() error
+ ExceedIPLimit() error
+}
+
+type MetricsRateLimiterHandler struct{}
+
+func (MetricsRateLimiterHandler) ExceedPeerLimit() error {
+ rateLimitsExceeded.WithLabelValues("peer_id").Inc()
+ return nil
+}
+func (MetricsRateLimiterHandler) ExceedIPLimit() error {
+ rateLimitsExceeded.WithLabelValues("ip").Inc()
+ return nil
+}
+
+var ErrRateLimitExceeded = errors.New("rate limit has been exceeded")
+
+type DropPeerRateLimiterHandler struct {
+ // Tolerance is a number of how many a limit must be exceeded
+ // in order to drop a peer.
+ Tolerance int64
+
+ peerLimitExceeds int64
+ ipLimitExceeds int64
+}
+
+func (h *DropPeerRateLimiterHandler) ExceedPeerLimit() error {
+ h.peerLimitExceeds++
+ if h.Tolerance > 0 && h.peerLimitExceeds >= h.Tolerance {
+ return ErrRateLimitExceeded
+ }
+ return nil
+}
+
+func (h *DropPeerRateLimiterHandler) ExceedIPLimit() error {
+ h.ipLimitExceeds++
+ if h.Tolerance > 0 && h.ipLimitExceeds >= h.Tolerance {
+ return ErrRateLimitExceeded
+ }
+ return nil
+}
+
+type PeerRateLimiterConfig struct {
+ LimitPerSecIP int64
+ LimitPerSecPeerID int64
+ WhitelistedIPs []string
+ WhitelistedPeerIDs []enode.ID
+}
+
+var defaultPeerRateLimiterConfig = PeerRateLimiterConfig{
+ LimitPerSecIP: 10,
+ LimitPerSecPeerID: 5,
+ WhitelistedIPs: nil,
+ WhitelistedPeerIDs: nil,
+}
+
+type PeerRateLimiter struct {
+ peerIDThrottler *tb.Throttler
+ ipThrottler *tb.Throttler
+
+ limitPerSecIP int64
+ limitPerSecPeerID int64
+
+ whitelistedPeerIDs []enode.ID
+ whitelistedIPs []string
+
+ handlers []RateLimiterHandler
+}
+
+func NewPeerRateLimiter(cfg *PeerRateLimiterConfig, handlers ...RateLimiterHandler) *PeerRateLimiter {
+ if cfg == nil {
+ copy := defaultPeerRateLimiterConfig
+ cfg = ©
+ }
+
+ return &PeerRateLimiter{
+ peerIDThrottler: tb.NewThrottler(time.Millisecond * 100),
+ ipThrottler: tb.NewThrottler(time.Millisecond * 100),
+ limitPerSecIP: cfg.LimitPerSecIP,
+ limitPerSecPeerID: cfg.LimitPerSecPeerID,
+ whitelistedPeerIDs: cfg.WhitelistedPeerIDs,
+ whitelistedIPs: cfg.WhitelistedIPs,
+ handlers: handlers,
+ }
+}
+
+func (r *PeerRateLimiter) decorate(p *Peer, rw p2p.MsgReadWriter, runLoop runLoop) error {
+ in, out := p2p.MsgPipe()
+ defer in.Close()
+ defer out.Close()
+ errC := make(chan error, 1)
+
+ // Read from the original reader and write to the message pipe.
+ go func() {
+ for {
+ packet, err := rw.ReadMsg()
+ if err != nil {
+ errC <- fmt.Errorf("failed to read packet: %v", err)
+ return
+ }
+
+ rateLimitsProcessed.Inc()
+
+ var ip string
+ if p != nil && p.peer != nil {
+ ip = p.peer.Node().IP().String()
+ }
+ if halted := r.throttleIP(ip); halted {
+ for _, h := range r.handlers {
+ if err := h.ExceedIPLimit(); err != nil {
+ errC <- fmt.Errorf("exceed rate limit by IP: %w", err)
+ return
+ }
+ }
+ }
+
+ var peerID []byte
+ if p != nil {
+ peerID = p.ID()
+ }
+ if halted := r.throttlePeer(peerID); halted {
+ for _, h := range r.handlers {
+ if err := h.ExceedPeerLimit(); err != nil {
+ errC <- fmt.Errorf("exceeded rate limit by peer: %w", err)
+ return
+ }
+ }
+ }
+
+ if err := in.WriteMsg(packet); err != nil {
+ errC <- fmt.Errorf("failed to write packet to pipe: %v", err)
+ return
+ }
+ }
+ }()
+
+ // Read from the message pipe and write to the original writer.
+ go func() {
+ for {
+ packet, err := in.ReadMsg()
+ if err != nil {
+ errC <- fmt.Errorf("failed to read packet from pipe: %v", err)
+ return
+ }
+ if err := rw.WriteMsg(packet); err != nil {
+ errC <- fmt.Errorf("failed to write packet: %v", err)
+ return
+ }
+ }
+ }()
+
+ go func() {
+ errC <- runLoop(p, out)
+ }()
+
+ return <-errC
+}
+
+// throttleIP throttles a number of messages incoming from a given IP.
+// It allows 10 packets per second.
+func (r *PeerRateLimiter) throttleIP(ip string) bool {
+ if r.limitPerSecIP == 0 {
+ return false
+ }
+ if stringSliceContains(r.whitelistedIPs, ip) {
+ return false
+ }
+ return r.ipThrottler.Halt(ip, 1, r.limitPerSecIP)
+}
+
+// throttlePeer throttles a number of messages incoming from a peer.
+// It allows 3 packets per second.
+func (r *PeerRateLimiter) throttlePeer(peerID []byte) bool {
+ if r.limitPerSecIP == 0 {
+ return false
+ }
+ var id enode.ID
+ copy(id[:], peerID)
+ if enodeIDSliceContains(r.whitelistedPeerIDs, id) {
+ return false
+ }
+ return r.peerIDThrottler.Halt(id.String(), 1, r.limitPerSecPeerID)
+}
+
+func stringSliceContains(s []string, searched string) bool {
+ for _, item := range s {
+ if item == searched {
+ return true
+ }
+ }
+ return false
+}
+
+func enodeIDSliceContains(s []enode.ID, searched enode.ID) bool {
+ for _, item := range s {
+ if bytes.Equal(item.Bytes(), searched.Bytes()) {
+ return true
+ }
+ }
+ return false
+}
diff --git a/vendor/github.com/status-im/status-go/waku/topic.go b/vendor/github.com/status-im/status-go/waku/topic.go
new file mode 100644
index 000000000..a9e77ff89
--- /dev/null
+++ b/vendor/github.com/status-im/status-go/waku/topic.go
@@ -0,0 +1,56 @@
+// Copyright 2019 The Waku Library Authors.
+//
+// The Waku library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The Waku library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty off
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the Waku library. If not, see .
+//
+// This software uses the go-ethereum library, which is licensed
+// under the GNU Lesser General Public Library, version 3 or any later.
+
+package waku
+
+import (
+ "github.com/ethereum/go-ethereum/common/hexutil"
+)
+
+// TopicType represents a cryptographically secure, probabilistic partial
+// classifications of a message, determined as the first (left) 4 bytes of the
+// SHA3 hash of some arbitrary data given by the original author of the message.
+type TopicType [TopicLength]byte
+
+// BytesToTopic converts from the byte array representation of a topic
+// into the TopicType type.
+func BytesToTopic(b []byte) (t TopicType) {
+ sz := TopicLength
+ if x := len(b); x < TopicLength {
+ sz = x
+ }
+ for i := 0; i < sz; i++ {
+ t[i] = b[i]
+ }
+ return t
+}
+
+// String converts a topic byte array to a string representation.
+func (t *TopicType) String() string {
+ return hexutil.Encode(t[:])
+}
+
+// MarshalText returns the hex representation of t.
+func (t TopicType) MarshalText() ([]byte, error) {
+ return hexutil.Bytes(t[:]).MarshalText()
+}
+
+// UnmarshalText parses a hex representation to a topic.
+func (t *TopicType) UnmarshalText(input []byte) error {
+ return hexutil.UnmarshalFixedText("Topic", input, t[:])
+}
diff --git a/vendor/github.com/status-im/status-go/waku/waku.go b/vendor/github.com/status-im/status-go/waku/waku.go
new file mode 100644
index 000000000..fe68e660d
--- /dev/null
+++ b/vendor/github.com/status-im/status-go/waku/waku.go
@@ -0,0 +1,1490 @@
+// Copyright 2019 The Waku Library Authors.
+//
+// The Waku library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The Waku library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty off
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the Waku library. If not, see .
+//
+// This software uses the go-ethereum library, which is licensed
+// under the GNU Lesser General Public Library, version 3 or any later.
+
+package waku
+
+import (
+ "bytes"
+ "crypto/ecdsa"
+ "crypto/sha256"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "math"
+ "runtime"
+ "sync"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common/hexutil"
+
+ "go.uber.org/zap"
+
+ mapset "github.com/deckarep/golang-set"
+ "golang.org/x/crypto/pbkdf2"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/event"
+ "github.com/ethereum/go-ethereum/log"
+ "github.com/ethereum/go-ethereum/p2p"
+ "github.com/ethereum/go-ethereum/p2p/enode"
+ "github.com/ethereum/go-ethereum/rlp"
+ "github.com/ethereum/go-ethereum/rpc"
+)
+
+// TimeSyncError error for clock skew errors.
+type TimeSyncError error
+
+type settings struct {
+ MaxMsgSize uint32 // Maximal message length allowed by the waku node
+ EnableConfirmations bool // Enable sending message confirmations
+ MinPow float64 // Minimal PoW required by the waku node
+ MinPowTolerance float64 // Minimal PoW tolerated by the waku node for a limited time
+ BloomFilter []byte // Bloom filter for topics of interest for this node
+ BloomFilterTolerance []byte // Bloom filter tolerated by the waku node for a limited time
+ LightClient bool // Light client mode enabled does not forward messages
+ RestrictLightClientsConn bool // Restrict connection between two light clients
+ SyncAllowance int // Maximum time in seconds allowed to process the waku-related messages
+}
+
+// Waku represents a dark communication interface through the Ethereum
+// network, using its very own P2P communication layer.
+type Waku struct {
+ protocol p2p.Protocol // Protocol description and parameters
+ filters *Filters // Message filters installed with Subscribe function
+
+ privateKeys map[string]*ecdsa.PrivateKey // Private key storage
+ symKeys map[string][]byte // Symmetric key storage
+ keyMu sync.RWMutex // Mutex associated with key stores
+
+ envelopes map[common.Hash]*Envelope // Pool of envelopes currently tracked by this node
+ expirations map[uint32]mapset.Set // Message expiration pool
+ poolMu sync.RWMutex // Mutex to sync the message and expiration pools
+
+ peers map[*Peer]struct{} // Set of currently active peers
+ peerMu sync.RWMutex // Mutex to sync the active peer set
+
+ msgQueue chan *Envelope // Message queue for normal waku messages
+ p2pMsgQueue chan interface{} // Message queue for peer-to-peer messages (not to be forwarded any further) and history delivery confirmations.
+ quit chan struct{} // Channel used for graceful exit
+
+ settings settings // Holds configuration settings that can be dynamically changed
+ settingsMu sync.RWMutex // Mutex to sync the settings access
+
+ mailServer MailServer
+
+ rateLimiter *PeerRateLimiter
+
+ envelopeFeed event.Feed
+
+ timeSource func() time.Time // source of time for waku
+
+ logger *zap.Logger
+}
+
+// New creates a Waku client ready to communicate through the Ethereum P2P network.
+func New(cfg *Config, logger *zap.Logger) *Waku {
+ if cfg == nil {
+ c := DefaultConfig
+ cfg = &c
+ }
+
+ if logger == nil {
+ logger = zap.NewNop()
+ }
+
+ waku := &Waku{
+ privateKeys: make(map[string]*ecdsa.PrivateKey),
+ symKeys: make(map[string][]byte),
+ envelopes: make(map[common.Hash]*Envelope),
+ expirations: make(map[uint32]mapset.Set),
+ peers: make(map[*Peer]struct{}),
+ msgQueue: make(chan *Envelope, messageQueueLimit),
+ p2pMsgQueue: make(chan interface{}, messageQueueLimit),
+ quit: make(chan struct{}),
+ timeSource: time.Now,
+ logger: logger,
+ }
+
+ waku.settings = settings{
+ MaxMsgSize: cfg.MaxMessageSize,
+ MinPow: cfg.MinimumAcceptedPoW,
+ MinPowTolerance: cfg.MinimumAcceptedPoW,
+ EnableConfirmations: cfg.EnableConfirmations,
+ LightClient: cfg.LightClient,
+ RestrictLightClientsConn: cfg.RestrictLightClientsConn,
+ SyncAllowance: DefaultSyncAllowance,
+ }
+
+ if cfg.FullNode {
+ waku.settings.BloomFilter = MakeFullNodeBloom()
+ waku.settings.BloomFilterTolerance = MakeFullNodeBloom()
+ }
+
+ waku.filters = NewFilters(waku)
+
+ // p2p waku sub-protocol handler
+ waku.protocol = p2p.Protocol{
+ Name: ProtocolName,
+ Version: uint(ProtocolVersion),
+ Length: NumberOfMessageCodes,
+ Run: waku.HandlePeer,
+ NodeInfo: func() interface{} {
+ return map[string]interface{}{
+ "version": ProtocolVersionStr,
+ "maxMessageSize": waku.MaxMessageSize(),
+ "minimumPoW": waku.MinPow(),
+ }
+ },
+ }
+
+ return waku
+}
+
+// Version returns the waku sub-protocol version number.
+func (w *Waku) Version() uint {
+ return w.protocol.Version
+}
+
+// MinPow returns the PoW value required by this node.
+func (w *Waku) MinPow() float64 {
+ w.settingsMu.RLock()
+ defer w.settingsMu.RUnlock()
+ return w.settings.MinPow
+}
+
+// SetMinimumPoW sets the minimal PoW required by this node
+func (w *Waku) SetMinimumPoW(val float64, tolerate bool) error {
+ if val < 0.0 {
+ return fmt.Errorf("invalid PoW: %f", val)
+ }
+
+ w.settingsMu.Lock()
+ w.settings.MinPow = val
+ w.settingsMu.Unlock()
+
+ w.notifyPeersAboutPowRequirementChange(val)
+
+ if tolerate {
+ go func() {
+ // allow some time before all the peers have processed the notification
+ time.Sleep(time.Duration(w.settings.SyncAllowance) * time.Second)
+ w.settingsMu.Lock()
+ w.settings.MinPowTolerance = val
+ w.settingsMu.Unlock()
+ }()
+ }
+
+ return nil
+}
+
+// MinPowTolerance returns the value of minimum PoW which is tolerated for a limited
+// time after PoW was changed. If sufficient time have elapsed or no change of PoW
+// have ever occurred, the return value will be the same as return value of MinPow().
+func (w *Waku) MinPowTolerance() float64 {
+ w.settingsMu.RLock()
+ defer w.settingsMu.RUnlock()
+ return w.settings.MinPowTolerance
+}
+
+// BloomFilter returns the aggregated bloom filter for all the topics of interest.
+// The nodes are required to send only messages that match the advertised bloom filter.
+// If a message does not match the bloom, it will tantamount to spam, and the peer will
+// be disconnected.
+func (w *Waku) BloomFilter() []byte {
+ w.settingsMu.RLock()
+ defer w.settingsMu.RUnlock()
+ return w.settings.BloomFilter
+}
+
+// BloomFilterTolerance returns the bloom filter which is tolerated for a limited
+// time after new bloom was advertised to the peers. If sufficient time have elapsed
+// or no change of bloom filter have ever occurred, the return value will be the same
+// as return value of BloomFilter().
+func (w *Waku) BloomFilterTolerance() []byte {
+ w.settingsMu.RLock()
+ defer w.settingsMu.RUnlock()
+ return w.settings.BloomFilterTolerance
+}
+
+// SetBloomFilter sets the new bloom filter
+func (w *Waku) SetBloomFilter(bloom []byte) error {
+ if len(bloom) != BloomFilterSize {
+ return fmt.Errorf("invalid bloom filter size: %d", len(bloom))
+ }
+
+ b := make([]byte, BloomFilterSize)
+ copy(b, bloom)
+
+ w.settingsMu.Lock()
+ w.settings.BloomFilter = b
+ w.settingsMu.Unlock()
+ w.notifyPeersAboutBloomFilterChange(b)
+
+ go func() {
+ // allow some time before all the peers have processed the notification
+ time.Sleep(time.Duration(w.settings.SyncAllowance) * time.Second)
+ w.settingsMu.Lock()
+ w.settings.BloomFilterTolerance = b
+ w.settingsMu.Unlock()
+ }()
+
+ return nil
+}
+
+// MaxMessageSize returns the maximum accepted message size.
+func (w *Waku) MaxMessageSize() uint32 {
+ w.settingsMu.RLock()
+ defer w.settingsMu.RUnlock()
+ return w.settings.MaxMsgSize
+}
+
+// SetMaxMessageSize sets the maximal message size allowed by this node
+func (w *Waku) SetMaxMessageSize(size uint32) error {
+ if size > MaxMessageSize {
+ return fmt.Errorf("message size too large [%d>%d]", size, MaxMessageSize)
+ }
+ w.settingsMu.Lock()
+ w.settings.MaxMsgSize = size
+ w.settingsMu.Unlock()
+ return nil
+}
+
+// LightClientMode indicates is this node is light client (does not forward any messages)
+func (w *Waku) LightClientMode() bool {
+ w.settingsMu.RLock()
+ defer w.settingsMu.RUnlock()
+ return w.settings.LightClient
+}
+
+// SetLightClientMode makes node light client (does not forward any messages)
+func (w *Waku) SetLightClientMode(v bool) {
+ w.settingsMu.Lock()
+ w.settings.LightClient = v
+ w.settingsMu.Unlock()
+}
+
+// LightClientModeConnectionRestricted indicates that connection to light client in light client mode not allowed
+func (w *Waku) LightClientModeConnectionRestricted() bool {
+ w.settingsMu.RLock()
+ defer w.settingsMu.RUnlock()
+ return w.settings.RestrictLightClientsConn
+}
+
+// RateLimiting returns RateLimits information.
+func (w *Waku) RateLimits() RateLimits {
+ if w.rateLimiter == nil {
+ return RateLimits{}
+ }
+ return RateLimits{
+ IPLimits: uint64(w.rateLimiter.limitPerSecIP),
+ PeerIDLimits: uint64(w.rateLimiter.limitPerSecPeerID),
+ }
+}
+
+// ConfirmationsEnabled returns true if message confirmations are enabled.
+func (w *Waku) ConfirmationsEnabled() bool {
+ w.settingsMu.RLock()
+ defer w.settingsMu.RUnlock()
+ return w.settings.EnableConfirmations
+}
+
+// CurrentTime returns current time.
+func (w *Waku) CurrentTime() time.Time {
+ return w.timeSource()
+}
+
+// SetTimeSource assigns a particular source of time to a waku object.
+func (w *Waku) SetTimeSource(timesource func() time.Time) {
+ w.timeSource = timesource
+}
+
+// APIs returns the RPC descriptors the Waku implementation offers
+func (w *Waku) APIs() []rpc.API {
+ return []rpc.API{
+ {
+ Namespace: ProtocolName,
+ Version: ProtocolVersionStr,
+ Service: NewPublicWakuAPI(w),
+ Public: true,
+ },
+ }
+}
+
+// Protocols returns the waku sub-protocols ran by this particular client.
+func (w *Waku) Protocols() []p2p.Protocol {
+ return []p2p.Protocol{w.protocol}
+}
+
+// RegisterMailServer registers MailServer interface.
+// MailServer will process all the incoming messages with p2pRequestCode.
+func (w *Waku) RegisterMailServer(server MailServer) {
+ w.mailServer = server
+}
+
+// SetRateLimiter registers a rate limiter.
+func (w *Waku) RegisterRateLimiter(r *PeerRateLimiter) {
+ w.rateLimiter = r
+}
+
+// SubscribeEnvelopeEvents subscribes to envelopes feed.
+// In order to prevent blocking waku producers events must be amply buffered.
+func (w *Waku) SubscribeEnvelopeEvents(events chan<- EnvelopeEvent) event.Subscription {
+ return w.envelopeFeed.Subscribe(events)
+}
+
+func (w *Waku) notifyPeersAboutPowRequirementChange(pow float64) {
+ arr := w.getPeers()
+ for _, p := range arr {
+ err := p.notifyAboutPowRequirementChange(pow)
+ if err != nil {
+ // allow one retry
+ err = p.notifyAboutPowRequirementChange(pow)
+ }
+ if err != nil {
+ w.logger.Warn("failed to notify peer about new pow requirement", zap.Binary("peer", p.ID()), zap.Error(err))
+ }
+ }
+}
+
+func (w *Waku) notifyPeersAboutBloomFilterChange(bloom []byte) {
+ arr := w.getPeers()
+ for _, p := range arr {
+ err := p.notifyAboutBloomFilterChange(bloom)
+ if err != nil {
+ // allow one retry
+ err = p.notifyAboutBloomFilterChange(bloom)
+ }
+ if err != nil {
+ w.logger.Warn("failed to notify peer about new pow requirement", zap.Binary("peer", p.ID()), zap.Error(err))
+ }
+ }
+}
+
+func (w *Waku) getPeers() []*Peer {
+ arr := make([]*Peer, len(w.peers))
+ i := 0
+ w.peerMu.Lock()
+ for p := range w.peers {
+ arr[i] = p
+ i++
+ }
+ w.peerMu.Unlock()
+ return arr
+}
+
+// getPeer retrieves peer by ID
+func (w *Waku) getPeer(peerID []byte) (*Peer, error) {
+ w.peerMu.Lock()
+ defer w.peerMu.Unlock()
+ for p := range w.peers {
+ id := p.peer.ID()
+ if bytes.Equal(peerID, id[:]) {
+ return p, nil
+ }
+ }
+ return nil, fmt.Errorf("could not find peer with ID: %x", peerID)
+}
+
+// AllowP2PMessagesFromPeer marks specific peer trusted,
+// which will allow it to send historic (expired) messages.
+func (w *Waku) AllowP2PMessagesFromPeer(peerID []byte) error {
+ p, err := w.getPeer(peerID)
+ if err != nil {
+ return err
+ }
+ p.trusted = true
+ return nil
+}
+
+// RequestHistoricMessages sends a message with p2pRequestCode to a specific peer,
+// 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),
+// which are not supposed to be forwarded any further.
+// The waku protocol is agnostic of the format and contents of envelope.
+func (w *Waku) RequestHistoricMessages(peerID []byte, envelope *Envelope) error {
+ return w.RequestHistoricMessagesWithTimeout(peerID, envelope, 0)
+}
+
+// RequestHistoricMessagesWithTimeout acts as RequestHistoricMessages but requires to pass a timeout.
+// It sends an event EventMailServerRequestExpired after the timeout.
+func (w *Waku) RequestHistoricMessagesWithTimeout(peerID []byte, envelope *Envelope, timeout time.Duration) error {
+ p, err := w.getPeer(peerID)
+ if err != nil {
+ return err
+ }
+ p.trusted = true
+
+ w.envelopeFeed.Send(EnvelopeEvent{
+ Peer: p.peer.ID(),
+ Topic: envelope.Topic,
+ Hash: envelope.Hash(),
+ Event: EventMailServerRequestSent,
+ })
+
+ err = p2p.Send(p.ws, p2pRequestCode, envelope)
+ if timeout != 0 {
+ go w.expireRequestHistoricMessages(p.peer.ID(), envelope.Hash(), timeout)
+ }
+ return err
+}
+
+func (w *Waku) SendMessagesRequest(peerID []byte, request MessagesRequest) error {
+ if err := request.Validate(); err != nil {
+ return err
+ }
+ p, err := w.getPeer(peerID)
+ if err != nil {
+ return err
+ }
+ p.trusted = true
+ if err := p2p.Send(p.ws, p2pRequestCode, request); err != nil {
+ return err
+ }
+ w.envelopeFeed.Send(EnvelopeEvent{
+ Peer: p.peer.ID(),
+ Hash: common.BytesToHash(request.ID),
+ Event: EventMailServerRequestSent,
+ })
+ return nil
+}
+
+func (w *Waku) expireRequestHistoricMessages(peer enode.ID, hash common.Hash, timeout time.Duration) {
+ timer := time.NewTimer(timeout)
+ defer timer.Stop()
+ select {
+ case <-w.quit:
+ return
+ case <-timer.C:
+ w.envelopeFeed.Send(EnvelopeEvent{
+ Peer: peer,
+ Hash: hash,
+ Event: EventMailServerRequestExpired,
+ })
+ }
+}
+
+func (w *Waku) SendHistoricMessageResponse(peerID []byte, payload []byte) error {
+ size, r, err := rlp.EncodeToReader(payload)
+ if err != nil {
+ return err
+ }
+ peer, err := w.getPeer(peerID)
+ if err != nil {
+ return err
+ }
+ return peer.ws.WriteMsg(p2p.Msg{Code: p2pRequestCompleteCode, Size: uint32(size), Payload: r})
+}
+
+// SendP2PMessage sends a peer-to-peer message to a specific peer.
+// It sends one or more envelopes in a single batch.
+func (w *Waku) SendP2PMessages(peerID []byte, envelopes ...*Envelope) error {
+ p, err := w.getPeer(peerID)
+ if err != nil {
+ return err
+ }
+ return p2p.Send(p.ws, p2pMessageCode, envelopes)
+}
+
+// SendP2PDirect sends a peer-to-peer message to a specific peer.
+// It sends one or more envelopes in a single batch.
+func (w *Waku) SendP2PDirect(peerID []byte, envelopes ...*Envelope) error {
+ peer, err := w.getPeer(peerID)
+ if err != nil {
+ return err
+ }
+ return p2p.Send(peer.ws, p2pMessageCode, envelopes)
+}
+
+// SendRawP2PDirect sends a peer-to-peer message to a specific peer.
+// It sends one or more envelopes in a single batch.
+func (w *Waku) SendRawP2PDirect(peerID []byte, envelopes ...rlp.RawValue) error {
+ peer, err := w.getPeer(peerID)
+ if err != nil {
+ return err
+ }
+ return p2p.Send(peer.ws, p2pMessageCode, envelopes)
+}
+
+// NewKeyPair generates a new cryptographic identity for the client, and injects
+// it into the known identities for message decryption. Returns ID of the new key pair.
+func (w *Waku) NewKeyPair() (string, error) {
+ key, err := crypto.GenerateKey()
+ if err != nil || !validatePrivateKey(key) {
+ key, err = crypto.GenerateKey() // retry once
+ }
+ if err != nil {
+ return "", err
+ }
+ if !validatePrivateKey(key) {
+ return "", fmt.Errorf("failed to generate valid key")
+ }
+
+ id, err := toDeterministicID(hexutil.Encode(crypto.FromECDSAPub(&key.PublicKey)), keyIDSize)
+ if err != nil {
+ return "", err
+ }
+
+ w.keyMu.Lock()
+ defer w.keyMu.Unlock()
+
+ if w.privateKeys[id] != nil {
+ return "", fmt.Errorf("failed to generate unique ID")
+ }
+ w.privateKeys[id] = key
+ return id, nil
+}
+
+// DeleteKeyPair deletes the specified key if it exists.
+func (w *Waku) DeleteKeyPair(key string) bool {
+ deterministicID, err := toDeterministicID(key, keyIDSize)
+ if err != nil {
+ return false
+ }
+
+ w.keyMu.Lock()
+ defer w.keyMu.Unlock()
+
+ if w.privateKeys[deterministicID] != nil {
+ delete(w.privateKeys, deterministicID)
+ return true
+ }
+ return false
+}
+
+// AddKeyPair imports a asymmetric private key and returns it identifier.
+func (w *Waku) AddKeyPair(key *ecdsa.PrivateKey) (string, error) {
+ id, err := makeDeterministicID(hexutil.Encode(crypto.FromECDSAPub(&key.PublicKey)), keyIDSize)
+ if err != nil {
+ return "", err
+ }
+ if w.HasKeyPair(id) {
+ return id, nil // no need to re-inject
+ }
+
+ w.keyMu.Lock()
+ w.privateKeys[id] = key
+ w.keyMu.Unlock()
+
+ return id, nil
+}
+
+// SelectKeyPair adds cryptographic identity, and makes sure
+// that it is the only private key known to the node.
+func (w *Waku) SelectKeyPair(key *ecdsa.PrivateKey) error {
+ id, err := makeDeterministicID(common.ToHex(crypto.FromECDSAPub(&key.PublicKey)), keyIDSize)
+ if err != nil {
+ return err
+ }
+
+ w.keyMu.Lock()
+ defer w.keyMu.Unlock()
+
+ w.privateKeys = make(map[string]*ecdsa.PrivateKey) // reset key store
+ w.privateKeys[id] = key
+
+ return nil
+}
+
+// DeleteKeyPairs removes all cryptographic identities known to the node
+func (w *Waku) DeleteKeyPairs() error {
+ w.keyMu.Lock()
+ defer w.keyMu.Unlock()
+
+ w.privateKeys = make(map[string]*ecdsa.PrivateKey)
+
+ return nil
+}
+
+// HasKeyPair checks if the waku node is configured with the private key
+// of the specified public pair.
+func (w *Waku) HasKeyPair(id string) bool {
+ deterministicID, err := toDeterministicID(id, keyIDSize)
+ if err != nil {
+ return false
+ }
+
+ w.keyMu.RLock()
+ defer w.keyMu.RUnlock()
+ return w.privateKeys[deterministicID] != nil
+}
+
+// GetPrivateKey retrieves the private key of the specified identity.
+func (w *Waku) GetPrivateKey(id string) (*ecdsa.PrivateKey, error) {
+ deterministicID, err := toDeterministicID(id, keyIDSize)
+ if err != nil {
+ return nil, err
+ }
+
+ w.keyMu.RLock()
+ defer w.keyMu.RUnlock()
+ key := w.privateKeys[deterministicID]
+ if key == nil {
+ return nil, fmt.Errorf("invalid id")
+ }
+ return key, nil
+}
+
+// GenerateSymKey generates a random symmetric key and stores it under id,
+// which is then returned. Will be used in the future for session key exchange.
+func (w *Waku) GenerateSymKey() (string, error) {
+ key, err := generateSecureRandomData(aesKeyLength)
+ if err != nil {
+ return "", err
+ } else if !validateDataIntegrity(key, aesKeyLength) {
+ return "", fmt.Errorf("error in GenerateSymKey: crypto/rand failed to generate random data")
+ }
+
+ id, err := GenerateRandomID()
+ if err != nil {
+ return "", fmt.Errorf("failed to generate ID: %s", err)
+ }
+
+ w.keyMu.Lock()
+ defer w.keyMu.Unlock()
+
+ if w.symKeys[id] != nil {
+ return "", fmt.Errorf("failed to generate unique ID")
+ }
+ w.symKeys[id] = key
+ return id, nil
+}
+
+// AddSymKey stores the key with a given id.
+func (w *Waku) AddSymKey(id string, key []byte) (string, error) {
+ deterministicID, err := toDeterministicID(id, keyIDSize)
+ if err != nil {
+ return "", err
+ }
+
+ w.keyMu.Lock()
+ defer w.keyMu.Unlock()
+
+ if w.symKeys[deterministicID] != nil {
+ return "", fmt.Errorf("key already exists: %v", id)
+ }
+ w.symKeys[deterministicID] = key
+ return deterministicID, nil
+}
+
+// AddSymKeyDirect stores the key, and returns its id.
+func (w *Waku) AddSymKeyDirect(key []byte) (string, error) {
+ if len(key) != aesKeyLength {
+ return "", fmt.Errorf("wrong key size: %d", len(key))
+ }
+
+ id, err := GenerateRandomID()
+ if err != nil {
+ return "", fmt.Errorf("failed to generate ID: %s", err)
+ }
+
+ w.keyMu.Lock()
+ defer w.keyMu.Unlock()
+
+ if w.symKeys[id] != nil {
+ return "", fmt.Errorf("failed to generate unique ID")
+ }
+ w.symKeys[id] = key
+ return id, nil
+}
+
+// AddSymKeyFromPassword generates the key from password, stores it, and returns its id.
+func (w *Waku) AddSymKeyFromPassword(password string) (string, error) {
+ id, err := GenerateRandomID()
+ if err != nil {
+ return "", fmt.Errorf("failed to generate ID: %s", err)
+ }
+ if w.HasSymKey(id) {
+ return "", fmt.Errorf("failed to generate unique ID")
+ }
+
+ // kdf should run no less than 0.1 seconds on an average computer,
+ // because it's an once in a session experience
+ derived := pbkdf2.Key([]byte(password), nil, 65356, aesKeyLength, sha256.New)
+ if err != nil {
+ return "", err
+ }
+
+ w.keyMu.Lock()
+ defer w.keyMu.Unlock()
+
+ // double check is necessary, because deriveKeyMaterial() is very slow
+ if w.symKeys[id] != nil {
+ return "", fmt.Errorf("critical error: failed to generate unique ID")
+ }
+ w.symKeys[id] = derived
+ return id, nil
+}
+
+// HasSymKey returns true if there is a key associated with the given id.
+// Otherwise returns false.
+func (w *Waku) HasSymKey(id string) bool {
+ w.keyMu.RLock()
+ defer w.keyMu.RUnlock()
+ return w.symKeys[id] != nil
+}
+
+// DeleteSymKey deletes the key associated with the name string if it exists.
+func (w *Waku) DeleteSymKey(id string) bool {
+ w.keyMu.Lock()
+ defer w.keyMu.Unlock()
+ if w.symKeys[id] != nil {
+ delete(w.symKeys, id)
+ return true
+ }
+ return false
+}
+
+// GetSymKey returns the symmetric key associated with the given id.
+func (w *Waku) GetSymKey(id string) ([]byte, error) {
+ w.keyMu.RLock()
+ defer w.keyMu.RUnlock()
+ if w.symKeys[id] != nil {
+ return w.symKeys[id], nil
+ }
+ return nil, fmt.Errorf("non-existent key ID")
+}
+
+// Subscribe installs a new message handler used for filtering, decrypting
+// and subsequent storing of incoming messages.
+func (w *Waku) Subscribe(f *Filter) (string, error) {
+ s, err := w.filters.Install(f)
+ if err == nil {
+ w.updateBloomFilter(f)
+ }
+ return s, err
+}
+
+// updateBloomFilter recalculates the new value of bloom filter,
+// and informs the peers if necessary.
+func (w *Waku) updateBloomFilter(f *Filter) {
+ aggregate := make([]byte, BloomFilterSize)
+ for _, t := range f.Topics {
+ top := BytesToTopic(t)
+ b := TopicToBloom(top)
+ aggregate = addBloom(aggregate, b)
+ }
+
+ if !BloomFilterMatch(w.BloomFilter(), aggregate) {
+ // existing bloom filter must be updated
+ aggregate = addBloom(w.BloomFilter(), aggregate)
+ w.SetBloomFilter(aggregate)
+ }
+}
+
+// GetFilter returns the filter by id.
+func (w *Waku) GetFilter(id string) *Filter {
+ return w.filters.Get(id)
+}
+
+// Unsubscribe removes an installed message handler.
+func (w *Waku) Unsubscribe(id string) error {
+ ok := w.filters.Uninstall(id)
+ if !ok {
+ return fmt.Errorf("Unsubscribe: Invalid ID")
+ }
+ return nil
+}
+
+// Send injects a message into the waku send queue, to be distributed in the
+// network in the coming cycles.
+func (w *Waku) Send(envelope *Envelope) error {
+ ok, err := w.add(envelope, false)
+ if err == nil && !ok {
+ return fmt.Errorf("failed to add envelope")
+ }
+ return err
+}
+
+// Start implements node.Service, starting the background data propagation thread
+// of the Waku protocol.
+func (w *Waku) Start(*p2p.Server) error {
+ go w.update()
+
+ numCPU := runtime.NumCPU()
+ for i := 0; i < numCPU; i++ {
+ go w.processQueue()
+ }
+ go w.processP2P()
+
+ return nil
+}
+
+// Stop implements node.Service, stopping the background data propagation thread
+// of the Waku protocol.
+func (w *Waku) Stop() error {
+ close(w.quit)
+ return nil
+}
+
+// HandlePeer is called by the underlying P2P layer when the waku sub-protocol
+// connection is negotiated.
+func (w *Waku) HandlePeer(peer *p2p.Peer, rw p2p.MsgReadWriter) error {
+ // Create the new peer and start tracking it
+ wakuPeer := newPeer(w, peer, rw, w.logger.Named("waku/peer"))
+
+ w.peerMu.Lock()
+ w.peers[wakuPeer] = struct{}{}
+ w.peerMu.Unlock()
+
+ defer func() {
+ w.peerMu.Lock()
+ delete(w.peers, wakuPeer)
+ w.peerMu.Unlock()
+ }()
+
+ // Run the peer handshake and state updates
+ if err := wakuPeer.handshake(); err != nil {
+ return err
+ }
+ wakuPeer.start()
+ defer wakuPeer.stop()
+
+ if w.rateLimiter != nil {
+ return w.rateLimiter.decorate(wakuPeer, rw, w.runMessageLoop)
+ }
+ return w.runMessageLoop(wakuPeer, rw)
+}
+
+// sendConfirmation sends messageResponseCode and batchAcknowledgedCode messages.
+func (w *Waku) sendConfirmation(rw p2p.MsgReadWriter, data []byte, envelopeErrors []EnvelopeError) (err error) {
+ batchHash := crypto.Keccak256Hash(data)
+ err = p2p.Send(rw, messageResponseCode, NewMessagesResponse(batchHash, envelopeErrors))
+ err = p2p.Send(rw, batchAcknowledgedCode, batchHash) // DEPRECATED
+ return
+}
+
+// runMessageLoop reads and processes inbound messages directly to merge into client-global state.
+func (w *Waku) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error {
+ logger := w.logger.Named("runMessageLoop")
+ peerID := p.peer.ID()
+
+ for {
+ // fetch the next packet
+ packet, err := rw.ReadMsg()
+ if err != nil {
+ logger.Info("failed to read a message", zap.Binary("peer", peerID[:]), zap.Error(err))
+ return err
+ }
+
+ if packet.Size > w.MaxMessageSize() {
+ logger.Warn("oversize message received", zap.Binary("peer", peerID[:]), zap.Uint32("size", packet.Size))
+ return errors.New("oversize message received")
+ }
+
+ switch packet.Code {
+ case messagesCode:
+ if err := w.handleMessagesCode(p, rw, packet, logger); err != nil {
+ logger.Warn("failed to handle messagesCode message, peer will be disconnected", zap.Binary("peer", peerID[:]), zap.Error(err))
+ return err
+ }
+ case messageResponseCode:
+ if err := w.handleMessageResponseCode(p, packet, logger); err != nil {
+ logger.Warn("failed to handle messageResponseCode message, peer will be disconnected", zap.Binary("peer", peerID[:]), zap.Error(err))
+ return err
+ }
+ case batchAcknowledgedCode:
+ if err := w.handleBatchAcknowledgeCode(p, packet, logger); err != nil {
+
+ }
+ case powRequirementCode:
+ if err := w.handlePowRequirementCode(p, packet, logger); err != nil {
+ logger.Warn("failed to handle powRequirementCode message, peer will be disconnected", zap.Binary("peer", peerID[:]), zap.Error(err))
+ return err
+ }
+ case bloomFilterExCode:
+ if err := w.handleBloomFilterExCode(p, packet, logger); err != nil {
+ logger.Warn("failed to decode bloom filter exchange message, peer will be disconnected", zap.Binary("peer", peerID[:]), zap.Error(err))
+ return err
+ }
+ case p2pMessageCode:
+ if err := w.handleP2PMessageCode(p, packet, logger); err != nil {
+ logger.Warn("failed to decode direct message, peer will be disconnected", zap.Binary("peer", peerID[:]), zap.Error(err))
+ return err
+ }
+ case p2pRequestCode:
+ if err := w.handleP2PRequestCode(p, packet, logger); err != nil {
+ logger.Warn("failed to decode p2p request message, peer will be disconnected", zap.Binary("peer", peerID[:]), zap.Error(err))
+ return err
+ }
+ case p2pRequestCompleteCode:
+ if err := w.handleP2PRequestCompleteCode(p, packet, logger); err != nil {
+ logger.Warn("failed to decode p2p request complete message, peer will be disconnected", zap.Binary("peer", peerID[:]), zap.Error(err))
+ return err
+ }
+ default:
+ // New message types might be implemented in the future versions of Waku.
+ // For forward compatibility, just ignore.
+ logger.Debug("ignored packet with message code", zap.Uint64("code", packet.Code))
+ }
+
+ _ = packet.Discard()
+ }
+}
+
+func (w *Waku) handleMessagesCode(p *Peer, rw p2p.MsgReadWriter, packet p2p.Msg, logger *zap.Logger) error {
+ peerID := p.peer.ID()
+
+ // decode the contained envelopes
+ data, err := ioutil.ReadAll(packet.Payload)
+ if err != nil {
+ envelopesRejectedCounter.WithLabelValues("failed_read").Inc()
+ return fmt.Errorf("failed to read packet payload: %w", err)
+ }
+
+ var envelopes []*Envelope
+ if err := rlp.DecodeBytes(data, &envelopes); err != nil {
+ envelopesRejectedCounter.WithLabelValues("invalid_data").Inc()
+ return fmt.Errorf("invalid payload: %w", err)
+ }
+
+ envelopeErrors := make([]EnvelopeError, 0)
+ trouble := false
+ for _, env := range envelopes {
+ cached, err := w.add(env, w.LightClientMode())
+ if err != nil {
+ _, isTimeSyncError := err.(TimeSyncError)
+ if !isTimeSyncError {
+ trouble = true
+ logger.Info("invalid envelope received", zap.Binary("peer", peerID[:]), zap.Error(err))
+ }
+ envelopeErrors = append(envelopeErrors, ErrorToEnvelopeError(env.Hash(), err))
+ } else if cached {
+ p.mark(env)
+ }
+
+ w.envelopeFeed.Send(EnvelopeEvent{
+ Event: EventEnvelopeReceived,
+ Topic: env.Topic,
+ Hash: env.Hash(),
+ Peer: p.peer.ID(),
+ })
+ envelopesValidatedCounter.Inc()
+ }
+
+ if w.ConfirmationsEnabled() {
+ go w.sendConfirmation(rw, data, envelopeErrors)
+ }
+
+ if trouble {
+ return errors.New("received invalid envelope")
+ }
+ return nil
+}
+
+func (w *Waku) handlePowRequirementCode(p *Peer, packet p2p.Msg, logger *zap.Logger) error {
+ s := rlp.NewStream(packet.Payload, uint64(packet.Size))
+ i, err := s.Uint()
+ if err != nil {
+ envelopesRejectedCounter.WithLabelValues("invalid_pow_req").Inc()
+ return fmt.Errorf("invalid powRequirementCode message: %w", err)
+ }
+ f := math.Float64frombits(i)
+ if math.IsInf(f, 0) || math.IsNaN(f) || f < 0.0 {
+ envelopesRejectedCounter.WithLabelValues("invalid_pow_req").Inc()
+ return errors.New("invalid value in powRequirementCode message")
+ }
+ p.powRequirement = f
+ return nil
+}
+
+func (w *Waku) handleBloomFilterExCode(p *Peer, packet p2p.Msg, logger *zap.Logger) error {
+ var bloom []byte
+ err := packet.Decode(&bloom)
+ if err == nil && len(bloom) != BloomFilterSize {
+ err = fmt.Errorf("wrong bloom filter size %d", len(bloom))
+ }
+ if err != nil {
+ envelopesRejectedCounter.WithLabelValues("invalid_bloom").Inc()
+ return errors.New("invalid bloom filter exchange message")
+ }
+
+ p.setBloomFilter(bloom)
+ return nil
+}
+
+func (w *Waku) handleP2PMessageCode(p *Peer, packet p2p.Msg, logger *zap.Logger) error {
+ // peer-to-peer message, sent directly to peer bypassing PoW checks, etc.
+ // this message is not supposed to be forwarded to other peers, and
+ // therefore might not satisfy the PoW, expiry and other requirements.
+ // these messages are only accepted from the trusted peer.
+ if !p.trusted {
+ return nil
+ }
+
+ var (
+ envelopes []*Envelope
+ err error
+ )
+
+ if err = packet.Decode(&envelopes); err != nil {
+ return fmt.Errorf("invalid direct message payload: %w", err)
+ }
+
+ for _, envelope := range envelopes {
+ w.postP2P(envelope)
+ }
+ return nil
+}
+
+func (w *Waku) handleP2PRequestCode(p *Peer, packet p2p.Msg, logger *zap.Logger) error {
+ peerID := p.peer.ID()
+
+ // Must be processed if mail server is implemented. Otherwise ignore.
+ if w.mailServer == nil {
+ return nil
+ }
+
+ // Read all data as we will try to decode it possibly twice.
+ data, err := ioutil.ReadAll(packet.Payload)
+ if err != nil {
+ return fmt.Errorf("invalid p2p request messages: %w", err)
+ }
+ r := bytes.NewReader(data)
+ packet.Payload = r
+
+ var requestDeprecated Envelope
+ errDepReq := packet.Decode(&requestDeprecated)
+ if errDepReq == nil {
+ w.mailServer.DeliverMail(p.ID(), &requestDeprecated)
+ return nil
+ } else {
+ logger.Info("failed to decode p2p request message (deprecated)", zap.Binary("peer", peerID[:]), zap.Error(errDepReq))
+ }
+
+ // As we failed to decode the request, let's set the offset
+ // to the beginning and try decode it again.
+ if _, err := r.Seek(0, io.SeekStart); err != nil {
+ return fmt.Errorf("invalid p2p request message: %w", err)
+ }
+
+ var request MessagesRequest
+ errReq := packet.Decode(&request)
+ if errReq == nil {
+ w.mailServer.Deliver(p.ID(), request)
+ return nil
+ } else {
+ logger.Info("failed to decode p2p request message", zap.Binary("peer", peerID[:]), zap.Error(errDepReq))
+ }
+
+ return errors.New("invalid p2p request message")
+}
+
+func (w *Waku) handleP2PRequestCompleteCode(p *Peer, packet p2p.Msg, logger *zap.Logger) error {
+ if !p.trusted {
+ return nil
+ }
+
+ var payload []byte
+ if err := packet.Decode(&payload); err != nil {
+ return fmt.Errorf("invalid p2p request complete message: %w", err)
+ }
+
+ event, err := CreateMailServerEvent(p.peer.ID(), payload)
+ if err != nil {
+ return fmt.Errorf("invalid p2p request complete payload: %w", err)
+ }
+
+ w.postP2P(*event)
+ return nil
+}
+
+func (w *Waku) handleMessageResponseCode(p *Peer, packet p2p.Msg, logger *zap.Logger) error {
+ var resp MultiVersionResponse
+ if err := packet.Decode(&resp); err != nil {
+ envelopesRejectedCounter.WithLabelValues("failed_read").Inc()
+ return fmt.Errorf("invalid response message: %w", err)
+ }
+ if resp.Version != 1 {
+ logger.Info("received unsupported version of MultiVersionResponse for messageResponseCode packet", zap.Uint("version", resp.Version))
+ return nil
+ }
+
+ response, err := resp.DecodeResponse1()
+ if err != nil {
+ envelopesRejectedCounter.WithLabelValues("invalid_data").Inc()
+ return fmt.Errorf("failed to decode response message: %w", err)
+ }
+
+ w.envelopeFeed.Send(EnvelopeEvent{
+ Batch: response.Hash,
+ Event: EventBatchAcknowledged,
+ Peer: p.peer.ID(),
+ Data: response.Errors,
+ })
+
+ return nil
+}
+
+func (w *Waku) handleBatchAcknowledgeCode(p *Peer, packet p2p.Msg, logger *zap.Logger) error {
+ var batchHash common.Hash
+ if err := packet.Decode(&batchHash); err != nil {
+ return fmt.Errorf("invalid batch ack message: %w", err)
+ }
+ w.envelopeFeed.Send(EnvelopeEvent{
+ Batch: batchHash,
+ Event: EventBatchAcknowledged,
+ Peer: p.peer.ID(),
+ })
+ return nil
+}
+
+// add inserts a new envelope into the message pool to be distributed within the
+// waku network. It also inserts the envelope into the expiration pool at the
+// appropriate time-stamp. In case of error, connection should be dropped.
+// param isP2P indicates whether the message is peer-to-peer (should not be forwarded).
+func (w *Waku) add(envelope *Envelope, isP2P bool) (bool, error) {
+ now := uint32(w.timeSource().Unix())
+ sent := envelope.Expiry - envelope.TTL
+
+ envelopesReceivedCounter.Inc()
+ if sent > now {
+ if sent-DefaultSyncAllowance > now {
+ envelopesCacheFailedCounter.WithLabelValues("in_future").Inc()
+ log.Warn("envelope created in the future", "hash", envelope.Hash())
+ return false, TimeSyncError(errors.New("envelope from future"))
+ }
+ // recalculate PoW, adjusted for the time difference, plus one second for latency
+ envelope.calculatePoW(sent - now + 1)
+ }
+
+ if envelope.Expiry < now {
+ if envelope.Expiry+DefaultSyncAllowance*2 < now {
+ envelopesCacheFailedCounter.WithLabelValues("very_old").Inc()
+ log.Warn("very old envelope", "hash", envelope.Hash())
+ return false, TimeSyncError(errors.New("very old envelope"))
+ }
+ log.Debug("expired envelope dropped", "hash", envelope.Hash().Hex())
+ envelopesCacheFailedCounter.WithLabelValues("expired").Inc()
+ return false, nil // drop envelope without error
+ }
+
+ if uint32(envelope.size()) > w.MaxMessageSize() {
+ envelopesCacheFailedCounter.WithLabelValues("oversized").Inc()
+ return false, fmt.Errorf("huge messages are not allowed [%x]", envelope.Hash())
+ }
+
+ if envelope.PoW() < w.MinPow() {
+ // maybe the value was recently changed, and the peers did not adjust yet.
+ // in this case the previous value is retrieved by MinPowTolerance()
+ // for a short period of peer synchronization.
+ if envelope.PoW() < w.MinPowTolerance() {
+ envelopesCacheFailedCounter.WithLabelValues("low_pow").Inc()
+ return false, fmt.Errorf("envelope with low PoW received: PoW=%f, hash=[%v]", envelope.PoW(), envelope.Hash().Hex())
+ }
+ }
+
+ if !BloomFilterMatch(w.BloomFilter(), envelope.Bloom()) {
+ // maybe the value was recently changed, and the peers did not adjust yet.
+ // in this case the previous value is retrieved by BloomFilterTolerance()
+ // for a short period of peer synchronization.
+ if !BloomFilterMatch(w.BloomFilterTolerance(), envelope.Bloom()) {
+ envelopesCacheFailedCounter.WithLabelValues("no_bloom_match").Inc()
+ return false, fmt.Errorf("envelope does not match bloom filter, hash=[%v], bloom: \n%x \n%x \n%x",
+ envelope.Hash().Hex(), w.BloomFilter(), envelope.Bloom(), envelope.Topic)
+ }
+ }
+
+ hash := envelope.Hash()
+
+ w.poolMu.Lock()
+ _, alreadyCached := w.envelopes[hash]
+ if !alreadyCached {
+ w.envelopes[hash] = envelope
+ if w.expirations[envelope.Expiry] == nil {
+ w.expirations[envelope.Expiry] = mapset.NewThreadUnsafeSet()
+ }
+ if !w.expirations[envelope.Expiry].Contains(hash) {
+ w.expirations[envelope.Expiry].Add(hash)
+ }
+ }
+ w.poolMu.Unlock()
+
+ if alreadyCached {
+ log.Trace("w envelope already cached", "hash", envelope.Hash().Hex())
+ envelopesCachedCounter.WithLabelValues("hit").Inc()
+ } else {
+ log.Trace("cached w envelope", "hash", envelope.Hash().Hex())
+ envelopesCachedCounter.WithLabelValues("miss").Inc()
+ envelopesSizeMeter.Observe(float64(envelope.size()))
+ w.postEvent(envelope, isP2P) // notify the local node about the new message
+ if w.mailServer != nil {
+ w.mailServer.Archive(envelope)
+ w.envelopeFeed.Send(EnvelopeEvent{
+ Topic: envelope.Topic,
+ Hash: envelope.Hash(),
+ Event: EventMailServerEnvelopeArchived,
+ })
+ }
+ }
+ return true, nil
+}
+
+func (w *Waku) postP2P(event interface{}) {
+ w.p2pMsgQueue <- event
+}
+
+// postEvent queues the message for further processing.
+func (w *Waku) postEvent(envelope *Envelope, isP2P bool) {
+ if isP2P {
+ w.postP2P(envelope)
+ } else {
+ w.msgQueue <- envelope
+ }
+}
+
+// processQueue delivers the messages to the watchers during the lifetime of the waku node.
+func (w *Waku) processQueue() {
+ for {
+ select {
+ case <-w.quit:
+ return
+ case e := <-w.msgQueue:
+ w.filters.NotifyWatchers(e, false)
+ w.envelopeFeed.Send(EnvelopeEvent{
+ Topic: e.Topic,
+ Hash: e.Hash(),
+ Event: EventEnvelopeAvailable,
+ })
+ }
+ }
+}
+
+func (w *Waku) processP2P() {
+ for {
+ select {
+ case <-w.quit:
+ return
+ case e := <-w.p2pMsgQueue:
+ switch event := e.(type) {
+ case *Envelope:
+ w.filters.NotifyWatchers(event, true)
+ w.envelopeFeed.Send(EnvelopeEvent{
+ Topic: event.Topic,
+ Hash: event.Hash(),
+ Event: EventEnvelopeAvailable,
+ })
+ case EnvelopeEvent:
+ w.envelopeFeed.Send(event)
+ }
+ }
+ }
+}
+
+// update loops until the lifetime of the waku node, updating its internal
+// state by expiring stale messages from the pool.
+func (w *Waku) update() {
+ // Start a ticker to check for expirations
+ expire := time.NewTicker(expirationCycle)
+
+ // Repeat updates until termination is requested
+ for {
+ select {
+ case <-expire.C:
+ w.expire()
+
+ case <-w.quit:
+ return
+ }
+ }
+}
+
+// expire iterates over all the expiration timestamps, removing all stale
+// messages from the pools.
+func (w *Waku) expire() {
+ w.poolMu.Lock()
+ defer w.poolMu.Unlock()
+
+ now := uint32(w.timeSource().Unix())
+ for expiry, hashSet := range w.expirations {
+ if expiry < now {
+ // Dump all expired messages and remove timestamp
+ hashSet.Each(func(v interface{}) bool {
+ delete(w.envelopes, v.(common.Hash))
+ envelopesCachedCounter.WithLabelValues("clear").Inc()
+ w.envelopeFeed.Send(EnvelopeEvent{
+ Hash: v.(common.Hash),
+ Event: EventEnvelopeExpired,
+ })
+ return false
+ })
+ w.expirations[expiry].Clear()
+ delete(w.expirations, expiry)
+ }
+ }
+}
+
+// Envelopes retrieves all the messages currently pooled by the node.
+func (w *Waku) Envelopes() []*Envelope {
+ w.poolMu.RLock()
+ defer w.poolMu.RUnlock()
+
+ all := make([]*Envelope, 0, len(w.envelopes))
+ for _, envelope := range w.envelopes {
+ all = append(all, envelope)
+ }
+ return all
+}
+
+// GetEnvelope retrieves an envelope from the message queue by its hash.
+// It returns nil if the envelope can not be found.
+func (w *Waku) GetEnvelope(hash common.Hash) *Envelope {
+ w.poolMu.RLock()
+ defer w.poolMu.RUnlock()
+ return w.envelopes[hash]
+}
+
+// isEnvelopeCached checks if envelope with specific hash has already been received and cached.
+func (w *Waku) isEnvelopeCached(hash common.Hash) bool {
+ w.poolMu.Lock()
+ defer w.poolMu.Unlock()
+
+ _, exist := w.envelopes[hash]
+ return exist
+}
+
+// ValidatePublicKey checks the format of the given public key.
+func ValidatePublicKey(k *ecdsa.PublicKey) bool {
+ return k != nil && k.X != nil && k.Y != nil && k.X.Sign() != 0 && k.Y.Sign() != 0
+}
+
+// validatePrivateKey checks the format of the given private key.
+func validatePrivateKey(k *ecdsa.PrivateKey) bool {
+ if k == nil || k.D == nil || k.D.Sign() == 0 {
+ return false
+ }
+ return ValidatePublicKey(&k.PublicKey)
+}
+
+// validateDataIntegrity returns false if the data have the wrong or contains all zeros,
+// which is the simplest and the most common bug.
+func validateDataIntegrity(k []byte, expectedSize int) bool {
+ if len(k) != expectedSize {
+ return false
+ }
+ if expectedSize > 3 && containsOnlyZeros(k) {
+ return false
+ }
+ return true
+}
+
+// containsOnlyZeros checks if the data contain only zeros.
+func containsOnlyZeros(data []byte) bool {
+ for _, b := range data {
+ if b != 0 {
+ return false
+ }
+ }
+ return true
+}
+
+// bytesToUintLittleEndian converts the slice to 64-bit unsigned integer.
+func bytesToUintLittleEndian(b []byte) (res uint64) {
+ mul := uint64(1)
+ for i := 0; i < len(b); i++ {
+ res += uint64(b[i]) * mul
+ mul *= 256
+ }
+ return res
+}
+
+// BytesToUintBigEndian converts the slice to 64-bit unsigned integer.
+func BytesToUintBigEndian(b []byte) (res uint64) {
+ for i := 0; i < len(b); i++ {
+ res *= 256
+ res += uint64(b[i])
+ }
+ return res
+}
+
+// GenerateRandomID generates a random string, which is then returned to be used as a key id
+func GenerateRandomID() (id string, err error) {
+ buf, err := generateSecureRandomData(keyIDSize)
+ if err != nil {
+ return "", err
+ }
+ if !validateDataIntegrity(buf, keyIDSize) {
+ return "", fmt.Errorf("error in generateRandomID: crypto/rand failed to generate random data")
+ }
+ id = common.Bytes2Hex(buf)
+ return id, err
+}
+
+// makeDeterministicID generates a deterministic ID, based on a given input
+func makeDeterministicID(input string, keyLen int) (id string, err error) {
+ buf := pbkdf2.Key([]byte(input), nil, 4096, keyLen, sha256.New)
+ if !validateDataIntegrity(buf, keyIDSize) {
+ return "", fmt.Errorf("error in GenerateDeterministicID: failed to generate key")
+ }
+ id = common.Bytes2Hex(buf)
+ return id, err
+}
+
+// toDeterministicID reviews incoming id, and transforms it to format
+// expected internally be private key store. Originally, public keys
+// were used as keys, now random keys are being used. And in order to
+// make it easier to consume, we now allow both random IDs and public
+// keys to be passed.
+func toDeterministicID(id string, expectedLen int) (string, error) {
+ if len(id) != (expectedLen * 2) { // we received hex key, so number of chars in id is doubled
+ var err error
+ id, err = makeDeterministicID(id, expectedLen)
+ if err != nil {
+ return "", err
+ }
+ }
+
+ return id, nil
+}
+
+func isFullNode(bloom []byte) bool {
+ if bloom == nil {
+ return true
+ }
+ for _, b := range bloom {
+ if b != 255 {
+ return false
+ }
+ }
+ return true
+}
+
+func BloomFilterMatch(filter, sample []byte) bool {
+ if filter == nil {
+ return true
+ }
+
+ for i := 0; i < BloomFilterSize; i++ {
+ f := filter[i]
+ s := sample[i]
+ if (f | s) != f {
+ return false
+ }
+ }
+
+ return true
+}
+
+func addBloom(a, b []byte) []byte {
+ c := make([]byte, BloomFilterSize)
+ for i := 0; i < BloomFilterSize; i++ {
+ c[i] = a[i] | b[i]
+ }
+ return c
+}
diff --git a/vendor/github.com/status-im/status-go/whisper/v6/doc.go b/vendor/github.com/status-im/status-go/whisper/v6/doc.go
index 12d39ab0b..fdee9d708 100644
--- a/vendor/github.com/status-im/status-go/whisper/v6/doc.go
+++ b/vendor/github.com/status-im/status-go/whisper/v6/doc.go
@@ -105,10 +105,9 @@ const (
// in order to bypass the expiry checks.
type MailServer interface {
Archive(env *Envelope)
- // DEPRECATED
- DeliverMail(whisperPeer *Peer, request *Envelope)
- Deliver(whisperPeer *Peer, request MessagesRequest)
- SyncMail(*Peer, SyncMailRequest) error
+ DeliverMail(peerID []byte, req *Envelope) // DEPRECATED; user Deliver instead
+ Deliver(peerID []byte, req MessagesRequest)
+ SyncMail(peerID []byte, req SyncMailRequest) error
}
// MessagesRequest contains details of a request of historic messages.
diff --git a/vendor/github.com/status-im/status-go/whisper/v6/metrics.go b/vendor/github.com/status-im/status-go/whisper/v6/metrics.go
index 6ffa436fc..09b3af10f 100644
--- a/vendor/github.com/status-im/status-go/whisper/v6/metrics.go
+++ b/vendor/github.com/status-im/status-go/whisper/v6/metrics.go
@@ -6,37 +6,37 @@ import (
var (
envelopesReceivedCounter = prom.NewCounter(prom.CounterOpts{
- Name: "waku_envelopes_received_total",
+ Name: "whisper_envelopes_received_total",
Help: "Number of envelopes received.",
})
envelopesValidatedCounter = prom.NewCounter(prom.CounterOpts{
- Name: "waku_envelopes_validated_total",
+ Name: "whisper_envelopes_validated_total",
Help: "Number of envelopes processed successfully.",
})
envelopesRejectedCounter = prom.NewCounterVec(prom.CounterOpts{
- Name: "waku_envelopes_rejected_total",
+ Name: "whisper_envelopes_rejected_total",
Help: "Number of envelopes rejected.",
}, []string{"reason"})
envelopesCacheFailedCounter = prom.NewCounterVec(prom.CounterOpts{
- Name: "waku_envelopes_cache_failures_total",
+ Name: "whisper_envelopes_cache_failures_total",
Help: "Number of envelopes which failed to be cached.",
}, []string{"type"})
envelopesCachedCounter = prom.NewCounterVec(prom.CounterOpts{
- Name: "waku_envelopes_cached_total",
+ Name: "whisper_envelopes_cached_total",
Help: "Number of envelopes cached.",
}, []string{"cache"})
envelopesSizeMeter = prom.NewHistogram(prom.HistogramOpts{
- Name: "waku_envelopes_size_bytes",
+ Name: "whisper_envelopes_size_bytes",
Help: "Size of processed Waku envelopes in bytes.",
Buckets: prom.ExponentialBuckets(256, 4, 10),
})
// rate limiter metrics
rateLimitsProcessed = prom.NewCounter(prom.CounterOpts{
- Name: "waku_rate_limits_processed_total",
+ Name: "whisper_rate_limits_processed_total",
Help: "Number of packets Waku rate limiter processed.",
})
rateLimitsExceeded = prom.NewCounterVec(prom.CounterOpts{
- Name: "waku_rate_limits_exceeded_total",
+ Name: "whisper_rate_limits_exceeded_total",
Help: "Number of times the Waku rate limits were exceeded",
}, []string{"type"})
)
diff --git a/vendor/github.com/status-im/status-go/whisper/v6/whisper.go b/vendor/github.com/status-im/status-go/whisper/v6/whisper.go
index cff9dcf54..693fede2d 100644
--- a/vendor/github.com/status-im/status-go/whisper/v6/whisper.go
+++ b/vendor/github.com/status-im/status-go/whisper/v6/whisper.go
@@ -104,7 +104,7 @@ type Whisper struct {
statsMu sync.Mutex // guard stats
stats Statistics // Statistics of whisper node
- mailServer MailServer // MailServer interface
+ mailServer MailServer
rateLimiter *PeerRateLimiter
@@ -264,7 +264,7 @@ func (whisper *Whisper) GetCurrentTime() time.Time {
// RegisterServer registers MailServer interface.
// MailServer will process all the incoming messages with p2pRequestCode.
-func (whisper *Whisper) RegisterServer(server MailServer) {
+func (whisper *Whisper) RegisterMailServer(server MailServer) {
whisper.mailServer = server
}
@@ -502,12 +502,15 @@ func (whisper *Whisper) expireRequestHistoricMessages(peer enode.ID, hash common
}
}
-func (whisper *Whisper) SendHistoricMessageResponse(peer *Peer, payload []byte) error {
+func (whisper *Whisper) SendHistoricMessageResponse(peerID []byte, payload []byte) error {
size, r, err := rlp.EncodeToReader(payload)
if err != nil {
return err
}
-
+ peer, err := whisper.getPeer(peerID)
+ if err != nil {
+ return err
+ }
return peer.ws.WriteMsg(p2p.Msg{Code: p2pRequestCompleteCode, Size: uint32(size), Payload: r})
}
@@ -530,29 +533,37 @@ func (whisper *Whisper) SyncMessages(peerID []byte, req SyncMailRequest) error {
}
// SendSyncResponse sends a response to a Mail Server with a slice of envelopes.
-func (whisper *Whisper) SendSyncResponse(p *Peer, data SyncResponse) error {
- return p2p.Send(p.ws, p2pSyncResponseCode, data)
+func (whisper *Whisper) SendSyncResponse(peerID []byte, data SyncResponse) error {
+ peer, err := whisper.getPeer(peerID)
+ if err != nil {
+ return err
+ }
+ return p2p.Send(peer.ws, p2pSyncResponseCode, data)
}
// SendRawSyncResponse sends a response to a Mail Server with a slice of envelopes.
-func (whisper *Whisper) SendRawSyncResponse(p *Peer, data RawSyncResponse) error {
- return p2p.Send(p.ws, p2pSyncResponseCode, data)
+func (whisper *Whisper) SendRawSyncResponse(peerID []byte, data RawSyncResponse) error {
+ peer, err := whisper.getPeer(peerID)
+ if err != nil {
+ return err
+ }
+ return p2p.Send(peer.ws, p2pSyncResponseCode, data)
}
// SendP2PMessage sends a peer-to-peer message to a specific peer.
func (whisper *Whisper) SendP2PMessage(peerID []byte, envelopes ...*Envelope) error {
- p, err := whisper.getPeer(peerID)
- if err != nil {
- return err
- }
- return whisper.SendP2PDirect(p, envelopes...)
+ return whisper.SendP2PDirect(peerID, envelopes...)
}
// SendP2PDirect sends a peer-to-peer message to a specific peer.
// If only a single envelope is given, data is sent as a single object
// rather than a slice. This is important to keep this method backward compatible
// as it used to send only single envelopes.
-func (whisper *Whisper) SendP2PDirect(peer *Peer, envelopes ...*Envelope) error {
+func (whisper *Whisper) SendP2PDirect(peerID []byte, envelopes ...*Envelope) error {
+ peer, err := whisper.getPeer(peerID)
+ if err != nil {
+ return err
+ }
if len(envelopes) == 1 {
return p2p.Send(peer.ws, p2pMessageCode, envelopes[0])
}
@@ -563,7 +574,11 @@ func (whisper *Whisper) SendP2PDirect(peer *Peer, envelopes ...*Envelope) error
// If only a single envelope is given, data is sent as a single object
// rather than a slice. This is important to keep this method backward compatible
// as it used to send only single envelopes.
-func (whisper *Whisper) SendRawP2PDirect(peer *Peer, envelopes ...rlp.RawValue) error {
+func (whisper *Whisper) SendRawP2PDirect(peerID []byte, envelopes ...rlp.RawValue) error {
+ peer, err := whisper.getPeer(peerID)
+ if err != nil {
+ return err
+ }
if len(envelopes) == 1 {
return p2p.Send(peer.ws, p2pMessageCode, envelopes[0])
}
@@ -1099,13 +1114,13 @@ func (whisper *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error {
return fmt.Errorf("sync mail request was invalid: %v", err)
}
- if err := whisper.mailServer.SyncMail(p, request); err != nil {
+ if err := whisper.mailServer.SyncMail(p.ID(), request); err != nil {
log.Error(
"failed to sync envelopes",
"peer", p.peer.ID().String(),
)
_ = whisper.SendSyncResponse(
- p,
+ p.ID(),
SyncResponse{Error: err.Error()},
)
return err
@@ -1157,7 +1172,7 @@ func (whisper *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error {
var requestDeprecated Envelope
errDepReq := packet.Decode(&requestDeprecated)
if errDepReq == nil {
- whisper.mailServer.DeliverMail(p, &requestDeprecated)
+ whisper.mailServer.DeliverMail(p.ID(), &requestDeprecated)
continue
} else {
log.Info("failed to decode p2p request message (deprecated)", "peer", p.peer.ID(), "err", errDepReq)
@@ -1172,7 +1187,7 @@ func (whisper *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error {
var request MessagesRequest
errReq := packet.Decode(&request)
if errReq == nil {
- whisper.mailServer.Deliver(p, request)
+ whisper.mailServer.Deliver(p.ID(), request)
continue
} else {
log.Info("failed to decode p2p request message", "peer", p.peer.ID(), "err", errReq)
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 6f4a00773..e2244a46d 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -3,7 +3,7 @@ github.com/BurntSushi/toml
# github.com/allegro/bigcache v1.2.0
github.com/allegro/bigcache
github.com/allegro/bigcache/queue
-# github.com/aristanetworks/goarista v0.0.0-20190502180301-283422fc1708
+# github.com/aristanetworks/goarista v0.0.0-20191106175434-873d404c7f40
github.com/aristanetworks/goarista/monotime
# github.com/beevik/ntp v0.2.0
github.com/beevik/ntp
@@ -28,7 +28,7 @@ github.com/davecgh/go-spew/spew
github.com/deckarep/golang-set
# github.com/edsrzf/mmap-go v1.0.0
github.com/edsrzf/mmap-go
-# github.com/elastic/gosigar v0.10.4
+# github.com/elastic/gosigar v0.10.5
github.com/elastic/gosigar
github.com/elastic/gosigar/sys/windows
# github.com/ethereum/go-ethereum v1.9.5 => github.com/status-im/go-ethereum v1.9.5-status.7
@@ -167,7 +167,7 @@ github.com/ipfs/go-log/tracer/wire
github.com/ipfs/go-log/writer
# github.com/jackpal/gateway v1.0.5
github.com/jackpal/gateway
-# github.com/jackpal/go-nat-pmp v1.0.1
+# github.com/jackpal/go-nat-pmp v1.0.2
github.com/jackpal/go-nat-pmp
# github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2
github.com/jbenet/go-temp-err-catcher
@@ -343,7 +343,7 @@ github.com/prometheus/procfs/internal/util
github.com/prometheus/tsdb/fileutil
# github.com/rjeczalik/notify v0.9.2
github.com/rjeczalik/notify
-# github.com/rs/cors v1.6.0
+# github.com/rs/cors v1.7.0
github.com/rs/cors
# github.com/russolsen/transit v0.0.0-20180705123435-0794b4c4505a
github.com/russolsen/transit
@@ -397,6 +397,8 @@ github.com/status-im/status-go/protocol/transport/whisper
github.com/status-im/status-go/protocol/transport/whisper/migrations
github.com/status-im/status-go/protocol/v1
github.com/status-im/status-go/protocol/zaputil
+# github.com/status-im/status-go/waku v1.0.0 => ./waku
+github.com/status-im/status-go/waku
# github.com/status-im/status-go/whisper/v6 v6.0.1 => ./whisper
github.com/status-im/status-go/whisper/v6
# github.com/status-im/tcp-shaker v0.0.0-20191114194237-215893130501
@@ -487,7 +489,7 @@ go.uber.org/zap/internal/bufferpool
go.uber.org/zap/internal/color
go.uber.org/zap/internal/exit
go.uber.org/zap/zapcore
-# golang.org/x/crypto v0.0.0-20191119213627-4f8c1d86b1ba
+# golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c
golang.org/x/crypto/blake2s
golang.org/x/crypto/curve25519
golang.org/x/crypto/ed25519
diff --git a/waku/api.go b/waku/api.go
index ef49fe1ce..73712bf7a 100644
--- a/waku/api.go
+++ b/waku/api.go
@@ -26,10 +26,9 @@ import (
"sync"
"time"
- "github.com/prometheus/common/log"
-
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/rpc"
)
diff --git a/waku/doc.go b/waku/doc.go
index 03dfd8e5c..f31ccd76e 100644
--- a/waku/doc.go
+++ b/waku/doc.go
@@ -89,8 +89,8 @@ const (
// in order to bypass the expiry checks.
type MailServer interface {
Archive(env *Envelope)
- DeliverMail(wakuPeer *Peer, request *Envelope) // DEPRECATED
- Deliver(wakuPeer *Peer, request MessagesRequest)
+ DeliverMail(peerID []byte, request *Envelope) // DEPRECATED; use Deliver()
+ Deliver(peerID []byte, request MessagesRequest)
}
// MessagesRequest contains details of a request of historic messages.
diff --git a/waku/message.go b/waku/message.go
index 91848b4a6..b35953dea 100644
--- a/waku/message.go
+++ b/waku/message.go
@@ -29,11 +29,10 @@ import (
"strconv"
"time"
- "github.com/prometheus/common/log"
-
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/ecies"
+ "github.com/ethereum/go-ethereum/log"
)
// MessageParams specifies the exact way a message should be wrapped
diff --git a/waku/waku.go b/waku/waku.go
index 98ad566ed..fe68e660d 100644
--- a/waku/waku.go
+++ b/waku/waku.go
@@ -87,7 +87,7 @@ type Waku struct {
settings settings // Holds configuration settings that can be dynamically changed
settingsMu sync.RWMutex // Mutex to sync the settings access
- mailServer MailServer // MailServer interface
+ mailServer MailServer
rateLimiter *PeerRateLimiter
@@ -480,11 +480,15 @@ func (w *Waku) expireRequestHistoricMessages(peer enode.ID, hash common.Hash, ti
}
}
-func (w *Waku) SendHistoricMessageResponse(peer *Peer, payload []byte) error {
+func (w *Waku) SendHistoricMessageResponse(peerID []byte, payload []byte) error {
size, r, err := rlp.EncodeToReader(payload)
if err != nil {
return err
}
+ peer, err := w.getPeer(peerID)
+ if err != nil {
+ return err
+ }
return peer.ws.WriteMsg(p2p.Msg{Code: p2pRequestCompleteCode, Size: uint32(size), Payload: r})
}
@@ -500,13 +504,21 @@ func (w *Waku) SendP2PMessages(peerID []byte, envelopes ...*Envelope) error {
// SendP2PDirect sends a peer-to-peer message to a specific peer.
// It sends one or more envelopes in a single batch.
-func (w *Waku) SendP2PDirect(peer *Peer, envelopes ...*Envelope) error {
+func (w *Waku) SendP2PDirect(peerID []byte, envelopes ...*Envelope) error {
+ peer, err := w.getPeer(peerID)
+ if err != nil {
+ return err
+ }
return p2p.Send(peer.ws, p2pMessageCode, envelopes)
}
// SendRawP2PDirect sends a peer-to-peer message to a specific peer.
// It sends one or more envelopes in a single batch.
-func (w *Waku) SendRawP2PDirect(peer *Peer, envelopes ...rlp.RawValue) error {
+func (w *Waku) SendRawP2PDirect(peerID []byte, envelopes ...rlp.RawValue) error {
+ peer, err := w.getPeer(peerID)
+ if err != nil {
+ return err
+ }
return p2p.Send(peer.ws, p2pMessageCode, envelopes)
}
@@ -1050,7 +1062,7 @@ func (w *Waku) handleP2PRequestCode(p *Peer, packet p2p.Msg, logger *zap.Logger)
var requestDeprecated Envelope
errDepReq := packet.Decode(&requestDeprecated)
if errDepReq == nil {
- w.mailServer.DeliverMail(p, &requestDeprecated)
+ w.mailServer.DeliverMail(p.ID(), &requestDeprecated)
return nil
} else {
logger.Info("failed to decode p2p request message (deprecated)", zap.Binary("peer", peerID[:]), zap.Error(errDepReq))
@@ -1065,7 +1077,7 @@ func (w *Waku) handleP2PRequestCode(p *Peer, packet p2p.Msg, logger *zap.Logger)
var request MessagesRequest
errReq := packet.Decode(&request)
if errReq == nil {
- w.mailServer.Deliver(p, request)
+ w.mailServer.Deliver(p.ID(), request)
return nil
} else {
logger.Info("failed to decode p2p request message", zap.Binary("peer", peerID[:]), zap.Error(errDepReq))
diff --git a/whisper/doc.go b/whisper/doc.go
index 12d39ab0b..fdee9d708 100644
--- a/whisper/doc.go
+++ b/whisper/doc.go
@@ -105,10 +105,9 @@ const (
// in order to bypass the expiry checks.
type MailServer interface {
Archive(env *Envelope)
- // DEPRECATED
- DeliverMail(whisperPeer *Peer, request *Envelope)
- Deliver(whisperPeer *Peer, request MessagesRequest)
- SyncMail(*Peer, SyncMailRequest) error
+ DeliverMail(peerID []byte, req *Envelope) // DEPRECATED; user Deliver instead
+ Deliver(peerID []byte, req MessagesRequest)
+ SyncMail(peerID []byte, req SyncMailRequest) error
}
// MessagesRequest contains details of a request of historic messages.
diff --git a/whisper/metrics.go b/whisper/metrics.go
index 6ffa436fc..09b3af10f 100644
--- a/whisper/metrics.go
+++ b/whisper/metrics.go
@@ -6,37 +6,37 @@ import (
var (
envelopesReceivedCounter = prom.NewCounter(prom.CounterOpts{
- Name: "waku_envelopes_received_total",
+ Name: "whisper_envelopes_received_total",
Help: "Number of envelopes received.",
})
envelopesValidatedCounter = prom.NewCounter(prom.CounterOpts{
- Name: "waku_envelopes_validated_total",
+ Name: "whisper_envelopes_validated_total",
Help: "Number of envelopes processed successfully.",
})
envelopesRejectedCounter = prom.NewCounterVec(prom.CounterOpts{
- Name: "waku_envelopes_rejected_total",
+ Name: "whisper_envelopes_rejected_total",
Help: "Number of envelopes rejected.",
}, []string{"reason"})
envelopesCacheFailedCounter = prom.NewCounterVec(prom.CounterOpts{
- Name: "waku_envelopes_cache_failures_total",
+ Name: "whisper_envelopes_cache_failures_total",
Help: "Number of envelopes which failed to be cached.",
}, []string{"type"})
envelopesCachedCounter = prom.NewCounterVec(prom.CounterOpts{
- Name: "waku_envelopes_cached_total",
+ Name: "whisper_envelopes_cached_total",
Help: "Number of envelopes cached.",
}, []string{"cache"})
envelopesSizeMeter = prom.NewHistogram(prom.HistogramOpts{
- Name: "waku_envelopes_size_bytes",
+ Name: "whisper_envelopes_size_bytes",
Help: "Size of processed Waku envelopes in bytes.",
Buckets: prom.ExponentialBuckets(256, 4, 10),
})
// rate limiter metrics
rateLimitsProcessed = prom.NewCounter(prom.CounterOpts{
- Name: "waku_rate_limits_processed_total",
+ Name: "whisper_rate_limits_processed_total",
Help: "Number of packets Waku rate limiter processed.",
})
rateLimitsExceeded = prom.NewCounterVec(prom.CounterOpts{
- Name: "waku_rate_limits_exceeded_total",
+ Name: "whisper_rate_limits_exceeded_total",
Help: "Number of times the Waku rate limits were exceeded",
}, []string{"type"})
)
diff --git a/whisper/whisper.go b/whisper/whisper.go
index cff9dcf54..693fede2d 100644
--- a/whisper/whisper.go
+++ b/whisper/whisper.go
@@ -104,7 +104,7 @@ type Whisper struct {
statsMu sync.Mutex // guard stats
stats Statistics // Statistics of whisper node
- mailServer MailServer // MailServer interface
+ mailServer MailServer
rateLimiter *PeerRateLimiter
@@ -264,7 +264,7 @@ func (whisper *Whisper) GetCurrentTime() time.Time {
// RegisterServer registers MailServer interface.
// MailServer will process all the incoming messages with p2pRequestCode.
-func (whisper *Whisper) RegisterServer(server MailServer) {
+func (whisper *Whisper) RegisterMailServer(server MailServer) {
whisper.mailServer = server
}
@@ -502,12 +502,15 @@ func (whisper *Whisper) expireRequestHistoricMessages(peer enode.ID, hash common
}
}
-func (whisper *Whisper) SendHistoricMessageResponse(peer *Peer, payload []byte) error {
+func (whisper *Whisper) SendHistoricMessageResponse(peerID []byte, payload []byte) error {
size, r, err := rlp.EncodeToReader(payload)
if err != nil {
return err
}
-
+ peer, err := whisper.getPeer(peerID)
+ if err != nil {
+ return err
+ }
return peer.ws.WriteMsg(p2p.Msg{Code: p2pRequestCompleteCode, Size: uint32(size), Payload: r})
}
@@ -530,29 +533,37 @@ func (whisper *Whisper) SyncMessages(peerID []byte, req SyncMailRequest) error {
}
// SendSyncResponse sends a response to a Mail Server with a slice of envelopes.
-func (whisper *Whisper) SendSyncResponse(p *Peer, data SyncResponse) error {
- return p2p.Send(p.ws, p2pSyncResponseCode, data)
+func (whisper *Whisper) SendSyncResponse(peerID []byte, data SyncResponse) error {
+ peer, err := whisper.getPeer(peerID)
+ if err != nil {
+ return err
+ }
+ return p2p.Send(peer.ws, p2pSyncResponseCode, data)
}
// SendRawSyncResponse sends a response to a Mail Server with a slice of envelopes.
-func (whisper *Whisper) SendRawSyncResponse(p *Peer, data RawSyncResponse) error {
- return p2p.Send(p.ws, p2pSyncResponseCode, data)
+func (whisper *Whisper) SendRawSyncResponse(peerID []byte, data RawSyncResponse) error {
+ peer, err := whisper.getPeer(peerID)
+ if err != nil {
+ return err
+ }
+ return p2p.Send(peer.ws, p2pSyncResponseCode, data)
}
// SendP2PMessage sends a peer-to-peer message to a specific peer.
func (whisper *Whisper) SendP2PMessage(peerID []byte, envelopes ...*Envelope) error {
- p, err := whisper.getPeer(peerID)
- if err != nil {
- return err
- }
- return whisper.SendP2PDirect(p, envelopes...)
+ return whisper.SendP2PDirect(peerID, envelopes...)
}
// SendP2PDirect sends a peer-to-peer message to a specific peer.
// If only a single envelope is given, data is sent as a single object
// rather than a slice. This is important to keep this method backward compatible
// as it used to send only single envelopes.
-func (whisper *Whisper) SendP2PDirect(peer *Peer, envelopes ...*Envelope) error {
+func (whisper *Whisper) SendP2PDirect(peerID []byte, envelopes ...*Envelope) error {
+ peer, err := whisper.getPeer(peerID)
+ if err != nil {
+ return err
+ }
if len(envelopes) == 1 {
return p2p.Send(peer.ws, p2pMessageCode, envelopes[0])
}
@@ -563,7 +574,11 @@ func (whisper *Whisper) SendP2PDirect(peer *Peer, envelopes ...*Envelope) error
// If only a single envelope is given, data is sent as a single object
// rather than a slice. This is important to keep this method backward compatible
// as it used to send only single envelopes.
-func (whisper *Whisper) SendRawP2PDirect(peer *Peer, envelopes ...rlp.RawValue) error {
+func (whisper *Whisper) SendRawP2PDirect(peerID []byte, envelopes ...rlp.RawValue) error {
+ peer, err := whisper.getPeer(peerID)
+ if err != nil {
+ return err
+ }
if len(envelopes) == 1 {
return p2p.Send(peer.ws, p2pMessageCode, envelopes[0])
}
@@ -1099,13 +1114,13 @@ func (whisper *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error {
return fmt.Errorf("sync mail request was invalid: %v", err)
}
- if err := whisper.mailServer.SyncMail(p, request); err != nil {
+ if err := whisper.mailServer.SyncMail(p.ID(), request); err != nil {
log.Error(
"failed to sync envelopes",
"peer", p.peer.ID().String(),
)
_ = whisper.SendSyncResponse(
- p,
+ p.ID(),
SyncResponse{Error: err.Error()},
)
return err
@@ -1157,7 +1172,7 @@ func (whisper *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error {
var requestDeprecated Envelope
errDepReq := packet.Decode(&requestDeprecated)
if errDepReq == nil {
- whisper.mailServer.DeliverMail(p, &requestDeprecated)
+ whisper.mailServer.DeliverMail(p.ID(), &requestDeprecated)
continue
} else {
log.Info("failed to decode p2p request message (deprecated)", "peer", p.peer.ID(), "err", errDepReq)
@@ -1172,7 +1187,7 @@ func (whisper *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error {
var request MessagesRequest
errReq := packet.Decode(&request)
if errReq == nil {
- whisper.mailServer.Deliver(p, request)
+ whisper.mailServer.Deliver(p.ID(), request)
continue
} else {
log.Info("failed to decode p2p request message", "peer", p.peer.ID(), "err", errReq)