Update for status-protocol-go API changes (#1627)

This commit is contained in:
Pedro Pombeiro 2019-10-09 16:22:53 +02:00 committed by GitHub
parent e164cbe421
commit a2f106e4c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
149 changed files with 2365 additions and 12545 deletions

View File

@ -12,7 +12,6 @@ import (
"path/filepath"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode"
@ -22,9 +21,12 @@ import (
"github.com/status-im/status-go/rpc"
"github.com/status-im/status-go/services/shhext"
"github.com/status-im/status-go/t/helpers"
whisper "github.com/status-im/whisper/whisperv6"
"github.com/status-im/status-protocol-go/transport/whisper/gethbridge"
statusproto "github.com/status-im/status-protocol-go/types"
"golang.org/x/crypto/sha3"
"golang.org/x/crypto/ssh/terminal"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
)
const (
@ -105,11 +107,12 @@ func verifyMailserverBehavior(mailserverNode *enode.Node) {
defer func() { _ = clientBackend.StopNode() }()
clientNode := clientBackend.StatusNode()
clientWhisperService, err := clientNode.WhisperService()
clientGethWhisperService, err := clientNode.WhisperService()
if err != nil {
logger.Error("Could not retrieve Whisper service", "error", err)
os.Exit(1)
}
clientWhisperService := gethbridge.NewGethWhisperWrapper(clientGethWhisperService)
clientShhExtService, err := clientNode.ShhExtService()
if err != nil {
logger.Error("Could not retrieve shhext service", "error", err)
@ -139,7 +142,7 @@ func verifyMailserverBehavior(mailserverNode *enode.Node) {
}
mailboxPeer := mailserverNode.ID().Bytes()
err = clientWhisperService.AllowP2PMessagesFromPeer(mailboxPeer)
err = clientGethWhisperService.AllowP2PMessagesFromPeer(mailboxPeer)
if err != nil {
logger.Error("Failed to allow P2P messages from mailserver peer", "error", err, mailserverNode.String())
os.Exit(1)
@ -155,12 +158,12 @@ func verifyMailserverBehavior(mailserverNode *enode.Node) {
}
// watch for envelopes to be available in filters in the client
envelopeAvailableWatcher := make(chan whisper.EnvelopeEvent, 1024)
envelopeAvailableWatcher := make(chan whispertypes.EnvelopeEvent, 1024)
sub := clientWhisperService.SubscribeEnvelopeEvents(envelopeAvailableWatcher)
defer sub.Unsubscribe()
// watch for mailserver responses in the client
mailServerResponseWatcher := make(chan whisper.EnvelopeEvent, 1024)
mailServerResponseWatcher := make(chan whispertypes.EnvelopeEvent, 1024)
sub = clientWhisperService.SubscribeEnvelopeEvents(mailServerResponseWatcher)
defer sub.Unsubscribe()
@ -179,7 +182,7 @@ func verifyMailserverBehavior(mailserverNode *enode.Node) {
logger.Error("Error requesting historic messages from mailserver", "error", err)
os.Exit(2)
}
requestID := common.BytesToHash(requestIDBytes)
requestID := statusproto.BytesToHash(requestIDBytes)
// wait for mailserver request sent event
err = waitForMailServerRequestSent(mailServerResponseWatcher, requestID, time.Duration(*timeout)*time.Second)
@ -196,7 +199,7 @@ func verifyMailserverBehavior(mailserverNode *enode.Node) {
}
// wait for last envelope sent by the mailserver to be available for filters
err = waitForEnvelopeEvents(envelopeAvailableWatcher, []string{resp.LastEnvelopeHash.String()}, whisper.EventEnvelopeAvailable)
err = waitForEnvelopeEvents(envelopeAvailableWatcher, []string{resp.LastEnvelopeHash.String()}, whispertypes.EventEnvelopeAvailable)
if err != nil {
logger.Error("Error waiting for envelopes to be available to client filter", "error", err)
os.Exit(4)
@ -300,32 +303,32 @@ func startClientNode() (*api.StatusBackend, error) {
return clientBackend, err
}
func joinPublicChat(w *whisper.Whisper, rpcClient *rpc.Client, name string) (string, whisper.TopicType, string, error) {
func joinPublicChat(w whispertypes.Whisper, rpcClient *rpc.Client, name string) (string, whispertypes.TopicType, string, error) {
keyID, err := w.AddSymKeyFromPassword(name)
if err != nil {
return "", whisper.TopicType{}, "", err
return "", whispertypes.TopicType{}, "", err
}
h := sha3.NewLegacyKeccak256()
_, err = h.Write([]byte(name))
if err != nil {
return "", whisper.TopicType{}, "", err
return "", whispertypes.TopicType{}, "", err
}
fullTopic := h.Sum(nil)
topic := whisper.BytesToTopic(fullTopic)
topic := whispertypes.BytesToTopic(fullTopic)
whisperAPI := whisper.NewPublicWhisperAPI(w)
filterID, err := whisperAPI.NewMessageFilter(whisper.Criteria{SymKeyID: keyID, Topics: []whisper.TopicType{topic}})
whisperAPI := w.PublicWhisperAPI()
filterID, err := whisperAPI.NewMessageFilter(whispertypes.Criteria{SymKeyID: keyID, Topics: []whispertypes.TopicType{topic}})
return keyID, topic, filterID, err
}
func waitForMailServerRequestSent(events chan whisper.EnvelopeEvent, requestID common.Hash, timeout time.Duration) error {
func waitForMailServerRequestSent(events chan whispertypes.EnvelopeEvent, requestID statusproto.Hash, timeout time.Duration) error {
timeoutTimer := time.NewTimer(timeout)
for {
select {
case event := <-events:
if event.Hash == requestID && event.Event == whisper.EventMailServerRequestSent {
if event.Hash == requestID && event.Event == whispertypes.EventMailServerRequestSent {
timeoutTimer.Stop()
return nil
}
@ -335,7 +338,7 @@ func waitForMailServerRequestSent(events chan whisper.EnvelopeEvent, requestID c
}
}
func waitForMailServerResponse(events chan whisper.EnvelopeEvent, requestID common.Hash, timeout time.Duration) (*whisper.MailServerResponse, error) {
func waitForMailServerResponse(events chan whispertypes.EnvelopeEvent, requestID statusproto.Hash, timeout time.Duration) (*whispertypes.MailServerResponse, error) {
timeoutTimer := time.NewTimer(timeout)
for {
select {
@ -353,25 +356,25 @@ func waitForMailServerResponse(events chan whisper.EnvelopeEvent, requestID comm
}
}
func decodeMailServerResponse(event whisper.EnvelopeEvent) (*whisper.MailServerResponse, error) {
func decodeMailServerResponse(event whispertypes.EnvelopeEvent) (*whispertypes.MailServerResponse, error) {
switch event.Event {
case whisper.EventMailServerRequestSent:
case whispertypes.EventMailServerRequestSent:
return nil, nil
case whisper.EventMailServerRequestCompleted:
resp, ok := event.Data.(*whisper.MailServerResponse)
case whispertypes.EventMailServerRequestCompleted:
resp, ok := event.Data.(*whispertypes.MailServerResponse)
if !ok {
return nil, errors.New("failed to convert event to a *MailServerResponse")
}
return resp, nil
case whisper.EventMailServerRequestExpired:
case whispertypes.EventMailServerRequestExpired:
return nil, errors.New("no messages available from mailserver")
default:
return nil, fmt.Errorf("unexpected event type: %v", event.Event)
}
}
func waitForEnvelopeEvents(events chan whisper.EnvelopeEvent, hashes []string, event whisper.EventType) error {
func waitForEnvelopeEvents(events chan whispertypes.EnvelopeEvent, hashes []string, event whispertypes.EventType) error {
check := make(map[string]struct{})
for _, hash := range hashes {
check[hash] = struct{}{}

View File

@ -6,8 +6,8 @@ import (
"errors"
"time"
"github.com/ethereum/go-ethereum/common"
whisper "github.com/status-im/whisper/whisperv6"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
statusproto "github.com/status-im/status-protocol-go/types"
"github.com/syndtr/goleveldb/leveldb/util"
)
@ -26,7 +26,7 @@ type DB interface {
}
// TopicHistoryKey defines bytes that are used as unique key for TopicHistory.
// first 4 bytes are whisper.TopicType bytes
// first 4 bytes are whispertypes.TopicType bytes
// next 8 bytes are time.Duration encoded in big endian notation.
type TopicHistoryKey [12]byte
@ -36,7 +36,7 @@ func LoadTopicHistoryFromKey(db DB, key TopicHistoryKey) (th TopicHistory, err e
if (key == TopicHistoryKey{}) {
return th, ErrEmptyKey
}
topic := whisper.TopicType{}
topic := whispertypes.TopicType{}
copy(topic[:], key[:4])
duration := binary.BigEndian.Uint64(key[4:])
th = TopicHistory{db: db, Topic: topic, Duration: time.Duration(duration)}
@ -47,7 +47,7 @@ func LoadTopicHistoryFromKey(db DB, key TopicHistoryKey) (th TopicHistory, err e
type TopicHistory struct {
db DB
// whisper topic
Topic whisper.TopicType
Topic whispertypes.TopicType
Duration time.Duration
// Timestamp that was used for the first request with this topic.
@ -57,7 +57,7 @@ type TopicHistory struct {
Current time.Time
End time.Time
RequestID common.Hash
RequestID statusproto.Hash
}
// Key returns unique identifier for this TopicHistory.
@ -115,7 +115,7 @@ func (t TopicHistory) SameRange(other TopicHistory) bool {
// Pending returns true if this topic was requested from a mail server.
func (t TopicHistory) Pending() bool {
return t.RequestID != common.Hash{}
return t.RequestID != statusproto.Hash{}
}
// HistoryRequest is kept in the database while request is in the progress.
@ -127,7 +127,7 @@ type HistoryRequest struct {
histories []TopicHistory
// Generated ID
ID common.Hash
ID statusproto.Hash
// List of the topics
TopicHistoryKeys []TopicHistoryKey
}
@ -167,8 +167,8 @@ func (req HistoryRequest) Save() error {
}
// Replace saves request with new ID and all data attached to the old one.
func (req HistoryRequest) Replace(id common.Hash) error {
if (req.ID != common.Hash{}) {
func (req HistoryRequest) Replace(id statusproto.Hash) error {
if (req.ID != statusproto.Hash{}) {
if err := req.Delete(); err != nil {
return err
}

View File

@ -3,8 +3,8 @@ package db
import (
"time"
"github.com/ethereum/go-ethereum/common"
whisper "github.com/status-im/whisper/whisperv6"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
statusproto "github.com/status-im/status-protocol-go/types"
"github.com/syndtr/goleveldb/leveldb/errors"
)
@ -24,7 +24,7 @@ type HistoryStore struct {
// GetHistory creates history instance and loads history from database.
// Returns instance populated with topic and duration if history is not found in database.
func (h HistoryStore) GetHistory(topic whisper.TopicType, duration time.Duration) (TopicHistory, error) {
func (h HistoryStore) GetHistory(topic whispertypes.TopicType, duration time.Duration) (TopicHistory, error) {
thist := h.NewHistory(topic, duration)
err := thist.Load()
if err != nil && err != errors.ErrNotFound {
@ -39,12 +39,12 @@ func (h HistoryStore) NewRequest() HistoryRequest {
}
// NewHistory creates TopicHistory object with required values.
func (h HistoryStore) NewHistory(topic whisper.TopicType, duration time.Duration) TopicHistory {
func (h HistoryStore) NewHistory(topic whispertypes.TopicType, duration time.Duration) TopicHistory {
return TopicHistory{db: h.topicDB, Duration: duration, Topic: topic}
}
// GetRequest loads HistoryRequest from database.
func (h HistoryStore) GetRequest(id common.Hash) (HistoryRequest, error) {
func (h HistoryStore) GetRequest(id statusproto.Hash) (HistoryRequest, error) {
req := HistoryRequest{requestDB: h.requestDB, topicDB: h.topicDB, ID: id}
err := req.Load()
if err != nil {
@ -74,7 +74,7 @@ func (h HistoryStore) GetAllRequests() ([]HistoryRequest, error) {
// GetHistoriesByTopic returns all histories with a given topic.
// This is needed when we will have multiple range per single topic.
// TODO explain
func (h HistoryStore) GetHistoriesByTopic(topic whisper.TopicType) ([]TopicHistory, error) {
func (h HistoryStore) GetHistoriesByTopic(topic whispertypes.TopicType) ([]TopicHistory, error) {
rst := []TopicHistory{}
iter := h.topicDB.NewIterator(h.topicDB.Range(topic[:], nil))
for iter.Next() {

View File

@ -4,8 +4,8 @@ import (
"testing"
"time"
"github.com/ethereum/go-ethereum/common"
whisper "github.com/status-im/whisper/whisperv6"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
statusproto "github.com/status-im/status-protocol-go/types"
"github.com/stretchr/testify/require"
)
@ -16,7 +16,7 @@ func createInMemStore(t *testing.T) HistoryStore {
}
func TestGetNewHistory(t *testing.T) {
topic := whisper.TopicType{1}
topic := whispertypes.TopicType{1}
duration := time.Hour
store := createInMemStore(t)
th, err := store.GetHistory(topic, duration)
@ -26,7 +26,7 @@ func TestGetNewHistory(t *testing.T) {
}
func TestGetExistingHistory(t *testing.T) {
topic := whisper.TopicType{1}
topic := whispertypes.TopicType{1}
duration := time.Hour
store := createInMemStore(t)
th, err := store.GetHistory(topic, duration)
@ -43,13 +43,13 @@ func TestGetExistingHistory(t *testing.T) {
func TestNewHistoryRequest(t *testing.T) {
store := createInMemStore(t)
id := common.Hash{1}
id := statusproto.Hash{1}
req, err := store.GetRequest(id)
require.Error(t, err)
req = store.NewRequest()
req.ID = id
th, err := store.GetHistory(whisper.TopicType{1}, time.Hour)
th, err := store.GetHistory(whispertypes.TopicType{1}, time.Hour)
require.NoError(t, err)
req.AddHistory(th)
require.NoError(t, req.Save())
@ -61,8 +61,8 @@ func TestNewHistoryRequest(t *testing.T) {
func TestGetAllRequests(t *testing.T) {
store := createInMemStore(t)
idOne := common.Hash{1}
idTwo := common.Hash{2}
idOne := statusproto.Hash{1}
idTwo := statusproto.Hash{2}
req := store.NewRequest()
req.ID = idOne

View File

@ -4,8 +4,8 @@ import (
"testing"
"time"
"github.com/ethereum/go-ethereum/common"
whisper "github.com/status-im/whisper/whisperv6"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
statusproto "github.com/status-im/status-protocol-go/types"
"github.com/stretchr/testify/require"
)
@ -14,7 +14,7 @@ func TestTopicHistoryStoreLoadFromKey(t *testing.T) {
require.NoError(t, err)
th := TopicHistory{
db: db,
Topic: whisper.TopicType{1, 1, 1},
Topic: whispertypes.TopicType{1, 1, 1},
Duration: 10 * time.Hour,
}
require.NoError(t, th.Save())
@ -71,7 +71,7 @@ func TestTopicHistorySameRange(t *testing.T) {
}
func TestAddHistory(t *testing.T) {
topic := whisper.TopicType{1, 1, 1}
topic := whispertypes.TopicType{1, 1, 1}
now := time.Now()
topicdb, err := NewMemoryDBNamespace(TopicHistoryBucket)
@ -80,7 +80,7 @@ func TestAddHistory(t *testing.T) {
require.NoError(t, err)
th := TopicHistory{db: topicdb, Topic: topic, Current: now}
id := common.Hash{1}
id := statusproto.Hash{1}
req := HistoryRequest{requestDB: requestdb, topicDB: topicdb, ID: id}
req.AddHistory(th)
@ -94,8 +94,8 @@ func TestAddHistory(t *testing.T) {
}
func TestRequestIncludesMethod(t *testing.T) {
topicOne := whisper.TopicType{1}
topicTwo := whisper.TopicType{2}
topicOne := whispertypes.TopicType{1}
topicTwo := whispertypes.TopicType{2}
testCases := []struct {
description string
result bool

6
go.mod
View File

@ -30,10 +30,8 @@ require (
github.com/status-im/keycard-go v0.0.0-20190424133014-d95853db0f48 // indirect
github.com/status-im/migrate/v4 v4.3.1-status.0.20190822050738-a9d340ec8fb7
github.com/status-im/rendezvous v1.3.0
github.com/status-im/status-protocol-go v0.2.3-0.20190926081215-cc44ddb7ce44
github.com/status-im/whisper v1.4.14
github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 // indirect
github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 // indirect
github.com/status-im/status-protocol-go v0.2.3-0.20191009073015-e7ecec99a52b
github.com/status-im/whisper v1.5.1
github.com/stretchr/testify v1.4.0
github.com/syndtr/goleveldb v1.0.0
github.com/tyler-smith/go-bip39 v1.0.2 // indirect

17
go.sum
View File

@ -27,8 +27,11 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/allegro/bigcache v0.0.0-20190218064605-e24eb225f156 h1:hh7BAWFHv41r0gce0KRYtDJpL4erKfmB1/mpgoSADeI=
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/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
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-20190502180301-283422fc1708/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
github.com/aristanetworks/goarista v0.0.0-20190704150520-f44d68189fd7 h1:fKnuvQ/O22ZpD7HaJjGQXn/GxOdDJOQFL8bpM8Xe3X8=
github.com/aristanetworks/goarista v0.0.0-20190704150520-f44d68189fd7/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
@ -41,6 +44,7 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce
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/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ=
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-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI=
github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3 h1:A/EVblehb75cUgXA5njHPn0kLAsykn6mJGz7rnmW5W0=
@ -115,7 +119,6 @@ github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt
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/ethereum/go-ethereum v1.8.20/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY=
github.com/ethereum/go-ethereum v1.8.27/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY=
github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc h1:jtW8jbpkO4YirRSyepBOH8E+2HEw6/hKkBvFPwhUN8c=
github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
@ -459,9 +462,13 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w=
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo=
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
@ -549,10 +556,10 @@ github.com/status-im/migrate/v4 v4.3.1-status.0.20190822050738-a9d340ec8fb7 h1:g
github.com/status-im/migrate/v4 v4.3.1-status.0.20190822050738-a9d340ec8fb7/go.mod h1:r8HggRBZ/k7TRwByq/Hp3P/ubFppIna0nvyavVK0pjA=
github.com/status-im/rendezvous v1.3.0 h1:7RK/MXXW+tlm0asKm1u7Qp7Yni6AO29a7j8+E4Lbjg4=
github.com/status-im/rendezvous v1.3.0/go.mod h1:+hzjuP+j/XzLPeF6E50b88pWOTLdTcwjvNYt+Gh1W1s=
github.com/status-im/status-protocol-go v0.2.3-0.20190926081215-cc44ddb7ce44 h1:/dyB9wnkkNURvznzewDov3ulnLbjl8h1OeEEr5NQmQM=
github.com/status-im/status-protocol-go v0.2.3-0.20190926081215-cc44ddb7ce44/go.mod h1:g059a1CeUmHKzsokiKwdk5pCuhCPE1GeOh8vULbfn5w=
github.com/status-im/whisper v1.4.14 h1:9VHqx4+PUYfhDnYYtDxHkg/3cfVvkHjPNciY4LO83yc=
github.com/status-im/whisper v1.4.14/go.mod h1:WS6z39YJQ8WJa9s+DmTuEM/s2nVF6Iz3B1SZYw5cYf0=
github.com/status-im/status-protocol-go v0.2.3-0.20191009073015-e7ecec99a52b h1:hCB3tnF1yJ/IN0v+zR+Omc5DKUyUPyrrhyYkJUupnSw=
github.com/status-im/status-protocol-go v0.2.3-0.20191009073015-e7ecec99a52b/go.mod h1:z4P5yngpR7aB6N6uYtJnhOkHzDHAHlqxTbIbaSX72Jg=
github.com/status-im/whisper v1.5.1 h1:87/XIg0Wjua7lXBGiEXgAfTOqlt2Q1dMDuxugTyZbbA=
github.com/status-im/whisper v1.5.1/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/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw=
github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 h1:njlZPzLwU639dk2kqnCPPv+wNjq7Xb6EfUxe/oX0/NM=

View File

@ -32,6 +32,8 @@ import (
"github.com/status-im/status-go/services/status"
"github.com/status-im/status-go/static"
"github.com/status-im/status-go/timesource"
"github.com/status-im/status-protocol-go/transport/whisper/gethbridge"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
whisper "github.com/status-im/whisper/whisperv6"
"github.com/syndtr/goleveldb/leveldb"
)
@ -356,7 +358,7 @@ func activateShhService(stack *node.Node, config *params.NodeConfig, db *leveldb
if err := ctx.Service(&whisper); err != nil {
return nil, err
}
return shhext.New(whisper, shhext.EnvelopeSignalHandler{}, db, config.ShhextConfig), nil
return shhext.New(gethbridge.NewGethWhisperWrapper(whisper), shhext.EnvelopeSignalHandler{}, db, config.ShhextConfig), nil
})
}
@ -375,7 +377,7 @@ func activateIncentivisationService(stack *node.Node, config *params.NodeConfig)
logger.Info("activating incentivisation")
// TODO(dshulyak) add a config option to enable it by default, but disable if app is started from statusd
return stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
var w *whisper.Whisper
var w whispertypes.Whisper
if err := ctx.Service(&w); err != nil {
return nil, err
}
@ -399,7 +401,7 @@ func activateIncentivisationService(stack *node.Node, config *params.NodeConfig)
return nil, err
}
return incentivisation.New(privateKey, whisper.NewPublicWhisperAPI(w), incentivisationConfig, contract), nil
return incentivisation.New(privateKey, w.PublicWhisperAPI(), incentivisationConfig, contract), nil
})
}

View File

@ -4,9 +4,9 @@ import (
"testing"
"github.com/ethereum/go-ethereum/accounts"
whisper "github.com/status-im/whisper/whisperv6"
"github.com/status-im/status-go/params"
whisper "github.com/status-im/whisper/whisperv6"
"github.com/stretchr/testify/require"
)

View File

@ -8,6 +8,10 @@ import (
"encoding/binary"
"encoding/hex"
"fmt"
"math/big"
"net"
"sort"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
gethcommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
@ -15,12 +19,11 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/rpc"
"math/big"
"net"
"sort"
whisper "github.com/status-im/whisper/whisperv6"
"time"
statustransp "github.com/status-im/status-protocol-go/transport/whisper"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
)
const (
@ -51,15 +54,6 @@ func (n *Enode) PublicKeyString() string {
return hex.EncodeToString(n.PublicKey)
}
type Whisper interface {
Post(ctx context.Context, req whisper.NewMessage) (hexutil.Bytes, error)
NewMessageFilter(req whisper.Criteria) (string, error)
AddPrivateKey(ctx context.Context, privateKey hexutil.Bytes) (string, error)
DeleteKeyPair(ctx context.Context, key string) (bool, error)
GenerateSymKeyFromPassword(ctx context.Context, passwd string) (string, error)
GetFilterMessages(id string) ([]*whisper.Message, error)
}
type ServiceConfig struct {
RPCEndpoint string
ContractAddress string
@ -68,7 +62,7 @@ type ServiceConfig struct {
}
type Service struct {
w Whisper
w whispertypes.PublicWhisperAPI
whisperKeyID string
whisperSymKeyID string
whisperFilterID string
@ -87,7 +81,7 @@ type Service struct {
}
// New returns a new incentivization Service
func New(prv *ecdsa.PrivateKey, w Whisper, config *ServiceConfig, contract Contract) *Service {
func New(prv *ecdsa.PrivateKey, w whispertypes.PublicWhisperAPI, config *ServiceConfig, contract Contract) *Service {
logger := log.New("package", "status-go/incentivisation/service")
return &Service{
w: w,
@ -307,9 +301,9 @@ func (s *Service) Start(server *p2p.Server) error {
}
s.whisperSymKeyID = whisperSymKeyID
criteria := whisper.Criteria{
criteria := whispertypes.Criteria{
SymKeyID: whisperSymKeyID,
Topics: []whisper.TopicType{toWhisperTopic(defaultTopic)},
Topics: []whispertypes.TopicType{toWhisperTopic(defaultTopic)},
}
filterID, err := s.w.NewMessageFilter(criteria)
if err != nil {
@ -437,7 +431,7 @@ func (s *Service) addressString() string {
// postPing publishes a whisper message
func (s *Service) postPing() (hexutil.Bytes, error) {
msg := defaultWhisperMessage()
msg := statustransp.DefaultWhisperMessage()
msg.Topic = toWhisperTopic(defaultTopic)
@ -484,18 +478,8 @@ func ip2Long(ip string) (uint32, error) {
return long, nil
}
func toWhisperTopic(s string) whisper.TopicType {
return whisper.BytesToTopic(crypto.Keccak256([]byte(s)))
}
func defaultWhisperMessage() whisper.NewMessage {
msg := whisper.NewMessage{}
msg.TTL = 10
msg.PowTarget = 0.002
msg.PowTime = 1
return msg
func toWhisperTopic(s string) whispertypes.TopicType {
return whispertypes.BytesToTopic(crypto.Keccak256([]byte(s)))
}
func int2ip(nn uint32) net.IP {

View File

@ -9,10 +9,10 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
gethcommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
whisper "github.com/status-im/whisper/whisperv6"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
statusproto "github.com/status-im/status-protocol-go/types"
"github.com/stretchr/testify/suite"
)
@ -34,8 +34,8 @@ type Vote struct {
}
type MockWhisper struct {
sentMessages []whisper.NewMessage
filterMessages []*whisper.Message
sentMessages []whispertypes.NewMessage
filterMessages []*whispertypes.Message
}
func BuildMockContract() *MockContract {
@ -99,14 +99,14 @@ func (c *MockContract) GetInactiveNode(opts *bind.CallOpts, index *big.Int) ([]b
return c.inactiveNodes[index.Int64()], 0, 0, 0, 0, nil
}
func (w *MockWhisper) Post(ctx context.Context, req whisper.NewMessage) (hexutil.Bytes, error) {
func (w *MockWhisper) Post(ctx context.Context, req whispertypes.NewMessage) ([]byte, error) {
w.sentMessages = append(w.sentMessages, req)
return nil, nil
}
func (w *MockWhisper) NewMessageFilter(req whisper.Criteria) (string, error) {
func (w *MockWhisper) NewMessageFilter(req whispertypes.Criteria) (string, error) {
return "", nil
}
func (w *MockWhisper) AddPrivateKey(ctx context.Context, privateKey hexutil.Bytes) (string, error) {
func (w *MockWhisper) AddPrivateKey(ctx context.Context, privateKey statusproto.HexBytes) (string, error) {
return "", nil
}
func (w *MockWhisper) DeleteKeyPair(ctx context.Context, key string) (bool, error) {
@ -115,7 +115,7 @@ func (w *MockWhisper) DeleteKeyPair(ctx context.Context, key string) (bool, erro
func (w *MockWhisper) GenerateSymKeyFromPassword(ctx context.Context, passwd string) (string, error) {
return "", nil
}
func (w *MockWhisper) GetFilterMessages(id string) ([]*whisper.Message, error) {
func (w *MockWhisper) GetFilterMessages(id string) ([]*whispertypes.Message, error) {
return w.filterMessages, nil
}
@ -164,7 +164,7 @@ func (s *IncentivisationSuite) TestPerform() {
now := time.Now().Unix()
// Add some envelopes
s.mockWhisper.filterMessages = []*whisper.Message{
s.mockWhisper.filterMessages = []*whispertypes.Message{
{
// We strip the first byte when processing
Sig: append(nodeOne, nodeOne[0]),

View File

@ -9,8 +9,6 @@ import (
"math/big"
"time"
"github.com/ethereum/go-ethereum/common"
"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"
@ -25,6 +23,9 @@ import (
statusproto "github.com/status-im/status-protocol-go"
"github.com/status-im/status-protocol-go/encryption/multidevice"
statustransp "github.com/status-im/status-protocol-go/transport/whisper"
"github.com/status-im/status-protocol-go/transport/whisper/gethbridge"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
statusproto_types "github.com/status-im/status-protocol-go/types"
)
const (
@ -73,10 +74,10 @@ type MessagesRequest struct {
// Topic is a regular Whisper topic.
// DEPRECATED
Topic whisper.TopicType `json:"topic"`
Topic whispertypes.TopicType `json:"topic"`
// Topics is a list of Whisper topics.
Topics []whisper.TopicType `json:"topics"`
Topics []whispertypes.TopicType `json:"topics"`
// SymKeyID is an ID of a symmetric key to authenticate to MailServer.
// It's derived from MailServer password.
@ -146,7 +147,7 @@ type SyncMessagesRequest struct {
// Topics is a list of Whisper topics.
// If empty, a full bloom filter will be used.
Topics []whisper.TopicType `json:"topics"`
Topics []whispertypes.TopicType `json:"topics"`
}
// SyncMessagesResponse is a response from the mail server
@ -177,7 +178,7 @@ type InitiateHistoryRequestParams struct {
// PublicAPI extends whisper public API.
type PublicAPI struct {
service *Service
publicAPI *whisper.PublicWhisperAPI
publicAPI whispertypes.PublicWhisperAPI
log log.Logger
}
@ -185,7 +186,7 @@ type PublicAPI struct {
func NewPublicAPI(s *Service) *PublicAPI {
return &PublicAPI{
service: s,
publicAPI: whisper.NewPublicWhisperAPI(s.w),
publicAPI: s.w.PublicWhisperAPI(),
log: log.New("package", "status-go/services/sshext.PublicAPI"),
}
}
@ -210,9 +211,9 @@ func (api *PublicAPI) RequestMessagesSync(conf RetryConfig, r MessagesRequest) (
var resp MessagesResponse
shh := api.service.w
events := make(chan whisper.EnvelopeEvent, 10)
events := make(chan whispertypes.EnvelopeEvent, 10)
var (
requestID hexutil.Bytes
requestID statusproto_types.HexBytes
err error
retries int
)
@ -227,7 +228,7 @@ func (api *PublicAPI) RequestMessagesSync(conf RetryConfig, r MessagesRequest) (
sub.Unsubscribe()
return resp, err
}
mailServerResp, err := waitForExpiredOrCompleted(common.BytesToHash(requestID), events, timeout)
mailServerResp, err := waitForExpiredOrCompleted(statusproto_types.BytesToHash(requestID), events, timeout)
sub.Unsubscribe()
if err == nil {
resp.Cursor = hex.EncodeToString(mailServerResp.Cursor)
@ -240,12 +241,12 @@ func (api *PublicAPI) RequestMessagesSync(conf RetryConfig, r MessagesRequest) (
return resp, fmt.Errorf("failed to request messages after %d retries", retries)
}
func waitForExpiredOrCompleted(requestID common.Hash, events chan whisper.EnvelopeEvent, timeout time.Duration) (*whisper.MailServerResponse, error) {
func waitForExpiredOrCompleted(requestID statusproto_types.Hash, events chan whispertypes.EnvelopeEvent, timeout time.Duration) (*whispertypes.MailServerResponse, error) {
expired := fmt.Errorf("request %x expired", requestID)
after := time.NewTimer(timeout)
defer after.Stop()
for {
var ev whisper.EnvelopeEvent
var ev whispertypes.EnvelopeEvent
select {
case ev = <-events:
case <-after.C:
@ -255,20 +256,20 @@ func waitForExpiredOrCompleted(requestID common.Hash, events chan whisper.Envelo
continue
}
switch ev.Event {
case whisper.EventMailServerRequestCompleted:
data, ok := ev.Data.(*whisper.MailServerResponse)
case whispertypes.EventMailServerRequestCompleted:
data, ok := ev.Data.(*whispertypes.MailServerResponse)
if ok {
return data, nil
}
return nil, errors.New("invalid event data type")
case whisper.EventMailServerRequestExpired:
case whispertypes.EventMailServerRequestExpired:
return nil, expired
}
}
}
// RequestMessages sends a request for historic messages to a MailServer.
func (api *PublicAPI) RequestMessages(_ context.Context, r MessagesRequest) (hexutil.Bytes, error) {
func (api *PublicAPI) RequestMessages(_ context.Context, r MessagesRequest) (statusproto_types.HexBytes, error) {
api.log.Info("RequestMessages", "request", r)
shh := api.service.w
now := api.service.w.GetCurrentTime()
@ -334,20 +335,20 @@ func (api *PublicAPI) RequestMessages(_ context.Context, r MessagesRequest) (hex
// createSyncMailRequest creates SyncMailRequest. It uses a full bloom filter
// if no topics are given.
func createSyncMailRequest(r SyncMessagesRequest) (whisper.SyncMailRequest, error) {
func createSyncMailRequest(r SyncMessagesRequest) (whispertypes.SyncMailRequest, error) {
var bloom []byte
if len(r.Topics) > 0 {
bloom = topicsToBloom(r.Topics...)
} else {
bloom = whisper.MakeFullNodeBloom()
bloom = whispertypes.MakeFullNodeBloom()
}
cursor, err := hex.DecodeString(r.Cursor)
if err != nil {
return whisper.SyncMailRequest{}, err
return whispertypes.SyncMailRequest{}, err
}
return whisper.SyncMailRequest{
return whispertypes.SyncMailRequest{
Lower: r.From,
Upper: r.To,
Bloom: bloom,
@ -356,7 +357,7 @@ func createSyncMailRequest(r SyncMessagesRequest) (whisper.SyncMailRequest, erro
}, nil
}
func createSyncMessagesResponse(r whisper.SyncEventResponse) SyncMessagesResponse {
func createSyncMessagesResponse(r whispertypes.SyncEventResponse) SyncMessagesResponse {
return SyncMessagesResponse{
Cursor: hex.EncodeToString(r.Cursor),
Error: r.Error,
@ -423,7 +424,7 @@ func (api *PublicAPI) ConfirmMessagesProcessedByID(messageConfirmations []*dedup
// in other words don't use PFS-enabled messages. Otherwise, SendDirectMessage is used.
// It's important to call PublicAPI.afterSend() so that the client receives a signal
// with confirmation that the message left the device.
func (api *PublicAPI) Post(ctx context.Context, newMessage whisper.NewMessage) (hexutil.Bytes, error) {
func (api *PublicAPI) Post(ctx context.Context, newMessage whispertypes.NewMessage) (statusproto_types.HexBytes, error) {
return api.publicAPI.Post(ctx, newMessage)
}
@ -431,7 +432,7 @@ func (api *PublicAPI) Post(ctx context.Context, newMessage whisper.NewMessage) (
// Message's payload is a transit encoded message.
// It's important to call PublicAPI.afterSend() so that the client receives a signal
// with confirmation that the message left the device.
func (api *PublicAPI) SendPublicMessage(ctx context.Context, msg SendPublicMessageRPC) (hexutil.Bytes, error) {
func (api *PublicAPI) SendPublicMessage(ctx context.Context, msg SendPublicMessageRPC) (statusproto_types.HexBytes, error) {
chat := statusproto.Chat{
Name: msg.Chat,
}
@ -442,7 +443,7 @@ func (api *PublicAPI) SendPublicMessage(ctx context.Context, msg SendPublicMessa
// Message's payload is a transit encoded message.
// It's important to call PublicAPI.afterSend() so that the client receives a signal
// with confirmation that the message left the device.
func (api *PublicAPI) SendDirectMessage(ctx context.Context, msg SendDirectMessageRPC) (hexutil.Bytes, error) {
func (api *PublicAPI) SendDirectMessage(ctx context.Context, msg SendDirectMessageRPC) (statusproto_types.HexBytes, error) {
publicKey, err := crypto.UnmarshalPubkey(msg.PubKey)
if err != nil {
return nil, err
@ -454,7 +455,7 @@ func (api *PublicAPI) SendDirectMessage(ctx context.Context, msg SendDirectMessa
return api.service.messenger.SendRaw(ctx, chat, msg.Payload)
}
func (api *PublicAPI) requestMessagesUsingPayload(request db.HistoryRequest, peer, symkeyID string, payload []byte, force bool, timeout time.Duration, topics []whisper.TopicType) (hash common.Hash, err error) {
func (api *PublicAPI) requestMessagesUsingPayload(request db.HistoryRequest, peer, symkeyID string, payload []byte, force bool, timeout time.Duration, topics []whispertypes.TopicType) (hash statusproto_types.Hash, err error) {
shh := api.service.w
now := api.service.w.GetCurrentTime()
@ -518,7 +519,7 @@ func (api *PublicAPI) requestMessagesUsingPayload(request db.HistoryRequest, pee
// - Topic
// - Duration in nanoseconds. Will be used to determine starting time for history request.
// After that status-go will guarantee that request for this topic and date will be performed.
func (api *PublicAPI) InitiateHistoryRequests(parent context.Context, request InitiateHistoryRequestParams) (rst []hexutil.Bytes, err error) {
func (api *PublicAPI) InitiateHistoryRequests(parent context.Context, request InitiateHistoryRequestParams) (rst []statusproto_types.HexBytes, err error) {
tx := api.service.storage.NewTx()
defer func() {
if err == nil {
@ -532,7 +533,7 @@ func (api *PublicAPI) InitiateHistoryRequests(parent context.Context, request In
}
var (
payload []byte
hash common.Hash
hash statusproto_types.Hash
)
for i := range requests {
req := requests[i]
@ -555,7 +556,7 @@ func (api *PublicAPI) InitiateHistoryRequests(parent context.Context, request In
func (api *PublicAPI) CompleteRequest(parent context.Context, hex string) (err error) {
tx := api.service.storage.NewTx()
ctx := NewContextFromService(parent, api.service, tx)
err = api.service.historyUpdates.UpdateFinishedRequest(ctx, common.HexToHash(hex))
err = api.service.historyUpdates.UpdateFinishedRequest(ctx, statusproto_types.HexToHash(hex))
if err == nil {
return tx.Commit()
}
@ -667,7 +668,7 @@ func makeEnvelop(
nodeID *ecdsa.PrivateKey,
pow float64,
now time.Time,
) (*whisper.Envelope, error) {
) (whispertypes.Envelope, error) {
params := whisper.MessageParams{
PoW: pow,
Payload: payload,
@ -685,7 +686,11 @@ func makeEnvelop(
if err != nil {
return nil, err
}
return message.Wrap(&params, now)
envelope, err := message.Wrap(&params, now)
if err != nil {
return nil, err
}
return gethbridge.NewGethEnvelopeWrapper(envelope), nil
}
// makeMessagesRequestPayload makes a specific payload for MailServer
@ -719,13 +724,13 @@ func createBloomFilter(r MessagesRequest) []byte {
return topicsToBloom(r.Topics...)
}
return whisper.TopicToBloom(r.Topic)
return whisper.TopicToBloom(whisper.TopicType(r.Topic))
}
func topicsToBloom(topics ...whisper.TopicType) []byte {
func topicsToBloom(topics ...whispertypes.TopicType) []byte {
i := new(big.Int)
for _, topic := range topics {
bloom := whisper.TopicToBloom(topic)
bloom := whispertypes.TopicToBloom(topic)
i.Or(i, new(big.Int).SetBytes(bloom[:]))
}

View File

@ -7,10 +7,13 @@ import (
"testing"
"time"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
statusproto "github.com/status-im/status-protocol-go/types"
whisper "github.com/status-im/whisper/whisperv6"
"github.com/ethereum/go-ethereum/common"
"github.com/status-im/status-go/mailserver"
whisper "github.com/status-im/whisper/whisperv6"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@ -100,26 +103,26 @@ func TestMakeMessagesRequestPayload(t *testing.T) {
func TestTopicsToBloom(t *testing.T) {
t1 := stringToTopic("t1")
b1 := whisper.TopicToBloom(t1)
b1 := whispertypes.TopicToBloom(t1)
t2 := stringToTopic("t2")
b2 := whisper.TopicToBloom(t2)
b2 := whispertypes.TopicToBloom(t2)
t3 := stringToTopic("t3")
b3 := whisper.TopicToBloom(t3)
b3 := whispertypes.TopicToBloom(t3)
reqBloom := topicsToBloom(t1)
assert.True(t, whisper.BloomFilterMatch(reqBloom, b1))
assert.False(t, whisper.BloomFilterMatch(reqBloom, b2))
assert.False(t, whisper.BloomFilterMatch(reqBloom, b3))
assert.True(t, whispertypes.BloomFilterMatch(reqBloom, b1))
assert.False(t, whispertypes.BloomFilterMatch(reqBloom, b2))
assert.False(t, whispertypes.BloomFilterMatch(reqBloom, b3))
reqBloom = topicsToBloom(t1, t2)
assert.True(t, whisper.BloomFilterMatch(reqBloom, b1))
assert.True(t, whisper.BloomFilterMatch(reqBloom, b2))
assert.False(t, whisper.BloomFilterMatch(reqBloom, b3))
assert.True(t, whispertypes.BloomFilterMatch(reqBloom, b1))
assert.True(t, whispertypes.BloomFilterMatch(reqBloom, b2))
assert.False(t, whispertypes.BloomFilterMatch(reqBloom, b3))
reqBloom = topicsToBloom(t1, t2, t3)
assert.True(t, whisper.BloomFilterMatch(reqBloom, b1))
assert.True(t, whisper.BloomFilterMatch(reqBloom, b2))
assert.True(t, whisper.BloomFilterMatch(reqBloom, b3))
assert.True(t, whispertypes.BloomFilterMatch(reqBloom, b1))
assert.True(t, whispertypes.BloomFilterMatch(reqBloom, b2))
assert.True(t, whispertypes.BloomFilterMatch(reqBloom, b3))
}
func TestCreateBloomFilter(t *testing.T) {
@ -130,36 +133,36 @@ func TestCreateBloomFilter(t *testing.T) {
bloom := createBloomFilter(req)
assert.Equal(t, topicsToBloom(t1), bloom)
req = MessagesRequest{Topics: []whisper.TopicType{t1, t2}}
req = MessagesRequest{Topics: []whispertypes.TopicType{t1, t2}}
bloom = createBloomFilter(req)
assert.Equal(t, topicsToBloom(t1, t2), bloom)
}
func stringToTopic(s string) whisper.TopicType {
return whisper.BytesToTopic([]byte(s))
func stringToTopic(s string) whispertypes.TopicType {
return whispertypes.BytesToTopic([]byte(s))
}
func TestCreateSyncMailRequest(t *testing.T) {
testCases := []struct {
Name string
Req SyncMessagesRequest
Verify func(*testing.T, whisper.SyncMailRequest)
Verify func(*testing.T, whispertypes.SyncMailRequest)
Error string
}{
{
Name: "no topics",
Req: SyncMessagesRequest{},
Verify: func(t *testing.T, r whisper.SyncMailRequest) {
require.Equal(t, whisper.MakeFullNodeBloom(), r.Bloom)
Verify: func(t *testing.T, r whispertypes.SyncMailRequest) {
require.Equal(t, whispertypes.MakeFullNodeBloom(), r.Bloom)
},
},
{
Name: "some topics",
Req: SyncMessagesRequest{
Topics: []whisper.TopicType{{0x01, 0xff, 0xff, 0xff}},
Topics: []whispertypes.TopicType{{0x01, 0xff, 0xff, 0xff}},
},
Verify: func(t *testing.T, r whisper.SyncMailRequest) {
expectedBloom := whisper.TopicToBloom(whisper.TopicType{0x01, 0xff, 0xff, 0xff})
Verify: func(t *testing.T, r whispertypes.SyncMailRequest) {
expectedBloom := whispertypes.TopicToBloom(whispertypes.TopicType{0x01, 0xff, 0xff, 0xff})
require.Equal(t, expectedBloom, r.Bloom)
},
},
@ -168,7 +171,7 @@ func TestCreateSyncMailRequest(t *testing.T) {
Req: SyncMessagesRequest{
Cursor: hex.EncodeToString([]byte{0x01, 0x02, 0x03}),
},
Verify: func(t *testing.T, r whisper.SyncMailRequest) {
Verify: func(t *testing.T, r whispertypes.SyncMailRequest) {
require.Equal(t, []byte{0x01, 0x02, 0x03}, r.Cursor)
},
},
@ -223,9 +226,9 @@ func TestSyncMessagesErrors(t *testing.T) {
func TestExpiredOrCompleted(t *testing.T) {
timeout := time.Millisecond
events := make(chan whisper.EnvelopeEvent)
events := make(chan whispertypes.EnvelopeEvent)
errors := make(chan error, 1)
hash := common.Hash{1}
hash := statusproto.Hash{1}
go func() {
_, err := waitForExpiredOrCompleted(hash, events, timeout)
errors <- err

View File

@ -4,7 +4,7 @@ import (
"time"
"github.com/status-im/status-go/db"
whisper "github.com/status-im/whisper/whisperv6"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
"github.com/syndtr/goleveldb/leveldb"
"github.com/syndtr/goleveldb/leveldb/util"
"golang.org/x/crypto/sha3"
@ -21,7 +21,7 @@ func newCache(db *leveldb.DB) *cache {
return &cache{db, time.Now}
}
func (d *cache) Has(filterID string, message *whisper.Message) (bool, error) {
func (d *cache) Has(filterID string, message *whispertypes.Message) (bool, error) {
has, err := d.db.Has(d.KeyToday(filterID, message), nil)
if err != nil {
@ -34,7 +34,7 @@ func (d *cache) Has(filterID string, message *whisper.Message) (bool, error) {
return d.db.Has(d.keyYesterday(filterID, message), nil)
}
func (d *cache) Put(filterID string, messages []*whisper.Message) error {
func (d *cache) Put(filterID string, messages []*whispertypes.Message) error {
batch := leveldb.Batch{}
for _, msg := range messages {
@ -89,11 +89,11 @@ func (d *cache) cleanOldEntries() error {
return d.db.Write(&batch, nil)
}
func (d *cache) keyYesterday(filterID string, message *whisper.Message) []byte {
func (d *cache) keyYesterday(filterID string, message *whispertypes.Message) []byte {
return prefixedKey(d.yesterdayDateString(), filterID, message)
}
func (d *cache) KeyToday(filterID string, message *whisper.Message) []byte {
func (d *cache) KeyToday(filterID string, message *whispertypes.Message) []byte {
return prefixedKey(d.todayDateString(), filterID, message)
}
@ -112,11 +112,11 @@ func dateString(t time.Time) string {
return t.Format("20060102")
}
func prefixedKey(date, filterID string, message *whisper.Message) []byte {
func prefixedKey(date, filterID string, message *whispertypes.Message) []byte {
return db.Key(db.DeduplicatorCache, []byte(date), []byte(filterID), key(message))
}
func key(message *whisper.Message) []byte {
func key(message *whispertypes.Message) []byte {
data := make([]byte, len(message.Payload)+len(message.Topic))
copy(data[:], message.Payload)
copy(data[len(message.Payload):], message.Topic[:])

View File

@ -3,8 +3,8 @@ package dedup
import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/common/hexutil"
whisper "github.com/status-im/whisper/whisperv6"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
statusproto "github.com/status-im/status-protocol-go/types"
"github.com/syndtr/goleveldb/leveldb"
)
@ -21,21 +21,21 @@ type Deduplicator struct {
}
type Author struct {
PublicKey hexutil.Bytes `json:"publicKey"`
Alias string `json:"alias"`
Identicon string `json:"identicon"`
PublicKey statusproto.HexBytes `json:"publicKey"`
Alias string `json:"alias"`
Identicon string `json:"identicon"`
}
type Metadata struct {
DedupID []byte `json:"dedupId"`
EncryptionID hexutil.Bytes `json:"encryptionId"`
MessageID hexutil.Bytes `json:"messageId"`
Author Author `json:"author"`
DedupID []byte `json:"dedupId"`
EncryptionID statusproto.HexBytes `json:"encryptionId"`
MessageID statusproto.HexBytes `json:"messageId"`
Author Author `json:"author"`
}
type DeduplicateMessage struct {
Message *whisper.Message `json:"message"`
Metadata Metadata `json:"metadata"`
Message *whispertypes.Message `json:"message"`
Metadata Metadata `json:"metadata"`
}
// NewDeduplicator creates a new deduplicator

View File

@ -3,14 +3,14 @@ package dedup
import (
"crypto/rand"
whisper "github.com/status-im/whisper/whisperv6"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
)
func generateMessages(count int) []*whisper.Message {
result := []*whisper.Message{}
func generateMessages(count int) []*whispertypes.Message {
result := []*whispertypes.Message{}
for ; count > 0; count-- {
content := mustGenerateRandomBytes()
result = append(result, &whisper.Message{Payload: content})
result = append(result, &whispertypes.Message{Payload: content})
}
return result
}
@ -21,7 +21,7 @@ func generateDedupMessages(count int) []*DeduplicateMessage {
content := mustGenerateRandomBytes()
result = append(result, &DeduplicateMessage{
Metadata: Metadata{},
Message: &whisper.Message{Payload: content},
Message: &whispertypes.Message{Payload: content},
})
}
return result

View File

@ -7,11 +7,11 @@ import (
"sync"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp"
"github.com/status-im/status-go/db"
"github.com/status-im/status-go/mailserver"
whisper "github.com/status-im/whisper/whisperv6"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
statusproto "github.com/status-im/status-protocol-go/types"
)
const (
@ -36,7 +36,7 @@ type HistoryUpdateReactor struct {
// UpdateFinishedRequest removes successfully finished request and updates every topic
// attached to the request.
func (reactor *HistoryUpdateReactor) UpdateFinishedRequest(ctx Context, id common.Hash) error {
func (reactor *HistoryUpdateReactor) UpdateFinishedRequest(ctx Context, id statusproto.Hash) error {
reactor.mu.Lock()
defer reactor.mu.Unlock()
req, err := ctx.HistoryStore().GetRequest(id)
@ -45,7 +45,7 @@ func (reactor *HistoryUpdateReactor) UpdateFinishedRequest(ctx Context, id commo
}
for i := range req.Histories() {
th := &req.Histories()[i]
th.RequestID = common.Hash{}
th.RequestID = statusproto.Hash{}
th.Current = th.End
th.End = time.Time{}
if err := th.Save(); err != nil {
@ -56,7 +56,7 @@ func (reactor *HistoryUpdateReactor) UpdateFinishedRequest(ctx Context, id commo
}
// UpdateTopicHistory updates Current timestamp for the TopicHistory with a given timestamp.
func (reactor *HistoryUpdateReactor) UpdateTopicHistory(ctx Context, topic whisper.TopicType, timestamp time.Time) error {
func (reactor *HistoryUpdateReactor) UpdateTopicHistory(ctx Context, topic whispertypes.TopicType, timestamp time.Time) error {
reactor.mu.Lock()
defer reactor.mu.Unlock()
histories, err := ctx.HistoryStore().GetHistoriesByTopic(topic)
@ -87,7 +87,7 @@ func (reactor *HistoryUpdateReactor) UpdateTopicHistory(ctx Context, topic whisp
// TopicRequest defines what user has to provide.
type TopicRequest struct {
Topic whisper.TopicType
Topic whispertypes.TopicType
Duration time.Duration
}
@ -96,14 +96,14 @@ type TopicRequest struct {
func (reactor *HistoryUpdateReactor) CreateRequests(ctx Context, topicRequests []TopicRequest) ([]db.HistoryRequest, error) {
reactor.mu.Lock()
defer reactor.mu.Unlock()
seen := map[whisper.TopicType]struct{}{}
seen := map[whispertypes.TopicType]struct{}{}
for i := range topicRequests {
if _, exist := seen[topicRequests[i].Topic]; exist {
return nil, errors.New("only one duration per topic is allowed")
}
seen[topicRequests[i].Topic] = struct{}{}
}
histories := map[whisper.TopicType]db.TopicHistory{}
histories := map[whispertypes.TopicType]db.TopicHistory{}
for i := range topicRequests {
th, err := ctx.HistoryStore().GetHistory(topicRequests[i].Topic, topicRequests[i].Duration)
if err != nil {
@ -250,7 +250,7 @@ func CreateTopicOptionsFromRequest(req db.HistoryRequest) TopicOptions {
return rst
}
func mapToList(topics map[whisper.TopicType]db.TopicHistory) []db.TopicHistory {
func mapToList(topics map[whispertypes.TopicType]db.TopicHistory) []db.TopicHistory {
rst := make([]db.TopicHistory, 0, len(topics))
for key := range topics {
rst = append(rst, topics[key])
@ -289,7 +289,7 @@ type Range struct {
// TopicOption request for a single topic.
type TopicOption struct {
Topic whisper.TopicType
Topic whispertypes.TopicType
Range Range
}
@ -298,7 +298,7 @@ type TopicOptions []TopicOption
// ToBloomFilterOption creates bloom filter request from a list of topics.
func (options TopicOptions) ToBloomFilterOption() BloomFilterOption {
topics := make([]whisper.TopicType, len(options))
topics := make([]whispertypes.TopicType, len(options))
var start, end uint64
for i := range options {
opt := options[i]
@ -318,8 +318,8 @@ func (options TopicOptions) ToBloomFilterOption() BloomFilterOption {
}
// Topics returns list of whisper TopicType attached to each TopicOption.
func (options TopicOptions) Topics() []whisper.TopicType {
rst := make([]whisper.TopicType, len(options))
func (options TopicOptions) Topics() []whispertypes.TopicType {
rst := make([]whispertypes.TopicType, len(options))
for i := range options {
rst[i] = options[i].Topic
}

View File

@ -5,11 +5,11 @@ import (
"testing"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp"
"github.com/status-im/status-go/db"
"github.com/status-im/status-go/mailserver"
whisper "github.com/status-im/whisper/whisperv6"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
statusproto "github.com/status-im/status-protocol-go/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@ -51,7 +51,7 @@ func TestRenewRequest(t *testing.T) {
func TestCreateTopicOptionsFromRequest(t *testing.T) {
req := db.HistoryRequest{}
topic := whisper.TopicType{1}
topic := whispertypes.TopicType{1}
now := time.Now()
req.AddHistory(db.TopicHistory{Topic: topic, Current: now, End: now})
options := CreateTopicOptionsFromRequest(req)
@ -65,8 +65,8 @@ func TestCreateTopicOptionsFromRequest(t *testing.T) {
func TestTopicOptionsToBloom(t *testing.T) {
options := TopicOptions{
{Topic: whisper.TopicType{1}, Range: Range{Start: 1, End: 10}},
{Topic: whisper.TopicType{2}, Range: Range{Start: 3, End: 12}},
{Topic: whispertypes.TopicType{1}, Range: Range{Start: 1, End: 10}},
{Topic: whispertypes.TopicType{2}, Range: Range{Start: 3, End: 12}},
}
bloom := options.ToBloomFilterOption()
require.Equal(t, uint64(3), bloom.Range.Start, "Start must be the latest Start across all options")
@ -105,9 +105,9 @@ func TestCreateRequestsEmptyState(t *testing.T) {
ctx := newTestContext(t)
reactor := NewHistoryUpdateReactor()
requests, err := reactor.CreateRequests(ctx, []TopicRequest{
{Topic: whisper.TopicType{1}, Duration: time.Hour},
{Topic: whisper.TopicType{2}, Duration: time.Hour},
{Topic: whisper.TopicType{3}, Duration: 10 * time.Hour},
{Topic: whispertypes.TopicType{1}, Duration: time.Hour},
{Topic: whispertypes.TopicType{2}, Duration: time.Hour},
{Topic: whispertypes.TopicType{3}, Duration: 10 * time.Hour},
})
require.NoError(t, err)
require.Len(t, requests, 2)
@ -128,15 +128,15 @@ func TestCreateRequestsWithExistingRequest(t *testing.T) {
ctx := newTestContext(t)
store := ctx.HistoryStore()
req := store.NewRequest()
req.ID = common.Hash{1}
th := store.NewHistory(whisper.TopicType{1}, time.Hour)
req.ID = statusproto.Hash{1}
th := store.NewHistory(whispertypes.TopicType{1}, time.Hour)
req.AddHistory(th)
require.NoError(t, req.Save())
reactor := NewHistoryUpdateReactor()
requests, err := reactor.CreateRequests(ctx, []TopicRequest{
{Topic: whisper.TopicType{1}, Duration: time.Hour},
{Topic: whisper.TopicType{2}, Duration: time.Hour},
{Topic: whisper.TopicType{3}, Duration: time.Hour},
{Topic: whispertypes.TopicType{1}, Duration: time.Hour},
{Topic: whispertypes.TopicType{2}, Duration: time.Hour},
{Topic: whispertypes.TopicType{3}, Duration: time.Hour},
})
require.NoError(t, err)
require.Len(t, requests, 2)
@ -157,13 +157,13 @@ func TestCreateMultiRequestsWithSameTopic(t *testing.T) {
ctx := newTestContext(t)
store := ctx.HistoryStore()
reactor := NewHistoryUpdateReactor()
topic := whisper.TopicType{1}
topic := whispertypes.TopicType{1}
requests, err := reactor.CreateRequests(ctx, []TopicRequest{
{Topic: topic, Duration: time.Hour},
})
require.NoError(t, err)
require.Len(t, requests, 1)
requests[0].ID = common.Hash{1}
requests[0].ID = statusproto.Hash{1}
require.NoError(t, requests[0].Save())
// duration changed. request wasn't finished
@ -175,7 +175,7 @@ func TestCreateMultiRequestsWithSameTopic(t *testing.T) {
longest := 0
for i := range requests {
r := &requests[i]
r.ID = common.Hash{byte(i)}
r.ID = statusproto.Hash{byte(i)}
require.NoError(t, r.Save())
require.Len(t, r.Histories(), 1)
if r.Histories()[0].Duration == 10*time.Hour {
@ -203,11 +203,11 @@ func TestRequestFinishedUpdate(t *testing.T) {
ctx := newTestContext(t)
store := ctx.HistoryStore()
req := store.NewRequest()
req.ID = common.Hash{1}
req.ID = statusproto.Hash{1}
now := ctx.Time()
thOne := store.NewHistory(whisper.TopicType{1}, time.Hour)
thOne := store.NewHistory(whispertypes.TopicType{1}, time.Hour)
thOne.End = now
thTwo := store.NewHistory(whisper.TopicType{2}, time.Hour)
thTwo := store.NewHistory(whispertypes.TopicType{2}, time.Hour)
thTwo.End = now
req.AddHistory(thOne)
req.AddHistory(thTwo)
@ -228,12 +228,12 @@ func TestRequestFinishedUpdate(t *testing.T) {
func TestTopicHistoryUpdate(t *testing.T) {
ctx := newTestContext(t)
store := ctx.HistoryStore()
reqID := common.Hash{1}
reqID := statusproto.Hash{1}
request := store.NewRequest()
request.ID = reqID
now := time.Now()
require.NoError(t, request.Save())
th := store.NewHistory(whisper.TopicType{1}, time.Hour)
th := store.NewHistory(whispertypes.TopicType{1}, time.Hour)
th.RequestID = request.ID
th.End = now
require.NoError(t, th.Save())
@ -251,12 +251,12 @@ func TestTopicHistoryUpdate(t *testing.T) {
func TestGroupHistoriesByRequestTimestamp(t *testing.T) {
requests := GroupHistoriesByRequestTimespan(createInMemStore(t), []db.TopicHistory{
{Topic: whisper.TopicType{1}, Duration: time.Hour},
{Topic: whisper.TopicType{2}, Duration: time.Hour},
{Topic: whisper.TopicType{3}, Duration: 2 * time.Hour},
{Topic: whisper.TopicType{4}, Duration: 2 * time.Hour},
{Topic: whisper.TopicType{5}, Duration: 3 * time.Hour},
{Topic: whisper.TopicType{6}, Duration: 3 * time.Hour},
{Topic: whispertypes.TopicType{1}, Duration: time.Hour},
{Topic: whispertypes.TopicType{2}, Duration: time.Hour},
{Topic: whispertypes.TopicType{3}, Duration: 2 * time.Hour},
{Topic: whispertypes.TopicType{4}, Duration: 2 * time.Hour},
{Topic: whispertypes.TopicType{5}, Duration: 3 * time.Hour},
{Topic: whispertypes.TopicType{6}, Duration: 3 * time.Hour},
})
require.Len(t, requests, 3)
for _, req := range requests {
@ -267,7 +267,7 @@ func TestGroupHistoriesByRequestTimestamp(t *testing.T) {
// initial creation of the history index. no other histories in store
func TestAdjustHistoryWithNoOtherHistories(t *testing.T) {
store := createInMemStore(t)
th := store.NewHistory(whisper.TopicType{1}, time.Hour)
th := store.NewHistory(whispertypes.TopicType{1}, time.Hour)
adjusted, err := adjustRequestedHistories(store, []db.TopicHistory{th})
require.NoError(t, err)
require.Len(t, adjusted, 1)
@ -281,7 +281,7 @@ func TestAdjustHistoryWithNoOtherHistories(t *testing.T) {
// that covers all of them e.g. {Duration: 4h}
func TestAdjustHistoryWithExistingLowerRanges(t *testing.T) {
store := createInMemStore(t)
topic := whisper.TopicType{1}
topic := whispertypes.TopicType{1}
histories := make([]db.TopicHistory, 3)
i := 0
for i = range histories {
@ -309,7 +309,7 @@ func TestAdjustHistoryWithExistingLowerRanges(t *testing.T) {
// We see that there is no reason to keep all indexes and we can squash them.
func TestAdjustHistoriesWithExistingCoveredLowerRanges(t *testing.T) {
store := createInMemStore(t)
topic := whisper.TopicType{1}
topic := whispertypes.TopicType{1}
histories := make([]db.TopicHistory, 3)
i := 0
now := time.Now()
@ -332,7 +332,7 @@ func TestAdjustHistoriesWithExistingCoveredLowerRanges(t *testing.T) {
func TestAdjustHistoryReplaceTopicWithHigherDuration(t *testing.T) {
store := createInMemStore(t)
topic := whisper.TopicType{1}
topic := whispertypes.TopicType{1}
hour := store.NewHistory(topic, time.Hour)
require.NoError(t, hour.Save())
minute := store.NewHistory(topic, time.Minute)
@ -346,9 +346,9 @@ func TestAdjustHistoryReplaceTopicWithHigherDuration(t *testing.T) {
// it will be discarded and we will use existing index
func TestAdjustHistoryRemoveTopicIfPendingWithHigherDuration(t *testing.T) {
store := createInMemStore(t)
topic := whisper.TopicType{1}
topic := whispertypes.TopicType{1}
hour := store.NewHistory(topic, time.Hour)
hour.RequestID = common.Hash{1}
hour.RequestID = statusproto.Hash{1}
require.NoError(t, hour.Save())
minute := store.NewHistory(topic, time.Minute)
adjusted, err := adjustRequestedHistories(store, []db.TopicHistory{minute})

View File

@ -3,9 +3,9 @@ package shhext
import (
"sync"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
whisper "github.com/status-im/whisper/whisperv6"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
statusproto "github.com/status-im/status-protocol-go/types"
)
// EnvelopeState in local tracker
@ -24,11 +24,11 @@ const (
// MailRequestMonitor is responsible for monitoring history request to mailservers.
type MailRequestMonitor struct {
w *whisper.Whisper
w whispertypes.Whisper
handler EnvelopeEventsHandler
mu sync.Mutex
cache map[common.Hash]EnvelopeState
cache map[statusproto.Hash]EnvelopeState
requestsRegistry *RequestsRegistry
@ -52,7 +52,7 @@ func (m *MailRequestMonitor) Stop() {
m.wg.Wait()
}
func (m *MailRequestMonitor) GetState(hash common.Hash) EnvelopeState {
func (m *MailRequestMonitor) GetState(hash statusproto.Hash) EnvelopeState {
m.mu.Lock()
defer m.mu.Unlock()
state, exist := m.cache[hash]
@ -64,7 +64,7 @@ func (m *MailRequestMonitor) GetState(hash common.Hash) EnvelopeState {
// handleEnvelopeEvents processes whisper envelope events
func (m *MailRequestMonitor) handleEnvelopeEvents() {
events := make(chan whisper.EnvelopeEvent, 100) // must be buffered to prevent blocking whisper
events := make(chan whispertypes.EnvelopeEvent, 100) // must be buffered to prevent blocking whisper
sub := m.w.SubscribeEnvelopeEvents(events)
defer sub.Unsubscribe()
for {
@ -79,11 +79,11 @@ func (m *MailRequestMonitor) handleEnvelopeEvents() {
// handleEvent based on type of the event either triggers
// confirmation handler or removes hash from MailRequestMonitor
func (m *MailRequestMonitor) handleEvent(event whisper.EnvelopeEvent) {
handlers := map[whisper.EventType]func(whisper.EnvelopeEvent){
whisper.EventMailServerRequestSent: m.handleRequestSent,
whisper.EventMailServerRequestCompleted: m.handleEventMailServerRequestCompleted,
whisper.EventMailServerRequestExpired: m.handleEventMailServerRequestExpired,
func (m *MailRequestMonitor) handleEvent(event whispertypes.EnvelopeEvent) {
handlers := map[whispertypes.EventType]func(whispertypes.EnvelopeEvent){
whispertypes.EventMailServerRequestSent: m.handleRequestSent,
whispertypes.EventMailServerRequestCompleted: m.handleEventMailServerRequestCompleted,
whispertypes.EventMailServerRequestExpired: m.handleEventMailServerRequestExpired,
}
if handler, ok := handlers[event.Event]; ok {
@ -91,13 +91,13 @@ func (m *MailRequestMonitor) handleEvent(event whisper.EnvelopeEvent) {
}
}
func (m *MailRequestMonitor) handleRequestSent(event whisper.EnvelopeEvent) {
func (m *MailRequestMonitor) handleRequestSent(event whispertypes.EnvelopeEvent) {
m.mu.Lock()
defer m.mu.Unlock()
m.cache[event.Hash] = MailServerRequestSent
}
func (m *MailRequestMonitor) handleEventMailServerRequestCompleted(event whisper.EnvelopeEvent) {
func (m *MailRequestMonitor) handleEventMailServerRequestCompleted(event whispertypes.EnvelopeEvent) {
m.mu.Lock()
defer m.mu.Unlock()
m.requestsRegistry.Unregister(event.Hash)
@ -108,13 +108,13 @@ func (m *MailRequestMonitor) handleEventMailServerRequestCompleted(event whisper
log.Debug("mailserver response received", "hash", event.Hash)
delete(m.cache, event.Hash)
if m.handler != nil {
if resp, ok := event.Data.(*whisper.MailServerResponse); ok {
if resp, ok := event.Data.(*whispertypes.MailServerResponse); ok {
m.handler.MailServerRequestCompleted(event.Hash, resp.LastEnvelopeHash, resp.Cursor, resp.Error)
}
}
}
func (m *MailRequestMonitor) handleEventMailServerRequestExpired(event whisper.EnvelopeEvent) {
func (m *MailRequestMonitor) handleEventMailServerRequestExpired(event whispertypes.EnvelopeEvent) {
m.mu.Lock()
defer m.mu.Unlock()
m.requestsRegistry.Unregister(event.Hash)

View File

@ -5,13 +5,13 @@ import (
"testing"
"time"
"github.com/ethereum/go-ethereum/common"
whisper "github.com/status-im/whisper/whisperv6"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
statusproto "github.com/status-im/status-protocol-go/types"
"github.com/stretchr/testify/suite"
)
var (
testHash = common.Hash{0x01}
testHash = statusproto.Hash{0x01}
)
func TestMailRequestMonitorSuite(t *testing.T) {
@ -26,7 +26,7 @@ type MailRequestMonitorSuite struct {
func (s *MailRequestMonitorSuite) SetupTest() {
s.monitor = &MailRequestMonitor{
cache: map[common.Hash]EnvelopeState{},
cache: map[statusproto.Hash]EnvelopeState{},
requestsRegistry: NewRequestsRegistry(0),
}
}
@ -35,10 +35,10 @@ func (s *MailRequestMonitorSuite) TestRequestCompleted() {
mock := newHandlerMock(1)
s.monitor.handler = mock
s.monitor.cache[testHash] = MailServerRequestSent
s.monitor.handleEvent(whisper.EnvelopeEvent{
Event: whisper.EventMailServerRequestCompleted,
s.monitor.handleEvent(whispertypes.EnvelopeEvent{
Event: whispertypes.EventMailServerRequestCompleted,
Hash: testHash,
Data: &whisper.MailServerResponse{},
Data: &whispertypes.MailServerResponse{},
})
select {
case requestID := <-mock.requestsCompleted:
@ -53,10 +53,10 @@ func (s *MailRequestMonitorSuite) TestRequestFailed() {
mock := newHandlerMock(1)
s.monitor.handler = mock
s.monitor.cache[testHash] = MailServerRequestSent
s.monitor.handleEvent(whisper.EnvelopeEvent{
Event: whisper.EventMailServerRequestCompleted,
s.monitor.handleEvent(whispertypes.EnvelopeEvent{
Event: whispertypes.EventMailServerRequestCompleted,
Hash: testHash,
Data: &whisper.MailServerResponse{Error: errors.New("test error")},
Data: &whispertypes.MailServerResponse{Error: errors.New("test error")},
})
select {
case requestID := <-mock.requestsFailed:
@ -71,8 +71,8 @@ func (s *MailRequestMonitorSuite) TestRequestExpiration() {
mock := newHandlerMock(1)
s.monitor.handler = mock
s.monitor.cache[testHash] = MailServerRequestSent
s.monitor.handleEvent(whisper.EnvelopeEvent{
Event: whisper.EventMailServerRequestExpired,
s.monitor.handleEvent(whispertypes.EnvelopeEvent{
Event: whispertypes.EventMailServerRequestExpired,
Hash: testHash,
})
select {

View File

@ -6,6 +6,7 @@ import (
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/status-im/status-go/db"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
"github.com/syndtr/goleveldb/leveldb"
"github.com/syndtr/goleveldb/leveldb/iterator"
"github.com/syndtr/goleveldb/leveldb/util"
@ -67,8 +68,8 @@ func (c *Cache) Replace(nodes []*enode.Node) error {
if err != nil {
return err
}
if _, exist := newNodes[record.ID()]; exist {
delete(newNodes, record.ID())
if _, exist := newNodes[whispertypes.EnodeID(record.ID())]; exist {
delete(newNodes, whispertypes.EnodeID(record.ID()))
} else {
batch.Delete(iter.Key())
}
@ -124,10 +125,10 @@ func unmarshalKeyValue(key, value []byte) (record PeerRecord, err error) {
return record, err
}
func nodesToMap(nodes []*enode.Node) map[enode.ID]*enode.Node {
rst := map[enode.ID]*enode.Node{}
func nodesToMap(nodes []*enode.Node) map[whispertypes.EnodeID]*enode.Node {
rst := map[whispertypes.EnodeID]*enode.Node{}
for _, n := range nodes {
rst[n.ID()] = n
rst[whispertypes.EnodeID(n.ID())] = n
}
return rst
}

View File

@ -4,12 +4,12 @@ import (
"sync"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode"
whisper "github.com/status-im/whisper/whisperv6"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
statusproto "github.com/status-im/status-protocol-go/types"
)
const (
@ -28,9 +28,9 @@ type PeerEventsSubscriber interface {
SubscribeEvents(chan *p2p.PeerEvent) event.Subscription
}
// EnvelopeEventSubscbriber interface to subscribe for whisper.EnvelopeEvent's.
type EnvelopeEventSubscbriber interface {
SubscribeEnvelopeEvents(chan<- whisper.EnvelopeEvent) event.Subscription
// EnvelopeEventSubscriber interface to subscribe for whispertypes.EnvelopeEvent's.
type EnvelopeEventSubscriber interface {
SubscribeEnvelopeEvents(chan<- whispertypes.EnvelopeEvent) whispertypes.Subscription
}
type p2pServer interface {
@ -39,7 +39,7 @@ type p2pServer interface {
}
// NewConnectionManager creates an instance of ConnectionManager.
func NewConnectionManager(server p2pServer, whisper EnvelopeEventSubscbriber, target, maxFailures int, timeout time.Duration) *ConnectionManager {
func NewConnectionManager(server p2pServer, whisper EnvelopeEventSubscriber, target, maxFailures int, timeout time.Duration) *ConnectionManager {
return &ConnectionManager{
server: server,
whisper: whisper,
@ -56,7 +56,7 @@ type ConnectionManager struct {
quit chan struct{}
server p2pServer
whisper EnvelopeEventSubscbriber
whisper EnvelopeEventSubscriber
notifications chan []*enode.Node
connectedTarget int
@ -85,10 +85,10 @@ func (ps *ConnectionManager) Start() {
state := newInternalState(ps.server, ps.connectedTarget, ps.timeoutWaitAdded)
events := make(chan *p2p.PeerEvent, peerEventsBuffer)
sub := ps.server.SubscribeEvents(events)
whisperEvents := make(chan whisper.EnvelopeEvent, whisperEventsBuffer)
whisperEvents := make(chan whispertypes.EnvelopeEvent, whisperEventsBuffer)
whisperSub := ps.whisper.SubscribeEnvelopeEvents(whisperEvents)
requests := map[common.Hash]struct{}{}
failuresPerServer := map[enode.ID]int{}
requests := map[statusproto.Hash]struct{}{}
failuresPerServer := map[whispertypes.EnodeID]int{}
defer sub.Unsubscribe()
defer whisperSub.Unsubscribe()
@ -110,13 +110,13 @@ func (ps *ConnectionManager) Start() {
case ev := <-whisperEvents:
// TODO treat failed requests the same way as expired
switch ev.Event {
case whisper.EventMailServerRequestSent:
case whispertypes.EventMailServerRequestSent:
requests[ev.Hash] = struct{}{}
case whisper.EventMailServerRequestCompleted:
case whispertypes.EventMailServerRequestCompleted:
// reset failures count on first success
failuresPerServer[ev.Peer] = 0
delete(requests, ev.Hash)
case whisper.EventMailServerRequestExpired:
case whispertypes.EventMailServerRequestExpired:
_, exist := requests[ev.Hash]
if !exist {
continue
@ -148,9 +148,9 @@ func (ps *ConnectionManager) Stop() {
}
func (state *internalState) processReplacement(newNodes []*enode.Node, events <-chan *p2p.PeerEvent) {
replacement := map[enode.ID]*enode.Node{}
replacement := map[whispertypes.EnodeID]*enode.Node{}
for _, n := range newNodes {
replacement[n.ID()] = n
replacement[whispertypes.EnodeID(n.ID())] = n
}
state.replaceNodes(replacement)
if state.ReachedTarget() {
@ -170,8 +170,8 @@ func newInternalState(srv PeerAdderRemover, target int, timeout time.Duration) *
return &internalState{
options: options{target: target, timeout: timeout},
srv: srv,
connected: map[enode.ID]struct{}{},
currentNodes: map[enode.ID]*enode.Node{},
connected: map[whispertypes.EnodeID]struct{}{},
currentNodes: map[whispertypes.EnodeID]*enode.Node{},
}
}
@ -184,15 +184,15 @@ type internalState struct {
options
srv PeerAdderRemover
connected map[enode.ID]struct{}
currentNodes map[enode.ID]*enode.Node
connected map[whispertypes.EnodeID]struct{}
currentNodes map[whispertypes.EnodeID]*enode.Node
}
func (state *internalState) ReachedTarget() bool {
return len(state.connected) >= state.target
}
func (state *internalState) replaceNodes(new map[enode.ID]*enode.Node) {
func (state *internalState) replaceNodes(new map[whispertypes.EnodeID]*enode.Node) {
for nid, n := range state.currentNodes {
if _, exist := new[nid]; !exist {
delete(state.connected, nid)
@ -207,7 +207,7 @@ func (state *internalState) replaceNodes(new map[enode.ID]*enode.Node) {
state.currentNodes = new
}
func (state *internalState) nodeAdded(peer enode.ID) {
func (state *internalState) nodeAdded(peer whispertypes.EnodeID) {
n, exist := state.currentNodes[peer]
if !exist {
return
@ -215,11 +215,11 @@ func (state *internalState) nodeAdded(peer enode.ID) {
if state.ReachedTarget() {
state.srv.RemovePeer(n)
} else {
state.connected[n.ID()] = struct{}{}
state.connected[whispertypes.EnodeID(n.ID())] = struct{}{}
}
}
func (state *internalState) nodeDisconnected(peer enode.ID) {
func (state *internalState) nodeDisconnected(peer whispertypes.EnodeID) {
n, exist := state.currentNodes[peer] // unrelated event
if !exist {
return
@ -248,10 +248,10 @@ func processPeerEvent(state *internalState, ev *p2p.PeerEvent) {
switch ev.Type {
case p2p.PeerEventTypeAdd:
log.Debug("connected to a mailserver", "address", ev.Peer)
state.nodeAdded(ev.Peer)
state.nodeAdded(whispertypes.EnodeID(ev.Peer))
case p2p.PeerEventTypeDrop:
log.Debug("mailserver disconnected", "address", ev.Peer)
state.nodeDisconnected(ev.Peer)
state.nodeDisconnected(whispertypes.EnodeID(ev.Peer))
}
}

View File

@ -6,25 +6,25 @@ import (
"testing"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/status-im/status-go/t/utils"
whisper "github.com/status-im/whisper/whisperv6"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
statusproto "github.com/status-im/status-protocol-go/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
type fakePeerEvents struct {
mu sync.Mutex
nodes map[enode.ID]struct{}
nodes map[whispertypes.EnodeID]struct{}
input chan *p2p.PeerEvent
}
func (f *fakePeerEvents) Nodes() []enode.ID {
func (f *fakePeerEvents) Nodes() []whispertypes.EnodeID {
f.mu.Lock()
rst := make([]enode.ID, 0, len(f.nodes))
rst := make([]whispertypes.EnodeID, 0, len(f.nodes))
for n := range f.nodes {
rst = append(rst, n)
}
@ -34,7 +34,7 @@ func (f *fakePeerEvents) Nodes() []enode.ID {
func (f *fakePeerEvents) AddPeer(node *enode.Node) {
f.mu.Lock()
f.nodes[node.ID()] = struct{}{}
f.nodes[whispertypes.EnodeID(node.ID())] = struct{}{}
f.mu.Unlock()
if f.input == nil {
return
@ -47,7 +47,7 @@ func (f *fakePeerEvents) AddPeer(node *enode.Node) {
func (f *fakePeerEvents) RemovePeer(node *enode.Node) {
f.mu.Lock()
delete(f.nodes, node.ID())
delete(f.nodes, whispertypes.EnodeID(node.ID()))
f.mu.Unlock()
if f.input == nil {
return
@ -59,7 +59,7 @@ func (f *fakePeerEvents) RemovePeer(node *enode.Node) {
}
func newFakePeerAdderRemover() *fakePeerEvents {
return &fakePeerEvents{nodes: map[enode.ID]struct{}{}}
return &fakePeerEvents{nodes: map[whispertypes.EnodeID]struct{}{}}
}
func (f *fakePeerEvents) SubscribeEvents(output chan *p2p.PeerEvent) event.Subscription {
@ -83,10 +83,10 @@ func newFakeServer() *fakePeerEvents {
}
type fakeEnvelopeEvents struct {
input chan whisper.EnvelopeEvent
input chan whispertypes.EnvelopeEvent
}
func (f *fakeEnvelopeEvents) SubscribeEnvelopeEvents(output chan<- whisper.EnvelopeEvent) event.Subscription {
func (f *fakeEnvelopeEvents) SubscribeEnvelopeEvents(output chan<- whispertypes.EnvelopeEvent) whispertypes.Subscription {
return event.NewSubscription(func(quit <-chan struct{}) error {
for {
select {
@ -102,7 +102,7 @@ func (f *fakeEnvelopeEvents) SubscribeEnvelopeEvents(output chan<- whisper.Envel
func newFakeEnvelopesEvents() *fakeEnvelopeEvents {
return &fakeEnvelopeEvents{
input: make(chan whisper.EnvelopeEvent),
input: make(chan whispertypes.EnvelopeEvent),
}
}
@ -114,13 +114,13 @@ func fillWithRandomNodes(t *testing.T, nodes []*enode.Node) {
}
}
func getMapWithRandomNodes(t *testing.T, n int) map[enode.ID]*enode.Node {
func getMapWithRandomNodes(t *testing.T, n int) map[whispertypes.EnodeID]*enode.Node {
nodes := make([]*enode.Node, n)
fillWithRandomNodes(t, nodes)
return nodesToMap(nodes)
}
func mergeOldIntoNew(old, new map[enode.ID]*enode.Node) {
func mergeOldIntoNew(old, new map[whispertypes.EnodeID]*enode.Node) {
for n := range old {
new[n] = old[n]
}
@ -129,8 +129,8 @@ func mergeOldIntoNew(old, new map[enode.ID]*enode.Node) {
func TestReplaceNodes(t *testing.T) {
type testCase struct {
description string
old map[enode.ID]*enode.Node
new map[enode.ID]*enode.Node
old map[whispertypes.EnodeID]*enode.Node
new map[whispertypes.EnodeID]*enode.Node
target int
}
for _, tc := range []testCase{
@ -183,7 +183,7 @@ func TestPartialReplaceNodesAboveTarget(t *testing.T) {
new := getMapWithRandomNodes(t, 2)
state := newInternalState(peers, 1, 0)
state.replaceNodes(old)
state.nodeAdded(initial.ID())
state.nodeAdded(whispertypes.EnodeID(initial.ID()))
mergeOldIntoNew(old, new)
state.replaceNodes(new)
require.Len(t, peers.nodes, 1)
@ -209,7 +209,7 @@ func TestConnectionManagerAddDrop(t *testing.T) {
if len(nodes) != target {
return fmt.Errorf("unexpected number of connected servers: %d", len(nodes))
}
initial = nodes[0]
initial = enode.ID(nodes[0])
return nil
}, time.Second, 100*time.Millisecond))
// Send an event that peer was dropped.
@ -224,7 +224,7 @@ func TestConnectionManagerAddDrop(t *testing.T) {
if len(nodes) != target {
return fmt.Errorf("unexpected number of connected servers: %d", len(nodes))
}
if nodes[0] == initial {
if enode.ID(nodes[0]) == initial {
return fmt.Errorf("connected node wasn't changed from %s", initial)
}
return nil
@ -250,7 +250,7 @@ func TestConnectionManagerReplace(t *testing.T) {
if len(connected) != target {
return fmt.Errorf("unexpected number of connected servers: %d", len(connected))
}
if nodes[0].ID() != connected[0] {
if whispertypes.EnodeID(nodes[0].ID()) != connected[0] {
return fmt.Errorf("connected with a wrong peer. expected %s, got %s", nodes[0].ID(), connected[0])
}
return nil
@ -263,7 +263,7 @@ func TestConnectionManagerReplace(t *testing.T) {
if len(connected) != target {
return fmt.Errorf("unexpected number of connected servers: %d", len(connected))
}
switch connected[0] {
switch enode.ID(connected[0]) {
case nodes[1].ID():
case nodes[2].ID():
default:
@ -273,7 +273,7 @@ func TestConnectionManagerReplace(t *testing.T) {
}, time.Second, 100*time.Millisecond))
}
func setupTestConnectionAfterExpiry(t *testing.T, server *fakePeerEvents, whisperMock *fakeEnvelopeEvents, target, maxFailures int, hash common.Hash) (*ConnectionManager, enode.ID) {
func setupTestConnectionAfterExpiry(t *testing.T, server *fakePeerEvents, whisperMock *fakeEnvelopeEvents, target, maxFailures int, hash statusproto.Hash) (*ConnectionManager, whispertypes.EnodeID) {
connmanager := NewConnectionManager(server, whisperMock, target, maxFailures, 0)
connmanager.Start()
nodes := []*enode.Node{}
@ -282,7 +282,7 @@ func setupTestConnectionAfterExpiry(t *testing.T, server *fakePeerEvents, whispe
}
// Send two random nodes to connection manager.
connmanager.Notify(nodes)
var initial enode.ID
var initial whispertypes.EnodeID
// Wait until connection manager establishes connection with one node.
require.NoError(t, utils.Eventually(func() error {
nodes := server.Nodes()
@ -294,8 +294,8 @@ func setupTestConnectionAfterExpiry(t *testing.T, server *fakePeerEvents, whispe
}, time.Second, 100*time.Millisecond))
// Send event that history request for connected peer was sent.
select {
case whisperMock.input <- whisper.EnvelopeEvent{
Event: whisper.EventMailServerRequestSent, Peer: initial, Hash: hash}:
case whisperMock.input <- whispertypes.EnvelopeEvent{
Event: whispertypes.EventMailServerRequestSent, Peer: initial, Hash: hash}:
case <-time.After(time.Second):
require.FailNow(t, "can't send a 'sent' event")
}
@ -307,14 +307,14 @@ func TestConnectionChangedAfterExpiry(t *testing.T) {
whisperMock := newFakeEnvelopesEvents()
target := 1
maxFailures := 1
hash := common.Hash{1}
hash := statusproto.Hash{1}
connmanager, initial := setupTestConnectionAfterExpiry(t, server, whisperMock, target, maxFailures, hash)
defer connmanager.Stop()
// And eventually expired.
select {
case whisperMock.input <- whisper.EnvelopeEvent{
Event: whisper.EventMailServerRequestExpired, Peer: initial, Hash: hash}:
case whisperMock.input <- whispertypes.EnvelopeEvent{
Event: whispertypes.EventMailServerRequestExpired, Peer: initial, Hash: hash}:
case <-time.After(time.Second):
require.FailNow(t, "can't send an 'expiry' event")
}
@ -335,14 +335,14 @@ func TestConnectionChangedAfterSecondExpiry(t *testing.T) {
whisperMock := newFakeEnvelopesEvents()
target := 1
maxFailures := 2
hash := common.Hash{1}
hash := statusproto.Hash{1}
connmanager, initial := setupTestConnectionAfterExpiry(t, server, whisperMock, target, maxFailures, hash)
defer connmanager.Stop()
// First expired is sent. Nothing should happen.
select {
case whisperMock.input <- whisper.EnvelopeEvent{
Event: whisper.EventMailServerRequestExpired, Peer: initial, Hash: hash}:
case whisperMock.input <- whispertypes.EnvelopeEvent{
Event: whispertypes.EventMailServerRequestExpired, Peer: initial, Hash: hash}:
case <-time.After(time.Second):
require.FailNow(t, "can't send an 'expiry' event")
}
@ -361,8 +361,8 @@ func TestConnectionChangedAfterSecondExpiry(t *testing.T) {
// second expiry event
select {
case whisperMock.input <- whisper.EnvelopeEvent{
Event: whisper.EventMailServerRequestExpired, Peer: initial, Hash: hash}:
case whisperMock.input <- whispertypes.EnvelopeEvent{
Event: whispertypes.EventMailServerRequestExpired, Peer: initial, Hash: hash}:
case <-time.After(time.Second):
require.FailNow(t, "can't send an 'expiry' event")
}

View File

@ -5,12 +5,11 @@ import (
"time"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p/enode"
whisper "github.com/status-im/whisper/whisperv6"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
)
// NewLastUsedConnectionMonitor returns pointer to the instance of LastUsedConnectionMonitor.
func NewLastUsedConnectionMonitor(ps *PeerStore, cache *Cache, whisper EnvelopeEventSubscbriber) *LastUsedConnectionMonitor {
func NewLastUsedConnectionMonitor(ps *PeerStore, cache *Cache, whisper EnvelopeEventSubscriber) *LastUsedConnectionMonitor {
return &LastUsedConnectionMonitor{
ps: ps,
cache: cache,
@ -23,7 +22,7 @@ type LastUsedConnectionMonitor struct {
ps *PeerStore
cache *Cache
whisper EnvelopeEventSubscbriber
whisper EnvelopeEventSubscriber
quit chan struct{}
wg sync.WaitGroup
@ -34,7 +33,7 @@ func (mon *LastUsedConnectionMonitor) Start() {
mon.quit = make(chan struct{})
mon.wg.Add(1)
go func() {
events := make(chan whisper.EnvelopeEvent, whisperEventsBuffer)
events := make(chan whispertypes.EnvelopeEvent, whisperEventsBuffer)
sub := mon.whisper.SubscribeEnvelopeEvents(events)
defer sub.Unsubscribe()
defer mon.wg.Done()
@ -50,7 +49,7 @@ func (mon *LastUsedConnectionMonitor) Start() {
if node == nil {
continue
}
if ev.Event == whisper.EventMailServerRequestCompleted {
if ev.Event == whispertypes.EventMailServerRequestCompleted {
err := mon.updateRecord(ev.Peer)
if err != nil {
log.Error("unable to update storage", "peer", ev.Peer, "error", err)
@ -61,7 +60,7 @@ func (mon *LastUsedConnectionMonitor) Start() {
}()
}
func (mon *LastUsedConnectionMonitor) updateRecord(nodeID enode.ID) error {
func (mon *LastUsedConnectionMonitor) updateRecord(nodeID whispertypes.EnodeID) error {
node := mon.ps.Get(nodeID)
if node == nil {
return nil

View File

@ -8,7 +8,7 @@ import (
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/status-im/status-go/t/utils"
whisper "github.com/status-im/whisper/whisperv6"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
"github.com/stretchr/testify/require"
)
@ -25,8 +25,8 @@ func TestUsedConnectionPersisted(t *testing.T) {
// Send a confirmation that we received history from one of the peers.
select {
case whisperMock.input <- whisper.EnvelopeEvent{
Event: whisper.EventMailServerRequestCompleted, Peer: nodes[0].ID()}:
case whisperMock.input <- whispertypes.EnvelopeEvent{
Event: whispertypes.EventMailServerRequestCompleted, Peer: whispertypes.EnodeID(nodes[0].ID())}:
case <-time.After(time.Second):
require.FailNow(t, "can't send a 'completed' event")
}
@ -47,15 +47,15 @@ func TestUsedConnectionPersisted(t *testing.T) {
}
}
if !used {
return fmt.Errorf("record %s is not marked as used", nodes[0].ID())
return fmt.Errorf("record %s is not marked as used", whispertypes.EnodeID(nodes[0].ID()))
}
return nil
}, time.Second, 100*time.Millisecond))
// Use different peer, first will be marked as unused.
select {
case whisperMock.input <- whisper.EnvelopeEvent{
Event: whisper.EventMailServerRequestCompleted, Peer: nodes[1].ID()}:
case whisperMock.input <- whispertypes.EnvelopeEvent{
Event: whispertypes.EventMailServerRequestCompleted, Peer: whispertypes.EnodeID(nodes[1].ID())}:
case <-time.After(time.Second):
require.FailNow(t, "can't send a 'completed' event")
}

View File

@ -6,6 +6,7 @@ import (
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
)
var (
@ -21,7 +22,7 @@ type PeersProvider interface {
// NewPeerStore returns an instance of PeerStore.
func NewPeerStore(cache *Cache) *PeerStore {
return &PeerStore{
nodes: map[enode.ID]*enode.Node{},
nodes: map[whispertypes.EnodeID]*enode.Node{},
cache: cache,
}
}
@ -29,13 +30,13 @@ func NewPeerStore(cache *Cache) *PeerStore {
// PeerStore stores list of selected mail servers and keeps N of them connected.
type PeerStore struct {
mu sync.RWMutex
nodes map[enode.ID]*enode.Node
nodes map[whispertypes.EnodeID]*enode.Node
cache *Cache
}
// Exist confirms that peers was added to a store.
func (ps *PeerStore) Exist(nodeID enode.ID) bool {
func (ps *PeerStore) Exist(nodeID whispertypes.EnodeID) bool {
ps.mu.RLock()
defer ps.mu.RUnlock()
_, exist := ps.nodes[nodeID]
@ -43,7 +44,7 @@ func (ps *PeerStore) Exist(nodeID enode.ID) bool {
}
// Get returns instance of the node with requested ID or nil if ID is not found.
func (ps *PeerStore) Get(nodeID enode.ID) *enode.Node {
func (ps *PeerStore) Get(nodeID whispertypes.EnodeID) *enode.Node {
ps.mu.RLock()
defer ps.mu.RUnlock()
return ps.nodes[nodeID]
@ -52,9 +53,9 @@ func (ps *PeerStore) Get(nodeID enode.ID) *enode.Node {
// Update updates peers locally.
func (ps *PeerStore) Update(nodes []*enode.Node) error {
ps.mu.Lock()
ps.nodes = map[enode.ID]*enode.Node{}
ps.nodes = map[whispertypes.EnodeID]*enode.Node{}
for _, n := range nodes {
ps.nodes[n.ID()] = n
ps.nodes[whispertypes.EnodeID(n.ID())] = n
}
ps.mu.Unlock()
return ps.cache.Replace(nodes)

View File

@ -6,6 +6,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
"github.com/stretchr/testify/require"
)
@ -24,11 +25,11 @@ func TestUpdateResetsInternalStorage(t *testing.T) {
r2, err := RandomNode()
require.NoError(t, err)
require.NoError(t, store.Update([]*enode.Node{r1, r2}))
require.True(t, store.Exist(r1.ID()))
require.True(t, store.Exist(r2.ID()))
require.True(t, store.Exist(whispertypes.EnodeID(r1.ID())))
require.True(t, store.Exist(whispertypes.EnodeID(r2.ID())))
require.NoError(t, store.Update([]*enode.Node{r2}))
require.False(t, store.Exist(r1.ID()))
require.True(t, store.Exist(r2.ID()))
require.False(t, store.Exist(whispertypes.EnodeID(r1.ID())))
require.True(t, store.Exist(whispertypes.EnodeID(r2.ID())))
}
func TestGetNodeByID(t *testing.T) {
@ -36,8 +37,8 @@ func TestGetNodeByID(t *testing.T) {
r1, err := RandomNode()
require.NoError(t, err)
require.NoError(t, store.Update([]*enode.Node{r1}))
require.Equal(t, r1, store.Get(r1.ID()))
require.Nil(t, store.Get(enode.ID{1}))
require.Equal(t, r1, store.Get(whispertypes.EnodeID(r1.ID())))
require.Nil(t, store.Get(whispertypes.EnodeID{1}))
}
type fakePeerProvider struct {

View File

@ -4,6 +4,7 @@ import (
"sort"
"github.com/ethereum/go-ethereum/p2p/enode"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
)
// GetFirstConnected returns first connected peer that is also added to a peer store.
@ -11,7 +12,7 @@ import (
func GetFirstConnected(provider PeersProvider, store *PeerStore) (*enode.Node, error) {
peers := provider.Peers()
for _, p := range peers {
if store.Exist(p.ID()) {
if store.Exist(whispertypes.EnodeID(p.ID())) {
return p.Node(), nil
}
}

View File

@ -6,6 +6,7 @@ import (
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
"github.com/stretchr/testify/require"
)
@ -27,7 +28,7 @@ func TestGetFirstConnected(t *testing.T) {
require.NoError(t, store.Update(nodes))
node, err := GetFirstConnected(provider, store)
require.NoError(t, err)
require.Contains(t, nodesMap, node.ID())
require.Contains(t, nodesMap, whispertypes.EnodeID(node.ID()))
}
type trackingNodeNotifee struct {

View File

@ -6,8 +6,8 @@ import (
"sync"
"time"
"github.com/ethereum/go-ethereum/common"
whisper "github.com/status-im/whisper/whisperv6"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
statusproto "github.com/status-im/status-protocol-go/types"
)
const (
@ -17,7 +17,7 @@ const (
type requestMeta struct {
timestamp time.Time
lastUID common.Hash
lastUID statusproto.Hash
}
// NewRequestsRegistry creates instance of the RequestsRegistry and returns pointer to it.
@ -33,13 +33,13 @@ func NewRequestsRegistry(delay time.Duration) *RequestsRegistry {
type RequestsRegistry struct {
mu sync.Mutex
delay time.Duration
uidToTopics map[common.Hash]common.Hash
byTopicsHash map[common.Hash]requestMeta
uidToTopics map[statusproto.Hash]statusproto.Hash
byTopicsHash map[statusproto.Hash]requestMeta
}
// Register request with given topics. If request with same topics was made in less then configured delay then error
// will be returned.
func (r *RequestsRegistry) Register(uid common.Hash, topics []whisper.TopicType) error {
func (r *RequestsRegistry) Register(uid statusproto.Hash, topics []whispertypes.TopicType) error {
r.mu.Lock()
defer r.mu.Unlock()
topicsHash := topicsToHash(topics)
@ -58,7 +58,7 @@ func (r *RequestsRegistry) Register(uid common.Hash, topics []whisper.TopicType)
}
// Has returns true if given uid is stored in registry.
func (r *RequestsRegistry) Has(uid common.Hash) bool {
func (r *RequestsRegistry) Has(uid statusproto.Hash) bool {
r.mu.Lock()
defer r.mu.Unlock()
_, exist := r.uidToTopics[uid]
@ -66,7 +66,7 @@ func (r *RequestsRegistry) Has(uid common.Hash) bool {
}
// Unregister removes request with given UID from registry.
func (r *RequestsRegistry) Unregister(uid common.Hash) {
func (r *RequestsRegistry) Unregister(uid statusproto.Hash) {
r.mu.Lock()
defer r.mu.Unlock()
topicsHash, exist := r.uidToTopics[uid]
@ -85,15 +85,15 @@ func (r *RequestsRegistry) Unregister(uid common.Hash) {
func (r *RequestsRegistry) Clear() {
r.mu.Lock()
defer r.mu.Unlock()
r.uidToTopics = map[common.Hash]common.Hash{}
r.byTopicsHash = map[common.Hash]requestMeta{}
r.uidToTopics = map[statusproto.Hash]statusproto.Hash{}
r.byTopicsHash = map[statusproto.Hash]requestMeta{}
}
// topicsToHash returns non-cryptographic hash of the topics.
func topicsToHash(topics []whisper.TopicType) common.Hash {
func topicsToHash(topics []whispertypes.TopicType) statusproto.Hash {
hash := fnv.New32()
for i := range topics {
_, _ = hash.Write(topics[i][:]) // never returns error per documentation
}
return common.BytesToHash(hash.Sum(nil))
return statusproto.BytesToHash(hash.Sum(nil))
}

View File

@ -4,39 +4,39 @@ import (
"testing"
"time"
"github.com/ethereum/go-ethereum/common"
whisper "github.com/status-im/whisper/whisperv6"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
statusproto "github.com/status-im/status-protocol-go/types"
"github.com/stretchr/testify/require"
)
func TestRegisterSameRequests(t *testing.T) {
registry := NewRequestsRegistry(10 * time.Second)
topics := []whisper.TopicType{{1}}
require.NoError(t, registry.Register(common.Hash{1}, topics))
require.Error(t, registry.Register(common.Hash{2}, topics))
topics := []whispertypes.TopicType{{1}}
require.NoError(t, registry.Register(statusproto.Hash{1}, topics))
require.Error(t, registry.Register(statusproto.Hash{2}, topics))
}
func TestRegisterSameRequestsWithoutDelay(t *testing.T) {
registry := NewRequestsRegistry(0)
topics := []whisper.TopicType{{1}}
require.NoError(t, registry.Register(common.Hash{1}, topics))
require.NoError(t, registry.Register(common.Hash{2}, topics))
topics := []whispertypes.TopicType{{1}}
require.NoError(t, registry.Register(statusproto.Hash{1}, topics))
require.NoError(t, registry.Register(statusproto.Hash{2}, topics))
}
func TestRegisterDifferentRequests(t *testing.T) {
registry := NewRequestsRegistry(10 * time.Second)
require.NoError(t, registry.Register(common.Hash{1}, []whisper.TopicType{{1}}))
require.NoError(t, registry.Register(common.Hash{2}, []whisper.TopicType{{2}}))
require.NoError(t, registry.Register(statusproto.Hash{1}, []whispertypes.TopicType{{1}}))
require.NoError(t, registry.Register(statusproto.Hash{2}, []whispertypes.TopicType{{2}}))
}
func TestUnregisterReplacedRequest(t *testing.T) {
registry := NewRequestsRegistry(0)
unreg := common.Hash{1}
topics := []whisper.TopicType{{1}}
unreg := statusproto.Hash{1}
topics := []whispertypes.TopicType{{1}}
require.NoError(t, registry.Register(unreg, topics))
replacement := common.Hash{2}
replacement := statusproto.Hash{2}
require.NoError(t, registry.Register(replacement, topics))
// record should be replaced with common.Hash{2}, so when we will remove unreg it will not affect topics map
// record should be replaced with statusproto.Hash{2}, so when we will remove unreg it will not affect topics map
registry.Unregister(unreg)
record, exist := registry.uidToTopics[replacement]
require.True(t, exist, "replaced record should exist")

View File

@ -6,12 +6,12 @@ import (
"database/sql"
"encoding/hex"
"fmt"
"github.com/status-im/status-go/logutils"
"os"
"path/filepath"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/status-im/status-go/logutils"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/node"
@ -27,7 +27,8 @@ import (
protocol "github.com/status-im/status-protocol-go"
protocolwhisper "github.com/status-im/status-protocol-go/transport/whisper"
whisper "github.com/status-im/whisper/whisperv6"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
statusproto "github.com/status-im/status-protocol-go/types"
"github.com/syndtr/goleveldb/leveldb"
"go.uber.org/zap"
)
@ -43,8 +44,8 @@ const (
type EnvelopeEventsHandler interface {
EnvelopeSent([][]byte)
EnvelopeExpired([][]byte, error)
MailServerRequestCompleted(common.Hash, common.Hash, []byte, error)
MailServerRequestExpired(common.Hash)
MailServerRequestCompleted(statusproto.Hash, statusproto.Hash, []byte, error)
MailServerRequestExpired(statusproto.Hash)
}
// Service is a service that provides some additional Whisper API.
@ -53,7 +54,7 @@ type Service struct {
cancelMessenger chan struct{}
storage db.TransactionalStorage
w *whisper.Whisper
w whispertypes.Whisper
config params.ShhextConfig
mailMonitor *MailRequestMonitor
requestsRegistry *RequestsRegistry
@ -71,7 +72,7 @@ type Service struct {
var _ node.Service = (*Service)(nil)
// New returns a new Service.
func New(w *whisper.Whisper, handler EnvelopeEventsHandler, ldb *leveldb.DB, config params.ShhextConfig) *Service {
func New(w whispertypes.Whisper, handler EnvelopeEventsHandler, ldb *leveldb.DB, config params.ShhextConfig) *Service {
cache := mailservers.NewCache(ldb)
ps := mailservers.NewPeerStore(cache)
delay := defaultRequestsDelay
@ -83,7 +84,7 @@ func New(w *whisper.Whisper, handler EnvelopeEventsHandler, ldb *leveldb.DB, con
mailMonitor := &MailRequestMonitor{
w: w,
handler: handler,
cache: map[common.Hash]EnvelopeState{},
cache: map[statusproto.Hash]EnvelopeState{},
requestsRegistry: requestsRegistry,
}
return &Service{
@ -119,7 +120,7 @@ func (s *Service) InitProtocol(db *sql.DB) error { // nolint: gocyclo
envelopesMonitorConfig := &protocolwhisper.EnvelopesMonitorConfig{
MaxAttempts: s.config.MaxMessageDeliveryAttempts,
MailserverConfirmationsEnabled: s.config.MailServerConfirmations,
IsMailserver: func(peer enode.ID) bool {
IsMailserver: func(peer whispertypes.EnodeID) bool {
return s.peerStore.Exist(peer)
},
EnvelopeEventsHandler: EnvelopeSignalHandler{},
@ -343,7 +344,7 @@ func (s *Service) Stop() error {
return nil
}
func (s *Service) syncMessages(ctx context.Context, mailServerID []byte, r whisper.SyncMailRequest) (resp whisper.SyncEventResponse, err error) {
func (s *Service) syncMessages(ctx context.Context, mailServerID []byte, r whispertypes.SyncMailRequest) (resp whispertypes.SyncEventResponse, err error) {
err = s.w.SyncMessages(mailServerID, r)
if err != nil {
return
@ -351,7 +352,7 @@ func (s *Service) syncMessages(ctx context.Context, mailServerID []byte, r whisp
// Wait for the response which is received asynchronously as a p2p packet.
// This packet handler will send an event which contains the response payload.
events := make(chan whisper.EnvelopeEvent, 1024)
events := make(chan whispertypes.EnvelopeEvent, 1024)
sub := s.w.SubscribeEnvelopeEvents(events)
defer sub.Unsubscribe()
@ -365,7 +366,7 @@ func (s *Service) syncMessages(ctx context.Context, mailServerID []byte, r whisp
for {
select {
case event := <-events:
if event.Event != whisper.EventMailServerSyncFinished {
if event.Event != whispertypes.EventMailServerSyncFinished {
continue
}
@ -373,7 +374,7 @@ func (s *Service) syncMessages(ctx context.Context, mailServerID []byte, r whisp
var ok bool
resp, ok = event.Data.(whisper.SyncEventResponse)
resp, ok = event.Data.(whispertypes.SyncEventResponse)
if !ok {
err = fmt.Errorf("did not understand the response event data")
return

View File

@ -23,6 +23,9 @@ import (
"github.com/status-im/status-go/sqlite"
"github.com/status-im/status-go/t/helpers"
"github.com/status-im/status-go/t/utils"
"github.com/status-im/status-protocol-go/transport/whisper/gethbridge"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
statusproto "github.com/status-im/status-protocol-go/types"
whisper "github.com/status-im/whisper/whisperv6"
"github.com/stretchr/testify/suite"
"github.com/syndtr/goleveldb/leveldb"
@ -44,18 +47,18 @@ func newHandlerMock(buf int) handlerMock {
return handlerMock{
confirmations: make(chan [][]byte, buf),
expirations: make(chan failureMessage, buf),
requestsCompleted: make(chan common.Hash, buf),
requestsExpired: make(chan common.Hash, buf),
requestsFailed: make(chan common.Hash, buf),
requestsCompleted: make(chan statusproto.Hash, buf),
requestsExpired: make(chan statusproto.Hash, buf),
requestsFailed: make(chan statusproto.Hash, buf),
}
}
type handlerMock struct {
confirmations chan [][]byte
expirations chan failureMessage
requestsCompleted chan common.Hash
requestsExpired chan common.Hash
requestsFailed chan common.Hash
requestsCompleted chan statusproto.Hash
requestsExpired chan statusproto.Hash
requestsFailed chan statusproto.Hash
}
func (t handlerMock) EnvelopeSent(ids [][]byte) {
@ -66,7 +69,7 @@ func (t handlerMock) EnvelopeExpired(ids [][]byte, err error) {
t.expirations <- failureMessage{IDs: ids, Error: err}
}
func (t handlerMock) MailServerRequestCompleted(requestID common.Hash, lastEnvelopeHash common.Hash, cursor []byte, err error) {
func (t handlerMock) MailServerRequestCompleted(requestID statusproto.Hash, lastEnvelopeHash statusproto.Hash, cursor []byte, err error) {
if err == nil {
t.requestsCompleted <- requestID
} else {
@ -74,7 +77,7 @@ func (t handlerMock) MailServerRequestCompleted(requestID common.Hash, lastEnvel
}
}
func (t handlerMock) MailServerRequestExpired(hash common.Hash) {
func (t handlerMock) MailServerRequestExpired(hash statusproto.Hash) {
t.requestsExpired <- hash
}
@ -87,13 +90,13 @@ type ShhExtSuite struct {
nodes []*node.Node
services []*Service
whisper []*whisper.Whisper
whisper []whispertypes.Whisper
}
func (s *ShhExtSuite) SetupTest() {
s.nodes = make([]*node.Node, 2)
s.services = make([]*Service, 2)
s.whisper = make([]*whisper.Whisper, 2)
s.whisper = make([]whispertypes.Whisper, 2)
directory, err := ioutil.TempDir("", "status-go-testing")
s.Require().NoError(err)
@ -111,7 +114,7 @@ func (s *ShhExtSuite) SetupTest() {
}
stack, err := node.New(cfg)
s.NoError(err)
s.whisper[i] = whisper.New(nil)
s.whisper[i] = gethbridge.NewGethWhisperWrapper(whisper.New(nil))
privateKey, err := crypto.GenerateKey()
s.NoError(err)
@ -119,7 +122,7 @@ func (s *ShhExtSuite) SetupTest() {
s.NoError(err)
s.NoError(stack.Register(func(n *node.ServiceContext) (node.Service, error) {
return s.whisper[i], nil
return gethbridge.GetGethWhisperFrom(s.whisper[i]), nil
}))
config := params.ShhextConfig{
@ -162,7 +165,7 @@ func (s *ShhExtSuite) TestInitProtocol() {
db, err := leveldb.Open(storage.NewMemStorage(), nil)
s.Require().NoError(err)
shh := whisper.New(nil)
shh := gethbridge.NewGethWhisperWrapper(whisper.New(nil))
privateKey, err := crypto.GenerateKey()
s.Require().NoError(err)
err = shh.SelectKeyPair(privateKey)
@ -183,7 +186,7 @@ func (s *ShhExtSuite) TestInitProtocol() {
func (s *ShhExtSuite) TestRequestMessagesErrors() {
var err error
shh := whisper.New(nil)
shh := gethbridge.NewGethWhisperWrapper(whisper.New(nil))
aNode, err := node.New(&node.Config{
P2P: p2p.Config{
MaxPeers: math.MaxInt32,
@ -193,7 +196,7 @@ func (s *ShhExtSuite) TestRequestMessagesErrors() {
}) // in-memory node as no data dir
s.NoError(err)
err = aNode.Register(func(*node.ServiceContext) (node.Service, error) {
return shh, nil
return gethbridge.GetGethWhisperFrom(shh), nil
})
s.NoError(err)
@ -256,15 +259,15 @@ func (s *ShhExtSuite) TestMultipleRequestMessagesWithoutForce() {
s.NoError(err)
s.NoError(client.Call(nil, "shhext_requestMessages", MessagesRequest{
MailServerPeer: s.nodes[1].Server().Self().URLv4(),
Topics: []whisper.TopicType{{1}},
Topics: []whispertypes.TopicType{{1}},
}))
s.EqualError(client.Call(nil, "shhext_requestMessages", MessagesRequest{
MailServerPeer: s.nodes[1].Server().Self().URLv4(),
Topics: []whisper.TopicType{{1}},
Topics: []whispertypes.TopicType{{1}},
}), "another request with the same topics was sent less than 3s ago. Please wait for a bit longer, or set `force` to true in request parameters")
s.NoError(client.Call(nil, "shhext_requestMessages", MessagesRequest{
MailServerPeer: s.nodes[1].Server().Self().URLv4(),
Topics: []whisper.TopicType{{2}},
Topics: []whispertypes.TopicType{{2}},
}))
}
@ -273,7 +276,7 @@ func (s *ShhExtSuite) TestFailedRequestUnregistered() {
s.nodes[0].Server().AddPeer(s.nodes[1].Server().Self())
s.Require().NoError(<-waitErr)
client, err := s.nodes[0].Attach()
topics := []whisper.TopicType{{1}}
topics := []whispertypes.TopicType{{1}}
s.NoError(err)
s.EqualError(client.Call(nil, "shhext_requestMessages", MessagesRequest{
MailServerPeer: "enode://19872f94b1e776da3a13e25afa71b47dfa99e658afd6427ea8d6e03c22a99f13590205a8826443e95a37eee1d815fc433af7a8ca9a8d0df7943d1f55684045b7@0.0.0.0:30305",
@ -288,7 +291,7 @@ func (s *ShhExtSuite) TestFailedRequestUnregistered() {
func (s *ShhExtSuite) TestRequestMessagesSuccess() {
var err error
shh := whisper.New(nil)
shh := gethbridge.NewGethWhisperWrapper(whisper.New(nil))
privateKey, err := crypto.GenerateKey()
s.Require().NoError(err)
err = shh.SelectKeyPair(privateKey)
@ -301,7 +304,7 @@ func (s *ShhExtSuite) TestRequestMessagesSuccess() {
NoUSB: true,
}) // in-memory node as no data dir
s.Require().NoError(err)
err = aNode.Register(func(*node.ServiceContext) (node.Service, error) { return shh, nil })
err = aNode.Register(func(*node.ServiceContext) (node.Service, error) { return gethbridge.GetGethWhisperFrom(shh), nil })
s.Require().NoError(err)
err = aNode.Start()
@ -408,10 +411,11 @@ func (s *WhisperNodeMockSuite) SetupTest() {
err := w.HandlePeer(peer, rw2)
errorc <- err
}()
s.Require().NoError(p2p.ExpectMsg(rw1, statusCode, []interface{}{whisper.ProtocolVersion, math.Float64bits(w.MinPow()), w.BloomFilter(), false, true}))
s.Require().NoError(p2p.SendItems(rw1, statusCode, whisper.ProtocolVersion, whisper.ProtocolVersion, math.Float64bits(w.MinPow()), w.BloomFilter(), true, true))
whisperWrapper := gethbridge.NewGethWhisperWrapper(w)
s.Require().NoError(p2p.ExpectMsg(rw1, statusCode, []interface{}{whisper.ProtocolVersion, math.Float64bits(whisperWrapper.MinPow()), whisperWrapper.BloomFilter(), false, true}))
s.Require().NoError(p2p.SendItems(rw1, statusCode, whisper.ProtocolVersion, whisper.ProtocolVersion, math.Float64bits(whisperWrapper.MinPow()), whisperWrapper.BloomFilter(), true, true))
s.localService = New(w, nil, db, params.ShhextConfig{MailServerConfirmations: true, MaxMessageDeliveryAttempts: 3})
s.localService = New(whisperWrapper, nil, db, params.ShhextConfig{MailServerConfirmations: true, MaxMessageDeliveryAttempts: 3})
s.Require().NoError(s.localService.UpdateMailservers([]*enode.Node{node}))
s.localWhisperAPI = whisper.NewPublicWhisperAPI(w)
@ -514,7 +518,7 @@ type RequestWithTrackingHistorySuite struct {
envelopeSymkey string
envelopeSymkeyID string
localWhisperAPI *whisper.PublicWhisperAPI
localWhisperAPI whispertypes.PublicWhisperAPI
localAPI *PublicAPI
localService *Service
localContext Context
@ -532,10 +536,11 @@ func (s *RequestWithTrackingHistorySuite) SetupTest() {
MinimumAcceptedPOW: 0,
MaxMessageSize: 100 << 10,
}
local := whisper.New(conf)
s.Require().NoError(local.Start(nil))
localSHH := whisper.New(conf)
local := gethbridge.NewGethWhisperWrapper(localSHH)
s.Require().NoError(localSHH.Start(nil))
s.localWhisperAPI = whisper.NewPublicWhisperAPI(local)
s.localWhisperAPI = local.PublicWhisperAPI()
s.localService = New(local, nil, db, params.ShhextConfig{})
s.localContext = NewContextFromService(context.Background(), s.localService, s.localService.storage)
localPkey, err := crypto.GenerateKey()
@ -551,15 +556,15 @@ func (s *RequestWithTrackingHistorySuite) SetupTest() {
s.Require().NoError(s.localService.Start(&p2p.Server{Config: p2p.Config{PrivateKey: localPkey}}))
s.localAPI = NewPublicAPI(s.localService)
remote := whisper.New(conf)
s.remoteWhisper = remote
s.Require().NoError(remote.Start(nil))
remoteSHH := whisper.New(conf)
s.remoteWhisper = remoteSHH
s.Require().NoError(remoteSHH.Start(nil))
s.remoteMailserver = &mailserver.WMailServer{}
remote.RegisterServer(s.remoteMailserver)
remoteSHH.RegisterServer(s.remoteMailserver)
password := "test"
tmpdir, err = ioutil.TempDir("", "tracking-history-tests-")
s.Require().NoError(err)
s.Require().NoError(s.remoteMailserver.Init(remote, &params.WhisperConfig{
s.Require().NoError(s.remoteMailserver.Init(remoteSHH, &params.WhisperConfig{
DataDir: tmpdir,
MailServerPassword: password,
}))
@ -573,11 +578,11 @@ func (s *RequestWithTrackingHistorySuite) SetupTest() {
// FIXME close this in tear down
rw1, rw2 := p2p.MsgPipe()
go func() {
err := local.HandlePeer(remotePeer, rw1)
err := localSHH.HandlePeer(remotePeer, rw1)
s.Require().NoError(err)
}()
go func() {
err := remote.HandlePeer(localPeer, rw2)
err := remoteSHH.HandlePeer(localPeer, rw2)
s.Require().NoError(err)
}()
s.mailSymKey, err = s.localWhisperAPI.GenerateSymKeyFromPassword(context.Background(), password)
@ -588,13 +593,13 @@ func (s *RequestWithTrackingHistorySuite) SetupTest() {
s.Require().NoError(err)
}
func (s *RequestWithTrackingHistorySuite) postEnvelopes(topics ...whisper.TopicType) []hexutil.Bytes {
func (s *RequestWithTrackingHistorySuite) postEnvelopes(topics ...whispertypes.TopicType) []hexutil.Bytes {
var (
rst = make([]hexutil.Bytes, len(topics))
err error
)
for i, t := range topics {
rst[i], err = s.localWhisperAPI.Post(context.Background(), whisper.NewMessage{
rst[i], err = s.localWhisperAPI.Post(context.Background(), whispertypes.NewMessage{
SymKeyID: s.envelopeSymkeyID,
TTL: 10,
Topic: t,
@ -612,8 +617,8 @@ func (s *RequestWithTrackingHistorySuite) waitForArchival(hexes []hexutil.Bytes)
s.Require().NoError(waitForArchival(events, 2*time.Second, hexes...))
}
func (s *RequestWithTrackingHistorySuite) createEmptyFilter(topics ...whisper.TopicType) string {
filterid, err := s.localWhisperAPI.NewMessageFilter(whisper.Criteria{
func (s *RequestWithTrackingHistorySuite) createEmptyFilter(topics ...whispertypes.TopicType) string {
filterid, err := s.localWhisperAPI.NewMessageFilter(whispertypes.Criteria{
SymKeyID: s.envelopeSymkeyID,
Topics: topics,
AllowP2P: true,
@ -627,7 +632,7 @@ func (s *RequestWithTrackingHistorySuite) createEmptyFilter(topics ...whisper.To
return filterid
}
func (s *RequestWithTrackingHistorySuite) initiateHistoryRequest(topics ...TopicRequest) []hexutil.Bytes {
func (s *RequestWithTrackingHistorySuite) initiateHistoryRequest(topics ...TopicRequest) []statusproto.HexBytes {
requests, err := s.localAPI.InitiateHistoryRequests(context.Background(), InitiateHistoryRequestParams{
Peer: s.remoteNode.String(),
SymKeyID: s.mailSymKey,
@ -651,7 +656,6 @@ func (s *RequestWithTrackingHistorySuite) waitMessagesDelivered(filterid string,
}
return nil
}, 2*time.Second, 200*time.Millisecond))
}
func (s *RequestWithTrackingHistorySuite) waitNoRequests() {
@ -669,9 +673,9 @@ func (s *RequestWithTrackingHistorySuite) waitNoRequests() {
}
func (s *RequestWithTrackingHistorySuite) TestMultipleMergeIntoOne() {
topic1 := whisper.TopicType{1, 1, 1, 1}
topic2 := whisper.TopicType{2, 2, 2, 2}
topic3 := whisper.TopicType{3, 3, 3, 3}
topic1 := whispertypes.TopicType{1, 1, 1, 1}
topic2 := whispertypes.TopicType{2, 2, 2, 2}
topic3 := whispertypes.TopicType{3, 3, 3, 3}
hexes := s.postEnvelopes(topic1, topic2, topic3)
s.waitForArchival(hexes)
@ -683,6 +687,7 @@ func (s *RequestWithTrackingHistorySuite) TestMultipleMergeIntoOne() {
)
// since we are using different duration for 3rd topic there will be 2 requests
s.Require().Len(requests, 2)
s.Require().NotEqual(requests[0], requests[1])
s.waitMessagesDelivered(filterid, hexes...)
s.Require().NoError(s.localService.historyUpdates.UpdateTopicHistory(s.localContext, topic1, time.Now()))
@ -702,8 +707,8 @@ func (s *RequestWithTrackingHistorySuite) TestMultipleMergeIntoOne() {
}
func (s *RequestWithTrackingHistorySuite) TestSingleRequest() {
topic1 := whisper.TopicType{1, 1, 1, 1}
topic2 := whisper.TopicType{255, 255, 255, 255}
topic1 := whispertypes.TopicType{1, 1, 1, 1}
topic2 := whispertypes.TopicType{255, 255, 255, 255}
hexes := s.postEnvelopes(topic1, topic2)
s.waitForArchival(hexes)
@ -717,8 +722,8 @@ func (s *RequestWithTrackingHistorySuite) TestSingleRequest() {
}
func (s *RequestWithTrackingHistorySuite) TestPreviousRequestReplaced() {
topic1 := whisper.TopicType{1, 1, 1, 1}
topic2 := whisper.TopicType{255, 255, 255, 255}
topic1 := whispertypes.TopicType{1, 1, 1, 1}
topic2 := whispertypes.TopicType{255, 255, 255, 255}
requests := s.initiateHistoryRequest(
TopicRequest{Topic: topic1, Duration: time.Hour},

View File

@ -1,8 +1,8 @@
package shhext
import (
"github.com/ethereum/go-ethereum/common"
"github.com/status-im/status-go/signal"
statusproto "github.com/status-im/status-protocol-go/types"
)
// EnvelopeSignalHandler sends signals when envelope is sent or expired.
@ -19,12 +19,12 @@ func (h EnvelopeSignalHandler) EnvelopeExpired(identifiers [][]byte, err error)
}
// MailServerRequestCompleted triggered when the mailserver sends a message to notify that the request has been completed
func (h EnvelopeSignalHandler) MailServerRequestCompleted(requestID common.Hash, lastEnvelopeHash common.Hash, cursor []byte, err error) {
func (h EnvelopeSignalHandler) MailServerRequestCompleted(requestID statusproto.Hash, lastEnvelopeHash statusproto.Hash, cursor []byte, err error) {
signal.SendMailServerRequestCompleted(requestID, lastEnvelopeHash, cursor, err)
}
// MailServerRequestExpired triggered when the mailserver request expires
func (h EnvelopeSignalHandler) MailServerRequestExpired(hash common.Hash) {
func (h EnvelopeSignalHandler) MailServerRequestExpired(hash statusproto.Hash) {
signal.SendMailServerRequestExpired(hash)
}

View File

@ -11,13 +11,3 @@ var DiscoveryTopicBytes = ToTopic(discoveryTopic)
func ToTopic(s string) whisper.TopicType {
return whisper.BytesToTopic(crypto.Keccak256([]byte(s)))
}
func DefaultWhisperMessage() whisper.NewMessage {
msg := whisper.NewMessage{}
msg.TTL = 10
msg.PowTarget = 0.002
msg.PowTime = 1
return msg
}

View File

@ -3,12 +3,12 @@ package signal
import (
"encoding/hex"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/status-im/status-go/services/shhext/dedup"
whisper "github.com/status-im/whisper/whisperv6"
statustransp "github.com/status-im/status-protocol-go/transport/whisper"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
statusproto "github.com/status-im/status-protocol-go/types"
)
const (
@ -46,17 +46,17 @@ const (
// EnvelopeSignal includes hash of the envelope.
type EnvelopeSignal struct {
IDs []hexutil.Bytes `json:"ids"`
Hash common.Hash `json:"hash"`
Message string `json:"message"`
IDs []hexutil.Bytes `json:"ids"`
Hash statusproto.Hash `json:"hash"`
Message string `json:"message"`
}
// MailServerResponseSignal holds the data received in the response from the mailserver.
type MailServerResponseSignal struct {
RequestID common.Hash `json:"requestID"`
LastEnvelopeHash common.Hash `json:"lastEnvelopeHash"`
Cursor string `json:"cursor"`
ErrorMsg string `json:"errorMessage"`
RequestID statusproto.Hash `json:"requestID"`
LastEnvelopeHash statusproto.Hash `json:"lastEnvelopeHash"`
Cursor string `json:"cursor"`
ErrorMsg string `json:"errorMessage"`
}
// DecryptMessageFailedSignal holds the sender of the message that could not be decrypted
@ -82,7 +82,7 @@ type Filter struct {
// Identity is the public key of the other recipient for non-public chats
Identity string `json:"identity"`
// Topic is the whisper topic
Topic whisper.TopicType `json:"topic"`
Topic whispertypes.TopicType `json:"topic"`
}
type WhisperFilterAddedSignal struct {
@ -121,7 +121,7 @@ func SendEnvelopeExpired(identifiers [][]byte, err error) {
}
// SendMailServerRequestCompleted triggered when mail server response has been received
func SendMailServerRequestCompleted(requestID common.Hash, lastEnvelopeHash common.Hash, cursor []byte, err error) {
func SendMailServerRequestCompleted(requestID statusproto.Hash, lastEnvelopeHash statusproto.Hash, cursor []byte, err error) {
errorMsg := ""
if err != nil {
errorMsg = err.Error()
@ -136,7 +136,7 @@ func SendMailServerRequestCompleted(requestID common.Hash, lastEnvelopeHash comm
}
// SendMailServerRequestExpired triggered when mail server request expires
func SendMailServerRequestExpired(hash common.Hash) {
func SendMailServerRequestExpired(hash statusproto.Hash) {
send(EventMailServerRequestExpired, EnvelopeSignal{Hash: hash})
}

View File

@ -10,6 +10,8 @@ import (
"github.com/ethereum/go-ethereum/node"
"github.com/status-im/status-go/params"
"github.com/status-im/status-go/services/shhext"
"github.com/status-im/status-protocol-go/transport/whisper/gethbridge"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
whisper "github.com/status-im/whisper/whisperv6"
"github.com/stretchr/testify/require"
)
@ -41,7 +43,7 @@ func testMailserverPeer(t *testing.T) {
BackupDisabledDataDir: os.TempDir(),
InstallationID: "1",
}
mailService := shhext.New(shhService, nil, nil, config)
mailService := shhext.New(gethbridge.NewGethWhisperWrapper(shhService), nil, nil, config)
shhextAPI := shhext.NewPublicAPI(mailService)
// create node with services
@ -88,7 +90,7 @@ func testMailserverPeer(t *testing.T) {
requestID, err := shhextAPI.RequestMessages(context.TODO(), shhext.MessagesRequest{
MailServerPeer: *peerURL,
SymKeyID: symKeyID,
Topic: topic,
Topic: whispertypes.TopicType(topic),
})
require.NoError(t, err)
require.NotNil(t, requestID)

View File

@ -2,9 +2,4 @@
.DS_Store
/server/server.exe
/server/server
/server/server_dar*
/server/server_fre*
/server/server_win*
/server/server_net*
/server/server_ope*
CHANGELOG.md

View File

@ -14,7 +14,7 @@ before_install:
- go get github.com/mattn/goveralls
- go get golang.org/x/tools/cmd/cover
- go get golang.org/x/tools/cmd/goimports
- go get golang.org/x/lint/golint
- go get github.com/golang/lint/golint
- go get github.com/stretchr/testify/assert
- go get github.com/gordonklaus/ineffassign

View File

@ -46,15 +46,10 @@ config := bigcache.Config {
// if value is reached then the oldest entries can be overridden for the new ones
// 0 value means no size limit
HardMaxCacheSize: 8192,
// callback fired when the oldest entry is removed because of its expiration time or no space left
// for the new entry, or because delete was called. A bitmask representing the reason will be returned.
// Default value is nil which means no callback and it prevents from unwrapping the oldest entry.
// callback fired when the oldest entry is removed because of its
// expiration time or no space left for the new entry. Default value is nil which
// means no callback and it prevents from unwrapping the oldest entry.
OnRemove: nil,
// OnRemoveWithReason is a callback fired when the oldest entry is removed because of its expiration time or no space left
// for the new entry, or because delete was called. A constant representing the reason will be passed through.
// Default value is nil which means no callback and it prevents from unwrapping the oldest entry.
// Ignored if OnRemove is specified.
OnRemoveWithReason: nil,
}
cache, initErr := bigcache.NewBigCache(config)
@ -79,20 +74,20 @@ Benchmark tests were made using an i7-6700K with 32GB of RAM on Windows 10.
```bash
cd caches_bench; go test -bench=. -benchtime=10s ./... -timeout 30m
BenchmarkMapSet-8 3000000 569 ns/op 202 B/op 3 allocs/op
BenchmarkConcurrentMapSet-8 1000000 1592 ns/op 347 B/op 8 allocs/op
BenchmarkFreeCacheSet-8 3000000 775 ns/op 355 B/op 2 allocs/op
BenchmarkBigCacheSet-8 3000000 640 ns/op 303 B/op 2 allocs/op
BenchmarkMapGet-8 5000000 407 ns/op 24 B/op 1 allocs/op
BenchmarkConcurrentMapGet-8 3000000 558 ns/op 24 B/op 2 allocs/op
BenchmarkFreeCacheGet-8 2000000 682 ns/op 136 B/op 2 allocs/op
BenchmarkBigCacheGet-8 3000000 512 ns/op 152 B/op 4 allocs/op
BenchmarkBigCacheSetParallel-8 10000000 225 ns/op 313 B/op 3 allocs/op
BenchmarkFreeCacheSetParallel-8 10000000 218 ns/op 341 B/op 3 allocs/op
BenchmarkConcurrentMapSetParallel-8 5000000 318 ns/op 200 B/op 6 allocs/op
BenchmarkBigCacheGetParallel-8 20000000 178 ns/op 152 B/op 4 allocs/op
BenchmarkFreeCacheGetParallel-8 20000000 295 ns/op 136 B/op 3 allocs/op
BenchmarkConcurrentMapGetParallel-8 10000000 237 ns/op 24 B/op 2 allocs/op
BenchmarkMapSet-8 2000000 716 ns/op 336 B/op 3 allocs/op
BenchmarkConcurrentMapSet-8 1000000 1292 ns/op 347 B/op 8 allocs/op
BenchmarkFreeCacheSet-8 3000000 501 ns/op 371 B/op 3 allocs/op
BenchmarkBigCacheSet-8 3000000 482 ns/op 303 B/op 2 allocs/op
BenchmarkMapGet-8 5000000 309 ns/op 24 B/op 1 allocs/op
BenchmarkConcurrentMapGet-8 2000000 659 ns/op 24 B/op 2 allocs/op
BenchmarkFreeCacheGet-8 3000000 541 ns/op 152 B/op 3 allocs/op
BenchmarkBigCacheGet-8 3000000 420 ns/op 152 B/op 3 allocs/op
BenchmarkBigCacheSetParallel-8 10000000 184 ns/op 313 B/op 3 allocs/op
BenchmarkFreeCacheSetParallel-8 10000000 195 ns/op 357 B/op 4 allocs/op
BenchmarkConcurrentMapSetParallel-8 5000000 242 ns/op 200 B/op 6 allocs/op
BenchmarkBigCacheGetParallel-8 20000000 100 ns/op 152 B/op 4 allocs/op
BenchmarkFreeCacheGetParallel-8 10000000 133 ns/op 152 B/op 4 allocs/op
BenchmarkConcurrentMapGetParallel-8 10000000 202 ns/op 24 B/op 2 allocs/op
```
Writes and reads in bigcache are faster than in freecache.

View File

@ -10,7 +10,7 @@ const (
)
// BigCache is fast, concurrent, evicting cache created to keep big number of entries without impact on performance.
// It keeps entries on heap but omits GC for them. To achieve that, operations take place on byte arrays,
// It keeps entries on heap but omits GC for them. To achieve that operations on bytes arrays take place,
// therefore entries (de)serialization in front of the cache will be needed in most use cases.
type BigCache struct {
shards []*cacheShard
@ -20,22 +20,8 @@ type BigCache struct {
config Config
shardMask uint64
maxShardSize uint32
close chan struct{}
}
// RemoveReason is a value used to signal to the user why a particular key was removed in the OnRemove callback.
type RemoveReason uint32
const (
// Expired means the key is past its LifeWindow.
Expired RemoveReason = iota
// NoSpace means the key is the oldest and the cache size was at its maximum when Set was called, or the
// entry exceeded the maximum shard size.
NoSpace
// Deleted means Delete was called and this key was removed as a result.
Deleted
)
// NewBigCache initialize new instance of BigCache
func NewBigCache(config Config) (*BigCache, error) {
return newBigCache(config, &systemClock{})
@ -59,16 +45,13 @@ func newBigCache(config Config, clock clock) (*BigCache, error) {
config: config,
shardMask: uint64(config.Shards - 1),
maxShardSize: uint32(config.maximumShardSize()),
close: make(chan struct{}),
}
var onRemove func(wrappedEntry []byte, reason RemoveReason)
if config.OnRemove != nil {
onRemove = cache.providedOnRemove
} else if config.OnRemoveWithReason != nil {
onRemove = cache.providedOnRemoveWithReason
} else {
var onRemove func(wrappedEntry []byte)
if config.OnRemove == nil {
onRemove = cache.notProvidedOnRemove
} else {
onRemove = cache.providedOnRemove
}
for i := 0; i < config.Shards; i++ {
@ -77,15 +60,8 @@ func newBigCache(config Config, clock clock) (*BigCache, error) {
if config.CleanWindow > 0 {
go func() {
ticker := time.NewTicker(config.CleanWindow)
defer ticker.Stop()
for {
select {
case t := <-ticker.C:
cache.cleanUp(uint64(t.Unix()))
case <-cache.close:
return
}
for t := range time.Tick(config.CleanWindow) {
cache.cleanUp(uint64(t.Unix()))
}
}()
}
@ -93,16 +69,8 @@ func newBigCache(config Config, clock clock) (*BigCache, error) {
return cache, nil
}
// Close is used to signal a shutdown of the cache when you are done with it.
// This allows the cleaning goroutines to exit and ensures references are not
// kept to the cache preventing GC of the entire cache.
func (c *BigCache) Close() error {
close(c.close)
return nil
}
// Get reads entry for the key.
// It returns an ErrEntryNotFound when
// It returns an EntryNotFoundError when
// no entry exists for the given key.
func (c *BigCache) Get(key string) ([]byte, error) {
hashedKey := c.hash.Sum64(key)
@ -141,15 +109,6 @@ func (c *BigCache) Len() int {
return len
}
// Capacity returns amount of bytes store in the cache.
func (c *BigCache) Capacity() int {
var len int
for _, shard := range c.shards {
len += shard.capacity()
}
return len
}
// Stats returns cache's statistics
func (c *BigCache) Stats() Stats {
var s Stats
@ -169,10 +128,10 @@ func (c *BigCache) Iterator() *EntryInfoIterator {
return newIterator(c)
}
func (c *BigCache) onEvict(oldestEntry []byte, currentTimestamp uint64, evict func(reason RemoveReason) error) bool {
func (c *BigCache) onEvict(oldestEntry []byte, currentTimestamp uint64, evict func() error) bool {
oldestTimestamp := readTimestampFromEntry(oldestEntry)
if currentTimestamp-oldestTimestamp > c.lifeWindow {
evict(Expired)
evict()
return true
}
return false
@ -188,15 +147,9 @@ func (c *BigCache) getShard(hashedKey uint64) (shard *cacheShard) {
return c.shards[hashedKey&c.shardMask]
}
func (c *BigCache) providedOnRemove(wrappedEntry []byte, reason RemoveReason) {
func (c *BigCache) providedOnRemove(wrappedEntry []byte) {
c.config.OnRemove(readKeyFromEntry(wrappedEntry), readEntry(wrappedEntry))
}
func (c *BigCache) providedOnRemoveWithReason(wrappedEntry []byte, reason RemoveReason) {
if c.config.onRemoveFilter == 0 || (1<<uint(reason))&c.config.onRemoveFilter > 0 {
c.config.OnRemoveWithReason(readKeyFromEntry(wrappedEntry), readEntry(wrappedEntry), reason)
}
}
func (c *BigCache) notProvidedOnRemove(wrappedEntry []byte, reason RemoveReason) {
func (c *BigCache) notProvidedOnRemove(wrappedEntry []byte) {
}

View File

@ -1,14 +0,0 @@
// +build !appengine
package bigcache
import (
"reflect"
"unsafe"
)
func bytesToString(b []byte) string {
bytesHeader := (*reflect.SliceHeader)(unsafe.Pointer(&b))
strHeader := reflect.StringHeader{Data: bytesHeader.Data, Len: bytesHeader.Len}
return *(*string)(unsafe.Pointer(&strHeader))
}

View File

@ -1,7 +0,0 @@
// +build appengine
package bigcache
func bytesToString(b []byte) string {
return string(b)
}

View File

@ -26,16 +26,8 @@ type Config struct {
// the oldest entries are overridden for the new ones.
HardMaxCacheSize int
// OnRemove is a callback fired when the oldest entry is removed because of its expiration time or no space left
// for the new entry, or because delete was called.
// Default value is nil which means no callback and it prevents from unwrapping the oldest entry.
// for the new entry. Default value is nil which means no callback and it prevents from unwrapping the oldest entry.
OnRemove func(key string, entry []byte)
// OnRemoveWithReason is a callback fired when the oldest entry is removed because of its expiration time or no space left
// for the new entry, or because delete was called. A constant representing the reason will be passed through.
// Default value is nil which means no callback and it prevents from unwrapping the oldest entry.
// Ignored if OnRemove is specified.
OnRemoveWithReason func(key string, entry []byte, reason RemoveReason)
onRemoveFilter int
// Logger is a logging interface and used in combination with `Verbose`
// Defaults to `DefaultLogger()`
@ -73,14 +65,3 @@ func (c Config) maximumShardSize() int {
return maxShardSize
}
// OnRemoveFilterSet sets which remove reasons will trigger a call to OnRemoveWithReason.
// Filtering out reasons prevents bigcache from unwrapping them, which saves cpu.
func (c Config) OnRemoveFilterSet(reasons ...RemoveReason) Config {
c.onRemoveFilter = 0
for i := range reasons {
c.onRemoveFilter |= 1 << uint(reasons[i])
}
return c
}

View File

@ -2,6 +2,8 @@ package bigcache
import (
"encoding/binary"
"reflect"
"unsafe"
)
const (
@ -53,6 +55,12 @@ func readKeyFromEntry(data []byte) string {
return bytesToString(dst)
}
func bytesToString(b []byte) string {
bytesHeader := (*reflect.SliceHeader)(unsafe.Pointer(&b))
strHeader := reflect.StringHeader{Data: bytesHeader.Data, Len: bytesHeader.Len}
return *(*string)(unsafe.Pointer(&strHeader))
}
func readHashFromEntry(data []byte) uint64 {
return binary.LittleEndian.Uint64(data[timestampSizeInBytes:])
}

View File

@ -1,6 +1,17 @@
package bigcache
import "errors"
import "fmt"
// ErrEntryNotFound is an error type struct which is returned when entry was not found for provided key
var ErrEntryNotFound = errors.New("Entry not found")
// EntryNotFoundError is an error type struct which is returned when entry was not found for provided key
type EntryNotFoundError struct {
message string
}
func notFound(key string) error {
return &EntryNotFoundError{fmt.Sprintf("Entry %q not found", key)}
}
// Error returned when entry does not exist.
func (e EntryNotFoundError) Error() string {
return e.message
}

View File

@ -16,12 +16,6 @@ const (
minimumEmptyBlobSize = 32 + headerEntrySize
)
var (
errEmptyQueue = &queueError{"Empty queue"}
errInvalidIndex = &queueError{"Index must be greater than zero. Invalid index."}
errIndexOutOfBounds = &queueError{"Index out of range"}
)
// BytesQueue is a non-thread safe queue type of fifo based on bytes array.
// For every push operation index of entry is returned. It can be used to read the entry later
type BytesQueue struct {
@ -168,11 +162,6 @@ func (q *BytesQueue) Get(index int) ([]byte, error) {
return data, err
}
// CheckGet checks if an entry can be read from index
func (q *BytesQueue) CheckGet(index int) error {
return q.peekCheckErr(index)
}
// Capacity returns number of allocated bytes for queue
func (q *BytesQueue) Capacity() int {
return q.capacity
@ -188,35 +177,18 @@ func (e *queueError) Error() string {
return e.message
}
// peekCheckErr is identical to peek, but does not actually return any data
func (q *BytesQueue) peekCheckErr(index int) error {
if q.count == 0 {
return errEmptyQueue
}
if index <= 0 {
return errInvalidIndex
}
if index+headerEntrySize >= len(q.array) {
return errIndexOutOfBounds
}
return nil
}
func (q *BytesQueue) peek(index int) ([]byte, int, error) {
if q.count == 0 {
return nil, 0, errEmptyQueue
return nil, 0, &queueError{"Empty queue"}
}
if index <= 0 {
return nil, 0, errInvalidIndex
return nil, 0, &queueError{"Index must be grater than zero. Invalid index."}
}
if index+headerEntrySize >= len(q.array) {
return nil, 0, errIndexOutOfBounds
return nil, 0, &queueError{"Index out of range"}
}
blockSize := int(binary.LittleEndian.Uint32(q.array[index : index+headerEntrySize]))

View File

@ -8,14 +8,12 @@ import (
"github.com/allegro/bigcache/queue"
)
type onRemoveCallback func(wrappedEntry []byte, reason RemoveReason)
type cacheShard struct {
hashmap map[uint64]uint32
entries queue.BytesQueue
lock sync.RWMutex
entryBuffer []byte
onRemove onRemoveCallback
onRemove func(wrappedEntry []byte)
isVerbose bool
logger Logger
@ -25,6 +23,8 @@ type cacheShard struct {
stats Stats
}
type onRemoveCallback func(wrappedEntry []byte)
func (s *cacheShard) get(key string, hashedKey uint64) ([]byte, error) {
s.lock.RLock()
itemIndex := s.hashmap[hashedKey]
@ -32,7 +32,7 @@ func (s *cacheShard) get(key string, hashedKey uint64) ([]byte, error) {
if itemIndex == 0 {
s.lock.RUnlock()
s.miss()
return nil, ErrEntryNotFound
return nil, notFound(key)
}
wrappedEntry, err := s.entries.Get(int(itemIndex))
@ -47,12 +47,11 @@ func (s *cacheShard) get(key string, hashedKey uint64) ([]byte, error) {
}
s.lock.RUnlock()
s.collision()
return nil, ErrEntryNotFound
return nil, notFound(key)
}
entry := readEntry(wrappedEntry)
s.lock.RUnlock()
s.hit()
return entry, nil
return readEntry(wrappedEntry), nil
}
func (s *cacheShard) set(key string, hashedKey uint64, entry []byte) error {
@ -78,7 +77,7 @@ func (s *cacheShard) set(key string, hashedKey uint64, entry []byte) error {
s.lock.Unlock()
return nil
}
if s.removeOldestEntry(NoSpace) != nil {
if s.removeOldestEntry() != nil {
s.lock.Unlock()
return fmt.Errorf("entry is bigger than max shard size")
}
@ -86,17 +85,17 @@ func (s *cacheShard) set(key string, hashedKey uint64, entry []byte) error {
}
func (s *cacheShard) del(key string, hashedKey uint64) error {
// Optimistic pre-check using only readlock
s.lock.RLock()
itemIndex := s.hashmap[hashedKey]
if itemIndex == 0 {
s.lock.RUnlock()
s.delmiss()
return ErrEntryNotFound
return notFound(key)
}
if err := s.entries.CheckGet(int(itemIndex)); err != nil {
wrappedEntry, err := s.entries.Get(int(itemIndex))
if err != nil {
s.lock.RUnlock()
s.delmiss()
return err
@ -105,25 +104,8 @@ func (s *cacheShard) del(key string, hashedKey uint64) error {
s.lock.Lock()
{
// After obtaining the writelock, we need to read the same again,
// since the data delivered earlier may be stale now
itemIndex = s.hashmap[hashedKey]
if itemIndex == 0 {
s.lock.Unlock()
s.delmiss()
return ErrEntryNotFound
}
wrappedEntry, err := s.entries.Get(int(itemIndex))
if err != nil {
s.lock.Unlock()
s.delmiss()
return err
}
delete(s.hashmap, hashedKey)
s.onRemove(wrappedEntry, Deleted)
s.onRemove(wrappedEntry)
resetKeyFromEntry(wrappedEntry)
}
s.lock.Unlock()
@ -132,10 +114,10 @@ func (s *cacheShard) del(key string, hashedKey uint64) error {
return nil
}
func (s *cacheShard) onEvict(oldestEntry []byte, currentTimestamp uint64, evict func(reason RemoveReason) error) bool {
func (s *cacheShard) onEvict(oldestEntry []byte, currentTimestamp uint64, evict func() error) bool {
oldestTimestamp := readTimestampFromEntry(oldestEntry)
if currentTimestamp-oldestTimestamp > s.lifeWindow {
evict(Expired)
evict()
return true
}
return false
@ -154,23 +136,18 @@ func (s *cacheShard) cleanUp(currentTimestamp uint64) {
}
func (s *cacheShard) getOldestEntry() ([]byte, error) {
s.lock.RLock()
defer s.lock.RUnlock()
return s.entries.Peek()
}
func (s *cacheShard) getEntry(index int) ([]byte, error) {
s.lock.RLock()
entry, err := s.entries.Get(index)
s.lock.RUnlock()
return entry, err
return s.entries.Get(index)
}
func (s *cacheShard) copyKeys() (keys []uint32, next int) {
s.lock.RLock()
keys = make([]uint32, len(s.hashmap))
s.lock.RLock()
for _, index := range s.hashmap {
keys[next] = index
next++
@ -180,12 +157,12 @@ func (s *cacheShard) copyKeys() (keys []uint32, next int) {
return keys, next
}
func (s *cacheShard) removeOldestEntry(reason RemoveReason) error {
func (s *cacheShard) removeOldestEntry() error {
oldest, err := s.entries.Pop()
if err == nil {
hash := readHashFromEntry(oldest)
delete(s.hashmap, hash)
s.onRemove(oldest, reason)
s.onRemove(oldest)
return nil
}
return err
@ -206,13 +183,6 @@ func (s *cacheShard) len() int {
return res
}
func (s *cacheShard) capacity() int {
s.lock.RLock()
res := s.entries.Capacity()
s.lock.RUnlock()
return res
}
func (s *cacheShard) getStats() Stats {
var stats = Stats{
Hits: atomic.LoadInt64(&s.stats.Hits),

View File

@ -1,63 +0,0 @@
// Copyright 2015 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
// This file is ignored during the regular build due to the following build tag.
// It is called by go generate and used to automatically generate pre-computed
// tables used to accelerate operations.
// +build ignore
package main
import (
"bytes"
"compress/zlib"
"encoding/base64"
"fmt"
"log"
"os"
"github.com/btcsuite/btcd/btcec"
)
func main() {
fi, err := os.Create("secp256k1.go")
if err != nil {
log.Fatal(err)
}
defer fi.Close()
// Compress the serialized byte points.
serialized := btcec.S256().SerializedBytePoints()
var compressed bytes.Buffer
w := zlib.NewWriter(&compressed)
if _, err := w.Write(serialized); err != nil {
fmt.Println(err)
os.Exit(1)
}
w.Close()
// Encode the compressed byte points with base64.
encoded := make([]byte, base64.StdEncoding.EncodedLen(compressed.Len()))
base64.StdEncoding.Encode(encoded, compressed.Bytes())
fmt.Fprintln(fi, "// Copyright (c) 2015 The btcsuite developers")
fmt.Fprintln(fi, "// Use of this source code is governed by an ISC")
fmt.Fprintln(fi, "// license that can be found in the LICENSE file.")
fmt.Fprintln(fi)
fmt.Fprintln(fi, "package btcec")
fmt.Fprintln(fi)
fmt.Fprintln(fi, "// Auto-generated file (see genprecomps.go)")
fmt.Fprintln(fi, "// DO NOT EDIT")
fmt.Fprintln(fi)
fmt.Fprintf(fi, "var secp256k1BytePoints = %q\n", string(encoded))
a1, b1, a2, b2 := btcec.S256().EndomorphismVectors()
fmt.Println("The following values are the computed linearly " +
"independent vectors needed to make use of the secp256k1 " +
"endomorphism:")
fmt.Printf("a1: %x\n", a1)
fmt.Printf("b1: %x\n", b1)
fmt.Printf("a2: %x\n", a2)
fmt.Printf("b2: %x\n", b2)
}

View File

@ -1,79 +0,0 @@
// Copyright (c) 2015 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
//+build ignore
package main
import (
"bytes"
"io"
"log"
"os"
"strconv"
)
var (
start = []byte(`// Copyright (c) 2015 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
// AUTOGENERATED by genalphabet.go; do not edit.
package base58
const (
// alphabet is the modified base58 alphabet used by Bitcoin.
alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
alphabetIdx0 = '1'
)
var b58 = [256]byte{`)
end = []byte(`}`)
alphabet = []byte("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz")
tab = []byte("\t")
invalid = []byte("255")
comma = []byte(",")
space = []byte(" ")
nl = []byte("\n")
)
func write(w io.Writer, b []byte) {
_, err := w.Write(b)
if err != nil {
log.Fatal(err)
}
}
func main() {
fi, err := os.Create("alphabet.go")
if err != nil {
log.Fatal(err)
}
defer fi.Close()
write(fi, start)
write(fi, nl)
for i := byte(0); i < 32; i++ {
write(fi, tab)
for j := byte(0); j < 8; j++ {
idx := bytes.IndexByte(alphabet, i*8+j)
if idx == -1 {
write(fi, invalid)
} else {
write(fi, strconv.AppendInt(nil, int64(idx), 10))
}
write(fi, comma)
if j != 7 {
write(fi, space)
}
}
write(fi, nl)
}
write(fi, end)
write(fi, nl)
}

93
vendor/github.com/lib/pq/oid/gen.go generated vendored
View File

@ -1,93 +0,0 @@
// +build ignore
// Generate the table of OID values
// Run with 'go run gen.go'.
package main
import (
"database/sql"
"fmt"
"log"
"os"
"os/exec"
"strings"
_ "github.com/lib/pq"
)
// OID represent a postgres Object Identifier Type.
type OID struct {
ID int
Type string
}
// Name returns an upper case version of the oid type.
func (o OID) Name() string {
return strings.ToUpper(o.Type)
}
func main() {
datname := os.Getenv("PGDATABASE")
sslmode := os.Getenv("PGSSLMODE")
if datname == "" {
os.Setenv("PGDATABASE", "pqgotest")
}
if sslmode == "" {
os.Setenv("PGSSLMODE", "disable")
}
db, err := sql.Open("postgres", "")
if err != nil {
log.Fatal(err)
}
rows, err := db.Query(`
SELECT typname, oid
FROM pg_type WHERE oid < 10000
ORDER BY oid;
`)
if err != nil {
log.Fatal(err)
}
oids := make([]*OID, 0)
for rows.Next() {
var oid OID
if err = rows.Scan(&oid.Type, &oid.ID); err != nil {
log.Fatal(err)
}
oids = append(oids, &oid)
}
if err = rows.Err(); err != nil {
log.Fatal(err)
}
cmd := exec.Command("gofmt")
cmd.Stderr = os.Stderr
w, err := cmd.StdinPipe()
if err != nil {
log.Fatal(err)
}
f, err := os.Create("types.go")
if err != nil {
log.Fatal(err)
}
cmd.Stdout = f
err = cmd.Start()
if err != nil {
log.Fatal(err)
}
fmt.Fprintln(w, "// Code generated by gen.go. DO NOT EDIT.")
fmt.Fprintln(w, "\npackage oid")
fmt.Fprintln(w, "const (")
for _, oid := range oids {
fmt.Fprintf(w, "T_%s Oid = %d\n", oid.Type, oid.ID)
}
fmt.Fprintln(w, ")")
fmt.Fprintln(w, "var TypeName = map[Oid]string{")
for _, oid := range oids {
fmt.Fprintf(w, "T_%s: \"%s\",\n", oid.Type, oid.Name())
}
fmt.Fprintln(w, "}")
w.Close()
cmd.Wait()
}

View File

@ -4,17 +4,13 @@ notifications:
language: go
go:
- "1.12.x"
- "1.13beta1"
- "1.13.x"
install: true
env:
- GO111MODULE=on GOFLAGS=-mod=vendor
matrix:
allow_failures:
- go: "1.13beta1"
before_script:
- make install-linter

View File

@ -24,7 +24,7 @@ vendor:
install-linter:
# install linter
curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(shell go env GOPATH)/bin v1.17.1
curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(shell go env GOPATH)/bin v1.19.0
.PHONY: install-linter
install-dev:

View File

@ -3,19 +3,15 @@ package statusproto
import (
"crypto/ecdsa"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
"github.com/google/uuid"
statusproto "github.com/status-im/status-protocol-go/types"
)
type ChatPagination struct {
From uint
To uint
}
type ChatType int
const (
ChatTypeOneToOne = iota + 1
ChatTypeOneToOne ChatType = iota + 1
ChatTypePublic
ChatTypePrivateGroupChat
)
@ -87,7 +83,7 @@ type ChatMember struct {
}
func (c ChatMember) PublicKey() (*ecdsa.PublicKey, error) {
b, err := hexutil.Decode(c.ID)
b, err := statusproto.DecodeHex(c.ID)
if err != nil {
return nil, err
}
@ -95,7 +91,7 @@ func (c ChatMember) PublicKey() (*ecdsa.PublicKey, error) {
}
func oneToOneChatID(publicKey *ecdsa.PublicKey) string {
return hexutil.Encode(crypto.FromECDSAPub(publicKey))
return statusproto.EncodeHex(crypto.FromECDSAPub(publicKey))
}
func CreateOneToOneChat(name string, publicKey *ecdsa.PublicKey) Chat {
@ -117,6 +113,19 @@ func CreatePublicChat(name string) Chat {
}
}
func groupChatID(creator *ecdsa.PublicKey) string {
return uuid.New().String() + statusproto.EncodeHex(crypto.FromECDSAPub(creator))
}
func CreateGroupChat(name string, creator *ecdsa.PublicKey) Chat {
return Chat{
ID: groupChatID(creator),
Name: name,
Active: true,
ChatType: ChatTypePrivateGroupChat,
}
}
func findChatByID(chatID string, chats []*Chat) *Chat {
for _, c := range chats {
if c.ID == chatID {

View File

@ -3,8 +3,8 @@ package statusproto
import (
"crypto/ecdsa"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
statusproto "github.com/status-im/status-protocol-go/types"
)
const (
@ -50,7 +50,7 @@ type Contact struct {
}
func (c Contact) PublicKey() (*ecdsa.PublicKey, error) {
b, err := hexutil.Decode(c.ID)
b, err := statusproto.DecodeHex(c.ID)
if err != nil {
return nil, err
}

View File

@ -16,17 +16,32 @@ const (
aesNonceLength = 12
)
// Sign signs the hash of an arbitrary string
func Sign(content string, identity *ecdsa.PrivateKey) (string, error) {
signature, err := crypto.Sign(crypto.Keccak256([]byte(content)), identity)
// SignBytes signs the hash of arbitrary data.
func SignBytes(data []byte, identity *ecdsa.PrivateKey) ([]byte, error) {
return crypto.Sign(crypto.Keccak256(data), identity)
}
// SignStringAsHex signs the Keccak256 hash of arbitrary data and returns its hex representation.
func SignBytesAsHex(data []byte, identity *ecdsa.PrivateKey) (string, error) {
signature, err := SignBytes(data, identity)
if err != nil {
return "", err
}
return hex.EncodeToString(signature), nil
}
// VerifySignatures verifys tuples of signatures content/hash/public key
// SignStringAsHex signs the Keccak256 hash of arbitrary string and returns its hex representation.
func SignStringAsHex(data string, identity *ecdsa.PrivateKey) (string, error) {
return SignBytesAsHex([]byte(data), identity)
}
// Sign signs the hash of arbitrary data.
// DEPRECATED: use SignStringAsHex instead.
func Sign(data string, identity *ecdsa.PrivateKey) (string, error) {
return SignStringAsHex(data, identity)
}
// VerifySignatures verifies tuples of signatures content/hash/public key
func VerifySignatures(signaturePairs [][3]string) error {
for _, signaturePair := range signaturePairs {
content := crypto.Keccak256([]byte(signaturePair[0]))

View File

@ -5,22 +5,19 @@ go 1.12
require (
github.com/aristanetworks/goarista v0.0.0-20190704150520-f44d68189fd7 // indirect
github.com/cenkalti/backoff/v3 v3.0.0
github.com/deckarep/golang-set v1.7.1 // indirect
github.com/ethereum/go-ethereum v1.8.27
github.com/ethereum/go-ethereum v1.9.5
github.com/golang/protobuf v1.3.2
github.com/google/uuid v1.1.1
github.com/jinzhu/copier v0.0.0-20190625015134-976e0346caa8
github.com/lucasb-eyer/go-colorful v1.0.2
github.com/mutecomm/go-sqlcipher v0.0.0-20190227152316-55dbde17881f
github.com/onsi/ginkgo v1.8.0 // indirect
github.com/onsi/gomega v1.5.0 // indirect
github.com/pkg/errors v0.8.1
github.com/rs/cors v1.6.0 // indirect
github.com/russolsen/ohyeah v0.0.0-20160324131710-f4938c005315 // indirect
github.com/russolsen/same v0.0.0-20160222130632-f089df61f51d // indirect
github.com/russolsen/transit v0.0.0-20180705123435-0794b4c4505a
github.com/status-im/doubleratchet v2.0.0+incompatible
github.com/status-im/migrate/v4 v4.0.0-20190821140204-a9d340ec8fb76af4afda06acf01740d45d2661ed
github.com/status-im/whisper v1.4.14
github.com/status-im/whisper v1.5.1
github.com/stretchr/testify v1.3.1-0.20190712000136-221dbe5ed467
github.com/vacp2p/mvds v0.0.21
go.uber.org/zap v1.10.0
@ -29,4 +26,4 @@ require (
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3 // indirect
)
replace github.com/ethereum/go-ethereum v1.8.27 => github.com/status-im/go-ethereum v1.8.27-status.4
replace github.com/ethereum/go-ethereum v1.9.5 => github.com/status-im/go-ethereum v1.9.5-status.4

View File

@ -16,13 +16,16 @@ github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEV
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8=
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/allegro/bigcache v0.0.0-20190218064605-e24eb225f156 h1:hh7BAWFHv41r0gce0KRYtDJpL4erKfmB1/mpgoSADeI=
github.com/allegro/bigcache v0.0.0-20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
github.com/allegro/bigcache v1.1.0/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
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-20190704150520-f44d68189fd7 h1:fKnuvQ/O22ZpD7HaJjGQXn/GxOdDJOQFL8bpM8Xe3X8=
github.com/aristanetworks/goarista v0.0.0-20190704150520-f44d68189fd7/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
@ -32,6 +35,8 @@ github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCS
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6 h1:Eey/GGQ/E5Xp1P2Lyx1qj007hLZfbi0+CoVeJruGCtI=
github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ=
github.com/btcsuite/btcd v0.0.0-20181013004428-67e573d211ac h1:/zx+Hglw2JN/pwVam1Z8cTCTl4pWyrbvOn2oooqCQSs=
github.com/btcsuite/btcd v0.0.0-20181013004428-67e573d211ac/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ=
github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c=
github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s=
@ -74,6 +79,7 @@ github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/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=
@ -83,6 +89,7 @@ github.com/fsouza/fake-gcs-server v1.7.0/go.mod h1:5XIRs4YvwNbNoz+1JF8j6KLAyDh7R
github.com/gizak/termui v0.0.0-20170117222342-991cd3d38091/go.mod h1:PkJoWUt/zacQKysNfQtcw1RW+eK2SxkieVBtl+4ovLA=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
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-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-stack/stack v1.5.4/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
@ -117,11 +124,15 @@ github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+u
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.1 h1:Dw4jY2nghMMRsh1ol8dv1axHkDwMQK2DHerMNJsIpJU=
github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
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/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
@ -134,11 +145,16 @@ 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/huin/goupnp v1.0.0 h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo=
github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc=
github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
github.com/influxdata/influxdb v0.0.0-20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY=
github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ=
github.com/jackc/pgx v3.2.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I=
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/jackpal/go-nat-pmp v1.0.1 h1:i0LektDkO1QlrTm/cSuP+PyBCDnYvjPLGl4LdWEMiaA=
github.com/jackpal/go-nat-pmp v1.0.1/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jinzhu/copier v0.0.0-20190625015134-976e0346caa8 h1:mGIXW/lubQ4B+3bXTLxcTMTjUNDqoF6T/HUW9LbFx9s=
github.com/jinzhu/copier v0.0.0-20190625015134-976e0346caa8/go.mod h1:yL958EeXv8Ylng6IfnvG4oflryUi3vgA3xPs9hmII1s=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
@ -183,11 +199,11 @@ github.com/nsf/termbox-go v0.0.0-20170211012700-3540b76b9c77/go.mod h1:IuKpRQcYE
github.com/olekukonko/tablewriter v0.0.0-20170128050532-febf2d34b54a/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w=
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo=
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
@ -237,12 +253,14 @@ github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/status-im/doubleratchet v2.0.0+incompatible h1:s77lF1lDubK0RKftxN2vH8G9gwtVVp13ggWfyY4O1q4=
github.com/status-im/doubleratchet v2.0.0+incompatible/go.mod h1:1sqR0+yhiM/bd+wrdX79AOt2csZuJOni0nUDzKNuqOU=
github.com/status-im/go-ethereum v1.8.27-status.4 h1:8jTQsYDLtKd/XCa++ZkexTPHfANIDh084JbO2SBAwp4=
github.com/status-im/go-ethereum v1.8.27-status.4/go.mod h1:Ulij8LMpMvXnbnPcmDqrpI+iXoXSjxItuY/wmbasTZU=
github.com/status-im/go-ethereum v1.9.5-status.4 h1:F5VrxH9LmTxWl4qwQjs0TI5TgG9dVuZKqGmdwHJ0cWk=
github.com/status-im/go-ethereum v1.9.5-status.4/go.mod h1:Ulij8LMpMvXnbnPcmDqrpI+iXoXSjxItuY/wmbasTZU=
github.com/status-im/migrate/v4 v4.0.0-20190821140204-a9d340ec8fb76af4afda06acf01740d45d2661ed h1:K2iga8l8OQIHnk2bBq2QsZTO2Q38YWy04xIspdITCdM=
github.com/status-im/migrate/v4 v4.0.0-20190821140204-a9d340ec8fb76af4afda06acf01740d45d2661ed/go.mod h1:r8HggRBZ/k7TRwByq/Hp3P/ubFppIna0nvyavVK0pjA=
github.com/status-im/whisper v1.4.14 h1:9VHqx4+PUYfhDnYYtDxHkg/3cfVvkHjPNciY4LO83yc=
github.com/status-im/whisper v1.4.14/go.mod h1:WS6z39YJQ8WJa9s+DmTuEM/s2nVF6Iz3B1SZYw5cYf0=
github.com/status-im/whisper v1.5.1 h1:87/XIg0Wjua7lXBGiEXgAfTOqlt2Q1dMDuxugTyZbbA=
github.com/status-im/whisper v1.5.1/go.mod h1:emrOxzJme0k66QtbbQ2bdd3P8RCdLZ8sTD7SkwH1s2s=
github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw=
github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
@ -288,6 +306,7 @@ golang.org/x/net v0.0.0-20180112015858-5ccada7d0a7b/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181108082009-03003ca0c849/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=

View File

@ -31,7 +31,7 @@ func renderBase64(id Identicon) (string, error) {
}
func setBackgroundWhite(img *image.RGBA) {
draw.Draw(img, img.Bounds(), &image.Uniform{color.White}, image.ZP, draw.Src)
draw.Draw(img, img.Bounds(), &image.Uniform{C: color.White}, image.Point{}, draw.Src)
}
func drawRect(rgba *image.RGBA, i int, c color.Color) {
@ -45,7 +45,7 @@ func drawRect(rgba *image.RGBA, i int, c color.Color) {
10+(i/maxRow)*sizeSquare+sizeSquare,
)
draw.Draw(rgba, r, &image.Uniform{c}, image.ZP, draw.Src)
draw.Draw(rgba, r, &image.Uniform{C: c}, image.Point{}, draw.Src)
}
// GenerateBase64 generates an identicon in base64 png format given a string

View File

@ -3,18 +3,18 @@ package statusproto
import (
"database/sql/driver"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/pkg/errors"
statusproto "github.com/status-im/status-protocol-go/types"
)
type hexutilSQL hexutil.Bytes
type hexutilSQL statusproto.HexBytes
func (h hexutilSQL) Value() (driver.Value, error) {
return []byte(h), nil
}
func (h hexutilSQL) String() string {
return hexutil.Encode(h)
return statusproto.EncodeHex(h)
}
func (h *hexutilSQL) Scan(value interface{}) error {

View File

@ -14,8 +14,8 @@ import (
"github.com/status-im/status-protocol-go/encryption"
"github.com/status-im/status-protocol-go/encryption/multidevice"
transport "github.com/status-im/status-protocol-go/transport/whisper"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
protocol "github.com/status-im/status-protocol-go/v1"
whisper "github.com/status-im/whisper/whisperv6"
datasyncnode "github.com/vacp2p/mvds/node"
datasyncproto "github.com/vacp2p/mvds/protobuf"
"go.uber.org/zap"
@ -155,7 +155,7 @@ func (p *messageProcessor) sendPrivate(
return nil, errors.Wrap(err, "failed to send a message spec")
}
p.transport.Track([][]byte{messageID}, hash, *newMessage)
p.transport.Track([][]byte{messageID}, hash, newMessage)
}
return messageID, nil
@ -187,7 +187,7 @@ func (p *messageProcessor) SendPublic(ctx context.Context, chatID string, data [
return nil, err
}
hash, err := p.transport.SendPublic(ctx, &newMessage, chatID)
hash, err := p.transport.SendPublic(ctx, newMessage, chatID)
if err != nil {
return nil, err
}
@ -201,21 +201,21 @@ func (p *messageProcessor) SendPublic(ctx context.Context, chatID string, data [
// SendPublicRaw takes encoded data, encrypts it and sends through the wire.
func (p *messageProcessor) SendPublicRaw(ctx context.Context, chatName string, data []byte) ([]byte, error) {
var newMessage whisper.NewMessage
var newMessage *whispertypes.NewMessage
wrappedMessage, err := p.tryWrapMessageV1(data)
if err != nil {
return nil, errors.Wrap(err, "failed to wrap message")
}
newMessage = whisper.NewMessage{
newMessage = &whispertypes.NewMessage{
TTL: whisperTTL,
Payload: wrappedMessage,
PowTarget: whisperPoW,
PowTime: whisperPoWTime,
}
hash, err := p.transport.SendPublic(ctx, &newMessage, chatName)
hash, err := p.transport.SendPublic(ctx, newMessage, chatName)
if err != nil {
return nil, err
}
@ -230,13 +230,11 @@ func (p *messageProcessor) SendPublicRaw(ctx context.Context, chatName string, d
// Process processes received Whisper messages through all the layers
// and returns decoded user messages.
// It also handled all non-user messages like PairMessage.
func (p *messageProcessor) Process(message *whisper.ReceivedMessage) ([]*protocol.Message, error) {
func (p *messageProcessor) Process(shhMessage *whispertypes.Message) ([]*protocol.Message, error) {
logger := p.logger.With(zap.String("site", "Process"))
var decodedMessages []*protocol.Message
shhMessage := whisper.ToWhisperMessage(message)
hlogger := logger.With(zap.Binary("hash", shhMessage.Hash))
hlogger.Debug("handling a received message")
@ -283,7 +281,7 @@ func (p *messageProcessor) processPairMessage(m protocol.PairMessage) error {
// layer message, or in case of Raw methods, the processing stops at the layer
// before.
// It returns an error only if the processing of required steps failed.
func (p *messageProcessor) handleMessages(shhMessage *whisper.Message, applicationLayer bool) ([]*protocol.StatusMessage, error) {
func (p *messageProcessor) handleMessages(shhMessage *whispertypes.Message, applicationLayer bool) ([]*protocol.StatusMessage, error) {
logger := p.logger.With(zap.String("site", "handleMessages"))
hlogger := logger.With(zap.Binary("hash", shhMessage.Hash))
var statusMessage protocol.StatusMessage
@ -423,13 +421,13 @@ func (p *messageProcessor) sendDataSync(ctx context.Context, publicKey *ecdsa.Pu
return err
}
p.transport.Track(messageIDs, hash, *newMessage)
p.transport.Track(messageIDs, hash, newMessage)
return nil
}
// sendMessageSpec analyses the spec properties and selects a proper transport method.
func (p *messageProcessor) sendMessageSpec(ctx context.Context, publicKey *ecdsa.PublicKey, messageSpec *encryption.ProtocolMessageSpec) ([]byte, *whisper.NewMessage, error) {
func (p *messageProcessor) sendMessageSpec(ctx context.Context, publicKey *ecdsa.PublicKey, messageSpec *encryption.ProtocolMessageSpec) ([]byte, *whispertypes.NewMessage, error) {
newMessage, err := messageSpecToWhisper(messageSpec)
if err != nil {
return nil, nil, err
@ -442,33 +440,33 @@ func (p *messageProcessor) sendMessageSpec(ctx context.Context, publicKey *ecdsa
switch {
case messageSpec.SharedSecret != nil:
logger.Debug("sending using shared secret")
hash, err = p.transport.SendPrivateWithSharedSecret(ctx, &newMessage, publicKey, messageSpec.SharedSecret)
hash, err = p.transport.SendPrivateWithSharedSecret(ctx, newMessage, publicKey, messageSpec.SharedSecret)
case messageSpec.PartitionedTopicMode() == encryption.PartitionTopicV1:
logger.Debug("sending partitioned topic")
hash, err = p.transport.SendPrivateWithPartitioned(ctx, &newMessage, publicKey)
hash, err = p.transport.SendPrivateWithPartitioned(ctx, newMessage, publicKey)
case !p.featureFlags.genericDiscoveryTopicEnabled:
logger.Debug("sending partitioned topic (generic discovery topic disabled)")
hash, err = p.transport.SendPrivateWithPartitioned(ctx, &newMessage, publicKey)
hash, err = p.transport.SendPrivateWithPartitioned(ctx, newMessage, publicKey)
default:
logger.Debug("sending using discovery topic")
hash, err = p.transport.SendPrivateOnDiscovery(ctx, &newMessage, publicKey)
hash, err = p.transport.SendPrivateOnDiscovery(ctx, newMessage, publicKey)
}
if err != nil {
return nil, nil, err
}
return hash, &newMessage, nil
return hash, newMessage, nil
}
func messageSpecToWhisper(spec *encryption.ProtocolMessageSpec) (whisper.NewMessage, error) {
var newMessage whisper.NewMessage
func messageSpecToWhisper(spec *encryption.ProtocolMessageSpec) (*whispertypes.NewMessage, error) {
var newMessage *whispertypes.NewMessage
payload, err := proto.Marshal(spec.Message)
if err != nil {
return newMessage, err
}
newMessage = whisper.NewMessage{
newMessage = &whispertypes.NewMessage{
TTL: whisperTTL,
Payload: payload,
PowTarget: whisperPoW,

View File

@ -9,10 +9,8 @@ import (
"strings"
"time"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
"github.com/pkg/errors"
whisper "github.com/status-im/whisper/whisperv6"
"go.uber.org/zap"
"github.com/status-im/status-protocol-go/encryption"
@ -22,6 +20,8 @@ import (
"github.com/status-im/status-protocol-go/identity/identicon"
"github.com/status-im/status-protocol-go/sqlite"
transport "github.com/status-im/status-protocol-go/transport/whisper"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
statusproto "github.com/status-im/status-protocol-go/types"
protocol "github.com/status-im/status-protocol-go/v1"
)
@ -169,7 +169,7 @@ func WithEnvelopesMonitorConfig(emc *transport.EnvelopesMonitorConfig) Option {
func NewMessenger(
identity *ecdsa.PrivateKey,
shh *whisper.Whisper,
shh whispertypes.Whisper,
installationID string,
opts ...Option,
) (*Messenger, error) {
@ -228,7 +228,7 @@ func NewMessenger(
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
chatName := transport.ContactCodeTopic(&messenger.identity.PublicKey)
_, err = messenger.transport.SendPublic(ctx, &newMessage, chatName)
_, err = messenger.transport.SendPublic(ctx, newMessage, chatName)
if err != nil {
slogger.Warn("failed to send a contact code", zap.Error(err))
}
@ -404,7 +404,7 @@ func (m *Messenger) handleSharedSecrets(secrets []*sharedsecret.Secret) ([]*tran
var result []*transport.Filter
for _, secret := range secrets {
logger.Debug("received shared secret", zap.Binary("identity", crypto.FromECDSAPub(secret.Identity)))
fSecret := transport.NegotiatedSecret{
fSecret := whispertypes.NegotiatedSecret{
PublicKey: secret.Identity,
Key: secret.Key,
}
@ -627,7 +627,7 @@ func (m *Messenger) retrieveLatest(ctx context.Context) ([]*protocol.Message, er
return nil, errors.Wrap(err, "failed to retrieve messages")
}
logger := m.logger.With(zap.String("site", "RetrieveAll"))
logger := m.logger.With(zap.String("site", "retrieveLatest"))
logger.Debug("retrieved messages", zap.Int("count", len(latest)))
var result []*protocol.Message
@ -670,8 +670,7 @@ func (m *Messenger) RetrieveRawAll() (map[transport.Filter][]*protocol.StatusMes
result := make(map[transport.Filter][]*protocol.StatusMessage)
for chat, messages := range chatWithMessages {
for _, message := range messages {
shhMessage := whisper.ToWhisperMessage(message)
for _, shhMessage := range messages {
// TODO: fix this to use an exported method.
statusMessages, err := m.processor.handleMessages(shhMessage, false)
if err != nil {
@ -889,7 +888,7 @@ func (p *postProcessor) matchMessage(message *protocol.Message, chats []*Chat) (
case message.MessageT == protocol.MessageTypePrivate:
// It's an incoming private message. ChatID is calculated from the signature.
// If a chat does not exist, a new one is created and saved.
chatID := hexutil.Encode(crypto.FromECDSAPub(message.SigPubKey))
chatID := statusproto.EncodeHex(crypto.FromECDSAPub(message.SigPubKey))
chat := findChatByID(chatID, chats)
if chat == nil {
// TODO: this should be a three-word name used in the mobile client
@ -905,7 +904,7 @@ func (p *postProcessor) matchMessage(message *protocol.Message, chats []*Chat) (
// It needs to be verified if the signature public key belongs to the chat.
chatID := message.Content.ChatID
chat := findChatByID(chatID, chats)
sigPubKeyHex := hexutil.Encode(crypto.FromECDSAPub(message.SigPubKey))
sigPubKeyHex := statusproto.EncodeHex(crypto.FromECDSAPub(message.SigPubKey))
for _, member := range chat.Members {
if member.ID == sigPubKeyHex {
return chat, nil

View File

@ -5,9 +5,8 @@ import (
"errors"
"sync"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/p2p/enode"
whisper "github.com/status-im/whisper/whisperv6"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
statusproto "github.com/status-im/status-protocol-go/types"
"go.uber.org/zap"
)
@ -27,7 +26,7 @@ type EnvelopesMonitorConfig struct {
EnvelopeEventsHandler EnvelopeEventsHandler
MaxAttempts int
MailserverConfirmationsEnabled bool
IsMailserver func(enode.ID) bool
IsMailserver func(whispertypes.EnodeID) bool
Logger *zap.Logger
}
@ -35,21 +34,26 @@ type EnvelopesMonitorConfig struct {
type EnvelopeEventsHandler interface {
EnvelopeSent([][]byte)
EnvelopeExpired([][]byte, error)
MailServerRequestCompleted(common.Hash, common.Hash, []byte, error)
MailServerRequestExpired(common.Hash)
MailServerRequestCompleted(statusproto.Hash, statusproto.Hash, []byte, error)
MailServerRequestExpired(statusproto.Hash)
}
// NewEnvelopesMonitor returns a pointer to an instance of the EnvelopesMonitor.
func NewEnvelopesMonitor(w *whisper.Whisper, config *EnvelopesMonitorConfig) *EnvelopesMonitor {
func NewEnvelopesMonitor(w whispertypes.Whisper, config EnvelopesMonitorConfig) *EnvelopesMonitor {
logger := config.Logger
if logger == nil {
logger = zap.NewNop()
}
var whisperAPI whispertypes.PublicWhisperAPI
if w != nil {
whisperAPI = w.PublicWhisperAPI()
}
return &EnvelopesMonitor{
w: w,
whisperAPI: whisper.NewPublicWhisperAPI(w),
whisperAPI: whisperAPI,
handler: config.EnvelopeEventsHandler,
mailServerConfirmation: config.MailserverConfirmationsEnabled,
maxAttempts: config.MaxAttempts,
@ -57,35 +61,35 @@ func NewEnvelopesMonitor(w *whisper.Whisper, config *EnvelopesMonitorConfig) *En
logger: logger.With(zap.Namespace("EnvelopesMonitor")),
// key is envelope hash (event.Hash)
envelopes: map[common.Hash]EnvelopeState{},
messages: map[common.Hash]whisper.NewMessage{},
attempts: map[common.Hash]int{},
identifiers: make(map[common.Hash][][]byte),
envelopes: map[statusproto.Hash]EnvelopeState{},
messages: map[statusproto.Hash]*whispertypes.NewMessage{},
attempts: map[statusproto.Hash]int{},
identifiers: make(map[statusproto.Hash][][]byte),
// key is hash of the batch (event.Batch)
batches: map[common.Hash]map[common.Hash]struct{}{},
batches: map[statusproto.Hash]map[statusproto.Hash]struct{}{},
}
}
// EnvelopesMonitor is responsible for monitoring whisper envelopes state.
type EnvelopesMonitor struct {
w *whisper.Whisper
whisperAPI *whisper.PublicWhisperAPI
w whispertypes.Whisper
whisperAPI whispertypes.PublicWhisperAPI
handler EnvelopeEventsHandler
mailServerConfirmation bool
maxAttempts int
mu sync.Mutex
envelopes map[common.Hash]EnvelopeState
batches map[common.Hash]map[common.Hash]struct{}
envelopes map[statusproto.Hash]EnvelopeState
batches map[statusproto.Hash]map[statusproto.Hash]struct{}
messages map[common.Hash]whisper.NewMessage
attempts map[common.Hash]int
identifiers map[common.Hash][][]byte
messages map[statusproto.Hash]*whispertypes.NewMessage
attempts map[statusproto.Hash]int
identifiers map[statusproto.Hash][][]byte
wg sync.WaitGroup
quit chan struct{}
isMailserver func(peer enode.ID) bool
isMailserver func(peer whispertypes.EnodeID) bool
logger *zap.Logger
}
@ -107,16 +111,16 @@ func (m *EnvelopesMonitor) Stop() {
}
// Add hash to a tracker.
func (m *EnvelopesMonitor) Add(identifiers [][]byte, envelopeHash common.Hash, message whisper.NewMessage) {
func (m *EnvelopesMonitor) Add(identifiers [][]byte, envelopeHash statusproto.Hash, message whispertypes.NewMessage) {
m.mu.Lock()
defer m.mu.Unlock()
m.envelopes[envelopeHash] = EnvelopePosted
m.identifiers[envelopeHash] = identifiers
m.messages[envelopeHash] = message
m.messages[envelopeHash] = &message
m.attempts[envelopeHash] = 1
}
func (m *EnvelopesMonitor) GetState(hash common.Hash) EnvelopeState {
func (m *EnvelopesMonitor) GetState(hash statusproto.Hash) EnvelopeState {
m.mu.Lock()
defer m.mu.Unlock()
state, exist := m.envelopes[hash]
@ -128,13 +132,18 @@ func (m *EnvelopesMonitor) GetState(hash common.Hash) EnvelopeState {
// handleEnvelopeEvents processes whisper envelope events
func (m *EnvelopesMonitor) handleEnvelopeEvents() {
events := make(chan whisper.EnvelopeEvent, 100) // must be buffered to prevent blocking whisper
events := make(chan whispertypes.EnvelopeEvent, 100) // must be buffered to prevent blocking whisper
sub := m.w.SubscribeEnvelopeEvents(events)
defer sub.Unsubscribe()
defer func() {
close(events)
sub.Unsubscribe()
}()
for {
select {
case <-m.quit:
return
case <-sub.Err():
return
case event := <-events:
m.handleEvent(event)
}
@ -143,19 +152,19 @@ func (m *EnvelopesMonitor) handleEnvelopeEvents() {
// handleEvent based on type of the event either triggers
// confirmation handler or removes hash from tracker
func (m *EnvelopesMonitor) handleEvent(event whisper.EnvelopeEvent) {
handlers := map[whisper.EventType]func(whisper.EnvelopeEvent){
whisper.EventEnvelopeSent: m.handleEventEnvelopeSent,
whisper.EventEnvelopeExpired: m.handleEventEnvelopeExpired,
whisper.EventBatchAcknowledged: m.handleAcknowledgedBatch,
whisper.EventEnvelopeReceived: m.handleEventEnvelopeReceived,
func (m *EnvelopesMonitor) handleEvent(event whispertypes.EnvelopeEvent) {
handlers := map[whispertypes.EventType]func(whispertypes.EnvelopeEvent){
whispertypes.EventEnvelopeSent: m.handleEventEnvelopeSent,
whispertypes.EventEnvelopeExpired: m.handleEventEnvelopeExpired,
whispertypes.EventBatchAcknowledged: m.handleAcknowledgedBatch,
whispertypes.EventEnvelopeReceived: m.handleEventEnvelopeReceived,
}
if handler, ok := handlers[event.Event]; ok {
handler(event)
}
}
func (m *EnvelopesMonitor) handleEventEnvelopeSent(event whisper.EnvelopeEvent) {
func (m *EnvelopesMonitor) handleEventEnvelopeSent(event whispertypes.EnvelopeEvent) {
if m.mailServerConfirmation {
if !m.isMailserver(event.Peer) {
return
@ -172,9 +181,9 @@ func (m *EnvelopesMonitor) handleEventEnvelopeSent(event whisper.EnvelopeEvent)
return
}
m.logger.Debug("envelope is sent", zap.String("hash", event.Hash.String()), zap.String("peer", event.Peer.String()))
if event.Batch != (common.Hash{}) {
if event.Batch != (statusproto.Hash{}) {
if _, ok := m.batches[event.Batch]; !ok {
m.batches[event.Batch] = map[common.Hash]struct{}{}
m.batches[event.Batch] = map[statusproto.Hash]struct{}{}
}
m.batches[event.Batch][event.Hash] = struct{}{}
m.logger.Debug("waiting for a confirmation", zap.String("batch", event.Batch.String()))
@ -186,7 +195,7 @@ func (m *EnvelopesMonitor) handleEventEnvelopeSent(event whisper.EnvelopeEvent)
}
}
func (m *EnvelopesMonitor) handleAcknowledgedBatch(event whisper.EnvelopeEvent) {
func (m *EnvelopesMonitor) handleAcknowledgedBatch(event whispertypes.EnvelopeEvent) {
if m.mailServerConfirmation {
if !m.isMailserver(event.Peer) {
return
@ -201,11 +210,11 @@ func (m *EnvelopesMonitor) handleAcknowledgedBatch(event whisper.EnvelopeEvent)
m.logger.Debug("batch is not found", zap.String("batch", event.Batch.String()))
}
m.logger.Debug("received a confirmation", zap.String("batch", event.Batch.String()), zap.String("peer", event.Peer.String()))
envelopeErrors, ok := event.Data.([]whisper.EnvelopeError)
envelopeErrors, ok := event.Data.([]whispertypes.EnvelopeError)
if event.Data != nil && !ok {
m.logger.Error("received unexpected data in the the confirmation event", zap.String("batch", event.Batch.String()))
}
failedEnvelopes := map[common.Hash]struct{}{}
failedEnvelopes := map[statusproto.Hash]struct{}{}
for i := range envelopeErrors {
envelopeError := envelopeErrors[i]
_, exist := m.envelopes[envelopeError.Hash]
@ -213,7 +222,7 @@ func (m *EnvelopesMonitor) handleAcknowledgedBatch(event whisper.EnvelopeEvent)
m.logger.Warn("envelope that was posted by us is discarded", zap.String("hash", envelopeError.Hash.String()), zap.String("peer", event.Peer.String()), zap.String("error", envelopeError.Description))
var err error
switch envelopeError.Code {
case whisper.EnvelopeTimeNotSynced:
case whispertypes.EnvelopeTimeNotSynced:
err = errors.New("envelope wasn't delivered due to time sync issues")
}
m.handleEnvelopeFailure(envelopeError.Hash, err)
@ -237,7 +246,7 @@ func (m *EnvelopesMonitor) handleAcknowledgedBatch(event whisper.EnvelopeEvent)
delete(m.batches, event.Batch)
}
func (m *EnvelopesMonitor) handleEventEnvelopeExpired(event whisper.EnvelopeEvent) {
func (m *EnvelopesMonitor) handleEventEnvelopeExpired(event whispertypes.EnvelopeEvent) {
m.mu.Lock()
defer m.mu.Unlock()
m.handleEnvelopeFailure(event.Hash, errors.New("envelope expired due to connectivity issues"))
@ -245,7 +254,7 @@ func (m *EnvelopesMonitor) handleEventEnvelopeExpired(event whisper.EnvelopeEven
// handleEnvelopeFailure is a common code path for processing envelopes failures. not thread safe, lock
// must be used on a higher level.
func (m *EnvelopesMonitor) handleEnvelopeFailure(hash common.Hash, err error) {
func (m *EnvelopesMonitor) handleEnvelopeFailure(hash statusproto.Hash, err error) {
if state, ok := m.envelopes[hash]; ok {
message, exist := m.messages[hash]
if !exist {
@ -259,7 +268,7 @@ func (m *EnvelopesMonitor) handleEnvelopeFailure(hash common.Hash, err error) {
}
if attempt < m.maxAttempts {
m.logger.Debug("retrying to send a message", zap.String("hash", hash.String()), zap.Int("attempt", attempt+1))
hex, err := m.whisperAPI.Post(context.TODO(), message)
hex, err := m.whisperAPI.Post(context.TODO(), *message)
if err != nil {
m.logger.Error("failed to retry sending message", zap.String("hash", hash.String()), zap.Int("attempt", attempt+1), zap.Error(err))
if m.handler != nil {
@ -267,7 +276,7 @@ func (m *EnvelopesMonitor) handleEnvelopeFailure(hash common.Hash, err error) {
}
}
envelopeID := common.BytesToHash(hex)
envelopeID := statusproto.BytesToHash(hex)
m.envelopes[envelopeID] = EnvelopePosted
m.messages[envelopeID] = message
m.attempts[envelopeID] = attempt + 1
@ -281,7 +290,7 @@ func (m *EnvelopesMonitor) handleEnvelopeFailure(hash common.Hash, err error) {
}
}
func (m *EnvelopesMonitor) handleEventEnvelopeReceived(event whisper.EnvelopeEvent) {
func (m *EnvelopesMonitor) handleEventEnvelopeReceived(event whispertypes.EnvelopeEvent) {
if m.mailServerConfirmation {
if !m.isMailserver(event.Peer) {
return
@ -302,7 +311,7 @@ func (m *EnvelopesMonitor) handleEventEnvelopeReceived(event whisper.EnvelopeEve
// clearMessageState removes all message and envelope state.
// not thread-safe, should be protected on a higher level.
func (m *EnvelopesMonitor) clearMessageState(envelopeID common.Hash) {
func (m *EnvelopesMonitor) clearMessageState(envelopeID statusproto.Hash) {
delete(m.envelopes, envelopeID)
delete(m.messages, envelopeID)
delete(m.attempts, envelopeID)

View File

@ -10,7 +10,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/pkg/errors"
whisper "github.com/status-im/whisper/whisperv6"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
"go.uber.org/zap"
)
@ -26,15 +26,10 @@ var (
type whisperFilter struct {
FilterID string
Topic whisper.TopicType
Topic whispertypes.TopicType
SymKeyID string
}
type NegotiatedSecret struct {
PublicKey *ecdsa.PublicKey
Key []byte
}
// TODO: revise fields encoding/decoding. Some are encoded using hexutil and some using encoding/hex.
type Filter struct {
// ChatID is the identifier of the chat
@ -49,7 +44,7 @@ type Filter struct {
// It's encoded using encoding/hex.
Identity string `json:"identity"`
// Topic is the whisper topic
Topic whisper.TopicType `json:"topic"`
Topic whispertypes.TopicType `json:"topic"`
// Discovery is whether this is a discovery topic
Discovery bool `json:"discovery"`
// Negotiated tells us whether is a negotiated topic
@ -63,7 +58,7 @@ func (c *Filter) IsPublic() bool {
}
type filtersManager struct {
whisper *whisper.Whisper
whisper whispertypes.Whisper
persistence *sqlitePersistence
privateKey *ecdsa.PrivateKey
keys map[string][]byte // a cache of symmetric manager derived from passwords
@ -76,7 +71,7 @@ type filtersManager struct {
}
// newFiltersManager returns a new filtersManager.
func newFiltersManager(db *sql.DB, w *whisper.Whisper, privateKey *ecdsa.PrivateKey, logger *zap.Logger) (*filtersManager, error) {
func newFiltersManager(db *sql.DB, w whispertypes.Whisper, privateKey *ecdsa.PrivateKey, logger *zap.Logger) (*filtersManager, error) {
if logger == nil {
logger = zap.NewNop()
}
@ -288,7 +283,7 @@ func (s *filtersManager) loadPartitioned(publicKey *ecdsa.PublicKey, listen bool
}
// LoadNegotiated loads a negotiated secret as a filter.
func (s *filtersManager) LoadNegotiated(secret NegotiatedSecret) (*Filter, error) {
func (s *filtersManager) LoadNegotiated(secret whispertypes.NegotiatedSecret) (*Filter, error) {
s.mutex.Lock()
defer s.mutex.Unlock()
@ -483,13 +478,11 @@ func (s *filtersManager) addSymmetric(chatID string) (*whisperFilter, error) {
}
}
f := &whisper.Filter{
KeySym: symKey,
PoW: minPow,
AllowP2P: true,
Topics: topics,
Messages: s.whisper.NewMessageStore(),
}
f := s.whisper.CreateFilterWrapper(
nil, symKey,
minPow,
topics,
s.whisper.NewMessageStore())
id, err := s.whisper.Subscribe(f)
if err != nil {
@ -499,7 +492,7 @@ func (s *filtersManager) addSymmetric(chatID string) (*whisperFilter, error) {
return &whisperFilter{
FilterID: id,
SymKeyID: symKeyID,
Topic: whisper.BytesToTopic(topic),
Topic: whispertypes.BytesToTopic(topic),
}, nil
}
@ -518,19 +511,17 @@ func (s *filtersManager) addAsymmetric(chatID string, listen bool) (*whisperFilt
topic := toTopic(chatID)
topics := [][]byte{topic}
f := &whisper.Filter{
KeyAsym: s.privateKey,
PoW: pow,
AllowP2P: true,
Topics: topics,
Messages: s.whisper.NewMessageStore(),
}
f := s.whisper.CreateFilterWrapper(
s.privateKey, nil,
pow,
topics,
s.whisper.NewMessageStore())
id, err := s.whisper.Subscribe(f)
if err != nil {
return nil, err
}
return &whisperFilter{FilterID: id, Topic: whisper.BytesToTopic(topic)}, nil
return &whisperFilter{FilterID: id, Topic: whispertypes.BytesToTopic(topic)}, nil
}
// GetNegotiated returns a negotiated chat given an identity
@ -542,7 +533,7 @@ func (s *filtersManager) GetNegotiated(identity *ecdsa.PublicKey) *Filter {
}
func toTopic(s string) []byte {
return crypto.Keccak256([]byte(s))[:whisper.TopicLength]
return crypto.Keccak256([]byte(s))[:whispertypes.TopicLength]
}
// ToTopic converts a string to a whisper topic.

View File

@ -0,0 +1,31 @@
package gethbridge
import (
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
statusproto "github.com/status-im/status-protocol-go/types"
whisper "github.com/status-im/whisper/whisperv6"
)
type gethEnvelopeWrapper struct {
envelope *whisper.Envelope
}
// NewGethEnvelopeWrapper returns an object that wraps Geth's Envelope in a whispertypes interface
func NewGethEnvelopeWrapper(e *whisper.Envelope) whispertypes.Envelope {
return &gethEnvelopeWrapper{
envelope: e,
}
}
// GetGethEnvelopeFrom retrieves the underlying whisper Envelope struct from a wrapped Envelope interface
func GetGethEnvelopeFrom(f whispertypes.Envelope) *whisper.Envelope {
return f.(*gethEnvelopeWrapper).envelope
}
func (w *gethEnvelopeWrapper) Hash() statusproto.Hash {
return statusproto.Hash(w.envelope.Hash())
}
func (w *gethEnvelopeWrapper) Bloom() []byte {
return w.envelope.Bloom()
}

View File

@ -0,0 +1,30 @@
package gethbridge
import (
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
statusproto "github.com/status-im/status-protocol-go/types"
whisper "github.com/status-im/whisper/whisperv6"
)
// NewGethEnvelopeErrorWrapper returns a whispertypes.EnvelopeError object that mimics Geth's EnvelopeError
func NewGethEnvelopeErrorWrapper(envelopeError *whisper.EnvelopeError) *whispertypes.EnvelopeError {
if envelopeError == nil {
panic("envelopeError should not be nil")
}
return &whispertypes.EnvelopeError{
Hash: statusproto.Hash(envelopeError.Hash),
Code: mapGethErrorCode(envelopeError.Code),
Description: envelopeError.Description,
}
}
func mapGethErrorCode(code uint) uint {
switch code {
case whisper.EnvelopeTimeNotSynced:
return whispertypes.EnvelopeTimeNotSynced
case whisper.EnvelopeOtherError:
return whispertypes.EnvelopeOtherError
}
return whispertypes.EnvelopeOtherError
}

View File

@ -0,0 +1,34 @@
package gethbridge
import (
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
statusproto "github.com/status-im/status-protocol-go/types"
whisper "github.com/status-im/whisper/whisperv6"
)
// NewGethEnvelopeEventWrapper returns a whispertypes.EnvelopeEvent object that mimics Geth's EnvelopeEvent
func NewGethEnvelopeEventWrapper(envelopeEvent *whisper.EnvelopeEvent) *whispertypes.EnvelopeEvent {
if envelopeEvent == nil {
panic("envelopeEvent should not be nil")
}
wrappedData := envelopeEvent.Data
switch data := envelopeEvent.Data.(type) {
case []whisper.EnvelopeError:
wrappedData := make([]whispertypes.EnvelopeError, len(data))
for index, envError := range data {
wrappedData[index] = *NewGethEnvelopeErrorWrapper(&envError)
}
case *whisper.MailServerResponse:
wrappedData = NewGethMailServerResponseWrapper(data)
case whisper.SyncEventResponse:
wrappedData = NewGethSyncEventResponseWrapper(data)
}
return &whispertypes.EnvelopeEvent{
Event: whispertypes.EventType(envelopeEvent.Event),
Hash: statusproto.Hash(envelopeEvent.Hash),
Batch: statusproto.Hash(envelopeEvent.Batch),
Peer: whispertypes.EnodeID(envelopeEvent.Peer),
Data: wrappedData,
}
}

View File

@ -0,0 +1,38 @@
package gethbridge
import (
"crypto/ecdsa"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
whisper "github.com/status-im/whisper/whisperv6"
)
type gethFilterWrapper struct {
filter *whisper.Filter
}
// NewGethFilterWrapper returns an object that wraps Geth's Filter in a whispertypes interface
func NewGethFilterWrapper(f *whisper.Filter) whispertypes.Filter {
if f.Messages == nil {
panic("Messages should not be nil")
}
return &gethFilterWrapper{
filter: f,
}
}
// GetGethFilterFrom retrieves the underlying whisper Filter struct from a wrapped Filter interface
func GetGethFilterFrom(f whispertypes.Filter) *whisper.Filter {
return f.(*gethFilterWrapper).filter
}
// KeyAsym returns the private Key of recipient
func (w *gethFilterWrapper) KeyAsym() *ecdsa.PrivateKey {
return w.filter.KeyAsym
}
// KeySym returns the key associated with the Topic
func (w *gethFilterWrapper) KeySym() []byte {
return w.filter.KeySym
}

View File

@ -0,0 +1,20 @@
package gethbridge
import (
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
statusproto "github.com/status-im/status-protocol-go/types"
whisper "github.com/status-im/whisper/whisperv6"
)
// NewGethMailServerResponseWrapper returns a whispertypes.MailServerResponse object that mimics Geth's MailServerResponse
func NewGethMailServerResponseWrapper(mailServerResponse *whisper.MailServerResponse) *whispertypes.MailServerResponse {
if mailServerResponse == nil {
panic("mailServerResponse should not be nil")
}
return &whispertypes.MailServerResponse{
LastEnvelopeHash: statusproto.Hash(mailServerResponse.LastEnvelopeHash),
Cursor: mailServerResponse.Cursor,
Error: mailServerResponse.Error,
}
}

View File

@ -0,0 +1,43 @@
package gethbridge
import (
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
whisper "github.com/status-im/whisper/whisperv6"
)
type gethMessageStoreWrapper struct {
messageStore whisper.MessageStore
}
// NewGethMessageStoreWrapper returns an object that wraps Geth's MessageStore in a whispertypes interface
func NewGethMessageStoreWrapper(messageStore whisper.MessageStore) whispertypes.MessageStore {
if messageStore == nil {
panic("messageStore cannot be nil")
}
return &gethMessageStoreWrapper{
messageStore: messageStore,
}
}
// GetGethMessageStoreFrom retrieves the underlying whisper MessageStore interface from a wrapped MessageStore interface
func GetGethMessageStoreFrom(m whispertypes.MessageStore) whisper.MessageStore {
return m.(*gethMessageStoreWrapper).messageStore
}
func (w *gethMessageStoreWrapper) Add(m whispertypes.ReceivedMessage) error {
return w.messageStore.Add(GetGethReceivedMessageFrom(m))
}
func (w *gethMessageStoreWrapper) Pop() ([]whispertypes.ReceivedMessage, error) {
msgs, err := w.messageStore.Pop()
if err != nil {
return nil, err
}
wrappedMsgs := make([]whispertypes.ReceivedMessage, len(msgs))
for index, m := range msgs {
wrappedMsgs[index] = NewGethReceivedMessageWrapper(m)
}
return wrappedMsgs, err
}

View File

@ -0,0 +1,103 @@
package gethbridge
import (
"context"
"github.com/ethereum/go-ethereum/common/hexutil"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
statusproto "github.com/status-im/status-protocol-go/types"
whisper "github.com/status-im/whisper/whisperv6"
)
type gethPublicWhisperAPIWrapper struct {
publicWhisperAPI *whisper.PublicWhisperAPI
}
// NewGethPublicWhisperAPIWrapper returns an object that wraps Geth's PublicWhisperAPI in a whispertypes interface
func NewGethPublicWhisperAPIWrapper(publicWhisperAPI *whisper.PublicWhisperAPI) whispertypes.PublicWhisperAPI {
if publicWhisperAPI == nil {
panic("publicWhisperAPI cannot be nil")
}
return &gethPublicWhisperAPIWrapper{
publicWhisperAPI: publicWhisperAPI,
}
}
// AddPrivateKey imports the given private key.
func (w *gethPublicWhisperAPIWrapper) AddPrivateKey(ctx context.Context, privateKey statusproto.HexBytes) (string, error) {
return w.publicWhisperAPI.AddPrivateKey(ctx, hexutil.Bytes(privateKey))
}
// GenerateSymKeyFromPassword derives a key from the given password, stores it, and returns its ID.
func (w *gethPublicWhisperAPIWrapper) GenerateSymKeyFromPassword(ctx context.Context, passwd string) (string, error) {
return w.publicWhisperAPI.GenerateSymKeyFromPassword(ctx, passwd)
}
// DeleteKeyPair removes the key with the given key if it exists.
func (w *gethPublicWhisperAPIWrapper) DeleteKeyPair(ctx context.Context, key string) (bool, error) {
return w.publicWhisperAPI.DeleteKeyPair(ctx, key)
}
// NewMessageFilter creates a new filter that can be used to poll for
// (new) messages that satisfy the given criteria.
func (w *gethPublicWhisperAPIWrapper) NewMessageFilter(req whispertypes.Criteria) (string, error) {
topics := make([]whisper.TopicType, len(req.Topics))
for index, tt := range req.Topics {
topics[index] = whisper.TopicType(tt)
}
criteria := whisper.Criteria{
SymKeyID: req.SymKeyID,
PrivateKeyID: req.PrivateKeyID,
Sig: req.Sig,
MinPow: req.MinPow,
Topics: topics,
AllowP2P: req.AllowP2P,
}
return w.publicWhisperAPI.NewMessageFilter(criteria)
}
// GetFilterMessages returns the messages that match the filter criteria and
// are received between the last poll and now.
func (w *gethPublicWhisperAPIWrapper) GetFilterMessages(id string) ([]*whispertypes.Message, error) {
msgs, err := w.publicWhisperAPI.GetFilterMessages(id)
if err != nil {
return nil, err
}
wrappedMsgs := make([]*whispertypes.Message, len(msgs))
for index, msg := range msgs {
wrappedMsgs[index] = &whispertypes.Message{
Sig: msg.Sig,
TTL: msg.TTL,
Timestamp: msg.Timestamp,
Topic: whispertypes.TopicType(msg.Topic),
Payload: msg.Payload,
Padding: msg.Padding,
PoW: msg.PoW,
Hash: msg.Hash,
Dst: msg.Dst,
P2P: msg.P2P,
}
}
return wrappedMsgs, nil
}
// Post posts a message on the Whisper network.
// returns the hash of the message in case of success.
func (w *gethPublicWhisperAPIWrapper) Post(ctx context.Context, req whispertypes.NewMessage) ([]byte, error) {
msg := whisper.NewMessage{
SymKeyID: req.SymKeyID,
PublicKey: req.PublicKey,
Sig: req.Sig,
TTL: req.TTL,
Topic: whisper.TopicType(req.Topic),
Payload: req.Payload,
Padding: req.Padding,
PowTime: req.PowTime,
PowTarget: req.PowTarget,
TargetPeer: req.TargetPeer,
}
return w.publicWhisperAPI.Post(ctx, msg)
}

View File

@ -0,0 +1,26 @@
package gethbridge
import (
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
whisper "github.com/status-im/whisper/whisperv6"
)
type gethReceivedMessageWrapper struct {
receivedMessage *whisper.ReceivedMessage
}
// NewGethReceivedMessageWrapper returns an object that wraps Geth's ReceivedMessage in a whispertypes interface
func NewGethReceivedMessageWrapper(receivedMessage *whisper.ReceivedMessage) whispertypes.ReceivedMessage {
if receivedMessage == nil {
panic("receivedMessage cannot be nil")
}
return &gethReceivedMessageWrapper{
receivedMessage: receivedMessage,
}
}
// GetGethReceivedMessageFrom retrieves the underlying whisper ReceivedMessage struct from a wrapped ReceivedMessage interface
func GetGethReceivedMessageFrom(m whispertypes.ReceivedMessage) *whisper.ReceivedMessage {
return m.(*gethReceivedMessageWrapper).receivedMessage
}

View File

@ -0,0 +1,29 @@
package gethbridge
import (
"github.com/ethereum/go-ethereum/event"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
)
type gethSubscriptionWrapper struct {
subscription event.Subscription
}
// NewGethSubscriptionWrapper returns an object that wraps Geth's Subscription in a whispertypes interface
func NewGethSubscriptionWrapper(subscription event.Subscription) whispertypes.Subscription {
if subscription == nil {
panic("subscription cannot be nil")
}
return &gethSubscriptionWrapper{
subscription: subscription,
}
}
func (w *gethSubscriptionWrapper) Err() <-chan error {
return w.subscription.Err()
}
func (w *gethSubscriptionWrapper) Unsubscribe() {
w.subscription.Unsubscribe()
}

View File

@ -0,0 +1,14 @@
package gethbridge
import (
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
whisper "github.com/status-im/whisper/whisperv6"
)
// NewGethSyncEventResponseWrapper returns a whispertypes.SyncEventResponse object that mimics Geth's SyncEventResponse
func NewGethSyncEventResponseWrapper(syncEventResponse whisper.SyncEventResponse) whispertypes.SyncEventResponse {
return whispertypes.SyncEventResponse{
Cursor: syncEventResponse.Cursor,
Error: syncEventResponse.Error,
}
}

View File

@ -0,0 +1,17 @@
package gethbridge
import (
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
whisper "github.com/status-im/whisper/whisperv6"
)
// GetGethSyncMailRequestFrom converts a whisper SyncMailRequest struct from a SyncMailRequest struct
func GetGethSyncMailRequestFrom(r *whispertypes.SyncMailRequest) *whisper.SyncMailRequest {
return &whisper.SyncMailRequest{
Lower: r.Lower,
Upper: r.Upper,
Bloom: r.Bloom,
Limit: r.Limit,
Cursor: r.Cursor,
}
}

View File

@ -0,0 +1,150 @@
package gethbridge
import (
"crypto/ecdsa"
"time"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
whisper "github.com/status-im/whisper/whisperv6"
)
type gethWhisperWrapper struct {
whisper *whisper.Whisper
}
// NewGethWhisperWrapper returns an object that wraps Geth's Whisper in a whispertypes interface
func NewGethWhisperWrapper(w *whisper.Whisper) whispertypes.Whisper {
if w == nil {
panic("w cannot be nil")
}
return &gethWhisperWrapper{
whisper: w,
}
}
// GetGethWhisperFrom retrieves the underlying whisper Whisper struct from a wrapped Whisper interface
func GetGethWhisperFrom(m whispertypes.Whisper) *whisper.Whisper {
return m.(*gethWhisperWrapper).whisper
}
func (w *gethWhisperWrapper) PublicWhisperAPI() whispertypes.PublicWhisperAPI {
return NewGethPublicWhisperAPIWrapper(whisper.NewPublicWhisperAPI(w.whisper))
}
func (w *gethWhisperWrapper) NewMessageStore() whispertypes.MessageStore {
return NewGethMessageStoreWrapper(w.whisper.NewMessageStore())
}
// MinPow returns the PoW value required by this node.
func (w *gethWhisperWrapper) MinPow() float64 {
return w.whisper.MinPow()
}
// BloomFilter returns the aggregated bloom filter for all the topics of interest.
// The nodes are required to send only messages that match the advertised bloom filter.
// If a message does not match the bloom, it will tantamount to spam, and the peer will
// be disconnected.
func (w *gethWhisperWrapper) BloomFilter() []byte {
return w.whisper.BloomFilter()
}
// GetCurrentTime returns current time.
func (w *gethWhisperWrapper) GetCurrentTime() time.Time {
return w.whisper.GetCurrentTime()
}
// SetTimeSource assigns a particular source of time to a whisper object.
func (w *gethWhisperWrapper) SetTimeSource(timesource func() time.Time) {
w.whisper.SetTimeSource(timesource)
}
func (w *gethWhisperWrapper) SubscribeEnvelopeEvents(eventsProxy chan<- whispertypes.EnvelopeEvent) whispertypes.Subscription {
events := make(chan whisper.EnvelopeEvent, 100) // must be buffered to prevent blocking whisper
go func() {
for e := range events {
eventsProxy <- *NewGethEnvelopeEventWrapper(&e)
}
}()
return NewGethSubscriptionWrapper(w.whisper.SubscribeEnvelopeEvents(events))
}
// SelectedKeyPairID returns the id of currently selected key pair.
// It helps distinguish between different users w/o exposing the user identity itself.
func (w *gethWhisperWrapper) SelectedKeyPairID() string {
return w.whisper.SelectedKeyPairID()
}
func (w *gethWhisperWrapper) GetPrivateKey(id string) (*ecdsa.PrivateKey, error) {
return w.whisper.GetPrivateKey(id)
}
// AddKeyPair imports a asymmetric private key and returns a deterministic identifier.
func (w *gethWhisperWrapper) AddKeyPair(key *ecdsa.PrivateKey) (string, error) {
return w.whisper.AddKeyPair(key)
}
// DeleteKeyPair deletes the specified key if it exists.
func (w *gethWhisperWrapper) DeleteKeyPair(key string) bool {
return w.whisper.DeleteKeyPair(key)
}
// SelectKeyPair adds cryptographic identity, and makes sure
// that it is the only private key known to the node.
func (w *gethWhisperWrapper) SelectKeyPair(key *ecdsa.PrivateKey) error {
return w.whisper.SelectKeyPair(key)
}
func (w *gethWhisperWrapper) AddSymKeyDirect(key []byte) (string, error) {
return w.whisper.AddSymKeyDirect(key)
}
func (w *gethWhisperWrapper) AddSymKeyFromPassword(password string) (string, error) {
return w.whisper.AddSymKeyFromPassword(password)
}
func (w *gethWhisperWrapper) DeleteSymKey(id string) bool {
return w.whisper.DeleteSymKey(id)
}
func (w *gethWhisperWrapper) GetSymKey(id string) ([]byte, error) {
return w.whisper.GetSymKey(id)
}
func (w *gethWhisperWrapper) Subscribe(f whispertypes.Filter) (string, error) {
return w.whisper.Subscribe(GetGethFilterFrom(f))
}
func (w *gethWhisperWrapper) GetFilter(id string) whispertypes.Filter {
return NewGethFilterWrapper(w.whisper.GetFilter(id))
}
func (w *gethWhisperWrapper) Unsubscribe(id string) error {
return w.whisper.Unsubscribe(id)
}
func (w *gethWhisperWrapper) CreateFilterWrapper(keyAsym *ecdsa.PrivateKey, keySym []byte, pow float64, topics [][]byte, messages whispertypes.MessageStore) whispertypes.Filter {
return NewGethFilterWrapper(&whisper.Filter{
KeyAsym: keyAsym,
KeySym: keySym,
PoW: pow,
AllowP2P: true,
Topics: topics,
Messages: GetGethMessageStoreFrom(messages),
})
}
// RequestHistoricMessages sends a message with p2pRequestCode to a specific peer,
// which is known to implement MailServer interface, and is supposed to process this
// request and respond with a number of peer-to-peer messages (possibly expired),
// which are not supposed to be forwarded any further.
// The whisper protocol is agnostic of the format and contents of envelope.
func (w *gethWhisperWrapper) RequestHistoricMessagesWithTimeout(peerID []byte, envelope whispertypes.Envelope, timeout time.Duration) error {
return w.whisper.RequestHistoricMessagesWithTimeout(peerID, GetGethEnvelopeFrom(envelope), timeout)
}
// SyncMessages can be sent between two Mail Servers and syncs envelopes between them.
func (w *gethWhisperWrapper) SyncMessages(peerID []byte, req whispertypes.SyncMailRequest) error {
return w.whisper.SyncMessages(peerID, *GetGethSyncMailRequestFrom(&req))
}

View File

@ -0,0 +1,81 @@
package whispertypes
import statusproto "github.com/status-im/status-protocol-go/types"
// 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 interface {
Hash() statusproto.Hash // Cached hash of the envelope to avoid rehashing every time.
Bloom() []byte
}
// EventType used to define known envelope events.
type EventType string
// NOTE: This list of event names is extracted from Geth. It must be kept in sync, or otherwise a mapping layer needs to be created
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"
)
const (
EnvelopeTimeNotSynced uint = 1000
EnvelopeOtherError
)
// EnvelopeEvent used for envelopes events.
type EnvelopeEvent struct {
Event EventType
Hash statusproto.Hash
Batch statusproto.Hash
Peer EnodeID
Data interface{}
}
// EnvelopeError code and optional description of the error.
type EnvelopeError struct {
Hash statusproto.Hash
Code uint
Description string
}
// Subscription represents a stream of events. The carrier of the events is typically a
// channel, but isn't part of the interface.
//
// Subscriptions can fail while established. Failures are reported through an error
// channel. It receives a value if there is an issue with the subscription (e.g. the
// network connection delivering the events has been closed). Only one value will ever be
// sent.
//
// The error channel is closed when the subscription ends successfully (i.e. when the
// source of events is closed). It is also closed when Unsubscribe is called.
//
// The Unsubscribe method cancels the sending of events. You must call Unsubscribe in all
// cases to ensure that resources related to the subscription are released. It can be
// called any number of times.
type Subscription interface {
Err() <-chan error // returns the error channel
Unsubscribe() // cancels sending of events, closing the error channel
}

View File

@ -0,0 +1,17 @@
package whispertypes
import (
"crypto/ecdsa"
)
// Filter represents a Whisper message filter
type Filter interface {
KeyAsym() *ecdsa.PrivateKey // Private Key of recipient
KeySym() []byte // Key associated with the Topic
}
// MessageStore defines the interface for a temporary message store.
type MessageStore interface {
Add(ReceivedMessage) error
Pop() ([]ReceivedMessage, error)
}

View File

@ -0,0 +1,32 @@
package whispertypes
import statusproto "github.com/status-im/status-protocol-go/types"
// MailServerResponse is the response payload sent by the mailserver
type MailServerResponse struct {
LastEnvelopeHash statusproto.Hash
Cursor []byte
Error error
}
// 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
}
// SyncEventResponse is a response from the Mail Server
// form which the peer received envelopes.
type SyncEventResponse struct {
Cursor []byte
Error string
}

View File

@ -0,0 +1,10 @@
package whispertypes
import (
"crypto/ecdsa"
)
type NegotiatedSecret struct {
PublicKey *ecdsa.PublicKey
Key []byte
}

View File

@ -0,0 +1,11 @@
package whispertypes
import "fmt"
// EnodeID is a unique identifier for each node.
type EnodeID [32]byte
// ID prints as a long hexadecimal number.
func (n EnodeID) String() string {
return fmt.Sprintf("%x", n[:])
}

View File

@ -0,0 +1,6 @@
package whispertypes
// ReceivedMessage represents a data packet to be received through the
// Whisper protocol and successfully decrypted.
type ReceivedMessage interface {
}

View File

@ -0,0 +1,67 @@
package whispertypes
import (
"context"
statusproto "github.com/status-im/status-protocol-go/types"
)
// 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"`
}
// 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"`
}
// 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"`
}
// PublicWhisperAPI provides the whisper RPC service that can be
// use publicly without security implications.
type PublicWhisperAPI interface {
// AddPrivateKey imports the given private key.
AddPrivateKey(ctx context.Context, privateKey statusproto.HexBytes) (string, error)
// GenerateSymKeyFromPassword derives a key from the given password, stores it, and returns its ID.
GenerateSymKeyFromPassword(ctx context.Context, passwd string) (string, error)
// DeleteKeyPair removes the key with the given key if it exists.
DeleteKeyPair(ctx context.Context, key string) (bool, error)
// Post posts a message on the Whisper network.
// returns the hash of the message in case of success.
Post(ctx context.Context, req NewMessage) ([]byte, error)
// NewMessageFilter creates a new filter that can be used to poll for
// (new) messages that satisfy the given criteria.
NewMessageFilter(req Criteria) (string, error)
// GetFilterMessages returns the messages that match the filter criteria and
// are received between the last poll and now.
GetFilterMessages(id string) ([]*Message, error)
}

View File

@ -0,0 +1,88 @@
package whispertypes
import (
"github.com/ethereum/go-ethereum/common/hexutil"
statusproto "github.com/status-im/status-protocol-go/types"
)
const (
// TopicLength is the expected length of the topic, in bytes
TopicLength = 4
BloomFilterSize = 64 // in bytes
)
// TopicType represents a cryptographically secure, probabilistic partial
// classifications of a message, determined as the first (left) 4 bytes of the
// SHA3 hash of some arbitrary data given by the original author of the message.
type TopicType [TopicLength]byte
// BytesToTopic converts from the byte array representation of a topic
// into the TopicType type.
func BytesToTopic(b []byte) (t TopicType) {
sz := TopicLength
if x := len(b); x < TopicLength {
sz = x
}
for i := 0; i < sz; i++ {
t[i] = b[i]
}
return t
}
// String converts a topic byte array to a string representation.
func (t *TopicType) String() string {
return statusproto.EncodeHex(t[:])
}
// MarshalText returns the hex representation of t.
func (t TopicType) MarshalText() ([]byte, error) {
return statusproto.HexBytes(t[:]).MarshalText()
}
// UnmarshalText parses a hex representation to a topic.
func (t *TopicType) UnmarshalText(input []byte) error {
return hexutil.UnmarshalFixedText("Topic", input, t[:])
}
// 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
}
func BloomFilterMatch(filter, sample []byte) bool {
if filter == nil {
return true
}
for i := 0; i < BloomFilterSize; i++ {
f := filter[i]
s := sample[i]
if (f | s) != f {
return false
}
}
return true
}
func MakeFullNodeBloom() []byte {
bloom := make([]byte, BloomFilterSize)
for i := 0; i < BloomFilterSize; i++ {
bloom[i] = 0xFF
}
return bloom
}

View File

@ -0,0 +1,61 @@
package whispertypes
import (
"crypto/ecdsa"
"time"
)
// Whisper represents a dark communication interface through the Ethereum
// network, using its very own P2P communication layer.
type Whisper interface {
PublicWhisperAPI() PublicWhisperAPI
NewMessageStore() MessageStore
// MinPow returns the PoW value required by this node.
MinPow() float64
// BloomFilter returns the aggregated bloom filter for all the topics of interest.
// The nodes are required to send only messages that match the advertised bloom filter.
// If a message does not match the bloom, it will tantamount to spam, and the peer will
// be disconnected.
BloomFilter() []byte
// SetTimeSource assigns a particular source of time to a whisper object.
SetTimeSource(timesource func() time.Time)
// GetCurrentTime returns current time.
GetCurrentTime() time.Time
// SelectedKeyPairID returns the id of currently selected key pair.
// It helps distinguish between different users w/o exposing the user identity itself.
SelectedKeyPairID() string
// GetPrivateKey retrieves the private key of the specified identity.
GetPrivateKey(id string) (*ecdsa.PrivateKey, error)
SubscribeEnvelopeEvents(events chan<- EnvelopeEvent) Subscription
// AddKeyPair imports a asymmetric private key and returns a deterministic identifier.
AddKeyPair(key *ecdsa.PrivateKey) (string, error)
// DeleteKeyPair deletes the specified key if it exists.
DeleteKeyPair(key string) bool
// SelectKeyPair adds cryptographic identity, and makes sure
// that it is the only private key known to the node.
SelectKeyPair(key *ecdsa.PrivateKey) error
AddSymKeyDirect(key []byte) (string, error)
AddSymKeyFromPassword(password string) (string, error)
DeleteSymKey(id string) bool
GetSymKey(id string) ([]byte, error)
Subscribe(f Filter) (string, error)
GetFilter(id string) Filter
Unsubscribe(id string) error
CreateFilterWrapper(keyAsym *ecdsa.PrivateKey, keySym []byte, pow float64, topics [][]byte, messages MessageStore) Filter
// RequestHistoricMessages sends a message with p2pRequestCode to a specific peer,
// which is known to implement MailServer interface, and is supposed to process this
// request and respond with a number of peer-to-peer messages (possibly expired),
// which are not supposed to be forwarded any further.
// The whisper protocol is agnostic of the format and contents of envelope.
// A timeout of 0 never expires.
RequestHistoricMessagesWithTimeout(peerID []byte, envelope Envelope, timeout time.Duration) error
// SyncMessages can be sent between two Mail Servers and syncs envelopes between them.
SyncMessages(peerID []byte, req SyncMailRequest) error
}

View File

@ -1,11 +1,11 @@
package whisper
import (
whisper "github.com/status-im/whisper/whisperv6"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
)
type RequestOptions struct {
Topics []whisper.TopicType
Topics []whispertypes.TopicType
Password string
Limit int
From int64 // in seconds
@ -16,8 +16,8 @@ const (
defaultPowTime = 1
)
func DefaultWhisperMessage() whisper.NewMessage {
msg := whisper.NewMessage{}
func DefaultWhisperMessage() whispertypes.NewMessage {
msg := whispertypes.NewMessage{}
msg.TTL = 10
msg.PowTarget = 0.002

View File

@ -7,11 +7,12 @@ import (
"sync"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/pkg/errors"
whisper "github.com/status-im/whisper/whisperv6"
"go.uber.org/zap"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
statusproto "github.com/status-im/status-protocol-go/types"
)
var (
@ -20,7 +21,7 @@ var (
)
type whisperServiceKeysManager struct {
shh *whisper.Whisper
shh whispertypes.Whisper
// Identity of the current user.
privateKey *ecdsa.PrivateKey
@ -67,8 +68,8 @@ func SetGenericDiscoveryTopicSupport(val bool) Option {
// WhisperServiceTransport is a transport based on Whisper service.
type WhisperServiceTransport struct {
shh *whisper.Whisper
shhAPI *whisper.PublicWhisperAPI // only PublicWhisperAPI implements logic to send messages
shh whispertypes.Whisper
shhAPI whispertypes.PublicWhisperAPI // only PublicWhisperAPI implements logic to send messages
keysManager *whisperServiceKeysManager
filters *filtersManager
logger *zap.Logger
@ -79,9 +80,9 @@ type WhisperServiceTransport struct {
genericDiscoveryTopicEnabled bool
}
// NewWhisperService returns a new WhisperServiceTransport.
// NewWhisperServiceTransport returns a new WhisperServiceTransport.
func NewWhisperServiceTransport(
shh *whisper.Whisper,
shh whispertypes.Whisper,
privateKey *ecdsa.PrivateKey,
db *sql.DB,
mailservers []string,
@ -96,13 +97,17 @@ func NewWhisperServiceTransport(
var envelopesMonitor *EnvelopesMonitor
if envelopesMonitorConfig != nil {
envelopesMonitor = NewEnvelopesMonitor(shh, envelopesMonitorConfig)
envelopesMonitor = NewEnvelopesMonitor(shh, *envelopesMonitorConfig)
envelopesMonitor.Start()
}
var shhAPI whispertypes.PublicWhisperAPI
if shh != nil {
shhAPI = shh.PublicWhisperAPI()
}
t := &WhisperServiceTransport{
shh: shh,
shhAPI: whisper.NewPublicWhisperAPI(shh),
shhAPI: shhAPI,
envelopesMonitor: envelopesMonitor,
keysManager: &whisperServiceKeysManager{
shh: shh,
@ -145,7 +150,7 @@ func (a *WhisperServiceTransport) Reset() error {
return a.filters.Reset()
}
func (a *WhisperServiceTransport) ProcessNegotiatedSecret(secret NegotiatedSecret) (*Filter, error) {
func (a *WhisperServiceTransport) ProcessNegotiatedSecret(secret whispertypes.NegotiatedSecret) (*Filter, error) {
filter, err := a.filters.LoadNegotiated(secret)
if err != nil {
return nil, err
@ -181,7 +186,7 @@ func (a *WhisperServiceTransport) LeavePrivate(publicKey *ecdsa.PublicKey) error
}
type Message struct {
Message *whisper.ReceivedMessage // TODO: should it be whisper.Message?
Message *whispertypes.Message
Public bool
}
@ -189,12 +194,12 @@ func (a *WhisperServiceTransport) RetrieveAllMessages() ([]Message, error) {
var messages []Message
for _, filter := range a.filters.Filters() {
f := a.shh.GetFilter(filter.FilterID)
if f == nil {
return nil, errors.New("failed to return a filter")
filterMsgs, err := a.shhAPI.GetFilterMessages(filter.FilterID)
if err != nil {
return nil, err
}
for _, m := range f.Retrieve() {
for _, m := range filterMsgs {
messages = append(messages, Message{
Message: m,
Public: filter.IsPublic(),
@ -205,36 +210,31 @@ func (a *WhisperServiceTransport) RetrieveAllMessages() ([]Message, error) {
return messages, nil
}
func (a *WhisperServiceTransport) RetrievePublicMessages(chatID string) ([]*whisper.ReceivedMessage, error) {
func (a *WhisperServiceTransport) RetrievePublicMessages(chatID string) ([]*whispertypes.Message, error) {
filter, err := a.filters.LoadPublic(chatID)
if err != nil {
return nil, err
}
f := a.shh.GetFilter(filter.FilterID)
if f == nil {
return nil, errors.New("failed to return a filter")
}
return f.Retrieve(), nil
return a.shhAPI.GetFilterMessages(filter.FilterID)
}
func (a *WhisperServiceTransport) RetrievePrivateMessages(publicKey *ecdsa.PublicKey) ([]*whisper.ReceivedMessage, error) {
func (a *WhisperServiceTransport) RetrievePrivateMessages(publicKey *ecdsa.PublicKey) ([]*whispertypes.Message, error) {
chats := a.filters.FiltersByPublicKey(publicKey)
discoveryChats, err := a.filters.Init(nil, nil, true)
if err != nil {
return nil, err
}
var result []*whisper.ReceivedMessage
var result []*whispertypes.Message
for _, chat := range append(chats, discoveryChats...) {
f := a.shh.GetFilter(chat.FilterID)
if f == nil {
return nil, errors.New("failed to return a filter")
filterMsgs, err := a.shhAPI.GetFilterMessages(chat.FilterID)
if err != nil {
return nil, err
}
result = append(result, f.Retrieve()...)
result = append(result, filterMsgs...)
}
return result, nil
@ -242,35 +242,19 @@ func (a *WhisperServiceTransport) RetrievePrivateMessages(publicKey *ecdsa.Publi
// DEPRECATED
// Use RetrieveAllMessages instead.
func (a *WhisperServiceTransport) RetrieveRawAll() (map[Filter][]*whisper.ReceivedMessage, error) {
result := make(map[Filter][]*whisper.ReceivedMessage)
allFilters := a.filters.Filters()
for _, filter := range allFilters {
f := a.shh.GetFilter(filter.FilterID)
if f == nil {
return nil, errors.New("failed to return a filter")
}
result[*filter] = append(result[*filter], f.Retrieve()...)
}
return result, nil
func (a *WhisperServiceTransport) RetrieveRawAll() (map[Filter][]*whispertypes.Message, error) {
return nil, errors.New("not implemented")
}
// DEPRECATED
func (a *WhisperServiceTransport) RetrieveRaw(filterID string) ([]*whisper.ReceivedMessage, error) {
f := a.shh.GetFilter(filterID)
if f == nil {
return nil, errors.New("failed to return a filter")
}
return f.Retrieve(), nil
func (a *WhisperServiceTransport) RetrieveRaw(filterID string) ([]*whispertypes.Message, error) {
return a.shhAPI.GetFilterMessages(filterID)
}
// SendPublic sends a new message using the Whisper service.
// For public filters, chat name is used as an ID as well as
// a topic.
func (a *WhisperServiceTransport) SendPublic(ctx context.Context, newMessage *whisper.NewMessage, chatName string) ([]byte, error) {
func (a *WhisperServiceTransport) SendPublic(ctx context.Context, newMessage *whispertypes.NewMessage, chatName string) ([]byte, error) {
if err := a.addSig(newMessage); err != nil {
return nil, err
}
@ -281,17 +265,17 @@ func (a *WhisperServiceTransport) SendPublic(ctx context.Context, newMessage *wh
}
newMessage.SymKeyID = filter.SymKeyID
newMessage.Topic = filter.Topic
newMessage.Topic = whispertypes.TopicType(filter.Topic)
return a.shhAPI.Post(ctx, *newMessage)
}
func (a *WhisperServiceTransport) SendPrivateWithSharedSecret(ctx context.Context, newMessage *whisper.NewMessage, publicKey *ecdsa.PublicKey, secret []byte) ([]byte, error) {
func (a *WhisperServiceTransport) SendPrivateWithSharedSecret(ctx context.Context, newMessage *whispertypes.NewMessage, publicKey *ecdsa.PublicKey, secret []byte) ([]byte, error) {
if err := a.addSig(newMessage); err != nil {
return nil, err
}
filter, err := a.filters.LoadNegotiated(NegotiatedSecret{
filter, err := a.filters.LoadNegotiated(whispertypes.NegotiatedSecret{
PublicKey: publicKey,
Key: secret,
})
@ -300,13 +284,13 @@ func (a *WhisperServiceTransport) SendPrivateWithSharedSecret(ctx context.Contex
}
newMessage.SymKeyID = filter.SymKeyID
newMessage.Topic = filter.Topic
newMessage.Topic = whispertypes.TopicType(filter.Topic)
newMessage.PublicKey = nil
return a.shhAPI.Post(ctx, *newMessage)
}
func (a *WhisperServiceTransport) SendPrivateWithPartitioned(ctx context.Context, newMessage *whisper.NewMessage, publicKey *ecdsa.PublicKey) ([]byte, error) {
func (a *WhisperServiceTransport) SendPrivateWithPartitioned(ctx context.Context, newMessage *whispertypes.NewMessage, publicKey *ecdsa.PublicKey) ([]byte, error) {
if err := a.addSig(newMessage); err != nil {
return nil, err
}
@ -316,13 +300,13 @@ func (a *WhisperServiceTransport) SendPrivateWithPartitioned(ctx context.Context
return nil, err
}
newMessage.Topic = filter.Topic
newMessage.Topic = whispertypes.TopicType(filter.Topic)
newMessage.PublicKey = crypto.FromECDSAPub(publicKey)
return a.shhAPI.Post(ctx, *newMessage)
}
func (a *WhisperServiceTransport) SendPrivateOnDiscovery(ctx context.Context, newMessage *whisper.NewMessage, publicKey *ecdsa.PublicKey) ([]byte, error) {
func (a *WhisperServiceTransport) SendPrivateOnDiscovery(ctx context.Context, newMessage *whispertypes.NewMessage, publicKey *ecdsa.PublicKey) ([]byte, error) {
if err := a.addSig(newMessage); err != nil {
return nil, err
}
@ -333,7 +317,7 @@ func (a *WhisperServiceTransport) SendPrivateOnDiscovery(ctx context.Context, ne
// TODO: change this anyway, it should be explicit
// and idempotent.
newMessage.Topic = whisper.BytesToTopic(
newMessage.Topic = whispertypes.BytesToTopic(
ToTopic(discoveryTopic),
)
newMessage.PublicKey = crypto.FromECDSAPub(publicKey)
@ -341,7 +325,7 @@ func (a *WhisperServiceTransport) SendPrivateOnDiscovery(ctx context.Context, ne
return a.shhAPI.Post(ctx, *newMessage)
}
func (a *WhisperServiceTransport) addSig(newMessage *whisper.NewMessage) error {
func (a *WhisperServiceTransport) addSig(newMessage *whispertypes.NewMessage) error {
sigID, err := a.keysManager.AddOrGetKeyPair(a.keysManager.privateKey)
if err != nil {
return err
@ -350,9 +334,9 @@ func (a *WhisperServiceTransport) addSig(newMessage *whisper.NewMessage) error {
return nil
}
func (a *WhisperServiceTransport) Track(identifiers [][]byte, hash []byte, newMessage whisper.NewMessage) {
func (a *WhisperServiceTransport) Track(identifiers [][]byte, hash []byte, newMessage *whispertypes.NewMessage) {
if a.envelopesMonitor != nil {
a.envelopesMonitor.Add(identifiers, common.BytesToHash(hash), newMessage)
a.envelopesMonitor.Add(identifiers, statusproto.BytesToHash(hash), *newMessage)
}
}
@ -385,10 +369,10 @@ type MessagesRequest struct {
// Topic is a regular Whisper topic.
// DEPRECATED
Topic whisper.TopicType `json:"topic"`
Topic whispertypes.TopicType `json:"topic"`
// Topics is a list of Whisper topics.
Topics []whisper.TopicType `json:"topics"`
Topics []whispertypes.TopicType `json:"topics"`
// SymKeyID is an ID of a symmetric key to authenticate to MailServer.
// It's derived from MailServer password.

View File

@ -0,0 +1,80 @@
// Code extracted from vendor/github.com/ethereum/go-ethereum/common/types.go
package statusproto
import (
"encoding/hex"
)
const (
// HashLength is the expected length of the hash
HashLength = 32
)
// Hash represents the 32 byte Keccak256 hash of arbitrary data.
type Hash [HashLength]byte
// Encode encodes b as a hex string with 0x prefix.
func encode(b []byte) string {
enc := make([]byte, len(b)*2+2)
copy(enc, "0x")
hex.Encode(enc[2:], b)
return string(enc)
}
// has0xPrefix validates str begins with '0x' or '0X'.
func has0xPrefix(str string) bool {
return len(str) >= 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X')
}
// Hex2Bytes returns the bytes represented by the hexadecimal string str.
func Hex2Bytes(str string) []byte {
h, _ := hex.DecodeString(str)
return h
}
// FromHex returns the bytes represented by the hexadecimal string s.
// s may be prefixed with "0x".
func FromHex(s string) []byte {
if has0xPrefix(s) {
s = s[2:]
}
if len(s)%2 == 1 {
s = "0" + s
}
return Hex2Bytes(s)
}
// HexToHash sets byte representation of s to hash.
// If b is larger than len(h), b will be cropped from the left.
func HexToHash(s string) Hash { return BytesToHash(FromHex(s)) }
// Hex converts a hash to a hex string.
func (h *Hash) Hex() string { return encode(h[:]) }
// Bytes gets the byte representation of the underlying hash.
func (h Hash) Bytes() []byte { return h[:] }
// String implements the stringer interface and is used also by the logger when
// doing full logging into a file.
func (h *Hash) String() string {
return h.Hex()
}
// SetBytes sets the hash to the value of b.
// If b is larger than len(h), b will be cropped from the left.
func (h *Hash) SetBytes(b []byte) {
if len(b) > len(h) {
b = b[len(b)-HashLength:]
}
copy(h[HashLength-len(b):], b)
}
// BytesToHash sets b to hash.
// If b is larger than len(h), b will be cropped from the left.
func BytesToHash(b []byte) Hash {
var h Hash
h.SetBytes(b)
return h
}

View File

@ -0,0 +1,32 @@
// Code extracted from vendor/github.com/ethereum/go-ethereum/common/hexutil/hexutil.go
package statusproto
import (
"encoding/hex"
"reflect"
)
var (
bytesT = reflect.TypeOf(HexBytes(nil))
)
// HexBytes marshals/unmarshals as a JSON string with 0x prefix.
// The empty slice marshals as "0x".
type HexBytes []byte
// MarshalText implements encoding.TextMarshaler
func (b HexBytes) MarshalText() ([]byte, error) {
result := make([]byte, len(b)*2+2)
copy(result, `0x`)
hex.Encode(result[2:], b)
return result, nil
}
// UnmarshalJSON implements json.Unmarshaler.
func (b *HexBytes) UnmarshalJSON(input []byte) error {
if !isString(input) {
return errNonString(bytesT)
}
return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), bytesT)
}

View File

@ -0,0 +1,171 @@
// Code extracted from vendor/github.com/ethereum/go-ethereum/common/hexutil/json.go
package statusproto
import (
"encoding/hex"
"encoding/json"
"fmt"
"reflect"
"strconv"
)
const (
badNibble = ^uint64(0)
uintBits = 32 << (uint64(^uint(0)) >> 63)
)
// Errors
var (
ErrEmptyString = &decError{"empty hex string"}
ErrSyntax = &decError{"invalid hex string"}
ErrMissingPrefix = &decError{"hex string without 0x prefix"}
ErrOddLength = &decError{"hex string of odd length"}
ErrEmptyNumber = &decError{"hex string \"0x\""}
ErrLeadingZero = &decError{"hex number with leading zero digits"}
ErrUint64Range = &decError{"hex number > 64 bits"}
ErrUintRange = &decError{fmt.Sprintf("hex number > %d bits", uintBits)}
ErrBig256Range = &decError{"hex number > 256 bits"}
)
type decError struct{ msg string }
func (err decError) Error() string { return err.msg }
func decodeNibble(in byte) uint64 {
switch {
case in >= '0' && in <= '9':
return uint64(in - '0')
case in >= 'A' && in <= 'F':
return uint64(in - 'A' + 10)
case in >= 'a' && in <= 'f':
return uint64(in - 'a' + 10)
default:
return badNibble
}
}
// UnmarshalText implements encoding.TextUnmarshaler.
func (b *HexBytes) UnmarshalText(input []byte) error {
raw, err := checkText(input, true)
if err != nil {
return err
}
dec := make([]byte, len(raw)/2)
if _, err = hex.Decode(dec, raw); err != nil {
err = mapError(err)
} else {
*b = dec
}
return err
}
// UnmarshalFixedHexText decodes the input as a string with 0x prefix. The length of out
// determines the required input length. This function is commonly used to implement the
// UnmarshalText method for fixed-size types.
func UnmarshalFixedHexText(typname string, input, out []byte) error {
raw, err := checkText(input, true)
if err != nil {
return err
}
if len(raw)/2 != len(out) {
return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname)
}
// Pre-verify syntax before modifying out.
for _, b := range raw {
if decodeNibble(b) == badNibble {
return ErrSyntax
}
}
_, err = hex.Decode(out, raw)
return err
}
// String returns the hex encoding of b.
func (b HexBytes) String() string {
return EncodeHex(b)
}
// EncodeHex encodes b as a hex string with 0x prefix.
func EncodeHex(b []byte) string {
enc := make([]byte, len(b)*2+2)
copy(enc, "0x")
hex.Encode(enc[2:], b)
return string(enc)
}
// DecodeHex decodes a hex string with 0x prefix.
func DecodeHex(input string) ([]byte, error) {
if len(input) == 0 {
return nil, ErrEmptyString
}
if !has0xPrefix(input) {
return nil, ErrMissingPrefix
}
b, err := hex.DecodeString(input[2:])
if err != nil {
err = mapError(err)
}
return b, err
}
// MustDecodeHex decodes a hex string with 0x prefix. It panics for invalid input.
func MustDecodeHex(input string) []byte {
dec, err := DecodeHex(input)
if err != nil {
panic(err)
}
return dec
}
func isString(input []byte) bool {
return len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"'
}
func bytesHave0xPrefix(input []byte) bool {
return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X')
}
func checkText(input []byte, wantPrefix bool) ([]byte, error) {
if len(input) == 0 {
return nil, nil // empty strings are allowed
}
if bytesHave0xPrefix(input) {
input = input[2:]
} else if wantPrefix {
return nil, ErrMissingPrefix
}
if len(input)%2 != 0 {
return nil, ErrOddLength
}
return input, nil
}
func mapError(err error) error {
if err, ok := err.(*strconv.NumError); ok {
switch err.Err {
case strconv.ErrRange:
return ErrUint64Range
case strconv.ErrSyntax:
return ErrSyntax
}
}
if _, ok := err.(hex.InvalidByteError); ok {
return ErrSyntax
}
if err == hex.ErrLength {
return ErrOddLength
}
return err
}
func wrapTypeError(err error, typ reflect.Type) error {
if _, ok := err.(*decError); ok {
return &json.UnmarshalTypeError{Value: err.Error(), Type: typ}
}
return err
}
func errNonString(typ reflect.Type) error {
return &json.UnmarshalTypeError{Value: "non-string", Type: typ}
}

View File

@ -1,6 +1,24 @@
package statusproto
import "bytes"
import (
"bytes"
"crypto/ecdsa"
"encoding/json"
"reflect"
"sort"
"github.com/status-im/status-protocol-go/crypto"
)
const (
MembershipUpdateChatCreated = "chat-created"
MembershipUpdateNameChanged = "name-changed"
MembershipUpdateMembersAdded = "members-added"
MembershipUpdateMemberJoined = "member-joined"
MembershipUpdateMemberRemoved = "member-removed"
MembershipUpdateAdminsAdded = "admins-added"
MembershipUpdateAdminRemoved = "admin-removed"
)
// MembershipUpdateMessage is a message used to propagate information
// about group membership changes.
@ -18,6 +36,34 @@ type MembershipUpdate struct {
Events []MembershipUpdateEvent `json:"events"`
}
// Sign creates a signature from MembershipUpdateEvents
// and updates MembershipUpdate's signature.
// It follows the algorithm describe in the spec:
// https://github.com/status-im/specs/blob/master/status-group-chats-spec.md#signature.
func (u *MembershipUpdate) Sign(identity *ecdsa.PrivateKey) error {
sort.Slice(u.Events, func(i, j int) bool {
return u.Events[i].ClockValue < u.Events[j].ClockValue
})
tuples := make([]interface{}, len(u.Events))
for idx, event := range u.Events {
tuples[idx] = tupleMembershipUpdateEvent(event)
}
structureToSign := []interface{}{
tuples,
u.ChatID,
}
data, err := json.Marshal(structureToSign)
if err != nil {
return err
}
signature, err := crypto.SignBytesAsHex(data, identity)
if err != nil {
return err
}
u.Signature = signature
return nil
}
type MembershipUpdateEvent struct {
Type string `json:"type"`
ClockValue int64 `json:"clockValue"`
@ -26,6 +72,62 @@ type MembershipUpdateEvent struct {
Name string `json:"name,omitempty"` // name of the group chat
}
func NewChatCreatedEvent(name string, clock int64) MembershipUpdateEvent {
return MembershipUpdateEvent{
Type: MembershipUpdateChatCreated,
Name: name,
ClockValue: clock,
}
}
func NewNameChangedEvent(name string, clock int64) MembershipUpdateEvent {
return MembershipUpdateEvent{
Type: MembershipUpdateNameChanged,
Name: name,
ClockValue: clock,
}
}
func NewMembersAddedEvent(members []string, clock int64) MembershipUpdateEvent {
return MembershipUpdateEvent{
Type: MembershipUpdateMembersAdded,
Members: members,
ClockValue: clock,
}
}
func NewMemberJoinedEvent(member string, clock int64) MembershipUpdateEvent {
return MembershipUpdateEvent{
Type: MembershipUpdateMemberJoined,
Member: member,
ClockValue: clock,
}
}
func NewAdminsAddedEvent(admins []string, clock int64) MembershipUpdateEvent {
return MembershipUpdateEvent{
Type: MembershipUpdateAdminsAdded,
Members: admins,
ClockValue: clock,
}
}
func NewMemberRemovedEvent(member string, clock int64) MembershipUpdateEvent {
return MembershipUpdateEvent{
Type: MembershipUpdateMemberRemoved,
Member: member,
ClockValue: clock,
}
}
func NewAdminRemovedEvent(admin string, clock int64) MembershipUpdateEvent {
return MembershipUpdateEvent{
Type: MembershipUpdateAdminRemoved,
Member: admin,
ClockValue: clock,
}
}
// EncodeMembershipUpdateMessage encodes a MembershipUpdateMessage using Transit serialization.
func EncodeMembershipUpdateMessage(value MembershipUpdateMessage) ([]byte, error) {
var buf bytes.Buffer
@ -35,3 +137,91 @@ func EncodeMembershipUpdateMessage(value MembershipUpdateMessage) ([]byte, error
}
return buf.Bytes(), nil
}
var membershipUpdateEventFieldNamesCompat = map[string]string{
"ClockValue": "clock-value",
"Name": "name",
"Type": "type",
"Member": "member",
"Members": "members",
}
func tupleMembershipUpdateEvent(update MembershipUpdateEvent) [][]interface{} {
// Sort all slices first.
sort.Slice(update.Members, func(i, j int) bool {
return update.Members[i] < update.Members[j]
})
v := reflect.ValueOf(update)
result := make([][]interface{}, 0, v.NumField())
for i := 0; i < v.NumField(); i++ {
fieldName := v.Type().Field(i).Name
if name, exists := membershipUpdateEventFieldNamesCompat[fieldName]; exists {
fieldName = name
}
field := v.Field(i)
if !isZeroValue(field) {
result = append(result, []interface{}{fieldName, field.Interface()})
}
}
// Sort the result lexicographically.
// We know that the first item of a tuple is a string
// because it's a field name.
sort.Slice(result, func(i, j int) bool {
return result[i][0].(string) < result[j][0].(string)
})
return result
}
type Group struct {
ChatID string
Admins []string
Contacts []string
}
// ValidateEvent returns true if a given event is valid.
func (g *Group) ValidateEvent(from string, event MembershipUpdateEvent) bool {
switch event.Type {
case MembershipUpdateChatCreated:
return len(g.Admins) == 0 && len(g.Contacts) == 0
case MembershipUpdateNameChanged:
return stringSliceContains(g.Admins, from) && len(event.Name) > 0
case MembershipUpdateMembersAdded:
return stringSliceContains(g.Admins, from)
case MembershipUpdateMemberJoined:
return stringSliceContains(g.Contacts, from) && from == event.Member
case MembershipUpdateMemberRemoved:
// Member can remove themselves or admin can remove a member.
return from == event.Member || (stringSliceContains(g.Admins, from) && !stringSliceContains(g.Admins, event.Member))
case MembershipUpdateAdminsAdded:
return stringSliceContains(g.Admins, from) && stringSliceSubset(event.Members, g.Contacts)
case MembershipUpdateAdminRemoved:
return stringSliceContains(g.Admins, from) && from == event.Member
default:
return false
}
}
func stringSliceContains(slice []string, item string) bool {
for _, s := range slice {
if s == item {
return true
}
}
return false
}
func stringSliceSubset(subset []string, set []string) bool {
for _, item1 := range set {
var found bool
for _, item2 := range subset {
if item1 == item2 {
found = true
break
}
}
if found {
return true
}
}
return false
}

View File

@ -8,10 +8,10 @@ import (
"strings"
"time"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
"github.com/golang/protobuf/proto"
"github.com/pkg/errors"
statusproto "github.com/status-im/status-protocol-go/types"
)
const (
@ -152,7 +152,7 @@ func EncodeMessage(value Message) ([]byte, error) {
// MessageID calculates the messageID from author's compressed public key
// and not encrypted but encoded payload.
func MessageID(author *ecdsa.PublicKey, data []byte) hexutil.Bytes {
func MessageID(author *ecdsa.PublicKey, data []byte) statusproto.HexBytes {
keyBytes := crypto.FromECDSAPub(author)
return crypto.Keccak256(append(keyBytes, data...))
}

View File

@ -4,7 +4,6 @@ import (
"crypto/ecdsa"
"log"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
"github.com/golang/protobuf/proto"
"github.com/jinzhu/copier"
@ -12,13 +11,14 @@ import (
"github.com/status-im/status-protocol-go/applicationmetadata"
"github.com/status-im/status-protocol-go/datasync"
"github.com/status-im/status-protocol-go/encryption"
whisper "github.com/status-im/whisper/whisperv6"
whispertypes "github.com/status-im/status-protocol-go/transport/whisper/types"
statusproto "github.com/status-im/status-protocol-go/types"
)
// StatusMessage is any Status Protocol message.
type StatusMessage struct {
// TransportMessage is the parsed message received from the transport layer, i.e the input
TransportMessage *whisper.Message
TransportMessage *whispertypes.Message
// ParsedMessage is the parsed message by the application layer, i.e the output
ParsedMessage interface{}
@ -28,7 +28,7 @@ type StatusMessage struct {
DecryptedPayload []byte
// ID is the canonical ID of the message
ID hexutil.Bytes
ID statusproto.HexBytes
// Hash is the transport layer hash
Hash []byte
@ -54,7 +54,7 @@ func (s *StatusMessage) Clone() (*StatusMessage, error) {
return copy, err
}
func (m *StatusMessage) HandleTransport(shhMessage *whisper.Message) error {
func (m *StatusMessage) HandleTransport(shhMessage *whispertypes.Message) error {
publicKey, err := crypto.UnmarshalPubkey(shhMessage.Sig)
if err != nil {
return errors.Wrap(err, "failed to get signature")

View File

@ -0,0 +1,11 @@
// +build go1.13
package statusproto
import "reflect"
// isZeroValue reports whether v is the zero value for its type.
// It panics if the argument is invalid.
func isZeroValue(v reflect.Value) bool {
return v.IsZero()
}

View File

@ -0,0 +1,48 @@
// +build !go1.13
package statusproto
import (
"math"
"reflect"
)
// isZeroValue reports whether v is the zero value for its type.
// It panics if the argument is invalid.
func isZeroValue(v reflect.Value) bool {
switch v.Kind() {
case reflect.Bool:
return !v.Bool()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return v.Int() == 0
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return v.Uint() == 0
case reflect.Float32, reflect.Float64:
return math.Float64bits(v.Float()) == 0
case reflect.Complex64, reflect.Complex128:
c := v.Complex()
return math.Float64bits(real(c)) == 0 && math.Float64bits(imag(c)) == 0
case reflect.Array:
for i := 0; i < v.Len(); i++ {
if !isZeroValue(v.Index(i)) {
return false
}
}
return true
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer:
return v.IsNil()
case reflect.String:
return v.Len() == 0
case reflect.Struct:
for i := 0; i < v.NumField(); i++ {
if !isZeroValue(v.Field(i)) {
return false
}
}
return true
default:
// This should never happens, but will act as a safeguard for
// later, as a default value doesn't makes sense here.
panic(&reflect.ValueError{Method: "reflect.Value.IsZero", Kind: v.Kind()})
}
}

View File

@ -102,7 +102,7 @@ func (api *PublicWhisperAPI) SetBloomFilter(ctx context.Context, bloom hexutil.B
// 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.ParseV4(url)
n, err := enode.Parse(enode.ValidSchemes, url)
if err != nil {
return false, err
}
@ -290,7 +290,7 @@ func (api *PublicWhisperAPI) Post(ctx context.Context, req NewMessage) (hexutil.
// send to specific node (skip PoW check)
if len(req.TargetPeer) > 0 {
n, err := enode.ParseV4(req.TargetPeer)
n, err := enode.Parse(enode.ValidSchemes, req.TargetPeer)
if err != nil {
return nil, fmt.Errorf("failed to parse target peer: %s", err)
}

View File

@ -38,6 +38,7 @@ import (
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp"
)
@ -65,7 +66,7 @@ const (
signatureFlag = byte(4)
TopicLength = 4 // in bytes
signatureLength = 65 // 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

View File

@ -27,7 +27,6 @@ import (
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/ecies"
"github.com/ethereum/go-ethereum/rlp"
@ -82,7 +81,7 @@ func (e *Envelope) Seal(options *MessageParams) error {
return nil
}
var target, bestBit int
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
@ -92,19 +91,21 @@ func (e *Envelope) Seal(options *MessageParams) error {
target = e.powToFirstBit(options.PoW)
}
buf := make([]byte, 64)
h := crypto.Keccak256(e.rlpWithoutNonce())
copy(buf[:32], h)
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[56:], nonce)
d := new(big.Int).SetBytes(crypto.Keccak256(buf))
firstBit := math.FirstBitSet(d)
if firstBit > bestBit {
e.Nonce, bestBit = nonce, firstBit
if target > 0 && bestBit >= target {
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
}
}
@ -112,7 +113,7 @@ func (e *Envelope) Seal(options *MessageParams) error {
}
}
if target > 0 && bestBit < target {
if target > 0 && bestLeadingZeros < target {
return fmt.Errorf("failed to reach the PoW target, specified pow time (%d seconds) was insufficient", options.WorkTime)
}
@ -129,14 +130,14 @@ func (e *Envelope) PoW() float64 {
}
func (e *Envelope) calculatePoW(diff uint32) {
buf := make([]byte, 64)
h := crypto.Keccak256(e.rlpWithoutNonce())
copy(buf[:32], h)
binary.BigEndian.PutUint64(buf[56:], e.Nonce)
d := new(big.Int).SetBytes(crypto.Keccak256(buf))
firstBit := math.FirstBitSet(d)
x := gmath.Pow(2, float64(firstBit))
x /= float64(e.size())
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
}

View File

@ -134,7 +134,7 @@ func (peer *Peer) handshake() error {
}
}
isRemotePeerLightNode, err := s.Bool()
isRemotePeerLightNode, _ := s.Bool()
if isRemotePeerLightNode && isLightNode && isRestrictedLightNodeConnection {
return fmt.Errorf("peer [%x] is useless: two light client communication restricted", peer.ID())
}

View File

@ -1,712 +0,0 @@
// Copyright 2012 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.
// +build ignore
//go:generate go run gen.go
//go:generate go run gen.go -test
package main
import (
"bytes"
"flag"
"fmt"
"go/format"
"io/ioutil"
"math/rand"
"os"
"sort"
"strings"
)
// identifier converts s to a Go exported identifier.
// It converts "div" to "Div" and "accept-charset" to "AcceptCharset".
func identifier(s string) string {
b := make([]byte, 0, len(s))
cap := true
for _, c := range s {
if c == '-' {
cap = true
continue
}
if cap && 'a' <= c && c <= 'z' {
c -= 'a' - 'A'
}
cap = false
b = append(b, byte(c))
}
return string(b)
}
var test = flag.Bool("test", false, "generate table_test.go")
func genFile(name string, buf *bytes.Buffer) {
b, err := format.Source(buf.Bytes())
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
if err := ioutil.WriteFile(name, b, 0644); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
func main() {
flag.Parse()
var all []string
all = append(all, elements...)
all = append(all, attributes...)
all = append(all, eventHandlers...)
all = append(all, extra...)
sort.Strings(all)
// uniq - lists have dups
w := 0
for _, s := range all {
if w == 0 || all[w-1] != s {
all[w] = s
w++
}
}
all = all[:w]
if *test {
var buf bytes.Buffer
fmt.Fprintln(&buf, "// Code generated by go generate gen.go; DO NOT EDIT.\n")
fmt.Fprintln(&buf, "//go:generate go run gen.go -test\n")
fmt.Fprintln(&buf, "package atom\n")
fmt.Fprintln(&buf, "var testAtomList = []string{")
for _, s := range all {
fmt.Fprintf(&buf, "\t%q,\n", s)
}
fmt.Fprintln(&buf, "}")
genFile("table_test.go", &buf)
return
}
// Find hash that minimizes table size.
var best *table
for i := 0; i < 1000000; i++ {
if best != nil && 1<<(best.k-1) < len(all) {
break
}
h := rand.Uint32()
for k := uint(0); k <= 16; k++ {
if best != nil && k >= best.k {
break
}
var t table
if t.init(h, k, all) {
best = &t
break
}
}
}
if best == nil {
fmt.Fprintf(os.Stderr, "failed to construct string table\n")
os.Exit(1)
}
// Lay out strings, using overlaps when possible.
layout := append([]string{}, all...)
// Remove strings that are substrings of other strings
for changed := true; changed; {
changed = false
for i, s := range layout {
if s == "" {
continue
}
for j, t := range layout {
if i != j && t != "" && strings.Contains(s, t) {
changed = true
layout[j] = ""
}
}
}
}
// Join strings where one suffix matches another prefix.
for {
// Find best i, j, k such that layout[i][len-k:] == layout[j][:k],
// maximizing overlap length k.
besti := -1
bestj := -1
bestk := 0
for i, s := range layout {
if s == "" {
continue
}
for j, t := range layout {
if i == j {
continue
}
for k := bestk + 1; k <= len(s) && k <= len(t); k++ {
if s[len(s)-k:] == t[:k] {
besti = i
bestj = j
bestk = k
}
}
}
}
if bestk > 0 {
layout[besti] += layout[bestj][bestk:]
layout[bestj] = ""
continue
}
break
}
text := strings.Join(layout, "")
atom := map[string]uint32{}
for _, s := range all {
off := strings.Index(text, s)
if off < 0 {
panic("lost string " + s)
}
atom[s] = uint32(off<<8 | len(s))
}
var buf bytes.Buffer
// Generate the Go code.
fmt.Fprintln(&buf, "// Code generated by go generate gen.go; DO NOT EDIT.\n")
fmt.Fprintln(&buf, "//go:generate go run gen.go\n")
fmt.Fprintln(&buf, "package atom\n\nconst (")
// compute max len
maxLen := 0
for _, s := range all {
if maxLen < len(s) {
maxLen = len(s)
}
fmt.Fprintf(&buf, "\t%s Atom = %#x\n", identifier(s), atom[s])
}
fmt.Fprintln(&buf, ")\n")
fmt.Fprintf(&buf, "const hash0 = %#x\n\n", best.h0)
fmt.Fprintf(&buf, "const maxAtomLen = %d\n\n", maxLen)
fmt.Fprintf(&buf, "var table = [1<<%d]Atom{\n", best.k)
for i, s := range best.tab {
if s == "" {
continue
}
fmt.Fprintf(&buf, "\t%#x: %#x, // %s\n", i, atom[s], s)
}
fmt.Fprintf(&buf, "}\n")
datasize := (1 << best.k) * 4
fmt.Fprintln(&buf, "const atomText =")
textsize := len(text)
for len(text) > 60 {
fmt.Fprintf(&buf, "\t%q +\n", text[:60])
text = text[60:]
}
fmt.Fprintf(&buf, "\t%q\n\n", text)
genFile("table.go", &buf)
fmt.Fprintf(os.Stdout, "%d atoms; %d string bytes + %d tables = %d total data\n", len(all), textsize, datasize, textsize+datasize)
}
type byLen []string
func (x byLen) Less(i, j int) bool { return len(x[i]) > len(x[j]) }
func (x byLen) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x byLen) Len() int { return len(x) }
// fnv computes the FNV hash with an arbitrary starting value h.
func fnv(h uint32, s string) uint32 {
for i := 0; i < len(s); i++ {
h ^= uint32(s[i])
h *= 16777619
}
return h
}
// A table represents an attempt at constructing the lookup table.
// The lookup table uses cuckoo hashing, meaning that each string
// can be found in one of two positions.
type table struct {
h0 uint32
k uint
mask uint32
tab []string
}
// hash returns the two hashes for s.
func (t *table) hash(s string) (h1, h2 uint32) {
h := fnv(t.h0, s)
h1 = h & t.mask
h2 = (h >> 16) & t.mask
return
}
// init initializes the table with the given parameters.
// h0 is the initial hash value,
// k is the number of bits of hash value to use, and
// x is the list of strings to store in the table.
// init returns false if the table cannot be constructed.
func (t *table) init(h0 uint32, k uint, x []string) bool {
t.h0 = h0
t.k = k
t.tab = make([]string, 1<<k)
t.mask = 1<<k - 1
for _, s := range x {
if !t.insert(s) {
return false
}
}
return true
}
// insert inserts s in the table.
func (t *table) insert(s string) bool {
h1, h2 := t.hash(s)
if t.tab[h1] == "" {
t.tab[h1] = s
return true
}
if t.tab[h2] == "" {
t.tab[h2] = s
return true
}
if t.push(h1, 0) {
t.tab[h1] = s
return true
}
if t.push(h2, 0) {
t.tab[h2] = s
return true
}
return false
}
// push attempts to push aside the entry in slot i.
func (t *table) push(i uint32, depth int) bool {
if depth > len(t.tab) {
return false
}
s := t.tab[i]
h1, h2 := t.hash(s)
j := h1 + h2 - i
if t.tab[j] != "" && !t.push(j, depth+1) {
return false
}
t.tab[j] = s
return true
}
// The lists of element names and attribute keys were taken from
// https://html.spec.whatwg.org/multipage/indices.html#index
// as of the "HTML Living Standard - Last Updated 16 April 2018" version.
// "command", "keygen" and "menuitem" have been removed from the spec,
// but are kept here for backwards compatibility.
var elements = []string{
"a",
"abbr",
"address",
"area",
"article",
"aside",
"audio",
"b",
"base",
"bdi",
"bdo",
"blockquote",
"body",
"br",
"button",
"canvas",
"caption",
"cite",
"code",
"col",
"colgroup",
"command",
"data",
"datalist",
"dd",
"del",
"details",
"dfn",
"dialog",
"div",
"dl",
"dt",
"em",
"embed",
"fieldset",
"figcaption",
"figure",
"footer",
"form",
"h1",
"h2",
"h3",
"h4",
"h5",
"h6",
"head",
"header",
"hgroup",
"hr",
"html",
"i",
"iframe",
"img",
"input",
"ins",
"kbd",
"keygen",
"label",
"legend",
"li",
"link",
"main",
"map",
"mark",
"menu",
"menuitem",
"meta",
"meter",
"nav",
"noscript",
"object",
"ol",
"optgroup",
"option",
"output",
"p",
"param",
"picture",
"pre",
"progress",
"q",
"rp",
"rt",
"ruby",
"s",
"samp",
"script",
"section",
"select",
"slot",
"small",
"source",
"span",
"strong",
"style",
"sub",
"summary",
"sup",
"table",
"tbody",
"td",
"template",
"textarea",
"tfoot",
"th",
"thead",
"time",
"title",
"tr",
"track",
"u",
"ul",
"var",
"video",
"wbr",
}
// https://html.spec.whatwg.org/multipage/indices.html#attributes-3
//
// "challenge", "command", "contextmenu", "dropzone", "icon", "keytype", "mediagroup",
// "radiogroup", "spellcheck", "scoped", "seamless", "sortable" and "sorted" have been removed from the spec,
// but are kept here for backwards compatibility.
var attributes = []string{
"abbr",
"accept",
"accept-charset",
"accesskey",
"action",
"allowfullscreen",
"allowpaymentrequest",
"allowusermedia",
"alt",
"as",
"async",
"autocomplete",
"autofocus",
"autoplay",
"challenge",
"charset",
"checked",
"cite",
"class",
"color",
"cols",
"colspan",
"command",
"content",
"contenteditable",
"contextmenu",
"controls",
"coords",
"crossorigin",
"data",
"datetime",
"default",
"defer",
"dir",
"dirname",
"disabled",
"download",
"draggable",
"dropzone",
"enctype",
"for",
"form",
"formaction",
"formenctype",
"formmethod",
"formnovalidate",
"formtarget",
"headers",
"height",
"hidden",
"high",
"href",
"hreflang",
"http-equiv",
"icon",
"id",
"inputmode",
"integrity",
"is",
"ismap",
"itemid",
"itemprop",
"itemref",
"itemscope",
"itemtype",
"keytype",
"kind",
"label",
"lang",
"list",
"loop",
"low",
"manifest",
"max",
"maxlength",
"media",
"mediagroup",
"method",
"min",
"minlength",
"multiple",
"muted",
"name",
"nomodule",
"nonce",
"novalidate",
"open",
"optimum",
"pattern",
"ping",
"placeholder",
"playsinline",
"poster",
"preload",
"radiogroup",
"readonly",
"referrerpolicy",
"rel",
"required",
"reversed",
"rows",
"rowspan",
"sandbox",
"spellcheck",
"scope",
"scoped",
"seamless",
"selected",
"shape",
"size",
"sizes",
"sortable",
"sorted",
"slot",
"span",
"spellcheck",
"src",
"srcdoc",
"srclang",
"srcset",
"start",
"step",
"style",
"tabindex",
"target",
"title",
"translate",
"type",
"typemustmatch",
"updateviacache",
"usemap",
"value",
"width",
"workertype",
"wrap",
}
// "onautocomplete", "onautocompleteerror", "onmousewheel",
// "onshow" and "onsort" have been removed from the spec,
// but are kept here for backwards compatibility.
var eventHandlers = []string{
"onabort",
"onautocomplete",
"onautocompleteerror",
"onauxclick",
"onafterprint",
"onbeforeprint",
"onbeforeunload",
"onblur",
"oncancel",
"oncanplay",
"oncanplaythrough",
"onchange",
"onclick",
"onclose",
"oncontextmenu",
"oncopy",
"oncuechange",
"oncut",
"ondblclick",
"ondrag",
"ondragend",
"ondragenter",
"ondragexit",
"ondragleave",
"ondragover",
"ondragstart",
"ondrop",
"ondurationchange",
"onemptied",
"onended",
"onerror",
"onfocus",
"onhashchange",
"oninput",
"oninvalid",
"onkeydown",
"onkeypress",
"onkeyup",
"onlanguagechange",
"onload",
"onloadeddata",
"onloadedmetadata",
"onloadend",
"onloadstart",
"onmessage",
"onmessageerror",
"onmousedown",
"onmouseenter",
"onmouseleave",
"onmousemove",
"onmouseout",
"onmouseover",
"onmouseup",
"onmousewheel",
"onwheel",
"onoffline",
"ononline",
"onpagehide",
"onpageshow",
"onpaste",
"onpause",
"onplay",
"onplaying",
"onpopstate",
"onprogress",
"onratechange",
"onreset",
"onresize",
"onrejectionhandled",
"onscroll",
"onsecuritypolicyviolation",
"onseeked",
"onseeking",
"onselect",
"onshow",
"onsort",
"onstalled",
"onstorage",
"onsubmit",
"onsuspend",
"ontimeupdate",
"ontoggle",
"onunhandledrejection",
"onunload",
"onvolumechange",
"onwaiting",
}
// extra are ad-hoc values not covered by any of the lists above.
var extra = []string{
"acronym",
"align",
"annotation",
"annotation-xml",
"applet",
"basefont",
"bgsound",
"big",
"blink",
"center",
"color",
"desc",
"face",
"font",
"foreignObject", // HTML is case-insensitive, but SVG-embedded-in-HTML is case-sensitive.
"foreignobject",
"frame",
"frameset",
"image",
"isindex",
"listing",
"malignmark",
"marquee",
"math",
"mglyph",
"mi",
"mn",
"mo",
"ms",
"mtext",
"nobr",
"noembed",
"noframes",
"plaintext",
"prompt",
"public",
"rb",
"rtc",
"spacer",
"strike",
"svg",
"system",
"tt",
"xmp",
}

Some files were not shown because too many files have changed in this diff Show More