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  }