Add datasync, v1messages & disable discovery topic options

Adds support for datasync, V1Messages and disabling the discovery topic.
This is a backward compatible change as long as they are not toggled on
(they are not by default).
This commit is contained in:
Andrea Maria Piana 2019-07-26 09:17:29 +02:00
parent 21a62c731f
commit 9de77b21b2
53 changed files with 2303 additions and 431 deletions

View File

@ -1 +1 @@
0.31.0-beta.0
0.31.0-beta.1

2
go.mod
View File

@ -19,7 +19,7 @@ require (
github.com/status-im/doubleratchet v2.0.0+incompatible
github.com/status-im/migrate/v4 v4.3.1-status
github.com/status-im/rendezvous v1.3.0
github.com/status-im/status-protocol-go v0.1.1
github.com/status-im/status-protocol-go v0.1.3
github.com/status-im/whisper v1.4.14
github.com/stretchr/testify v1.3.0
github.com/syndtr/goleveldb v1.0.0

13
go.sum
View File

@ -145,6 +145,8 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
@ -216,6 +218,8 @@ github.com/jbenet/goprocess v0.1.3 h1:YKyIEECS/XvcfHtBzxtjBBbWK+MbvA6dG8ASiqwvr1
github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89 h1:12K8AlpT0/6QUXSfV0yi4Q0jkbq8NDtIKFtF61AoqV0=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
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=
github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI=
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
@ -438,8 +442,6 @@ github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
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.3 h1:h+CsF2Z/HyERLo5qTQnrK0RXHuDJ605hG2BbqNOLAAc=
github.com/status-im/go-ethereum v1.8.27-status.3/go.mod h1:Ulij8LMpMvXnbnPcmDqrpI+iXoXSjxItuY/wmbasTZU=
github.com/status-im/go-ethereum v1.8.27-status.5 h1:FS+1KwA97yWh9BtHse0BLfEWtldboSiTMA7nCavxtzc=
github.com/status-im/go-ethereum v1.8.27-status.5/go.mod h1:Ulij8LMpMvXnbnPcmDqrpI+iXoXSjxItuY/wmbasTZU=
github.com/status-im/go-fcm v1.0.0-status h1:eUNKm4ooAXdEf9/GaTYeTELna5aVMOEbzjbm2irQ0gY=
@ -451,14 +453,15 @@ github.com/status-im/migrate/v4 v4.3.1-status/go.mod h1:r8HggRBZ/k7TRwByq/Hp3P/u
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-go v0.29.0-beta.3/go.mod h1:8OHekmRoYTn9oZgMsBdhMEgeyfaQ4eI4ycOFHJCoX7M=
github.com/status-im/status-protocol-go v0.1.1 h1:PGKtMTgfk48LS2ZyNIEdJZJjQGVbkBfccf6EVYCjCpA=
github.com/status-im/status-protocol-go v0.1.1/go.mod h1:rqlsXFR7WENTB4HDJRByRg95UfRo8pjGWvrvVrC2Dm4=
github.com/status-im/status-protocol-go v0.1.3 h1:2ELZ3XR/11CHvElVUDIo9swUQRvrekFC5ZK9W1dB+Eo=
github.com/status-im/status-protocol-go v0.1.3/go.mod h1:K1sZNTGahmrliIsVDTPrruKMZqbbqd8inbfbfh9Wmw4=
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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v0.0.0-20170809224252-890a5c3458b4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v0.0.0-20190716104307-221dbe5ed46703ee255b1da0dec05086f5035f62/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
@ -468,6 +471,8 @@ github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpP
github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/uber/jaeger-client-go v0.0.0-20180607151842-f7e0d4744fa6/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
github.com/uber/jaeger-lib v0.0.0-20180615202729-a51202d6f4a7/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
github.com/vacp2p/mvds v0.0.19 h1:ZXopUNicQPzmIsggqa9Pbd6cqphFiyhthe3kneuJpC8=
github.com/vacp2p/mvds v0.0.19/go.mod h1:MxvN/VFp5zkjhUfJdBft+NrsVDwMsvueDIP2x0h6Tx8=
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc=
github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc h1:9lDbC6Rz4bwmou+oE6Dt4Cb2BGMur5eR/GYptkKUVHo=
github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM=

View File

@ -409,6 +409,15 @@ type ShhextConfig struct {
// WhisperCacheDir is a folder where whisper filters may persist messages before delivering them
// to a client.
WhisperCacheDir string
// DisableGenericDiscoveryTopic indicates whether we should be listening on the old discovery
DisableGenericDiscoveryTopic bool
// SendV1Messages indicates whether we should be sending v1-compatible only messages
SendV1Messages bool
// DatasyncEnabled indicates whether we should enable dataasync
DataSyncEnabled bool
}
// Validate validates the ShhextConfig struct and returns an error if inconsistent values are found

View File

@ -176,17 +176,17 @@ func (s *Service) initProtocol(address, encKey, password string) error {
os.Remove(v4Path)
}
options, err := buildMessengerOptions(s.config, sessionsDatabasePath, transportDatabasePath)
if err != nil {
return err
}
selectedKeyID := s.w.SelectedKeyPairID()
identity, err := s.w.GetPrivateKey(selectedKeyID)
if err != nil {
return err
}
// Create a custom zap.Logger which will forward logs from status-protocol-go to status-go logger.
zapLogger, err := logutils.NewZapLoggerWithAdapter(logutils.Logger())
if err != nil {
return err
}
messenger, err := protocol.NewMessenger(
identity,
&server{server: s.server},
@ -194,12 +194,7 @@ func (s *Service) initProtocol(address, encKey, password string) error {
dataDir,
encKey,
s.config.InstallationID,
protocol.WithDatabaseFilePaths(
sessionsDatabasePath,
transportDatabasePath,
),
protocol.WithGenericDiscoveryTopicSupport(),
protocol.WithCustomLogger(zapLogger),
options...,
)
if err != nil {
return err
@ -226,11 +221,19 @@ func (s *Service) retrieveMessagesLoop(tick time.Duration, cancel <-chan struct{
}
var signalMessages []*signal.Messages
for chat, messages := range chatWithMessages {
var retrievedMessages []*whisper.Message
for _, message := range messages {
whisperMessage := message.TransportMessage
whisperMessage.Payload = message.DecryptedPayload
retrievedMessages = append(retrievedMessages, whisperMessage)
}
signalMessage := &signal.Messages{
Chat: chat,
Error: nil, // TODO: what is it needed for?
Messages: s.deduplicator.Deduplicate(messages),
Messages: s.deduplicator.Deduplicate(retrievedMessages),
}
signalMessages = append(signalMessages, signalMessage)
}
@ -395,6 +398,35 @@ func (s *Service) syncMessages(ctx context.Context, mailServerID []byte, r whisp
}
}
func buildMessengerOptions(config params.ShhextConfig, sessionsDatabasePath string, transportDatabasePath string) ([]protocol.Option, error) {
// Create a custom zap.Logger which will forward logs from status-protocol-go to status-go logger.
zapLogger, err := logutils.NewZapLoggerWithAdapter(logutils.Logger())
if err != nil {
return nil, err
}
options := []protocol.Option{
protocol.WithCustomLogger(zapLogger),
protocol.WithDatabaseFilePaths(
sessionsDatabasePath,
transportDatabasePath,
),
}
if !config.DisableGenericDiscoveryTopic {
options = append(options, protocol.WithGenericDiscoveryTopicSupport())
}
if config.DataSyncEnabled {
options = append(options, protocol.WithDatasync())
}
if config.SendV1Messages {
options = append(options, protocol.WithSendV1Messages())
}
return options, nil
}
func (s *Service) afterPost(hash []byte, newMessage whisper.NewMessage) hexutil.Bytes {
s.envelopesMonitor.Add(common.BytesToHash(hash), newMessage)
mID := messageID(newMessage)

View File

@ -38,7 +38,6 @@ package proto
import (
"fmt"
"log"
"os"
"reflect"
"sort"
"strconv"
@ -194,7 +193,7 @@ func (p *Properties) Parse(s string) {
// "bytes,49,opt,name=foo,def=hello!"
fields := strings.Split(s, ",") // breaks def=, but handled below.
if len(fields) < 2 {
fmt.Fprintf(os.Stderr, "proto: tag has too few fields: %q\n", s)
log.Printf("proto: tag has too few fields: %q", s)
return
}
@ -214,7 +213,7 @@ func (p *Properties) Parse(s string) {
p.WireType = WireBytes
// no numeric converter for non-numeric types
default:
fmt.Fprintf(os.Stderr, "proto: tag has unknown wire type: %q\n", s)
log.Printf("proto: tag has unknown wire type: %q", s)
return
}

3
vendor/github.com/jinzhu/copier/Guardfile generated vendored Normal file
View File

@ -0,0 +1,3 @@
guard 'gotest' do
watch(%r{\.go$})
end

20
vendor/github.com/jinzhu/copier/License generated vendored Normal file
View File

@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2015 Jinzhu
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

100
vendor/github.com/jinzhu/copier/README.md generated vendored Normal file
View File

@ -0,0 +1,100 @@
# Copier
I am a copier, I copy everything from one to another
[![wercker status](https://app.wercker.com/status/9d44ad2d4e6253929c8fb71359effc0b/s/master "wercker status")](https://app.wercker.com/project/byKey/9d44ad2d4e6253929c8fb71359effc0b)
## Features
* Copy from field to field with same name
* Copy from method to field with same name
* Copy from field to method with same name
* Copy from slice to slice
* Copy from struct to slice
## Usage
```go
package main
import (
"fmt"
"github.com/jinzhu/copier"
)
type User struct {
Name string
Role string
Age int32
}
func (user *User) DoubleAge() int32 {
return 2 * user.Age
}
type Employee struct {
Name string
Age int32
DoubleAge int32
EmployeId int64
SuperRule string
}
func (employee *Employee) Role(role string) {
employee.SuperRule = "Super " + role
}
func main() {
var (
user = User{Name: "Jinzhu", Age: 18, Role: "Admin"}
users = []User{{Name: "Jinzhu", Age: 18, Role: "Admin"}, {Name: "jinzhu 2", Age: 30, Role: "Dev"}}
employee = Employee{}
employees = []Employee{}
)
copier.Copy(&employee, &user)
fmt.Printf("%#v \n", employee)
// Employee{
// Name: "Jinzhu", // Copy from field
// Age: 18, // Copy from field
// DoubleAge: 36, // Copy from method
// EmployeeId: 0, // Ignored
// SuperRule: "Super Admin", // Copy to method
// }
// Copy struct to slice
copier.Copy(&employees, &user)
fmt.Printf("%#v \n", employees)
// []Employee{
// {Name: "Jinzhu", Age: 18, DoubleAge: 36, EmployeId: 0, SuperRule: "Super Admin"}
// }
// Copy slice to slice
employees = []Employee{}
copier.Copy(&employees, &users)
fmt.Printf("%#v \n", employees)
// []Employee{
// {Name: "Jinzhu", Age: 18, DoubleAge: 36, EmployeId: 0, SuperRule: "Super Admin"},
// {Name: "jinzhu 2", Age: 30, DoubleAge: 60, EmployeId: 0, SuperRule: "Super Dev"},
// }
}
```
## Contributing
You can help to make the project better, check out [http://gorm.io/contribute.html](http://gorm.io/contribute.html) for things you can do.
# Author
**jinzhu**
* <http://github.com/jinzhu>
* <wosmvp@gmail.com>
* <http://twitter.com/zhangjinzhu>
## License
Released under the [MIT License](https://github.com/jinzhu/copier/blob/master/License).

189
vendor/github.com/jinzhu/copier/copier.go generated vendored Normal file
View File

@ -0,0 +1,189 @@
package copier
import (
"database/sql"
"errors"
"reflect"
)
// Copy copy things
func Copy(toValue interface{}, fromValue interface{}) (err error) {
var (
isSlice bool
amount = 1
from = indirect(reflect.ValueOf(fromValue))
to = indirect(reflect.ValueOf(toValue))
)
if !to.CanAddr() {
return errors.New("copy to value is unaddressable")
}
// Return is from value is invalid
if !from.IsValid() {
return
}
fromType := indirectType(from.Type())
toType := indirectType(to.Type())
// Just set it if possible to assign
// And need to do copy anyway if the type is struct
if fromType.Kind() != reflect.Struct && from.Type().AssignableTo(to.Type()) {
to.Set(from)
return
}
if fromType.Kind() != reflect.Struct || toType.Kind() != reflect.Struct {
return
}
if to.Kind() == reflect.Slice {
isSlice = true
if from.Kind() == reflect.Slice {
amount = from.Len()
}
}
for i := 0; i < amount; i++ {
var dest, source reflect.Value
if isSlice {
// source
if from.Kind() == reflect.Slice {
source = indirect(from.Index(i))
} else {
source = indirect(from)
}
// dest
dest = indirect(reflect.New(toType).Elem())
} else {
source = indirect(from)
dest = indirect(to)
}
// check source
if source.IsValid() {
fromTypeFields := deepFields(fromType)
//fmt.Printf("%#v", fromTypeFields)
// Copy from field to field or method
for _, field := range fromTypeFields {
name := field.Name
if fromField := source.FieldByName(name); fromField.IsValid() {
// has field
if toField := dest.FieldByName(name); toField.IsValid() {
if toField.CanSet() {
if !set(toField, fromField) {
if err := Copy(toField.Addr().Interface(), fromField.Interface()); err != nil {
return err
}
}
}
} else {
// try to set to method
var toMethod reflect.Value
if dest.CanAddr() {
toMethod = dest.Addr().MethodByName(name)
} else {
toMethod = dest.MethodByName(name)
}
if toMethod.IsValid() && toMethod.Type().NumIn() == 1 && fromField.Type().AssignableTo(toMethod.Type().In(0)) {
toMethod.Call([]reflect.Value{fromField})
}
}
}
}
// Copy from method to field
for _, field := range deepFields(toType) {
name := field.Name
var fromMethod reflect.Value
if source.CanAddr() {
fromMethod = source.Addr().MethodByName(name)
} else {
fromMethod = source.MethodByName(name)
}
if fromMethod.IsValid() && fromMethod.Type().NumIn() == 0 && fromMethod.Type().NumOut() == 1 {
if toField := dest.FieldByName(name); toField.IsValid() && toField.CanSet() {
values := fromMethod.Call([]reflect.Value{})
if len(values) >= 1 {
set(toField, values[0])
}
}
}
}
}
if isSlice {
if dest.Addr().Type().AssignableTo(to.Type().Elem()) {
to.Set(reflect.Append(to, dest.Addr()))
} else if dest.Type().AssignableTo(to.Type().Elem()) {
to.Set(reflect.Append(to, dest))
}
}
}
return
}
func deepFields(reflectType reflect.Type) []reflect.StructField {
var fields []reflect.StructField
if reflectType = indirectType(reflectType); reflectType.Kind() == reflect.Struct {
for i := 0; i < reflectType.NumField(); i++ {
v := reflectType.Field(i)
if v.Anonymous {
fields = append(fields, deepFields(v.Type)...)
} else {
fields = append(fields, v)
}
}
}
return fields
}
func indirect(reflectValue reflect.Value) reflect.Value {
for reflectValue.Kind() == reflect.Ptr {
reflectValue = reflectValue.Elem()
}
return reflectValue
}
func indirectType(reflectType reflect.Type) reflect.Type {
for reflectType.Kind() == reflect.Ptr || reflectType.Kind() == reflect.Slice {
reflectType = reflectType.Elem()
}
return reflectType
}
func set(to, from reflect.Value) bool {
if from.IsValid() {
if to.Kind() == reflect.Ptr {
//set `to` to nil if from is nil
if from.Kind() == reflect.Ptr && from.IsNil() {
to.Set(reflect.Zero(to.Type()))
return true
} else if to.IsNil() {
to.Set(reflect.New(to.Type().Elem()))
}
to = to.Elem()
}
if from.Type().ConvertibleTo(to.Type()) {
to.Set(from.Convert(to.Type()))
} else if scanner, ok := to.Addr().Interface().(sql.Scanner); ok {
err := scanner.Scan(from.Interface())
if err != nil {
return false
}
} else if from.Kind() == reflect.Ptr {
return set(to, from.Elem())
} else {
return false
}
}
return true
}

23
vendor/github.com/jinzhu/copier/wercker.yml generated vendored Normal file
View File

@ -0,0 +1,23 @@
box: golang
build:
steps:
- setup-go-workspace
# Gets the dependencies
- script:
name: go get
code: |
go get
# Build the project
- script:
name: go build
code: |
go build ./...
# Test the project
- script:
name: go test
code: |
go test ./...

View File

@ -1,3 +1,8 @@
run:
concurrency: 4
modules-download-mode: vendor
deadline: 5m
skip:
- migrations.go
- .*_mock.go
- vendor/

View File

@ -2,26 +2,22 @@ notifications:
email: false
language: go
go:
- "1.12.x"
- "1.13beta1"
install: true
env:
- GO111MODULE=on
before_script:
- make install-linter
- GO111MODULE=on GOFLAGS=-mod=vendor
matrix:
include:
- go: "1.11.x"
env: GOFLAGS=-mod=vendor
script:
allow_failures:
- go: "1.13beta1"
before_script:
- make install-linter
script:
- make lint
# fails without -a
- go test -a ./... # make test
- go: "1.12.x"
env: GOFLAGS=-mod=vendor
script:
- make lint
# fails without -a
- go test -a ./... # make test
- make test

View File

@ -19,6 +19,9 @@ import (
"github.com/status-im/status-protocol-go/encryption/multidevice"
transport "github.com/status-im/status-protocol-go/transport/whisper"
protocol "github.com/status-im/status-protocol-go/v1"
"github.com/status-im/status-protocol-go/datasync"
datasyncpeer "github.com/status-im/status-protocol-go/datasync/peer"
)
// Whisper message properties.
@ -34,6 +37,7 @@ type whisperAdapter struct {
privateKey *ecdsa.PrivateKey
transport *transport.WhisperServiceTransport
protocol *encryption.Protocol
datasync *datasync.DataSync
logger *zap.Logger
featureFlags featureFlags
@ -43,6 +47,7 @@ func newWhisperAdapter(
pk *ecdsa.PrivateKey,
t *transport.WhisperServiceTransport,
p *encryption.Protocol,
d *datasync.DataSync,
featureFlags featureFlags,
logger *zap.Logger,
) *whisperAdapter {
@ -50,13 +55,22 @@ func newWhisperAdapter(
logger = zap.NewNop()
}
return &whisperAdapter{
adapter := &whisperAdapter{
privateKey: pk,
transport: t,
protocol: p,
datasync: d,
featureFlags: featureFlags,
logger: logger.With(zap.Namespace("whisperAdapter")),
}
if featureFlags.datasync {
// We pass our encryption/transport handling to the datasync
// so it's correctly encrypted.
d.Init(adapter.encryptAndSend)
}
return adapter
}
func (a *whisperAdapter) JoinPublic(chatID string) error {
@ -75,6 +89,34 @@ func (a *whisperAdapter) LeavePrivate(publicKey *ecdsa.PublicKey) error {
return a.transport.LeavePrivate(publicKey)
}
type ChatMessages struct {
Messages []*protocol.Message
Public bool
ChatID string
}
func (a *whisperAdapter) RetrieveAllMessages() ([]ChatMessages, error) {
chatMessages, err := a.transport.RetrieveAllMessages()
if err != nil {
return nil, err
}
var result []ChatMessages
for _, messages := range chatMessages {
protoMessages, err := a.handleRetrievedMessages(messages.Messages)
if err != nil {
return nil, err
}
result = append(result, ChatMessages{
Messages: protoMessages,
Public: messages.Public,
ChatID: messages.ChatID,
})
}
return result, nil
}
// RetrievePublicMessages retrieves the collected public messages.
// It implies joining a chat if it has not been joined yet.
func (a *whisperAdapter) RetrievePublicMessages(chatID string) ([]*protocol.Message, error) {
@ -83,32 +125,7 @@ func (a *whisperAdapter) RetrievePublicMessages(chatID string) ([]*protocol.Mess
return nil, err
}
logger := a.logger.With(zap.String("site", "RetrievePublicMessages"))
decodedMessages := make([]*protocol.Message, 0, len(messages))
for _, item := range messages {
shhMessage := whisper.ToWhisperMessage(item)
hlogger := logger.With(zap.Binary("hash", shhMessage.Hash))
hlogger.Debug("received a public message")
statusMessage, err := a.decodeMessage(shhMessage)
if err != nil {
hlogger.Error("failed to decode message", zap.Error(err))
continue
}
switch m := statusMessage.Message.(type) {
case protocol.Message:
m.ID = statusMessage.ID
m.SigPubKey = statusMessage.SigPubKey
decodedMessages = append(decodedMessages, &m)
default:
hlogger.Error("skipped a public message of unsupported type")
}
}
return decodedMessages, nil
return a.handleRetrievedMessages(messages)
}
// RetrievePrivateMessages retrieves the collected private messages.
@ -119,34 +136,33 @@ func (a *whisperAdapter) RetrievePrivateMessages(publicKey *ecdsa.PublicKey) ([]
return nil, err
}
logger := a.logger.With(zap.String("site", "RetrievePrivateMessages"))
return a.handleRetrievedMessages(messages)
}
func (a *whisperAdapter) handleRetrievedMessages(messages []*whisper.ReceivedMessage) ([]*protocol.Message, error) {
logger := a.logger.With(zap.String("site", "handleRetrievedMessages"))
decodedMessages := make([]*protocol.Message, 0, len(messages))
for _, item := range messages {
shhMessage := whisper.ToWhisperMessage(item)
hlogger := logger.With(zap.Binary("hash", shhMessage.Hash))
hlogger.Debug("handling a received message")
hlogger.Debug("received a private message")
err := a.decryptMessage(context.Background(), shhMessage)
statusMessages, err := a.handleMessages(shhMessage, true)
if err != nil {
hlogger.Error("failed to decrypt a message", zap.Error(err))
}
statusMessage, err := a.decodeMessage(shhMessage)
if err != nil {
hlogger.Error("failed to decode a message", zap.Error(err))
hlogger.Info("failed to decode messages", zap.Error(err))
continue
}
switch m := statusMessage.Message.(type) {
for _, statusMessage := range statusMessages {
switch m := statusMessage.ParsedMessage.(type) {
case protocol.Message:
m.ID = statusMessage.ID
m.SigPubKey = statusMessage.SigPubKey
m.SigPubKey = statusMessage.SigPubKey()
decodedMessages = append(decodedMessages, &m)
case protocol.PairMessage:
fromOurDevice := isPubKeyEqual(statusMessage.SigPubKey, &a.privateKey.PublicKey)
fromOurDevice := isPubKeyEqual(statusMessage.SigPubKey(), &a.privateKey.PublicKey)
if !fromOurDevice {
hlogger.Debug("received PairMessage from not our device, skipping")
break
@ -161,94 +177,90 @@ func (a *whisperAdapter) RetrievePrivateMessages(publicKey *ecdsa.PublicKey) ([]
if err != nil {
return nil, err
}
default:
hlogger.Error("skipped a public message of unsupported type")
}
}
}
return decodedMessages, nil
}
// DEPRECATED
func (a *whisperAdapter) RetrieveRawAll() (map[filter.Chat][]*whisper.Message, error) {
func (a *whisperAdapter) RetrieveRawAll() (map[filter.Chat][]*protocol.StatusMessage, error) {
chatWithMessages, err := a.transport.RetrieveRawAll()
if err != nil {
return nil, err
}
logger := a.logger.With(zap.String("site", "RetrieveRawAll"))
result := make(map[filter.Chat][]*whisper.Message)
result := make(map[filter.Chat][]*protocol.StatusMessage)
for chat, messages := range chatWithMessages {
for _, message := range messages {
shhMessage := whisper.ToWhisperMessage(message)
err := a.decryptMessage(context.Background(), shhMessage)
statusMessages, err := a.handleMessages(shhMessage, false)
if err != nil {
logger.Warn("failed to decrypt a message", zap.Error(err), zap.Binary("messageID", shhMessage.Hash))
logger.Info("failed to decode messages", zap.Error(err))
continue
}
result[chat] = append(result[chat], shhMessage)
result[chat] = append(result[chat], statusMessages...)
}
}
return result, nil
}
// DEPRECATED
func (a *whisperAdapter) RetrieveRaw(filterID string) ([]*whisper.Message, error) {
messages, err := a.transport.RetrieveRaw(filterID)
// handleMessages expects a whisper message as input, and it will go through
// a series of transformations until the message is parsed into an application
// layer message, or in case of Raw methods, the processing stops at the layer
// before
func (a *whisperAdapter) handleMessages(shhMessage *whisper.Message, applicationLayer bool) ([]*protocol.StatusMessage, error) {
logger := a.logger.With(zap.String("site", "handleMessages"))
hlogger := logger.With(zap.Binary("hash", shhMessage.Hash))
var statusMessage protocol.StatusMessage
err := statusMessage.HandleTransport(shhMessage)
if err != nil {
hlogger.Error("failed to handle transport layer message", zap.Error(err))
return nil, err
}
logger := a.logger.With(zap.String("site", "RetrieveRaw"))
var result []*whisper.Message
for _, message := range messages {
shhMessage := whisper.ToWhisperMessage(message)
err := a.decryptMessage(context.Background(), shhMessage)
err = a.handleEncryptionLayer(context.Background(), &statusMessage)
if err != nil {
logger.Warn("failed to decrypt a message", zap.Error(err), zap.Binary("messageID", shhMessage.Hash))
}
result = append(result, shhMessage)
hlogger.Debug("failed to handle an encryption message", zap.Error(err))
}
return result, nil
statusMessages, err := statusMessage.HandleDatasync(a.datasync)
if err != nil {
hlogger.Debug("failed to handle datasync message", zap.Error(err))
}
for _, statusMessage := range statusMessages {
err := statusMessage.HandleApplicationMetadata()
if err != nil {
hlogger.Error("failed to handle application metadata layer message", zap.Error(err))
}
if applicationLayer {
err = statusMessage.HandleApplication()
if err != nil {
hlogger.Error("failed to handle application layer message")
}
}
}
return statusMessages, nil
}
func (a *whisperAdapter) decodeMessage(message *whisper.Message) (*protocol.StatusMessage, error) {
func (a *whisperAdapter) handleEncryptionLayer(ctx context.Context, message *protocol.StatusMessage) error {
publicKey := message.SigPubKey()
publicKey, err := crypto.UnmarshalPubkey(message.Sig)
if err != nil {
return nil, err
}
logger := a.logger.With(zap.String("site", "handleEncryptionLayer"))
decoded, err := protocol.DecodeMessage(publicKey, message.Payload)
if err != nil {
return nil, err
}
return &decoded, nil
}
func (a *whisperAdapter) decryptMessage(ctx context.Context, message *whisper.Message) error {
publicKey, err := crypto.UnmarshalPubkey(message.Sig)
if err != nil {
return errors.Wrap(err, "failed to get signature")
}
var protocolMessage encryption.ProtocolMessage
err = proto.Unmarshal(message.Payload, &protocolMessage)
if err != nil {
return errors.Wrap(err, "failed to unmarshal ProtocolMessage")
}
logger := a.logger.With(zap.String("site", "decryptMessage"))
payload, err := a.protocol.HandleMessage(
a.privateKey,
publicKey,
&protocolMessage,
message.Hash,
)
err := message.HandleEncryption(a.privateKey, publicKey, a.protocol)
if err == encryption.ErrDeviceNotFound {
handleErr := a.handleErrDeviceNotFound(ctx, publicKey)
if handleErr != nil {
@ -259,9 +271,7 @@ func (a *whisperAdapter) decryptMessage(ctx context.Context, message *whisper.Me
return errors.Wrap(err, "failed to process an encrypted message")
}
message.Payload = payload
return nil
}
func (a *whisperAdapter) handleErrDeviceNotFound(ctx context.Context, publicKey *ecdsa.PublicKey) error {
@ -307,11 +317,19 @@ func (a *whisperAdapter) SendPublic(ctx context.Context, chatName, chatID string
return nil, errors.Wrap(err, "failed to encode message")
}
newMessage := whisper.NewMessage{
TTL: whisperTTL,
Payload: encodedMessage,
PowTarget: whisperPoW,
PowTime: whisperPoWTime,
wrappedMessage, err := a.tryWrapMessageV1(encodedMessage)
if err != nil {
return nil, errors.Wrap(err, "failed to wrap message")
}
messageSpec, err := a.protocol.BuildPublicMessage(a.privateKey, wrappedMessage)
if err != nil {
return nil, errors.Wrap(err, "failed to build public message")
}
newMessage, err := a.messageSpecToWhisper(messageSpec)
if err != nil {
return nil, err
}
_, err = a.transport.SendPublic(ctx, newMessage, chatName)
@ -319,18 +337,27 @@ func (a *whisperAdapter) SendPublic(ctx context.Context, chatName, chatID string
return nil, err
}
return protocol.MessageID(&a.privateKey.PublicKey, encodedMessage), nil
return protocol.MessageID(&a.privateKey.PublicKey, wrappedMessage), nil
}
// SendPublicRaw takes encoded data, encrypts it and sends through the wire.
// DEPRECATED
func (a *whisperAdapter) SendPublicRaw(ctx context.Context, chatName string, data []byte) ([]byte, whisper.NewMessage, error) {
newMessage := whisper.NewMessage{
var newMessage whisper.NewMessage
wrappedMessage, err := a.tryWrapMessageV1(data)
if err != nil {
return nil, newMessage, errors.Wrap(err, "failed to wrap message")
}
newMessage = whisper.NewMessage{
TTL: whisperTTL,
Payload: data,
Payload: wrappedMessage,
PowTarget: whisperPoW,
PowTime: whisperPoWTime,
}
hash, err := a.transport.SendPublic(ctx, newMessage, chatName)
return hash, newMessage, err
}
@ -344,20 +371,25 @@ func (a *whisperAdapter) SendContactCode(ctx context.Context, messageSpec *encry
return a.transport.SendPublic(ctx, newMessage, filter.ContactCodeTopic(&a.privateKey.PublicKey))
}
func (a *whisperAdapter) tryWrapMessageV1(encodedMessage []byte) ([]byte, error) {
if a.featureFlags.sendV1Messages {
wrappedMessage, err := protocol.WrapMessageV1(encodedMessage, a.privateKey)
if err != nil {
return nil, errors.Wrap(err, "failed to wrap message")
}
return wrappedMessage, nil
}
return encodedMessage, nil
}
func (a *whisperAdapter) encodeMessage(message protocol.Message) ([]byte, error) {
encodedMessage, err := protocol.EncodeMessage(message)
if err != nil {
return nil, errors.Wrap(err, "failed to encode message")
}
if a.featureFlags.sendV1Messages {
encodedMessage, err = protocol.WrapMessageV1(encodedMessage, a.privateKey)
if err != nil {
return nil, errors.Wrap(err, "failed to wrap message")
}
}
return encodedMessage, nil
}
@ -388,16 +420,43 @@ func (a *whisperAdapter) SendPrivate(
return nil, nil, errors.Wrap(err, "failed to encode message")
}
messageSpec, err := a.protocol.BuildDirectMessage(a.privateKey, publicKey, encodedMessage)
wrappedMessage, err := a.tryWrapMessageV1(encodedMessage)
if err != nil {
return nil, nil, errors.Wrap(err, "failed to encrypt message")
return nil, nil, errors.Wrap(err, "failed to wrap message")
}
_, err = a.sendMessageSpec(ctx, publicKey, messageSpec)
if a.featureFlags.datasync {
if err := a.sendWithDataSync(publicKey, wrappedMessage); err != nil {
return nil, nil, errors.Wrap(err, "failed to send message with datasync")
}
} else {
err = a.encryptAndSend(ctx, publicKey, wrappedMessage)
if err != nil {
return nil, nil, err
}
return protocol.MessageID(&a.privateKey.PublicKey, encodedMessage), &message, nil
}
return protocol.MessageID(&a.privateKey.PublicKey, wrappedMessage), &message, nil
}
func (a *whisperAdapter) sendWithDataSync(publicKey *ecdsa.PublicKey, message []byte) error {
groupID := datasync.ToOneToOneGroupID(&a.privateKey.PublicKey, publicKey)
peerID := datasyncpeer.PublicKeyToPeerID(*publicKey)
exist, err := a.datasync.IsPeerInGroup(groupID, peerID)
if err != nil {
return errors.Wrap(err, "failed to check if peer is in group")
}
if !exist {
if err := a.datasync.AddPeer(groupID, peerID); err != nil {
return errors.Wrap(err, "failed to add peer")
}
}
_, err = a.datasync.AppendMessage(groupID, message)
if err != nil {
return errors.Wrap(err, "failed to append message to datasync")
}
return nil
}
// SendPrivateRaw takes encoded data, encrypts it and sends through the wire.
@ -415,7 +474,12 @@ func (a *whisperAdapter) SendPrivateRaw(
var newMessage whisper.NewMessage
messageSpec, err := a.protocol.BuildDirectMessage(a.privateKey, publicKey, data)
wrappedMessage, err := a.tryWrapMessageV1(data)
if err != nil {
return nil, newMessage, errors.Wrap(err, "failed to wrap message")
}
messageSpec, err := a.protocol.BuildDirectMessage(a.privateKey, publicKey, wrappedMessage)
if err != nil {
return nil, newMessage, errors.Wrap(err, "failed to encrypt message")
}
@ -425,6 +489,13 @@ func (a *whisperAdapter) SendPrivateRaw(
return nil, newMessage, errors.Wrap(err, "failed to convert ProtocolMessageSpec to whisper.NewMessage")
}
if a.featureFlags.datasync {
if err := a.sendWithDataSync(publicKey, wrappedMessage); err != nil {
return nil, newMessage, errors.Wrap(err, "failed to send message with datasync")
}
return nil, newMessage, err
}
hash, err := a.sendMessageSpec(ctx, publicKey, messageSpec)
return hash, newMessage, err
}
@ -452,6 +523,18 @@ func (a *whisperAdapter) sendMessageSpec(ctx context.Context, publicKey *ecdsa.P
}
}
func (a *whisperAdapter) encryptAndSend(ctx context.Context, publicKey *ecdsa.PublicKey, encodedMessage []byte) error {
messageSpec, err := a.protocol.BuildDirectMessage(a.privateKey, publicKey, encodedMessage)
if err != nil {
return errors.Wrap(err, "failed to encrypt message")
}
_, err = a.sendMessageSpec(ctx, publicKey, messageSpec)
if err != nil {
return err
}
return nil
}
func (a *whisperAdapter) messageSpecToWhisper(spec *encryption.ProtocolMessageSpec) (whisper.NewMessage, error) {
var newMessage whisper.NewMessage

View File

@ -0,0 +1,85 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: message.proto
package applicationmetadata
import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type Message struct {
Signature []byte `protobuf:"bytes,4001,opt,name=signature,proto3" json:"signature,omitempty"`
Payload []byte `protobuf:"bytes,4002,opt,name=payload,proto3" json:"payload,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Message) Reset() { *m = Message{} }
func (m *Message) String() string { return proto.CompactTextString(m) }
func (*Message) ProtoMessage() {}
func (*Message) Descriptor() ([]byte, []int) {
return fileDescriptor_33c57e4bae7b9afd, []int{0}
}
func (m *Message) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Message.Unmarshal(m, b)
}
func (m *Message) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Message.Marshal(b, m, deterministic)
}
func (m *Message) XXX_Merge(src proto.Message) {
xxx_messageInfo_Message.Merge(m, src)
}
func (m *Message) XXX_Size() int {
return xxx_messageInfo_Message.Size(m)
}
func (m *Message) XXX_DiscardUnknown() {
xxx_messageInfo_Message.DiscardUnknown(m)
}
var xxx_messageInfo_Message proto.InternalMessageInfo
func (m *Message) GetSignature() []byte {
if m != nil {
return m.Signature
}
return nil
}
func (m *Message) GetPayload() []byte {
if m != nil {
return m.Payload
}
return nil
}
func init() {
proto.RegisterType((*Message)(nil), "applicationmetadata.Message")
}
func init() { proto.RegisterFile("message.proto", fileDescriptor_33c57e4bae7b9afd) }
var fileDescriptor_33c57e4bae7b9afd = []byte{
// 112 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0xcd, 0x4d, 0x2d, 0x2e,
0x4e, 0x4c, 0x4f, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x4e, 0x2c, 0x28, 0xc8, 0xc9,
0x4c, 0x4e, 0x2c, 0xc9, 0xcc, 0xcf, 0xcb, 0x4d, 0x2d, 0x49, 0x4c, 0x49, 0x2c, 0x49, 0x54, 0x72,
0xe6, 0x62, 0xf7, 0x85, 0xa8, 0x12, 0x92, 0xe5, 0xe2, 0x2c, 0xce, 0x4c, 0xcf, 0x4b, 0x2c, 0x29,
0x2d, 0x4a, 0x95, 0x58, 0x28, 0xaf, 0xc0, 0xa8, 0xc1, 0x13, 0x84, 0x10, 0x11, 0x92, 0xe4, 0x62,
0x2f, 0x48, 0xac, 0xcc, 0xc9, 0x4f, 0x4c, 0x91, 0x58, 0x04, 0x91, 0x84, 0xf1, 0x93, 0xd8, 0xc0,
0x16, 0x18, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0xb0, 0x7f, 0x4a, 0x96, 0x71, 0x00, 0x00, 0x00,
}

View File

@ -0,0 +1,8 @@
syntax = "proto3";
package applicationmetadata;
message Message {
bytes signature = 4001;
bytes payload = 4002;
}

View File

@ -0,0 +1,22 @@
package applicationmetadata
import (
"crypto/ecdsa"
"github.com/ethereum/go-ethereum/crypto"
)
func (m *Message) RecoverKey() (*ecdsa.PublicKey, error) {
if m.Signature == nil {
return nil, nil
}
recoveredKey, err := crypto.SigToPub(
crypto.Keccak256(m.Payload),
m.Signature,
)
if err != nil {
return nil, err
}
return recoveredKey, nil
}

View File

@ -0,0 +1,17 @@
package applicationmetadata
import (
"github.com/golang/protobuf/proto"
)
//go:generate protoc --go_out=. ./message.proto
func Unmarshal(payload []byte) (*Message, error) {
var message Message
err := proto.Unmarshal(payload, &message)
if err != nil {
return nil, err
}
return &message, nil
}

View File

@ -0,0 +1,67 @@
package datasync
import (
"crypto/ecdsa"
"github.com/golang/protobuf/proto"
datasyncpeer "github.com/status-im/status-protocol-go/datasync/peer"
datasyncnode "github.com/vacp2p/mvds/node"
datasyncproto "github.com/vacp2p/mvds/protobuf"
datasynctransport "github.com/vacp2p/mvds/transport"
"go.uber.org/zap"
)
type DataSync struct {
*datasyncnode.Node
// DataSyncNodeTransport is the implemntation of the datasync transport interface
*DataSyncNodeTransport
logger *zap.Logger
sendingEnabled bool
}
func New(node *datasyncnode.Node, transport *DataSyncNodeTransport, sendingEnabled bool, logger *zap.Logger) *DataSync {
return &DataSync{Node: node, DataSyncNodeTransport: transport, sendingEnabled: sendingEnabled, logger: logger}
}
func (d *DataSync) Add(publicKey *ecdsa.PublicKey, datasyncMessage datasyncproto.Payload) {
packet := datasynctransport.Packet{
Sender: datasyncpeer.PublicKeyToPeerID(*publicKey),
Payload: datasyncMessage,
}
d.DataSyncNodeTransport.AddPacket(packet)
}
func (d *DataSync) Handle(sender *ecdsa.PublicKey, payload []byte) [][]byte {
var payloads [][]byte
logger := d.logger.With(zap.String("site", "Handle"))
datasyncMessage, err := unwrap(payload)
// If it failed to decode is not a protobuf message, if it successfully decoded but body is empty, is likedly a protobuf wrapped message
if err != nil || !datasyncMessage.IsValid() {
logger.Debug("handling non-datasync message", zap.Error(err), zap.Bool("datasyncMessage.IsValid()", datasyncMessage.IsValid()))
// Not a datasync message, return unchanged
payloads = append(payloads, payload)
} else {
logger.Debug("handling datasync message")
// datasync message
for _, message := range datasyncMessage.Messages {
//copiedMessage := statusMessage.Copy()
//copiedMessage.DataSyncLayerInfo.Payload = message.Body
payloads = append(payloads, message.Body)
}
if d.sendingEnabled {
d.Add(sender, datasyncMessage)
}
}
return payloads
}
func unwrap(payload []byte) (datasyncPayload datasyncproto.Payload, err error) {
err = proto.Unmarshal(payload, &datasyncPayload)
return
}
func (d *DataSync) Stop() {
d.Node.Stop()
}

View File

@ -0,0 +1,19 @@
package peer
import (
"crypto/ecdsa"
"github.com/ethereum/go-ethereum/crypto"
"github.com/vacp2p/mvds/state"
)
func PublicKeyToPeerID(k ecdsa.PublicKey) state.PeerID {
var p state.PeerID
copy(p[:], crypto.FromECDSAPub(&k))
return p
}
func PeerIDToPublicKey(p state.PeerID) (*ecdsa.PublicKey, error) {
return crypto.UnmarshalPubkey(p[:])
}

View File

@ -0,0 +1,61 @@
package datasync
import (
"context"
"crypto/ecdsa"
"errors"
"github.com/golang/protobuf/proto"
datasyncpeer "github.com/status-im/status-protocol-go/datasync/peer"
"github.com/vacp2p/mvds/protobuf"
"github.com/vacp2p/mvds/state"
"github.com/vacp2p/mvds/transport"
)
var errNotInitialized = errors.New("Datasync transport not initialized")
type DataSyncNodeTransport struct {
packets chan transport.Packet
dispatch func(context.Context, *ecdsa.PublicKey, []byte) error
}
func NewDataSyncNodeTransport() *DataSyncNodeTransport {
return &DataSyncNodeTransport{
packets: make(chan transport.Packet),
}
}
func (t *DataSyncNodeTransport) Init(dispatch func(context.Context, *ecdsa.PublicKey, []byte) error) {
t.dispatch = dispatch
}
func (t *DataSyncNodeTransport) AddPacket(p transport.Packet) {
t.packets <- p
}
func (t *DataSyncNodeTransport) Watch() transport.Packet {
return <-t.packets
}
func (t *DataSyncNodeTransport) Send(_ state.PeerID, peer state.PeerID, payload protobuf.Payload) error {
if t.dispatch == nil {
return errNotInitialized
}
data, err := proto.Marshal(&payload)
if err != nil {
return err
}
publicKey, err := datasyncpeer.PeerIDToPublicKey(peer)
if err != nil {
return err
}
return t.dispatch(context.TODO(), publicKey, data)
}
// CalculateSendTime calculates the next epoch
// at which a message should be sent.
func CalculateSendTime(count uint64, time int64) int64 {
return time + int64(count*2) // @todo this should match that time is increased by whisper periods, aka we only retransmit the first time when a message has expired.
}

View File

@ -0,0 +1,28 @@
package datasync
import (
"crypto/ecdsa"
"github.com/ethereum/go-ethereum/crypto"
"github.com/vacp2p/mvds/state"
)
func ToGroupID(data []byte) state.GroupID {
g := state.GroupID{}
copy(g[:], data[:])
return g
}
// ToOneToOneGroupID returns a groupID for a onetoonechat, which is taken by
// concatenating the bytes of the compressed keys, in ascending order by X
func ToOneToOneGroupID(key1 *ecdsa.PublicKey, key2 *ecdsa.PublicKey) state.GroupID {
pk1 := crypto.CompressPubkey(key1)
pk2 := crypto.CompressPubkey(key2)
var groupID []byte
if key1.X.Cmp(key2.X) == -1 {
groupID = append(pk1, pk2...)
} else {
groupID = append(pk2, pk1...)
}
return ToGroupID(crypto.Keccak256(groupID))
}

View File

@ -13,8 +13,6 @@
// 1558588866_add_version.up.sql (57B)
// 1559627659_add_contact_code.down.sql (32B)
// 1559627659_add_contact_code.up.sql (198B)
// 1561059285_add_whisper_keys.down.sql (25B)
// 1561059285_add_whisper_keys.up.sql (112B)
// 1561368210_add_installation_metadata.down.sql (35B)
// 1561368210_add_installation_metadata.up.sql (267B)
// doc.go (377B)
@ -101,7 +99,7 @@ func _1536754952_initial_schemaDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1536754952_initial_schema.down.sql", size: 83, mode: os.FileMode(0644), modTime: time.Unix(1562427968, 0)}
info := bindataFileInfo{name: "1536754952_initial_schema.down.sql", size: 83, mode: os.FileMode(0644), modTime: time.Unix(1564410717, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x44, 0xcf, 0x76, 0x71, 0x1f, 0x5e, 0x9a, 0x43, 0xd8, 0xcd, 0xb8, 0xc3, 0x70, 0xc3, 0x7f, 0xfc, 0x90, 0xb4, 0x25, 0x1e, 0xf4, 0x66, 0x20, 0xb8, 0x33, 0x7e, 0xb0, 0x76, 0x1f, 0xc, 0xc0, 0x75}}
return a, nil
}
@ -121,7 +119,7 @@ func _1536754952_initial_schemaUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1536754952_initial_schema.up.sql", size: 962, mode: os.FileMode(0644), modTime: time.Unix(1562427968, 0)}
info := bindataFileInfo{name: "1536754952_initial_schema.up.sql", size: 962, mode: os.FileMode(0644), modTime: time.Unix(1564410717, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xea, 0x90, 0x5a, 0x59, 0x3e, 0x3, 0xe2, 0x3c, 0x81, 0x42, 0xcd, 0x4c, 0x9a, 0xe8, 0xda, 0x93, 0x2b, 0x70, 0xa4, 0xd5, 0x29, 0x3e, 0xd5, 0xc9, 0x27, 0xb6, 0xb7, 0x65, 0xff, 0x0, 0xcb, 0xde}}
return a, nil
}
@ -141,7 +139,7 @@ func _1539249977_update_ratchet_infoDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1539249977_update_ratchet_info.down.sql", size: 311, mode: os.FileMode(0644), modTime: time.Unix(1562427968, 0)}
info := bindataFileInfo{name: "1539249977_update_ratchet_info.down.sql", size: 311, mode: os.FileMode(0644), modTime: time.Unix(1564410717, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x1, 0xa4, 0xeb, 0xa0, 0xe6, 0xa0, 0xd4, 0x48, 0xbb, 0xad, 0x6f, 0x7d, 0x67, 0x8c, 0xbd, 0x25, 0xde, 0x1f, 0x73, 0x9a, 0xbb, 0xa8, 0xc9, 0x30, 0xb7, 0xa9, 0x7c, 0xaf, 0xb5, 0x1, 0x61, 0xdd}}
return a, nil
}
@ -161,7 +159,7 @@ func _1539249977_update_ratchet_infoUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1539249977_update_ratchet_info.up.sql", size: 368, mode: os.FileMode(0644), modTime: time.Unix(1562427968, 0)}
info := bindataFileInfo{name: "1539249977_update_ratchet_info.up.sql", size: 368, mode: os.FileMode(0644), modTime: time.Unix(1564410717, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc, 0x8e, 0xbf, 0x6f, 0xa, 0xc0, 0xe1, 0x3c, 0x42, 0x28, 0x88, 0x1d, 0xdb, 0xba, 0x1c, 0x83, 0xec, 0xba, 0xd3, 0x5f, 0x5c, 0x77, 0x5e, 0xa7, 0x46, 0x36, 0xec, 0x69, 0xa, 0x4b, 0x17, 0x79}}
return a, nil
}
@ -181,7 +179,7 @@ func _1540715431_add_versionDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1540715431_add_version.down.sql", size: 127, mode: os.FileMode(0644), modTime: time.Unix(1562427968, 0)}
info := bindataFileInfo{name: "1540715431_add_version.down.sql", size: 127, mode: os.FileMode(0644), modTime: time.Unix(1564410717, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf5, 0x9, 0x4, 0xe3, 0x76, 0x2e, 0xb8, 0x9, 0x23, 0xf0, 0x70, 0x93, 0xc4, 0x50, 0xe, 0x9d, 0x84, 0x22, 0x8c, 0x94, 0xd3, 0x24, 0x9, 0x9a, 0xc1, 0xa1, 0x48, 0x45, 0xfd, 0x40, 0x6e, 0xe6}}
return a, nil
}
@ -201,7 +199,7 @@ func _1540715431_add_versionUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1540715431_add_version.up.sql", size: 265, mode: os.FileMode(0644), modTime: time.Unix(1562427968, 0)}
info := bindataFileInfo{name: "1540715431_add_version.up.sql", size: 265, mode: os.FileMode(0644), modTime: time.Unix(1564410717, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc7, 0x4c, 0x36, 0x96, 0xdf, 0x16, 0x10, 0xa6, 0x27, 0x1a, 0x79, 0x8b, 0x42, 0x83, 0x23, 0xc, 0x7e, 0xb6, 0x3d, 0x2, 0xda, 0xa4, 0xb4, 0xd, 0x27, 0x55, 0xba, 0xdc, 0xb2, 0x88, 0x8f, 0xa6}}
return a, nil
}
@ -221,7 +219,7 @@ func _1541164797_add_installationsDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1541164797_add_installations.down.sql", size: 26, mode: os.FileMode(0644), modTime: time.Unix(1562427968, 0)}
info := bindataFileInfo{name: "1541164797_add_installations.down.sql", size: 26, mode: os.FileMode(0644), modTime: time.Unix(1564410717, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf5, 0xfd, 0xe6, 0xd8, 0xca, 0x3b, 0x38, 0x18, 0xee, 0x0, 0x5f, 0x36, 0x9e, 0x1e, 0xd, 0x19, 0x3e, 0xb4, 0x73, 0x53, 0xe9, 0xa5, 0xac, 0xdd, 0xa1, 0x2f, 0xc7, 0x6c, 0xa8, 0xd9, 0xa, 0x88}}
return a, nil
}
@ -241,7 +239,7 @@ func _1541164797_add_installationsUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1541164797_add_installations.up.sql", size: 216, mode: os.FileMode(0644), modTime: time.Unix(1562427968, 0)}
info := bindataFileInfo{name: "1541164797_add_installations.up.sql", size: 216, mode: os.FileMode(0644), modTime: time.Unix(1564410717, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x2d, 0x18, 0x26, 0xb8, 0x88, 0x47, 0xdb, 0x83, 0xcc, 0xb6, 0x9d, 0x1c, 0x1, 0xae, 0x2f, 0xde, 0x97, 0x82, 0x3, 0x30, 0xa8, 0x63, 0xa1, 0x78, 0x4b, 0xa5, 0x9, 0x8, 0x75, 0xa2, 0x57, 0x81}}
return a, nil
}
@ -261,7 +259,7 @@ func _1558084410_add_secretDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1558084410_add_secret.down.sql", size: 56, mode: os.FileMode(0644), modTime: time.Unix(1562427968, 0)}
info := bindataFileInfo{name: "1558084410_add_secret.down.sql", size: 56, mode: os.FileMode(0644), modTime: time.Unix(1564410717, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x49, 0xb, 0x65, 0xdf, 0x59, 0xbf, 0xe9, 0x5, 0x5b, 0x6f, 0xd5, 0x3a, 0xb7, 0x57, 0xe8, 0x78, 0x38, 0x73, 0x53, 0x57, 0xf7, 0x24, 0x4, 0xe4, 0xa2, 0x49, 0x22, 0xa2, 0xc6, 0xfd, 0x80, 0xa4}}
return a, nil
}
@ -281,7 +279,7 @@ func _1558084410_add_secretUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1558084410_add_secret.up.sql", size: 301, mode: os.FileMode(0644), modTime: time.Unix(1562427968, 0)}
info := bindataFileInfo{name: "1558084410_add_secret.up.sql", size: 301, mode: os.FileMode(0644), modTime: time.Unix(1564410717, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf5, 0x32, 0x36, 0x8e, 0x47, 0xb0, 0x8f, 0xc1, 0xc6, 0xf7, 0xc6, 0x9f, 0x2d, 0x44, 0x75, 0x2b, 0x26, 0xec, 0x6, 0xa0, 0x7b, 0xa5, 0xbd, 0xc8, 0x76, 0x8a, 0x82, 0x68, 0x2, 0x42, 0xb5, 0xf4}}
return a, nil
}
@ -301,7 +299,7 @@ func _1558588866_add_versionUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1558588866_add_version.up.sql", size: 57, mode: os.FileMode(0644), modTime: time.Unix(1562427968, 0)}
info := bindataFileInfo{name: "1558588866_add_version.up.sql", size: 57, mode: os.FileMode(0644), modTime: time.Unix(1564410717, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x2a, 0xea, 0x64, 0x39, 0x61, 0x20, 0x83, 0x83, 0xb, 0x2e, 0x79, 0x64, 0xb, 0x53, 0xfa, 0xfe, 0xc6, 0xf7, 0x67, 0x42, 0xd3, 0x4f, 0xdc, 0x7e, 0x30, 0x32, 0xe8, 0x14, 0x41, 0xe9, 0xe7, 0x3b}}
return a, nil
}
@ -321,7 +319,7 @@ func _1559627659_add_contact_codeDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1559627659_add_contact_code.down.sql", size: 32, mode: os.FileMode(0644), modTime: time.Unix(1562427968, 0)}
info := bindataFileInfo{name: "1559627659_add_contact_code.down.sql", size: 32, mode: os.FileMode(0644), modTime: time.Unix(1564410717, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x5d, 0x64, 0x6d, 0xce, 0x24, 0x42, 0x20, 0x8d, 0x4f, 0x37, 0xaa, 0x9d, 0xc, 0x57, 0x98, 0xc1, 0xd1, 0x1a, 0x34, 0xcd, 0x9f, 0x8f, 0x34, 0x86, 0xb3, 0xd3, 0xdc, 0xf1, 0x7d, 0xe5, 0x1b, 0x6e}}
return a, nil
}
@ -341,51 +339,11 @@ func _1559627659_add_contact_codeUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1559627659_add_contact_code.up.sql", size: 198, mode: os.FileMode(0644), modTime: time.Unix(1562427968, 0)}
info := bindataFileInfo{name: "1559627659_add_contact_code.up.sql", size: 198, mode: os.FileMode(0644), modTime: time.Unix(1564410717, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x16, 0xf6, 0xc2, 0x62, 0x9c, 0xd2, 0xc9, 0x1e, 0xd8, 0xea, 0xaa, 0xea, 0x95, 0x8f, 0x89, 0x6a, 0x85, 0x5d, 0x9d, 0x99, 0x78, 0x3c, 0x90, 0x66, 0x99, 0x3e, 0x4b, 0x19, 0x62, 0xfb, 0x31, 0x4d}}
return a, nil
}
var __1561059285_add_whisper_keysDownSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x72\x09\xf2\x0f\x50\x08\x71\x74\xf2\x71\x55\x28\xcf\xc8\x2c\x2e\x48\x2d\x8a\xcf\x4e\xad\x2c\xb6\xe6\x02\x04\x00\x00\xff\xff\x42\x93\x8e\x79\x19\x00\x00\x00")
func _1561059285_add_whisper_keysDownSqlBytes() ([]byte, error) {
return bindataRead(
__1561059285_add_whisper_keysDownSql,
"1561059285_add_whisper_keys.down.sql",
)
}
func _1561059285_add_whisper_keysDownSql() (*asset, error) {
bytes, err := _1561059285_add_whisper_keysDownSqlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "1561059285_add_whisper_keys.down.sql", size: 25, mode: os.FileMode(0644), modTime: time.Unix(1562427968, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb9, 0x31, 0x3f, 0xce, 0xfa, 0x44, 0x36, 0x1b, 0xb0, 0xec, 0x5d, 0xb, 0x90, 0xb, 0x21, 0x4f, 0xd5, 0xe5, 0x50, 0xed, 0xc7, 0x43, 0xdf, 0x83, 0xb4, 0x3a, 0xc1, 0x55, 0x2e, 0x53, 0x7c, 0x67}}
return a, nil
}
var __1561059285_add_whisper_keysUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x04\xc0\xb1\x0a\xc2\x40\x0c\x06\xe0\xfd\x9e\xe2\x1f\x15\x7c\x03\xa7\xde\x19\x35\x18\x13\x09\x29\xb5\x53\x11\x3d\x68\xe9\x22\x56\x90\xbe\xbd\x5f\x71\x6a\x82\x10\x4d\x16\xc2\x6f\x9c\x96\x77\xfd\x0c\x73\x5d\x17\x6c\x12\xf0\x1c\x1f\xdf\x61\x7a\x21\xe8\x1e\xb8\x39\x5f\x1b\xef\x71\xa1\x1e\xa6\x28\xa6\x47\xe1\x12\xe0\x93\x9a\xd3\x2e\x01\x73\x5d\x91\xc5\x32\xd4\x02\xda\x8a\xa4\x2d\x3a\x8e\xb3\xb5\x01\xb7\x8e\x0f\xfb\xf4\x0f\x00\x00\xff\xff\x6e\x23\x28\x7d\x70\x00\x00\x00")
func _1561059285_add_whisper_keysUpSqlBytes() ([]byte, error) {
return bindataRead(
__1561059285_add_whisper_keysUpSql,
"1561059285_add_whisper_keys.up.sql",
)
}
func _1561059285_add_whisper_keysUpSql() (*asset, error) {
bytes, err := _1561059285_add_whisper_keysUpSqlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "1561059285_add_whisper_keys.up.sql", size: 112, mode: os.FileMode(0644), modTime: time.Unix(1562427968, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x25, 0x41, 0xc, 0x92, 0xdd, 0x9e, 0xff, 0x5d, 0xd0, 0x93, 0xe4, 0x24, 0x50, 0x29, 0xcf, 0xc6, 0xf7, 0x49, 0x3c, 0x73, 0xd9, 0x8c, 0xfa, 0xf2, 0xcf, 0xf6, 0x6f, 0xbc, 0x31, 0xe6, 0xf7, 0xe2}}
return a, nil
}
var __1561368210_add_installation_metadataDownSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x72\x09\xf2\x0f\x50\x08\x71\x74\xf2\x71\x55\xc8\xcc\x2b\x2e\x49\xcc\xc9\x49\x2c\xc9\xcc\xcf\x2b\x8e\xcf\x4d\x2d\x49\x4c\x49\x2c\x49\xb4\xe6\x02\x04\x00\x00\xff\xff\x03\x72\x7f\x08\x23\x00\x00\x00")
func _1561368210_add_installation_metadataDownSqlBytes() ([]byte, error) {
@ -401,7 +359,7 @@ func _1561368210_add_installation_metadataDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1561368210_add_installation_metadata.down.sql", size: 35, mode: os.FileMode(0644), modTime: time.Unix(1562427968, 0)}
info := bindataFileInfo{name: "1561368210_add_installation_metadata.down.sql", size: 35, mode: os.FileMode(0644), modTime: time.Unix(1564410717, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa8, 0xde, 0x3f, 0xd2, 0x4a, 0x50, 0x98, 0x56, 0xe3, 0xc0, 0xcd, 0x9d, 0xb0, 0x34, 0x3b, 0xe5, 0x62, 0x18, 0xb5, 0x20, 0xc9, 0x3e, 0xdc, 0x6a, 0x40, 0x36, 0x66, 0xea, 0x51, 0x8c, 0x71, 0xf5}}
return a, nil
}
@ -421,7 +379,7 @@ func _1561368210_add_installation_metadataUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1561368210_add_installation_metadata.up.sql", size: 267, mode: os.FileMode(0644), modTime: time.Unix(1562427968, 0)}
info := bindataFileInfo{name: "1561368210_add_installation_metadata.up.sql", size: 267, mode: os.FileMode(0644), modTime: time.Unix(1564410717, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb4, 0x71, 0x8f, 0x29, 0xb1, 0xaa, 0xd6, 0xd1, 0x8c, 0x17, 0xef, 0x6c, 0xd5, 0x80, 0xb8, 0x2c, 0xc3, 0xfe, 0xec, 0x24, 0x4d, 0xc8, 0x25, 0xd3, 0xb4, 0xcd, 0xa9, 0xac, 0x63, 0x61, 0xb2, 0x9c}}
return a, nil
}
@ -441,7 +399,7 @@ func docGo() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "doc.go", size: 377, mode: os.FileMode(0644), modTime: time.Unix(1562955235, 0)}
info := bindataFileInfo{name: "doc.go", size: 377, mode: os.FileMode(0644), modTime: time.Unix(1564410717, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x94, 0xd1, 0x5c, 0x73, 0x47, 0x65, 0xf9, 0x6e, 0xa0, 0xee, 0xb, 0x3d, 0xbe, 0xff, 0xef, 0xae, 0xc9, 0x46, 0x21, 0x85, 0x12, 0x46, 0xa1, 0x73, 0x74, 0xca, 0x71, 0xb1, 0xe1, 0x69, 0xe1, 0x82}}
return a, nil
}
@ -563,10 +521,6 @@ var _bindata = map[string]func() (*asset, error){
"1559627659_add_contact_code.up.sql": _1559627659_add_contact_codeUpSql,
"1561059285_add_whisper_keys.down.sql": _1561059285_add_whisper_keysDownSql,
"1561059285_add_whisper_keys.up.sql": _1561059285_add_whisper_keysUpSql,
"1561368210_add_installation_metadata.down.sql": _1561368210_add_installation_metadataDownSql,
"1561368210_add_installation_metadata.up.sql": _1561368210_add_installation_metadataUpSql,
@ -628,8 +582,6 @@ var _bintree = &bintree{nil, map[string]*bintree{
"1558588866_add_version.up.sql": &bintree{_1558588866_add_versionUpSql, map[string]*bintree{}},
"1559627659_add_contact_code.down.sql": &bintree{_1559627659_add_contact_codeDownSql, map[string]*bintree{}},
"1559627659_add_contact_code.up.sql": &bintree{_1559627659_add_contact_codeUpSql, map[string]*bintree{}},
"1561059285_add_whisper_keys.down.sql": &bintree{_1561059285_add_whisper_keysDownSql, map[string]*bintree{}},
"1561059285_add_whisper_keys.up.sql": &bintree{_1561059285_add_whisper_keysUpSql, map[string]*bintree{}},
"1561368210_add_installation_metadata.down.sql": &bintree{_1561368210_add_installation_metadataDownSql, map[string]*bintree{}},
"1561368210_add_installation_metadata.up.sql": &bintree{_1561368210_add_installation_metadataUpSql, map[string]*bintree{}},
"doc.go": &bintree{docGo, map[string]*bintree{}},

View File

@ -6,7 +6,8 @@ require (
github.com/aristanetworks/goarista v0.0.0-20190704150520-f44d68189fd7 // indirect
github.com/deckarep/golang-set v1.7.1 // indirect
github.com/ethereum/go-ethereum v1.8.27
github.com/golang/protobuf v1.3.1
github.com/golang/protobuf v1.3.2
github.com/jinzhu/copier v0.0.0-20190625015134-976e0346caa8
github.com/leodido/go-urn v1.1.0 // indirect
github.com/mutecomm/go-sqlcipher v0.0.0-20170920224653-f799951b4ab2
github.com/pkg/errors v0.8.1
@ -17,6 +18,7 @@ require (
github.com/status-im/status-go v0.29.0-beta.3
github.com/status-im/whisper v1.4.14
github.com/stretchr/testify v1.3.0
github.com/vacp2p/mvds v0.0.19
go.uber.org/atomic v1.4.0 // indirect
go.uber.org/multierr v1.1.0 // indirect
go.uber.org/zap v1.10.0

View File

@ -127,6 +127,8 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
@ -184,6 +186,8 @@ github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2/go.mod
github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY=
github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
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=
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
@ -364,6 +368,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v0.0.0-20170809224252-890a5c3458b4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v0.0.0-20190716104307-221dbe5ed46703ee255b1da0dec05086f5035f62/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
@ -373,6 +378,8 @@ github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpP
github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/uber/jaeger-client-go v0.0.0-20180607151842-f7e0d4744fa6/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
github.com/uber/jaeger-lib v0.0.0-20180615202729-a51202d6f4a7/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
github.com/vacp2p/mvds v0.0.19 h1:ZXopUNicQPzmIsggqa9Pbd6cqphFiyhthe3kneuJpC8=
github.com/vacp2p/mvds v0.0.19/go.mod h1:MxvN/VFp5zkjhUfJdBft+NrsVDwMsvueDIP2x0h6Tx8=
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc=
github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM=
github.com/whyrusleeping/go-notifier v0.0.0-20170827234753-097c5d47330f/go.mod h1:cZNvX9cFybI01GriPRMXDtczuvUhgbcYr9iCGaNlRv8=

View File

@ -1,9 +1,7 @@
// Code generated by go-bindata. DO NOT EDIT.
// sources:
// 000001_add_messages_contacts.down.db.sql (91B)
// 000001_add_messages_contacts.up.db.sql (685B)
// 000002_add_unread_to_user_messages.down.sql (210B)
// 000002_add_unread_to_user_messages.up.sql (113B)
// 000001_init.down.db.sql (82B)
// 000001_init.up.db.sql (840B)
// doc.go (377B)
package sqlite
@ -73,83 +71,43 @@ func (fi bindataFileInfo) Sys() interface{} {
return nil
}
var __000001_add_messages_contactsDownDbSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x72\x09\xf2\x0f\x50\x08\x71\x74\xf2\x71\x55\x28\x2d\x4e\x2d\x8a\xcf\x4d\x2d\x2e\x4e\x4c\x4f\x2d\xb6\xe6\x42\x97\x49\xce\xcf\x2b\x49\x4c\x2e\x41\x95\xc9\xc8\x2c\x2e\xc9\x2f\xaa\x8c\x47\x56\x11\x5f\x92\x5f\x90\x99\x6c\xcd\x05\x08\x00\x00\xff\xff\x1b\x57\x14\x62\x5b\x00\x00\x00")
var __000001_initDownDbSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x72\x09\xf2\x0f\x50\x08\x71\x74\xf2\x71\x55\x28\x2d\x4e\x2d\x8a\xcf\x4d\x2d\x2e\x4e\x4c\x4f\x2d\xb6\xe6\x42\x92\xc9\x4d\xcd\x4d\x4a\x2d\x2a\xce\xc8\x2c\x88\x2f\x2d\x48\x49\x2c\x41\x93\x4e\xce\x48\x2c\x89\x87\xaa\xb1\xe6\x02\x04\x00\x00\xff\xff\x69\x98\x5e\xa1\x52\x00\x00\x00")
func _000001_add_messages_contactsDownDbSqlBytes() ([]byte, error) {
func _000001_initDownDbSqlBytes() ([]byte, error) {
return bindataRead(
__000001_add_messages_contactsDownDbSql,
"000001_add_messages_contacts.down.db.sql",
__000001_initDownDbSql,
"000001_init.down.db.sql",
)
}
func _000001_add_messages_contactsDownDbSql() (*asset, error) {
bytes, err := _000001_add_messages_contactsDownDbSqlBytes()
func _000001_initDownDbSql() (*asset, error) {
bytes, err := _000001_initDownDbSqlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "000001_add_messages_contacts.down.db.sql", size: 91, mode: os.FileMode(0644), modTime: time.Unix(1562955202, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xee, 0x89, 0x87, 0xa3, 0x2, 0x4f, 0xb4, 0x8c, 0x2c, 0x15, 0x41, 0x85, 0x3c, 0xbe, 0x71, 0x55, 0xa1, 0x6a, 0xa1, 0x5e, 0x8e, 0xd8, 0xcf, 0x84, 0xed, 0xb0, 0x60, 0x3, 0xcb, 0xb5, 0x33, 0x7c}}
info := bindataFileInfo{name: "000001_init.down.db.sql", size: 82, mode: os.FileMode(0644), modTime: time.Unix(1564410717, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe8, 0x5f, 0xe0, 0x6, 0xfc, 0xed, 0xb7, 0xff, 0xb5, 0xf3, 0x33, 0x45, 0x1, 0x5b, 0x84, 0x80, 0x74, 0x60, 0x81, 0xa6, 0x8b, 0xb4, 0xd4, 0xad, 0x10, 0xa8, 0xb3, 0x61, 0x6f, 0xc5, 0x2f, 0xaa}}
return a, nil
}
var __000001_add_messages_contactsUpDbSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x7c\x92\xcf\x6e\xb3\x30\x10\xc4\xef\x7e\x8a\x3d\xf2\x49\x1c\xbe\x7b\x4f\x06\x96\xc4\x2a\xb5\x5b\xc7\x34\xc9\x09\x51\xc7\x6a\x50\xc2\x1f\xc5\x8e\x54\xde\xbe\x82\x42\xe3\xa6\x69\xae\x33\xf6\x7a\xe6\xb7\x8e\x25\x52\x85\xa0\x68\x94\x21\xb0\x14\xb8\x50\x80\x1b\xb6\x52\x2b\x38\x5b\x73\x2a\x6a\x63\x6d\xf9\x6e\x2c\x04\xa4\xda\x41\x94\x89\x08\x72\xce\x5e\x72\x1c\x4f\xf2\x3c\xcb\x42\xa2\xdb\xc6\x95\xda\x15\xd5\x0e\x5e\xa9\x8c\x97\x54\x5e\x99\xa6\x71\x85\xeb\x3b\x33\xdb\x21\x99\xc6\x5e\xa9\xce\x7c\x38\x50\xb8\x51\x21\xd1\xc7\x56\x1f\x20\x62\x0b\xc6\x55\x48\x5c\x55\x1b\xeb\xca\xba\xfb\x56\xe6\xb1\x7a\x5f\x8e\x0f\x4f\xb7\xe6\xc7\x2e\x83\xba\xf3\xdb\xb1\xd2\xc5\xc1\xf4\x63\x7a\xf2\xef\x81\x90\xa9\x34\xe3\x09\x6e\xe0\x92\xde\x82\xe0\x3f\x5b\x07\x17\xd3\xbb\xf7\x27\xac\xe9\xf4\x04\x6b\x66\xf1\x2c\xd9\x13\x95\x5b\x78\xc4\xad\xc7\xa5\x29\x6b\x73\x03\x97\x6b\xbb\x4a\x8f\xd1\x7d\x71\xa0\xc4\xb8\x2f\x59\x57\xba\x51\xbb\xd1\x10\xd6\x4c\x2d\x45\xae\x40\x8a\x35\x4b\xee\xe7\xde\x57\xd6\xb5\xa7\xbe\xf0\xf3\x17\x5f\x21\x02\x62\xfb\x46\x9b\xdd\xc4\x1c\x12\x4c\x69\x9e\x29\xf8\x7f\x7f\xf5\xbf\xbe\x47\x2a\x24\xb2\x05\x1f\xfa\xfb\x3c\x41\x62\x8a\x12\x79\x8c\x57\xf4\x82\xc1\x14\x1c\x12\xcc\x50\x21\xc4\x74\x15\xd3\x04\x87\xc5\x7d\x06\x00\x00\xff\xff\x28\x6d\x42\x61\xad\x02\x00\x00")
var __000001_initUpDbSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x52\xb1\x6e\xc2\x30\x14\xdc\xf3\x15\x6f\x24\x12\x43\xf7\x4e\x0e\xbc\x80\xd5\xd4\x6e\x1d\xa7\xc0\x14\x19\xe2\x82\x0b\x09\x11\x36\x52\xf9\xfb\xaa\x49\x8c\x02\x45\x15\xac\xef\xce\xe7\xbb\x7b\x6f\x24\x90\x48\x04\x49\xa2\x04\x81\xc6\xc0\xb8\x04\x9c\xd3\x54\xa6\x70\xb4\xfa\x90\x97\xda\x5a\xb5\xd6\x16\x06\x01\x00\x80\x29\x20\x4a\x78\x04\x19\xa3\xef\x19\x36\x6c\x96\x25\xc9\xb0\x01\x57\x1b\xe5\x72\x53\xc0\x07\x11\xa3\x29\x11\xd7\xe8\xbe\x72\xba\x72\xb9\x3b\xd5\xda\x53\x5a\xa4\xfb\xe3\x06\xe2\xf4\xb7\x03\x89\x73\xd9\x49\xec\xf6\xab\x2d\x44\x74\x42\x59\x37\x71\xa6\xd4\xd6\xa9\xb2\xbe\x98\xfa\xaf\xbc\xa1\x9e\x82\x37\x71\x29\x5c\x1f\x97\x3b\xb3\xca\xb7\xfa\xd4\xc4\x6b\x87\x9f\x3b\xb5\xb6\x40\x99\x3c\x07\x81\x31\xc6\x24\x4b\x24\x3c\x05\xe1\x73\x10\x74\xdd\x51\x36\xc6\xb9\x0f\x6f\x81\xb3\xcb\xe6\x06\x1d\xd2\x7b\x71\xab\xed\x52\x97\x4b\x7d\xb0\x1b\x53\xe7\xc7\xba\x50\xae\x5f\xb9\x2f\xf4\x4d\xd0\x57\x22\x16\xf0\x82\x8b\xab\x72\x0b\xe5\x54\xbb\x99\x47\x56\x12\x73\x81\x74\xc2\x1a\xbd\xb3\x4d\x10\x18\xa3\x40\x36\xc2\xb4\x79\x6e\x07\xa6\x08\x83\x10\x66\x54\x4e\x79\x26\x41\xf0\x19\x1d\xff\x9f\xa5\x91\xea\x02\x75\x29\xae\x1a\x7e\xc8\xa6\x2a\x4a\x53\x41\xc4\x79\x82\x84\xfd\x5d\x46\x4c\x92\x14\x5b\xe6\xd7\xde\x54\xba\xb8\x8b\x7a\x7f\xf6\x96\xdf\x5e\xbc\x67\x0e\x7b\x81\xc2\xdf\x63\xf8\x09\x00\x00\xff\xff\x66\xab\x2d\x2f\x48\x03\x00\x00")
func _000001_add_messages_contactsUpDbSqlBytes() ([]byte, error) {
func _000001_initUpDbSqlBytes() ([]byte, error) {
return bindataRead(
__000001_add_messages_contactsUpDbSql,
"000001_add_messages_contacts.up.db.sql",
__000001_initUpDbSql,
"000001_init.up.db.sql",
)
}
func _000001_add_messages_contactsUpDbSql() (*asset, error) {
bytes, err := _000001_add_messages_contactsUpDbSqlBytes()
func _000001_initUpDbSql() (*asset, error) {
bytes, err := _000001_initUpDbSqlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "000001_add_messages_contacts.up.db.sql", size: 685, mode: os.FileMode(0644), modTime: time.Unix(1562955202, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x1d, 0xd, 0x9, 0xd8, 0x7d, 0xba, 0x90, 0x3c, 0x7c, 0x6, 0xf2, 0x12, 0xb2, 0xbc, 0xd8, 0xbd, 0xc0, 0xea, 0xde, 0xa7, 0xae, 0x6a, 0x4b, 0xe5, 0x3d, 0xc3, 0xa4, 0x4a, 0x6d, 0x62, 0x2b, 0x91}}
return a, nil
}
var __000002_add_unread_to_user_messagesDownSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x44\x8e\x31\x4e\xc5\x30\x10\x44\x7b\x4e\x31\x25\x14\xfe\x07\xa0\xa6\xa1\x4a\x03\x07\xd8\xd8\x43\x62\xc9\xde\xb5\xec\xb5\x42\x6e\x8f\x2c\x21\x68\xdf\xee\xbc\x99\x10\xf0\xb1\xbd\x6d\xcf\x92\xa4\xbe\xbc\x22\x8a\xaa\x39\x52\xb7\x86\x68\x65\x56\xc5\x95\xfd\xb4\xe9\x88\xd6\xee\xac\x07\x04\x2e\x7b\xe1\xe3\x29\x04\xbc\xd7\x56\x58\xa9\xff\xd7\x3c\x40\x19\x37\xf6\xe9\xb8\x08\x25\x13\xdc\x90\x66\x2b\x39\x8a\x13\x23\x9e\xac\xb2\xc2\x6e\xe8\x8c\x9d\x8b\x66\x7f\xe0\x53\x0b\xc7\x80\x9f\xec\x5c\x1e\xc1\xa8\xd2\x9d\x1d\x97\xdc\xeb\xfb\xa0\x2f\xf8\x27\xb0\x2f\x88\x82\xdf\x79\xf8\xaa\xfe\x9d\xf5\x13\x00\x00\xff\xff\x1c\xd9\x39\x28\xd2\x00\x00\x00")
func _000002_add_unread_to_user_messagesDownSqlBytes() ([]byte, error) {
return bindataRead(
__000002_add_unread_to_user_messagesDownSql,
"000002_add_unread_to_user_messages.down.sql",
)
}
func _000002_add_unread_to_user_messagesDownSql() (*asset, error) {
bytes, err := _000002_add_unread_to_user_messagesDownSqlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "000002_add_unread_to_user_messages.down.sql", size: 210, mode: os.FileMode(0644), modTime: time.Unix(1562955202, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xdc, 0x47, 0x8e, 0x4b, 0x54, 0x6a, 0xfc, 0x61, 0xa5, 0x37, 0xc6, 0xd6, 0xd3, 0x22, 0xcd, 0xbe, 0xb3, 0x60, 0xd8, 0xa0, 0xe2, 0x67, 0x27, 0x5, 0xf3, 0x6d, 0xca, 0x84, 0xd5, 0xfc, 0x94, 0x1a}}
return a, nil
}
var __000002_add_unread_to_user_messagesUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x2c\xcc\x41\xca\xc2\x30\x10\x40\xe1\x7d\x4f\xf1\x2e\x50\xfe\x7f\xef\x2a\x9a\x08\xc2\x98\x82\x4c\xd6\x12\x70\x2c\xc5\xaa\x90\x21\x9e\x5f\x84\xae\xde\xea\x7d\x41\x34\x5d\xd0\xb0\x97\x44\x77\x6b\xd7\xa7\xb9\xd7\xd9\x7c\x00\x08\x31\x72\x98\xa4\x9c\x33\xf7\xb5\xce\xce\x29\x2b\x79\x52\x72\x11\x21\xa6\x63\x28\xa2\xfc\xef\x18\x47\x3e\xb5\x2d\xef\xee\x6c\xc0\x36\xac\xcb\xc3\x68\x56\x6f\x7f\xfd\xf5\xcb\xf0\x0d\x00\x00\xff\xff\xbc\x55\xda\x47\x71\x00\x00\x00")
func _000002_add_unread_to_user_messagesUpSqlBytes() ([]byte, error) {
return bindataRead(
__000002_add_unread_to_user_messagesUpSql,
"000002_add_unread_to_user_messages.up.sql",
)
}
func _000002_add_unread_to_user_messagesUpSql() (*asset, error) {
bytes, err := _000002_add_unread_to_user_messagesUpSqlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "000002_add_unread_to_user_messages.up.sql", size: 113, mode: os.FileMode(0644), modTime: time.Unix(1562955202, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x8a, 0x92, 0x67, 0x90, 0x5, 0xb4, 0x82, 0x13, 0x78, 0x83, 0xae, 0x5e, 0x13, 0x67, 0x2f, 0xdd, 0xe1, 0xcb, 0x11, 0x70, 0xdb, 0x5, 0xb6, 0xb0, 0x1c, 0x29, 0x99, 0xae, 0x1a, 0x32, 0xb0, 0x41}}
info := bindataFileInfo{name: "000001_init.up.db.sql", size: 840, mode: os.FileMode(0644), modTime: time.Unix(1564410717, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe7, 0x27, 0x96, 0x3b, 0x72, 0x81, 0x7d, 0xba, 0xa4, 0xfb, 0xf7, 0x4, 0xd, 0x6f, 0xc8, 0x30, 0xfe, 0x47, 0xe0, 0x9, 0xf, 0x43, 0x13, 0x6, 0x55, 0xfc, 0xee, 0x15, 0x69, 0x99, 0x53, 0x3f}}
return a, nil
}
@ -168,7 +126,7 @@ func docGo() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "doc.go", size: 377, mode: os.FileMode(0644), modTime: time.Unix(1562955202, 0)}
info := bindataFileInfo{name: "doc.go", size: 377, mode: os.FileMode(0644), modTime: time.Unix(1564410717, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x94, 0xd1, 0x5c, 0x73, 0x47, 0x65, 0xf9, 0x6e, 0xa0, 0xee, 0xb, 0x3d, 0xbe, 0xff, 0xef, 0xae, 0xc9, 0x46, 0x21, 0x85, 0x12, 0x46, 0xa1, 0x73, 0x74, 0xca, 0x71, 0xb1, 0xe1, 0x69, 0xe1, 0x82}}
return a, nil
}
@ -264,13 +222,9 @@ func AssetNames() []string {
// _bindata is a table, holding each asset generator, mapped to its name.
var _bindata = map[string]func() (*asset, error){
"000001_add_messages_contacts.down.db.sql": _000001_add_messages_contactsDownDbSql,
"000001_init.down.db.sql": _000001_initDownDbSql,
"000001_add_messages_contacts.up.db.sql": _000001_add_messages_contactsUpDbSql,
"000002_add_unread_to_user_messages.down.sql": _000002_add_unread_to_user_messagesDownSql,
"000002_add_unread_to_user_messages.up.sql": _000002_add_unread_to_user_messagesUpSql,
"000001_init.up.db.sql": _000001_initUpDbSql,
"doc.go": docGo,
}
@ -316,10 +270,8 @@ type bintree struct {
}
var _bintree = &bintree{nil, map[string]*bintree{
"000001_add_messages_contacts.down.db.sql": &bintree{_000001_add_messages_contactsDownDbSql, map[string]*bintree{}},
"000001_add_messages_contacts.up.db.sql": &bintree{_000001_add_messages_contactsUpDbSql, map[string]*bintree{}},
"000002_add_unread_to_user_messages.down.sql": &bintree{_000002_add_unread_to_user_messagesDownSql, map[string]*bintree{}},
"000002_add_unread_to_user_messages.up.sql": &bintree{_000002_add_unread_to_user_messagesUpSql, map[string]*bintree{}},
"000001_init.down.db.sql": &bintree{_000001_initDownDbSql, map[string]*bintree{}},
"000001_init.up.db.sql": &bintree{_000001_initUpDbSql, map[string]*bintree{}},
"doc.go": &bintree{docGo, map[string]*bintree{}},
}}

View File

@ -3,6 +3,7 @@ package statusproto
import (
"context"
"crypto/ecdsa"
"fmt"
"path/filepath"
"time"
@ -11,6 +12,8 @@ import (
"github.com/pkg/errors"
whisper "github.com/status-im/whisper/whisperv6"
"github.com/status-im/status-protocol-go/datasync"
datasyncpeer "github.com/status-im/status-protocol-go/datasync/peer"
"github.com/status-im/status-protocol-go/encryption"
"github.com/status-im/status-protocol-go/encryption/multidevice"
"github.com/status-im/status-protocol-go/encryption/sharedsecret"
@ -19,12 +22,10 @@ import (
transport "github.com/status-im/status-protocol-go/transport/whisper"
"github.com/status-im/status-protocol-go/transport/whisper/filter"
protocol "github.com/status-im/status-protocol-go/v1"
)
const (
// messagesDatabaseFileName is a name of the SQL file in which
// messages are stored.
messagesDatabaseFileName = "messages.sql"
datasyncnode "github.com/vacp2p/mvds/node"
datasyncpeers "github.com/vacp2p/mvds/peers"
datasyncstate "github.com/vacp2p/mvds/state"
datasyncstore "github.com/vacp2p/mvds/store"
)
var (
@ -44,13 +45,11 @@ type Messenger struct {
persistence persistence
adapter *whisperAdapter
encryptor *encryption.Protocol
logger *zap.Logger
ownMessages map[string][]*protocol.Message
featureFlags featureFlags
messagesPersistenceEnabled bool
logger *zap.Logger
shutdownTasks []func() error
}
@ -61,6 +60,9 @@ type featureFlags struct {
// V1 messages adds additional wrapping
// which contains a signature and payload.
sendV1Messages bool
// datasync indicates whether messages should be sent using datasync, breaking change for non-v1 clients
datasync bool
}
type config struct {
@ -132,6 +134,13 @@ func WithSendV1Messages() func(c *config) error {
}
}
func WithDatasync() func(c *config) error {
return func(c *config) error {
c.featureFlags.datasync = true
return nil
}
}
func NewMessenger(
identity *ecdsa.PrivateKey,
server transport.Server,
@ -186,9 +195,11 @@ func NewMessenger(
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
_, err := messenger.adapter.SendContactCode(ctx, messageSpec)
if err != nil {
slogger.Warn("failed to send a contact code", zap.Error(err))
}
}
}
// Set default database file paths.
if c.encryptionLayerFilePath == "" {
@ -224,6 +235,8 @@ func NewMessenger(
return nil, errors.Wrap(err, "failed to create the encryption layer")
}
messagesDatabaseFileName := fmt.Sprintf("%s.messages.sql", installationID)
applicationLayerFilePath := filepath.Join(dataDir, messagesDatabaseFileName)
applicationLayerPersistence, err := sqlite.Open(applicationLayerFilePath, dbKey, sqlite.MigrationConfig{
AssetNames: migrations.AssetNames(),
@ -234,9 +247,22 @@ func NewMessenger(
if err != nil {
return nil, errors.Wrap(err, "failed to initialize messages db")
}
dataSyncTransport := datasync.NewDataSyncNodeTransport()
dataSyncStore := datasyncstore.NewDummyStore()
dataSyncNode := datasyncnode.NewNode(
&dataSyncStore,
dataSyncTransport,
datasyncstate.NewSyncState(), // @todo sqlite syncstate
datasync.CalculateSendTime,
0,
datasyncpeer.PublicKeyToPeerID(identity.PublicKey),
datasyncnode.BATCH,
datasyncpeers.NewMemoryPersistence(),
)
datasync := datasync.New(dataSyncNode, dataSyncTransport, c.featureFlags.datasync, logger)
persistence := &sqlitePersistence{db: applicationLayerPersistence}
adapter := newWhisperAdapter(identity, t, encryptionProtocol, c.featureFlags, logger)
adapter := newWhisperAdapter(identity, t, encryptionProtocol, datasync, c.featureFlags, logger)
messenger = &Messenger{
identity: identity,
persistence: persistence,
@ -248,6 +274,7 @@ func NewMessenger(
shutdownTasks: []func() error{
persistence.Close,
adapter.transport.Reset,
func() error { datasync.Stop(); return nil },
// Currently this often fails, seems like it's safe to ignore them
// https://github.com/uber-go/zap/issues/328
func() error { _ = logger.Sync; return nil },
@ -260,6 +287,9 @@ func NewMessenger(
if err := encryptionProtocol.Start(identity); err != nil {
return nil, err
}
if c.featureFlags.datasync {
dataSyncNode.Start(300 * time.Millisecond)
}
logger.Debug("messages persistence", zap.Bool("enabled", c.messagesPersistenceEnabled))
@ -402,6 +432,47 @@ var (
RetrieveLastDay = RetrieveConfig{latest: true, last24Hours: true}
)
// RetrieveAll retrieves all previously fetched messages
func (m *Messenger) RetrieveAll(ctx context.Context, c RetrieveConfig) (allMessages []*protocol.Message, err error) {
latest, err := m.adapter.RetrieveAllMessages()
if err != nil {
err = errors.Wrap(err, "failed to retrieve messages")
return
}
for _, messages := range latest {
chatID := messages.ChatID
_, err = m.persistence.SaveMessages(chatID, messages.Messages)
if err != nil {
return nil, errors.Wrap(err, "failed to save messages")
}
if !messages.Public {
// Return any own messages for this chat as well.
if ownMessages, ok := m.ownMessages[chatID]; ok {
messages.Messages = append(messages.Messages, ownMessages...)
}
}
retrievedMessages, err := m.retrieveSaved(ctx, chatID, c, messages.Messages)
if err != nil {
return nil, errors.Wrap(err, "failed to get saved messages")
}
allMessages = append(allMessages, retrievedMessages...)
}
// Delete own messages as they were added to the result.
for _, messages := range latest {
if !messages.Public {
delete(m.ownMessages, messages.ChatID)
}
}
return
}
func (m *Messenger) Retrieve(ctx context.Context, chat Chat, c RetrieveConfig) (messages []*protocol.Message, err error) {
var (
latest []*protocol.Message
@ -442,40 +513,41 @@ func (m *Messenger) Retrieve(ctx context.Context, chat Chat, c RetrieveConfig) (
}
}
// We may need to add more messages from the past.
result, err := m.retrieveSaved(ctx, chat.ID(), c, append(latest, ownLatest...))
if err != nil {
return nil, err
}
// When our messages are returned, we can delete them.
delete(m.ownMessages, chat.ID())
return m.retrieveSaved(ctx, chat, c, append(latest, ownLatest...))
return result, nil
}
func (m *Messenger) retrieveSaved(ctx context.Context, chat Chat, c RetrieveConfig, latest []*protocol.Message) (messages []*protocol.Message, err error) {
func (m *Messenger) retrieveSaved(ctx context.Context, chatID string, c RetrieveConfig, latest []*protocol.Message) (messages []*protocol.Message, err error) {
if !m.messagesPersistenceEnabled {
return latest, nil
}
if !c.latest {
return m.persistence.Messages(chat.ID(), c.From, c.To)
return m.persistence.Messages(chatID, c.From, c.To)
}
if c.last24Hours {
to := time.Now()
from := to.Add(-time.Hour * 24)
return m.persistence.Messages(chat.ID(), from, to)
return m.persistence.Messages(chatID, from, to)
}
return latest, nil
}
// DEPRECATED
func (m *Messenger) RetrieveRawAll() (map[filter.Chat][]*whisper.Message, error) {
func (m *Messenger) RetrieveRawAll() (map[filter.Chat][]*protocol.StatusMessage, error) {
return m.adapter.RetrieveRawAll()
}
// DEPRECATED
func (m *Messenger) RetrieveRawWithFilter(filterID string) ([]*whisper.Message, error) {
return m.adapter.RetrieveRaw(filterID)
}
// DEPRECATED
func (m *Messenger) LoadFilters(chats []*filter.Chat) ([]*filter.Chat, error) {
return m.adapter.transport.LoadFilters(chats, m.featureFlags.genericDiscoveryTopicEnabled)

View File

@ -47,7 +47,7 @@ func (db sqlitePersistence) LastMessageClock(chatID string) (int64, error) {
}
var last sql.NullInt64
err := db.db.QueryRow("SELECT max(clock) FROM user_messages WHERE contact_id = ?", chatID).Scan(&last)
err := db.db.QueryRow("SELECT max(clock) FROM user_messages WHERE chat_id = ?", chatID).Scan(&last)
if err != nil {
return 0, err
}
@ -64,7 +64,7 @@ func (db sqlitePersistence) SaveMessages(chatID string, messages []*protocol.Mes
return
}
stmt, err = tx.Prepare(`INSERT INTO user_messages(
id, contact_id, content_type, message_type, text, clock, timestamp, content_chat_id, content_text, public_key, flags)
id, chat_id, content_type, message_type, text, clock, timestamp, content_chat_id, content_text, public_key, flags)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
if err != nil {
return
@ -111,7 +111,7 @@ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
func (db sqlitePersistence) Messages(chatID string, from, to time.Time) (result []*protocol.Message, err error) {
rows, err := db.db.Query(`SELECT
id, content_type, message_type, text, clock, timestamp, content_chat_id, content_text, public_key, flags
FROM user_messages WHERE contact_id = ? AND timestamp >= ? AND timestamp <= ? ORDER BY timestamp`,
FROM user_messages WHERE chat_id = ? AND timestamp >= ? AND timestamp <= ? ORDER BY timestamp`,
chatID, protocol.TimestampInMsFromTime(from), protocol.TimestampInMsFromTime(to))
if err != nil {
return nil, err
@ -144,7 +144,7 @@ FROM user_messages WHERE contact_id = ? AND timestamp >= ? AND timestamp <= ? OR
func (db sqlitePersistence) NewMessages(chatID string, rowid int64) ([]*protocol.Message, error) {
rows, err := db.db.Query(`SELECT
id, content_type, message_type, text, clock, timestamp, content_chat_id, content_text, public_key, flags
FROM user_messages WHERE contact_id = ? AND rowid >= ? ORDER BY clock`,
FROM user_messages WHERE chat_id = ? AND rowid >= ? ORDER BY clock`,
chatID, rowid)
if err != nil {
return nil, err
@ -192,7 +192,7 @@ func (db sqlitePersistence) UnreadMessages(chatID string) ([]*protocol.Message,
FROM
user_messages
WHERE
contact_id = ? AND
chat_id = ? AND
flags & ? == 0
ORDER BY clock`,
chatID, protocol.MessageRead,

View File

@ -58,6 +58,10 @@ type Chat struct {
Listen bool `json:"listen"`
}
func (c *Chat) IsPublic() bool {
return !c.OneToOne
}
type ChatsManager struct {
whisper *whisper.Whisper
persistence *sqlitePersistence
@ -278,6 +282,7 @@ func (s *ChatsManager) loadPartitioned(publicKey *ecdsa.PublicKey, listen bool)
Topic: filter.Topic,
Identity: publicKeyToStr(publicKey),
Listen: listen,
OneToOne: true,
}
s.chats[chatID] = chat
@ -310,6 +315,7 @@ func (s *ChatsManager) LoadNegotiated(secret NegotiatedSecret) (*Chat, error) {
Identity: publicKeyToStr(secret.PublicKey),
Negotiated: true,
Listen: true,
OneToOne: true,
}
s.chats[chat.ChatID] = chat
@ -354,6 +360,7 @@ func (s *ChatsManager) LoadDiscovery() ([]*Chat, error) {
Identity: identityStr,
Discovery: true,
Listen: true,
OneToOne: true,
}
discoveryResponse, err = s.addAsymmetric(personalDiscoveryChat.ChatID, true)
@ -373,6 +380,7 @@ func (s *ChatsManager) LoadDiscovery() ([]*Chat, error) {
Identity: identityStr,
Discovery: true,
Listen: true,
OneToOne: true,
}
discoveryResponse, err = s.addAsymmetric(discoveryChat.ChatID, true)
@ -411,6 +419,7 @@ func (s *ChatsManager) LoadPublic(chatID string) (*Chat, error) {
SymKeyID: filterAndTopic.SymKeyID,
Topic: filterAndTopic.Topic,
Listen: true,
OneToOne: false,
}
s.chats[chatID] = chat

View File

@ -86,7 +86,7 @@ func _1561059285_add_whisper_keysDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1561059285_add_whisper_keys.down.sql", size: 25, mode: os.FileMode(0644), modTime: time.Unix(1562956766, 0)}
info := bindataFileInfo{name: "1561059285_add_whisper_keys.down.sql", size: 25, mode: os.FileMode(0644), modTime: time.Unix(1564410717, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb9, 0x31, 0x3f, 0xce, 0xfa, 0x44, 0x36, 0x1b, 0xb0, 0xec, 0x5d, 0xb, 0x90, 0xb, 0x21, 0x4f, 0xd5, 0xe5, 0x50, 0xed, 0xc7, 0x43, 0xdf, 0x83, 0xb4, 0x3a, 0xc1, 0x55, 0x2e, 0x53, 0x7c, 0x67}}
return a, nil
}
@ -106,7 +106,7 @@ func _1561059285_add_whisper_keysUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1561059285_add_whisper_keys.up.sql", size: 112, mode: os.FileMode(0644), modTime: time.Unix(1562956695, 0)}
info := bindataFileInfo{name: "1561059285_add_whisper_keys.up.sql", size: 112, mode: os.FileMode(0644), modTime: time.Unix(1564410717, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x25, 0x41, 0xc, 0x92, 0xdd, 0x9e, 0xff, 0x5d, 0xd0, 0x93, 0xe4, 0x24, 0x50, 0x29, 0xcf, 0xc6, 0xf7, 0x49, 0x3c, 0x73, 0xd9, 0x8c, 0xfa, 0xf2, 0xcf, 0xf6, 0x6f, 0xbc, 0x31, 0xe6, 0xf7, 0xe2}}
return a, nil
}
@ -126,7 +126,7 @@ func docGo() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "doc.go", size: 377, mode: os.FileMode(0644), modTime: time.Unix(1562956695, 0)}
info := bindataFileInfo{name: "doc.go", size: 377, mode: os.FileMode(0644), modTime: time.Unix(1564410717, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x94, 0xd1, 0x5c, 0x73, 0x47, 0x65, 0xf9, 0x6e, 0xa0, 0xee, 0xb, 0x3d, 0xbe, 0xff, 0xef, 0xae, 0xc9, 0x46, 0x21, 0x85, 0x12, 0x46, 0xa1, 0x73, 0x74, 0xca, 0x71, 0xb1, 0xe1, 0x69, 0xe1, 0x82}}
return a, nil
}

View File

@ -167,6 +167,34 @@ func (a *WhisperServiceTransport) LeavePrivate(publicKey *ecdsa.PublicKey) error
return a.chats.Remove(chats...)
}
type ChatMessages struct {
Messages []*whisper.ReceivedMessage
Public bool
ChatID string
}
func (a *WhisperServiceTransport) RetrieveAllMessages() ([]ChatMessages, error) {
chatMessages := make(map[string]ChatMessages)
for _, chat := range a.chats.Chats() {
f := a.shh.GetFilter(chat.FilterID)
if f == nil {
return nil, errors.New("failed to return a filter")
}
messages := chatMessages[chat.ChatID]
messages.ChatID = chat.ChatID
messages.Public = chat.IsPublic()
messages.Messages = append(messages.Messages, f.Retrieve()...)
}
var result []ChatMessages
for _, messages := range chatMessages {
result = append(result, messages)
}
return result, nil
}
func (a *WhisperServiceTransport) RetrievePublicMessages(chatID string) ([]*whisper.ReceivedMessage, error) {
chat, err := a.chats.LoadPublic(chatID)
if err != nil {
@ -183,7 +211,7 @@ func (a *WhisperServiceTransport) RetrievePublicMessages(chatID string) ([]*whis
func (a *WhisperServiceTransport) RetrievePrivateMessages(publicKey *ecdsa.PublicKey) ([]*whisper.ReceivedMessage, error) {
chats := a.chats.ChatsByPublicKey(publicKey)
discoveryChats, err := a.chats.LoadDiscovery()
discoveryChats, err := a.chats.Init(nil, nil, true)
if err != nil {
return nil, err
}
@ -195,6 +223,7 @@ func (a *WhisperServiceTransport) RetrievePrivateMessages(publicKey *ecdsa.Publi
if f == nil {
return nil, errors.New("failed to return a filter")
}
result = append(result, f.Retrieve()...)
}
@ -211,6 +240,7 @@ func (a *WhisperServiceTransport) RetrieveRawAll() (map[filter.Chat][]*whisper.R
if f == nil {
return nil, errors.New("failed to return a filter")
}
result[*chat] = append(result[*chat], f.Retrieve()...)
}

View File

@ -0,0 +1,3 @@
# v1 statusproto package folder
This folder contains only data types mentioned in the specification and required for its implementation.

View File

@ -5,16 +5,14 @@ import (
"crypto/ecdsa"
"encoding/hex"
"encoding/json"
"errors"
"github.com/pkg/errors"
"time"
"github.com/ethereum/go-ethereum/crypto"
"github.com/golang/protobuf/proto"
"log"
"strings"
"time"
)
//go:generate protoc --go_out=. ./message.proto
const (
// ContentTypeTextPlain means that the message contains plain text.
ContentTypeTextPlain = "text/plain"
@ -67,26 +65,6 @@ const (
MessageRead Flags = 1 << iota
)
// StatusMessage is any Status Protocol message.
type StatusMessage struct {
Message interface{}
ID []byte `json:"-"`
SigPubKey *ecdsa.PublicKey `json:"-"`
}
func (m *StatusMessage) MarshalJSON() ([]byte, error) {
type MessageAlias StatusMessage
item := struct {
*MessageAlias
ID string `json:"id"`
}{
MessageAlias: (*MessageAlias)(m),
ID: "0x" + hex.EncodeToString(m.ID),
}
return json.Marshal(item)
}
// Message is a chat message sent by an user.
type Message struct {
Text string `json:"text"` // TODO: why is this duplicated?
@ -99,6 +77,8 @@ type Message struct {
Flags Flags `json:"-"`
ID []byte `json:"-"`
SigPubKey *ecdsa.PublicKey `json:"-"`
ChatID string `json:"-"`
Public bool `json:"-"`
}
func (m *Message) MarshalJSON() ([]byte, error) {
@ -114,10 +94,6 @@ func (m *Message) MarshalJSON() ([]byte, error) {
return json.Marshal(item)
}
func (m Message) Unread() bool {
return !m.Flags.Has(MessageRead)
}
// createTextMessage creates a Message.
func createTextMessage(data []byte, lastClock int64, chatID, messageType string) Message {
text := strings.TrimSpace(string(data))
@ -144,17 +120,12 @@ func CreatePrivateTextMessage(data []byte, lastClock int64, chatID string) Messa
return createTextMessage(data, lastClock, chatID, MessageTypePrivate)
}
func unwrapMessage(data []byte) (*StatusProtocolMessage, error) {
var message StatusProtocolMessage
err := proto.Unmarshal(data, &message)
if err != nil {
return nil, err
}
return &message, nil
}
func decodeTransitMessage(originalPayload []byte) (interface{}, error) {
payload := make([]byte, len(originalPayload))
copy(payload, originalPayload)
// This modifies the payload
buf := bytes.NewBuffer(payload)
func decodeTransitMessage(data []byte) (interface{}, error) {
buf := bytes.NewBuffer(data)
decoder := NewMessageDecoder(buf)
value, err := decoder.Decode()
if err != nil {
@ -163,42 +134,6 @@ func decodeTransitMessage(data []byte) (interface{}, error) {
return value, nil
}
// DecodeMessage decodes a raw payload to StatusMessage struct.
func DecodeMessage(transportPublicKey *ecdsa.PublicKey, data []byte) (message StatusMessage, err error) {
transitMessage := data
// Getting a signature from transport message should happen only if
// the signature was not defined in the payload itself.
message.SigPubKey = transportPublicKey
statusProtocolMessage, err := unwrapMessage(data)
if err == nil {
// Wrapped message, extract transit and signature
transitMessage = statusProtocolMessage.Payload
if statusProtocolMessage.Signature != nil {
recoveredKey, err := crypto.SigToPub(
crypto.Keccak256(transitMessage),
statusProtocolMessage.Signature,
)
if err != nil {
return message, err
}
message.SigPubKey = recoveredKey
}
}
message.ID = MessageID(message.SigPubKey, transitMessage)
value, err := decodeTransitMessage(transitMessage)
if err != nil {
log.Printf("[message::DecodeMessage] could not decode message: %#x", message.ID)
return message, err
}
message.Message = value
return message, nil
}
// EncodeMessage encodes a Message using Transit serialization.
func EncodeMessage(value Message) ([]byte, error) {
var buf bytes.Buffer

View File

@ -21,8 +21,8 @@ var _ = math.Inf
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type StatusProtocolMessage struct {
Signature []byte `protobuf:"bytes,1,opt,name=signature,proto3" json:"signature,omitempty"`
Payload []byte `protobuf:"bytes,2,opt,name=payload,proto3" json:"payload,omitempty"`
Signature []byte `protobuf:"bytes,4001,opt,name=signature,proto3" json:"signature,omitempty"`
Payload []byte `protobuf:"bytes,4002,opt,name=payload,proto3" json:"payload,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@ -74,12 +74,12 @@ func init() {
func init() { proto.RegisterFile("message.proto", fileDescriptor_33c57e4bae7b9afd) }
var fileDescriptor_33c57e4bae7b9afd = []byte{
// 108 bytes of a gzipped FileDescriptorProto
// 109 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0xcd, 0x4d, 0x2d, 0x2e,
0x4e, 0x4c, 0x4f, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x2e, 0x2e, 0x49, 0x2c, 0x29,
0x2d, 0x06, 0x73, 0x94, 0xfc, 0xb9, 0x44, 0x83, 0xc1, 0xdc, 0x00, 0x10, 0x37, 0x39, 0x3f, 0xc7,
0x17, 0xa2, 0x56, 0x48, 0x86, 0x8b, 0xb3, 0x38, 0x33, 0x3d, 0x2f, 0xb1, 0xa4, 0xb4, 0x28, 0x55,
0x82, 0x51, 0x81, 0x51, 0x83, 0x27, 0x08, 0x21, 0x20, 0x24, 0xc1, 0xc5, 0x5e, 0x90, 0x58, 0x99,
0x93, 0x9f, 0x98, 0x22, 0xc1, 0x04, 0x96, 0x83, 0x71, 0x93, 0xd8, 0xc0, 0xe6, 0x1a, 0x03, 0x02,
0x00, 0x00, 0xff, 0xff, 0xda, 0x9a, 0x88, 0x4b, 0x75, 0x00, 0x00, 0x00,
0x2d, 0x06, 0x73, 0x94, 0x02, 0xb9, 0x44, 0x83, 0xc1, 0xdc, 0x00, 0x10, 0x37, 0x39, 0x3f, 0xc7,
0x17, 0xa2, 0x56, 0x48, 0x96, 0x8b, 0xb3, 0x38, 0x33, 0x3d, 0x2f, 0xb1, 0xa4, 0xb4, 0x28, 0x55,
0x62, 0xa1, 0xbc, 0x02, 0xa3, 0x06, 0x4f, 0x10, 0x42, 0x44, 0x48, 0x92, 0x8b, 0xbd, 0x20, 0xb1,
0x32, 0x27, 0x3f, 0x31, 0x45, 0x62, 0x11, 0x44, 0x12, 0xc6, 0x4f, 0x62, 0x03, 0x9b, 0x6c, 0x0c,
0x08, 0x00, 0x00, 0xff, 0xff, 0x92, 0x1a, 0x92, 0xf0, 0x77, 0x00, 0x00, 0x00,
}

View File

@ -1,8 +0,0 @@
syntax = "proto3";
package statusproto;
message StatusProtocolMessage {
bytes signature = 1;
bytes payload = 2;
}

View File

@ -0,0 +1,142 @@
package statusproto
import (
"crypto/ecdsa"
"github.com/pkg/errors"
"log"
"github.com/ethereum/go-ethereum/crypto"
"github.com/golang/protobuf/proto"
"github.com/jinzhu/copier"
"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"
)
// StatusMessage is any Status Protocol message.
type StatusMessage struct {
// TransportMessage is the parsed message received from the trasport layer, i.e the input
TransportMessage *whisper.Message
// ParsedMessage is the parsed message by the application layer, i.e the output
ParsedMessage interface{}
// TransportPayload is the payload as received from the transport layer
TransportPayload []byte
// DecryptedPayload is the payload after having been processed by the encryption layer
DecryptedPayload []byte
// ID is the canonical ID of the message
ID []byte
// Hash is the transport layer hash
Hash []byte
// TransportLayerSigPubKey contains the public key provided by the transport layer
TransportLayerSigPubKey *ecdsa.PublicKey
// ApplicationMetadataLayerPubKey contains the public key provided by the application metadata layer
ApplicationMetadataLayerSigPubKey *ecdsa.PublicKey
}
// SigPubKey returns the most important signature, from the application layer to transport
func (s *StatusMessage) SigPubKey() *ecdsa.PublicKey {
if s.ApplicationMetadataLayerSigPubKey != nil {
return s.ApplicationMetadataLayerSigPubKey
}
return s.TransportLayerSigPubKey
}
func (s *StatusMessage) Clone() (*StatusMessage, error) {
copy := &StatusMessage{}
err := copier.Copy(&copy, s)
return copy, err
}
func (m *StatusMessage) HandleTransport(shhMessage *whisper.Message) error {
publicKey, err := crypto.UnmarshalPubkey(shhMessage.Sig)
if err != nil {
return errors.Wrap(err, "failed to get signature")
}
m.TransportMessage = shhMessage
m.Hash = shhMessage.Hash
m.TransportLayerSigPubKey = publicKey
m.TransportPayload = shhMessage.Payload
return nil
}
func (m *StatusMessage) HandleEncryption(myKey *ecdsa.PrivateKey, senderKey *ecdsa.PublicKey, enc *encryption.Protocol) error {
// As we handle non-encrypted messages, we make sure that DecryptPayload
// is set regardless of whether this step is successful
m.DecryptedPayload = m.TransportPayload
var protocolMessage encryption.ProtocolMessage
err := proto.Unmarshal(m.TransportPayload, &protocolMessage)
if err != nil {
return errors.Wrap(err, "failed to unmarshal ProtocolMessage")
}
payload, err := enc.HandleMessage(
myKey,
senderKey,
&protocolMessage,
m.Hash,
)
if err != nil {
return errors.Wrap(err, "failed to handle Encryption message")
}
m.DecryptedPayload = payload
return nil
}
func (m *StatusMessage) HandleDatasync(datasync *datasync.DataSync) ([]*StatusMessage, error) {
var statusMessages []*StatusMessage
payloads := datasync.Handle(
m.SigPubKey(),
m.DecryptedPayload,
)
for _, payload := range payloads {
message, err := m.Clone()
if err != nil {
return nil, err
}
message.DecryptedPayload = payload
statusMessages = append(statusMessages, message)
}
return statusMessages, nil
}
func (m *StatusMessage) HandleApplicationMetadata() error {
message, err := applicationmetadata.Unmarshal(m.DecryptedPayload)
// Not an applicationmetadata message, calculate ID using the previous
// signature
if err != nil {
m.ID = MessageID(m.SigPubKey(), m.DecryptedPayload)
return nil
}
recoveredKey, err := message.RecoverKey()
if err != nil {
return err
}
m.ApplicationMetadataLayerSigPubKey = recoveredKey
m.DecryptedPayload = message.Payload
m.ID = MessageID(m.SigPubKey(), m.DecryptedPayload)
return nil
}
func (m *StatusMessage) HandleApplication() error {
value, err := decodeTransitMessage(m.DecryptedPayload)
if err != nil {
log.Printf("[message::DecodeMessage] could not decode message: %#x", m.Hash)
return err
}
m.ParsedMessage = value
return nil
}

21
vendor/github.com/vacp2p/mvds/LICENSE generated vendored Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Status
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

404
vendor/github.com/vacp2p/mvds/node/node.go generated vendored Normal file
View File

@ -0,0 +1,404 @@
// Package Node contains node logic.
package node
// @todo this is a very rough implementation that needs cleanup
import (
"context"
"fmt"
"log"
"sync/atomic"
"time"
"github.com/vacp2p/mvds/peers"
"github.com/vacp2p/mvds/protobuf"
"github.com/vacp2p/mvds/state"
"github.com/vacp2p/mvds/store"
"github.com/vacp2p/mvds/transport"
)
// Mode represents the synchronization mode.
type Mode int
const (
INTERACTIVE Mode = iota
BATCH
)
// CalculateNextEpoch is a function used to calculate the next `SendEpoch` for a given message.
type CalculateNextEpoch func(count uint64, epoch int64) int64
// Node represents an MVDS node, it runs all the logic like sending and receiving protocol messages.
type Node struct {
ctx context.Context
cancel context.CancelFunc
store store.MessageStore
transport transport.Transport
syncState state.SyncState
peers peers.Persistence
payloads payloads
nextEpoch CalculateNextEpoch
ID state.PeerID
epoch int64
mode Mode
}
// NewNode returns a new node.
func NewNode(
ms store.MessageStore,
st transport.Transport,
ss state.SyncState,
nextEpoch CalculateNextEpoch,
currentEpoch int64,
id state.PeerID,
mode Mode,
pp peers.Persistence,
) *Node {
ctx, cancel := context.WithCancel(context.Background())
return &Node{
ctx: ctx,
cancel: cancel,
store: ms,
transport: st,
syncState: ss,
peers: pp,
payloads: newPayloads(),
nextEpoch: nextEpoch,
ID: id,
epoch: currentEpoch,
mode: mode,
}
}
// Start listens for new messages received by the node and sends out those required every epoch.
func (n *Node) Start(duration time.Duration) {
go func() {
for {
select {
case <-n.ctx.Done():
log.Print("Watch stopped")
return
default:
p := n.transport.Watch()
go n.onPayload(p.Sender, p.Payload)
}
}
}()
go func() {
for {
select {
case <-n.ctx.Done():
log.Print("Epoch processing stopped")
return
default:
log.Printf("Node: %x Epoch: %d", n.ID[:4], n.epoch)
time.Sleep(duration)
err := n.sendMessages()
if err != nil {
log.Printf("Error sending messages: %+v\n", err)
}
atomic.AddInt64(&n.epoch, 1)
}
}
}()
}
// Stop message reading and epoch processing
func (n *Node) Stop() {
log.Print("Stopping node")
n.cancel()
}
// AppendMessage sends a message to a given group.
func (n *Node) AppendMessage(groupID state.GroupID, data []byte) (state.MessageID, error) {
m := protobuf.Message{
GroupId: groupID[:],
Timestamp: time.Now().Unix(),
Body: data,
}
id := m.ID()
peers, err := n.peers.GetByGroupID(groupID)
if err != nil {
return state.MessageID{}, fmt.Errorf("trying to send to unknown group %x", groupID[:4])
}
err = n.store.Add(&m)
if err != nil {
return state.MessageID{}, err
}
for _, p := range peers {
t := state.OFFER
if n.mode == BATCH {
t = state.MESSAGE
}
n.insertSyncState(&groupID, id, p, t)
}
log.Printf("[%x] node %x sending %x\n", groupID[:4], n.ID[:4], id[:4])
// @todo think about a way to insta trigger send messages when send was selected, we don't wanna wait for ticks here
return id, nil
}
// RequestMessage adds a REQUEST record to the next payload for a given message ID.
func (n *Node) RequestMessage(group state.GroupID, id state.MessageID) error {
peers, err := n.peers.GetByGroupID(group)
if err != nil {
return fmt.Errorf("trying to request from an unknown group %x", group[:4])
}
for _, p := range peers {
exist, err := n.IsPeerInGroup(group, p)
if err != nil {
return err
}
if exist {
continue
}
n.insertSyncState(&group, id, p, state.REQUEST)
}
return nil
}
// AddPeer adds a peer to a specific group making it a recipient of messages.
func (n *Node) AddPeer(group state.GroupID, id state.PeerID) error {
return n.peers.Add(group, id)
}
// IsPeerInGroup checks whether a peer is in the specified group.
func (n *Node) IsPeerInGroup(g state.GroupID, p state.PeerID) (bool, error) {
return n.peers.Exists(g, p)
}
func (n *Node) sendMessages() error {
err := n.syncState.Map(n.epoch, func(s state.State) state.State {
m := s.MessageID
p := s.PeerID
switch s.Type {
case state.OFFER:
n.payloads.AddOffers(p, m[:])
case state.REQUEST:
n.payloads.AddRequests(p, m[:])
log.Printf("sending REQUEST (%x -> %x): %x\n", n.ID[:4], p[:4], m[:4])
case state.MESSAGE:
g := *s.GroupID
// TODO: Handle errors
exist, err := n.IsPeerInGroup(g, p)
if err != nil {
return s
}
if !exist {
return s
}
msg, err := n.store.Get(m)
if err != nil {
log.Printf("failed to retreive message %x %s", m[:4], err.Error())
return s
}
n.payloads.AddMessages(p, msg)
log.Printf("[%x] sending MESSAGE (%x -> %x): %x\n", g[:4], n.ID[:4], p[:4], m[:4])
}
return n.updateSendEpoch(s)
})
if err != nil {
log.Printf("error while mapping sync state: %s", err.Error())
return err
}
return n.payloads.MapAndClear(func(peer state.PeerID, payload protobuf.Payload) error {
err := n.transport.Send(n.ID, peer, payload)
if err != nil {
log.Printf("error sending message: %s", err.Error())
return err
}
return nil
})
}
func (n *Node) onPayload(sender state.PeerID, payload protobuf.Payload) {
// Acks, Requests and Offers are all arrays of bytes as protobuf doesn't allow type aliases otherwise arrays of messageIDs would be nicer.
if err := n.onAck(sender, payload.Acks); err != nil {
log.Printf("error processing acks: %s", err.Error())
}
if err := n.onRequest(sender, payload.Requests); err != nil {
log.Printf("error processing requests: %s", err.Error())
}
if err := n.onOffer(sender, payload.Offers); err != nil {
log.Printf("error processing offers: %s", err.Error())
}
messageIds := n.onMessages(sender, payload.Messages)
n.payloads.AddAcks(sender, messageIds)
}
func (n *Node) onOffer(sender state.PeerID, offers [][]byte) error {
for _, raw := range offers {
id := toMessageID(raw)
log.Printf("OFFER (%x -> %x): %x received.\n", sender[:4], n.ID[:4], id[:4])
exist, err := n.store.Has(id)
// @todo maybe ack?
if err != nil {
return err
}
if exist {
continue
}
n.insertSyncState(nil, id, sender, state.REQUEST)
}
return nil
}
func (n *Node) onRequest(sender state.PeerID, requests [][]byte) error {
for _, raw := range requests {
id := toMessageID(raw)
log.Printf("REQUEST (%x -> %x): %x received.\n", sender[:4], n.ID[:4], id[:4])
message, err := n.store.Get(id)
if err != nil {
return err
}
if message == nil {
log.Printf("message %x does not exist", id[:4])
continue
}
groupID := toGroupID(message.GroupId)
exist, err := n.IsPeerInGroup(groupID, sender)
if err != nil {
return err
}
if !exist {
log.Printf("[%x] peer %x is not in group", groupID, sender[:4])
continue
}
n.insertSyncState(&groupID, id, sender, state.MESSAGE)
}
return nil
}
func (n *Node) onAck(sender state.PeerID, acks [][]byte) error {
for _, ack := range acks {
id := toMessageID(ack)
err := n.syncState.Remove(id, sender)
if err != nil {
log.Printf("error while removing sync state %s", err.Error())
return err
}
log.Printf("ACK (%x -> %x): %x received.\n", sender[:4], n.ID[:4], id[:4])
}
return nil
}
func (n *Node) onMessages(sender state.PeerID, messages []*protobuf.Message) [][]byte {
a := make([][]byte, 0)
for _, m := range messages {
groupID := toGroupID(m.GroupId)
err := n.onMessage(sender, *m)
if err != nil {
log.Printf("Error processing messsage: %+v\n", err)
continue
}
id := m.ID()
log.Printf("[%x] sending ACK (%x -> %x): %x\n", groupID[:4], n.ID[:4], sender[:4], id[:4])
a = append(a, id[:])
}
return a
}
func (n *Node) onMessage(sender state.PeerID, msg protobuf.Message) error {
id := msg.ID()
groupID := toGroupID(msg.GroupId)
log.Printf("MESSAGE (%x -> %x): %x received.\n", sender[:4], n.ID[:4], id[:4])
err := n.syncState.Remove(id, sender)
if err != nil {
return err
}
err = n.store.Add(&msg)
if err != nil {
return err
// @todo process, should this function ever even have an error?
}
peers, err := n.peers.GetByGroupID(groupID)
if err != nil {
return err
}
for _, peer := range peers {
if peer == sender {
continue
}
n.insertSyncState(&groupID, id, peer, state.OFFER)
}
return nil
}
func (n *Node) insertSyncState(groupID *state.GroupID, messageID state.MessageID, peerID state.PeerID, t state.RecordType) {
s := state.State{
GroupID: groupID,
MessageID: messageID,
PeerID: peerID,
Type: t,
SendEpoch: n.epoch + 1,
}
err := n.syncState.Add(s)
if err != nil {
log.Printf("error (%s) setting sync state group: %x id: %x peer: %x", err.Error(), groupID, messageID, peerID)
}
}
func (n *Node) updateSendEpoch(s state.State) state.State {
s.SendCount += 1
s.SendEpoch += n.nextEpoch(s.SendCount, n.epoch)
return s
}
func toMessageID(b []byte) state.MessageID {
var id state.MessageID
copy(id[:], b)
return id
}
func toGroupID(b []byte) state.GroupID {
var id state.GroupID
copy(id[:], b)
return id
}

93
vendor/github.com/vacp2p/mvds/node/payloads.go generated vendored Normal file
View File

@ -0,0 +1,93 @@
package node
import (
"sync"
"github.com/vacp2p/mvds/protobuf"
"github.com/vacp2p/mvds/state"
)
type payloads struct {
sync.Mutex
payloads map[state.PeerID]protobuf.Payload
}
// @todo check in all the functions below that we aren't duplicating stuff
func newPayloads() payloads {
return payloads{
payloads: make(map[state.PeerID]protobuf.Payload),
}
}
func (p *payloads) AddOffers(peer state.PeerID, offers ...[]byte) {
p.Lock()
defer p.Unlock()
payload := p.get(peer)
payload.Offers = append(payload.Offers, offers...)
p.set(peer, payload)
}
func (p *payloads) AddAcks(peer state.PeerID, acks [][]byte) {
p.Lock()
defer p.Unlock()
payload := p.get(peer)
payload.Acks = append(payload.Acks, acks...)
p.set(peer, payload)
}
func (p *payloads) AddRequests(peer state.PeerID, request ...[]byte) {
p.Lock()
defer p.Unlock()
payload := p.get(peer)
payload.Requests = append(payload.Requests, request...)
p.set(peer, payload)
}
func (p *payloads) AddMessages(peer state.PeerID, messages ...*protobuf.Message) {
p.Lock()
defer p.Unlock()
payload := p.get(peer)
if payload.Messages == nil {
payload.Messages = make([]*protobuf.Message, 0)
}
payload.Messages = append(payload.Messages, messages...)
p.set(peer, payload)
}
func (p *payloads) MapAndClear(f func(state.PeerID, protobuf.Payload) error) error {
p.Lock()
defer p.Unlock()
for peer, payload := range p.payloads {
err := f(peer, payload)
if err != nil {
return err
}
}
// TODO: this should only be called upon confirmation that the message has been sent
p.payloads = make(map[state.PeerID]protobuf.Payload)
return nil
}
func (p *payloads) get(peer state.PeerID) protobuf.Payload {
payload, _ := p.payloads[peer]
return payload
}
func (p *payloads) set(peer state.PeerID, payload protobuf.Payload) {
p.payloads[peer] = payload
}

39
vendor/github.com/vacp2p/mvds/peers/persistence.go generated vendored Normal file
View File

@ -0,0 +1,39 @@
package peers
import (
"github.com/vacp2p/mvds/state"
)
type Persistence interface {
Add(state.GroupID, state.PeerID) error
GetByGroupID(group state.GroupID) ([]state.PeerID, error)
Exists(state.GroupID, state.PeerID) (bool, error)
}
type MemoryPersistence struct {
peers map[state.GroupID][]state.PeerID
}
func NewMemoryPersistence() *MemoryPersistence {
return &MemoryPersistence{
peers: make(map[state.GroupID][]state.PeerID),
}
}
func (p *MemoryPersistence) Add(groupID state.GroupID, peerID state.PeerID) error {
p.peers[groupID] = append(p.peers[groupID], peerID)
return nil
}
func (p *MemoryPersistence) Exists(groupID state.GroupID, peerID state.PeerID) (bool, error) {
for _, peer := range p.peers[groupID] {
if peer == peerID {
return true, nil
}
}
return false, nil
}
func (p *MemoryPersistence) GetByGroupID(groupID state.GroupID) ([]state.PeerID, error) {
return p.peers[groupID], nil
}

20
vendor/github.com/vacp2p/mvds/protobuf/messageid.go generated vendored Normal file
View File

@ -0,0 +1,20 @@
package protobuf
import (
"crypto/sha256"
"encoding/binary"
"github.com/vacp2p/mvds/state"
)
// ID creates the MessageID for a Message
func (m Message) ID() state.MessageID {
t := make([]byte, 8)
binary.LittleEndian.PutUint64(t, uint64(m.Timestamp))
b := append([]byte("MESSAGE_ID"), m.GroupId[:]...)
b = append(b, t...)
b = append(b, m.Body...)
return sha256.Sum256(b)
}

7
vendor/github.com/vacp2p/mvds/protobuf/payload.go generated vendored Normal file
View File

@ -0,0 +1,7 @@
package protobuf
// IsValid checks whether there are any known field in the protobuf
// message
func (m *Payload) IsValid() bool {
return len(m.Messages)+len(m.Acks)+len(m.Offers)+len(m.Requests) != 0
}

164
vendor/github.com/vacp2p/mvds/protobuf/sync.pb.go generated vendored Normal file
View File

@ -0,0 +1,164 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: protobuf/sync.proto
package protobuf
import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type Payload struct {
Acks [][]byte `protobuf:"bytes,5001,rep,name=acks,proto3" json:"acks,omitempty"`
Offers [][]byte `protobuf:"bytes,5002,rep,name=offers,proto3" json:"offers,omitempty"`
Requests [][]byte `protobuf:"bytes,5003,rep,name=requests,proto3" json:"requests,omitempty"`
Messages []*Message `protobuf:"bytes,5004,rep,name=messages,proto3" json:"messages,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Payload) Reset() { *m = Payload{} }
func (m *Payload) String() string { return proto.CompactTextString(m) }
func (*Payload) ProtoMessage() {}
func (*Payload) Descriptor() ([]byte, []int) {
return fileDescriptor_2dca527c092c79d7, []int{0}
}
func (m *Payload) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Payload.Unmarshal(m, b)
}
func (m *Payload) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Payload.Marshal(b, m, deterministic)
}
func (m *Payload) XXX_Merge(src proto.Message) {
xxx_messageInfo_Payload.Merge(m, src)
}
func (m *Payload) XXX_Size() int {
return xxx_messageInfo_Payload.Size(m)
}
func (m *Payload) XXX_DiscardUnknown() {
xxx_messageInfo_Payload.DiscardUnknown(m)
}
var xxx_messageInfo_Payload proto.InternalMessageInfo
func (m *Payload) GetAcks() [][]byte {
if m != nil {
return m.Acks
}
return nil
}
func (m *Payload) GetOffers() [][]byte {
if m != nil {
return m.Offers
}
return nil
}
func (m *Payload) GetRequests() [][]byte {
if m != nil {
return m.Requests
}
return nil
}
func (m *Payload) GetMessages() []*Message {
if m != nil {
return m.Messages
}
return nil
}
type Message struct {
GroupId []byte `protobuf:"bytes,6001,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"`
Timestamp int64 `protobuf:"varint,6002,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
Body []byte `protobuf:"bytes,6003,opt,name=body,proto3" json:"body,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Message) Reset() { *m = Message{} }
func (m *Message) String() string { return proto.CompactTextString(m) }
func (*Message) ProtoMessage() {}
func (*Message) Descriptor() ([]byte, []int) {
return fileDescriptor_2dca527c092c79d7, []int{1}
}
func (m *Message) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Message.Unmarshal(m, b)
}
func (m *Message) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Message.Marshal(b, m, deterministic)
}
func (m *Message) XXX_Merge(src proto.Message) {
xxx_messageInfo_Message.Merge(m, src)
}
func (m *Message) XXX_Size() int {
return xxx_messageInfo_Message.Size(m)
}
func (m *Message) XXX_DiscardUnknown() {
xxx_messageInfo_Message.DiscardUnknown(m)
}
var xxx_messageInfo_Message proto.InternalMessageInfo
func (m *Message) GetGroupId() []byte {
if m != nil {
return m.GroupId
}
return nil
}
func (m *Message) GetTimestamp() int64 {
if m != nil {
return m.Timestamp
}
return 0
}
func (m *Message) GetBody() []byte {
if m != nil {
return m.Body
}
return nil
}
func init() {
proto.RegisterType((*Payload)(nil), "mvds.Payload")
proto.RegisterType((*Message)(nil), "mvds.Message")
}
func init() { proto.RegisterFile("protobuf/sync.proto", fileDescriptor_2dca527c092c79d7) }
var fileDescriptor_2dca527c092c79d7 = []byte{
// 215 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x2e, 0x28, 0xca, 0x2f,
0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0xae, 0xcc, 0x4b, 0xd6, 0x03, 0xf3, 0x84, 0x58, 0x72, 0xcb,
0x52, 0x8a, 0x95, 0x1a, 0x18, 0xb9, 0xd8, 0x03, 0x12, 0x2b, 0x73, 0xf2, 0x13, 0x53, 0x84, 0x84,
0xb9, 0x58, 0x12, 0x93, 0xb3, 0x8b, 0x25, 0x3a, 0xd5, 0x15, 0x98, 0x35, 0x78, 0x82, 0xc0, 0x1c,
0x21, 0x71, 0x2e, 0xb6, 0xfc, 0xb4, 0xb4, 0xd4, 0xa2, 0x62, 0x89, 0x2e, 0x88, 0x30, 0x94, 0x2b,
0x24, 0xcd, 0xc5, 0x51, 0x94, 0x5a, 0x58, 0x9a, 0x5a, 0x5c, 0x52, 0x2c, 0xd1, 0x0d, 0x91, 0x82,
0x0b, 0x08, 0x69, 0x71, 0x71, 0xe4, 0xa6, 0x16, 0x17, 0x27, 0xa6, 0xa7, 0x16, 0x4b, 0xf4, 0x80,
0x24, 0xb9, 0x8d, 0x78, 0xf5, 0x40, 0x16, 0xea, 0xf9, 0x42, 0x84, 0x83, 0xe0, 0xf2, 0x4a, 0x91,
0x5c, 0xec, 0x50, 0x41, 0x21, 0x29, 0x2e, 0x8e, 0xf4, 0xa2, 0xfc, 0xd2, 0x82, 0xf8, 0xcc, 0x14,
0x89, 0x8f, 0x7a, 0x0a, 0x8c, 0x1a, 0x3c, 0x41, 0xec, 0x60, 0x01, 0xcf, 0x14, 0x21, 0x59, 0x2e,
0xce, 0x92, 0xcc, 0xdc, 0xd4, 0xe2, 0x92, 0xc4, 0xdc, 0x02, 0x89, 0x4f, 0x20, 0x49, 0xe6, 0x20,
0x84, 0x08, 0xc8, 0xf1, 0x49, 0xf9, 0x29, 0x95, 0x12, 0x9f, 0x21, 0xda, 0xc0, 0x1c, 0x27, 0xae,
0x28, 0x0e, 0x98, 0xd7, 0x93, 0xd8, 0xc0, 0x2c, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x18,
0xdd, 0xc7, 0x8d, 0x0d, 0x01, 0x00, 0x00,
}

17
vendor/github.com/vacp2p/mvds/protobuf/sync.proto generated vendored Normal file
View File

@ -0,0 +1,17 @@
syntax = "proto3";
package mvds;
option go_package = "protobuf";
message Payload {
repeated bytes acks = 5001;
repeated bytes offers = 5002;
repeated bytes requests = 5003;
repeated Message messages = 5004;
}
message Message {
bytes group_id = 6001;
int64 timestamp = 6002;
bytes body = 6003;
}

4
vendor/github.com/vacp2p/mvds/state/peerid.go generated vendored Normal file
View File

@ -0,0 +1,4 @@
package state
// PeerID is the ID for a specific peer.
type PeerID [65]byte

29
vendor/github.com/vacp2p/mvds/state/state.go generated vendored Normal file
View File

@ -0,0 +1,29 @@
// Package state contains everything related to the synchronization state for MVDS.
package state
// RecordType is the type for a specific record, either `OFFER`, `REQUEST` or `MESSAGE`.
type RecordType int
const (
OFFER RecordType = iota
REQUEST
MESSAGE
)
// State is a struct used to store a records [state](https://github.com/status-im/bigbrother-specs/blob/master/data_sync/mvds.md#state).
type State struct {
Type RecordType
SendCount uint64
SendEpoch int64
// GroupID is optional, thus nullable
GroupID *GroupID
PeerID PeerID
MessageID MessageID
}
type SyncState interface {
Add(newState State) error
Remove(id MessageID, peer PeerID) error
All() ([]State, error)
Map(epoch int64, process func(State) State) error
}

61
vendor/github.com/vacp2p/mvds/state/state_memory.go generated vendored Normal file
View File

@ -0,0 +1,61 @@
package state
import (
"sync"
)
type memorySyncState struct {
sync.Mutex
state []State
}
func NewSyncState() *memorySyncState {
return &memorySyncState{}
}
func (s *memorySyncState) Add(newState State) error {
s.Lock()
defer s.Unlock()
s.state = append(s.state, newState)
return nil
}
func (s *memorySyncState) Remove(id MessageID, peer PeerID) error {
s.Lock()
defer s.Unlock()
var newState []State
for _, state := range s.state {
if state.MessageID != id || state.PeerID != peer {
newState = append(newState, state)
}
}
s.state = newState
return nil
}
func (s *memorySyncState) All() ([]State, error) {
s.Lock()
defer s.Unlock()
return s.state, nil
}
func (s *memorySyncState) Map(epoch int64, process func(State) State) error {
s.Lock()
defer s.Unlock()
for i, state := range s.state {
if state.SendEpoch > epoch {
continue
}
s.state[i] = process(state)
}
return nil
}

4
vendor/github.com/vacp2p/mvds/state/sync_types.go generated vendored Normal file
View File

@ -0,0 +1,4 @@
package state
type MessageID [32]byte
type GroupID [32]byte

13
vendor/github.com/vacp2p/mvds/store/messagestore.go generated vendored Normal file
View File

@ -0,0 +1,13 @@
// Package store contains everything storage related for MVDS.
package store
import (
"github.com/vacp2p/mvds/protobuf"
"github.com/vacp2p/mvds/state"
)
type MessageStore interface {
Has(id state.MessageID) (bool, error)
Get(id state.MessageID) (*protobuf.Message, error)
Add(message *protobuf.Message) error
}

View File

@ -0,0 +1,45 @@
package store
import (
"errors"
"sync"
"github.com/vacp2p/mvds/protobuf"
"github.com/vacp2p/mvds/state"
)
type DummyStore struct {
sync.Mutex
ms map[state.MessageID]*protobuf.Message
}
func NewDummyStore() DummyStore {
return DummyStore{ms: make(map[state.MessageID]*protobuf.Message)}
}
func (ds *DummyStore) Has(id state.MessageID) (bool, error) {
ds.Lock()
defer ds.Unlock()
_, ok := ds.ms[id]
return ok, nil
}
func (ds *DummyStore) Get(id state.MessageID) (*protobuf.Message, error) {
ds.Lock()
defer ds.Unlock()
m, ok := ds.ms[id]
if !ok {
return nil, errors.New("message does not exist")
}
return m, nil
}
func (ds *DummyStore) Add(message *protobuf.Message) error {
ds.Lock()
defer ds.Unlock()
ds.ms[message.ID()] = message
return nil
}

View File

@ -0,0 +1,54 @@
package transport
import (
"errors"
math "math/rand"
"sync"
"time"
"github.com/vacp2p/mvds/protobuf"
"github.com/vacp2p/mvds/state"
)
// ChannelTransport implements a basic MVDS transport using channels for basic testing purposes.
type ChannelTransport struct {
sync.Mutex
offline int
in <-chan Packet
out map[state.PeerID]chan<- Packet
}
func NewChannelTransport(offline int, in <-chan Packet) *ChannelTransport {
return &ChannelTransport{
offline: offline,
in: in,
out: make(map[state.PeerID]chan<- Packet),
}
}
func (t *ChannelTransport) AddOutput(id state.PeerID, c chan<- Packet) {
t.out[id] = c
}
func (t *ChannelTransport) Watch() Packet {
return <-t.in
}
func (t *ChannelTransport) Send(sender state.PeerID, peer state.PeerID, payload protobuf.Payload) error {
// @todo we can do this better, we put node onlineness into a goroutine where we just stop the nodes for x seconds
// outside of this class
math.Seed(time.Now().UnixNano())
if math.Intn(100) < t.offline {
return nil
}
c, ok := t.out[peer]
if !ok {
return errors.New("peer unknown")
}
c <- Packet{Sender: sender, Payload: payload}
return nil
}

18
vendor/github.com/vacp2p/mvds/transport/transport.go generated vendored Normal file
View File

@ -0,0 +1,18 @@
// Package transport contains transport related logic for MVDS.
package transport
import (
"github.com/vacp2p/mvds/protobuf"
"github.com/vacp2p/mvds/state"
)
type Packet struct {
Sender state.PeerID
Payload protobuf.Payload
}
// Transport defines an interface allowing for agnostic transport implementations.
type Transport interface {
Watch() Packet
Send(sender state.PeerID, peer state.PeerID, payload protobuf.Payload) error
}

16
vendor/modules.txt vendored
View File

@ -108,7 +108,7 @@ github.com/golang-migrate/migrate/v4/source
github.com/golang-migrate/migrate/v4
# github.com/golang/mock v1.2.0
github.com/golang/mock/gomock
# github.com/golang/protobuf v1.3.1
# github.com/golang/protobuf v1.3.2
github.com/golang/protobuf/proto
github.com/golang/protobuf/protoc-gen-go/descriptor
# github.com/golang/snappy v0.0.1
@ -152,6 +152,8 @@ github.com/jbenet/goprocess
github.com/jbenet/goprocess/context
github.com/jbenet/goprocess/periodic
github.com/jbenet/goprocess/ratelimit
# github.com/jinzhu/copier v0.0.0-20190625015134-976e0346caa8
github.com/jinzhu/copier
# github.com/karalabe/hid v0.0.0-20181128192157-d815e0c1a2e2
github.com/karalabe/hid
# github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b
@ -315,11 +317,13 @@ github.com/status-im/migrate/v4/database/sqlcipher
github.com/status-im/rendezvous
github.com/status-im/rendezvous/protocol
github.com/status-im/rendezvous/server
# github.com/status-im/status-protocol-go v0.1.1
# github.com/status-im/status-protocol-go v0.1.3
github.com/status-im/status-protocol-go
github.com/status-im/status-protocol-go/encryption/multidevice
github.com/status-im/status-protocol-go/sqlite
github.com/status-im/status-protocol-go/transport/whisper/filter
github.com/status-im/status-protocol-go/datasync
github.com/status-im/status-protocol-go/datasync/peer
github.com/status-im/status-protocol-go/encryption
github.com/status-im/status-protocol-go/encryption/sharedsecret
github.com/status-im/status-protocol-go/internal/sqlite
@ -329,6 +333,7 @@ github.com/status-im/status-protocol-go/transport/whisper/internal/sqlite
github.com/status-im/status-protocol-go/crypto
github.com/status-im/status-protocol-go/encryption/internal/sqlite
github.com/status-im/status-protocol-go/encryption/publisher
github.com/status-im/status-protocol-go/applicationmetadata
# github.com/status-im/whisper v1.4.14
github.com/status-im/whisper/whisperv6
# github.com/stretchr/testify v1.3.0
@ -348,6 +353,13 @@ github.com/syndtr/goleveldb/leveldb/filter
github.com/syndtr/goleveldb/leveldb/journal
github.com/syndtr/goleveldb/leveldb/memdb
github.com/syndtr/goleveldb/leveldb/table
# github.com/vacp2p/mvds v0.0.19
github.com/vacp2p/mvds/node
github.com/vacp2p/mvds/peers
github.com/vacp2p/mvds/state
github.com/vacp2p/mvds/store
github.com/vacp2p/mvds/protobuf
github.com/vacp2p/mvds/transport
# github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc
github.com/whyrusleeping/go-logging
# github.com/whyrusleeping/go-notifier v0.0.0-20170827234753-097c5d47330f