Refactored BasePayloadReceiver to handle Receive()

Additionally to allow this process flow I refactored RawMessagePayloadReceiver and InstallationPayloadHandler to use a dedicated Marshaller type. Also added a fix to struct extention functionality, we want to ignore the process if there is no public key because that will key encoding. Seems an unnecessary bug to have to handle when you know there is no key.
This commit is contained in:
Samuel Hawksby-Robinson 2023-04-03 00:08:29 +01:00
parent 44a1379fbe
commit 465afd0131
13 changed files with 222 additions and 237 deletions

View File

@ -1 +1 @@
0.142.5 0.142.6

View File

@ -28,6 +28,11 @@ func getPubKeyData(publicKey string) (*PublicKeyData, error) {
} }
func ExtendStructWithPubKeyData(publicKey string, item any) (any, error) { func ExtendStructWithPubKeyData(publicKey string, item any) (any, error) {
// If the public key is empty, do not attempt to extend the incoming item
if publicKey == "" {
return item, nil
}
pkd, err := getPubKeyData(publicKey) pkd, err := getPubKeyData(publicKey)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -2,6 +2,7 @@ package settings
import ( import (
"encoding/json" "encoding/json"
"reflect"
accountJson "github.com/status-im/status-go/account/json" accountJson "github.com/status-im/status-go/account/json"
"github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/eth-node/types"
@ -200,3 +201,8 @@ func (s Settings) MarshalJSON() ([]byte, error) {
} }
return json.Marshal(ext) return json.Marshal(ext)
} }
func (s Settings) IsEmpty() bool {
empty := reflect.Zero(reflect.TypeOf(s)).Interface()
return reflect.DeepEqual(s, empty)
}

View File

@ -111,7 +111,7 @@ type SenderClient struct {
*BaseClient *BaseClient
accountMounter PayloadMounter accountMounter PayloadMounter
rawMessageMounter PayloadMounter rawMessageMounter PayloadMounter
installationMounter *InstallationPayloadMounterReceiver installationMounter PayloadMounterReceiver
} }
// NewSenderClient returns a fully qualified SenderClient created with the incoming parameters // NewSenderClient returns a fully qualified SenderClient created with the incoming parameters
@ -284,8 +284,8 @@ type ReceiverClient struct {
*BaseClient *BaseClient
accountReceiver PayloadReceiver accountReceiver PayloadReceiver
rawMessageReceiver *RawMessagePayloadReceiver rawMessageReceiver PayloadReceiver
installationReceiver *InstallationPayloadMounterReceiver installationReceiver PayloadMounterReceiver
} }
// NewReceiverClient returns a fully qualified ReceiverClient created with the incoming parameters // NewReceiverClient returns a fully qualified ReceiverClient created with the incoming parameters

View File

@ -25,6 +25,10 @@ type PayloadLocker interface {
LockPayload() LockPayload()
} }
// TODO if this interface only gets a logger, then maybe remove the interface and change consuming function params
// to accept a *zap.logger
// https://github.com/status-im/status-go/issues/3370
type HandlerServer interface { type HandlerServer interface {
GetLogger() *zap.Logger GetLogger() *zap.Logger
} }

View File

@ -17,9 +17,6 @@ func (ep *EncryptionPayload) lock() {
ep.locked = true ep.locked = true
} }
// TODO resolve the many cases of other structs simply wrapping their encryptor rather than embedding the functionality
// https://github.com/status-im/status-go/issues/3302
// PayloadEncryptor is responsible for encrypting and decrypting payload data // PayloadEncryptor is responsible for encrypting and decrypting payload data
type PayloadEncryptor struct { type PayloadEncryptor struct {
aesKey []byte aesKey []byte
@ -93,6 +90,7 @@ func (pem *PayloadEncryptor) lockPayload() {
pem.payload.lock() pem.payload.lock()
} }
// PayloadLockPayload Embeds a *PayloadEncryptor to give all embedding structs EncryptionPayload Locking
type PayloadLockPayload struct { type PayloadLockPayload struct {
*PayloadEncryptor *PayloadEncryptor
} }
@ -101,6 +99,8 @@ func (pl *PayloadLockPayload) LockPayload() {
pl.lockPayload() pl.lockPayload()
} }
// PayloadToSend Embeds a *PayloadEncryptor to give all embedding structs EncryptionPayload ToSend() functionality
// Useful to securely implement the PayloadMounter interface
type PayloadToSend struct { type PayloadToSend struct {
*PayloadEncryptor *PayloadEncryptor
} }
@ -109,6 +109,8 @@ func (pts *PayloadToSend) ToSend() []byte {
return pts.getEncrypted() return pts.getEncrypted()
} }
// PayloadReceived Embeds a *PayloadEncryptor to give all embedding structs EncryptionPayload Received() functionality
// Useful to securely implement the PayloadReceiver interface
type PayloadReceived struct { type PayloadReceived struct {
*PayloadEncryptor *PayloadEncryptor
} }

View File

@ -1,6 +1,7 @@
package pairing package pairing
import ( import (
"encoding/json"
"errors" "errors"
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
@ -8,15 +9,14 @@ import (
"github.com/status-im/status-go/api" "github.com/status-im/status-go/api"
"github.com/status-im/status-go/multiaccounts" "github.com/status-im/status-go/multiaccounts"
"github.com/status-im/status-go/multiaccounts/accounts"
"github.com/status-im/status-go/multiaccounts/settings"
"github.com/status-im/status-go/protocol/protobuf" "github.com/status-im/status-go/protocol/protobuf"
) )
const keystoreDir = "keystore" const keystoreDir = "keystore"
var ( var (
// TODO add validation on config to ensure required fields have valid values
// https://github.com/status-im/status-go/issues/3303
ErrKeyFileAlreadyExists = errors.New("key file already exists") ErrKeyFileAlreadyExists = errors.New("key file already exists")
ErrKeyUIDEmptyAsSender = errors.New("keyUID must be provided as sender") ErrKeyUIDEmptyAsSender = errors.New("keyUID must be provided as sender")
ErrNodeConfigNilAsReceiver = errors.New("node config must be provided as receiver") ErrNodeConfigNilAsReceiver = errors.New("node config must be provided as receiver")
@ -103,36 +103,86 @@ func (ppm *AccountPayloadMarshaller) multiaccountFromProtobuf(pbMultiAccount *pr
ppm.multiaccount.FromProtobuf(pbMultiAccount) ppm.multiaccount.FromProtobuf(pbMultiAccount)
} }
// RawMessagePayloadMarshaller is responsible for marshalling and unmarshalling raw message data type RawMessagesPayload struct {
type RawMessagePayloadMarshaller struct { rawMessages []*protobuf.RawMessage
payload *protobuf.SyncRawMessage subAccounts []*accounts.Account
setting *settings.Settings
} }
func NewRawMessagePayloadMarshaller(payload *protobuf.SyncRawMessage) *RawMessagePayloadMarshaller { func NewRawMessagesPayload() *RawMessagesPayload {
return &RawMessagesPayload{
setting: new(settings.Settings),
}
}
// RawMessagePayloadMarshaller is responsible for marshalling and unmarshalling raw message data
type RawMessagePayloadMarshaller struct {
payload *RawMessagesPayload
}
func NewRawMessagePayloadMarshaller(payload *RawMessagesPayload) *RawMessagePayloadMarshaller {
return &RawMessagePayloadMarshaller{ return &RawMessagePayloadMarshaller{
payload: payload, payload: payload,
} }
} }
func (rmm *RawMessagePayloadMarshaller) MarshalProtobuf() ([]byte, error) { func (rmm *RawMessagePayloadMarshaller) MarshalProtobuf() (data []byte, err error) {
return proto.Marshal(rmm.payload) syncRawMessage := new(protobuf.SyncRawMessage)
syncRawMessage.RawMessages = rmm.payload.rawMessages
if len(rmm.payload.subAccounts) > 0 {
syncRawMessage.SubAccountsJsonBytes, err = json.Marshal(rmm.payload.subAccounts)
if err != nil {
return nil, err
}
}
if !rmm.payload.setting.IsEmpty() {
syncRawMessage.SettingsJsonBytes, err = json.Marshal(rmm.payload.setting)
if err != nil {
return nil, err
}
}
return proto.Marshal(syncRawMessage)
}
func (rmm *RawMessagePayloadMarshaller) UnmarshalProtobuf(data []byte) error {
syncRawMessage := new(protobuf.SyncRawMessage)
err := proto.Unmarshal(data, syncRawMessage)
if err != nil {
return err
}
if syncRawMessage.SubAccountsJsonBytes != nil {
err = json.Unmarshal(syncRawMessage.SubAccountsJsonBytes, &rmm.payload.subAccounts)
if err != nil {
return err
}
}
if syncRawMessage.SettingsJsonBytes != nil {
err = json.Unmarshal(syncRawMessage.SettingsJsonBytes, rmm.payload.setting)
if err != nil {
return err
}
}
rmm.payload.rawMessages = syncRawMessage.RawMessages
return nil
} }
// InstallationPayloadMounterReceiver represents an InstallationPayload Repository // InstallationPayloadMounterReceiver represents an InstallationPayload Repository
type InstallationPayloadMounterReceiver struct { type InstallationPayloadMounterReceiver struct {
PayloadMounter PayloadMounter
*InstallationPayloadReceiver PayloadReceiver
} }
func NewInstallationPayloadMounterReceiver(logger *zap.Logger, encryptor *PayloadEncryptor, backend *api.GethStatusBackend, deviceType string) *InstallationPayloadMounterReceiver { func NewInstallationPayloadMounterReceiver(encryptor *PayloadEncryptor, backend *api.GethStatusBackend, deviceType string) *InstallationPayloadMounterReceiver {
l := logger.Named("InstallationPayloadMounterReceiver")
return &InstallationPayloadMounterReceiver{ return &InstallationPayloadMounterReceiver{
NewInstallationPayloadMounter(l, encryptor, backend, deviceType), NewInstallationPayloadMounter(encryptor, backend, deviceType),
NewInstallationPayloadReceiver(l, encryptor, backend, deviceType), NewInstallationPayloadReceiver(encryptor, backend, deviceType),
} }
} }
func (i *InstallationPayloadMounterReceiver) LockPayload() { func (i *InstallationPayloadMounterReceiver) LockPayload() {
i.PayloadMounter.LockPayload() i.PayloadMounter.LockPayload()
i.InstallationPayloadReceiver.LockPayload() i.PayloadReceiver.LockPayload()
} }

View File

@ -5,7 +5,6 @@ import (
"github.com/status-im/status-go/api" "github.com/status-im/status-go/api"
"github.com/status-im/status-go/multiaccounts" "github.com/status-im/status-go/multiaccounts"
"github.com/status-im/status-go/protocol/protobuf"
) )
type PayloadMounter interface { type PayloadMounter interface {
@ -26,29 +25,29 @@ type BasePayloadMounter struct {
*PayloadLockPayload *PayloadLockPayload
*PayloadToSend *PayloadToSend
payloadLoader PayloadLoader loader PayloadLoader
payloadMarshaller ProtobufMarshaller marshaller ProtobufMarshaller
encryptor *PayloadEncryptor encryptor *PayloadEncryptor
} }
func NewBasePayloadMounter(loader PayloadLoader, marshaller ProtobufMarshaller, e *PayloadEncryptor) *BasePayloadMounter { func NewBasePayloadMounter(loader PayloadLoader, marshaller ProtobufMarshaller, e *PayloadEncryptor) *BasePayloadMounter {
return &BasePayloadMounter{ return &BasePayloadMounter{
PayloadLockPayload: &PayloadLockPayload{e}, PayloadLockPayload: &PayloadLockPayload{e},
PayloadToSend: &PayloadToSend{e}, PayloadToSend: &PayloadToSend{e},
payloadLoader: loader, loader: loader,
payloadMarshaller: marshaller, marshaller: marshaller,
encryptor: e, encryptor: e,
} }
} }
// Mount loads and prepares the payload to be stored in the PayloadLoader's state ready for later access // Mount loads and prepares the payload to be stored in the PayloadLoader's state ready for later access
func (bpm *BasePayloadMounter) Mount() error { func (bpm *BasePayloadMounter) Mount() error {
err := bpm.payloadLoader.Load() err := bpm.loader.Load()
if err != nil { if err != nil {
return err return err
} }
p, err := bpm.payloadMarshaller.MarshalProtobuf() p, err := bpm.marshaller.MarshalProtobuf()
if err != nil { if err != nil {
return err return err
} }
@ -65,7 +64,7 @@ func (bpm *BasePayloadMounter) Mount() error {
| |
*/ */
// NewAccountPayloadMounter generates a new and initialised AccountPayloadMounter // NewAccountPayloadMounter generates a new and initialised AccountPayload flavoured BasePayloadMounter
// responsible for the whole lifecycle of an AccountPayload // responsible for the whole lifecycle of an AccountPayload
func NewAccountPayloadMounter(pe *PayloadEncryptor, config *SenderConfig, logger *zap.Logger) (*BasePayloadMounter, error) { func NewAccountPayloadMounter(pe *PayloadEncryptor, config *SenderConfig, logger *zap.Logger) (*BasePayloadMounter, error) {
l := logger.Named("AccountPayloadLoader") l := logger.Named("AccountPayloadLoader")
@ -141,11 +140,11 @@ func (apl *AccountPayloadLoader) Load() error {
| |
*/ */
// NewRawMessagePayloadMounter generates a new and initialised RawMessagePayloadMounter // NewRawMessagePayloadMounter generates a new and initialised RawMessagePayload flavoured BasePayloadMounter
// responsible for the whole lifecycle of an RawMessagePayload // responsible for the whole lifecycle of an RawMessagePayload
func NewRawMessagePayloadMounter(logger *zap.Logger, pe *PayloadEncryptor, backend *api.GethStatusBackend, config *SenderConfig) *BasePayloadMounter { func NewRawMessagePayloadMounter(logger *zap.Logger, pe *PayloadEncryptor, backend *api.GethStatusBackend, config *SenderConfig) *BasePayloadMounter {
pe = pe.Renew() pe = pe.Renew()
payload := new(protobuf.SyncRawMessage) payload := NewRawMessagesPayload()
return NewBasePayloadMounter( return NewBasePayloadMounter(
NewRawMessageLoader(backend, payload, config), NewRawMessageLoader(backend, payload, config),
@ -155,13 +154,13 @@ func NewRawMessagePayloadMounter(logger *zap.Logger, pe *PayloadEncryptor, backe
} }
type RawMessageLoader struct { type RawMessageLoader struct {
payload *protobuf.SyncRawMessage payload *RawMessagesPayload
syncRawMessageHandler *SyncRawMessageHandler syncRawMessageHandler *SyncRawMessageHandler
keyUID string keyUID string
deviceType string deviceType string
} }
func NewRawMessageLoader(backend *api.GethStatusBackend, payload *protobuf.SyncRawMessage, config *SenderConfig) *RawMessageLoader { func NewRawMessageLoader(backend *api.GethStatusBackend, payload *RawMessagesPayload, config *SenderConfig) *RawMessageLoader {
return &RawMessageLoader{ return &RawMessageLoader{
syncRawMessageHandler: NewSyncRawMessageHandler(backend), syncRawMessageHandler: NewSyncRawMessageHandler(backend),
payload: payload, payload: payload,
@ -171,7 +170,7 @@ func NewRawMessageLoader(backend *api.GethStatusBackend, payload *protobuf.SyncR
} }
func (r *RawMessageLoader) Load() (err error) { func (r *RawMessageLoader) Load() (err error) {
*r.payload, err = r.syncRawMessageHandler.PrepareRawMessage(r.keyUID, r.deviceType) r.payload.rawMessages, r.payload.subAccounts, r.payload.setting, err = r.syncRawMessageHandler.PrepareRawMessage(r.keyUID, r.deviceType)
return err return err
} }
@ -184,11 +183,11 @@ func (r *RawMessageLoader) Load() (err error) {
| |
*/ */
// NewInstallationPayloadMounter generates a new and initialised InstallationPayloadMounter // NewInstallationPayloadMounter generates a new and initialised InstallationPayload flavoured BasePayloadMounter
// responsible for the whole lifecycle of an InstallationPayload // responsible for the whole lifecycle of an InstallationPayload
func NewInstallationPayloadMounter(logger *zap.Logger, pe *PayloadEncryptor, backend *api.GethStatusBackend, deviceType string) *BasePayloadMounter { func NewInstallationPayloadMounter(pe *PayloadEncryptor, backend *api.GethStatusBackend, deviceType string) *BasePayloadMounter {
pe = pe.Renew() pe = pe.Renew()
payload := new(protobuf.SyncRawMessage) payload := NewRawMessagesPayload()
return NewBasePayloadMounter( return NewBasePayloadMounter(
NewInstallationPayloadLoader(backend, payload, deviceType), NewInstallationPayloadLoader(backend, payload, deviceType),
@ -198,12 +197,12 @@ func NewInstallationPayloadMounter(logger *zap.Logger, pe *PayloadEncryptor, bac
} }
type InstallationPayloadLoader struct { type InstallationPayloadLoader struct {
payload *protobuf.SyncRawMessage payload *RawMessagesPayload
syncRawMessageHandler *SyncRawMessageHandler syncRawMessageHandler *SyncRawMessageHandler
deviceType string deviceType string
} }
func NewInstallationPayloadLoader(backend *api.GethStatusBackend, payload *protobuf.SyncRawMessage, deviceType string) *InstallationPayloadLoader { func NewInstallationPayloadLoader(backend *api.GethStatusBackend, payload *RawMessagesPayload, deviceType string) *InstallationPayloadLoader {
return &InstallationPayloadLoader{ return &InstallationPayloadLoader{
payload: payload, payload: payload,
syncRawMessageHandler: NewSyncRawMessageHandler(backend), syncRawMessageHandler: NewSyncRawMessageHandler(backend),
@ -217,7 +216,8 @@ func (r *InstallationPayloadLoader) Load() error {
if err != nil { if err != nil {
return err return err
} }
*r.payload = rawMessageCollector.convertToSyncRawMessage() rms := rawMessageCollector.convertToSyncRawMessage()
r.payload.rawMessages = rms.RawMessages
return nil return nil
} }
@ -232,12 +232,12 @@ func (r *InstallationPayloadLoader) Load() error {
// NewPayloadMounters returns PayloadMounter s configured to handle local pairing transfers of: // NewPayloadMounters returns PayloadMounter s configured to handle local pairing transfers of:
// - AccountPayload, RawMessagePayload and InstallationPayload // - AccountPayload, RawMessagePayload and InstallationPayload
func NewPayloadMounters(logger *zap.Logger, pe *PayloadEncryptor, backend *api.GethStatusBackend, config *SenderConfig) (PayloadMounter, PayloadMounter, *InstallationPayloadMounterReceiver, error) { func NewPayloadMounters(logger *zap.Logger, pe *PayloadEncryptor, backend *api.GethStatusBackend, config *SenderConfig) (PayloadMounter, PayloadMounter, PayloadMounterReceiver, error) {
am, err := NewAccountPayloadMounter(pe, config, logger) am, err := NewAccountPayloadMounter(pe, config, logger)
if err != nil { if err != nil {
return nil, nil, nil, err return nil, nil, nil, err
} }
rmm := NewRawMessagePayloadMounter(logger, pe, backend, config) rmm := NewRawMessagePayloadMounter(logger, pe, backend, config)
imr := NewInstallationPayloadMounterReceiver(logger, pe, backend, config.DeviceType) imr := NewInstallationPayloadMounterReceiver(pe, backend, config.DeviceType)
return am, rmm, imr, nil return am, rmm, imr, nil
} }

View File

@ -32,15 +32,44 @@ type PayloadStorer interface {
type BasePayloadReceiver struct { type BasePayloadReceiver struct {
*PayloadLockPayload *PayloadLockPayload
*PayloadReceived *PayloadReceived
encryptor *PayloadEncryptor
unmarshaller ProtobufUnmarshaller
storer PayloadStorer
receiveCallback func()
} }
func NewBaseBasePayloadReceiver(e *PayloadEncryptor) *BasePayloadReceiver { func NewBaseBasePayloadReceiver(e *PayloadEncryptor, um ProtobufUnmarshaller, s PayloadStorer, callback func()) *BasePayloadReceiver {
return &BasePayloadReceiver{ return &BasePayloadReceiver{
&PayloadLockPayload{e}, PayloadLockPayload: &PayloadLockPayload{e},
&PayloadReceived{e}, PayloadReceived: &PayloadReceived{e},
encryptor: e,
unmarshaller: um,
storer: s,
receiveCallback: callback,
} }
} }
// Receive takes a []byte representing raw data, parses and stores the data
func (bpr *BasePayloadReceiver) Receive(data []byte) error {
err := bpr.encryptor.decrypt(data)
if err != nil {
return err
}
err = bpr.unmarshaller.UnmarshalProtobuf(bpr.Received())
if err != nil {
return err
}
if bpr.receiveCallback != nil {
bpr.receiveCallback()
}
return bpr.storer.Store()
}
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| AccountPayload | AccountPayload
@ -50,56 +79,24 @@ func NewBaseBasePayloadReceiver(e *PayloadEncryptor) *BasePayloadReceiver {
| |
*/ */
// AccountPayloadReceiver is responsible for the whole lifecycle of a AccountPayload // NewAccountPayloadReceiver generates a new and initialised AccountPayload flavoured BasePayloadReceiver
type AccountPayloadReceiver struct { // AccountPayloadReceiver is responsible for the whole receive and store cycle of an AccountPayload
*BasePayloadReceiver func NewAccountPayloadReceiver(e *PayloadEncryptor, p *AccountPayload, config *ReceiverConfig, logger *zap.Logger) (*BasePayloadReceiver, error) {
logger *zap.Logger
accountPayload *AccountPayload
encryptor *PayloadEncryptor
accountPayloadMarshaller *AccountPayloadMarshaller
accountStorer *AccountPayloadStorer
}
// NewAccountPayloadReceiver generates a new and initialised AccountPayloadManager
func NewAccountPayloadReceiver(e *PayloadEncryptor, config *ReceiverConfig, logger *zap.Logger) (*AccountPayloadReceiver, error) {
l := logger.Named("AccountPayloadManager") l := logger.Named("AccountPayloadManager")
l.Debug("fired", zap.Any("config", config)) l.Debug("fired", zap.Any("config", config))
e = e.Renew() e = e.Renew()
// A new SHARED AccountPayload aps, err := NewAccountPayloadStorer(p, config)
p := new(AccountPayload)
accountPayloadRepository, err := NewAccountPayloadStorer(p, config)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &AccountPayloadReceiver{ return NewBaseBasePayloadReceiver(e, NewPairingPayloadMarshaller(p, l), aps,
BasePayloadReceiver: NewBaseBasePayloadReceiver(e), func() {
logger: l, signal.SendLocalPairingEvent(Event{Type: EventReceivedAccount, Action: ActionPairingAccount, Data: p.multiaccount})
accountPayload: p, },
encryptor: e, ), nil
accountPayloadMarshaller: NewPairingPayloadMarshaller(p, l),
accountStorer: accountPayloadRepository,
}, nil
}
// Receive takes a []byte representing raw data, parses and stores the data
func (apr *AccountPayloadReceiver) Receive(data []byte) error {
err := apr.encryptor.decrypt(data)
if err != nil {
return err
}
err = apr.accountPayloadMarshaller.UnmarshalProtobuf(apr.Received())
if err != nil {
return err
}
signal.SendLocalPairingEvent(Event{Type: EventReceivedAccount, Action: ActionPairingAccount, Data: apr.accountPayload.multiaccount})
return apr.accountStorer.Store()
} }
// AccountPayloadStorer is responsible for parsing, validating and storing AccountPayload data // AccountPayloadStorer is responsible for parsing, validating and storing AccountPayload data
@ -217,38 +214,19 @@ func (aps *AccountPayloadStorer) storeMultiAccount() error {
| |
*/ */
type RawMessagePayloadReceiver struct { // NewRawMessagePayloadReceiver generates a new and initialised RawMessagesPayload flavoured BasePayloadReceiver
*BasePayloadReceiver // RawMessagePayloadReceiver is responsible for the whole receive and store cycle of a RawMessagesPayload
func NewRawMessagePayloadReceiver(accountPayload *AccountPayload, e *PayloadEncryptor, backend *api.GethStatusBackend, config *ReceiverConfig) *BasePayloadReceiver {
logger *zap.Logger
encryptor *PayloadEncryptor
storer *RawMessageStorer
}
func NewRawMessagePayloadReceiver(logger *zap.Logger, accountPayload *AccountPayload, e *PayloadEncryptor, backend *api.GethStatusBackend, config *ReceiverConfig) *RawMessagePayloadReceiver {
l := logger.Named("RawMessagePayloadManager")
e = e.Renew() e = e.Renew()
payload := NewRawMessagesPayload()
return &RawMessagePayloadReceiver{ return NewBaseBasePayloadReceiver(e,
BasePayloadReceiver: NewBaseBasePayloadReceiver(e), NewRawMessagePayloadMarshaller(payload),
logger: l, NewRawMessageStorer(backend, payload, accountPayload, config), nil)
encryptor: e,
storer: NewRawMessageStorer(backend, accountPayload, config),
}
}
func (r *RawMessagePayloadReceiver) Receive(data []byte) error {
err := r.encryptor.decrypt(data)
if err != nil {
return err
}
r.storer.payload = r.Received()
return r.storer.Store()
} }
type RawMessageStorer struct { type RawMessageStorer struct {
payload []byte payload *RawMessagesPayload
syncRawMessageHandler *SyncRawMessageHandler syncRawMessageHandler *SyncRawMessageHandler
accountPayload *AccountPayload accountPayload *AccountPayload
nodeConfig *params.NodeConfig nodeConfig *params.NodeConfig
@ -256,10 +234,10 @@ type RawMessageStorer struct {
deviceType string deviceType string
} }
func NewRawMessageStorer(backend *api.GethStatusBackend, accountPayload *AccountPayload, config *ReceiverConfig) *RawMessageStorer { func NewRawMessageStorer(backend *api.GethStatusBackend, payload *RawMessagesPayload, accountPayload *AccountPayload, config *ReceiverConfig) *RawMessageStorer {
return &RawMessageStorer{ return &RawMessageStorer{
syncRawMessageHandler: NewSyncRawMessageHandler(backend), syncRawMessageHandler: NewSyncRawMessageHandler(backend),
payload: make([]byte, 0), payload: payload,
accountPayload: accountPayload, accountPayload: accountPayload,
nodeConfig: config.NodeConfig, nodeConfig: config.NodeConfig,
settingCurrentNetwork: config.SettingCurrentNetwork, settingCurrentNetwork: config.SettingCurrentNetwork,
@ -268,11 +246,10 @@ func NewRawMessageStorer(backend *api.GethStatusBackend, accountPayload *Account
} }
func (r *RawMessageStorer) Store() error { func (r *RawMessageStorer) Store() error {
accountPayload := r.accountPayload if r.accountPayload == nil || r.accountPayload.multiaccount == nil {
if accountPayload == nil || accountPayload.multiaccount == nil {
return fmt.Errorf("no known multiaccount when storing raw messages") return fmt.Errorf("no known multiaccount when storing raw messages")
} }
return r.syncRawMessageHandler.HandleRawMessage(accountPayload, r.nodeConfig, r.settingCurrentNetwork, r.deviceType, r.payload) return r.syncRawMessageHandler.HandleRawMessage(r.accountPayload, r.nodeConfig, r.settingCurrentNetwork, r.deviceType, r.payload)
} }
/* /*
@ -284,45 +261,28 @@ func (r *RawMessageStorer) Store() error {
| |
*/ */
type InstallationPayloadReceiver struct { // NewInstallationPayloadReceiver generates a new and initialised InstallationPayload flavoured BasePayloadReceiver
*BasePayloadReceiver // InstallationPayloadReceiver is responsible for the whole receive and store cycle of a RawMessagesPayload specifically
// for sending / requesting installation data from the Receiver device.
logger *zap.Logger func NewInstallationPayloadReceiver(e *PayloadEncryptor, backend *api.GethStatusBackend, deviceType string) *BasePayloadReceiver {
encryptor *PayloadEncryptor
storer *InstallationPayloadStorer
}
func NewInstallationPayloadReceiver(logger *zap.Logger, e *PayloadEncryptor, backend *api.GethStatusBackend, deviceType string) *InstallationPayloadReceiver {
l := logger.Named("InstallationPayloadManager")
e = e.Renew() e = e.Renew()
payload := NewRawMessagesPayload()
return &InstallationPayloadReceiver{ return NewBaseBasePayloadReceiver(e,
BasePayloadReceiver: NewBaseBasePayloadReceiver(e), NewRawMessagePayloadMarshaller(payload),
logger: l, NewInstallationPayloadStorer(backend, payload, deviceType), nil)
encryptor: e,
storer: NewInstallationPayloadStorer(backend, deviceType),
}
}
func (i *InstallationPayloadReceiver) Receive(data []byte) error {
err := i.encryptor.decrypt(data)
if err != nil {
return err
}
i.storer.payload = i.encryptor.getDecrypted()
return i.storer.Store()
} }
type InstallationPayloadStorer struct { type InstallationPayloadStorer struct {
payload []byte payload *RawMessagesPayload
syncRawMessageHandler *SyncRawMessageHandler syncRawMessageHandler *SyncRawMessageHandler
deviceType string deviceType string
backend *api.GethStatusBackend backend *api.GethStatusBackend
} }
func NewInstallationPayloadStorer(backend *api.GethStatusBackend, deviceType string) *InstallationPayloadStorer { func NewInstallationPayloadStorer(backend *api.GethStatusBackend, payload *RawMessagesPayload, deviceType string) *InstallationPayloadStorer {
return &InstallationPayloadStorer{ return &InstallationPayloadStorer{
payload: payload,
syncRawMessageHandler: NewSyncRawMessageHandler(backend), syncRawMessageHandler: NewSyncRawMessageHandler(backend),
deviceType: deviceType, deviceType: deviceType,
backend: backend, backend: backend,
@ -334,15 +294,11 @@ func (r *InstallationPayloadStorer) Store() error {
if messenger == nil { if messenger == nil {
return fmt.Errorf("messenger is nil when invoke InstallationPayloadRepository#Store()") return fmt.Errorf("messenger is nil when invoke InstallationPayloadRepository#Store()")
} }
rawMessages, _, _, err := r.syncRawMessageHandler.unmarshalSyncRawMessage(r.payload) err := messenger.SetInstallationDeviceType(r.deviceType)
if err != nil { if err != nil {
return err return err
} }
err = messenger.SetInstallationDeviceType(r.deviceType) return messenger.HandleSyncRawMessages(r.payload.rawMessages)
if err != nil {
return err
}
return messenger.HandleSyncRawMessages(rawMessages)
} }
/* /*
@ -354,12 +310,15 @@ func (r *InstallationPayloadStorer) Store() error {
| |
*/ */
func NewPayloadReceivers(logger *zap.Logger, pe *PayloadEncryptor, backend *api.GethStatusBackend, config *ReceiverConfig) (*AccountPayloadReceiver, *RawMessagePayloadReceiver, *InstallationPayloadMounterReceiver, error) { func NewPayloadReceivers(logger *zap.Logger, pe *PayloadEncryptor, backend *api.GethStatusBackend, config *ReceiverConfig) (PayloadReceiver, PayloadReceiver, PayloadMounterReceiver, error) {
ar, err := NewAccountPayloadReceiver(pe, config, logger) // A new SHARED AccountPayload
p := new(AccountPayload)
ar, err := NewAccountPayloadReceiver(pe, p, config, logger)
if err != nil { if err != nil {
return nil, nil, nil, err return nil, nil, nil, err
} }
rmr := NewRawMessagePayloadReceiver(logger, ar.accountPayload, pe, backend, config) rmr := NewRawMessagePayloadReceiver(p, pe, backend, config)
imr := NewInstallationPayloadMounterReceiver(logger, pe, backend, config.DeviceType) imr := NewInstallationPayloadMounterReceiver(pe, backend, config.DeviceType)
return ar, rmr, imr, nil return ar, rmr, imr, nil
} }

View File

@ -21,7 +21,7 @@ func (r *RawMessageCollector) getRawMessages() []*common.RawMessage {
return r.rawMessages return r.rawMessages
} }
func (r *RawMessageCollector) convertToSyncRawMessage() protobuf.SyncRawMessage { func (r *RawMessageCollector) convertToSyncRawMessage() *protobuf.SyncRawMessage {
syncRawMessage := new(protobuf.SyncRawMessage) syncRawMessage := new(protobuf.SyncRawMessage)
for _, m := range r.getRawMessages() { for _, m := range r.getRawMessages() {
rawMessage := new(protobuf.RawMessage) rawMessage := new(protobuf.RawMessage)
@ -29,5 +29,5 @@ func (r *RawMessageCollector) convertToSyncRawMessage() protobuf.SyncRawMessage
rawMessage.MessageType = m.MessageType rawMessage.MessageType = m.MessageType
syncRawMessage.RawMessages = append(syncRawMessage.RawMessages, rawMessage) syncRawMessage.RawMessages = append(syncRawMessage.RawMessages, rawMessage)
} }
return *syncRawMessage return syncRawMessage
} }

View File

@ -2,12 +2,9 @@ package pairing
import ( import (
"context" "context"
"encoding/json"
"fmt" "fmt"
"path/filepath" "path/filepath"
"github.com/golang/protobuf/proto"
"github.com/status-im/status-go/api" "github.com/status-im/status-go/api"
"github.com/status-im/status-go/multiaccounts/accounts" "github.com/status-im/status-go/multiaccounts/accounts"
"github.com/status-im/status-go/multiaccounts/settings" "github.com/status-im/status-go/multiaccounts/settings"
@ -38,10 +35,11 @@ func (s *SyncRawMessageHandler) CollectInstallationData(rawMessageCollector *Raw
return err return err
} }
func (s *SyncRawMessageHandler) PrepareRawMessage(keyUID, deviceType string) (rsm protobuf.SyncRawMessage, err error) { func (s *SyncRawMessageHandler) PrepareRawMessage(keyUID, deviceType string) (rm []*protobuf.RawMessage, as []*accounts.Account, syncSettings *settings.Settings, err error) {
syncSettings = new(settings.Settings)
messenger := s.backend.Messenger() messenger := s.backend.Messenger()
if messenger == nil { if messenger == nil {
return rsm, fmt.Errorf("messenger is nil when PrepareRawMessage") return nil, nil, nil, fmt.Errorf("messenger is nil when PrepareRawMessage")
} }
currentAccount, err := s.backend.GetActiveAccount() currentAccount, err := s.backend.GetActiveAccount()
@ -49,7 +47,7 @@ func (s *SyncRawMessageHandler) PrepareRawMessage(keyUID, deviceType string) (rs
return return
} }
if keyUID != currentAccount.KeyUID { if keyUID != currentAccount.KeyUID {
return rsm, fmt.Errorf("keyUID not equal") return nil, nil, nil, fmt.Errorf("keyUID not equal")
} }
messenger.SetLocalPairing(true) messenger.SetLocalPairing(true)
@ -67,26 +65,16 @@ func (s *SyncRawMessageHandler) PrepareRawMessage(keyUID, deviceType string) (rs
return return
} }
rsm = rawMessageCollector.convertToSyncRawMessage() rsm := rawMessageCollector.convertToSyncRawMessage()
rm = rsm.RawMessages
accountService := s.backend.StatusNode().AccountService() accountService := s.backend.StatusNode().AccountService()
var (
subAccounts []*accounts.Account as, err = accountService.GetAccountsByKeyUID(keyUID)
setting settings.Settings
)
subAccounts, err = accountService.GetAccountsByKeyUID(keyUID)
if err != nil { if err != nil {
return return
} }
rsm.SubAccountsJsonBytes, err = json.Marshal(subAccounts) *syncSettings, err = accountService.GetSettings()
if err != nil {
return
}
setting, err = accountService.GetSettings()
if err != nil {
return
}
rsm.SettingsJsonBytes, err = json.Marshal(setting)
if err != nil { if err != nil {
return return
} }
@ -94,12 +82,8 @@ func (s *SyncRawMessageHandler) PrepareRawMessage(keyUID, deviceType string) (rs
return return
} }
func (s *SyncRawMessageHandler) HandleRawMessage(accountPayload *AccountPayload, nodeConfig *params.NodeConfig, settingCurrentNetwork, deviceType string, rawMessagePayload []byte) error { func (s *SyncRawMessageHandler) HandleRawMessage(accountPayload *AccountPayload, nodeConfig *params.NodeConfig, settingCurrentNetwork, deviceType string, rmp *RawMessagesPayload) (err error) {
account := accountPayload.multiaccount account := accountPayload.multiaccount
rawMessages, subAccounts, setting, err := s.unmarshalSyncRawMessage(rawMessagePayload)
if err != nil {
return err
}
activeAccount, _ := s.backend.GetActiveAccount() activeAccount, _ := s.backend.GetActiveAccount()
if activeAccount == nil { // not login yet if activeAccount == nil { // not login yet
@ -115,10 +99,10 @@ func (s *SyncRawMessageHandler) HandleRawMessage(accountPayload *AccountPayload,
if err != nil { if err != nil {
return err return err
} }
setting.InstallationID = nodeConfig.ShhextConfig.InstallationID rmp.setting.InstallationID = nodeConfig.ShhextConfig.InstallationID
setting.CurrentNetwork = settingCurrentNetwork rmp.setting.CurrentNetwork = settingCurrentNetwork
err = s.backend.StartNodeWithAccountAndInitialConfig(*account, accountPayload.password, *setting, nodeConfig, subAccounts) err = s.backend.StartNodeWithAccountAndInitialConfig(*account, accountPayload.password, *rmp.setting, nodeConfig, rmp.subAccounts)
} }
if err != nil { if err != nil {
return err return err
@ -133,30 +117,5 @@ func (s *SyncRawMessageHandler) HandleRawMessage(accountPayload *AccountPayload,
if err != nil { if err != nil {
return err return err
} }
return messenger.HandleSyncRawMessages(rawMessages) return messenger.HandleSyncRawMessages(rmp.rawMessages)
}
func (s *SyncRawMessageHandler) unmarshalSyncRawMessage(payload []byte) ([]*protobuf.RawMessage, []*accounts.Account, *settings.Settings, error) {
var (
syncRawMessage protobuf.SyncRawMessage
subAccounts []*accounts.Account
setting *settings.Settings
)
err := proto.Unmarshal(payload, &syncRawMessage)
if err != nil {
return nil, nil, nil, err
}
if syncRawMessage.SubAccountsJsonBytes != nil {
err = json.Unmarshal(syncRawMessage.SubAccountsJsonBytes, &subAccounts)
if err != nil {
return nil, nil, nil, err
}
}
if syncRawMessage.SettingsJsonBytes != nil {
err = json.Unmarshal(syncRawMessage.SettingsJsonBytes, &setting)
if err != nil {
return nil, nil, nil, err
}
}
return syncRawMessage.RawMessages, subAccounts, setting, nil
} }

View File

@ -113,7 +113,7 @@ type SenderServer struct {
*BaseServer *BaseServer
accountMounter PayloadMounter accountMounter PayloadMounter
rawMessageMounter PayloadMounter rawMessageMounter PayloadMounter
installationMounter *InstallationPayloadMounterReceiver installationMounter PayloadMounterReceiver
} }
// NewSenderServer returns a *SenderServer init from the given *SenderServerConfig // NewSenderServer returns a *SenderServer init from the given *SenderServerConfig

View File

@ -326,33 +326,33 @@ func (s *SyncDeviceSuite) TestPairingSyncDeviceClientAsReceiver() {
func defaultSettings(generatedAccountInfo generator.GeneratedAccountInfo, derivedAddresses map[string]generator.AccountInfo, mnemonic *string) (*settings.Settings, error) { func defaultSettings(generatedAccountInfo generator.GeneratedAccountInfo, derivedAddresses map[string]generator.AccountInfo, mnemonic *string) (*settings.Settings, error) {
chatKeyString := derivedAddresses[pathDefaultChat].PublicKey chatKeyString := derivedAddresses[pathDefaultChat].PublicKey
settings := &settings.Settings{} syncSettings := &settings.Settings{}
settings.KeyUID = generatedAccountInfo.KeyUID syncSettings.KeyUID = generatedAccountInfo.KeyUID
settings.Address = types.HexToAddress(generatedAccountInfo.Address) syncSettings.Address = types.HexToAddress(generatedAccountInfo.Address)
settings.WalletRootAddress = types.HexToAddress(derivedAddresses[pathWalletRoot].Address) syncSettings.WalletRootAddress = types.HexToAddress(derivedAddresses[pathWalletRoot].Address)
// Set chat key & name // Set chat key & name
name, err := alias.GenerateFromPublicKeyString(chatKeyString) name, err := alias.GenerateFromPublicKeyString(chatKeyString)
if err != nil { if err != nil {
return nil, err return nil, err
} }
settings.Name = name syncSettings.Name = name
settings.PublicKey = chatKeyString syncSettings.PublicKey = chatKeyString
settings.DappsAddress = types.HexToAddress(derivedAddresses[pathDefaultWallet].Address) syncSettings.DappsAddress = types.HexToAddress(derivedAddresses[pathDefaultWallet].Address)
settings.EIP1581Address = types.HexToAddress(derivedAddresses[pathEIP1581].Address) syncSettings.EIP1581Address = types.HexToAddress(derivedAddresses[pathEIP1581].Address)
settings.Mnemonic = mnemonic syncSettings.Mnemonic = mnemonic
settings.SigningPhrase = "balabala" syncSettings.SigningPhrase = "balabala"
settings.SendPushNotifications = true syncSettings.SendPushNotifications = true
settings.InstallationID = uuid.New().String() syncSettings.InstallationID = uuid.New().String()
settings.UseMailservers = true syncSettings.UseMailservers = true
settings.PreviewPrivacy = true syncSettings.PreviewPrivacy = true
settings.Currency = "usd" syncSettings.Currency = "usd"
settings.ProfilePicturesVisibility = 1 syncSettings.ProfilePicturesVisibility = 1
settings.LinkPreviewRequestEnabled = true syncSettings.LinkPreviewRequestEnabled = true
visibleTokens := make(map[string][]string) visibleTokens := make(map[string][]string)
visibleTokens["mainnet"] = []string{"SNT"} visibleTokens["mainnet"] = []string{"SNT"}
@ -361,14 +361,14 @@ func defaultSettings(generatedAccountInfo generator.GeneratedAccountInfo, derive
return nil, err return nil, err
} }
visibleTokenJSONRaw := json.RawMessage(visibleTokensJSON) visibleTokenJSONRaw := json.RawMessage(visibleTokensJSON)
settings.WalletVisibleTokens = &visibleTokenJSONRaw syncSettings.WalletVisibleTokens = &visibleTokenJSONRaw
networks := `[{"id":"goerli_rpc","chain-explorer-link":"https://goerli.etherscan.io/address/","name":"Goerli with upstream RPC","config":{"NetworkId":5,"DataDir":"/ethereum/goerli_rpc","UpstreamConfig":{"Enabled":true,"URL":"https://goerli-archival.gateway.pokt.network/v1/lb/3ef2018191814b7e1009b8d9"}}},{"id":"mainnet_rpc","chain-explorer-link":"https://etherscan.io/address/","name":"Mainnet with upstream RPC","config":{"NetworkId":1,"DataDir":"/ethereum/mainnet_rpc","UpstreamConfig":{"Enabled":true,"URL":"https://eth-archival.gateway.pokt.network/v1/lb/3ef2018191814b7e1009b8d9"}}}]` networks := `[{"id":"goerli_rpc","chain-explorer-link":"https://goerli.etherscan.io/address/","name":"Goerli with upstream RPC","config":{"NetworkId":5,"DataDir":"/ethereum/goerli_rpc","UpstreamConfig":{"Enabled":true,"URL":"https://goerli-archival.gateway.pokt.network/v1/lb/3ef2018191814b7e1009b8d9"}}},{"id":"mainnet_rpc","chain-explorer-link":"https://etherscan.io/address/","name":"Mainnet with upstream RPC","config":{"NetworkId":1,"DataDir":"/ethereum/mainnet_rpc","UpstreamConfig":{"Enabled":true,"URL":"https://eth-archival.gateway.pokt.network/v1/lb/3ef2018191814b7e1009b8d9"}}}]`
var networksRawMessage json.RawMessage = []byte(networks) var networksRawMessage json.RawMessage = []byte(networks)
settings.Networks = &networksRawMessage syncSettings.Networks = &networksRawMessage
settings.CurrentNetwork = currentNetwork syncSettings.CurrentNetwork = currentNetwork
return settings, nil return syncSettings, nil
} }
func defaultNodeConfig(installationID, keyUID string) (*params.NodeConfig, error) { func defaultNodeConfig(installationID, keyUID string) (*params.NodeConfig, error) {