Skip to content

Commit d97fe93

Browse files
authored
feat: add xpub and cold wallet fields to keypair (#7407)
Added xpub (representing extended public key) and cold wallet (representing the cold wallet, StatusKeycard, Ledger, Trezor...) fields to keypair type and updated related database and migration files.
1 parent dd1403b commit d97fe93

11 files changed

Lines changed: 94 additions & 30 deletions

File tree

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,7 @@ vendor-hash:
516516
echo "Replaced vendorHash $${CURRENT_VENDOR_HASH} with $${NEW_VENDOR_HASH}"
517517

518518

519-
migration: DEFAULT_MIGRATION_PATH := appdatabase/migrations/sql
519+
migration: DEFAULT_MIGRATION_PATH := internal/db/appdatabase/migrations/sql
520520
migration:
521521
touch $(DEFAULT_MIGRATION_PATH)/$$(date '+%s')_$(D).up.sql
522522

@@ -534,7 +534,7 @@ version:
534534
tag-version:
535535
bash scripts/tag_version.sh $(TARGET_COMMIT)
536536

537-
migration-wallet: DEFAULT_WALLET_MIGRATION_PATH := walletdatabase/migrations/sql
537+
migration-wallet: DEFAULT_WALLET_MIGRATION_PATH := internal/db/walletdatabase/migrations/sql
538538
migration-wallet:
539539
touch $(DEFAULT_WALLET_MIGRATION_PATH)/$$(date +%s)_$(D).up.sql
540540

internal/accounts-management/persistence_operations.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,8 @@ func (m *AccountsManager) CreateKeypairFromMnemonicAndStore(mnemonic string, pas
105105
return
106106
}
107107

108-
func (m *AccountsManager) AddKeypairStoredToKeycard(keyUID string, masterAddress string, name string,
109-
walletAccounts []*types.Account, clock uint64) (keypair *types.Keypair, err error) {
108+
func (m *AccountsManager) AddKeypairStoredToKeycard(keyUID string, masterAddress string, name string, xpub string,
109+
coldWallet types.ColdWalletType, walletAccounts []*types.Account, clock uint64) (keypair *types.Keypair, err error) {
110110

111111
if len(walletAccounts) == 0 {
112112
err = ErrKeypairMustHaveAtLeastOneWalletAccount
@@ -141,6 +141,17 @@ func (m *AccountsManager) AddKeypairStoredToKeycard(keyUID string, masterAddress
141141
return
142142
}
143143

144+
position, err := m.persistence.GetPositionForNextNewAccount()
145+
if err != nil {
146+
return nil, err
147+
}
148+
149+
for _, walletAccount := range walletAccounts {
150+
walletAccount.Position = position
151+
walletAccount.Operable = types.AccountFullyOperable
152+
position++
153+
}
154+
144155
// prepare keypair
145156
keypair = &types.Keypair{
146157
Name: name,
@@ -150,6 +161,8 @@ func (m *AccountsManager) AddKeypairStoredToKeycard(keyUID string, masterAddress
150161
LastUsedDerivationIndex: 0,
151162
Clock: clock,
152163
Accounts: walletAccounts,
164+
XPub: xpub,
165+
ColdWallet: coldWallet,
153166
}
154167

155168
// store keypair to db

internal/accounts-management/types/keypair.go

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ var (
1616
type KeypairType string
1717
type AccountType string
1818
type AccountOperable string
19+
type ColdWalletType string
1920

2021
const (
2122
KeypairTypeProfile KeypairType = "profile"
@@ -34,20 +35,28 @@ const (
3435
AccountNonOperable AccountOperable = "no" // an account is non operable it is not a keycard account and there is no keystore file for it and no keystore file for the address it is derived from
3536
AccountPartiallyOperable AccountOperable = "partially" // an account is partially operable if it is not a keycard account and there is created keystore file for the address it is derived from
3637
AccountFullyOperable AccountOperable = "fully" // an account is fully operable if it is not a keycard account and there is a keystore file for it
38+
)
3739

40+
const (
41+
ColdWalletTypeNone ColdWalletType = ""
42+
ColdWalletTypeStatusKeycard ColdWalletType = "status-keycard"
43+
ColdWalletTypeLedger ColdWalletType = "ledger"
44+
ColdWalletTypeTrezor ColdWalletType = "trezor"
3845
)
3946

4047
type Keypair struct {
41-
KeyUID string `json:"key-uid"`
42-
Name string `json:"name"`
43-
Type KeypairType `json:"type"`
44-
DerivedFrom string `json:"derived-from"`
45-
LastUsedDerivationIndex uint64 `json:"last-used-derivation-index,omitempty"`
46-
SyncedFrom string `json:"synced-from,omitempty"` // keeps an info which device this keypair is added from can be one of two values defined in constants or device name (custom)
47-
Clock uint64 `json:"clock,omitempty"`
48-
Accounts []*Account `json:"accounts,omitempty"`
49-
Keycards []*Keycard `json:"keycards,omitempty"`
50-
Removed bool `json:"removed,omitempty"`
48+
KeyUID string `json:"key-uid"`
49+
Name string `json:"name"`
50+
Type KeypairType `json:"type"`
51+
DerivedFrom string `json:"derived-from"`
52+
LastUsedDerivationIndex uint64 `json:"last-used-derivation-index,omitempty"`
53+
SyncedFrom string `json:"synced-from,omitempty"` // keeps an info which device this keypair is added from can be one of two values defined in constants or device name (custom)
54+
Clock uint64 `json:"clock,omitempty"`
55+
Accounts []*Account `json:"accounts,omitempty"`
56+
Keycards []*Keycard `json:"keycards,omitempty"`
57+
Removed bool `json:"removed,omitempty"`
58+
XPub string `json:"xpub,omitempty"`
59+
ColdWallet ColdWalletType `json:"cold-wallet,omitempty"`
5160
}
5261

5362
type AccountCreationDetails struct {
@@ -146,16 +155,18 @@ func (a *Account) MarshalJSON() ([]byte, error) {
146155

147156
func (a *Keypair) MarshalJSON() ([]byte, error) {
148157
item := struct {
149-
KeyUID string `json:"key-uid"`
150-
Name string `json:"name"`
151-
Type KeypairType `json:"type"`
152-
DerivedFrom string `json:"derived-from"`
153-
LastUsedDerivationIndex uint64 `json:"last-used-derivation-index"`
154-
SyncedFrom string `json:"synced-from"`
155-
Clock uint64 `json:"clock"`
156-
Accounts []*Account `json:"accounts"`
157-
Keycards []*Keycard `json:"keycards"`
158-
Removed bool `json:"removed"`
158+
KeyUID string `json:"key-uid"`
159+
Name string `json:"name"`
160+
Type KeypairType `json:"type"`
161+
DerivedFrom string `json:"derived-from"`
162+
LastUsedDerivationIndex uint64 `json:"last-used-derivation-index"`
163+
SyncedFrom string `json:"synced-from"`
164+
Clock uint64 `json:"clock"`
165+
Accounts []*Account `json:"accounts"`
166+
Keycards []*Keycard `json:"keycards"`
167+
Removed bool `json:"removed"`
168+
XPub string `json:"xpub"`
169+
ColdWallet ColdWalletType `json:"cold-wallet"`
159170
}{
160171
KeyUID: a.KeyUID,
161172
Name: a.Name,
@@ -167,6 +178,8 @@ func (a *Keypair) MarshalJSON() ([]byte, error) {
167178
Accounts: a.Accounts,
168179
Keycards: a.Keycards,
169180
Removed: a.Removed,
181+
XPub: a.XPub,
182+
ColdWallet: a.ColdWallet,
170183
}
171184

172185
return json.Marshal(item)
@@ -184,6 +197,8 @@ func (a *Keypair) CopyKeypair() *Keypair {
184197
Accounts: make([]*Account, len(a.Accounts)),
185198
Keycards: make([]*Keycard, len(a.Keycards)),
186199
Removed: a.Removed,
200+
XPub: a.XPub,
201+
ColdWallet: a.ColdWallet,
187202
}
188203

189204
for i, acc := range a.Accounts {
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ALTER TABLE keypairs ADD COLUMN xpub VARCHAR NOT NULL DEFAULT "";
2+
ALTER TABLE keypairs ADD COLUMN cold_wallet VARCHAR NOT NULL DEFAULT "";

internal/db/multiaccounts/accounts/database.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ func (db *Database) processRows(rows *sql.Rows) ([]*accsmanagementtypes.Keypair,
105105
kpSyncedFrom sql.NullString
106106
kpClock sql.NullInt64
107107
kpRemoved sql.NullBool
108+
kpXPub sql.NullString
109+
kpColdWallet sql.NullString
108110
)
109111

110112
var (
@@ -133,6 +135,7 @@ func (db *Database) processRows(rows *sql.Rows) ([]*accsmanagementtypes.Keypair,
133135
pubkey := []byte{}
134136
err := rows.Scan(
135137
&kpKeyUID, &kpName, &kpType, &kpDerivedFrom, &kpLastUsedDerivationIndex, &kpSyncedFrom, &kpClock, &kpRemoved,
138+
&kpXPub, &kpColdWallet,
136139
&accAddress, &accKeyUID, &pubkey, &accPath, &accName, &accColorID, &accEmoji,
137140
&accWallet, &accChat, &accHidden, &accOperable, &accClock, &accCreatedAt, &accPosition, &accRemoved,
138141
&accProdPreferredChainIDs, &accTestPreferredChainIDs, &accAddressWasNotShown)
@@ -165,6 +168,12 @@ func (db *Database) processRows(rows *sql.Rows) ([]*accsmanagementtypes.Keypair,
165168
if kpRemoved.Valid {
166169
kp.Removed = kpRemoved.Bool
167170
}
171+
if kpXPub.Valid {
172+
kp.XPub = kpXPub.String
173+
}
174+
if kpColdWallet.Valid {
175+
kp.ColdWallet = accsmanagementtypes.ColdWalletType(kpColdWallet.String)
176+
}
168177
// check keypair accounts fields
169178
if accAddress.Valid {
170179
acc.Address = types2.BytesToAddress([]byte(accAddress.String))
@@ -924,11 +933,14 @@ func (db *Database) SaveOrUpdateKeypair(keypair *accsmanagementtypes.Keypair) er
924933
last_used_derivation_index = ?,
925934
synced_from = ?,
926935
clock = ?,
927-
removed = ?
936+
removed = ?,
937+
xpub = ?,
938+
cold_wallet = ?
928939
WHERE
929940
key_uid = ?;
930941
`, keypair.KeyUID, keypair.Type, keypair.DerivedFrom,
931-
keypair.Name, keypair.LastUsedDerivationIndex, keypair.SyncedFrom, keypair.Clock, keypair.Removed, keypair.KeyUID)
942+
keypair.Name, keypair.LastUsedDerivationIndex, keypair.SyncedFrom, keypair.Clock, keypair.Removed,
943+
keypair.XPub, keypair.ColdWallet, keypair.KeyUID)
932944
if err != nil {
933945
return err
934946
}

internal/db/multiaccounts/accounts/test_helper.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,8 @@ func SameKeypairs(expected, real *accsmanagementtypes.Keypair) bool {
397397
expected.DerivedFrom == real.DerivedFrom &&
398398
expected.LastUsedDerivationIndex == real.LastUsedDerivationIndex &&
399399
expected.Clock == real.Clock &&
400+
expected.XPub == real.XPub &&
401+
expected.ColdWallet == real.ColdWallet &&
400402
len(expected.Accounts) == len(real.Accounts)
401403

402404
if same {
@@ -426,6 +428,8 @@ func SameKeypairsWithDifferentSyncedFrom(expected, real *accsmanagementtypes.Key
426428
expected.DerivedFrom == real.DerivedFrom &&
427429
expected.LastUsedDerivationIndex == real.LastUsedDerivationIndex &&
428430
expected.Clock == real.Clock &&
431+
expected.XPub == real.XPub &&
432+
expected.ColdWallet == real.ColdWallet &&
429433
len(expected.Accounts) == len(real.Accounts)
430434

431435
if same && !ignoreSyncedFrom {

protocol/accounts_manager_interface.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ type AccountsManager interface {
2020
CreateKeypairFromMnemonicAndStore(mnemonic string, password string, keypairName string,
2121
walletAccount *types.AccountCreationDetails, profile bool, clock uint64) (keypair *types.Keypair, err error)
2222
AddKeypairStoredToKeycard(keyUID string, masterAddress string, name string,
23-
walletAccounts []*types.Account, clock uint64) (keypair *types.Keypair, err error)
23+
xpub string, coldWallet types.ColdWalletType, walletAccounts []*types.Account, clock uint64) (keypair *types.Keypair, err error)
2424
CreateKeypairFromPrivateKeyAndStore(privateKey string, password string, keypairName string,
2525
walletAccount *types.AccountCreationDetails, clock uint64) (keypair *types.Keypair, err error)
2626
MigrateNonProfileKeycardKeypairToApp(mnemonic string, password string, clock uint64) (string, error)

protocol/messenger_handler.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3185,6 +3185,8 @@ func (m *Messenger) handleSyncKeypair(message *protobuf.SyncKeypair, fromLocalPa
31853185
SyncedFrom: message.SyncedFrom,
31863186
Clock: message.Clock,
31873187
Removed: message.Removed,
3188+
XPub: message.Xpub,
3189+
ColdWallet: accsmanagementtypes.ColdWalletType(message.ColdWallet),
31883190
}
31893191

31903192
oldAddresses := make(map[types3.Address]bool)

protocol/messenger_wallet.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,10 @@ func (m *Messenger) AddKeypairViaSeedPhrase(mnemonic string, password string, na
128128
}
129129

130130
func (m *Messenger) AddKeypairStoredToKeycard(keyUID string, masterAddress string, name string,
131-
walletAccounts []*accsmanagementtypes.Account) (*accsmanagementtypes.Keypair, error) {
131+
xpub string, coldWallet accsmanagementtypes.ColdWalletType, walletAccounts []*accsmanagementtypes.Account) (*accsmanagementtypes.Keypair, error) {
132132
clock, _ := m.getLastClockWithRelatedChat()
133133

134-
keypair, err := m.accountsManager.AddKeypairStoredToKeycard(keyUID, masterAddress, name, walletAccounts, clock)
134+
keypair, err := m.accountsManager.AddKeypairStoredToKeycard(keyUID, masterAddress, name, xpub, coldWallet, walletAccounts, clock)
135135
if err != nil {
136136
return nil, err
137137
}
@@ -343,6 +343,8 @@ func (m *Messenger) prepareSyncKeypairMessage(kp *accsmanagementtypes.Keypair) (
343343
LastUsedDerivationIndex: kp.LastUsedDerivationIndex,
344344
SyncedFrom: kp.SyncedFrom,
345345
Removed: kp.Removed,
346+
Xpub: kp.XPub,
347+
ColdWallet: string(kp.ColdWallet),
346348
}
347349

348350
if kp.SyncedFrom == "" {

protocol/protobuf/pairing.proto

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,8 @@ message SyncKeypair {
306306
repeated SyncKeycard keycards = 9;
307307
bool removed = 10;
308308
bytes keycard_pairings = 11;
309+
string xpub = 12;
310+
string cold_wallet = 13;
309311
}
310312

311313
// this message is used for syncing accounts positions only, for syncing any other info consider

0 commit comments

Comments
 (0)