Move whisper to status-go monorepo (#1720)
This commit is contained in:
parent
4c0d8dedea
commit
4ac4a61e20
|
@ -2,7 +2,7 @@ package gethbridge
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
)
|
)
|
||||||
|
|
||||||
type gethEnvelopeWrapper struct {
|
type gethEnvelopeWrapper struct {
|
||||||
|
|
|
@ -2,7 +2,7 @@ package gethbridge
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewGethEnvelopeErrorWrapper returns a types.EnvelopeError object that mimics Geth's EnvelopeError
|
// NewGethEnvelopeErrorWrapper returns a types.EnvelopeError object that mimics Geth's EnvelopeError
|
||||||
|
|
|
@ -2,7 +2,7 @@ package gethbridge
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewGethEnvelopeEventWrapper returns a types.EnvelopeEvent object that mimics Geth's EnvelopeEvent
|
// NewGethEnvelopeEventWrapper returns a types.EnvelopeEvent object that mimics Geth's EnvelopeEvent
|
||||||
|
|
|
@ -2,7 +2,7 @@ package gethbridge
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
)
|
)
|
||||||
|
|
||||||
type gethFilterWrapper struct {
|
type gethFilterWrapper struct {
|
||||||
|
|
|
@ -2,7 +2,7 @@ package gethbridge
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewGethMailServerResponseWrapper returns a types.MailServerResponse object that mimics Geth's MailServerResponse
|
// NewGethMailServerResponseWrapper returns a types.MailServerResponse object that mimics Geth's MailServerResponse
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
gethens "github.com/status-im/status-go/eth-node/bridge/geth/ens"
|
gethens "github.com/status-im/status-go/eth-node/bridge/geth/ens"
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
enstypes "github.com/status-im/status-go/eth-node/types/ens"
|
enstypes "github.com/status-im/status-go/eth-node/types/ens"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
)
|
)
|
||||||
|
|
||||||
type gethPublicWhisperAPIWrapper struct {
|
type gethPublicWhisperAPIWrapper struct {
|
||||||
|
|
|
@ -2,7 +2,7 @@ package gethbridge
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewGethSyncEventResponseWrapper returns a types.SyncEventResponse object that mimics Geth's SyncEventResponse
|
// NewGethSyncEventResponseWrapper returns a types.SyncEventResponse object that mimics Geth's SyncEventResponse
|
||||||
|
|
|
@ -2,7 +2,7 @@ package gethbridge
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetGethSyncMailRequestFrom converts a whisper SyncMailRequest struct from a SyncMailRequest struct
|
// GetGethSyncMailRequestFrom converts a whisper SyncMailRequest struct from a SyncMailRequest struct
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
)
|
)
|
||||||
|
|
||||||
type gethWhisperWrapper struct {
|
type gethWhisperWrapper struct {
|
||||||
|
|
|
@ -6,12 +6,14 @@ replace github.com/ethereum/go-ethereum v1.9.5 => github.com/status-im/go-ethere
|
||||||
|
|
||||||
replace github.com/status-im/status-go/extkeys => ../extkeys
|
replace github.com/status-im/status-go/extkeys => ../extkeys
|
||||||
|
|
||||||
|
replace github.com/status-im/status-go/whisper => ../whisper
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/ethereum/go-ethereum v1.9.5
|
github.com/ethereum/go-ethereum v1.9.5
|
||||||
github.com/mattn/go-pointer v0.0.0-20190911064623-a0a44394634f
|
github.com/mattn/go-pointer v0.0.0-20190911064623-a0a44394634f
|
||||||
github.com/status-im/doubleratchet v3.0.0+incompatible
|
github.com/status-im/doubleratchet v3.0.0+incompatible
|
||||||
github.com/status-im/status-go/extkeys v1.0.0 // indirect
|
github.com/status-im/status-go/extkeys v1.0.0 // indirect
|
||||||
github.com/status-im/whisper v1.5.2
|
github.com/status-im/status-go/whisper v1.0.0 // indirect
|
||||||
github.com/stretchr/testify v1.4.0
|
github.com/stretchr/testify v1.4.0
|
||||||
github.com/wealdtech/go-ens/v3 v3.0.9
|
github.com/wealdtech/go-ens/v3 v3.0.9
|
||||||
go.uber.org/zap v1.13.0
|
go.uber.org/zap v1.13.0
|
||||||
|
|
|
@ -208,6 +208,7 @@ github.com/status-im/go-ethereum v1.9.5-status.6 h1:ytuTO1yBIAuTVRtRQoc2mrdyngtP
|
||||||
github.com/status-im/go-ethereum v1.9.5-status.6/go.mod h1:08JvQWE+IOnAFSe4UD4ACLNe2fDd9XmWMCq5Yzy9mk0=
|
github.com/status-im/go-ethereum v1.9.5-status.6/go.mod h1:08JvQWE+IOnAFSe4UD4ACLNe2fDd9XmWMCq5Yzy9mk0=
|
||||||
github.com/status-im/keycard-go v0.0.0-20190424133014-d95853db0f48 h1:ju5UTwk5Odtm4trrY+4Ca4RMj5OyXbmVeDAVad2T0Jw=
|
github.com/status-im/keycard-go v0.0.0-20190424133014-d95853db0f48 h1:ju5UTwk5Odtm4trrY+4Ca4RMj5OyXbmVeDAVad2T0Jw=
|
||||||
github.com/status-im/keycard-go v0.0.0-20190424133014-d95853db0f48/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
|
github.com/status-im/keycard-go v0.0.0-20190424133014-d95853db0f48/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
|
||||||
|
github.com/status-im/status-go v0.36.1 h1:nb9eTq0UQJ57YyTZSl5U05emFT+R4AW8/Bga6ocgOks=
|
||||||
github.com/status-im/whisper v1.5.2 h1:26NgiKusmPic38eQdtXnaY+iaQ/LuQ3Dh0kCGYT/Uxs=
|
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=
|
github.com/status-im/whisper v1.5.2/go.mod h1:emrOxzJme0k66QtbbQ2bdd3P8RCdLZ8sTD7SkwH1s2s=
|
||||||
github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 h1:gIlAHnH1vJb5vwEjIp5kBj/eu99p/bl0Ay2goiPe5xE=
|
github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 h1:gIlAHnH1vJb5vwEjIp5kBj/eu99p/bl0Ay2goiPe5xE=
|
||||||
|
@ -217,6 +218,7 @@ github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUW
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
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 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||||
github.com/stretchr/testify v0.0.0-20170809224252-890a5c3458b4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v0.0.0-20170809224252-890a5c3458b4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
@ -227,6 +229,7 @@ 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 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 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
|
||||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||||
|
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=
|
github.com/tyler-smith/go-bip39 v1.0.2 h1:+t3w+KwLXO6154GNJY+qUtIxLTmFjfUmpguQT1OlOT8=
|
||||||
github.com/tyler-smith/go-bip39 v1.0.2/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs=
|
github.com/tyler-smith/go-bip39 v1.0.2/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs=
|
||||||
github.com/uber/jaeger-client-go v0.0.0-20180607151842-f7e0d4744fa6/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
|
github.com/uber/jaeger-client-go v0.0.0-20180607151842-f7e0d4744fa6/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
|
||||||
|
|
4
go.mod
4
go.mod
|
@ -16,6 +16,8 @@ replace github.com/status-im/status-go/extkeys => ./extkeys
|
||||||
|
|
||||||
replace github.com/status-im/status-go/eth-node => ./eth-node
|
replace github.com/status-im/status-go/eth-node => ./eth-node
|
||||||
|
|
||||||
|
replace github.com/status-im/status-go/whisper => ./whisper
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/beevik/ntp v0.2.0
|
github.com/beevik/ntp v0.2.0
|
||||||
github.com/elastic/gosigar v0.10.5 // indirect
|
github.com/elastic/gosigar v0.10.5 // indirect
|
||||||
|
@ -44,8 +46,8 @@ require (
|
||||||
github.com/status-im/status-go/eth-node v0.0.0-20191126161717-86bc127b3d0a
|
github.com/status-im/status-go/eth-node v0.0.0-20191126161717-86bc127b3d0a
|
||||||
github.com/status-im/status-go/extkeys v1.0.0
|
github.com/status-im/status-go/extkeys v1.0.0
|
||||||
github.com/status-im/status-go/protocol v0.5.2
|
github.com/status-im/status-go/protocol v0.5.2
|
||||||
|
github.com/status-im/status-go/whisper v1.0.0
|
||||||
github.com/status-im/tcp-shaker v0.0.0-20191114194237-215893130501
|
github.com/status-im/tcp-shaker v0.0.0-20191114194237-215893130501
|
||||||
github.com/status-im/whisper v1.6.2
|
|
||||||
github.com/stretchr/testify v1.4.0
|
github.com/stretchr/testify v1.4.0
|
||||||
github.com/syndtr/goleveldb v1.0.0
|
github.com/syndtr/goleveldb v1.0.0
|
||||||
go.uber.org/zap v1.13.0
|
go.uber.org/zap v1.13.0
|
||||||
|
|
16
go.sum
16
go.sum
|
@ -28,14 +28,11 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
|
||||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
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 v0.0.0-20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
|
||||||
github.com/allegro/bigcache v1.1.0 h1:MLuIKTjdxDc+qsG2rhjsYjsHQC5LUGjIWzutg7M+W68=
|
|
||||||
github.com/allegro/bigcache v1.1.0/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
|
|
||||||
github.com/allegro/bigcache v1.2.0 h1:qDaE0QoF29wKBb3+pXFrJFy1ihe5OT9OiXhg1t85SxM=
|
github.com/allegro/bigcache v1.2.0 h1:qDaE0QoF29wKBb3+pXFrJFy1ihe5OT9OiXhg1t85SxM=
|
||||||
github.com/allegro/bigcache v1.2.0/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
|
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/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/apilayer/freegeoip v3.5.0+incompatible/go.mod h1:CUfFqErhFhXneJendyQ/rRcuA8kH8JxHvYnbOozmlCU=
|
||||||
github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
|
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/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 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-20190502180301-283422fc1708/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
|
||||||
|
@ -49,7 +46,6 @@ 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/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||||
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k=
|
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k=
|
||||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
||||||
github.com/btcsuite/btcd v0.0.0-20181013004428-67e573d211ac/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ=
|
|
||||||
github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8=
|
github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8=
|
||||||
github.com/btcsuite/btcd v0.0.0-20190418232430-6867ff32788a/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8=
|
github.com/btcsuite/btcd v0.0.0-20190418232430-6867ff32788a/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8=
|
||||||
github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI=
|
github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI=
|
||||||
|
@ -506,13 +502,11 @@ github.com/olekukonko/tablewriter v0.0.1 h1:b3iUnf1v+ppJiOfNX4yxxqfWKMQPZR5yoh8u
|
||||||
github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
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.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.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.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.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/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
|
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/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||||
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
|
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
|
||||||
|
@ -619,9 +613,6 @@ github.com/status-im/rendezvous v1.3.0 h1:7RK/MXXW+tlm0asKm1u7Qp7Yni6AO29a7j8+E4
|
||||||
github.com/status-im/rendezvous v1.3.0/go.mod h1:+hzjuP+j/XzLPeF6E50b88pWOTLdTcwjvNYt+Gh1W1s=
|
github.com/status-im/rendezvous v1.3.0/go.mod h1:+hzjuP+j/XzLPeF6E50b88pWOTLdTcwjvNYt+Gh1W1s=
|
||||||
github.com/status-im/tcp-shaker v0.0.0-20191114194237-215893130501 h1:oa0KU5jJRNtXaM/P465MhvSFo/HM2O8qi2DDuPcd7ro=
|
github.com/status-im/tcp-shaker v0.0.0-20191114194237-215893130501 h1:oa0KU5jJRNtXaM/P465MhvSFo/HM2O8qi2DDuPcd7ro=
|
||||||
github.com/status-im/tcp-shaker v0.0.0-20191114194237-215893130501/go.mod h1:RYo/itke1oU5k/6sj9DNM3QAwtE5rZSgg5JnkOv83hk=
|
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/go.mod h1:emrOxzJme0k66QtbbQ2bdd3P8RCdLZ8sTD7SkwH1s2s=
|
|
||||||
github.com/status-im/whisper v1.6.2 h1:68WS0R2PzfM1VFKq/LW/hxijYHrqStfSlEoYOH8KZE4=
|
|
||||||
github.com/status-im/whisper v1.6.2/go.mod h1:uacoZIYbpf7iVk+YgFIuym6R0Qv2asjn6GoZEZ3dBLI=
|
|
||||||
github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 h1:gIlAHnH1vJb5vwEjIp5kBj/eu99p/bl0Ay2goiPe5xE=
|
github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 h1:gIlAHnH1vJb5vwEjIp5kBj/eu99p/bl0Ay2goiPe5xE=
|
||||||
github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw=
|
github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw=
|
||||||
github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 h1:njlZPzLwU639dk2kqnCPPv+wNjq7Xb6EfUxe/oX0/NM=
|
github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 h1:njlZPzLwU639dk2kqnCPPv+wNjq7Xb6EfUxe/oX0/NM=
|
||||||
|
@ -630,6 +621,8 @@ github.com/stephens2424/writerset v1.0.2/go.mod h1:aS2JhsMn6eA7e82oNmW4rfsgAOp9C
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
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 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
|
||||||
|
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||||
github.com/stretchr/testify v0.0.0-20170809224252-890a5c3458b4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
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.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
@ -696,7 +689,6 @@ golang.org/dl v0.0.0-20190829154251-82a15e2f2ead/go.mod h1:IUMfjQLJQd4UTqG1Z90te
|
||||||
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
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-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190103213133-ff983b9c42bc/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
|
||||||
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
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-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/syndtr/goleveldb/leveldb"
|
"github.com/syndtr/goleveldb/leveldb"
|
||||||
"github.com/syndtr/goleveldb/leveldb/storage"
|
"github.com/syndtr/goleveldb/leveldb/storage"
|
||||||
|
|
|
@ -31,7 +31,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
"github.com/status-im/status-go/params"
|
"github.com/status-im/status-go/params"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
|
|
||||||
prom "github.com/prometheus/client_golang/prometheus"
|
prom "github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
package mailserver
|
package mailserver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/status-im/status-go/whisper"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DB is an interface to abstract interactions with the db so that the mailserver
|
// DB is an interface to abstract interactions with the db so that the mailserver
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
"github.com/status-im/status-go/params"
|
"github.com/status-im/status-go/params"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
"github.com/syndtr/goleveldb/leveldb"
|
"github.com/syndtr/goleveldb/leveldb"
|
||||||
"github.com/syndtr/goleveldb/leveldb/errors"
|
"github.com/syndtr/goleveldb/leveldb/errors"
|
||||||
"github.com/syndtr/goleveldb/leveldb/iterator"
|
"github.com/syndtr/goleveldb/leveldb/iterator"
|
||||||
|
|
|
@ -16,7 +16,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewPostgresDB(config *params.WhisperConfig) (*PostgresDB, error) {
|
func NewPostgresDB(config *params.WhisperConfig) (*PostgresDB, error) {
|
||||||
|
|
|
@ -34,7 +34,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
"github.com/status-im/status-go/params"
|
"github.com/status-im/status-go/params"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ import (
|
||||||
"github.com/status-im/status-go/services/status"
|
"github.com/status-im/status-go/services/status"
|
||||||
"github.com/status-im/status-go/static"
|
"github.com/status-im/status-go/static"
|
||||||
"github.com/status-im/status-go/timesource"
|
"github.com/status-im/status-go/timesource"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
"github.com/syndtr/goleveldb/leveldb"
|
"github.com/syndtr/goleveldb/leveldb"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/accounts"
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
|
|
||||||
"github.com/status-im/status-go/params"
|
"github.com/status-im/status-go/params"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||||
"github.com/ethereum/go-ethereum/p2p/enr"
|
"github.com/ethereum/go-ethereum/p2p/enr"
|
||||||
ma "github.com/multiformats/go-multiaddr"
|
ma "github.com/multiformats/go-multiaddr"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
"github.com/syndtr/goleveldb/leveldb"
|
"github.com/syndtr/goleveldb/leveldb"
|
||||||
|
|
||||||
"github.com/status-im/status-go/db"
|
"github.com/status-im/status-go/db"
|
||||||
|
|
|
@ -17,7 +17,7 @@ import (
|
||||||
gethnode "github.com/ethereum/go-ethereum/node"
|
gethnode "github.com/ethereum/go-ethereum/node"
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
|
|
||||||
"github.com/status-im/status-go/discovery"
|
"github.com/status-im/status-go/discovery"
|
||||||
"github.com/status-im/status-go/params"
|
"github.com/status-im/status-go/params"
|
||||||
|
|
|
@ -17,7 +17,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/p2p/discv5"
|
"github.com/ethereum/go-ethereum/p2p/discv5"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/status-im/status-go/static"
|
"github.com/status-im/status-go/static"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
validator "gopkg.in/go-playground/validator.v9"
|
validator "gopkg.in/go-playground/validator.v9"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ import (
|
||||||
"github.com/status-im/status-go/discovery"
|
"github.com/status-im/status-go/discovery"
|
||||||
"github.com/status-im/status-go/params"
|
"github.com/status-im/status-go/params"
|
||||||
"github.com/status-im/status-go/signal"
|
"github.com/status-im/status-go/signal"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PeerPoolSimulationSuite struct {
|
type PeerPoolSimulationSuite struct {
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||||
"github.com/status-im/status-go/params"
|
"github.com/status-im/status-go/params"
|
||||||
"github.com/status-im/status-go/t/helpers"
|
"github.com/status-im/status-go/t/helpers"
|
||||||
"github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
)
|
)
|
||||||
|
@ -389,7 +389,7 @@ func TestServerIgnoresInboundPeer(t *testing.T) {
|
||||||
topicPool.running = 1
|
topicPool.running = 1
|
||||||
topicPool.maxCachedPeers = 0
|
topicPool.maxCachedPeers = 0
|
||||||
|
|
||||||
whisper := whisperv6.New(nil)
|
whisper := whisper.New(nil)
|
||||||
srvkey, err := crypto.GenerateKey()
|
srvkey, err := crypto.GenerateKey()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
server := &p2p.Server{
|
server := &p2p.Server{
|
||||||
|
|
|
@ -8,6 +8,8 @@ replace github.com/gomarkdown/markdown => github.com/status-im/markdown v0.0.0-2
|
||||||
|
|
||||||
replace github.com/status-im/status-go/eth-node => ../eth-node
|
replace github.com/status-im/status-go/eth-node => ../eth-node
|
||||||
|
|
||||||
|
replace github.com/status-im/status-go/whisper => ../whisper
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/cenkalti/backoff/v3 v3.0.0
|
github.com/cenkalti/backoff/v3 v3.0.0
|
||||||
github.com/ethereum/go-ethereum v1.9.5
|
github.com/ethereum/go-ethereum v1.9.5
|
||||||
|
@ -23,7 +25,7 @@ require (
|
||||||
github.com/status-im/doubleratchet v3.0.0+incompatible
|
github.com/status-im/doubleratchet v3.0.0+incompatible
|
||||||
github.com/status-im/migrate/v4 v4.6.2-status.2
|
github.com/status-im/migrate/v4 v4.6.2-status.2
|
||||||
github.com/status-im/status-go/eth-node v0.0.0-20191120100713-5053b0b6835b
|
github.com/status-im/status-go/eth-node v0.0.0-20191120100713-5053b0b6835b
|
||||||
github.com/status-im/whisper v1.5.2
|
github.com/status-im/status-go/whisper v1.0.0
|
||||||
github.com/stretchr/testify v1.4.0
|
github.com/stretchr/testify v1.4.0
|
||||||
github.com/vacp2p/mvds v0.0.23
|
github.com/vacp2p/mvds v0.0.23
|
||||||
go.uber.org/zap v1.13.0
|
go.uber.org/zap v1.13.0
|
||||||
|
|
|
@ -487,6 +487,7 @@ github.com/status-im/markdown v0.0.0-20191113114344-af599402d015/go.mod h1:tmG2b
|
||||||
github.com/status-im/migrate/v4 v4.6.2-status.2 h1:SdC+sMDl/aI7vUlwD2qj2p7KsK4T60IS9z4/rYCCbI8=
|
github.com/status-im/migrate/v4 v4.6.2-status.2 h1:SdC+sMDl/aI7vUlwD2qj2p7KsK4T60IS9z4/rYCCbI8=
|
||||||
github.com/status-im/migrate/v4 v4.6.2-status.2/go.mod h1:c/kc90n47GZu/58nnz1OMLTf7uE4Da4gZP5qmU+A/v8=
|
github.com/status-im/migrate/v4 v4.6.2-status.2/go.mod h1:c/kc90n47GZu/58nnz1OMLTf7uE4Da4gZP5qmU+A/v8=
|
||||||
github.com/status-im/status-go v0.36.0 h1:91qDMJjHv+T3Li9FwxsWQ2JBVcYtvVDT0nGFSMnmM+8=
|
github.com/status-im/status-go v0.36.0 h1:91qDMJjHv+T3Li9FwxsWQ2JBVcYtvVDT0nGFSMnmM+8=
|
||||||
|
github.com/status-im/status-go v0.36.1 h1:nb9eTq0UQJ57YyTZSl5U05emFT+R4AW8/Bga6ocgOks=
|
||||||
github.com/status-im/status-go/extkeys v1.0.0 h1:Qyirsoi5Ye5UFfisgPtCjPb/RkBxyK+UsSiEcr2PVlM=
|
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/extkeys v1.0.0/go.mod h1:GdqJbrcpkNm5ZsSCpp+PdMxnXx+OcRBdm3PI0rs1FpU=
|
||||||
github.com/status-im/whisper v1.5.2 h1:26NgiKusmPic38eQdtXnaY+iaQ/LuQ3Dh0kCGYT/Uxs=
|
github.com/status-im/whisper v1.5.2 h1:26NgiKusmPic38eQdtXnaY+iaQ/LuQ3Dh0kCGYT/Uxs=
|
||||||
|
@ -501,6 +502,7 @@ github.com/stephens2424/writerset v1.0.2/go.mod h1:aS2JhsMn6eA7e82oNmW4rfsgAOp9C
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
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 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||||
github.com/stretchr/testify v0.0.0-20170809224252-890a5c3458b4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
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.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
|
|
@ -21,7 +21,7 @@ import (
|
||||||
"github.com/status-im/status-go/protocol/sqlite"
|
"github.com/status-im/status-go/protocol/sqlite"
|
||||||
transport "github.com/status-im/status-go/protocol/transport/whisper"
|
transport "github.com/status-im/status-go/protocol/transport/whisper"
|
||||||
v1protocol "github.com/status-im/status-go/protocol/v1"
|
v1protocol "github.com/status-im/status-go/protocol/v1"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
datasyncproto "github.com/vacp2p/mvds/protobuf"
|
datasyncproto "github.com/vacp2p/mvds/protobuf"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ import (
|
||||||
"github.com/status-im/status-go/protocol/protobuf"
|
"github.com/status-im/status-go/protocol/protobuf"
|
||||||
"github.com/status-im/status-go/protocol/sqlite"
|
"github.com/status-im/status-go/protocol/sqlite"
|
||||||
"github.com/status-im/status-go/protocol/tt"
|
"github.com/status-im/status-go/protocol/tt"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
|
@ -14,7 +14,7 @@ import (
|
||||||
|
|
||||||
_ "github.com/mutecomm/go-sqlcipher"
|
_ "github.com/mutecomm/go-sqlcipher"
|
||||||
"github.com/status-im/status-go/eth-node/crypto"
|
"github.com/status-im/status-go/eth-node/crypto"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
|
@ -18,7 +18,7 @@ import (
|
||||||
"github.com/status-im/status-go/mailserver"
|
"github.com/status-im/status-go/mailserver"
|
||||||
"github.com/status-im/status-go/params"
|
"github.com/status-im/status-go/params"
|
||||||
"github.com/status-im/status-go/services/shhext/mailservers"
|
"github.com/status-im/status-go/services/shhext/mailservers"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
|
|
||||||
gethbridge "github.com/status-im/status-go/eth-node/bridge/geth"
|
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/crypto"
|
||||||
|
|
|
@ -26,7 +26,7 @@ import (
|
||||||
"github.com/status-im/status-go/sqlite"
|
"github.com/status-im/status-go/sqlite"
|
||||||
"github.com/status-im/status-go/t/helpers"
|
"github.com/status-im/status-go/t/helpers"
|
||||||
"github.com/status-im/status-go/t/utils"
|
"github.com/status-im/status-go/t/utils"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
"github.com/syndtr/goleveldb/leveldb"
|
"github.com/syndtr/goleveldb/leveldb"
|
||||||
"github.com/syndtr/goleveldb/leveldb/storage"
|
"github.com/syndtr/goleveldb/leveldb/storage"
|
||||||
|
@ -469,7 +469,7 @@ func (s *RequestMessagesSyncSuite) TestExpired() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *RequestMessagesSyncSuite) testCompletedFromAttempt(target int) {
|
func (s *RequestMessagesSyncSuite) testCompletedFromAttempt(target int) {
|
||||||
const cursorSize = 36 // taken from mailserver_response.go from whisperv6 package
|
const cursorSize = 36 // taken from mailserver_response.go from whisper package
|
||||||
cursor := [cursorSize]byte{}
|
cursor := [cursorSize]byte{}
|
||||||
cursor[0] = 0x01
|
cursor[0] = 0x01
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ import (
|
||||||
"github.com/status-im/status-go/params"
|
"github.com/status-im/status-go/params"
|
||||||
"github.com/status-im/status-go/services/nodebridge"
|
"github.com/status-im/status-go/services/nodebridge"
|
||||||
"github.com/status-im/status-go/services/shhext"
|
"github.com/status-im/status-go/services/shhext"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/node"
|
"github.com/ethereum/go-ethereum/node"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||||
"github.com/ethereum/go-ethereum/p2p/nat"
|
"github.com/ethereum/go-ethereum/p2p/nat"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"github.com/status-im/status-go/node"
|
"github.com/status-im/status-go/node"
|
||||||
"github.com/status-im/status-go/params"
|
"github.com/status-im/status-go/params"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
|
|
||||||
"github.com/status-im/status-go/t/e2e"
|
"github.com/status-im/status-go/t/e2e"
|
||||||
. "github.com/status-im/status-go/t/utils"
|
. "github.com/status-im/status-go/t/utils"
|
||||||
|
|
|
@ -3,7 +3,7 @@ package e2e
|
||||||
import (
|
import (
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
|
|
||||||
"github.com/status-im/status-go/api"
|
"github.com/status-im/status-go/api"
|
||||||
"github.com/status-im/status-go/multiaccounts"
|
"github.com/status-im/status-go/multiaccounts"
|
||||||
|
|
|
@ -24,7 +24,7 @@ import (
|
||||||
"github.com/status-im/status-go/services/shhext"
|
"github.com/status-im/status-go/services/shhext"
|
||||||
"github.com/status-im/status-go/t/helpers"
|
"github.com/status-im/status-go/t/helpers"
|
||||||
"github.com/status-im/status-go/t/utils"
|
"github.com/status-im/status-go/t/utils"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
"golang.org/x/crypto/sha3"
|
"golang.org/x/crypto/sha3"
|
||||||
)
|
)
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
"github.com/status-im/status-go/account"
|
"github.com/status-im/status-go/account"
|
||||||
e2e "github.com/status-im/status-go/t/e2e"
|
e2e "github.com/status-im/status-go/t/e2e"
|
||||||
. "github.com/status-im/status-go/t/utils"
|
. "github.com/status-im/status-go/t/utils"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -32,8 +32,8 @@ matrix:
|
||||||
- os: osx
|
- os: osx
|
||||||
go: 1.12.x
|
go: 1.12.x
|
||||||
- os: linux
|
- os: linux
|
||||||
dist: xenial
|
dist: bionic
|
||||||
go: 1.12.x
|
go: 1.13.x
|
||||||
services:
|
services:
|
||||||
- docker
|
- docker
|
||||||
env:
|
env:
|
||||||
|
|
|
@ -22,8 +22,8 @@ environment:
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- rmdir C:\go /s /q
|
- rmdir C:\go /s /q
|
||||||
- appveyor DownloadFile https://storage.googleapis.com/golang/go1.12.9.windows-%GOARCH%.zip
|
- appveyor DownloadFile https://storage.googleapis.com/golang/go1.13.4.windows-%GOARCH%.zip
|
||||||
- 7z x go1.12.9.windows-%GOARCH%.zip -y -oC:\ > NUL
|
- 7z x go1.13.4.windows-%GOARCH%.zip -y -oC:\ > NUL
|
||||||
- go version
|
- go version
|
||||||
- gcc --version
|
- gcc --version
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ package gethbridge
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
)
|
)
|
||||||
|
|
||||||
type gethEnvelopeWrapper struct {
|
type gethEnvelopeWrapper struct {
|
||||||
|
|
|
@ -2,7 +2,7 @@ package gethbridge
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewGethEnvelopeErrorWrapper returns a types.EnvelopeError object that mimics Geth's EnvelopeError
|
// NewGethEnvelopeErrorWrapper returns a types.EnvelopeError object that mimics Geth's EnvelopeError
|
||||||
|
|
|
@ -2,7 +2,7 @@ package gethbridge
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewGethEnvelopeEventWrapper returns a types.EnvelopeEvent object that mimics Geth's EnvelopeEvent
|
// NewGethEnvelopeEventWrapper returns a types.EnvelopeEvent object that mimics Geth's EnvelopeEvent
|
||||||
|
|
|
@ -2,7 +2,7 @@ package gethbridge
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
)
|
)
|
||||||
|
|
||||||
type gethFilterWrapper struct {
|
type gethFilterWrapper struct {
|
||||||
|
|
2
vendor/github.com/status-im/status-go/eth-node/bridge/geth/mailserver_response.go
generated
vendored
2
vendor/github.com/status-im/status-go/eth-node/bridge/geth/mailserver_response.go
generated
vendored
|
@ -2,7 +2,7 @@ package gethbridge
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewGethMailServerResponseWrapper returns a types.MailServerResponse object that mimics Geth's MailServerResponse
|
// NewGethMailServerResponseWrapper returns a types.MailServerResponse object that mimics Geth's MailServerResponse
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
gethens "github.com/status-im/status-go/eth-node/bridge/geth/ens"
|
gethens "github.com/status-im/status-go/eth-node/bridge/geth/ens"
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
enstypes "github.com/status-im/status-go/eth-node/types/ens"
|
enstypes "github.com/status-im/status-go/eth-node/types/ens"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
2
vendor/github.com/status-im/status-go/eth-node/bridge/geth/public_whisper_api.go
generated
vendored
2
vendor/github.com/status-im/status-go/eth-node/bridge/geth/public_whisper_api.go
generated
vendored
|
@ -5,7 +5,7 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
)
|
)
|
||||||
|
|
||||||
type gethPublicWhisperAPIWrapper struct {
|
type gethPublicWhisperAPIWrapper struct {
|
||||||
|
|
2
vendor/github.com/status-im/status-go/eth-node/bridge/geth/syncevent_response.go
generated
vendored
2
vendor/github.com/status-im/status-go/eth-node/bridge/geth/syncevent_response.go
generated
vendored
|
@ -2,7 +2,7 @@ package gethbridge
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewGethSyncEventResponseWrapper returns a types.SyncEventResponse object that mimics Geth's SyncEventResponse
|
// NewGethSyncEventResponseWrapper returns a types.SyncEventResponse object that mimics Geth's SyncEventResponse
|
||||||
|
|
|
@ -2,7 +2,7 @@ package gethbridge
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetGethSyncMailRequestFrom converts a whisper SyncMailRequest struct from a SyncMailRequest struct
|
// GetGethSyncMailRequestFrom converts a whisper SyncMailRequest struct from a SyncMailRequest struct
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
whisper "github.com/status-im/whisper/whisperv6"
|
"github.com/status-im/status-go/whisper"
|
||||||
)
|
)
|
||||||
|
|
||||||
type gethWhisperWrapper struct {
|
type gethWhisperWrapper struct {
|
||||||
|
|
|
@ -8,6 +8,8 @@ replace github.com/gomarkdown/markdown => github.com/status-im/markdown v0.0.0-2
|
||||||
|
|
||||||
replace github.com/status-im/status-go/eth-node => ../eth-node
|
replace github.com/status-im/status-go/eth-node => ../eth-node
|
||||||
|
|
||||||
|
replace github.com/status-im/status-go/whisper => ../whisper
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/cenkalti/backoff/v3 v3.0.0
|
github.com/cenkalti/backoff/v3 v3.0.0
|
||||||
github.com/ethereum/go-ethereum v1.9.5
|
github.com/ethereum/go-ethereum v1.9.5
|
||||||
|
@ -23,7 +25,7 @@ require (
|
||||||
github.com/status-im/doubleratchet v3.0.0+incompatible
|
github.com/status-im/doubleratchet v3.0.0+incompatible
|
||||||
github.com/status-im/migrate/v4 v4.6.2-status.2
|
github.com/status-im/migrate/v4 v4.6.2-status.2
|
||||||
github.com/status-im/status-go/eth-node v0.0.0-20191120100713-5053b0b6835b
|
github.com/status-im/status-go/eth-node v0.0.0-20191120100713-5053b0b6835b
|
||||||
github.com/status-im/whisper v1.5.2
|
github.com/status-im/status-go/whisper v1.0.0
|
||||||
github.com/stretchr/testify v1.4.0
|
github.com/stretchr/testify v1.4.0
|
||||||
github.com/vacp2p/mvds v0.0.23
|
github.com/vacp2p/mvds v0.0.23
|
||||||
go.uber.org/zap v1.13.0
|
go.uber.org/zap v1.13.0
|
||||||
|
|
|
@ -487,6 +487,7 @@ github.com/status-im/markdown v0.0.0-20191113114344-af599402d015/go.mod h1:tmG2b
|
||||||
github.com/status-im/migrate/v4 v4.6.2-status.2 h1:SdC+sMDl/aI7vUlwD2qj2p7KsK4T60IS9z4/rYCCbI8=
|
github.com/status-im/migrate/v4 v4.6.2-status.2 h1:SdC+sMDl/aI7vUlwD2qj2p7KsK4T60IS9z4/rYCCbI8=
|
||||||
github.com/status-im/migrate/v4 v4.6.2-status.2/go.mod h1:c/kc90n47GZu/58nnz1OMLTf7uE4Da4gZP5qmU+A/v8=
|
github.com/status-im/migrate/v4 v4.6.2-status.2/go.mod h1:c/kc90n47GZu/58nnz1OMLTf7uE4Da4gZP5qmU+A/v8=
|
||||||
github.com/status-im/status-go v0.36.0 h1:91qDMJjHv+T3Li9FwxsWQ2JBVcYtvVDT0nGFSMnmM+8=
|
github.com/status-im/status-go v0.36.0 h1:91qDMJjHv+T3Li9FwxsWQ2JBVcYtvVDT0nGFSMnmM+8=
|
||||||
|
github.com/status-im/status-go v0.36.1 h1:nb9eTq0UQJ57YyTZSl5U05emFT+R4AW8/Bga6ocgOks=
|
||||||
github.com/status-im/status-go/extkeys v1.0.0 h1:Qyirsoi5Ye5UFfisgPtCjPb/RkBxyK+UsSiEcr2PVlM=
|
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/extkeys v1.0.0/go.mod h1:GdqJbrcpkNm5ZsSCpp+PdMxnXx+OcRBdm3PI0rs1FpU=
|
||||||
github.com/status-im/whisper v1.5.2 h1:26NgiKusmPic38eQdtXnaY+iaQ/LuQ3Dh0kCGYT/Uxs=
|
github.com/status-im/whisper v1.5.2 h1:26NgiKusmPic38eQdtXnaY+iaQ/LuQ3Dh0kCGYT/Uxs=
|
||||||
|
@ -501,6 +502,7 @@ github.com/stephens2424/writerset v1.0.2/go.mod h1:aS2JhsMn6eA7e82oNmW4rfsgAOp9C
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
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 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||||
github.com/stretchr/testify v0.0.0-20170809224252-890a5c3458b4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
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.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package whisperv6
|
package whisper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
|
@ -14,7 +14,7 @@
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package whisperv6
|
package whisper
|
||||||
|
|
||||||
// Config represents the configuration state of a whisper node.
|
// Config represents the configuration state of a whisper node.
|
||||||
type Config struct {
|
type Config struct {
|
|
@ -30,7 +30,7 @@ particularly the notion of singular endpoints.
|
||||||
|
|
||||||
// Contains the Whisper protocol constant definitions
|
// Contains the Whisper protocol constant definitions
|
||||||
|
|
||||||
package whisperv6
|
package whisper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
// Contains the Whisper protocol Envelope element.
|
// Contains the Whisper protocol Envelope element.
|
||||||
|
|
||||||
package whisperv6
|
package whisper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
|
@ -1,4 +1,4 @@
|
||||||
package whisperv6
|
package whisper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
@ -38,7 +38,6 @@ const (
|
||||||
// EnvelopeEvent used for envelopes events.
|
// EnvelopeEvent used for envelopes events.
|
||||||
type EnvelopeEvent struct {
|
type EnvelopeEvent struct {
|
||||||
Event EventType
|
Event EventType
|
||||||
Topic TopicType
|
|
||||||
Hash common.Hash
|
Hash common.Hash
|
||||||
Batch common.Hash
|
Batch common.Hash
|
||||||
Peer enode.ID
|
Peer enode.ID
|
|
@ -14,7 +14,7 @@
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package whisperv6
|
package whisper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
|
@ -1,6 +1,6 @@
|
||||||
// +build gofuzz
|
// +build gofuzz
|
||||||
|
|
||||||
package whisperv6
|
package whisper
|
||||||
|
|
||||||
func Fuzz(data []byte) int {
|
func Fuzz(data []byte) int {
|
||||||
if len(data) < 2 {
|
if len(data) < 2 {
|
|
@ -1,6 +1,6 @@
|
||||||
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
|
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
|
||||||
|
|
||||||
package whisperv6
|
package whisper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
|
@ -1,6 +1,6 @@
|
||||||
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
|
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
|
||||||
|
|
||||||
package whisperv6
|
package whisper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
|
@ -1,6 +1,6 @@
|
||||||
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
|
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
|
||||||
|
|
||||||
package whisperv6
|
package whisper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
|
@ -0,0 +1,17 @@
|
||||||
|
module github.com/status-im/status-go/whisper
|
||||||
|
|
||||||
|
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/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea
|
||||||
|
github.com/ethereum/go-ethereum v1.9.5
|
||||||
|
github.com/gorilla/websocket v1.4.1 // indirect
|
||||||
|
github.com/stretchr/objx v0.2.0 // indirect
|
||||||
|
github.com/stretchr/testify v1.3.0
|
||||||
|
github.com/syndtr/goleveldb v0.0.0-20181128100959-b001fa50d6b2
|
||||||
|
github.com/tsenart/tb v0.0.0-20181025101425-0d2499c8b6e9
|
||||||
|
golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf
|
||||||
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f
|
||||||
|
)
|
|
@ -0,0 +1,134 @@
|
||||||
|
bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=
|
||||||
|
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/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/allegro/bigcache v0.0.0-20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
|
||||||
|
github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 h1:rtI0fD4oG/8eVokGVPYJEW1F88p1ZNgXiEIs9thEE4A=
|
||||||
|
github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
|
||||||
|
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/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 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
|
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 h1:j4317fAZh7X6GqbFowYdYdI0L9bwxL07jyPZIdepyZ0=
|
||||||
|
github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/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/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||||
|
github.com/elastic/gosigar v0.0.0-20180330100440-37f05ff46ffa h1:o8OuEkracbk3qH6GvlI6XpEN1HTSxkzOG42xZpfDv/s=
|
||||||
|
github.com/elastic/gosigar v0.0.0-20180330100440-37f05ff46ffa/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/gizak/termui v0.0.0-20170117222342-991cd3d38091/go.mod h1:PkJoWUt/zacQKysNfQtcw1RW+eK2SxkieVBtl+4ovLA=
|
||||||
|
github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E=
|
||||||
|
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
|
||||||
|
github.com/go-stack/stack v1.5.4 h1:ACUuwAbOuCKT3mK+Az9UrqaSheA8lDWOfm0+ZT62NHY=
|
||||||
|
github.com/go-stack/stack v1.5.4/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
|
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/snappy v0.0.0-20170215233205-553a64147049 h1:K9KHZbXKpGydfDN0aZrsoHpLJlZsBrGMFWbgLDGnPZk=
|
||||||
|
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
|
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/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 h1:DqD8eigqlUm0+znmx7zhL0xvTW3+e1jCekJMfBUADWI=
|
||||||
|
github.com/huin/goupnp v0.0.0-20161224104101-679507af18f3/go.mod h1:MZ2ZmwcBpvOoJ22IJsc7va19ZwoheaBk43rKg12SKag=
|
||||||
|
github.com/influxdata/influxdb v0.0.0-20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY=
|
||||||
|
github.com/jackpal/go-nat-pmp v0.0.0-20160603034137-1fa385a6f458 h1:LPECOO5LcZx5tvkxraIptrg6AiAUf+28rFV9+noSZFA=
|
||||||
|
github.com/jackpal/go-nat-pmp v0.0.0-20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
|
||||||
|
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/julienschmidt/httprouter v0.0.0-20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||||
|
github.com/karalabe/hid v0.0.0-20181128192157-d815e0c1a2e2/go.mod h1:YvbcH+3Wo6XPs9nkgTY3u19KXLauXW+J5nB7hEHuX0A=
|
||||||
|
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
|
||||||
|
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/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
||||||
|
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
|
||||||
|
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 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
|
||||||
|
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
|
||||||
|
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
|
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/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/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/prometheus v0.0.0-20170814170113-3101606756c5/go.mod h1:oAIUtOny2rjMX0OWN5vPR5/q/twIROJvdqnQKDdil/s=
|
||||||
|
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/rs/cors v0.0.0-20160617231935-a62a804a8a00 h1:8DPul/X0IT/1TNMIxoKLwdemEOBBHDC/K4EB16Cw5WE=
|
||||||
|
github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||||
|
github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 h1:3hxavr+IHMsQBrYUPQM5v0CgENFktkkbg1sfpgM3h20=
|
||||||
|
github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ=
|
||||||
|
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.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
|
||||||
|
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||||
|
github.com/stretchr/testify v0.0.0-20170809224252-890a5c3458b4 h1:InXsxTNd7R4kIHKuA052litAUzokFLqjgbmhpUQTAs8=
|
||||||
|
github.com/stretchr/testify v0.0.0-20170809224252-890a5c3458b4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/syndtr/goleveldb v0.0.0-20181128100959-b001fa50d6b2 h1:GnOzE5fEFN3b2zDhJJABEofdb51uMRNb8eqIVtdducs=
|
||||||
|
github.com/syndtr/goleveldb v0.0.0-20181128100959-b001fa50d6b2/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
|
||||||
|
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=
|
||||||
|
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/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-20191029031824-8986dd9e96cf h1:fnPsqIDRbCSgumaMCRpoIoF2s4qxv0xSSS0BVZUE/ss=
|
||||||
|
golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
|
||||||
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
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/sys v0.0.0-20180909124046-d0be0721c37e/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-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
|
||||||
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
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/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
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/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||||
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
|
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/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 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
||||||
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
@ -1,4 +1,4 @@
|
||||||
package whisperv6
|
package whisper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
// Contains the Whisper protocol Message element.
|
// Contains the Whisper protocol Message element.
|
||||||
|
|
||||||
package whisperv6
|
package whisper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/aes"
|
"crypto/aes"
|
|
@ -0,0 +1,21 @@
|
||||||
|
package whisper
|
||||||
|
|
||||||
|
import "github.com/ethereum/go-ethereum/metrics"
|
||||||
|
|
||||||
|
var (
|
||||||
|
envelopeAddedCounter = metrics.NewRegisteredCounter("whisper/envelopeAdded", nil)
|
||||||
|
envelopeNewAddedCounter = metrics.NewRegisteredCounter("whisper/envelopeNewAdded", nil)
|
||||||
|
envelopeClearedCounter = metrics.NewRegisteredCounter("whisper/envelopeCleared", nil)
|
||||||
|
envelopeErrFromFutureCounter = metrics.NewRegisteredCounter("whisper/envelopeErrFromFuture", nil)
|
||||||
|
envelopeErrVeryOldCounter = metrics.NewRegisteredCounter("whisper/envelopeErrVeryOld", nil)
|
||||||
|
envelopeErrExpiredCounter = metrics.NewRegisteredCounter("whisper/envelopeErrExpired", nil)
|
||||||
|
envelopeErrOversizedCounter = metrics.NewRegisteredCounter("whisper/envelopeErrOversized", nil)
|
||||||
|
envelopeErrLowPowCounter = metrics.NewRegisteredCounter("whisper/envelopeErrLowPow", nil)
|
||||||
|
envelopeErrNoBloomMatchCounter = metrics.NewRegisteredCounter("whisper/envelopeErrNoBloomMatch", nil)
|
||||||
|
envelopeSizeMeter = metrics.NewRegisteredMeter("whisper/envelopeSize", nil)
|
||||||
|
|
||||||
|
// rate limiter metrics
|
||||||
|
rateLimiterProcessed = metrics.NewRegisteredCounter("whisper/rateLimiterProcessed", nil)
|
||||||
|
rateLimiterIPExceeded = metrics.NewRegisteredCounter("whisper/rateLimiterIPExceeded", nil)
|
||||||
|
rateLimiterPeerExceeded = metrics.NewRegisteredCounter("whisper/rateLimiterPeerExceeded", nil)
|
||||||
|
)
|
|
@ -14,7 +14,7 @@
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package whisperv6
|
package whisper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
|
@ -1,4 +1,4 @@
|
||||||
package whisperv6
|
package whisper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
@ -14,24 +14,14 @@ import (
|
||||||
type runLoop func(p *Peer, rw p2p.MsgReadWriter) error
|
type runLoop func(p *Peer, rw p2p.MsgReadWriter) error
|
||||||
|
|
||||||
type RateLimiterHandler interface {
|
type RateLimiterHandler interface {
|
||||||
IncProcessed()
|
ExceedPeerLimit()
|
||||||
IncExceedPeerLimit()
|
ExceedIPLimit()
|
||||||
IncExceedIPLimit()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type MetricsRateLimiterHandler struct{}
|
type MetricsRateLimiterHandler struct{}
|
||||||
|
|
||||||
func (MetricsRateLimiterHandler) IncProcessed() {
|
func (MetricsRateLimiterHandler) ExceedPeerLimit() { rateLimiterPeerExceeded.Inc(1) }
|
||||||
rateLimitsProcessed.Inc()
|
func (MetricsRateLimiterHandler) ExceedIPLimit() { rateLimiterIPExceeded.Inc(1) }
|
||||||
}
|
|
||||||
|
|
||||||
func (MetricsRateLimiterHandler) IncExceedPeerLimit() {
|
|
||||||
rateLimitsExceeded.WithLabelValues("max_peers").Inc()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (MetricsRateLimiterHandler) IncExceedIPLimit() {
|
|
||||||
rateLimitsExceeded.WithLabelValues("max_ips").Inc()
|
|
||||||
}
|
|
||||||
|
|
||||||
type PeerRateLimiterConfig struct {
|
type PeerRateLimiterConfig struct {
|
||||||
LimitPerSecIP int64
|
LimitPerSecIP int64
|
||||||
|
@ -40,7 +30,7 @@ type PeerRateLimiterConfig struct {
|
||||||
WhitelistedPeerIDs []enode.ID
|
WhitelistedPeerIDs []enode.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
var peerRateLimiterDefaults = PeerRateLimiterConfig{
|
var defaultPeerRateLimiterConfig = PeerRateLimiterConfig{
|
||||||
LimitPerSecIP: 10,
|
LimitPerSecIP: 10,
|
||||||
LimitPerSecPeerID: 5,
|
LimitPerSecPeerID: 5,
|
||||||
WhitelistedIPs: nil,
|
WhitelistedIPs: nil,
|
||||||
|
@ -62,7 +52,7 @@ type PeerRateLimiter struct {
|
||||||
|
|
||||||
func NewPeerRateLimiter(handler RateLimiterHandler, cfg *PeerRateLimiterConfig) *PeerRateLimiter {
|
func NewPeerRateLimiter(handler RateLimiterHandler, cfg *PeerRateLimiterConfig) *PeerRateLimiter {
|
||||||
if cfg == nil {
|
if cfg == nil {
|
||||||
copy := peerRateLimiterDefaults
|
copy := defaultPeerRateLimiterConfig
|
||||||
cfg = ©
|
cfg = ©
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,14 +82,14 @@ func (r *PeerRateLimiter) decorate(p *Peer, rw p2p.MsgReadWriter, runLoop runLoo
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
r.handler.IncProcessed()
|
rateLimiterProcessed.Inc(1)
|
||||||
|
|
||||||
var ip string
|
var ip string
|
||||||
if p != nil && p.peer != nil {
|
if p != nil && p.peer != nil {
|
||||||
ip = p.peer.Node().IP().String()
|
ip = p.peer.Node().IP().String()
|
||||||
}
|
}
|
||||||
if halted := r.throttleIP(ip); halted {
|
if halted := r.throttleIP(ip); halted {
|
||||||
r.handler.IncExceedIPLimit()
|
r.handler.ExceedIPLimit()
|
||||||
}
|
}
|
||||||
|
|
||||||
var peerID []byte
|
var peerID []byte
|
||||||
|
@ -107,7 +97,7 @@ func (r *PeerRateLimiter) decorate(p *Peer, rw p2p.MsgReadWriter, runLoop runLoo
|
||||||
peerID = p.ID()
|
peerID = p.ID()
|
||||||
}
|
}
|
||||||
if halted := r.throttlePeer(peerID); halted {
|
if halted := r.throttlePeer(peerID); halted {
|
||||||
r.handler.IncExceedPeerLimit()
|
r.handler.ExceedPeerLimit()
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := in.WriteMsg(packet); err != nil {
|
if err := in.WriteMsg(packet); err != nil {
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
// Contains the Whisper protocol Topic element.
|
// Contains the Whisper protocol Topic element.
|
||||||
|
|
||||||
package whisperv6
|
package whisper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
|
@ -14,7 +14,7 @@
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package whisperv6
|
package whisper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
@ -441,7 +441,6 @@ func (whisper *Whisper) RequestHistoricMessagesWithTimeout(peerID []byte, envelo
|
||||||
}
|
}
|
||||||
whisper.envelopeFeed.Send(EnvelopeEvent{
|
whisper.envelopeFeed.Send(EnvelopeEvent{
|
||||||
Peer: p.peer.ID(),
|
Peer: p.peer.ID(),
|
||||||
Topic: envelope.Topic,
|
|
||||||
Hash: envelope.Hash(),
|
Hash: envelope.Hash(),
|
||||||
Event: EventMailServerRequestSent,
|
Event: EventMailServerRequestSent,
|
||||||
})
|
})
|
||||||
|
@ -934,14 +933,12 @@ func (whisper *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error {
|
||||||
// decode the contained envelopes
|
// decode the contained envelopes
|
||||||
data, err := ioutil.ReadAll(packet.Payload)
|
data, err := ioutil.ReadAll(packet.Payload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
envelopesRejectedCounter.WithLabelValues("failed_read").Inc()
|
|
||||||
log.Warn("failed to read envelopes data", "peer", p.peer.ID(), "error", err)
|
log.Warn("failed to read envelopes data", "peer", p.peer.ID(), "error", err)
|
||||||
return errors.New("invalid enveloopes")
|
return errors.New("invalid enveloopes")
|
||||||
}
|
}
|
||||||
|
|
||||||
var envelopes []*Envelope
|
var envelopes []*Envelope
|
||||||
if err := rlp.DecodeBytes(data, &envelopes); err != nil {
|
if err := rlp.DecodeBytes(data, &envelopes); err != nil {
|
||||||
envelopesRejectedCounter.WithLabelValues("invalid_data").Inc()
|
|
||||||
log.Warn("failed to decode envelopes, peer will be disconnected", "peer", p.peer.ID(), "err", err)
|
log.Warn("failed to decode envelopes, peer will be disconnected", "peer", p.peer.ID(), "err", err)
|
||||||
return errors.New("invalid envelopes")
|
return errors.New("invalid envelopes")
|
||||||
}
|
}
|
||||||
|
@ -960,11 +957,9 @@ func (whisper *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error {
|
||||||
|
|
||||||
whisper.envelopeFeed.Send(EnvelopeEvent{
|
whisper.envelopeFeed.Send(EnvelopeEvent{
|
||||||
Event: EventEnvelopeReceived,
|
Event: EventEnvelopeReceived,
|
||||||
Topic: env.Topic,
|
|
||||||
Hash: env.Hash(),
|
Hash: env.Hash(),
|
||||||
Peer: p.peer.ID(),
|
Peer: p.peer.ID(),
|
||||||
})
|
})
|
||||||
envelopesValidatedCounter.Inc()
|
|
||||||
if cached {
|
if cached {
|
||||||
p.mark(env)
|
p.mark(env)
|
||||||
}
|
}
|
||||||
|
@ -979,14 +974,12 @@ func (whisper *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error {
|
||||||
case messageResponseCode:
|
case messageResponseCode:
|
||||||
var multiResponse MultiVersionResponse
|
var multiResponse MultiVersionResponse
|
||||||
if err := packet.Decode(&multiResponse); err != nil {
|
if err := packet.Decode(&multiResponse); err != nil {
|
||||||
envelopesRejectedCounter.WithLabelValues("failed_read").Inc()
|
|
||||||
log.Error("failed to decode messages response", "peer", p.peer.ID(), "error", err)
|
log.Error("failed to decode messages response", "peer", p.peer.ID(), "error", err)
|
||||||
return errors.New("invalid response message")
|
return errors.New("invalid response message")
|
||||||
}
|
}
|
||||||
if multiResponse.Version == 1 {
|
if multiResponse.Version == 1 {
|
||||||
response, err := multiResponse.DecodeResponse1()
|
response, err := multiResponse.DecodeResponse1()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
envelopesRejectedCounter.WithLabelValues("invalid_data").Inc()
|
|
||||||
log.Error("failed to decode messages response into first version of response", "peer", p.peer.ID(), "error", err)
|
log.Error("failed to decode messages response into first version of response", "peer", p.peer.ID(), "error", err)
|
||||||
}
|
}
|
||||||
whisper.envelopeFeed.Send(EnvelopeEvent{
|
whisper.envelopeFeed.Send(EnvelopeEvent{
|
||||||
|
@ -1013,13 +1006,11 @@ func (whisper *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error {
|
||||||
s := rlp.NewStream(packet.Payload, uint64(packet.Size))
|
s := rlp.NewStream(packet.Payload, uint64(packet.Size))
|
||||||
i, err := s.Uint()
|
i, err := s.Uint()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
envelopesRejectedCounter.WithLabelValues("invalid_pow_req").Inc()
|
|
||||||
log.Warn("failed to decode powRequirementCode message, peer will be disconnected", "peer", p.peer.ID(), "err", err)
|
log.Warn("failed to decode powRequirementCode message, peer will be disconnected", "peer", p.peer.ID(), "err", err)
|
||||||
return errors.New("invalid powRequirementCode message")
|
return errors.New("invalid powRequirementCode message")
|
||||||
}
|
}
|
||||||
f := math.Float64frombits(i)
|
f := math.Float64frombits(i)
|
||||||
if math.IsInf(f, 0) || math.IsNaN(f) || f < 0.0 {
|
if math.IsInf(f, 0) || math.IsNaN(f) || f < 0.0 {
|
||||||
envelopesRejectedCounter.WithLabelValues("invalid_pow_req").Inc()
|
|
||||||
log.Warn("invalid value in powRequirementCode message, peer will be disconnected", "peer", p.peer.ID(), "err", err)
|
log.Warn("invalid value in powRequirementCode message, peer will be disconnected", "peer", p.peer.ID(), "err", err)
|
||||||
return errors.New("invalid value in powRequirementCode message")
|
return errors.New("invalid value in powRequirementCode message")
|
||||||
}
|
}
|
||||||
|
@ -1033,7 +1024,6 @@ func (whisper *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error {
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn("failed to decode bloom filter exchange message, peer will be disconnected", "peer", p.peer.ID(), "err", err)
|
log.Warn("failed to decode bloom filter exchange message, peer will be disconnected", "peer", p.peer.ID(), "err", err)
|
||||||
envelopesRejectedCounter.WithLabelValues("invalid_bloom").Inc()
|
|
||||||
return errors.New("invalid bloom filter exchange message")
|
return errors.New("invalid bloom filter exchange message")
|
||||||
}
|
}
|
||||||
p.setBloomFilter(bloom)
|
p.setBloomFilter(bloom)
|
||||||
|
@ -1214,10 +1204,10 @@ func (whisper *Whisper) add(envelope *Envelope, isP2P bool) (bool, error) {
|
||||||
now := uint32(whisper.timeSource().Unix())
|
now := uint32(whisper.timeSource().Unix())
|
||||||
sent := envelope.Expiry - envelope.TTL
|
sent := envelope.Expiry - envelope.TTL
|
||||||
|
|
||||||
envelopesReceivedCounter.Inc()
|
envelopeAddedCounter.Inc(1)
|
||||||
if sent > now {
|
if sent > now {
|
||||||
if sent-DefaultSyncAllowance > now {
|
if sent-DefaultSyncAllowance > now {
|
||||||
envelopesCacheFailedCounter.WithLabelValues("in_future").Inc()
|
envelopeErrFromFutureCounter.Inc(1)
|
||||||
log.Warn("envelope created in the future", "hash", envelope.Hash())
|
log.Warn("envelope created in the future", "hash", envelope.Hash())
|
||||||
return false, TimeSyncError(errors.New("envelope from future"))
|
return false, TimeSyncError(errors.New("envelope from future"))
|
||||||
}
|
}
|
||||||
|
@ -1227,17 +1217,17 @@ func (whisper *Whisper) add(envelope *Envelope, isP2P bool) (bool, error) {
|
||||||
|
|
||||||
if envelope.Expiry < now {
|
if envelope.Expiry < now {
|
||||||
if envelope.Expiry+DefaultSyncAllowance*2 < now {
|
if envelope.Expiry+DefaultSyncAllowance*2 < now {
|
||||||
envelopesCacheFailedCounter.WithLabelValues("very_old").Inc()
|
envelopeErrVeryOldCounter.Inc(1)
|
||||||
log.Warn("very old envelope", "hash", envelope.Hash())
|
log.Warn("very old envelope", "hash", envelope.Hash())
|
||||||
return false, TimeSyncError(errors.New("very old envelope"))
|
return false, TimeSyncError(errors.New("very old envelope"))
|
||||||
}
|
}
|
||||||
log.Debug("expired envelope dropped", "hash", envelope.Hash().Hex())
|
log.Debug("expired envelope dropped", "hash", envelope.Hash().Hex())
|
||||||
envelopesCacheFailedCounter.WithLabelValues("expired").Inc()
|
envelopeErrExpiredCounter.Inc(1)
|
||||||
return false, nil // drop envelope without error
|
return false, nil // drop envelope without error
|
||||||
}
|
}
|
||||||
|
|
||||||
if uint32(envelope.size()) > whisper.MaxMessageSize() {
|
if uint32(envelope.size()) > whisper.MaxMessageSize() {
|
||||||
envelopesCacheFailedCounter.WithLabelValues("oversized").Inc()
|
envelopeErrOversizedCounter.Inc(1)
|
||||||
return false, fmt.Errorf("huge messages are not allowed [%x]", envelope.Hash())
|
return false, fmt.Errorf("huge messages are not allowed [%x]", envelope.Hash())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1246,7 +1236,7 @@ func (whisper *Whisper) add(envelope *Envelope, isP2P bool) (bool, error) {
|
||||||
// in this case the previous value is retrieved by MinPowTolerance()
|
// in this case the previous value is retrieved by MinPowTolerance()
|
||||||
// for a short period of peer synchronization.
|
// for a short period of peer synchronization.
|
||||||
if envelope.PoW() < whisper.MinPowTolerance() {
|
if envelope.PoW() < whisper.MinPowTolerance() {
|
||||||
envelopesCacheFailedCounter.WithLabelValues("low_pow").Inc()
|
envelopeErrLowPowCounter.Inc(1)
|
||||||
return false, fmt.Errorf("envelope with low PoW received: PoW=%f, hash=[%v]", envelope.PoW(), envelope.Hash().Hex())
|
return false, fmt.Errorf("envelope with low PoW received: PoW=%f, hash=[%v]", envelope.PoW(), envelope.Hash().Hex())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1256,7 +1246,7 @@ func (whisper *Whisper) add(envelope *Envelope, isP2P bool) (bool, error) {
|
||||||
// in this case the previous value is retrieved by BloomFilterTolerance()
|
// in this case the previous value is retrieved by BloomFilterTolerance()
|
||||||
// for a short period of peer synchronization.
|
// for a short period of peer synchronization.
|
||||||
if !BloomFilterMatch(whisper.BloomFilterTolerance(), envelope.Bloom()) {
|
if !BloomFilterMatch(whisper.BloomFilterTolerance(), envelope.Bloom()) {
|
||||||
envelopesCacheFailedCounter.WithLabelValues("no_bloom_match").Inc()
|
envelopeErrNoBloomMatchCounter.Inc(1)
|
||||||
return false, fmt.Errorf("envelope does not match bloom filter, hash=[%v], bloom: \n%x \n%x \n%x",
|
return false, fmt.Errorf("envelope does not match bloom filter, hash=[%v], bloom: \n%x \n%x \n%x",
|
||||||
envelope.Hash().Hex(), whisper.BloomFilter(), envelope.Bloom(), envelope.Topic)
|
envelope.Hash().Hex(), whisper.BloomFilter(), envelope.Bloom(), envelope.Topic)
|
||||||
}
|
}
|
||||||
|
@ -1279,11 +1269,10 @@ func (whisper *Whisper) add(envelope *Envelope, isP2P bool) (bool, error) {
|
||||||
|
|
||||||
if alreadyCached {
|
if alreadyCached {
|
||||||
log.Trace("whisper envelope already cached", "hash", envelope.Hash().Hex())
|
log.Trace("whisper envelope already cached", "hash", envelope.Hash().Hex())
|
||||||
envelopesCachedCounter.WithLabelValues("hit").Inc()
|
|
||||||
} else {
|
} else {
|
||||||
log.Trace("cached whisper envelope", "hash", envelope.Hash().Hex())
|
log.Trace("cached whisper envelope", "hash", envelope.Hash().Hex())
|
||||||
envelopesCachedCounter.WithLabelValues("miss").Inc()
|
envelopeNewAddedCounter.Inc(1)
|
||||||
envelopesSizeMeter.Observe(float64(envelope.size()))
|
envelopeSizeMeter.Mark(int64(envelope.size()))
|
||||||
whisper.statsMu.Lock()
|
whisper.statsMu.Lock()
|
||||||
whisper.stats.memoryUsed += envelope.size()
|
whisper.stats.memoryUsed += envelope.size()
|
||||||
whisper.statsMu.Unlock()
|
whisper.statsMu.Unlock()
|
||||||
|
@ -1291,7 +1280,6 @@ func (whisper *Whisper) add(envelope *Envelope, isP2P bool) (bool, error) {
|
||||||
if whisper.mailServer != nil {
|
if whisper.mailServer != nil {
|
||||||
whisper.mailServer.Archive(envelope)
|
whisper.mailServer.Archive(envelope)
|
||||||
whisper.envelopeFeed.Send(EnvelopeEvent{
|
whisper.envelopeFeed.Send(EnvelopeEvent{
|
||||||
Topic: envelope.Topic,
|
|
||||||
Hash: envelope.Hash(),
|
Hash: envelope.Hash(),
|
||||||
Event: EventMailServerEnvelopeArchived,
|
Event: EventMailServerEnvelopeArchived,
|
||||||
})
|
})
|
||||||
|
@ -1341,7 +1329,6 @@ func (whisper *Whisper) processQueue() {
|
||||||
case e := <-whisper.messageQueue:
|
case e := <-whisper.messageQueue:
|
||||||
whisper.filters.NotifyWatchers(e, false)
|
whisper.filters.NotifyWatchers(e, false)
|
||||||
whisper.envelopeFeed.Send(EnvelopeEvent{
|
whisper.envelopeFeed.Send(EnvelopeEvent{
|
||||||
Topic: e.Topic,
|
|
||||||
Hash: e.Hash(),
|
Hash: e.Hash(),
|
||||||
Event: EventEnvelopeAvailable,
|
Event: EventEnvelopeAvailable,
|
||||||
})
|
})
|
||||||
|
@ -1359,7 +1346,6 @@ func (whisper *Whisper) processP2P() {
|
||||||
case *Envelope:
|
case *Envelope:
|
||||||
whisper.filters.NotifyWatchers(event, true)
|
whisper.filters.NotifyWatchers(event, true)
|
||||||
whisper.envelopeFeed.Send(EnvelopeEvent{
|
whisper.envelopeFeed.Send(EnvelopeEvent{
|
||||||
Topic: event.Topic,
|
|
||||||
Hash: event.Hash(),
|
Hash: event.Hash(),
|
||||||
Event: EventEnvelopeAvailable,
|
Event: EventEnvelopeAvailable,
|
||||||
})
|
})
|
||||||
|
@ -1404,7 +1390,7 @@ func (whisper *Whisper) expire() {
|
||||||
hashSet.Each(func(v interface{}) bool {
|
hashSet.Each(func(v interface{}) bool {
|
||||||
sz := whisper.envelopes[v.(common.Hash)].size()
|
sz := whisper.envelopes[v.(common.Hash)].size()
|
||||||
delete(whisper.envelopes, v.(common.Hash))
|
delete(whisper.envelopes, v.(common.Hash))
|
||||||
envelopesCachedCounter.WithLabelValues("clear").Inc()
|
envelopeClearedCounter.Inc(1)
|
||||||
whisper.envelopeFeed.Send(EnvelopeEvent{
|
whisper.envelopeFeed.Send(EnvelopeEvent{
|
||||||
Hash: v.(common.Hash),
|
Hash: v.(common.Hash),
|
||||||
Event: EventEnvelopeExpired,
|
Event: EventEnvelopeExpired,
|
|
@ -1,50 +0,0 @@
|
||||||
package whisperv6
|
|
||||||
|
|
||||||
import prom "github.com/prometheus/client_golang/prometheus"
|
|
||||||
|
|
||||||
var (
|
|
||||||
envelopesReceivedCounter = prom.NewCounter(prom.CounterOpts{
|
|
||||||
Name: "whisper_envelopes_received_total",
|
|
||||||
Help: "Number of envelopes received.",
|
|
||||||
})
|
|
||||||
envelopesValidatedCounter = prom.NewCounter(prom.CounterOpts{
|
|
||||||
Name: "whisper_envelopes_validated_total",
|
|
||||||
Help: "Number of envelopes processed successfully.",
|
|
||||||
})
|
|
||||||
envelopesRejectedCounter = prom.NewCounterVec(prom.CounterOpts{
|
|
||||||
Name: "whisper_envelopes_rejected_total",
|
|
||||||
Help: "Number of envelopes rejected.",
|
|
||||||
}, []string{"reason"})
|
|
||||||
envelopesCacheFailedCounter = prom.NewCounterVec(prom.CounterOpts{
|
|
||||||
Name: "whisper_envelopes_cache_failures_total",
|
|
||||||
Help: "Number of envelopes which failed to be cached.",
|
|
||||||
}, []string{"type"})
|
|
||||||
envelopesCachedCounter = prom.NewCounterVec(prom.CounterOpts{
|
|
||||||
Name: "whisper_envelopes_cached_total",
|
|
||||||
Help: "Number of envelopes cached.",
|
|
||||||
}, []string{"cache"})
|
|
||||||
envelopesSizeMeter = prom.NewHistogram(prom.HistogramOpts{
|
|
||||||
Name: "whisper_envelopes_size_bytes",
|
|
||||||
Help: "Size of processed Whisper envelopes in bytes.",
|
|
||||||
Buckets: prom.ExponentialBuckets(256, 4, 10),
|
|
||||||
})
|
|
||||||
// rate limiter metrics
|
|
||||||
rateLimitsProcessed = prom.NewCounter(prom.CounterOpts{
|
|
||||||
Name: "whisper_rate_limits_processed_total",
|
|
||||||
Help: "Number of packets whisper rate limiter processed.",
|
|
||||||
})
|
|
||||||
rateLimitsExceeded = prom.NewCounterVec(prom.CounterOpts{
|
|
||||||
Name: "whisper_rate_limits_exceeded_total",
|
|
||||||
Help: "Number of times the whisper 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)
|
|
||||||
}
|
|
|
@ -1,159 +0,0 @@
|
||||||
// Copyright 2010 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package blowfish
|
|
||||||
|
|
||||||
// getNextWord returns the next big-endian uint32 value from the byte slice
|
|
||||||
// at the given position in a circular manner, updating the position.
|
|
||||||
func getNextWord(b []byte, pos *int) uint32 {
|
|
||||||
var w uint32
|
|
||||||
j := *pos
|
|
||||||
for i := 0; i < 4; i++ {
|
|
||||||
w = w<<8 | uint32(b[j])
|
|
||||||
j++
|
|
||||||
if j >= len(b) {
|
|
||||||
j = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*pos = j
|
|
||||||
return w
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExpandKey performs a key expansion on the given *Cipher. Specifically, it
|
|
||||||
// performs the Blowfish algorithm's key schedule which sets up the *Cipher's
|
|
||||||
// pi and substitution tables for calls to Encrypt. This is used, primarily,
|
|
||||||
// by the bcrypt package to reuse the Blowfish key schedule during its
|
|
||||||
// set up. It's unlikely that you need to use this directly.
|
|
||||||
func ExpandKey(key []byte, c *Cipher) {
|
|
||||||
j := 0
|
|
||||||
for i := 0; i < 18; i++ {
|
|
||||||
// Using inlined getNextWord for performance.
|
|
||||||
var d uint32
|
|
||||||
for k := 0; k < 4; k++ {
|
|
||||||
d = d<<8 | uint32(key[j])
|
|
||||||
j++
|
|
||||||
if j >= len(key) {
|
|
||||||
j = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c.p[i] ^= d
|
|
||||||
}
|
|
||||||
|
|
||||||
var l, r uint32
|
|
||||||
for i := 0; i < 18; i += 2 {
|
|
||||||
l, r = encryptBlock(l, r, c)
|
|
||||||
c.p[i], c.p[i+1] = l, r
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < 256; i += 2 {
|
|
||||||
l, r = encryptBlock(l, r, c)
|
|
||||||
c.s0[i], c.s0[i+1] = l, r
|
|
||||||
}
|
|
||||||
for i := 0; i < 256; i += 2 {
|
|
||||||
l, r = encryptBlock(l, r, c)
|
|
||||||
c.s1[i], c.s1[i+1] = l, r
|
|
||||||
}
|
|
||||||
for i := 0; i < 256; i += 2 {
|
|
||||||
l, r = encryptBlock(l, r, c)
|
|
||||||
c.s2[i], c.s2[i+1] = l, r
|
|
||||||
}
|
|
||||||
for i := 0; i < 256; i += 2 {
|
|
||||||
l, r = encryptBlock(l, r, c)
|
|
||||||
c.s3[i], c.s3[i+1] = l, r
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is similar to ExpandKey, but folds the salt during the key
|
|
||||||
// schedule. While ExpandKey is essentially expandKeyWithSalt with an all-zero
|
|
||||||
// salt passed in, reusing ExpandKey turns out to be a place of inefficiency
|
|
||||||
// and specializing it here is useful.
|
|
||||||
func expandKeyWithSalt(key []byte, salt []byte, c *Cipher) {
|
|
||||||
j := 0
|
|
||||||
for i := 0; i < 18; i++ {
|
|
||||||
c.p[i] ^= getNextWord(key, &j)
|
|
||||||
}
|
|
||||||
|
|
||||||
j = 0
|
|
||||||
var l, r uint32
|
|
||||||
for i := 0; i < 18; i += 2 {
|
|
||||||
l ^= getNextWord(salt, &j)
|
|
||||||
r ^= getNextWord(salt, &j)
|
|
||||||
l, r = encryptBlock(l, r, c)
|
|
||||||
c.p[i], c.p[i+1] = l, r
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < 256; i += 2 {
|
|
||||||
l ^= getNextWord(salt, &j)
|
|
||||||
r ^= getNextWord(salt, &j)
|
|
||||||
l, r = encryptBlock(l, r, c)
|
|
||||||
c.s0[i], c.s0[i+1] = l, r
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < 256; i += 2 {
|
|
||||||
l ^= getNextWord(salt, &j)
|
|
||||||
r ^= getNextWord(salt, &j)
|
|
||||||
l, r = encryptBlock(l, r, c)
|
|
||||||
c.s1[i], c.s1[i+1] = l, r
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < 256; i += 2 {
|
|
||||||
l ^= getNextWord(salt, &j)
|
|
||||||
r ^= getNextWord(salt, &j)
|
|
||||||
l, r = encryptBlock(l, r, c)
|
|
||||||
c.s2[i], c.s2[i+1] = l, r
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < 256; i += 2 {
|
|
||||||
l ^= getNextWord(salt, &j)
|
|
||||||
r ^= getNextWord(salt, &j)
|
|
||||||
l, r = encryptBlock(l, r, c)
|
|
||||||
c.s3[i], c.s3[i+1] = l, r
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func encryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
|
|
||||||
xl, xr := l, r
|
|
||||||
xl ^= c.p[0]
|
|
||||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[1]
|
|
||||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[2]
|
|
||||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[3]
|
|
||||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[4]
|
|
||||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[5]
|
|
||||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[6]
|
|
||||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[7]
|
|
||||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[8]
|
|
||||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[9]
|
|
||||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[10]
|
|
||||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[11]
|
|
||||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[12]
|
|
||||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[13]
|
|
||||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[14]
|
|
||||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[15]
|
|
||||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[16]
|
|
||||||
xr ^= c.p[17]
|
|
||||||
return xr, xl
|
|
||||||
}
|
|
||||||
|
|
||||||
func decryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
|
|
||||||
xl, xr := l, r
|
|
||||||
xl ^= c.p[17]
|
|
||||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[16]
|
|
||||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[15]
|
|
||||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[14]
|
|
||||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[13]
|
|
||||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[12]
|
|
||||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[11]
|
|
||||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[10]
|
|
||||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[9]
|
|
||||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[8]
|
|
||||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[7]
|
|
||||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[6]
|
|
||||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[5]
|
|
||||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[4]
|
|
||||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[3]
|
|
||||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[2]
|
|
||||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[1]
|
|
||||||
xr ^= c.p[0]
|
|
||||||
return xr, xl
|
|
||||||
}
|
|
|
@ -1,99 +0,0 @@
|
||||||
// Copyright 2010 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Package blowfish implements Bruce Schneier's Blowfish encryption algorithm.
|
|
||||||
//
|
|
||||||
// Blowfish is a legacy cipher and its short block size makes it vulnerable to
|
|
||||||
// birthday bound attacks (see https://sweet32.info). It should only be used
|
|
||||||
// where compatibility with legacy systems, not security, is the goal.
|
|
||||||
//
|
|
||||||
// Deprecated: any new system should use AES (from crypto/aes, if necessary in
|
|
||||||
// an AEAD mode like crypto/cipher.NewGCM) or XChaCha20-Poly1305 (from
|
|
||||||
// golang.org/x/crypto/chacha20poly1305).
|
|
||||||
package blowfish // import "golang.org/x/crypto/blowfish"
|
|
||||||
|
|
||||||
// The code is a port of Bruce Schneier's C implementation.
|
|
||||||
// See https://www.schneier.com/blowfish.html.
|
|
||||||
|
|
||||||
import "strconv"
|
|
||||||
|
|
||||||
// The Blowfish block size in bytes.
|
|
||||||
const BlockSize = 8
|
|
||||||
|
|
||||||
// A Cipher is an instance of Blowfish encryption using a particular key.
|
|
||||||
type Cipher struct {
|
|
||||||
p [18]uint32
|
|
||||||
s0, s1, s2, s3 [256]uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
type KeySizeError int
|
|
||||||
|
|
||||||
func (k KeySizeError) Error() string {
|
|
||||||
return "crypto/blowfish: invalid key size " + strconv.Itoa(int(k))
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewCipher creates and returns a Cipher.
|
|
||||||
// The key argument should be the Blowfish key, from 1 to 56 bytes.
|
|
||||||
func NewCipher(key []byte) (*Cipher, error) {
|
|
||||||
var result Cipher
|
|
||||||
if k := len(key); k < 1 || k > 56 {
|
|
||||||
return nil, KeySizeError(k)
|
|
||||||
}
|
|
||||||
initCipher(&result)
|
|
||||||
ExpandKey(key, &result)
|
|
||||||
return &result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewSaltedCipher creates a returns a Cipher that folds a salt into its key
|
|
||||||
// schedule. For most purposes, NewCipher, instead of NewSaltedCipher, is
|
|
||||||
// sufficient and desirable. For bcrypt compatibility, the key can be over 56
|
|
||||||
// bytes.
|
|
||||||
func NewSaltedCipher(key, salt []byte) (*Cipher, error) {
|
|
||||||
if len(salt) == 0 {
|
|
||||||
return NewCipher(key)
|
|
||||||
}
|
|
||||||
var result Cipher
|
|
||||||
if k := len(key); k < 1 {
|
|
||||||
return nil, KeySizeError(k)
|
|
||||||
}
|
|
||||||
initCipher(&result)
|
|
||||||
expandKeyWithSalt(key, salt, &result)
|
|
||||||
return &result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// BlockSize returns the Blowfish block size, 8 bytes.
|
|
||||||
// It is necessary to satisfy the Block interface in the
|
|
||||||
// package "crypto/cipher".
|
|
||||||
func (c *Cipher) BlockSize() int { return BlockSize }
|
|
||||||
|
|
||||||
// Encrypt encrypts the 8-byte buffer src using the key k
|
|
||||||
// and stores the result in dst.
|
|
||||||
// Note that for amounts of data larger than a block,
|
|
||||||
// it is not safe to just call Encrypt on successive blocks;
|
|
||||||
// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
|
|
||||||
func (c *Cipher) Encrypt(dst, src []byte) {
|
|
||||||
l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
|
|
||||||
r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
|
|
||||||
l, r = encryptBlock(l, r, c)
|
|
||||||
dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
|
|
||||||
dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decrypt decrypts the 8-byte buffer src using the key k
|
|
||||||
// and stores the result in dst.
|
|
||||||
func (c *Cipher) Decrypt(dst, src []byte) {
|
|
||||||
l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
|
|
||||||
r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
|
|
||||||
l, r = decryptBlock(l, r, c)
|
|
||||||
dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
|
|
||||||
dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func initCipher(c *Cipher) {
|
|
||||||
copy(c.p[0:], p[0:])
|
|
||||||
copy(c.s0[0:], s0[0:])
|
|
||||||
copy(c.s1[0:], s1[0:])
|
|
||||||
copy(c.s2[0:], s2[0:])
|
|
||||||
copy(c.s3[0:], s3[0:])
|
|
||||||
}
|
|
|
@ -1,199 +0,0 @@
|
||||||
// Copyright 2010 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// The startup permutation array and substitution boxes.
|
|
||||||
// They are the hexadecimal digits of PI; see:
|
|
||||||
// https://www.schneier.com/code/constants.txt.
|
|
||||||
|
|
||||||
package blowfish
|
|
||||||
|
|
||||||
var s0 = [256]uint32{
|
|
||||||
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96,
|
|
||||||
0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
|
|
||||||
0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658,
|
|
||||||
0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
|
|
||||||
0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e,
|
|
||||||
0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
|
|
||||||
0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6,
|
|
||||||
0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
|
|
||||||
0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c,
|
|
||||||
0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
|
|
||||||
0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1,
|
|
||||||
0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
|
|
||||||
0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a,
|
|
||||||
0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
|
|
||||||
0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176,
|
|
||||||
0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
|
|
||||||
0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706,
|
|
||||||
0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
|
|
||||||
0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b,
|
|
||||||
0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
|
|
||||||
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c,
|
|
||||||
0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
|
|
||||||
0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a,
|
|
||||||
0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
|
|
||||||
0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760,
|
|
||||||
0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
|
|
||||||
0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8,
|
|
||||||
0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
|
|
||||||
0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33,
|
|
||||||
0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
|
|
||||||
0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0,
|
|
||||||
0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
|
|
||||||
0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777,
|
|
||||||
0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
|
|
||||||
0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705,
|
|
||||||
0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
|
|
||||||
0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e,
|
|
||||||
0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
|
|
||||||
0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9,
|
|
||||||
0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
|
|
||||||
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f,
|
|
||||||
0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
|
|
||||||
0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
|
|
||||||
}
|
|
||||||
|
|
||||||
var s1 = [256]uint32{
|
|
||||||
0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d,
|
|
||||||
0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
|
|
||||||
0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65,
|
|
||||||
0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
|
|
||||||
0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9,
|
|
||||||
0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
|
|
||||||
0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d,
|
|
||||||
0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
|
|
||||||
0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc,
|
|
||||||
0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
|
|
||||||
0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908,
|
|
||||||
0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
|
|
||||||
0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124,
|
|
||||||
0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
|
|
||||||
0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908,
|
|
||||||
0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
|
|
||||||
0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b,
|
|
||||||
0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
|
|
||||||
0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa,
|
|
||||||
0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
|
|
||||||
0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d,
|
|
||||||
0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
|
|
||||||
0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5,
|
|
||||||
0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
|
|
||||||
0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96,
|
|
||||||
0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
|
|
||||||
0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca,
|
|
||||||
0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
|
|
||||||
0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77,
|
|
||||||
0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
|
|
||||||
0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054,
|
|
||||||
0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
|
|
||||||
0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea,
|
|
||||||
0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
|
|
||||||
0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646,
|
|
||||||
0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
|
|
||||||
0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea,
|
|
||||||
0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
|
|
||||||
0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e,
|
|
||||||
0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
|
|
||||||
0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd,
|
|
||||||
0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
|
|
||||||
0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
|
|
||||||
}
|
|
||||||
|
|
||||||
var s2 = [256]uint32{
|
|
||||||
0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7,
|
|
||||||
0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
|
|
||||||
0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af,
|
|
||||||
0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
|
|
||||||
0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4,
|
|
||||||
0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
|
|
||||||
0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec,
|
|
||||||
0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
|
|
||||||
0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332,
|
|
||||||
0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
|
|
||||||
0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58,
|
|
||||||
0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
|
|
||||||
0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22,
|
|
||||||
0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
|
|
||||||
0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60,
|
|
||||||
0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
|
|
||||||
0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99,
|
|
||||||
0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
|
|
||||||
0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74,
|
|
||||||
0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
|
|
||||||
0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3,
|
|
||||||
0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
|
|
||||||
0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979,
|
|
||||||
0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
|
|
||||||
0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa,
|
|
||||||
0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
|
|
||||||
0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086,
|
|
||||||
0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
|
|
||||||
0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24,
|
|
||||||
0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
|
|
||||||
0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84,
|
|
||||||
0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
|
|
||||||
0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09,
|
|
||||||
0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
|
|
||||||
0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe,
|
|
||||||
0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
|
|
||||||
0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0,
|
|
||||||
0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
|
|
||||||
0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188,
|
|
||||||
0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
|
|
||||||
0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8,
|
|
||||||
0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
|
|
||||||
0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
|
|
||||||
}
|
|
||||||
|
|
||||||
var s3 = [256]uint32{
|
|
||||||
0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742,
|
|
||||||
0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
|
|
||||||
0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79,
|
|
||||||
0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
|
|
||||||
0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a,
|
|
||||||
0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
|
|
||||||
0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1,
|
|
||||||
0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
|
|
||||||
0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797,
|
|
||||||
0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
|
|
||||||
0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6,
|
|
||||||
0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
|
|
||||||
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba,
|
|
||||||
0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
|
|
||||||
0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5,
|
|
||||||
0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
|
|
||||||
0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce,
|
|
||||||
0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
|
|
||||||
0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd,
|
|
||||||
0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
|
|
||||||
0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb,
|
|
||||||
0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
|
|
||||||
0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc,
|
|
||||||
0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
|
|
||||||
0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc,
|
|
||||||
0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
|
|
||||||
0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a,
|
|
||||||
0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
|
|
||||||
0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a,
|
|
||||||
0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
|
|
||||||
0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b,
|
|
||||||
0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
|
|
||||||
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e,
|
|
||||||
0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
|
|
||||||
0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623,
|
|
||||||
0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
|
|
||||||
0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a,
|
|
||||||
0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
|
|
||||||
0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3,
|
|
||||||
0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
|
|
||||||
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c,
|
|
||||||
0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
|
|
||||||
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6,
|
|
||||||
}
|
|
||||||
|
|
||||||
var p = [18]uint32{
|
|
||||||
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
|
|
||||||
0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
|
|
||||||
0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b,
|
|
||||||
}
|
|
|
@ -396,10 +396,10 @@ 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/transport/whisper/migrations
|
||||||
github.com/status-im/status-go/protocol/v1
|
github.com/status-im/status-go/protocol/v1
|
||||||
github.com/status-im/status-go/protocol/zaputil
|
github.com/status-im/status-go/protocol/zaputil
|
||||||
|
# github.com/status-im/status-go/whisper v1.0.0 => ./whisper
|
||||||
|
github.com/status-im/status-go/whisper
|
||||||
# github.com/status-im/tcp-shaker v0.0.0-20191114194237-215893130501
|
# github.com/status-im/tcp-shaker v0.0.0-20191114194237-215893130501
|
||||||
github.com/status-im/tcp-shaker
|
github.com/status-im/tcp-shaker
|
||||||
# github.com/status-im/whisper v1.6.2
|
|
||||||
github.com/status-im/whisper/whisperv6
|
|
||||||
# github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570
|
# github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570
|
||||||
github.com/steakknife/bloomfilter
|
github.com/steakknife/bloomfilter
|
||||||
# github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3
|
# github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3
|
||||||
|
|
|
@ -0,0 +1,604 @@
|
||||||
|
// Copyright 2016 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum 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 go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package whisper
|
||||||
|
|
||||||
|
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)")
|
||||||
|
)
|
||||||
|
|
||||||
|
// PublicWhisperAPI provides the whisper RPC service that can be
|
||||||
|
// use publicly without security implications.
|
||||||
|
type PublicWhisperAPI struct {
|
||||||
|
w *Whisper
|
||||||
|
|
||||||
|
mu sync.Mutex
|
||||||
|
lastUsed map[string]time.Time // keeps track when a filter was polled for the last time.
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPublicWhisperAPI create a new RPC whisper service.
|
||||||
|
func NewPublicWhisperAPI(w *Whisper) *PublicWhisperAPI {
|
||||||
|
api := &PublicWhisperAPI{
|
||||||
|
w: w,
|
||||||
|
lastUsed: make(map[string]time.Time),
|
||||||
|
}
|
||||||
|
return api
|
||||||
|
}
|
||||||
|
|
||||||
|
// Version returns the Whisper sub-protocol version.
|
||||||
|
func (api *PublicWhisperAPI) Version(ctx context.Context) string {
|
||||||
|
return ProtocolVersionStr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Info contains diagnostic information.
|
||||||
|
type Info struct {
|
||||||
|
Memory int `json:"memory"` // Memory size of the floating messages in bytes.
|
||||||
|
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 whisper node.
|
||||||
|
func (api *PublicWhisperAPI) Info(ctx context.Context) Info {
|
||||||
|
stats := api.w.Stats()
|
||||||
|
return Info{
|
||||||
|
Memory: stats.memoryUsed,
|
||||||
|
Messages: len(api.w.messageQueue) + 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 *PublicWhisperAPI) 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 *PublicWhisperAPI) SetMinPoW(ctx context.Context, pow float64) (bool, error) {
|
||||||
|
return true, api.w.SetMinimumPoW(pow)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetBloomFilter sets the new value of bloom filter, and notifies the peers.
|
||||||
|
func (api *PublicWhisperAPI) 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 *PublicWhisperAPI) 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 *PublicWhisperAPI) NewKeyPair(ctx context.Context) (string, error) {
|
||||||
|
return api.w.NewKeyPair()
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddPrivateKey imports the given private key.
|
||||||
|
func (api *PublicWhisperAPI) 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 *PublicWhisperAPI) 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 *PublicWhisperAPI) 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 *PublicWhisperAPI) 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 *PublicWhisperAPI) 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 *PublicWhisperAPI) 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 *PublicWhisperAPI) 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 *PublicWhisperAPI) 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 *PublicWhisperAPI) HasSymKey(ctx context.Context, id string) bool {
|
||||||
|
return api.w.HasSymKey(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSymKey returns the symmetric key associated with the given id.
|
||||||
|
func (api *PublicWhisperAPI) 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 *PublicWhisperAPI) 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 *PublicWhisperAPI) MakeLightClient(ctx context.Context) bool {
|
||||||
|
api.w.SetLightClientMode(true)
|
||||||
|
return api.w.LightClientMode()
|
||||||
|
}
|
||||||
|
|
||||||
|
// CancelLightClient cancels light client mode.
|
||||||
|
func (api *PublicWhisperAPI) 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 whisper 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 Whisper network.
|
||||||
|
// returns the hash of the message in case of success.
|
||||||
|
func (api *PublicWhisperAPI) 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
|
||||||
|
whisperMsg, err := NewSentMessage(params)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var result []byte
|
||||||
|
env, err := whisperMsg.Wrap(params, api.w.GetCurrentTime())
|
||||||
|
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.SendP2PMessage(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 *PublicWhisperAPI) UninstallFilter(id string) {
|
||||||
|
api.w.Unsubscribe(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unsubscribe disables and removes an existing filter.
|
||||||
|
func (api *PublicWhisperAPI) 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 *PublicWhisperAPI) 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: api.w.NewMessageStore(),
|
||||||
|
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 whisper 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
|
||||||
|
case <-notifier.Closed():
|
||||||
|
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 whisper 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToWhisperMessage converts an internal message into an API version.
|
||||||
|
func ToWhisperMessage(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] = ToWhisperMessage(msg)
|
||||||
|
}
|
||||||
|
return msgs
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetFilterMessages returns the messages that match the filter criteria and
|
||||||
|
// are received between the last poll and now.
|
||||||
|
func (api *PublicWhisperAPI) 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, ToWhisperMessage(msg))
|
||||||
|
}
|
||||||
|
|
||||||
|
return messages, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteMessageFilter deletes a filter.
|
||||||
|
func (api *PublicWhisperAPI) 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 *PublicWhisperAPI) 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: api.w.NewMessageStore(),
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
// Copyright 2018 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum 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 go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package whisper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMultipleTopicCopyInNewMessageFilter(t *testing.T) {
|
||||||
|
w := New(nil)
|
||||||
|
|
||||||
|
keyID, err := w.GenerateSymKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error generating symmetric key: %v", err)
|
||||||
|
}
|
||||||
|
api := PublicWhisperAPI{
|
||||||
|
w: w,
|
||||||
|
lastUsed: make(map[string]time.Time),
|
||||||
|
}
|
||||||
|
|
||||||
|
t1 := [4]byte{0xde, 0xea, 0xbe, 0xef}
|
||||||
|
t2 := [4]byte{0xca, 0xfe, 0xde, 0xca}
|
||||||
|
|
||||||
|
crit := Criteria{
|
||||||
|
SymKeyID: keyID,
|
||||||
|
Topics: []TopicType{TopicType(t1), TopicType(t2)},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = api.NewMessageFilter(crit)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error creating the filter: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
found := false
|
||||||
|
candidates := w.filters.getWatchersByTopic(TopicType(t1))
|
||||||
|
for _, f := range candidates {
|
||||||
|
if len(f.Topics) == 2 {
|
||||||
|
if bytes.Equal(f.Topics[0], t1[:]) && bytes.Equal(f.Topics[1], t2[:]) {
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
t.Fatalf("Could not find filter with both topics")
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,209 @@
|
||||||
|
// Copyright 2016 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum 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 go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package whisper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"golang.org/x/crypto/pbkdf2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func BenchmarkDeriveKeyMaterial(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
pbkdf2.Key([]byte("test"), nil, 65356, aesKeyLength, sha256.New)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkEncryptionSym(b *testing.B) {
|
||||||
|
InitSingleTest()
|
||||||
|
|
||||||
|
params, err := generateMessageParams()
|
||||||
|
if err != nil {
|
||||||
|
b.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
msg, _ := NewSentMessage(params)
|
||||||
|
_, err := msg.Wrap(params, time.Now())
|
||||||
|
if err != nil {
|
||||||
|
b.Errorf("failed Wrap with seed %d: %s.", seed, err)
|
||||||
|
b.Errorf("i = %d, len(msg.Raw) = %d, params.Payload = %d.", i, len(msg.Raw), len(params.Payload))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkEncryptionAsym(b *testing.B) {
|
||||||
|
InitSingleTest()
|
||||||
|
|
||||||
|
params, err := generateMessageParams()
|
||||||
|
if err != nil {
|
||||||
|
b.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
key, err := crypto.GenerateKey()
|
||||||
|
if err != nil {
|
||||||
|
b.Fatalf("failed GenerateKey with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
params.KeySym = nil
|
||||||
|
params.Dst = &key.PublicKey
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
msg, _ := NewSentMessage(params)
|
||||||
|
_, err := msg.Wrap(params, time.Now())
|
||||||
|
if err != nil {
|
||||||
|
b.Fatalf("failed Wrap with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkDecryptionSymValid(b *testing.B) {
|
||||||
|
InitSingleTest()
|
||||||
|
|
||||||
|
params, err := generateMessageParams()
|
||||||
|
if err != nil {
|
||||||
|
b.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
msg, _ := NewSentMessage(params)
|
||||||
|
env, err := msg.Wrap(params, time.Now())
|
||||||
|
if err != nil {
|
||||||
|
b.Fatalf("failed Wrap with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
f := Filter{KeySym: params.KeySym}
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
msg := env.Open(&f)
|
||||||
|
if msg == nil {
|
||||||
|
b.Fatalf("failed to open with seed %d.", seed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkDecryptionSymInvalid(b *testing.B) {
|
||||||
|
InitSingleTest()
|
||||||
|
|
||||||
|
params, err := generateMessageParams()
|
||||||
|
if err != nil {
|
||||||
|
b.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
msg, _ := NewSentMessage(params)
|
||||||
|
env, err := msg.Wrap(params, time.Now())
|
||||||
|
if err != nil {
|
||||||
|
b.Fatalf("failed Wrap with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
f := Filter{KeySym: []byte("arbitrary stuff here")}
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
msg := env.Open(&f)
|
||||||
|
if msg != nil {
|
||||||
|
b.Fatalf("opened envelope with invalid key, seed: %d.", seed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkDecryptionAsymValid(b *testing.B) {
|
||||||
|
InitSingleTest()
|
||||||
|
|
||||||
|
params, err := generateMessageParams()
|
||||||
|
if err != nil {
|
||||||
|
b.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
key, err := crypto.GenerateKey()
|
||||||
|
if err != nil {
|
||||||
|
b.Fatalf("failed GenerateKey with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
f := Filter{KeyAsym: key}
|
||||||
|
params.KeySym = nil
|
||||||
|
params.Dst = &key.PublicKey
|
||||||
|
msg, _ := NewSentMessage(params)
|
||||||
|
env, err := msg.Wrap(params, time.Now())
|
||||||
|
if err != nil {
|
||||||
|
b.Fatalf("failed Wrap with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
msg := env.Open(&f)
|
||||||
|
if msg == nil {
|
||||||
|
b.Fatalf("fail to open, seed: %d.", seed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkDecryptionAsymInvalid(b *testing.B) {
|
||||||
|
InitSingleTest()
|
||||||
|
|
||||||
|
params, err := generateMessageParams()
|
||||||
|
if err != nil {
|
||||||
|
b.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
key, err := crypto.GenerateKey()
|
||||||
|
if err != nil {
|
||||||
|
b.Fatalf("failed GenerateKey with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
params.KeySym = nil
|
||||||
|
params.Dst = &key.PublicKey
|
||||||
|
msg, _ := NewSentMessage(params)
|
||||||
|
env, err := msg.Wrap(params, time.Now())
|
||||||
|
if err != nil {
|
||||||
|
b.Fatalf("failed Wrap with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
key, err = crypto.GenerateKey()
|
||||||
|
if err != nil {
|
||||||
|
b.Fatalf("failed GenerateKey with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
f := Filter{KeyAsym: key}
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
msg := env.Open(&f)
|
||||||
|
if msg != nil {
|
||||||
|
b.Fatalf("opened envelope with invalid key, seed: %d.", seed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func increment(x []byte) {
|
||||||
|
for i := 0; i < len(x); i++ {
|
||||||
|
x[i]++
|
||||||
|
if x[i] != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkPoW(b *testing.B) {
|
||||||
|
InitSingleTest()
|
||||||
|
|
||||||
|
params, err := generateMessageParams()
|
||||||
|
if err != nil {
|
||||||
|
b.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
params.Payload = make([]byte, 32)
|
||||||
|
params.PoW = 10.0
|
||||||
|
params.TTL = 1
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
increment(params.Payload)
|
||||||
|
msg, _ := NewSentMessage(params)
|
||||||
|
_, err := msg.Wrap(params, time.Now())
|
||||||
|
if err != nil {
|
||||||
|
b.Fatalf("failed Wrap with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
// Copyright 2017 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum 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 go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package whisper
|
||||||
|
|
||||||
|
// Config represents the configuration state of a whisper node.
|
||||||
|
type Config struct {
|
||||||
|
MaxMessageSize uint32 `toml:",omitempty"`
|
||||||
|
MinimumAcceptedPOW float64 `toml:",omitempty"`
|
||||||
|
RestrictConnectionBetweenLightClients bool `toml:",omitempty"`
|
||||||
|
DisableConfirmations bool `toml:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultConfig represents (shocker!) the default configuration.
|
||||||
|
var DefaultConfig = Config{
|
||||||
|
MaxMessageSize: DefaultMaxMessageSize,
|
||||||
|
MinimumAcceptedPOW: DefaultMinimumPoW,
|
||||||
|
RestrictConnectionBetweenLightClients: true,
|
||||||
|
}
|
|
@ -0,0 +1,261 @@
|
||||||
|
// Copyright 2016 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum 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 go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
/*
|
||||||
|
Package whisper implements the Whisper protocol (version 6).
|
||||||
|
|
||||||
|
Whisper combines aspects of both DHTs and datagram messaging systems (e.g. UDP).
|
||||||
|
As such it may be likened and compared to both, not dissimilar to the
|
||||||
|
matter/energy duality (apologies to physicists for the blatant abuse of a
|
||||||
|
fundamental and beautiful natural principle).
|
||||||
|
|
||||||
|
Whisper is a pure identity-based messaging system. Whisper provides a low-level
|
||||||
|
(non-application-specific) but easily-accessible API without being based upon
|
||||||
|
or prejudiced by the low-level hardware attributes and characteristics,
|
||||||
|
particularly the notion of singular endpoints.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Contains the Whisper protocol constant definitions
|
||||||
|
|
||||||
|
package whisper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Whisper protocol parameters
|
||||||
|
const (
|
||||||
|
ProtocolVersion = uint64(6) // Protocol version number
|
||||||
|
ProtocolVersionStr = "6.0" // The same, as a string
|
||||||
|
ProtocolName = "shh" // Nickname of the protocol in geth
|
||||||
|
|
||||||
|
// whisper protocol message codes, according to EIP-627
|
||||||
|
statusCode = 0 // used by whisper protocol
|
||||||
|
messagesCode = 1 // normal whisper message
|
||||||
|
powRequirementCode = 2 // 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
|
||||||
|
p2pSyncRequestCode = 123 // used to sync envelopes between two mail servers
|
||||||
|
p2pSyncResponseCode = 124 // used to sync envelopes between two mail servers
|
||||||
|
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 directMessagesCode for delivery,
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// SyncMailRequest contains details which envelopes should be synced
|
||||||
|
// between Mail Servers.
|
||||||
|
type SyncMailRequest struct {
|
||||||
|
// Lower is a lower bound of time range for which messages are requested.
|
||||||
|
Lower uint32
|
||||||
|
// Upper is a lower bound of time range for which messages are requested.
|
||||||
|
Upper uint32
|
||||||
|
// Bloom is a bloom filter to filter envelopes.
|
||||||
|
Bloom []byte
|
||||||
|
// Limit is the max number of envelopes to return.
|
||||||
|
Limit uint32
|
||||||
|
// Cursor is used for pagination of the results.
|
||||||
|
Cursor []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate checks request's fields if they are valid.
|
||||||
|
func (r SyncMailRequest) Validate() error {
|
||||||
|
if r.Limit == 0 {
|
||||||
|
return errors.New("invalid 'Limit' value, expected value greater than 0")
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.Limit > MaxLimitInSyncMailRequest {
|
||||||
|
return fmt.Errorf("invalid 'Limit' value, expected value lower than %d", MaxLimitInSyncMailRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.Lower > r.Upper {
|
||||||
|
return errors.New("invalid 'Lower' value, can't be greater than 'Upper'")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SyncResponse is a struct representing a response sent to the peer
|
||||||
|
// asking for syncing archived envelopes.
|
||||||
|
type SyncResponse struct {
|
||||||
|
Envelopes []*Envelope
|
||||||
|
Cursor []byte
|
||||||
|
Final bool // if true it means all envelopes were processed
|
||||||
|
Error string
|
||||||
|
}
|
||||||
|
|
||||||
|
// RawSyncResponse is a struct representing a response sent to the peer
|
||||||
|
// asking for syncing archived envelopes.
|
||||||
|
type RawSyncResponse struct {
|
||||||
|
Envelopes []rlp.RawValue
|
||||||
|
Cursor []byte
|
||||||
|
Final bool // if true it means all envelopes were processed
|
||||||
|
Error string
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 instane 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(),
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
package whisper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSyncMailRequestValidate(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
Name string
|
||||||
|
Req SyncMailRequest
|
||||||
|
Error string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Name: "invalid zero Limit",
|
||||||
|
Req: SyncMailRequest{},
|
||||||
|
Error: "invalid 'Limit' value, expected value greater than 0",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "invalid large Limit",
|
||||||
|
Req: SyncMailRequest{Limit: 1e6},
|
||||||
|
Error: "invalid 'Limit' value, expected value lower than 1000",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "invalid Lower",
|
||||||
|
Req: SyncMailRequest{Limit: 10, Lower: 10, Upper: 5},
|
||||||
|
Error: "invalid 'Lower' value, can't be greater than 'Upper'",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.Name, func(t *testing.T) {
|
||||||
|
err := tc.Req.Validate()
|
||||||
|
if tc.Error != "" {
|
||||||
|
assert.EqualError(t, err, tc.Error)
|
||||||
|
} else {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEncodeDecodeVersionedResponse(t *testing.T) {
|
||||||
|
response := NewMessagesResponse(common.Hash{1}, []EnvelopeError{{Code: 1}})
|
||||||
|
bytes, err := rlp.EncodeToBytes(response)
|
||||||
|
require.NoError(t, err)
|
||||||
|
var mresponse MultiVersionResponse
|
||||||
|
require.NoError(t, rlp.DecodeBytes(bytes, &mresponse))
|
||||||
|
v1resp, err := mresponse.DecodeResponse1()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, response.Response.Hash, v1resp.Hash)
|
||||||
|
}
|
|
@ -0,0 +1,280 @@
|
||||||
|
// Copyright 2016 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum 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 go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
// Contains the Whisper protocol Envelope element.
|
||||||
|
|
||||||
|
package whisper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
gmath "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 Whisper
|
||||||
|
// 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 Whisper 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 Whisper 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 := gmath.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 := gmath.Log2(x)
|
||||||
|
bits = gmath.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
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEnvelope retrieves an envelope from the message queue by its hash.
|
||||||
|
// It returns nil if the envelope can not be found.
|
||||||
|
func (w *Whisper) GetEnvelope(hash common.Hash) *Envelope {
|
||||||
|
w.poolMu.RLock()
|
||||||
|
defer w.poolMu.RUnlock()
|
||||||
|
return w.envelopes[hash]
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
// Copyright 2017 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum 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 go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
// Contains the tests associated with the Whisper protocol Envelope object.
|
||||||
|
|
||||||
|
package whisper
|
||||||
|
|
||||||
|
import (
|
||||||
|
mrand "math/rand"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPoWCalculationsWithNoLeadingZeros(t *testing.T) {
|
||||||
|
e := Envelope{
|
||||||
|
TTL: 1,
|
||||||
|
Data: []byte{0xde, 0xad, 0xbe, 0xef},
|
||||||
|
Nonce: 100000,
|
||||||
|
}
|
||||||
|
|
||||||
|
e.calculatePoW(0)
|
||||||
|
|
||||||
|
if e.pow != 0.07692307692307693 {
|
||||||
|
t.Fatalf("invalid PoW calculation. Expected 0.07692307692307693, got %v", e.pow)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPoWCalculationsWith8LeadingZeros(t *testing.T) {
|
||||||
|
e := Envelope{
|
||||||
|
TTL: 1,
|
||||||
|
Data: []byte{0xde, 0xad, 0xbe, 0xef},
|
||||||
|
Nonce: 276,
|
||||||
|
}
|
||||||
|
e.calculatePoW(0)
|
||||||
|
|
||||||
|
if e.pow != 19.692307692307693 {
|
||||||
|
t.Fatalf("invalid PoW calculation. Expected 19.692307692307693, got %v", e.pow)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEnvelopeOpenAcceptsOnlyOneKeyTypeInFilter(t *testing.T) {
|
||||||
|
symKey := make([]byte, aesKeyLength)
|
||||||
|
mrand.Read(symKey)
|
||||||
|
|
||||||
|
asymKey, err := crypto.GenerateKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed GenerateKey with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
params := MessageParams{
|
||||||
|
PoW: 0.01,
|
||||||
|
WorkTime: 1,
|
||||||
|
TTL: uint32(mrand.Intn(1024)),
|
||||||
|
Payload: make([]byte, 50),
|
||||||
|
KeySym: symKey,
|
||||||
|
Dst: nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
mrand.Read(params.Payload)
|
||||||
|
|
||||||
|
msg, err := NewSentMessage(¶ms)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
e, err := msg.Wrap(¶ms, time.Now())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to Wrap the message in an envelope with seed %d: %s", seed, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
f := Filter{KeySym: symKey, KeyAsym: asymKey}
|
||||||
|
|
||||||
|
decrypted := e.Open(&f)
|
||||||
|
if decrypted != nil {
|
||||||
|
t.Fatalf("Managed to decrypt a message with an invalid filter, seed %d", seed)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
package whisper
|
||||||
|
|
||||||
|
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
|
||||||
|
Hash common.Hash
|
||||||
|
Batch common.Hash
|
||||||
|
Peer enode.ID
|
||||||
|
Data interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SyncEventResponse is a response from the Mail Server
|
||||||
|
// form which the peer received envelopes.
|
||||||
|
type SyncEventResponse struct {
|
||||||
|
Cursor []byte
|
||||||
|
Error string
|
||||||
|
}
|
|
@ -0,0 +1,294 @@
|
||||||
|
// Copyright 2016 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum 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 go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package whisper
|
||||||
|
|
||||||
|
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 Whisper 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 Whisper 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
|
||||||
|
|
||||||
|
whisper *Whisper
|
||||||
|
mutex sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFilters returns a newly created filter collection
|
||||||
|
func NewFilters(w *Whisper) *Filters {
|
||||||
|
return &Filters{
|
||||||
|
watchers: make(map[string]*Filter),
|
||||||
|
topicMatcher: make(map[TopicType]map[*Filter]struct{}),
|
||||||
|
allTopicsMatcher: make(map[*Filter]struct{}),
|
||||||
|
whisper: 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
|
||||||
|
}
|
|
@ -0,0 +1,831 @@
|
||||||
|
// Copyright 2016 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum 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 go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package whisper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
mrand "math/rand"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
)
|
||||||
|
|
||||||
|
var seed int64
|
||||||
|
|
||||||
|
// InitSingleTest should be called in the beginning of every
|
||||||
|
// test, which uses RNG, in order to make the tests
|
||||||
|
// reproduciblity independent of their sequence.
|
||||||
|
func InitSingleTest() {
|
||||||
|
seed = time.Now().Unix()
|
||||||
|
mrand.Seed(seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
func InitDebugTest(i int64) {
|
||||||
|
seed = i
|
||||||
|
mrand.Seed(seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
type FilterTestCase struct {
|
||||||
|
f *Filter
|
||||||
|
id string
|
||||||
|
alive bool
|
||||||
|
msgCnt int
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateFilter(t *testing.T, symmetric bool) (*Filter, error) {
|
||||||
|
var f Filter
|
||||||
|
f.Messages = NewMemoryMessageStore()
|
||||||
|
|
||||||
|
const topicNum = 8
|
||||||
|
f.Topics = make([][]byte, topicNum)
|
||||||
|
for i := 0; i < topicNum; i++ {
|
||||||
|
f.Topics[i] = make([]byte, 4)
|
||||||
|
mrand.Read(f.Topics[i])
|
||||||
|
f.Topics[i][0] = 0x01
|
||||||
|
}
|
||||||
|
|
||||||
|
key, err := crypto.GenerateKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("generateFilter 1 failed with seed %d.", seed)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
f.Src = &key.PublicKey
|
||||||
|
|
||||||
|
if symmetric {
|
||||||
|
f.KeySym = make([]byte, aesKeyLength)
|
||||||
|
mrand.Read(f.KeySym)
|
||||||
|
f.SymKeyHash = crypto.Keccak256Hash(f.KeySym)
|
||||||
|
} else {
|
||||||
|
f.KeyAsym, err = crypto.GenerateKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("generateFilter 2 failed with seed %d.", seed)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AcceptP2P & PoW are not set
|
||||||
|
return &f, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateTestCases(t *testing.T, SizeTestFilters int) []FilterTestCase {
|
||||||
|
cases := make([]FilterTestCase, SizeTestFilters)
|
||||||
|
for i := 0; i < SizeTestFilters; i++ {
|
||||||
|
f, _ := generateFilter(t, true)
|
||||||
|
cases[i].f = f
|
||||||
|
cases[i].alive = mrand.Int()&int(1) == 0
|
||||||
|
}
|
||||||
|
return cases
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInstallFilters(t *testing.T) {
|
||||||
|
InitSingleTest()
|
||||||
|
|
||||||
|
const SizeTestFilters = 256
|
||||||
|
w := New(&Config{})
|
||||||
|
filters := NewFilters(w)
|
||||||
|
tst := generateTestCases(t, SizeTestFilters)
|
||||||
|
|
||||||
|
var err error
|
||||||
|
var j string
|
||||||
|
for i := 0; i < SizeTestFilters; i++ {
|
||||||
|
j, err = filters.Install(tst[i].f)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("seed %d: failed to install filter: %s", seed, err)
|
||||||
|
}
|
||||||
|
tst[i].id = j
|
||||||
|
if len(j) != keyIDSize*2 {
|
||||||
|
t.Fatalf("seed %d: wrong filter id size [%d]", seed, len(j))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range tst {
|
||||||
|
if !testCase.alive {
|
||||||
|
filters.Uninstall(testCase.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, testCase := range tst {
|
||||||
|
fil := filters.Get(testCase.id)
|
||||||
|
exist := fil != nil
|
||||||
|
if exist != testCase.alive {
|
||||||
|
t.Fatalf("seed %d: failed alive: %d, %v, %v", seed, i, exist, testCase.alive)
|
||||||
|
}
|
||||||
|
if exist && fil.PoW != testCase.f.PoW {
|
||||||
|
t.Fatalf("seed %d: failed Get: %d, %v, %v", seed, i, exist, testCase.alive)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInstallSymKeyGeneratesHash(t *testing.T) {
|
||||||
|
InitSingleTest()
|
||||||
|
|
||||||
|
w := New(&Config{})
|
||||||
|
filters := NewFilters(w)
|
||||||
|
filter, _ := generateFilter(t, true)
|
||||||
|
|
||||||
|
// save the current SymKeyHash for comparison
|
||||||
|
initialSymKeyHash := filter.SymKeyHash
|
||||||
|
|
||||||
|
// ensure the SymKeyHash is invalid, for Install to recreate it
|
||||||
|
var invalid common.Hash
|
||||||
|
filter.SymKeyHash = invalid
|
||||||
|
|
||||||
|
_, err := filters.Install(filter)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error installing the filter: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, b := range filter.SymKeyHash {
|
||||||
|
if b != initialSymKeyHash[i] {
|
||||||
|
t.Fatalf("The filter's symmetric key hash was not properly generated by Install")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInstallIdenticalFilters(t *testing.T) {
|
||||||
|
InitSingleTest()
|
||||||
|
|
||||||
|
w := New(&Config{})
|
||||||
|
filters := NewFilters(w)
|
||||||
|
filter1, _ := generateFilter(t, true)
|
||||||
|
|
||||||
|
// Copy the first filter since some of its fields
|
||||||
|
// are randomly gnerated.
|
||||||
|
filter2 := &Filter{
|
||||||
|
KeySym: filter1.KeySym,
|
||||||
|
Topics: filter1.Topics,
|
||||||
|
PoW: filter1.PoW,
|
||||||
|
AllowP2P: filter1.AllowP2P,
|
||||||
|
Messages: NewMemoryMessageStore(),
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := filters.Install(filter1)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error installing the first filter with seed %d: %s", seed, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = filters.Install(filter2)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error installing the second filter with seed %d: %s", seed, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
params, err := generateMessageParams()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error generating message parameters with seed %d: %s", seed, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
params.KeySym = filter1.KeySym
|
||||||
|
params.Topic = BytesToTopic(filter1.Topics[0])
|
||||||
|
|
||||||
|
filter1.Src = ¶ms.Src.PublicKey
|
||||||
|
filter2.Src = ¶ms.Src.PublicKey
|
||||||
|
|
||||||
|
sentMessage, err := NewSentMessage(params)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
env, err := sentMessage.Wrap(params, time.Now())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed Wrap with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
msg := env.Open(filter1)
|
||||||
|
if msg == nil {
|
||||||
|
t.Fatalf("failed to Open with filter1")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !filter1.MatchEnvelope(env) {
|
||||||
|
t.Fatalf("failed matching with the first filter")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !filter2.MatchEnvelope(env) {
|
||||||
|
t.Fatalf("failed matching with the first filter")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !filter1.MatchMessage(msg) {
|
||||||
|
t.Fatalf("failed matching with the second filter")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !filter2.MatchMessage(msg) {
|
||||||
|
t.Fatalf("failed matching with the second filter")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInstallFilterWithSymAndAsymKeys(t *testing.T) {
|
||||||
|
InitSingleTest()
|
||||||
|
|
||||||
|
w := New(&Config{})
|
||||||
|
filters := NewFilters(w)
|
||||||
|
filter1, _ := generateFilter(t, true)
|
||||||
|
|
||||||
|
asymKey, err := crypto.GenerateKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unable to create asymetric keys: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the first filter since some of its fields
|
||||||
|
// are randomly gnerated.
|
||||||
|
filter := &Filter{
|
||||||
|
KeySym: filter1.KeySym,
|
||||||
|
KeyAsym: asymKey,
|
||||||
|
Topics: filter1.Topics,
|
||||||
|
PoW: filter1.PoW,
|
||||||
|
AllowP2P: filter1.AllowP2P,
|
||||||
|
Messages: NewMemoryMessageStore(),
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = filters.Install(filter)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("Error detecting that a filter had both an asymmetric and symmetric key, with seed %d", seed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestComparePubKey(t *testing.T) {
|
||||||
|
InitSingleTest()
|
||||||
|
|
||||||
|
key1, err := crypto.GenerateKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to generate first key with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
key2, err := crypto.GenerateKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to generate second key with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
if IsPubKeyEqual(&key1.PublicKey, &key2.PublicKey) {
|
||||||
|
t.Fatalf("public keys are equal, seed %d.", seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate key3 == key1
|
||||||
|
mrand.Seed(seed)
|
||||||
|
key3, err := crypto.GenerateKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to generate third key with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
if IsPubKeyEqual(&key1.PublicKey, &key3.PublicKey) {
|
||||||
|
t.Fatalf("key1 == key3, seed %d.", seed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMatchEnvelope(t *testing.T) {
|
||||||
|
InitSingleTest()
|
||||||
|
|
||||||
|
fsym, err := generateFilter(t, true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed generateFilter with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fasym, err := generateFilter(t, false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed generateFilter() with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
params, err := generateMessageParams()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
params.Topic[0] = 0xFF // topic mismatch
|
||||||
|
|
||||||
|
msg, err := NewSentMessage(params)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
env, err := msg.Wrap(params, time.Now())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed Wrap with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// encrypt symmetrically
|
||||||
|
i := mrand.Int() % 4
|
||||||
|
fsym.Topics[i] = params.Topic[:]
|
||||||
|
fasym.Topics[i] = params.Topic[:]
|
||||||
|
msg, err = NewSentMessage(params)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
env, err = msg.Wrap(params, time.Now())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed Wrap() with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// symmetric + matching topic: match
|
||||||
|
match := fsym.MatchEnvelope(env)
|
||||||
|
if !match {
|
||||||
|
t.Fatalf("failed MatchEnvelope() symmetric with seed %d.", seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
// symmetric + matching topic + insufficient PoW: mismatch
|
||||||
|
fsym.PoW = env.PoW() + 1.0
|
||||||
|
match = fsym.MatchEnvelope(env)
|
||||||
|
if match {
|
||||||
|
t.Fatalf("failed MatchEnvelope(symmetric + matching topic + insufficient PoW) asymmetric with seed %d.", seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
// symmetric + matching topic + sufficient PoW: match
|
||||||
|
fsym.PoW = env.PoW() / 2
|
||||||
|
match = fsym.MatchEnvelope(env)
|
||||||
|
if !match {
|
||||||
|
t.Fatalf("failed MatchEnvelope(symmetric + matching topic + sufficient PoW) with seed %d.", seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
// symmetric + topics are nil (wildcard): match
|
||||||
|
prevTopics := fsym.Topics
|
||||||
|
fsym.Topics = nil
|
||||||
|
match = fsym.MatchEnvelope(env)
|
||||||
|
if !match {
|
||||||
|
t.Fatalf("failed MatchEnvelope(symmetric + topics are nil) with seed %d.", seed)
|
||||||
|
}
|
||||||
|
fsym.Topics = prevTopics
|
||||||
|
|
||||||
|
// encrypt asymmetrically
|
||||||
|
key, err := crypto.GenerateKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed GenerateKey with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
params.KeySym = nil
|
||||||
|
params.Dst = &key.PublicKey
|
||||||
|
msg, err = NewSentMessage(params)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
env, err = msg.Wrap(params, time.Now())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed Wrap() with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// encryption method mismatch
|
||||||
|
match = fsym.MatchEnvelope(env)
|
||||||
|
if match {
|
||||||
|
t.Fatalf("failed MatchEnvelope(encryption method mismatch) with seed %d.", seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
// asymmetric + mismatching topic: mismatch
|
||||||
|
match = fasym.MatchEnvelope(env)
|
||||||
|
if !match {
|
||||||
|
t.Fatalf("failed MatchEnvelope(asymmetric + mismatching topic) with seed %d.", seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
// asymmetric + matching topic: match
|
||||||
|
fasym.Topics[i] = fasym.Topics[i+1]
|
||||||
|
match = fasym.MatchEnvelope(env)
|
||||||
|
if !match {
|
||||||
|
t.Fatalf("failed MatchEnvelope(asymmetric + matching topic) with seed %d.", seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
// asymmetric + filter without topic (wildcard): match
|
||||||
|
fasym.Topics = nil
|
||||||
|
match = fasym.MatchEnvelope(env)
|
||||||
|
if !match {
|
||||||
|
t.Fatalf("failed MatchEnvelope(asymmetric + filter without topic) with seed %d.", seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
// asymmetric + insufficient PoW: mismatch
|
||||||
|
fasym.PoW = env.PoW() + 1.0
|
||||||
|
match = fasym.MatchEnvelope(env)
|
||||||
|
if match {
|
||||||
|
t.Fatalf("failed MatchEnvelope(asymmetric + insufficient PoW) with seed %d.", seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
// asymmetric + sufficient PoW: match
|
||||||
|
fasym.PoW = env.PoW() / 2
|
||||||
|
match = fasym.MatchEnvelope(env)
|
||||||
|
if !match {
|
||||||
|
t.Fatalf("failed MatchEnvelope(asymmetric + sufficient PoW) with seed %d.", seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
// filter without topic + envelope without topic: match
|
||||||
|
env.Topic = TopicType{}
|
||||||
|
match = fasym.MatchEnvelope(env)
|
||||||
|
if !match {
|
||||||
|
t.Fatalf("failed MatchEnvelope(filter without topic + envelope without topic) with seed %d.", seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
// filter with topic + envelope without topic: mismatch
|
||||||
|
fasym.Topics = fsym.Topics
|
||||||
|
match = fasym.MatchEnvelope(env)
|
||||||
|
if !match {
|
||||||
|
// topic mismatch should have no affect, as topics are handled by topic matchers
|
||||||
|
t.Fatalf("failed MatchEnvelope(filter without topic + envelope without topic) with seed %d.", seed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMatchMessageSym(t *testing.T) {
|
||||||
|
InitSingleTest()
|
||||||
|
|
||||||
|
params, err := generateMessageParams()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := generateFilter(t, true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed generateFilter with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
const index = 1
|
||||||
|
params.KeySym = f.KeySym
|
||||||
|
params.Topic = BytesToTopic(f.Topics[index])
|
||||||
|
|
||||||
|
sentMessage, err := NewSentMessage(params)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
env, err := sentMessage.Wrap(params, time.Now())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed Wrap with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
msg := env.Open(f)
|
||||||
|
if msg == nil {
|
||||||
|
t.Fatalf("failed Open with seed %d.", seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Src: match
|
||||||
|
*f.Src.X = *params.Src.PublicKey.X
|
||||||
|
*f.Src.Y = *params.Src.PublicKey.Y
|
||||||
|
if !f.MatchMessage(msg) {
|
||||||
|
t.Fatalf("failed MatchEnvelope(src match) with seed %d.", seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
// insufficient PoW: mismatch
|
||||||
|
f.PoW = msg.PoW + 1.0
|
||||||
|
if f.MatchMessage(msg) {
|
||||||
|
t.Fatalf("failed MatchEnvelope(insufficient PoW) with seed %d.", seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
// sufficient PoW: match
|
||||||
|
f.PoW = msg.PoW / 2
|
||||||
|
if !f.MatchMessage(msg) {
|
||||||
|
t.Fatalf("failed MatchEnvelope(sufficient PoW) with seed %d.", seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
// topic mismatch
|
||||||
|
f.Topics[index][0]++
|
||||||
|
if !f.MatchMessage(msg) {
|
||||||
|
// topic mismatch should have no affect, as topics are handled by topic matchers
|
||||||
|
t.Fatalf("failed MatchEnvelope(topic mismatch) with seed %d.", seed)
|
||||||
|
}
|
||||||
|
f.Topics[index][0]--
|
||||||
|
|
||||||
|
// key mismatch
|
||||||
|
f.SymKeyHash[0]++
|
||||||
|
if f.MatchMessage(msg) {
|
||||||
|
t.Fatalf("failed MatchEnvelope(key mismatch) with seed %d.", seed)
|
||||||
|
}
|
||||||
|
f.SymKeyHash[0]--
|
||||||
|
|
||||||
|
// Src absent: match
|
||||||
|
f.Src = nil
|
||||||
|
if !f.MatchMessage(msg) {
|
||||||
|
t.Fatalf("failed MatchEnvelope(src absent) with seed %d.", seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
// key hash mismatch
|
||||||
|
h := f.SymKeyHash
|
||||||
|
f.SymKeyHash = common.Hash{}
|
||||||
|
if f.MatchMessage(msg) {
|
||||||
|
t.Fatalf("failed MatchEnvelope(key hash mismatch) with seed %d.", seed)
|
||||||
|
}
|
||||||
|
f.SymKeyHash = h
|
||||||
|
if !f.MatchMessage(msg) {
|
||||||
|
t.Fatalf("failed MatchEnvelope(key hash match) with seed %d.", seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
// encryption method mismatch
|
||||||
|
f.KeySym = nil
|
||||||
|
f.KeyAsym, err = crypto.GenerateKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed GenerateKey with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
if f.MatchMessage(msg) {
|
||||||
|
t.Fatalf("failed MatchEnvelope(encryption method mismatch) with seed %d.", seed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMatchMessageAsym(t *testing.T) {
|
||||||
|
InitSingleTest()
|
||||||
|
|
||||||
|
f, err := generateFilter(t, false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed generateFilter with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
params, err := generateMessageParams()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
const index = 1
|
||||||
|
params.Topic = BytesToTopic(f.Topics[index])
|
||||||
|
params.Dst = &f.KeyAsym.PublicKey
|
||||||
|
keySymOrig := params.KeySym
|
||||||
|
params.KeySym = nil
|
||||||
|
|
||||||
|
sentMessage, err := NewSentMessage(params)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
env, err := sentMessage.Wrap(params, time.Now())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed Wrap with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
msg := env.Open(f)
|
||||||
|
if msg == nil {
|
||||||
|
t.Fatalf("failed to open with seed %d.", seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Src: match
|
||||||
|
*f.Src.X = *params.Src.PublicKey.X
|
||||||
|
*f.Src.Y = *params.Src.PublicKey.Y
|
||||||
|
if !f.MatchMessage(msg) {
|
||||||
|
t.Fatalf("failed MatchMessage(src match) with seed %d.", seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
// insufficient PoW: mismatch
|
||||||
|
f.PoW = msg.PoW + 1.0
|
||||||
|
if f.MatchMessage(msg) {
|
||||||
|
t.Fatalf("failed MatchEnvelope(insufficient PoW) with seed %d.", seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
// sufficient PoW: match
|
||||||
|
f.PoW = msg.PoW / 2
|
||||||
|
if !f.MatchMessage(msg) {
|
||||||
|
t.Fatalf("failed MatchEnvelope(sufficient PoW) with seed %d.", seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
// topic mismatch
|
||||||
|
f.Topics[index][0]++
|
||||||
|
if !f.MatchMessage(msg) {
|
||||||
|
// topic mismatch should have no affect, as topics are handled by topic matchers
|
||||||
|
t.Fatalf("failed MatchEnvelope(topic mismatch) with seed %d.", seed)
|
||||||
|
}
|
||||||
|
f.Topics[index][0]--
|
||||||
|
|
||||||
|
// key mismatch
|
||||||
|
prev := *f.KeyAsym.PublicKey.X
|
||||||
|
zero := *big.NewInt(0)
|
||||||
|
*f.KeyAsym.PublicKey.X = zero
|
||||||
|
if f.MatchMessage(msg) {
|
||||||
|
t.Fatalf("failed MatchEnvelope(key mismatch) with seed %d.", seed)
|
||||||
|
}
|
||||||
|
*f.KeyAsym.PublicKey.X = prev
|
||||||
|
|
||||||
|
// Src absent: match
|
||||||
|
f.Src = nil
|
||||||
|
if !f.MatchMessage(msg) {
|
||||||
|
t.Fatalf("failed MatchEnvelope(src absent) with seed %d.", seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
// encryption method mismatch
|
||||||
|
f.KeySym = keySymOrig
|
||||||
|
f.KeyAsym = nil
|
||||||
|
if f.MatchMessage(msg) {
|
||||||
|
t.Fatalf("failed MatchEnvelope(encryption method mismatch) with seed %d.", seed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cloneFilter(orig *Filter) *Filter {
|
||||||
|
var clone Filter
|
||||||
|
clone.Messages = NewMemoryMessageStore()
|
||||||
|
clone.Src = orig.Src
|
||||||
|
clone.KeyAsym = orig.KeyAsym
|
||||||
|
clone.KeySym = orig.KeySym
|
||||||
|
clone.Topics = orig.Topics
|
||||||
|
clone.PoW = orig.PoW
|
||||||
|
clone.AllowP2P = orig.AllowP2P
|
||||||
|
clone.SymKeyHash = orig.SymKeyHash
|
||||||
|
return &clone
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateCompatibeEnvelope(t *testing.T, f *Filter) *Envelope {
|
||||||
|
params, err := generateMessageParams()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
params.KeySym = f.KeySym
|
||||||
|
params.Topic = BytesToTopic(f.Topics[2])
|
||||||
|
sentMessage, err := NewSentMessage(params)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
env, err := sentMessage.Wrap(params, time.Now())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed Wrap with seed %d: %s.", seed, err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return env
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWatchers(t *testing.T) {
|
||||||
|
InitSingleTest()
|
||||||
|
|
||||||
|
const NumFilters = 16
|
||||||
|
const NumMessages = 256
|
||||||
|
var i int
|
||||||
|
var j uint32
|
||||||
|
var e *Envelope
|
||||||
|
var x, firstID string
|
||||||
|
var err error
|
||||||
|
|
||||||
|
w := New(&Config{})
|
||||||
|
filters := NewFilters(w)
|
||||||
|
tst := generateTestCases(t, NumFilters)
|
||||||
|
for i = 0; i < NumFilters; i++ {
|
||||||
|
tst[i].f.Src = nil
|
||||||
|
x, err = filters.Install(tst[i].f)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to install filter with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
tst[i].id = x
|
||||||
|
if len(firstID) == 0 {
|
||||||
|
firstID = x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lastID := x
|
||||||
|
|
||||||
|
var envelopes [NumMessages]*Envelope
|
||||||
|
for i = 0; i < NumMessages; i++ {
|
||||||
|
j = mrand.Uint32() % NumFilters
|
||||||
|
e = generateCompatibeEnvelope(t, tst[j].f)
|
||||||
|
envelopes[i] = e
|
||||||
|
tst[j].msgCnt++
|
||||||
|
}
|
||||||
|
|
||||||
|
for i = 0; i < NumMessages; i++ {
|
||||||
|
filters.NotifyWatchers(envelopes[i], false)
|
||||||
|
}
|
||||||
|
|
||||||
|
var total int
|
||||||
|
var mail []*ReceivedMessage
|
||||||
|
var count [NumFilters]int
|
||||||
|
|
||||||
|
for i = 0; i < NumFilters; i++ {
|
||||||
|
mail = tst[i].f.Retrieve()
|
||||||
|
count[i] = len(mail)
|
||||||
|
total += len(mail)
|
||||||
|
}
|
||||||
|
|
||||||
|
if total != NumMessages {
|
||||||
|
t.Fatalf("failed with seed %d: total = %d, want: %d.", seed, total, NumMessages)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i = 0; i < NumFilters; i++ {
|
||||||
|
mail = tst[i].f.Retrieve()
|
||||||
|
if len(mail) != 0 {
|
||||||
|
t.Fatalf("failed with seed %d: i = %d.", seed, i)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tst[i].msgCnt != count[i] {
|
||||||
|
t.Fatalf("failed with seed %d: count[%d]: get %d, want %d.", seed, i, tst[i].msgCnt, count[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// another round with a cloned filter
|
||||||
|
|
||||||
|
clone := cloneFilter(tst[0].f)
|
||||||
|
filters.Uninstall(lastID)
|
||||||
|
total = 0
|
||||||
|
last := NumFilters - 1
|
||||||
|
tst[last].f = clone
|
||||||
|
filters.Install(clone)
|
||||||
|
for i = 0; i < NumFilters; i++ {
|
||||||
|
tst[i].msgCnt = 0
|
||||||
|
count[i] = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure that the first watcher receives at least one message
|
||||||
|
e = generateCompatibeEnvelope(t, tst[0].f)
|
||||||
|
envelopes[0] = e
|
||||||
|
tst[0].msgCnt++
|
||||||
|
for i = 1; i < NumMessages; i++ {
|
||||||
|
j = mrand.Uint32() % NumFilters
|
||||||
|
e = generateCompatibeEnvelope(t, tst[j].f)
|
||||||
|
envelopes[i] = e
|
||||||
|
tst[j].msgCnt++
|
||||||
|
}
|
||||||
|
|
||||||
|
for i = 0; i < NumMessages; i++ {
|
||||||
|
filters.NotifyWatchers(envelopes[i], false)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i = 0; i < NumFilters; i++ {
|
||||||
|
mail = tst[i].f.Retrieve()
|
||||||
|
count[i] = len(mail)
|
||||||
|
total += len(mail)
|
||||||
|
}
|
||||||
|
|
||||||
|
combined := tst[0].msgCnt + tst[last].msgCnt
|
||||||
|
if total != NumMessages+count[0] {
|
||||||
|
t.Fatalf("failed with seed %d: total = %d, count[0] = %d.", seed, total, count[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
if combined != count[0] {
|
||||||
|
t.Fatalf("failed with seed %d: combined = %d, count[0] = %d.", seed, combined, count[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
if combined != count[last] {
|
||||||
|
t.Fatalf("failed with seed %d: combined = %d, count[last] = %d.", seed, combined, count[last])
|
||||||
|
}
|
||||||
|
|
||||||
|
for i = 1; i < NumFilters-1; i++ {
|
||||||
|
mail = tst[i].f.Retrieve()
|
||||||
|
if len(mail) != 0 {
|
||||||
|
t.Fatalf("failed with seed %d: i = %d.", seed, i)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tst[i].msgCnt != count[i] {
|
||||||
|
t.Fatalf("failed with seed %d: i = %d, get %d, want %d.", seed, i, tst[i].msgCnt, count[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// test AcceptP2P
|
||||||
|
|
||||||
|
total = 0
|
||||||
|
filters.NotifyWatchers(envelopes[0], true)
|
||||||
|
|
||||||
|
for i = 0; i < NumFilters; i++ {
|
||||||
|
mail = tst[i].f.Retrieve()
|
||||||
|
total += len(mail)
|
||||||
|
}
|
||||||
|
|
||||||
|
if total != 0 {
|
||||||
|
t.Fatalf("failed with seed %d: total: got %d, want 0.", seed, total)
|
||||||
|
}
|
||||||
|
|
||||||
|
f := filters.Get(firstID)
|
||||||
|
if f == nil {
|
||||||
|
t.Fatalf("failed to get the filter with seed %d.", seed)
|
||||||
|
}
|
||||||
|
f.AllowP2P = true
|
||||||
|
total = 0
|
||||||
|
filters.NotifyWatchers(envelopes[0], true)
|
||||||
|
|
||||||
|
for i = 0; i < NumFilters; i++ {
|
||||||
|
mail = tst[i].f.Retrieve()
|
||||||
|
total += len(mail)
|
||||||
|
}
|
||||||
|
|
||||||
|
if total != 1 {
|
||||||
|
t.Fatalf("failed with seed %d: total: got %d, want 1.", seed, total)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVariableTopics(t *testing.T) {
|
||||||
|
InitSingleTest()
|
||||||
|
|
||||||
|
const lastTopicByte = 3
|
||||||
|
var match bool
|
||||||
|
params, err := generateMessageParams()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
msg, err := NewSentMessage(params)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
env, err := msg.Wrap(params, time.Now())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed Wrap with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := generateFilter(t, true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed generateFilter with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
env.Topic = BytesToTopic(f.Topics[i])
|
||||||
|
match = f.MatchEnvelope(env)
|
||||||
|
if !match {
|
||||||
|
t.Fatalf("failed MatchEnvelope symmetric with seed %d, step %d.", seed, i)
|
||||||
|
}
|
||||||
|
|
||||||
|
f.Topics[i][lastTopicByte]++
|
||||||
|
match = f.MatchEnvelope(env)
|
||||||
|
if !match {
|
||||||
|
// topic mismatch should have no affect, as topics are handled by topic matchers
|
||||||
|
t.Fatalf("MatchEnvelope symmetric with seed %d, step %d.", seed, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package whisper
|
||||||
|
|
||||||
|
func Fuzz(data []byte) int {
|
||||||
|
if len(data) < 2 {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := &ReceivedMessage{Raw: data}
|
||||||
|
msg.ValidateAndParse()
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
|
||||||
|
|
||||||
|
package whisper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = (*criteriaOverride)(nil)
|
||||||
|
|
||||||
|
// MarshalJSON marshals type Criteria to a json string
|
||||||
|
func (c Criteria) MarshalJSON() ([]byte, error) {
|
||||||
|
type Criteria struct {
|
||||||
|
SymKeyID string `json:"symKeyID"`
|
||||||
|
PrivateKeyID string `json:"privateKeyID"`
|
||||||
|
Sig hexutil.Bytes `json:"sig"`
|
||||||
|
MinPow float64 `json:"minPow"`
|
||||||
|
Topics []TopicType `json:"topics"`
|
||||||
|
AllowP2P bool `json:"allowP2P"`
|
||||||
|
}
|
||||||
|
var enc Criteria
|
||||||
|
enc.SymKeyID = c.SymKeyID
|
||||||
|
enc.PrivateKeyID = c.PrivateKeyID
|
||||||
|
enc.Sig = c.Sig
|
||||||
|
enc.MinPow = c.MinPow
|
||||||
|
enc.Topics = c.Topics
|
||||||
|
enc.AllowP2P = c.AllowP2P
|
||||||
|
return json.Marshal(&enc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON unmarshals type Criteria to a json string
|
||||||
|
func (c *Criteria) UnmarshalJSON(input []byte) error {
|
||||||
|
type Criteria struct {
|
||||||
|
SymKeyID *string `json:"symKeyID"`
|
||||||
|
PrivateKeyID *string `json:"privateKeyID"`
|
||||||
|
Sig *hexutil.Bytes `json:"sig"`
|
||||||
|
MinPow *float64 `json:"minPow"`
|
||||||
|
Topics []TopicType `json:"topics"`
|
||||||
|
AllowP2P *bool `json:"allowP2P"`
|
||||||
|
}
|
||||||
|
var dec Criteria
|
||||||
|
if err := json.Unmarshal(input, &dec); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if dec.SymKeyID != nil {
|
||||||
|
c.SymKeyID = *dec.SymKeyID
|
||||||
|
}
|
||||||
|
if dec.PrivateKeyID != nil {
|
||||||
|
c.PrivateKeyID = *dec.PrivateKeyID
|
||||||
|
}
|
||||||
|
if dec.Sig != nil {
|
||||||
|
c.Sig = *dec.Sig
|
||||||
|
}
|
||||||
|
if dec.MinPow != nil {
|
||||||
|
c.MinPow = *dec.MinPow
|
||||||
|
}
|
||||||
|
if dec.Topics != nil {
|
||||||
|
c.Topics = dec.Topics
|
||||||
|
}
|
||||||
|
if dec.AllowP2P != nil {
|
||||||
|
c.AllowP2P = *dec.AllowP2P
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
|
||||||
|
|
||||||
|
package whisper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = (*messageOverride)(nil)
|
||||||
|
|
||||||
|
// MarshalJSON marshals type Message to a json string
|
||||||
|
func (m Message) MarshalJSON() ([]byte, error) {
|
||||||
|
type Message struct {
|
||||||
|
Sig hexutil.Bytes `json:"sig,omitempty"`
|
||||||
|
TTL uint32 `json:"ttl"`
|
||||||
|
Timestamp uint32 `json:"timestamp"`
|
||||||
|
Topic TopicType `json:"topic"`
|
||||||
|
Payload hexutil.Bytes `json:"payload"`
|
||||||
|
Padding hexutil.Bytes `json:"padding"`
|
||||||
|
PoW float64 `json:"pow"`
|
||||||
|
Hash hexutil.Bytes `json:"hash"`
|
||||||
|
Dst hexutil.Bytes `json:"recipientPublicKey,omitempty"`
|
||||||
|
}
|
||||||
|
var enc Message
|
||||||
|
enc.Sig = m.Sig
|
||||||
|
enc.TTL = m.TTL
|
||||||
|
enc.Timestamp = m.Timestamp
|
||||||
|
enc.Topic = m.Topic
|
||||||
|
enc.Payload = m.Payload
|
||||||
|
enc.Padding = m.Padding
|
||||||
|
enc.PoW = m.PoW
|
||||||
|
enc.Hash = m.Hash
|
||||||
|
enc.Dst = m.Dst
|
||||||
|
return json.Marshal(&enc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON unmarshals type Message to a json string
|
||||||
|
func (m *Message) UnmarshalJSON(input []byte) error {
|
||||||
|
type Message struct {
|
||||||
|
Sig *hexutil.Bytes `json:"sig,omitempty"`
|
||||||
|
TTL *uint32 `json:"ttl"`
|
||||||
|
Timestamp *uint32 `json:"timestamp"`
|
||||||
|
Topic *TopicType `json:"topic"`
|
||||||
|
Payload *hexutil.Bytes `json:"payload"`
|
||||||
|
Padding *hexutil.Bytes `json:"padding"`
|
||||||
|
PoW *float64 `json:"pow"`
|
||||||
|
Hash *hexutil.Bytes `json:"hash"`
|
||||||
|
Dst *hexutil.Bytes `json:"recipientPublicKey,omitempty"`
|
||||||
|
}
|
||||||
|
var dec Message
|
||||||
|
if err := json.Unmarshal(input, &dec); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if dec.Sig != nil {
|
||||||
|
m.Sig = *dec.Sig
|
||||||
|
}
|
||||||
|
if dec.TTL != nil {
|
||||||
|
m.TTL = *dec.TTL
|
||||||
|
}
|
||||||
|
if dec.Timestamp != nil {
|
||||||
|
m.Timestamp = *dec.Timestamp
|
||||||
|
}
|
||||||
|
if dec.Topic != nil {
|
||||||
|
m.Topic = *dec.Topic
|
||||||
|
}
|
||||||
|
if dec.Payload != nil {
|
||||||
|
m.Payload = *dec.Payload
|
||||||
|
}
|
||||||
|
if dec.Padding != nil {
|
||||||
|
m.Padding = *dec.Padding
|
||||||
|
}
|
||||||
|
if dec.PoW != nil {
|
||||||
|
m.PoW = *dec.PoW
|
||||||
|
}
|
||||||
|
if dec.Hash != nil {
|
||||||
|
m.Hash = *dec.Hash
|
||||||
|
}
|
||||||
|
if dec.Dst != nil {
|
||||||
|
m.Dst = *dec.Dst
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,90 @@
|
||||||
|
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
|
||||||
|
|
||||||
|
package whisper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = (*newMessageOverride)(nil)
|
||||||
|
|
||||||
|
// MarshalJSON marshals type NewMessage to a json string
|
||||||
|
func (n NewMessage) MarshalJSON() ([]byte, error) {
|
||||||
|
type NewMessage struct {
|
||||||
|
SymKeyID string `json:"symKeyID"`
|
||||||
|
PublicKey hexutil.Bytes `json:"pubKey"`
|
||||||
|
Sig string `json:"sig"`
|
||||||
|
TTL uint32 `json:"ttl"`
|
||||||
|
Topic TopicType `json:"topic"`
|
||||||
|
Payload hexutil.Bytes `json:"payload"`
|
||||||
|
Padding hexutil.Bytes `json:"padding"`
|
||||||
|
PowTime uint32 `json:"powTime"`
|
||||||
|
PowTarget float64 `json:"powTarget"`
|
||||||
|
TargetPeer string `json:"targetPeer"`
|
||||||
|
}
|
||||||
|
var enc NewMessage
|
||||||
|
enc.SymKeyID = n.SymKeyID
|
||||||
|
enc.PublicKey = n.PublicKey
|
||||||
|
enc.Sig = n.Sig
|
||||||
|
enc.TTL = n.TTL
|
||||||
|
enc.Topic = n.Topic
|
||||||
|
enc.Payload = n.Payload
|
||||||
|
enc.Padding = n.Padding
|
||||||
|
enc.PowTime = n.PowTime
|
||||||
|
enc.PowTarget = n.PowTarget
|
||||||
|
enc.TargetPeer = n.TargetPeer
|
||||||
|
return json.Marshal(&enc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON unmarshals type NewMessage to a json string
|
||||||
|
func (n *NewMessage) UnmarshalJSON(input []byte) error {
|
||||||
|
type NewMessage struct {
|
||||||
|
SymKeyID *string `json:"symKeyID"`
|
||||||
|
PublicKey *hexutil.Bytes `json:"pubKey"`
|
||||||
|
Sig *string `json:"sig"`
|
||||||
|
TTL *uint32 `json:"ttl"`
|
||||||
|
Topic *TopicType `json:"topic"`
|
||||||
|
Payload *hexutil.Bytes `json:"payload"`
|
||||||
|
Padding *hexutil.Bytes `json:"padding"`
|
||||||
|
PowTime *uint32 `json:"powTime"`
|
||||||
|
PowTarget *float64 `json:"powTarget"`
|
||||||
|
TargetPeer *string `json:"targetPeer"`
|
||||||
|
}
|
||||||
|
var dec NewMessage
|
||||||
|
if err := json.Unmarshal(input, &dec); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if dec.SymKeyID != nil {
|
||||||
|
n.SymKeyID = *dec.SymKeyID
|
||||||
|
}
|
||||||
|
if dec.PublicKey != nil {
|
||||||
|
n.PublicKey = *dec.PublicKey
|
||||||
|
}
|
||||||
|
if dec.Sig != nil {
|
||||||
|
n.Sig = *dec.Sig
|
||||||
|
}
|
||||||
|
if dec.TTL != nil {
|
||||||
|
n.TTL = *dec.TTL
|
||||||
|
}
|
||||||
|
if dec.Topic != nil {
|
||||||
|
n.Topic = *dec.Topic
|
||||||
|
}
|
||||||
|
if dec.Payload != nil {
|
||||||
|
n.Payload = *dec.Payload
|
||||||
|
}
|
||||||
|
if dec.Padding != nil {
|
||||||
|
n.Padding = *dec.Padding
|
||||||
|
}
|
||||||
|
if dec.PowTime != nil {
|
||||||
|
n.PowTime = *dec.PowTime
|
||||||
|
}
|
||||||
|
if dec.PowTarget != nil {
|
||||||
|
n.PowTarget = *dec.PowTarget
|
||||||
|
}
|
||||||
|
if dec.TargetPeer != nil {
|
||||||
|
n.TargetPeer = *dec.TargetPeer
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
module github.com/status-im/status-go/whisper
|
||||||
|
|
||||||
|
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/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea
|
||||||
|
github.com/ethereum/go-ethereum v1.9.5
|
||||||
|
github.com/gorilla/websocket v1.4.1 // indirect
|
||||||
|
github.com/stretchr/objx v0.2.0 // indirect
|
||||||
|
github.com/stretchr/testify v1.3.0
|
||||||
|
github.com/syndtr/goleveldb v0.0.0-20181128100959-b001fa50d6b2
|
||||||
|
github.com/tsenart/tb v0.0.0-20181025101425-0d2499c8b6e9
|
||||||
|
golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf
|
||||||
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f
|
||||||
|
)
|
|
@ -0,0 +1,134 @@
|
||||||
|
bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=
|
||||||
|
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/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/allegro/bigcache v0.0.0-20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
|
||||||
|
github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 h1:rtI0fD4oG/8eVokGVPYJEW1F88p1ZNgXiEIs9thEE4A=
|
||||||
|
github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
|
||||||
|
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/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 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
|
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 h1:j4317fAZh7X6GqbFowYdYdI0L9bwxL07jyPZIdepyZ0=
|
||||||
|
github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/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/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||||
|
github.com/elastic/gosigar v0.0.0-20180330100440-37f05ff46ffa h1:o8OuEkracbk3qH6GvlI6XpEN1HTSxkzOG42xZpfDv/s=
|
||||||
|
github.com/elastic/gosigar v0.0.0-20180330100440-37f05ff46ffa/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/gizak/termui v0.0.0-20170117222342-991cd3d38091/go.mod h1:PkJoWUt/zacQKysNfQtcw1RW+eK2SxkieVBtl+4ovLA=
|
||||||
|
github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E=
|
||||||
|
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
|
||||||
|
github.com/go-stack/stack v1.5.4 h1:ACUuwAbOuCKT3mK+Az9UrqaSheA8lDWOfm0+ZT62NHY=
|
||||||
|
github.com/go-stack/stack v1.5.4/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
|
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/snappy v0.0.0-20170215233205-553a64147049 h1:K9KHZbXKpGydfDN0aZrsoHpLJlZsBrGMFWbgLDGnPZk=
|
||||||
|
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
|
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/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 h1:DqD8eigqlUm0+znmx7zhL0xvTW3+e1jCekJMfBUADWI=
|
||||||
|
github.com/huin/goupnp v0.0.0-20161224104101-679507af18f3/go.mod h1:MZ2ZmwcBpvOoJ22IJsc7va19ZwoheaBk43rKg12SKag=
|
||||||
|
github.com/influxdata/influxdb v0.0.0-20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY=
|
||||||
|
github.com/jackpal/go-nat-pmp v0.0.0-20160603034137-1fa385a6f458 h1:LPECOO5LcZx5tvkxraIptrg6AiAUf+28rFV9+noSZFA=
|
||||||
|
github.com/jackpal/go-nat-pmp v0.0.0-20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
|
||||||
|
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/julienschmidt/httprouter v0.0.0-20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||||
|
github.com/karalabe/hid v0.0.0-20181128192157-d815e0c1a2e2/go.mod h1:YvbcH+3Wo6XPs9nkgTY3u19KXLauXW+J5nB7hEHuX0A=
|
||||||
|
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
|
||||||
|
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/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
||||||
|
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
|
||||||
|
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 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
|
||||||
|
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
|
||||||
|
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
|
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/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/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/prometheus v0.0.0-20170814170113-3101606756c5/go.mod h1:oAIUtOny2rjMX0OWN5vPR5/q/twIROJvdqnQKDdil/s=
|
||||||
|
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/rs/cors v0.0.0-20160617231935-a62a804a8a00 h1:8DPul/X0IT/1TNMIxoKLwdemEOBBHDC/K4EB16Cw5WE=
|
||||||
|
github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||||
|
github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 h1:3hxavr+IHMsQBrYUPQM5v0CgENFktkkbg1sfpgM3h20=
|
||||||
|
github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ=
|
||||||
|
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.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
|
||||||
|
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||||
|
github.com/stretchr/testify v0.0.0-20170809224252-890a5c3458b4 h1:InXsxTNd7R4kIHKuA052litAUzokFLqjgbmhpUQTAs8=
|
||||||
|
github.com/stretchr/testify v0.0.0-20170809224252-890a5c3458b4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/syndtr/goleveldb v0.0.0-20181128100959-b001fa50d6b2 h1:GnOzE5fEFN3b2zDhJJABEofdb51uMRNb8eqIVtdducs=
|
||||||
|
github.com/syndtr/goleveldb v0.0.0-20181128100959-b001fa50d6b2/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
|
||||||
|
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=
|
||||||
|
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/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-20191029031824-8986dd9e96cf h1:fnPsqIDRbCSgumaMCRpoIoF2s4qxv0xSSS0BVZUE/ss=
|
||||||
|
golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
|
||||||
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
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/sys v0.0.0-20180909124046-d0be0721c37e/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-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
|
||||||
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
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/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
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/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||||
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
|
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/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 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
||||||
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
@ -0,0 +1,140 @@
|
||||||
|
package whisper
|
||||||
|
|
||||||
|
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 || event != nil {
|
||||||
|
return event, err
|
||||||
|
}
|
||||||
|
|
||||||
|
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:]
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
package whisper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/syndtr/goleveldb/leveldb/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
func checkValidErrorPayload(t *testing.T, id []byte, errorMsg string) {
|
||||||
|
requestID := common.BytesToHash(id)
|
||||||
|
errPayload := CreateMailServerRequestFailedPayload(requestID, errors.New(errorMsg))
|
||||||
|
nid := enode.ID{1}
|
||||||
|
event, err := CreateMailServerEvent(nid, errPayload)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, event)
|
||||||
|
require.Equal(t, nid, event.Peer)
|
||||||
|
require.Equal(t, requestID, event.Hash)
|
||||||
|
|
||||||
|
eventData, ok := event.Data.(*MailServerResponse)
|
||||||
|
if !ok {
|
||||||
|
require.FailNow(t, "Unexpected data in event: %v, expected a MailServerResponse", event.Data)
|
||||||
|
}
|
||||||
|
require.EqualError(t, eventData.Error, errorMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkValidSuccessPayload(t *testing.T, id []byte, lastHash []byte, timestamp uint32, envHash []byte) {
|
||||||
|
requestID := common.BytesToHash(id)
|
||||||
|
lastEnvelopeHash := common.BytesToHash(lastHash)
|
||||||
|
timestampBytes := make([]byte, 4)
|
||||||
|
binary.LittleEndian.PutUint32(timestampBytes, timestamp)
|
||||||
|
envelopeHash := common.BytesToHash(envHash)
|
||||||
|
cursor := append(timestampBytes, envelopeHash[:]...)
|
||||||
|
successPayload := CreateMailServerRequestCompletedPayload(common.BytesToHash(id), lastEnvelopeHash, cursor)
|
||||||
|
nid := enode.ID{1}
|
||||||
|
event, err := CreateMailServerEvent(nid, successPayload)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, event)
|
||||||
|
require.Equal(t, nid, event.Peer)
|
||||||
|
require.Equal(t, requestID, event.Hash)
|
||||||
|
|
||||||
|
eventData, ok := event.Data.(*MailServerResponse)
|
||||||
|
if !ok {
|
||||||
|
require.FailNow(t, "Unexpected data in event: %v, expected a MailServerResponse", event.Data)
|
||||||
|
}
|
||||||
|
require.Equal(t, lastEnvelopeHash, eventData.LastEnvelopeHash)
|
||||||
|
require.Equal(t, cursor, eventData.Cursor)
|
||||||
|
require.NoError(t, eventData.Error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateMailServerEvent(t *testing.T) {
|
||||||
|
// valid cases
|
||||||
|
longErrorMessage := "longMessage|"
|
||||||
|
for i := 0; i < 5; i++ {
|
||||||
|
longErrorMessage = longErrorMessage + longErrorMessage
|
||||||
|
}
|
||||||
|
checkValidErrorPayload(t, []byte{0x01}, "test error 1")
|
||||||
|
checkValidErrorPayload(t, []byte{0x02}, "test error 2")
|
||||||
|
checkValidErrorPayload(t, []byte{0x02}, "")
|
||||||
|
checkValidErrorPayload(t, []byte{0x00}, "test error 3")
|
||||||
|
checkValidErrorPayload(t, []byte{}, "test error 4")
|
||||||
|
|
||||||
|
checkValidSuccessPayload(t, []byte{0x01}, []byte{0x02}, 123, []byte{0x03})
|
||||||
|
// invalid payloads
|
||||||
|
|
||||||
|
// too small
|
||||||
|
_, err := CreateMailServerEvent(enode.ID{}, []byte{0x00})
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
// too big and not error payload
|
||||||
|
payloadTooBig := make([]byte, common.HashLength*2+cursorSize+100)
|
||||||
|
_, err = CreateMailServerEvent(enode.ID{}, payloadTooBig)
|
||||||
|
require.Error(t, err)
|
||||||
|
}
|
|
@ -0,0 +1,361 @@
|
||||||
|
// Copyright 2016 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum 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 go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
// Contains the Whisper protocol Message element.
|
||||||
|
|
||||||
|
package whisper
|
||||||
|
|
||||||
|
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
|
||||||
|
// Whisper 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
|
||||||
|
// Whisper 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 Whisper 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 Whisper 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)
|
||||||
|
}
|
|
@ -0,0 +1,495 @@
|
||||||
|
// Copyright 2016 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum 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 go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package whisper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/aes"
|
||||||
|
"crypto/cipher"
|
||||||
|
mrand "math/rand"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func generateMessageParams() (*MessageParams, error) {
|
||||||
|
// set all the parameters except p.Dst and p.Padding
|
||||||
|
|
||||||
|
buf := make([]byte, 4)
|
||||||
|
mrand.Read(buf)
|
||||||
|
sz := mrand.Intn(400)
|
||||||
|
|
||||||
|
var p MessageParams
|
||||||
|
p.PoW = 0.01
|
||||||
|
p.WorkTime = 1
|
||||||
|
p.TTL = uint32(mrand.Intn(1024))
|
||||||
|
p.Payload = make([]byte, sz)
|
||||||
|
p.KeySym = make([]byte, aesKeyLength)
|
||||||
|
mrand.Read(p.Payload)
|
||||||
|
mrand.Read(p.KeySym)
|
||||||
|
p.Topic = BytesToTopic(buf)
|
||||||
|
|
||||||
|
var err error
|
||||||
|
p.Src, err = crypto.GenerateKey()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &p, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func singleMessageTest(t *testing.T, symmetric bool) {
|
||||||
|
params, err := generateMessageParams()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
key, err := crypto.GenerateKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed GenerateKey with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !symmetric {
|
||||||
|
params.KeySym = nil
|
||||||
|
params.Dst = &key.PublicKey
|
||||||
|
}
|
||||||
|
|
||||||
|
text := make([]byte, 0, 512)
|
||||||
|
text = append(text, params.Payload...)
|
||||||
|
|
||||||
|
msg, err := NewSentMessage(params)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
env, err := msg.Wrap(params, time.Now())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed Wrap with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var decrypted *ReceivedMessage
|
||||||
|
if symmetric {
|
||||||
|
decrypted, err = env.OpenSymmetric(params.KeySym)
|
||||||
|
} else {
|
||||||
|
decrypted, err = env.OpenAsymmetric(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to encrypt with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !decrypted.ValidateAndParse() {
|
||||||
|
t.Fatalf("failed to validate with seed %d, symmetric = %v.", seed, symmetric)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !bytes.Equal(text, decrypted.Payload) {
|
||||||
|
t.Fatalf("failed with seed %d: compare payload.", seed)
|
||||||
|
}
|
||||||
|
if !isMessageSigned(decrypted.Raw[0]) {
|
||||||
|
t.Fatalf("failed with seed %d: unsigned.", seed)
|
||||||
|
}
|
||||||
|
if len(decrypted.Signature) != signatureLength {
|
||||||
|
t.Fatalf("failed with seed %d: signature len %d.", seed, len(decrypted.Signature))
|
||||||
|
}
|
||||||
|
if !IsPubKeyEqual(decrypted.Src, ¶ms.Src.PublicKey) {
|
||||||
|
t.Fatalf("failed with seed %d: signature mismatch.", seed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMessageEncryption(t *testing.T) {
|
||||||
|
InitSingleTest()
|
||||||
|
|
||||||
|
var symmetric bool
|
||||||
|
for i := 0; i < 256; i++ {
|
||||||
|
singleMessageTest(t, symmetric)
|
||||||
|
symmetric = !symmetric
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMessageWrap(t *testing.T) {
|
||||||
|
seed = int64(1777444222)
|
||||||
|
mrand.Seed(seed)
|
||||||
|
target := 128.0
|
||||||
|
|
||||||
|
params, err := generateMessageParams()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg, err := NewSentMessage(params)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
params.TTL = 1
|
||||||
|
params.WorkTime = 12
|
||||||
|
params.PoW = target
|
||||||
|
env, err := msg.Wrap(params, time.Now())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed Wrap with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pow := env.PoW()
|
||||||
|
if pow < target {
|
||||||
|
t.Fatalf("failed Wrap with seed %d: pow < target (%f vs. %f).", seed, pow, target)
|
||||||
|
}
|
||||||
|
|
||||||
|
// set PoW target too high, expect error
|
||||||
|
msg2, err := NewSentMessage(params)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
params.TTL = 1000000
|
||||||
|
params.WorkTime = 1
|
||||||
|
params.PoW = 10000000.0
|
||||||
|
_, err = msg2.Wrap(params, time.Now())
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("unexpectedly reached the PoW target with seed %d.", seed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMessageSeal(t *testing.T) {
|
||||||
|
// this test depends on deterministic choice of seed (1976726903)
|
||||||
|
seed = int64(1976726903)
|
||||||
|
mrand.Seed(seed)
|
||||||
|
|
||||||
|
params, err := generateMessageParams()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg, err := NewSentMessage(params)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
params.TTL = 1
|
||||||
|
|
||||||
|
env := NewEnvelope(params.TTL, params.Topic, msg, time.Now())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed Wrap with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
env.Expiry = uint32(seed) // make it deterministic
|
||||||
|
target := 32.0
|
||||||
|
params.WorkTime = 4
|
||||||
|
params.PoW = target
|
||||||
|
env.Seal(params)
|
||||||
|
|
||||||
|
env.calculatePoW(0)
|
||||||
|
pow := env.PoW()
|
||||||
|
if pow < target {
|
||||||
|
t.Fatalf("failed Wrap with seed %d: pow < target (%f vs. %f).", seed, pow, target)
|
||||||
|
}
|
||||||
|
|
||||||
|
params.WorkTime = 1
|
||||||
|
params.PoW = 1000000000.0
|
||||||
|
env.Seal(params)
|
||||||
|
env.calculatePoW(0)
|
||||||
|
pow = env.PoW()
|
||||||
|
if pow < 2*target {
|
||||||
|
t.Fatalf("failed Wrap with seed %d: pow too small %f.", seed, pow)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEnvelopeOpen(t *testing.T) {
|
||||||
|
InitSingleTest()
|
||||||
|
|
||||||
|
var symmetric bool
|
||||||
|
for i := 0; i < 32; i++ {
|
||||||
|
singleEnvelopeOpenTest(t, symmetric)
|
||||||
|
symmetric = !symmetric
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func singleEnvelopeOpenTest(t *testing.T, symmetric bool) {
|
||||||
|
params, err := generateMessageParams()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
key, err := crypto.GenerateKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed GenerateKey with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !symmetric {
|
||||||
|
params.KeySym = nil
|
||||||
|
params.Dst = &key.PublicKey
|
||||||
|
}
|
||||||
|
|
||||||
|
text := make([]byte, 0, 512)
|
||||||
|
text = append(text, params.Payload...)
|
||||||
|
|
||||||
|
msg, err := NewSentMessage(params)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
env, err := msg.Wrap(params, time.Now())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed Wrap with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var f Filter
|
||||||
|
if symmetric {
|
||||||
|
f = Filter{KeySym: params.KeySym}
|
||||||
|
} else {
|
||||||
|
f = Filter{KeyAsym: key}
|
||||||
|
}
|
||||||
|
decrypted := env.Open(&f)
|
||||||
|
if decrypted == nil {
|
||||||
|
t.Fatalf("failed to open with seed %d.", seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !bytes.Equal(text, decrypted.Payload) {
|
||||||
|
t.Fatalf("failed with seed %d: compare payload.", seed)
|
||||||
|
}
|
||||||
|
if !isMessageSigned(decrypted.Raw[0]) {
|
||||||
|
t.Fatalf("failed with seed %d: unsigned.", seed)
|
||||||
|
}
|
||||||
|
if len(decrypted.Signature) != signatureLength {
|
||||||
|
t.Fatalf("failed with seed %d: signature len %d.", seed, len(decrypted.Signature))
|
||||||
|
}
|
||||||
|
if !IsPubKeyEqual(decrypted.Src, ¶ms.Src.PublicKey) {
|
||||||
|
t.Fatalf("failed with seed %d: signature mismatch.", seed)
|
||||||
|
}
|
||||||
|
if decrypted.isAsymmetricEncryption() == symmetric {
|
||||||
|
t.Fatalf("failed with seed %d: asymmetric %v vs. %v.", seed, decrypted.isAsymmetricEncryption(), symmetric)
|
||||||
|
}
|
||||||
|
if decrypted.isSymmetricEncryption() != symmetric {
|
||||||
|
t.Fatalf("failed with seed %d: symmetric %v vs. %v.", seed, decrypted.isSymmetricEncryption(), symmetric)
|
||||||
|
}
|
||||||
|
if !symmetric {
|
||||||
|
if decrypted.Dst == nil {
|
||||||
|
t.Fatalf("failed with seed %d: dst is nil.", seed)
|
||||||
|
}
|
||||||
|
if !IsPubKeyEqual(decrypted.Dst, &key.PublicKey) {
|
||||||
|
t.Fatalf("failed with seed %d: Dst.", seed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEncryptWithZeroKey(t *testing.T) {
|
||||||
|
InitSingleTest()
|
||||||
|
|
||||||
|
params, err := generateMessageParams()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
msg, err := NewSentMessage(params)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
params.KeySym = make([]byte, aesKeyLength)
|
||||||
|
_, err = msg.Wrap(params, time.Now())
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("wrapped with zero key, seed: %d.", seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
params, err = generateMessageParams()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
msg, err = NewSentMessage(params)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
params.KeySym = make([]byte, 0)
|
||||||
|
_, err = msg.Wrap(params, time.Now())
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("wrapped with empty key, seed: %d.", seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
params, err = generateMessageParams()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
msg, err = NewSentMessage(params)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
params.KeySym = nil
|
||||||
|
_, err = msg.Wrap(params, time.Now())
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("wrapped with nil key, seed: %d.", seed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRlpEncode(t *testing.T) {
|
||||||
|
InitSingleTest()
|
||||||
|
|
||||||
|
params, err := generateMessageParams()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
msg, err := NewSentMessage(params)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
env, err := msg.Wrap(params, time.Now())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("wrapped with zero key, seed: %d.", seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
raw, err := rlp.EncodeToBytes(env)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("RLP encode failed: %s.", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var decoded Envelope
|
||||||
|
rlp.DecodeBytes(raw, &decoded)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("RLP decode failed: %s.", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
he := env.Hash()
|
||||||
|
hd := decoded.Hash()
|
||||||
|
|
||||||
|
if he != hd {
|
||||||
|
t.Fatalf("Hashes are not equal: %x vs. %x", he, hd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func singlePaddingTest(t *testing.T, padSize int) {
|
||||||
|
params, err := generateMessageParams()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed generateMessageParams with seed %d and sz=%d: %s.", seed, padSize, err)
|
||||||
|
}
|
||||||
|
params.Padding = make([]byte, padSize)
|
||||||
|
params.PoW = 0.0000000001
|
||||||
|
pad := make([]byte, padSize)
|
||||||
|
_, err = mrand.Read(pad)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("padding is not generated (seed %d): %s", seed, err)
|
||||||
|
}
|
||||||
|
n := copy(params.Padding, pad)
|
||||||
|
if n != padSize {
|
||||||
|
t.Fatalf("padding is not copied (seed %d): %s", seed, err)
|
||||||
|
}
|
||||||
|
msg, err := NewSentMessage(params)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
|
||||||
|
}
|
||||||
|
env, err := msg.Wrap(params, time.Now())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to wrap, seed: %d and sz=%d.", seed, padSize)
|
||||||
|
}
|
||||||
|
f := Filter{KeySym: params.KeySym}
|
||||||
|
decrypted := env.Open(&f)
|
||||||
|
if decrypted == nil {
|
||||||
|
t.Fatalf("failed to open, seed and sz=%d: %d.", seed, padSize)
|
||||||
|
}
|
||||||
|
if !bytes.Equal(pad, decrypted.Padding) {
|
||||||
|
t.Fatalf("padding is not retireved as expected with seed %d and sz=%d:\n[%x]\n[%x].", seed, padSize, pad, decrypted.Padding)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPadding(t *testing.T) {
|
||||||
|
InitSingleTest()
|
||||||
|
|
||||||
|
for i := 1; i < 260; i++ {
|
||||||
|
singlePaddingTest(t, i)
|
||||||
|
}
|
||||||
|
|
||||||
|
lim := 256 * 256
|
||||||
|
for i := lim - 5; i < lim+2; i++ {
|
||||||
|
singlePaddingTest(t, i)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 256; i++ {
|
||||||
|
n := mrand.Intn(256*254) + 256
|
||||||
|
singlePaddingTest(t, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 256; i++ {
|
||||||
|
n := mrand.Intn(256*1024) + 256*256
|
||||||
|
singlePaddingTest(t, n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPaddingAppendedToSymMessagesWithSignature(t *testing.T) {
|
||||||
|
params := &MessageParams{
|
||||||
|
Payload: make([]byte, 246),
|
||||||
|
KeySym: make([]byte, aesKeyLength),
|
||||||
|
}
|
||||||
|
|
||||||
|
pSrc, err := crypto.GenerateKey()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error creating the signature key %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
params.Src = pSrc
|
||||||
|
|
||||||
|
// Simulate a message with a payload just under 256 so that
|
||||||
|
// payload + flag + signature > 256. Check that the result
|
||||||
|
// is padded on the next 256 boundary.
|
||||||
|
msg := sentMessage{}
|
||||||
|
const payloadSizeFieldMinSize = 1
|
||||||
|
msg.Raw = make([]byte, flagsLength+payloadSizeFieldMinSize+len(params.Payload))
|
||||||
|
|
||||||
|
err = msg.appendPadding(params)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error appending padding to message %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(msg.Raw) != 512-signatureLength {
|
||||||
|
t.Errorf("Invalid size %d != 512", len(msg.Raw))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAesNonce(t *testing.T) {
|
||||||
|
key := hexutil.MustDecode("0x03ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd31")
|
||||||
|
block, err := aes.NewCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("NewCipher failed: %s", err)
|
||||||
|
}
|
||||||
|
aesgcm, err := cipher.NewGCM(block)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("NewGCM failed: %s", err)
|
||||||
|
}
|
||||||
|
// This is the most important single test in this package.
|
||||||
|
// If it fails, whisper will not be working.
|
||||||
|
if aesgcm.NonceSize() != aesNonceLength {
|
||||||
|
t.Fatalf("Nonce size is wrong. This is a critical error. Apparently AES nonce size have changed in the new version of AES GCM package. Whisper will not be working until this problem is resolved.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidateAndParseSizeOfPayloadSize(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
Name string
|
||||||
|
Raw []byte
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Name: "one byte of value 1",
|
||||||
|
Raw: []byte{1},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "two bytes of values 1 and 1",
|
||||||
|
Raw: []byte{1, 1},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.Name, func(t *testing.T) {
|
||||||
|
msg := ReceivedMessage{Raw: tc.Raw}
|
||||||
|
msg.ValidateAndParse()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue