github.com/status-im/status-go@v1.1.0/server/pairing/raw_message_handler.go (about) 1 package pairing 2 3 import ( 4 "context" 5 "crypto/ecdsa" 6 "fmt" 7 "strings" 8 9 ethcrypto "github.com/ethereum/go-ethereum/crypto" 10 11 "github.com/status-im/status-go/api" 12 "github.com/status-im/status-go/multiaccounts/accounts" 13 "github.com/status-im/status-go/multiaccounts/settings" 14 "github.com/status-im/status-go/protocol/encryption/multidevice" 15 "github.com/status-im/status-go/protocol/protobuf" 16 "github.com/status-im/status-go/protocol/requests" 17 "github.com/status-im/status-go/signal" 18 ) 19 20 type SyncRawMessageHandler struct { 21 backend *api.GethStatusBackend 22 } 23 24 func NewSyncRawMessageHandler(backend *api.GethStatusBackend) *SyncRawMessageHandler { 25 return &SyncRawMessageHandler{backend: backend} 26 } 27 28 func (s *SyncRawMessageHandler) CollectInstallationData(rawMessageCollector *RawMessageCollector, deviceType string) error { 29 // TODO Could this function be part of the installation data exchange flow? 30 // https://github.com/status-im/status-go/issues/3304 31 messenger := s.backend.Messenger() 32 if messenger == nil { 33 return fmt.Errorf("messenger is nil when CollectInstallationData") 34 } 35 err := messenger.SetInstallationDeviceType(deviceType) 36 if err != nil { 37 return err 38 } 39 _, err = messenger.SendPairInstallation(context.TODO(), rawMessageCollector.dispatchMessage) 40 return err 41 } 42 43 func (s *SyncRawMessageHandler) PrepareRawMessage(keyUID, deviceType string) (rm []*protobuf.RawMessage, kp *accounts.Keypair, syncSettings *settings.Settings, err error) { 44 syncSettings = new(settings.Settings) 45 messenger := s.backend.Messenger() 46 if messenger == nil { 47 return nil, nil, nil, fmt.Errorf("messenger is nil when PrepareRawMessage") 48 } 49 50 currentAccount, err := s.backend.GetActiveAccount() 51 if err != nil { 52 return 53 } 54 if keyUID != currentAccount.KeyUID { 55 return nil, nil, nil, fmt.Errorf("keyUID not equal") 56 } 57 58 messenger.SetLocalPairing(true) 59 defer func() { 60 messenger.SetLocalPairing(false) 61 }() 62 rawMessageCollector := new(RawMessageCollector) 63 err = messenger.SyncDevices(context.TODO(), currentAccount.Name, currentAccount.Identicon, rawMessageCollector.dispatchMessage) 64 if err != nil { 65 return 66 } 67 68 err = s.CollectInstallationData(rawMessageCollector, deviceType) 69 if err != nil { 70 return 71 } 72 73 rsm := rawMessageCollector.convertToSyncRawMessage() 74 rm = rsm.RawMessages 75 76 accountService := s.backend.StatusNode().AccountService() 77 78 kp, err = accountService.GetKeypairByKeyUID(keyUID) 79 if err != nil { 80 return 81 } 82 *syncSettings, err = accountService.GetSettings() 83 if err != nil { 84 return 85 } 86 87 return 88 } 89 90 func (s *SyncRawMessageHandler) HandleRawMessage( 91 accountPayload *AccountPayload, 92 createAccountRequest *requests.CreateAccount, 93 deviceType string, 94 rmp *RawMessagesPayload) (err error) { 95 96 activeAccount, _ := s.backend.GetActiveAccount() 97 if activeAccount == nil { // not login yet 98 err = s.login(accountPayload, createAccountRequest, rmp) 99 if err != nil { 100 return err 101 } 102 } 103 104 messenger := s.backend.Messenger() 105 if messenger == nil { 106 return fmt.Errorf("messenger is nil when HandleRawMessage") 107 } 108 err = messenger.SetInstallationDeviceType(deviceType) 109 if err != nil { 110 return err 111 } 112 113 installations := GetMessengerInstallationsMap(messenger) 114 115 err = messenger.HandleSyncRawMessages(rmp.rawMessages) 116 117 if err != nil { 118 return err 119 } 120 121 if newInstallation := FindNewInstallations(messenger, installations); newInstallation != nil { 122 signal.SendLocalPairingEvent(Event{ 123 Type: EventReceivedInstallation, 124 Action: ActionPairingInstallation, 125 Data: newInstallation}) 126 } 127 128 return nil 129 } 130 131 func (s *SyncRawMessageHandler) login(accountPayload *AccountPayload, createAccountRequest *requests.CreateAccount, rmp *RawMessagesPayload) error { 132 account := accountPayload.multiaccount 133 installationID := multidevice.GenerateInstallationID() 134 nodeConfig, err := api.DefaultNodeConfig(installationID, createAccountRequest) 135 if err != nil { 136 return err 137 } 138 139 keystoreRelativePath, err := s.backend.InitKeyStoreDirWithAccount(nodeConfig.RootDataDir, account.KeyUID) 140 nodeConfig.KeyStoreDir = keystoreRelativePath 141 142 if err != nil { 143 return err 144 } 145 146 var chatKey *ecdsa.PrivateKey 147 if accountPayload.chatKey != "" { 148 chatKeyHex := strings.Trim(accountPayload.chatKey, "0x") 149 chatKey, err = ethcrypto.HexToECDSA(chatKeyHex) 150 if err != nil { 151 return err 152 } 153 } 154 155 if accountPayload.exist { 156 return s.backend.StartNodeWithAccount(*account, accountPayload.password, nodeConfig, chatKey) 157 } 158 159 // Override some of received settings 160 rmp.setting.DeviceName = createAccountRequest.DeviceName 161 rmp.setting.InstallationID = installationID 162 rmp.setting.CurrentNetwork = api.DefaultCurrentNetwork 163 164 return s.backend.StartNodeWithAccountAndInitialConfig( 165 *account, 166 accountPayload.password, 167 *rmp.setting, 168 nodeConfig, 169 rmp.profileKeypair.Accounts, 170 chatKey, 171 ) 172 }