github.com/status-im/status-go@v1.1.0/server/pairing/payload_mounter.go (about)

     1  package pairing
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"go.uber.org/zap"
     8  
     9  	"github.com/status-im/status-go/api"
    10  	"github.com/status-im/status-go/multiaccounts"
    11  	"github.com/status-im/status-go/multiaccounts/accounts"
    12  )
    13  
    14  type PayloadMounter interface {
    15  	PayloadLocker
    16  
    17  	// Mount Loads the payload into the PayloadManager's state
    18  	Mount() error
    19  
    20  	// ToSend returns an outbound safe (encrypted) payload
    21  	ToSend() []byte
    22  }
    23  
    24  type PayloadLoader interface {
    25  	Load() error
    26  }
    27  
    28  type BasePayloadMounter struct {
    29  	*PayloadLockPayload
    30  	*PayloadToSend
    31  
    32  	loader     PayloadLoader
    33  	marshaller ProtobufMarshaller
    34  	encryptor  *PayloadEncryptor
    35  }
    36  
    37  func NewBasePayloadMounter(loader PayloadLoader, marshaller ProtobufMarshaller, e *PayloadEncryptor) *BasePayloadMounter {
    38  	return &BasePayloadMounter{
    39  		PayloadLockPayload: &PayloadLockPayload{e},
    40  		PayloadToSend:      &PayloadToSend{e},
    41  		loader:             loader,
    42  		marshaller:         marshaller,
    43  		encryptor:          e,
    44  	}
    45  }
    46  
    47  // Mount loads and prepares the payload to be stored in the PayloadLoader's state ready for later access
    48  func (bpm *BasePayloadMounter) Mount() error {
    49  	err := bpm.loader.Load()
    50  	if err != nil {
    51  		return err
    52  	}
    53  
    54  	p, err := bpm.marshaller.MarshalProtobuf()
    55  	if err != nil {
    56  		return err
    57  	}
    58  
    59  	return bpm.encryptor.encrypt(p)
    60  }
    61  
    62  /*
    63  |--------------------------------------------------------------------------
    64  | AccountPayload
    65  |--------------------------------------------------------------------------
    66  |
    67  | AccountPayloadMounter, AccountPayloadLoader and AccountPayloadMarshaller
    68  |
    69  */
    70  
    71  // NewAccountPayloadMounter generates a new and initialised AccountPayload flavoured BasePayloadMounter
    72  // responsible for the whole lifecycle of an AccountPayload
    73  func NewAccountPayloadMounter(pe *PayloadEncryptor, config *SenderConfig, logger *zap.Logger) (*BasePayloadMounter, error) {
    74  	l := logger.Named("AccountPayloadLoader")
    75  	l.Debug("fired", zap.Any("config", config))
    76  
    77  	pe = pe.Renew()
    78  
    79  	// A new SHARED AccountPayload
    80  	p := new(AccountPayload)
    81  	apl, err := NewAccountPayloadLoader(p, config)
    82  	if err != nil {
    83  		return nil, err
    84  	}
    85  
    86  	return NewBasePayloadMounter(
    87  		apl,
    88  		NewPairingPayloadMarshaller(p, l),
    89  		pe,
    90  	), nil
    91  }
    92  
    93  // AccountPayloadLoader is responsible for loading, parsing and validating AccountPayload data
    94  type AccountPayloadLoader struct {
    95  	*AccountPayload
    96  
    97  	multiaccountsDB *multiaccounts.Database
    98  	keystorePath    string
    99  	keyUID          string
   100  }
   101  
   102  func NewAccountPayloadLoader(p *AccountPayload, config *SenderConfig) (*AccountPayloadLoader, error) {
   103  	ppr := &AccountPayloadLoader{
   104  		AccountPayload: p,
   105  	}
   106  
   107  	if config == nil {
   108  		return ppr, nil
   109  	}
   110  
   111  	ppr.multiaccountsDB = config.DB
   112  	ppr.keyUID = config.KeyUID
   113  	ppr.password = config.Password
   114  	ppr.chatKey = config.ChatKey
   115  	ppr.keystorePath = config.KeystorePath
   116  	return ppr, nil
   117  }
   118  
   119  func (apl *AccountPayloadLoader) Load() error {
   120  	apl.keys = make(map[string][]byte)
   121  	err := loadKeys(apl.keys, apl.keystorePath)
   122  	if err != nil {
   123  		return err
   124  	}
   125  
   126  	err = validateKeys(apl.keys, apl.password)
   127  	if err != nil {
   128  		return err
   129  	}
   130  
   131  	apl.multiaccount, err = apl.multiaccountsDB.GetAccount(apl.keyUID)
   132  	if err != nil {
   133  		return err
   134  	}
   135  
   136  	return nil
   137  }
   138  
   139  /*
   140  |--------------------------------------------------------------------------
   141  | RawMessagePayload
   142  |--------------------------------------------------------------------------
   143  |
   144  | RawMessagePayloadMounter and RawMessageLoader
   145  |
   146  */
   147  
   148  // NewRawMessagePayloadMounter generates a new and initialised RawMessagePayload flavoured BasePayloadMounter
   149  // responsible for the whole lifecycle of an RawMessagePayload
   150  func NewRawMessagePayloadMounter(logger *zap.Logger, pe *PayloadEncryptor, backend *api.GethStatusBackend, config *SenderConfig) *BasePayloadMounter {
   151  	pe = pe.Renew()
   152  	payload := NewRawMessagesPayload()
   153  
   154  	return NewBasePayloadMounter(
   155  		NewRawMessageLoader(backend, payload, config),
   156  		NewRawMessagePayloadMarshaller(payload),
   157  		pe,
   158  	)
   159  }
   160  
   161  type RawMessageLoader struct {
   162  	payload               *RawMessagesPayload
   163  	syncRawMessageHandler *SyncRawMessageHandler
   164  	keyUID                string
   165  	deviceType            string
   166  }
   167  
   168  func NewRawMessageLoader(backend *api.GethStatusBackend, payload *RawMessagesPayload, config *SenderConfig) *RawMessageLoader {
   169  	return &RawMessageLoader{
   170  		syncRawMessageHandler: NewSyncRawMessageHandler(backend),
   171  		payload:               payload,
   172  		keyUID:                config.KeyUID,
   173  		deviceType:            config.DeviceType,
   174  	}
   175  }
   176  
   177  func (r *RawMessageLoader) Load() (err error) {
   178  	r.payload.rawMessages, r.payload.profileKeypair, r.payload.setting, err = r.syncRawMessageHandler.PrepareRawMessage(r.keyUID, r.deviceType)
   179  	return err
   180  }
   181  
   182  /*
   183  |--------------------------------------------------------------------------
   184  | InstallationPayload
   185  |--------------------------------------------------------------------------
   186  |
   187  | InstallationPayloadMounter and InstallationPayloadLoader
   188  |
   189  */
   190  
   191  // NewInstallationPayloadMounter generates a new and initialised InstallationPayload flavoured BasePayloadMounter
   192  // responsible for the whole lifecycle of an InstallationPayload
   193  func NewInstallationPayloadMounter(pe *PayloadEncryptor, backend *api.GethStatusBackend, deviceType string) *BasePayloadMounter {
   194  	pe = pe.Renew()
   195  	payload := NewRawMessagesPayload()
   196  
   197  	return NewBasePayloadMounter(
   198  		NewInstallationPayloadLoader(backend, payload, deviceType),
   199  		NewRawMessagePayloadMarshaller(payload),
   200  		pe,
   201  	)
   202  }
   203  
   204  type InstallationPayloadLoader struct {
   205  	payload               *RawMessagesPayload
   206  	syncRawMessageHandler *SyncRawMessageHandler
   207  	deviceType            string
   208  }
   209  
   210  func NewInstallationPayloadLoader(backend *api.GethStatusBackend, payload *RawMessagesPayload, deviceType string) *InstallationPayloadLoader {
   211  	return &InstallationPayloadLoader{
   212  		payload:               payload,
   213  		syncRawMessageHandler: NewSyncRawMessageHandler(backend),
   214  		deviceType:            deviceType,
   215  	}
   216  }
   217  
   218  func (r *InstallationPayloadLoader) Load() error {
   219  	rawMessageCollector := new(RawMessageCollector)
   220  	err := r.syncRawMessageHandler.CollectInstallationData(rawMessageCollector, r.deviceType)
   221  	if err != nil {
   222  		return err
   223  	}
   224  	rms := rawMessageCollector.convertToSyncRawMessage()
   225  	r.payload.rawMessages = rms.RawMessages
   226  	return nil
   227  }
   228  
   229  /*
   230  |--------------------------------------------------------------------------
   231  | PayloadMounters
   232  |--------------------------------------------------------------------------
   233  |
   234  | Funcs for all PayloadMounters AccountPayloadMounter, RawMessagePayloadMounter and InstallationPayloadMounter
   235  |
   236  */
   237  
   238  // NewPayloadMounters returns PayloadMounter s configured to handle local pairing transfers of:
   239  //   - AccountPayload, RawMessagePayload and InstallationPayload
   240  func NewPayloadMounters(logger *zap.Logger, pe *PayloadEncryptor, backend *api.GethStatusBackend, config *SenderConfig) (PayloadMounter, PayloadMounter, PayloadMounterReceiver, error) {
   241  	am, err := NewAccountPayloadMounter(pe, config, logger)
   242  	if err != nil {
   243  		return nil, nil, nil, err
   244  	}
   245  	rmm := NewRawMessagePayloadMounter(logger, pe, backend, config)
   246  	imr := NewInstallationPayloadMounterReceiver(pe, backend, config.DeviceType)
   247  	return am, rmm, imr, nil
   248  }
   249  
   250  /*
   251  |--------------------------------------------------------------------------
   252  | KeystoreFilesPayload
   253  |--------------------------------------------------------------------------
   254  */
   255  
   256  func NewKeystoreFilesPayloadMounter(backend *api.GethStatusBackend, pe *PayloadEncryptor, config *KeystoreFilesSenderConfig, logger *zap.Logger) (*BasePayloadMounter, error) {
   257  	l := logger.Named("KeystoreFilesPayloadLoader")
   258  	l.Debug("fired", zap.Any("config", config))
   259  
   260  	pe = pe.Renew()
   261  
   262  	// A new SHARED AccountPayload
   263  	p := new(AccountPayload)
   264  	kfpl, err := NewKeystoreFilesPayloadLoader(backend, p, config)
   265  	if err != nil {
   266  		return nil, err
   267  	}
   268  
   269  	return NewBasePayloadMounter(
   270  		kfpl,
   271  		NewPairingPayloadMarshaller(p, l),
   272  		pe,
   273  	), nil
   274  }
   275  
   276  type KeystoreFilesPayloadLoader struct {
   277  	*AccountPayload
   278  
   279  	keystorePath            string
   280  	loggedInKeyUID          string
   281  	keystoreFilesToTransfer []string
   282  }
   283  
   284  func NewKeystoreFilesPayloadLoader(backend *api.GethStatusBackend, p *AccountPayload, config *KeystoreFilesSenderConfig) (*KeystoreFilesPayloadLoader, error) {
   285  	if config == nil {
   286  		return nil, fmt.Errorf("empty keystore files sender config")
   287  	}
   288  
   289  	kfpl := &KeystoreFilesPayloadLoader{
   290  		AccountPayload: p,
   291  		keystorePath:   config.KeystorePath,
   292  		loggedInKeyUID: config.LoggedInKeyUID,
   293  	}
   294  
   295  	kfpl.password = config.Password
   296  
   297  	accountService := backend.StatusNode().AccountService()
   298  
   299  	for _, keyUID := range config.KeypairsToExport {
   300  		kp, err := accountService.GetKeypairByKeyUID(keyUID)
   301  		if err != nil {
   302  			return nil, err
   303  		}
   304  
   305  		if kp.Type == accounts.KeypairTypeSeed {
   306  			kfpl.keystoreFilesToTransfer = append(kfpl.keystoreFilesToTransfer, kp.DerivedFrom[2:])
   307  		}
   308  
   309  		for _, acc := range kp.Accounts {
   310  			kfpl.keystoreFilesToTransfer = append(kfpl.keystoreFilesToTransfer, acc.Address.Hex()[2:])
   311  		}
   312  	}
   313  
   314  	return kfpl, nil
   315  }
   316  
   317  func (kfpl *KeystoreFilesPayloadLoader) Load() error {
   318  	kfpl.keys = make(map[string][]byte)
   319  	err := loadKeys(kfpl.keys, kfpl.keystorePath)
   320  	if err != nil {
   321  		return err
   322  	}
   323  
   324  	// Create a new map to filter keys
   325  	filteredMap := make(map[string][]byte)
   326  	for _, searchKey := range kfpl.keystoreFilesToTransfer {
   327  		for key, value := range kfpl.keys {
   328  			if strings.Contains(key, strings.ToLower(searchKey)) {
   329  				filteredMap[key] = value
   330  				break
   331  			}
   332  		}
   333  	}
   334  
   335  	kfpl.keys = filteredMap
   336  
   337  	return validateKeys(kfpl.keys, kfpl.password)
   338  }