From 465afd0131a0b4c1baa8b12489ea6cb86bd3aec1 Mon Sep 17 00:00:00 2001 From: Samuel Hawksby-Robinson Date: Mon, 3 Apr 2023 00:08:29 +0100 Subject: [PATCH] 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. --- VERSION | 2 +- account/json/utils.go | 5 + multiaccounts/settings/structs.go | 6 + server/pairing/client.go | 6 +- server/pairing/interfaces.go | 4 + server/pairing/payload_encryptor.go | 8 +- server/pairing/payload_management.go | 80 ++++++++-- server/pairing/payload_mounter.go | 44 +++--- server/pairing/payload_receiver.go | 187 +++++++++--------------- server/pairing/raw_message_collector.go | 4 +- server/pairing/raw_message_handler.go | 69 ++------- server/pairing/server.go | 2 +- server/pairing/sync_device_test.go | 42 +++--- 13 files changed, 222 insertions(+), 237 deletions(-) diff --git a/VERSION b/VERSION index 455e4b308..a60f2152e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.142.5 +0.142.6 diff --git a/account/json/utils.go b/account/json/utils.go index 10b9f571a..f8699165c 100644 --- a/account/json/utils.go +++ b/account/json/utils.go @@ -28,6 +28,11 @@ func getPubKeyData(publicKey string) (*PublicKeyData, 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) if err != nil { return nil, err diff --git a/multiaccounts/settings/structs.go b/multiaccounts/settings/structs.go index 111a30183..ef2233168 100644 --- a/multiaccounts/settings/structs.go +++ b/multiaccounts/settings/structs.go @@ -2,6 +2,7 @@ package settings import ( "encoding/json" + "reflect" accountJson "github.com/status-im/status-go/account/json" "github.com/status-im/status-go/eth-node/types" @@ -200,3 +201,8 @@ func (s Settings) MarshalJSON() ([]byte, error) { } return json.Marshal(ext) } + +func (s Settings) IsEmpty() bool { + empty := reflect.Zero(reflect.TypeOf(s)).Interface() + return reflect.DeepEqual(s, empty) +} diff --git a/server/pairing/client.go b/server/pairing/client.go index e3e4df4dc..a04aeac45 100644 --- a/server/pairing/client.go +++ b/server/pairing/client.go @@ -111,7 +111,7 @@ type SenderClient struct { *BaseClient accountMounter PayloadMounter rawMessageMounter PayloadMounter - installationMounter *InstallationPayloadMounterReceiver + installationMounter PayloadMounterReceiver } // NewSenderClient returns a fully qualified SenderClient created with the incoming parameters @@ -284,8 +284,8 @@ type ReceiverClient struct { *BaseClient accountReceiver PayloadReceiver - rawMessageReceiver *RawMessagePayloadReceiver - installationReceiver *InstallationPayloadMounterReceiver + rawMessageReceiver PayloadReceiver + installationReceiver PayloadMounterReceiver } // NewReceiverClient returns a fully qualified ReceiverClient created with the incoming parameters diff --git a/server/pairing/interfaces.go b/server/pairing/interfaces.go index 90a28c605..d2f332291 100644 --- a/server/pairing/interfaces.go +++ b/server/pairing/interfaces.go @@ -25,6 +25,10 @@ type PayloadLocker interface { 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 { GetLogger() *zap.Logger } diff --git a/server/pairing/payload_encryptor.go b/server/pairing/payload_encryptor.go index 127febc76..bd0d2f54c 100644 --- a/server/pairing/payload_encryptor.go +++ b/server/pairing/payload_encryptor.go @@ -17,9 +17,6 @@ func (ep *EncryptionPayload) lock() { 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 type PayloadEncryptor struct { aesKey []byte @@ -93,6 +90,7 @@ func (pem *PayloadEncryptor) lockPayload() { pem.payload.lock() } +// PayloadLockPayload Embeds a *PayloadEncryptor to give all embedding structs EncryptionPayload Locking type PayloadLockPayload struct { *PayloadEncryptor } @@ -101,6 +99,8 @@ func (pl *PayloadLockPayload) 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 { *PayloadEncryptor } @@ -109,6 +109,8 @@ func (pts *PayloadToSend) ToSend() []byte { 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 { *PayloadEncryptor } diff --git a/server/pairing/payload_management.go b/server/pairing/payload_management.go index d59aa2c57..a607953ff 100644 --- a/server/pairing/payload_management.go +++ b/server/pairing/payload_management.go @@ -1,6 +1,7 @@ package pairing import ( + "encoding/json" "errors" "github.com/golang/protobuf/proto" @@ -8,15 +9,14 @@ import ( "github.com/status-im/status-go/api" "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" ) const keystoreDir = "keystore" 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") ErrKeyUIDEmptyAsSender = errors.New("keyUID must be provided as sender") ErrNodeConfigNilAsReceiver = errors.New("node config must be provided as receiver") @@ -103,36 +103,86 @@ func (ppm *AccountPayloadMarshaller) multiaccountFromProtobuf(pbMultiAccount *pr ppm.multiaccount.FromProtobuf(pbMultiAccount) } -// RawMessagePayloadMarshaller is responsible for marshalling and unmarshalling raw message data -type RawMessagePayloadMarshaller struct { - payload *protobuf.SyncRawMessage +type RawMessagesPayload struct { + rawMessages []*protobuf.RawMessage + 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{ payload: payload, } } -func (rmm *RawMessagePayloadMarshaller) MarshalProtobuf() ([]byte, error) { - return proto.Marshal(rmm.payload) +func (rmm *RawMessagePayloadMarshaller) MarshalProtobuf() (data []byte, err error) { + 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 type InstallationPayloadMounterReceiver struct { PayloadMounter - *InstallationPayloadReceiver + PayloadReceiver } -func NewInstallationPayloadMounterReceiver(logger *zap.Logger, encryptor *PayloadEncryptor, backend *api.GethStatusBackend, deviceType string) *InstallationPayloadMounterReceiver { - l := logger.Named("InstallationPayloadMounterReceiver") +func NewInstallationPayloadMounterReceiver(encryptor *PayloadEncryptor, backend *api.GethStatusBackend, deviceType string) *InstallationPayloadMounterReceiver { return &InstallationPayloadMounterReceiver{ - NewInstallationPayloadMounter(l, encryptor, backend, deviceType), - NewInstallationPayloadReceiver(l, encryptor, backend, deviceType), + NewInstallationPayloadMounter(encryptor, backend, deviceType), + NewInstallationPayloadReceiver(encryptor, backend, deviceType), } } func (i *InstallationPayloadMounterReceiver) LockPayload() { i.PayloadMounter.LockPayload() - i.InstallationPayloadReceiver.LockPayload() + i.PayloadReceiver.LockPayload() } diff --git a/server/pairing/payload_mounter.go b/server/pairing/payload_mounter.go index b8b58d2df..db87d0234 100644 --- a/server/pairing/payload_mounter.go +++ b/server/pairing/payload_mounter.go @@ -5,7 +5,6 @@ import ( "github.com/status-im/status-go/api" "github.com/status-im/status-go/multiaccounts" - "github.com/status-im/status-go/protocol/protobuf" ) type PayloadMounter interface { @@ -26,29 +25,29 @@ type BasePayloadMounter struct { *PayloadLockPayload *PayloadToSend - payloadLoader PayloadLoader - payloadMarshaller ProtobufMarshaller - encryptor *PayloadEncryptor + loader PayloadLoader + marshaller ProtobufMarshaller + encryptor *PayloadEncryptor } func NewBasePayloadMounter(loader PayloadLoader, marshaller ProtobufMarshaller, e *PayloadEncryptor) *BasePayloadMounter { return &BasePayloadMounter{ PayloadLockPayload: &PayloadLockPayload{e}, PayloadToSend: &PayloadToSend{e}, - payloadLoader: loader, - payloadMarshaller: marshaller, + loader: loader, + marshaller: marshaller, encryptor: e, } } // Mount loads and prepares the payload to be stored in the PayloadLoader's state ready for later access func (bpm *BasePayloadMounter) Mount() error { - err := bpm.payloadLoader.Load() + err := bpm.loader.Load() if err != nil { return err } - p, err := bpm.payloadMarshaller.MarshalProtobuf() + p, err := bpm.marshaller.MarshalProtobuf() if err != nil { 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 func NewAccountPayloadMounter(pe *PayloadEncryptor, config *SenderConfig, logger *zap.Logger) (*BasePayloadMounter, error) { 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 func NewRawMessagePayloadMounter(logger *zap.Logger, pe *PayloadEncryptor, backend *api.GethStatusBackend, config *SenderConfig) *BasePayloadMounter { pe = pe.Renew() - payload := new(protobuf.SyncRawMessage) + payload := NewRawMessagesPayload() return NewBasePayloadMounter( NewRawMessageLoader(backend, payload, config), @@ -155,13 +154,13 @@ func NewRawMessagePayloadMounter(logger *zap.Logger, pe *PayloadEncryptor, backe } type RawMessageLoader struct { - payload *protobuf.SyncRawMessage + payload *RawMessagesPayload syncRawMessageHandler *SyncRawMessageHandler keyUID 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{ syncRawMessageHandler: NewSyncRawMessageHandler(backend), payload: payload, @@ -171,7 +170,7 @@ func NewRawMessageLoader(backend *api.GethStatusBackend, payload *protobuf.SyncR } 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 } @@ -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 -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() - payload := new(protobuf.SyncRawMessage) + payload := NewRawMessagesPayload() return NewBasePayloadMounter( NewInstallationPayloadLoader(backend, payload, deviceType), @@ -198,12 +197,12 @@ func NewInstallationPayloadMounter(logger *zap.Logger, pe *PayloadEncryptor, bac } type InstallationPayloadLoader struct { - payload *protobuf.SyncRawMessage + payload *RawMessagesPayload syncRawMessageHandler *SyncRawMessageHandler 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{ payload: payload, syncRawMessageHandler: NewSyncRawMessageHandler(backend), @@ -217,7 +216,8 @@ func (r *InstallationPayloadLoader) Load() error { if err != nil { return err } - *r.payload = rawMessageCollector.convertToSyncRawMessage() + rms := rawMessageCollector.convertToSyncRawMessage() + r.payload.rawMessages = rms.RawMessages return nil } @@ -232,12 +232,12 @@ func (r *InstallationPayloadLoader) Load() error { // NewPayloadMounters returns PayloadMounter s configured to handle local pairing transfers of: // - 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) if err != nil { return nil, nil, nil, err } rmm := NewRawMessagePayloadMounter(logger, pe, backend, config) - imr := NewInstallationPayloadMounterReceiver(logger, pe, backend, config.DeviceType) + imr := NewInstallationPayloadMounterReceiver(pe, backend, config.DeviceType) return am, rmm, imr, nil } diff --git a/server/pairing/payload_receiver.go b/server/pairing/payload_receiver.go index a1a2900e2..c5fa30605 100644 --- a/server/pairing/payload_receiver.go +++ b/server/pairing/payload_receiver.go @@ -32,15 +32,44 @@ type PayloadStorer interface { type BasePayloadReceiver struct { *PayloadLockPayload *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{ - &PayloadLockPayload{e}, - &PayloadReceived{e}, + PayloadLockPayload: &PayloadLockPayload{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 @@ -50,56 +79,24 @@ func NewBaseBasePayloadReceiver(e *PayloadEncryptor) *BasePayloadReceiver { | */ -// AccountPayloadReceiver is responsible for the whole lifecycle of a AccountPayload -type AccountPayloadReceiver struct { - *BasePayloadReceiver - - 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) { +// NewAccountPayloadReceiver generates a new and initialised AccountPayload flavoured BasePayloadReceiver +// AccountPayloadReceiver is responsible for the whole receive and store cycle of an AccountPayload +func NewAccountPayloadReceiver(e *PayloadEncryptor, p *AccountPayload, config *ReceiverConfig, logger *zap.Logger) (*BasePayloadReceiver, error) { l := logger.Named("AccountPayloadManager") l.Debug("fired", zap.Any("config", config)) e = e.Renew() - // A new SHARED AccountPayload - p := new(AccountPayload) - accountPayloadRepository, err := NewAccountPayloadStorer(p, config) + aps, err := NewAccountPayloadStorer(p, config) if err != nil { return nil, err } - return &AccountPayloadReceiver{ - BasePayloadReceiver: NewBaseBasePayloadReceiver(e), - logger: l, - accountPayload: p, - encryptor: e, - 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() + return NewBaseBasePayloadReceiver(e, NewPairingPayloadMarshaller(p, l), aps, + func() { + signal.SendLocalPairingEvent(Event{Type: EventReceivedAccount, Action: ActionPairingAccount, Data: p.multiaccount}) + }, + ), nil } // AccountPayloadStorer is responsible for parsing, validating and storing AccountPayload data @@ -217,38 +214,19 @@ func (aps *AccountPayloadStorer) storeMultiAccount() error { | */ -type RawMessagePayloadReceiver struct { - *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") - +// NewRawMessagePayloadReceiver generates a new and initialised RawMessagesPayload flavoured 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 { e = e.Renew() + payload := NewRawMessagesPayload() - return &RawMessagePayloadReceiver{ - BasePayloadReceiver: NewBaseBasePayloadReceiver(e), - logger: l, - 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() + return NewBaseBasePayloadReceiver(e, + NewRawMessagePayloadMarshaller(payload), + NewRawMessageStorer(backend, payload, accountPayload, config), nil) } type RawMessageStorer struct { - payload []byte + payload *RawMessagesPayload syncRawMessageHandler *SyncRawMessageHandler accountPayload *AccountPayload nodeConfig *params.NodeConfig @@ -256,10 +234,10 @@ type RawMessageStorer struct { 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{ syncRawMessageHandler: NewSyncRawMessageHandler(backend), - payload: make([]byte, 0), + payload: payload, accountPayload: accountPayload, nodeConfig: config.NodeConfig, settingCurrentNetwork: config.SettingCurrentNetwork, @@ -268,11 +246,10 @@ func NewRawMessageStorer(backend *api.GethStatusBackend, accountPayload *Account } func (r *RawMessageStorer) Store() error { - accountPayload := r.accountPayload - if accountPayload == nil || accountPayload.multiaccount == nil { + if r.accountPayload == nil || r.accountPayload.multiaccount == nil { 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 { - *BasePayloadReceiver - - logger *zap.Logger - encryptor *PayloadEncryptor - storer *InstallationPayloadStorer -} - -func NewInstallationPayloadReceiver(logger *zap.Logger, e *PayloadEncryptor, backend *api.GethStatusBackend, deviceType string) *InstallationPayloadReceiver { - l := logger.Named("InstallationPayloadManager") - +// NewInstallationPayloadReceiver generates a new and initialised InstallationPayload flavoured BasePayloadReceiver +// InstallationPayloadReceiver is responsible for the whole receive and store cycle of a RawMessagesPayload specifically +// for sending / requesting installation data from the Receiver device. +func NewInstallationPayloadReceiver(e *PayloadEncryptor, backend *api.GethStatusBackend, deviceType string) *BasePayloadReceiver { e = e.Renew() + payload := NewRawMessagesPayload() - return &InstallationPayloadReceiver{ - BasePayloadReceiver: NewBaseBasePayloadReceiver(e), - logger: l, - 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() + return NewBaseBasePayloadReceiver(e, + NewRawMessagePayloadMarshaller(payload), + NewInstallationPayloadStorer(backend, payload, deviceType), nil) } type InstallationPayloadStorer struct { - payload []byte + payload *RawMessagesPayload syncRawMessageHandler *SyncRawMessageHandler deviceType string backend *api.GethStatusBackend } -func NewInstallationPayloadStorer(backend *api.GethStatusBackend, deviceType string) *InstallationPayloadStorer { +func NewInstallationPayloadStorer(backend *api.GethStatusBackend, payload *RawMessagesPayload, deviceType string) *InstallationPayloadStorer { return &InstallationPayloadStorer{ + payload: payload, syncRawMessageHandler: NewSyncRawMessageHandler(backend), deviceType: deviceType, backend: backend, @@ -334,15 +294,11 @@ func (r *InstallationPayloadStorer) Store() error { if messenger == nil { 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 { return err } - err = messenger.SetInstallationDeviceType(r.deviceType) - if err != nil { - return err - } - return messenger.HandleSyncRawMessages(rawMessages) + return messenger.HandleSyncRawMessages(r.payload.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) { - ar, err := NewAccountPayloadReceiver(pe, config, logger) +func NewPayloadReceivers(logger *zap.Logger, pe *PayloadEncryptor, backend *api.GethStatusBackend, config *ReceiverConfig) (PayloadReceiver, PayloadReceiver, PayloadMounterReceiver, error) { + // A new SHARED AccountPayload + p := new(AccountPayload) + + ar, err := NewAccountPayloadReceiver(pe, p, config, logger) if err != nil { return nil, nil, nil, err } - rmr := NewRawMessagePayloadReceiver(logger, ar.accountPayload, pe, backend, config) - imr := NewInstallationPayloadMounterReceiver(logger, pe, backend, config.DeviceType) + rmr := NewRawMessagePayloadReceiver(p, pe, backend, config) + imr := NewInstallationPayloadMounterReceiver(pe, backend, config.DeviceType) return ar, rmr, imr, nil } diff --git a/server/pairing/raw_message_collector.go b/server/pairing/raw_message_collector.go index a203e180d..ce2ec8a68 100644 --- a/server/pairing/raw_message_collector.go +++ b/server/pairing/raw_message_collector.go @@ -21,7 +21,7 @@ func (r *RawMessageCollector) getRawMessages() []*common.RawMessage { return r.rawMessages } -func (r *RawMessageCollector) convertToSyncRawMessage() protobuf.SyncRawMessage { +func (r *RawMessageCollector) convertToSyncRawMessage() *protobuf.SyncRawMessage { syncRawMessage := new(protobuf.SyncRawMessage) for _, m := range r.getRawMessages() { rawMessage := new(protobuf.RawMessage) @@ -29,5 +29,5 @@ func (r *RawMessageCollector) convertToSyncRawMessage() protobuf.SyncRawMessage rawMessage.MessageType = m.MessageType syncRawMessage.RawMessages = append(syncRawMessage.RawMessages, rawMessage) } - return *syncRawMessage + return syncRawMessage } diff --git a/server/pairing/raw_message_handler.go b/server/pairing/raw_message_handler.go index 919386130..081005ec3 100644 --- a/server/pairing/raw_message_handler.go +++ b/server/pairing/raw_message_handler.go @@ -2,12 +2,9 @@ package pairing import ( "context" - "encoding/json" "fmt" "path/filepath" - "github.com/golang/protobuf/proto" - "github.com/status-im/status-go/api" "github.com/status-im/status-go/multiaccounts/accounts" "github.com/status-im/status-go/multiaccounts/settings" @@ -38,10 +35,11 @@ func (s *SyncRawMessageHandler) CollectInstallationData(rawMessageCollector *Raw 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() 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() @@ -49,7 +47,7 @@ func (s *SyncRawMessageHandler) PrepareRawMessage(keyUID, deviceType string) (rs return } if keyUID != currentAccount.KeyUID { - return rsm, fmt.Errorf("keyUID not equal") + return nil, nil, nil, fmt.Errorf("keyUID not equal") } messenger.SetLocalPairing(true) @@ -67,26 +65,16 @@ func (s *SyncRawMessageHandler) PrepareRawMessage(keyUID, deviceType string) (rs return } - rsm = rawMessageCollector.convertToSyncRawMessage() + rsm := rawMessageCollector.convertToSyncRawMessage() + rm = rsm.RawMessages accountService := s.backend.StatusNode().AccountService() - var ( - subAccounts []*accounts.Account - setting settings.Settings - ) - subAccounts, err = accountService.GetAccountsByKeyUID(keyUID) + + as, err = accountService.GetAccountsByKeyUID(keyUID) if err != nil { return } - rsm.SubAccountsJsonBytes, err = json.Marshal(subAccounts) - if err != nil { - return - } - setting, err = accountService.GetSettings() - if err != nil { - return - } - rsm.SettingsJsonBytes, err = json.Marshal(setting) + *syncSettings, err = accountService.GetSettings() if err != nil { return } @@ -94,12 +82,8 @@ func (s *SyncRawMessageHandler) PrepareRawMessage(keyUID, deviceType string) (rs 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 - rawMessages, subAccounts, setting, err := s.unmarshalSyncRawMessage(rawMessagePayload) - if err != nil { - return err - } activeAccount, _ := s.backend.GetActiveAccount() if activeAccount == nil { // not login yet @@ -115,10 +99,10 @@ func (s *SyncRawMessageHandler) HandleRawMessage(accountPayload *AccountPayload, if err != nil { return err } - setting.InstallationID = nodeConfig.ShhextConfig.InstallationID - setting.CurrentNetwork = settingCurrentNetwork + rmp.setting.InstallationID = nodeConfig.ShhextConfig.InstallationID + 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 { return err @@ -133,30 +117,5 @@ func (s *SyncRawMessageHandler) HandleRawMessage(accountPayload *AccountPayload, if err != nil { return err } - return messenger.HandleSyncRawMessages(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 + return messenger.HandleSyncRawMessages(rmp.rawMessages) } diff --git a/server/pairing/server.go b/server/pairing/server.go index ab7b1009f..99e1e4206 100644 --- a/server/pairing/server.go +++ b/server/pairing/server.go @@ -113,7 +113,7 @@ type SenderServer struct { *BaseServer accountMounter PayloadMounter rawMessageMounter PayloadMounter - installationMounter *InstallationPayloadMounterReceiver + installationMounter PayloadMounterReceiver } // NewSenderServer returns a *SenderServer init from the given *SenderServerConfig diff --git a/server/pairing/sync_device_test.go b/server/pairing/sync_device_test.go index 99b90a11b..d11a1bcec 100644 --- a/server/pairing/sync_device_test.go +++ b/server/pairing/sync_device_test.go @@ -326,33 +326,33 @@ func (s *SyncDeviceSuite) TestPairingSyncDeviceClientAsReceiver() { func defaultSettings(generatedAccountInfo generator.GeneratedAccountInfo, derivedAddresses map[string]generator.AccountInfo, mnemonic *string) (*settings.Settings, error) { chatKeyString := derivedAddresses[pathDefaultChat].PublicKey - settings := &settings.Settings{} - settings.KeyUID = generatedAccountInfo.KeyUID - settings.Address = types.HexToAddress(generatedAccountInfo.Address) - settings.WalletRootAddress = types.HexToAddress(derivedAddresses[pathWalletRoot].Address) + syncSettings := &settings.Settings{} + syncSettings.KeyUID = generatedAccountInfo.KeyUID + syncSettings.Address = types.HexToAddress(generatedAccountInfo.Address) + syncSettings.WalletRootAddress = types.HexToAddress(derivedAddresses[pathWalletRoot].Address) // Set chat key & name name, err := alias.GenerateFromPublicKeyString(chatKeyString) if err != nil { return nil, err } - settings.Name = name - settings.PublicKey = chatKeyString + syncSettings.Name = name + syncSettings.PublicKey = chatKeyString - settings.DappsAddress = types.HexToAddress(derivedAddresses[pathDefaultWallet].Address) - settings.EIP1581Address = types.HexToAddress(derivedAddresses[pathEIP1581].Address) - settings.Mnemonic = mnemonic + syncSettings.DappsAddress = types.HexToAddress(derivedAddresses[pathDefaultWallet].Address) + syncSettings.EIP1581Address = types.HexToAddress(derivedAddresses[pathEIP1581].Address) + syncSettings.Mnemonic = mnemonic - settings.SigningPhrase = "balabala" + syncSettings.SigningPhrase = "balabala" - settings.SendPushNotifications = true - settings.InstallationID = uuid.New().String() - settings.UseMailservers = true + syncSettings.SendPushNotifications = true + syncSettings.InstallationID = uuid.New().String() + syncSettings.UseMailservers = true - settings.PreviewPrivacy = true - settings.Currency = "usd" - settings.ProfilePicturesVisibility = 1 - settings.LinkPreviewRequestEnabled = true + syncSettings.PreviewPrivacy = true + syncSettings.Currency = "usd" + syncSettings.ProfilePicturesVisibility = 1 + syncSettings.LinkPreviewRequestEnabled = true visibleTokens := make(map[string][]string) visibleTokens["mainnet"] = []string{"SNT"} @@ -361,14 +361,14 @@ func defaultSettings(generatedAccountInfo generator.GeneratedAccountInfo, derive return nil, err } 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"}}}]` var networksRawMessage json.RawMessage = []byte(networks) - settings.Networks = &networksRawMessage - settings.CurrentNetwork = currentNetwork + syncSettings.Networks = &networksRawMessage + syncSettings.CurrentNetwork = currentNetwork - return settings, nil + return syncSettings, nil } func defaultNodeConfig(installationID, keyUID string) (*params.NodeConfig, error) {