Handle messages in raw method as well

This commit is contained in:
Andrea Maria Piana 2019-07-26 16:38:27 +02:00
parent 0a8bf4c10e
commit 28b2244fed
No known key found for this signature in database
GPG Key ID: AA6CCA6DE0E06424
23 changed files with 811 additions and 380 deletions

View File

@ -22,8 +22,6 @@ import (
"github.com/status-im/status-protocol-go/datasync"
datasyncpeer "github.com/status-im/status-protocol-go/datasync/peer"
datasyncproto "github.com/vacp2p/mvds/protobuf"
datasynctransport "github.com/vacp2p/mvds/transport"
)
// Whisper message properties.
@ -149,28 +147,22 @@ func (a *whisperAdapter) handleRetrievedMessages(messages []*whisper.ReceivedMes
shhMessage := whisper.ToWhisperMessage(item)
hlogger := logger.With(zap.Binary("hash", shhMessage.Hash))
hlogger.Debug("handling a received message")
err := a.handleMessageEncryption(context.Background(), shhMessage)
if err != nil {
hlogger.Debug("failed to handle an encryption message", zap.Error(err))
}
statusMessages, err := a.handleDecodedMessages(shhMessage)
statusMessages, err := a.handleMessages(shhMessage, true)
if err != nil {
hlogger.Info("failed to decode messages", zap.Error(err))
continue
}
for _, statusMessage := range statusMessages {
switch m := statusMessage.Message.(type) {
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
@ -194,136 +186,81 @@ func (a *whisperAdapter) handleRetrievedMessages(messages []*whisper.ReceivedMes
}
// 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.handleMessageEncryption(context.Background(), shhMessage)
statusMessages, err := a.handleMessages(shhMessage, false)
if err != nil {
logger.Warn("failed to handle an encryption message", zap.Error(err), zap.Binary("messageID", shhMessage.Hash))
}
result[chat] = append(result[chat], shhMessage)
}
}
return result, nil
}
// DEPRECATED
func (a *whisperAdapter) RetrieveRaw(filterID string) ([]*whisper.Message, error) {
messages, err := a.transport.RetrieveRaw(filterID)
if err != nil {
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.handleMessageEncryption(context.Background(), shhMessage)
if err != nil {
logger.Warn("failed to handle an encryption message", zap.Error(err), zap.Binary("messageID", shhMessage.Hash))
}
result = append(result, shhMessage)
}
return result, nil
}
func (a *whisperAdapter) addDatasyncPacket(publicKey *ecdsa.PublicKey, datasyncMessage datasyncproto.Payload) {
packet := datasynctransport.Packet{
Sender: datasyncpeer.PublicKeyToPeerID(*publicKey),
Payload: datasyncMessage,
}
a.datasync.AddPacket(packet)
}
// handleDecodedMessages expects an unencrypted whisper message as it's argument.
// 1) Check if it's a datasync message
// 2) If it's a datasync message it will handle each transmitted message separately
// 3) if it's not a datasync message a single message will be handled
// Fingerprinting datasync messages is a bit tricky, as they might unmarshal fine
// because they are wrapped messages, so we need to check whether anything is
// poulated in the fields.
func (a *whisperAdapter) handleDecodedMessages(message *whisper.Message) ([]*protocol.StatusMessage, error) {
var decodedMessages []*protocol.StatusMessage
logger := a.logger.With(zap.String("site", "decodeMessages"))
hlogger := logger.With(zap.Binary("hash", message.Hash))
publicKey, err := crypto.UnmarshalPubkey(message.Sig)
if err != nil {
return nil, err
}
// Try first with datasync
datasyncMessage, err := protocol.UnwrapDatasync(message.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() {
hlogger.Debug("Handling non-datasync message")
// Not a datasync message
decodedMessage, err := protocol.DecodeMessage(publicKey, message.Payload)
if err != nil {
return nil, err
}
decodedMessages = append(decodedMessages, &decodedMessage)
} else {
hlogger.Debug("Handling datasync message")
// datasync message
for _, message := range datasyncMessage.Messages {
decodedMessage, err := protocol.DecodeMessage(publicKey, message.Body)
if err != nil {
hlogger.Error("failed to decode messages", zap.Error(err))
// Log and continue
logger.Info("failed to decode messages", zap.Error(err))
continue
}
// Addpacket to datasync if enabled
decodedMessages = append(decodedMessages, &decodedMessage)
}
if a.featureFlags.datasync {
a.addDatasyncPacket(publicKey, datasyncMessage)
}
result[chat] = append(result[chat], statusMessages...)
}
}
return decodedMessages, nil
return result, nil
}
func (a *whisperAdapter) handleMessageEncryption(ctx context.Context, message *whisper.Message) error {
publicKey, err := crypto.UnmarshalPubkey(message.Sig)
// 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 {
return errors.Wrap(err, "failed to get signature")
hlogger.Error("failed to handle transport layer message", zap.Error(err))
return nil, err
}
var protocolMessage encryption.ProtocolMessage
err = proto.Unmarshal(message.Payload, &protocolMessage)
err = a.handleEncryptionLayer(context.Background(), &statusMessage)
if err != nil {
return errors.Wrap(err, "failed to unmarshal ProtocolMessage")
hlogger.Debug("failed to handle an encryption message", zap.Error(err))
}
logger := a.logger.With(zap.String("site", "decryptMessage"))
statusMessages, err := statusMessage.HandleDatasync(a.datasync)
if err != nil {
hlogger.Debug("failed to handle datasync message", zap.Error(err))
payload, err := a.protocol.HandleMessage(
a.privateKey,
publicKey,
&protocolMessage,
message.Hash,
)
}
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) handleEncryptionLayer(ctx context.Context, message *protocol.StatusMessage) error {
publicKey := message.SigPubKey()
logger := a.logger.With(zap.String("site", "handleEncryptionLayer"))
err := message.HandleEncryption(a.privateKey, publicKey, a.protocol)
if err == encryption.ErrDeviceNotFound {
handleErr := a.handleErrDeviceNotFound(ctx, publicKey)
if handleErr != nil {
@ -334,9 +271,7 @@ func (a *whisperAdapter) handleMessageEncryption(ctx context.Context, message *w
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 {

View File

@ -121,10 +121,7 @@ func (s *AdaptersSuite) SetupTest() {
datasyncpeers.NewMemoryPersistence(),
)
datasync := &datasync.DataSync{
Node: dataSyncNode,
DataSyncNodeTransport: dataSyncTransport,
}
datasync := datasync.New(dataSyncNode, dataSyncTransport, true, logger)
s.a = newWhisperAdapter(
s.privateKey,
@ -150,20 +147,38 @@ func (s *AdaptersSuite) TestHandleDecodedMessagesSingle() {
message.Sig = crypto.FromECDSAPub(&privateKey.PublicKey)
message.Payload = encodedPayload
decodedMessage, err := s.a.handleDecodedMessages(message)
decodedMessages, err := s.a.handleMessages(message, true)
s.Require().NoError(err)
expected := []*protocol.StatusMessage{
&protocol.StatusMessage{
ID: protocol.MessageID(&privateKey.PublicKey, encodedPayload),
SigPubKey: &privateKey.PublicKey,
Message: testMessageStruct,
},
}
s.Require().Equal(expected, decodedMessage)
s.Require().Equal(1, len(decodedMessages))
s.Require().Equal(encodedPayload, decodedMessages[0].DecryptedPayload)
s.Require().Equal(&privateKey.PublicKey, decodedMessages[0].SigPubKey())
s.Require().Equal(protocol.MessageID(&privateKey.PublicKey, encodedPayload), decodedMessages[0].ID)
s.Require().Equal(testMessageStruct, decodedMessages[0].ParsedMessage)
}
func (s *AdaptersSuite) TestHandleDecodedMessagesRaw() {
privateKey, err := crypto.GenerateKey()
s.Require().NoError(err)
encodedPayload, err := protocol.EncodeMessage(testMessageStruct)
s.Require().NoError(err)
message := &whisper.Message{}
message.Sig = crypto.FromECDSAPub(&privateKey.PublicKey)
message.Payload = encodedPayload
decodedMessages, err := s.a.handleMessages(message, false)
s.Require().NoError(err)
s.Require().Equal(1, len(decodedMessages))
s.Require().Equal(message, decodedMessages[0].TransportMessage)
s.Require().Equal(encodedPayload, decodedMessages[0].DecryptedPayload)
s.Require().Equal(&privateKey.PublicKey, decodedMessages[0].SigPubKey())
s.Require().Equal(protocol.MessageID(&privateKey.PublicKey, encodedPayload), decodedMessages[0].ID)
s.Require().Equal(nil, decodedMessages[0].ParsedMessage)
}
func (s *AdaptersSuite) TestHandleDecodedMessagesWrapped() {
relayerKey, err := crypto.GenerateKey()
s.Require().NoError(err)
@ -180,16 +195,14 @@ func (s *AdaptersSuite) TestHandleDecodedMessagesWrapped() {
message.Sig = crypto.FromECDSAPub(&relayerKey.PublicKey)
message.Payload = wrappedPayload
decodedMessage, err := s.a.handleDecodedMessages(message)
decodedMessages, err := s.a.handleMessages(message, true)
s.Require().NoError(err)
expected := []*protocol.StatusMessage{
&protocol.StatusMessage{
ID: protocol.MessageID(&authorKey.PublicKey, encodedPayload),
SigPubKey: &authorKey.PublicKey,
Message: testMessageStruct,
},
}
s.Require().Equal(expected, decodedMessage)
s.Require().Equal(1, len(decodedMessages))
s.Require().Equal(&authorKey.PublicKey, decodedMessages[0].SigPubKey())
s.Require().Equal(protocol.MessageID(&authorKey.PublicKey, encodedPayload), decodedMessages[0].ID)
s.Require().Equal(encodedPayload, decodedMessages[0].DecryptedPayload)
s.Require().Equal(testMessageStruct, decodedMessages[0].ParsedMessage)
}
func (s *AdaptersSuite) TestHandleDecodedMessagesDatasync() {
@ -218,24 +231,20 @@ func (s *AdaptersSuite) TestHandleDecodedMessagesDatasync() {
message.Sig = crypto.FromECDSAPub(&relayerKey.PublicKey)
message.Payload = marshalledDataSyncMessage
decodedMessage, err := s.a.handleDecodedMessages(message)
decodedMessages, err := s.a.handleMessages(message, true)
s.Require().NoError(err)
// We send two messages, the unwrapped one will be attributed to the relayer, while the wrapped one will be attributed to the author
expected := []*protocol.StatusMessage{
&protocol.StatusMessage{
ID: protocol.MessageID(&relayerKey.PublicKey, encodedPayload),
SigPubKey: &relayerKey.PublicKey,
Message: testMessageStruct,
},
s.Require().Equal(2, len(decodedMessages))
s.Require().Equal(&relayerKey.PublicKey, decodedMessages[0].SigPubKey())
s.Require().Equal(protocol.MessageID(&relayerKey.PublicKey, encodedPayload), decodedMessages[0].ID)
s.Require().Equal(encodedPayload, decodedMessages[0].DecryptedPayload)
s.Require().Equal(testMessageStruct, decodedMessages[0].ParsedMessage)
&protocol.StatusMessage{
ID: protocol.MessageID(&authorKey.PublicKey, encodedPayload),
SigPubKey: &authorKey.PublicKey,
Message: testMessageStruct,
},
}
s.Require().Equal(expected, decodedMessage)
s.Require().Equal(&authorKey.PublicKey, decodedMessages[1].SigPubKey())
s.Require().Equal(protocol.MessageID(&authorKey.PublicKey, encodedPayload), decodedMessages[1].ID)
s.Require().Equal(encodedPayload, decodedMessages[1].DecryptedPayload)
s.Require().Equal(testMessageStruct, decodedMessages[1].ParsedMessage)
}
func (s *AdaptersSuite) TearDownTest() {

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

@ -1,8 +1,8 @@
syntax = "proto3";
package statusproto;
package applicationmetadata;
message StatusProtocolMessage {
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

@ -1,11 +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

@ -100,7 +100,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(1563295136, 0)}
info := bindataFileInfo{name: "1536754952_initial_schema.down.sql", size: 83, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 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
}
@ -120,7 +120,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(1563295136, 0)}
info := bindataFileInfo{name: "1536754952_initial_schema.up.sql", size: 962, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 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
}
@ -140,7 +140,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(1563295136, 0)}
info := bindataFileInfo{name: "1539249977_update_ratchet_info.down.sql", size: 311, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 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
}
@ -160,7 +160,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(1563295136, 0)}
info := bindataFileInfo{name: "1539249977_update_ratchet_info.up.sql", size: 368, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 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
}
@ -180,7 +180,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(1563295136, 0)}
info := bindataFileInfo{name: "1540715431_add_version.down.sql", size: 127, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 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
}
@ -200,7 +200,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(1563295136, 0)}
info := bindataFileInfo{name: "1540715431_add_version.up.sql", size: 265, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 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
}
@ -220,7 +220,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(1563295136, 0)}
info := bindataFileInfo{name: "1541164797_add_installations.down.sql", size: 26, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 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
}
@ -240,7 +240,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(1563295136, 0)}
info := bindataFileInfo{name: "1541164797_add_installations.up.sql", size: 216, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 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
}
@ -260,7 +260,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(1563295136, 0)}
info := bindataFileInfo{name: "1558084410_add_secret.down.sql", size: 56, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 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
}
@ -280,7 +280,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(1563295136, 0)}
info := bindataFileInfo{name: "1558084410_add_secret.up.sql", size: 301, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 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
}
@ -300,7 +300,7 @@ func _1558588866_add_versionDownSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1558588866_add_version.down.sql", size: 47, mode: os.FileMode(0644), modTime: time.Unix(1564125878, 0)}
info := bindataFileInfo{name: "1558588866_add_version.down.sql", size: 47, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xde, 0x52, 0x34, 0x3c, 0x46, 0x4a, 0xf0, 0x72, 0x47, 0x6f, 0x49, 0x5c, 0xc7, 0xf9, 0x32, 0xce, 0xc4, 0x3d, 0xfd, 0x61, 0xa1, 0x8b, 0x8f, 0xf2, 0x31, 0x34, 0xde, 0x15, 0x49, 0xa6, 0xde, 0xb9}}
return a, nil
}
@ -320,7 +320,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(1564125858, 0)}
info := bindataFileInfo{name: "1558588866_add_version.up.sql", size: 57, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 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
}
@ -340,7 +340,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(1563295136, 0)}
info := bindataFileInfo{name: "1559627659_add_contact_code.down.sql", size: 32, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 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
}
@ -360,7 +360,7 @@ 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(1563295136, 0)}
info := bindataFileInfo{name: "1559627659_add_contact_code.up.sql", size: 198, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 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
}
@ -380,7 +380,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(1563295136, 0)}
info := bindataFileInfo{name: "1561368210_add_installation_metadata.down.sql", size: 35, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 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
}
@ -400,7 +400,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(1563295136, 0)}
info := bindataFileInfo{name: "1561368210_add_installation_metadata.up.sql", size: 267, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 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
}
@ -420,7 +420,7 @@ func docGo() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "doc.go", size: 377, mode: os.FileMode(0644), modTime: time.Unix(1564131660, 0)}
info := bindataFileInfo{name: "doc.go", size: 377, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xef, 0xaf, 0xdf, 0xcf, 0x65, 0xae, 0x19, 0xfc, 0x9d, 0x29, 0xc1, 0x91, 0xaf, 0xb5, 0xd5, 0xb1, 0x56, 0xf3, 0xee, 0xa8, 0xba, 0x13, 0x65, 0xdb, 0xab, 0xcf, 0x4e, 0xac, 0x92, 0xe9, 0x60, 0xf1}}
return a, nil
}

1
go.mod
View File

@ -7,6 +7,7 @@ require (
github.com/deckarep/golang-set v1.7.1 // indirect
github.com/ethereum/go-ethereum v1.8.27
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

2
go.sum
View File

@ -187,6 +187,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=

View File

@ -269,10 +269,7 @@ func NewMessenger(
datasyncnode.BATCH,
datasyncpeers.NewMemoryPersistence(),
)
datasync := &datasync.DataSync{
Node: dataSyncNode,
DataSyncNodeTransport: dataSyncTransport,
}
datasync := datasync.New(dataSyncNode, dataSyncTransport, c.featureFlags.datasync, logger)
adapter := newWhisperAdapter(identity, t, encryptionProtocol, datasync, c.featureFlags, logger)
@ -287,7 +284,7 @@ func NewMessenger(
shutdownTasks: []func() error{
database.Close,
adapter.transport.Reset,
func() error { datasync.Node.Stop(); return nil },
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 },
@ -557,15 +554,10 @@ func (m *Messenger) retrieveSaved(ctx context.Context, chatID string, c Retrieve
}
// 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

@ -86,7 +86,7 @@ func _000001_initDownDbSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "000001_init.down.db.sql", size: 82, mode: os.FileMode(0644), modTime: time.Unix(1563295136, 0)}
info := bindataFileInfo{name: "000001_init.down.db.sql", size: 82, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 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
}
@ -106,7 +106,7 @@ func _000001_initUpDbSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "000001_init.up.db.sql", size: 840, mode: os.FileMode(0644), modTime: time.Unix(1563295136, 0)}
info := bindataFileInfo{name: "000001_init.up.db.sql", size: 840, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 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
}
@ -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(1564131679, 0)}
info := bindataFileInfo{name: "doc.go", size: 377, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xef, 0xaf, 0xdf, 0xcf, 0x65, 0xae, 0x19, 0xfc, 0x9d, 0x29, 0xc1, 0x91, 0xaf, 0xb5, 0xd5, 0xb1, 0x56, 0xf3, 0xee, 0xa8, 0xba, 0x13, 0x65, 0xdb, 0xab, 0xcf, 0x4e, 0xac, 0x92, 0xe9, 0x60, 0xf1}}
return a, nil
}

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(1563295136, 0)}
info := bindataFileInfo{name: "1561059285_add_whisper_keys.down.sql", size: 25, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 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(1563295136, 0)}
info := bindataFileInfo{name: "1561059285_add_whisper_keys.up.sql", size: 112, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 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: 373, mode: os.FileMode(0644), modTime: time.Unix(1564131660, 0)}
info := bindataFileInfo{name: "doc.go", size: 373, mode: os.FileMode(0644), modTime: time.Unix(1564400388, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x23, 0x6a, 0xc1, 0xce, 0x94, 0xf6, 0xef, 0xf1, 0x97, 0x95, 0xb, 0x35, 0xaf, 0x5f, 0xe7, 0x5f, 0xac, 0x6e, 0xb8, 0xab, 0xba, 0xb5, 0x35, 0x97, 0x22, 0x36, 0x11, 0xce, 0x44, 0xfc, 0xfa, 0xac}}
return a, nil
}

View File

@ -5,17 +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"
datasyncprotobuf "github.com/vacp2p/mvds/protobuf"
"log"
"strings"
"time"
)
//go:generate protoc --go_out=. ./message.proto
const (
// ContentTypeTextPlain means that the message contains plain text.
ContentTypeTextPlain = "text/plain"
@ -68,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?
@ -117,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))
@ -147,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 {
@ -166,47 +134,6 @@ func decodeTransitMessage(data []byte) (interface{}, error) {
return value, nil
}
func UnwrapDatasync(payload []byte) (datasyncPayload datasyncprotobuf.Payload, err error) {
err = proto.Unmarshal(payload, &datasyncPayload)
return
}
// 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

@ -20,24 +20,14 @@ var (
}
)
func TestDecodeMessage(t *testing.T) {
key, err := crypto.GenerateKey()
func TestDecodeTransitMessage(t *testing.T) {
val, err := decodeTransitMessage(testMessageBytes)
require.NoError(t, err)
val, err := DecodeMessage(&key.PublicKey, testMessageBytes)
require.NoError(t, err)
require.EqualValues(t, StatusMessage{
Message: testMessageStruct,
SigPubKey: &key.PublicKey,
ID: MessageID(&key.PublicKey, testMessageBytes),
}, val)
require.EqualValues(t, testMessageStruct, val)
}
func BenchmarkDecodeMessage(b *testing.B) {
key, err := crypto.GenerateKey()
require.NoError(b, err)
_, err = DecodeMessage(&key.PublicKey, testMessageBytes)
func BenchmarkDecodeTransitMessage(b *testing.B) {
_, err := decodeTransitMessage(testMessageBytes)
if err != nil {
b.Fatalf("failed to decode message: %v", err)
}
@ -45,67 +35,16 @@ func BenchmarkDecodeMessage(b *testing.B) {
b.ResetTimer()
for n := 0; n < b.N; n++ {
_, _ = DecodeMessage(&key.PublicKey, testMessageBytes)
_, _ = decodeTransitMessage(testMessageBytes)
}
}
func TestEncodeMessage(t *testing.T) {
key, err := crypto.GenerateKey()
require.NoError(t, err)
data, err := EncodeMessage(testMessageStruct)
require.NoError(t, err)
require.NoError(b, err)
// Decode it back to a struct because, for example, map encoding is non-deterministic
// and it is not possible to compare bytes.
val, err := DecodeMessage(&key.PublicKey, data)
require.NoError(t, err)
require.EqualValues(t, StatusMessage{
Message: testMessageStruct,
SigPubKey: &key.PublicKey,
ID: MessageID(&key.PublicKey, data),
}, val)
}
func TestWrappedMessageWithSignature(t *testing.T) {
key, err := crypto.GenerateKey()
require.NoError(t, err)
transportKey, err := crypto.GenerateKey()
require.NoError(t, err)
data, err := EncodeMessage(testMessageStruct)
require.NoError(t, err)
wrappedMessage, err := WrapMessageV1(data, key)
require.NoError(t, err)
// Decode it back to a struct because, for example, map encoding is non-deterministic
// and it is not possible to compare bytes.
val, err := DecodeMessage(&transportKey.PublicKey, wrappedMessage)
require.NoError(t, err)
require.EqualValues(t, StatusMessage{
Message: testMessageStruct,
ID: MessageID(&key.PublicKey, data),
SigPubKey: &key.PublicKey,
}, val)
}
func TestWrappedMessageWithoutSignature(t *testing.T) {
key, err := crypto.GenerateKey()
require.NoError(t, err)
data, err := EncodeMessage(testMessageStruct)
require.NoError(t, err)
wrappedMessage, err := WrapMessageV1(data, nil)
require.NoError(t, err)
// Decode it back to a struct because, for example, map encoding is non-deterministic
// and it is not possible to compare bytes.
val, err := DecodeMessage(&key.PublicKey, wrappedMessage)
require.NoError(t, err)
require.EqualValues(t, StatusMessage{
Message: testMessageStruct,
SigPubKey: &key.PublicKey,
ID: MessageID(&key.PublicKey, data),
}, val)
val, err := decodeTransitMessage(data)
require.NoError(b, err)
require.EqualValues(b, testMessageStruct, val)
}
func TestMessageID(t *testing.T) {
@ -119,24 +58,6 @@ func TestMessageID(t *testing.T) {
require.Equal(t, expectedID, MessageID(&key.PublicKey, data))
}
func TestMessageWrongPublicKey(t *testing.T) {
key, err := crypto.GenerateKey()
require.NoError(t, err)
wrongKey, err := crypto.GenerateKey()
require.NoError(t, err)
data, err := EncodeMessage(testMessageStruct)
require.NoError(t, err)
wrappedMessage, err := WrapMessageV1(data, key)
require.NoError(t, err)
// Decode it back to a struct because, for example, map encoding is non-deterministic
// and it is not possible to compare bytes.
val, err := DecodeMessage(&key.PublicKey, wrappedMessage)
require.NoError(t, err)
require.NotEqual(t, val.ID, MessageID(&wrongKey.PublicKey, data), val)
}
func TestTimestampInMs(t *testing.T) {
ts := TimestampInMs(1555274502548) // random timestamp in milliseconds
tt := ts.Time()

View File

@ -3,7 +3,6 @@ package statusproto
import (
"testing"
"github.com/ethereum/go-ethereum/crypto"
"github.com/stretchr/testify/require"
)
@ -18,31 +17,17 @@ var (
)
func TestDecodePairMessageMessage(t *testing.T) {
key, err := crypto.GenerateKey()
val, err := decodeTransitMessage(testPairMessageBytes)
require.NoError(t, err)
val, err := DecodeMessage(&key.PublicKey, testPairMessageBytes)
require.NoError(t, err)
require.EqualValues(t, StatusMessage{
Message: testPairMessageStruct,
SigPubKey: &key.PublicKey,
ID: MessageID(&key.PublicKey, testPairMessageBytes),
}, val)
require.EqualValues(t, testPairMessageStruct, val)
}
func TestEncodePairMessage(t *testing.T) {
key, err := crypto.GenerateKey()
require.NoError(t, err)
data, err := EncodePairMessage(testPairMessageStruct)
require.NoError(t, err)
// Decode it back to a struct because, for example, map encoding is non-deterministic
// and it is not possible to compare bytes.
val, err := DecodeMessage(&key.PublicKey, data)
val, err := decodeTransitMessage(data)
require.NoError(t, err)
require.EqualValues(t, StatusMessage{
Message: testPairMessageStruct,
SigPubKey: &key.PublicKey,
ID: MessageID(&key.PublicKey, data),
}, val)
require.EqualValues(t, testPairMessageStruct, val)
}

142
v1/status_message.go Normal file
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
}

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 ./...

2
vendor/modules.txt vendored
View File

@ -57,6 +57,8 @@ github.com/huin/goupnp/soap
github.com/huin/goupnp/ssdp
# github.com/jackpal/go-nat-pmp v1.0.1
github.com/jackpal/go-nat-pmp
# github.com/jinzhu/copier v0.0.0-20190625015134-976e0346caa8
github.com/jinzhu/copier
# github.com/leodido/go-urn v1.1.0
github.com/leodido/go-urn
# github.com/lib/pq v1.0.0