From 1470bec744f98b3f85f791e782ec0a3035098ab3 Mon Sep 17 00:00:00 2001 From: kyranjamie Date: Fri, 6 Oct 2023 13:02:28 +0200 Subject: [PATCH] fix: regtest addresses, closes #4223 --- .../accounts/blockchain/bitcoin/bitcoin-keychain.ts | 10 +++++++--- .../bitcoin/native-segwit-account.hooks.ts | 4 +--- .../blockchain/bitcoin/taproot-account.hooks.ts | 8 ++------ .../accounts/blockchain/stacks/stacks-accounts.ts | 4 ++-- src/app/store/chains/stx-chain.slice.ts | 6 ++++-- .../store/in-memory-key/in-memory-key.selectors.ts | 5 +++-- src/app/store/in-memory-key/in-memory-key.slice.ts | 9 +++++---- src/app/store/keys/key.actions.ts | 5 +++-- src/app/store/keys/key.selectors.ts | 7 ++++--- src/app/store/keys/key.slice.ts | 6 +++--- src/app/store/ledger/bitcoin-key.slice.ts | 5 +++-- src/app/store/utils/vault-reducer-migration.spec.ts | 9 +++++---- src/shared/constants.ts | 4 ++-- src/shared/crypto/bitcoin/bitcoin.utils.ts | 12 ++++++++---- src/shared/crypto/bitcoin/p2wpkh-address-gen.ts | 7 +++++-- src/shared/utils.ts | 2 ++ 16 files changed, 59 insertions(+), 44 deletions(-) diff --git a/src/app/store/accounts/blockchain/bitcoin/bitcoin-keychain.ts b/src/app/store/accounts/blockchain/bitcoin/bitcoin-keychain.ts index e8d872f3161..f3863e6ae63 100644 --- a/src/app/store/accounts/blockchain/bitcoin/bitcoin-keychain.ts +++ b/src/app/store/accounts/blockchain/bitcoin/bitcoin-keychain.ts @@ -3,7 +3,7 @@ import { useMemo } from 'react'; import { createSelector } from '@reduxjs/toolkit'; import { HDKey, Versions } from '@scure/bip32'; -import { NetworkModes } from '@shared/constants'; +import { BitcoinNetworkModes } from '@shared/constants'; import { getBtcSignerLibNetworkConfigByMode } from '@shared/crypto/bitcoin/bitcoin.network'; import { BitcoinAccount, @@ -25,11 +25,11 @@ import { useCurrentNetwork } from '@app/store/networks/networks.selectors'; export function bitcoinAccountBuilderFactory( softwareKeychainDerivationFn: ( key: HDKey, - network: NetworkModes + network: BitcoinNetworkModes ) => (accountIndex: number) => BitcoinAccount, ledgerKeychainLookupFn: ( keyMap: Record, - network: NetworkModes + network: BitcoinNetworkModes ) => (accountIndex: number) => BitcoinAccount | undefined ) { return createSelector( @@ -42,12 +42,16 @@ export function bitcoinAccountBuilderFactory( return { mainnet: ledgerKeychainLookupFn(bitcoinLedgerKeys, 'mainnet'), testnet: ledgerKeychainLookupFn(bitcoinLedgerKeys, 'testnet'), + signet: ledgerKeychainLookupFn(bitcoinLedgerKeys, 'signet'), + regtest: ledgerKeychainLookupFn(bitcoinLedgerKeys, 'regtest'), }; } if (!rootKeychain) throw new Error('No in-memory key found'); return { mainnet: softwareKeychainDerivationFn(rootKeychain, 'mainnet'), testnet: softwareKeychainDerivationFn(rootKeychain, 'testnet'), + signet: softwareKeychainDerivationFn(rootKeychain, 'signet'), + regtest: softwareKeychainDerivationFn(rootKeychain, 'regtest'), }; } ); diff --git a/src/app/store/accounts/blockchain/bitcoin/native-segwit-account.hooks.ts b/src/app/store/accounts/blockchain/bitcoin/native-segwit-account.hooks.ts index decaef452bb..f7bd64fc2a1 100644 --- a/src/app/store/accounts/blockchain/bitcoin/native-segwit-account.hooks.ts +++ b/src/app/store/accounts/blockchain/bitcoin/native-segwit-account.hooks.ts @@ -4,7 +4,6 @@ import { useSelector } from 'react-redux'; import { createSelector } from '@reduxjs/toolkit'; import { - bitcoinNetworkModeToCoreNetworkMode, deriveAddressIndexZeroFromAccount, lookUpLedgerKeysByPath, } from '@shared/crypto/bitcoin/bitcoin.utils'; @@ -36,8 +35,7 @@ const selectNativeSegwitAccountBuilder = bitcoinAccountBuilderFactory( const selectCurrentNetworkNativeSegwitAccountBuilder = createSelector( selectNativeSegwitAccountBuilder, selectCurrentNetwork, - (nativeSegwitKeychain, network) => - nativeSegwitKeychain[bitcoinNetworkModeToCoreNetworkMode(network.chain.bitcoin.network)] + (nativeSegwitKeychains, network) => nativeSegwitKeychains[network.chain.bitcoin.network] ); export function useNativeSegwitAccountBuilder() { diff --git a/src/app/store/accounts/blockchain/bitcoin/taproot-account.hooks.ts b/src/app/store/accounts/blockchain/bitcoin/taproot-account.hooks.ts index d7f8b7c1c6a..3822447a22e 100644 --- a/src/app/store/accounts/blockchain/bitcoin/taproot-account.hooks.ts +++ b/src/app/store/accounts/blockchain/bitcoin/taproot-account.hooks.ts @@ -4,10 +4,7 @@ import { useSelector } from 'react-redux'; import { createSelector } from '@reduxjs/toolkit'; import { BitcoinNetworkModes } from '@shared/constants'; -import { - bitcoinNetworkModeToCoreNetworkMode, - lookUpLedgerKeysByPath, -} from '@shared/crypto/bitcoin/bitcoin.utils'; +import { lookUpLedgerKeysByPath } from '@shared/crypto/bitcoin/bitcoin.utils'; import { deriveTaprootAccount, getTaprootAccountDerivationPath, @@ -35,8 +32,7 @@ const selectTaprootAccountBuilder = bitcoinAccountBuilderFactory( const selectCurrentNetworkTaprootAccountBuilder = createSelector( selectTaprootAccountBuilder, selectCurrentNetwork, - (taprootKeychain, network) => - taprootKeychain[bitcoinNetworkModeToCoreNetworkMode(network.chain.bitcoin.network)] + (taprootKeychains, network) => taprootKeychains[network.chain.bitcoin.network] ); const selectCurrentTaprootAccount = createSelector( selectCurrentNetworkTaprootAccountBuilder, diff --git a/src/app/store/accounts/blockchain/stacks/stacks-accounts.ts b/src/app/store/accounts/blockchain/stacks/stacks-accounts.ts index ab866a0871e..e343f716d3a 100644 --- a/src/app/store/accounts/blockchain/stacks/stacks-accounts.ts +++ b/src/app/store/accounts/blockchain/stacks/stacks-accounts.ts @@ -13,6 +13,7 @@ import { deriveStxPrivateKey, generateWallet } from '@stacks/wallet-sdk'; import { atom } from 'jotai'; import { DATA_DERIVATION_PATH, deriveStacksSalt } from '@shared/crypto/stacks/stacks-address-gen'; +import { defaultWalletKeyId } from '@shared/utils'; import { derivePublicKey } from '@app/common/keychain/keychain'; import { createNullArrayOfLength } from '@app/common/utils'; @@ -25,7 +26,6 @@ import { import { selectLedgerKey } from '@app/store/keys/key.selectors'; import { addressNetworkVersionState } from '@app/store/transactions/transaction'; -import { defaultKeyId } from '../../../keys/key.slice'; import { HardwareStacksAccount, SoftwareStacksAccount, @@ -62,7 +62,7 @@ const selectStacksWalletState = createSelector( selectStacksChain, (keychain, chain) => { if (!keychain) return; - const { highestAccountIndex, currentAccountIndex } = chain[defaultKeyId]; + const { highestAccountIndex, currentAccountIndex } = chain[defaultWalletKeyId]; const numberOfAccountsToDerive = Math.max(highestAccountIndex, currentAccountIndex) + 1; return createNullArrayOfLength(numberOfAccountsToDerive).map((_, index) => initalizeStacksAccount(keychain, index) diff --git a/src/app/store/chains/stx-chain.slice.ts b/src/app/store/chains/stx-chain.slice.ts index 4412b542ffb..e113860285c 100644 --- a/src/app/store/chains/stx-chain.slice.ts +++ b/src/app/store/chains/stx-chain.slice.ts @@ -1,6 +1,8 @@ import { PayloadAction, createSlice } from '@reduxjs/toolkit'; -import { defaultKeyId, keySlice } from '../keys/key.slice'; +import { defaultWalletKeyId } from '@shared/utils'; + +import { keySlice } from '../keys/key.slice'; interface StxChainKeyState { highestAccountIndex: number; @@ -8,7 +10,7 @@ interface StxChainKeyState { } const initialState: Record = { - [defaultKeyId]: { + [defaultWalletKeyId]: { highestAccountIndex: 0, currentAccountIndex: 0, }, diff --git a/src/app/store/in-memory-key/in-memory-key.selectors.ts b/src/app/store/in-memory-key/in-memory-key.selectors.ts index 80bd6032180..0a9ef5ee5f2 100644 --- a/src/app/store/in-memory-key/in-memory-key.selectors.ts +++ b/src/app/store/in-memory-key/in-memory-key.selectors.ts @@ -2,16 +2,17 @@ import { useSelector } from 'react-redux'; import { createSelector } from '@reduxjs/toolkit'; +import { defaultWalletKeyId } from '@shared/utils'; + import { mnemonicToRootNode } from '@app/common/keychain/keychain'; import { RootState } from '..'; -import { defaultKeyId } from '../keys/key.slice'; const selectInMemoryKey = (state: RootState) => state.inMemoryKeys; export const selectDefaultWalletKey = createSelector( selectInMemoryKey, - state => state.keys[defaultKeyId] + state => state.keys[defaultWalletKeyId] ); export const selectRootKeychain = createSelector(selectDefaultWalletKey, key => { diff --git a/src/app/store/in-memory-key/in-memory-key.slice.ts b/src/app/store/in-memory-key/in-memory-key.slice.ts index f95ef155d7e..2daf784c312 100644 --- a/src/app/store/in-memory-key/in-memory-key.slice.ts +++ b/src/app/store/in-memory-key/in-memory-key.slice.ts @@ -1,8 +1,9 @@ import { PayloadAction, createSlice } from '@reduxjs/toolkit'; import { logger } from '@shared/logger'; +import { defaultWalletKeyId } from '@shared/utils'; -import { defaultKeyId, keySlice } from '../keys/key.slice'; +import { keySlice } from '../keys/key.slice'; interface InMemoryKeyState { hasRestoredKeys: boolean; @@ -20,15 +21,15 @@ export const inMemoryKeySlice = createSlice({ reducers: { generateWalletKey(state, action: PayloadAction) { - if (state.keys[defaultKeyId]) { + if (state.keys[defaultWalletKeyId]) { logger.warn('Not generating another wallet, already exists.'); return; } - state.keys[defaultKeyId] = action.payload; + state.keys[defaultWalletKeyId] = action.payload; }, saveUsersSecretKeyToBeRestored(state, action: PayloadAction) { - state.keys[defaultKeyId] = action.payload; + state.keys[defaultWalletKeyId] = action.payload; }, setKeysInMemory(state, action: PayloadAction>) { diff --git a/src/app/store/keys/key.actions.ts b/src/app/store/keys/key.actions.ts index 71c92cce452..fc303d57eb6 100644 --- a/src/app/store/keys/key.actions.ts +++ b/src/app/store/keys/key.actions.ts @@ -2,6 +2,7 @@ import { AddressVersion } from '@stacks/transactions'; import { decryptMnemonic, encryptMnemonic } from '@shared/crypto/mnemonic-encryption'; import { logger } from '@shared/logger'; +import { defaultWalletKeyId } from '@shared/utils'; import { identifyUser } from '@shared/utils/analytics'; import { recurseAccountsForActivity } from '@app/common/account-restoration/account-restore'; @@ -19,7 +20,7 @@ import { stxChainSlice } from '../chains/stx-chain.slice'; import { selectDefaultWalletKey } from '../in-memory-key/in-memory-key.selectors'; import { inMemoryKeySlice } from '../in-memory-key/in-memory-key.slice'; import { selectCurrentKey } from './key.selectors'; -import { defaultKeyId, keySlice } from './key.slice'; +import { keySlice } from './key.slice'; function setWalletEncryptionPassword(args: { password: string; @@ -86,7 +87,7 @@ function setWalletEncryptionPassword(args: { dispatch( keySlice.actions.createStacksSoftwareWalletComplete({ type: 'software', - id: defaultKeyId, + id: defaultWalletKeyId, salt, encryptedSecretKey, }) diff --git a/src/app/store/keys/key.selectors.ts b/src/app/store/keys/key.selectors.ts index be2e9db854a..c4c794da3b1 100644 --- a/src/app/store/keys/key.selectors.ts +++ b/src/app/store/keys/key.selectors.ts @@ -2,18 +2,19 @@ import { useSelector } from 'react-redux'; import { createSelector } from '@reduxjs/toolkit'; +import { defaultWalletKeyId } from '@shared/utils'; + import { initialSearchParams } from '@app/common/initial-search-params'; import { initBigNumber } from '@app/common/math/helpers'; import { RootState } from '@app/store'; import { selectStacksChain } from '../chains/stx-chain.selectors'; -import { defaultKeyId } from './key.slice'; const selectKeysSlice = (state: RootState) => state.keys; export const selectCurrentKey = createSelector( selectKeysSlice, - state => state.entities[defaultKeyId] + state => state.entities[defaultWalletKeyId] ); export function useCurrentKeyDetails() { @@ -25,7 +26,7 @@ export const selectCurrentAccountIndex = createSelector(selectStacksChain, state if (customAccountIndex && initBigNumber(customAccountIndex).isInteger()) { return initBigNumber(customAccountIndex).toNumber(); } - return state[defaultKeyId].currentAccountIndex; + return state[defaultWalletKeyId].currentAccountIndex; }); export const selectLedgerKey = createSelector(selectKeysSlice, keys => { diff --git a/src/app/store/keys/key.slice.ts b/src/app/store/keys/key.slice.ts index 1e2fc8a79a6..e99e5bb0a90 100644 --- a/src/app/store/keys/key.slice.ts +++ b/src/app/store/keys/key.slice.ts @@ -1,11 +1,11 @@ import { PayloadAction, createEntityAdapter, createSlice } from '@reduxjs/toolkit'; +import { defaultWalletKeyId } from '@shared/utils'; + import { StxAndIdentityPublicKeys } from '@app/features/ledger/utils/stacks-ledger-utils'; import { migrateVaultReducerStoreToNewStateStructure } from '../utils/vault-reducer-migration'; -export const defaultKeyId = 'default' as const; - interface KeyConfigSoftware { type: 'software'; id: string; @@ -38,7 +38,7 @@ export const keySlice = createSlice({ }, signOut(state) { - keyAdapter.removeOne(state, defaultKeyId); + keyAdapter.removeOne(state, defaultWalletKeyId); }, debugKillStacks(state) { diff --git a/src/app/store/ledger/bitcoin-key.slice.ts b/src/app/store/ledger/bitcoin-key.slice.ts index 8a3a36f32f4..6995edbbc54 100644 --- a/src/app/store/ledger/bitcoin-key.slice.ts +++ b/src/app/store/ledger/bitcoin-key.slice.ts @@ -1,9 +1,10 @@ import { PayloadAction, createEntityAdapter, createSlice } from '@reduxjs/toolkit'; +import { defaultWalletKeyId } from '@shared/utils'; + import { BitcoinLedgerAccountDetails } from '@app/features/ledger/utils/bitcoin-ledger-utils'; import { RootState } from '..'; -import { defaultKeyId } from '../keys/key.slice'; interface PersistedBitcoinKeys extends BitcoinLedgerAccountDetails { walletId: string; @@ -19,7 +20,7 @@ export const bitcoinKeysSlice = createSlice({ bitcoinKeyAdapter.addMany( state, // While we only support a single wallet, we default to the `default` walletId - payload.map(key => ({ ...key, walletId: defaultKeyId })) + payload.map(key => ({ ...key, walletId: defaultWalletKeyId })) ); }, }, diff --git a/src/app/store/utils/vault-reducer-migration.spec.ts b/src/app/store/utils/vault-reducer-migration.spec.ts index ca09465ca3a..584c6b76f5f 100644 --- a/src/app/store/utils/vault-reducer-migration.spec.ts +++ b/src/app/store/utils/vault-reducer-migration.spec.ts @@ -1,7 +1,8 @@ import { LocalStorageMock } from '@tests/unit/local-storage-mock'; import { vi } from 'vitest'; -import { defaultKeyId } from '../keys/key.slice'; +import { defaultWalletKeyId } from '@shared/utils'; + import { migrateVaultReducerStoreToNewStateStructure } from './vault-reducer-migration'; (globalThis as any).localStorage = new LocalStorageMock(); @@ -32,11 +33,11 @@ describe(migrateVaultReducerStoreToNewStateStructure.name, () => { test('that it returns a migrated state object when wallet values are detected', () => { const returnedValue = migrateVaultReducerStoreToNewStateStructure({} as any); expect(returnedValue).toEqual({ - ids: [defaultKeyId], + ids: [defaultWalletKeyId], entities: { - [defaultKeyId]: { + [defaultWalletKeyId]: { type: 'software', - id: defaultKeyId, + id: defaultWalletKeyId, encryptedSecretKey: 'test-encrypted-key', salt: 'test-salt', }, diff --git a/src/shared/constants.ts b/src/shared/constants.ts index de5b3469a13..c6ccd8fd1a0 100644 --- a/src/shared/constants.ts +++ b/src/shared/constants.ts @@ -26,8 +26,8 @@ export const KEBAB_REGEX = /[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g; export const MICROBLOCKS_ENABLED = !IS_TEST_ENV && true; -export const GITHUB_ORG = 'hirosystems'; -export const GITHUB_REPO = 'wallet'; +export const GITHUB_ORG = 'leather-wallet'; +export const GITHUB_REPO = 'extension'; export enum WalletDefaultNetworkConfigurationIds { mainnet = 'mainnet', diff --git a/src/shared/crypto/bitcoin/bitcoin.utils.ts b/src/shared/crypto/bitcoin/bitcoin.utils.ts index 5b9b2e27592..4cb2705f81e 100644 --- a/src/shared/crypto/bitcoin/bitcoin.utils.ts +++ b/src/shared/crypto/bitcoin/bitcoin.utils.ts @@ -5,6 +5,7 @@ import * as btc from '@scure/btc-signer'; import { BitcoinNetworkModes, NetworkModes } from '@shared/constants'; import { whenNetwork } from '@shared/utils'; +import { defaultWalletKeyId } from '@shared/utils'; import { DerivationPathDepth } from '../derivation-path.utils'; import { BtcSignerNetwork } from './bitcoin.network'; @@ -173,13 +174,16 @@ export function getHdKeyVersionsFromNetwork(network: NetworkModes) { // Ledger wallets are keyed by their derivation path. To reuse the look up logic // between payment types, this factory fn accepts a fn that generates the path export function lookUpLedgerKeysByPath( - derivationPathFn: (network: BitcoinNetworkModes, accountIndex: number) => string + getDerivationPath: (network: BitcoinNetworkModes, accountIndex: number) => string ) { - return (keyMap: Record, network: NetworkModes) => + return ( + ledgerKeyMap: Record, + network: BitcoinNetworkModes + ) => (accountIndex: number) => { - const path = derivationPathFn(network, accountIndex); + const path = getDerivationPath(network, accountIndex); // Single wallet mode, hardcoded default walletId - const account = keyMap[path.replace('m', 'default')]; + const account = ledgerKeyMap[path.replace('m', defaultWalletKeyId)]; if (!account) return; return initBitcoinAccount(path, account.policy); }; diff --git a/src/shared/crypto/bitcoin/p2wpkh-address-gen.ts b/src/shared/crypto/bitcoin/p2wpkh-address-gen.ts index cf288af4a05..e21d418c608 100644 --- a/src/shared/crypto/bitcoin/p2wpkh-address-gen.ts +++ b/src/shared/crypto/bitcoin/p2wpkh-address-gen.ts @@ -1,7 +1,7 @@ import { HDKey } from '@scure/bip32'; import * as btc from '@scure/btc-signer'; -import { BitcoinNetworkModes, NetworkModes } from '@shared/constants'; +import { BitcoinNetworkModes } from '@shared/constants'; import { DerivationPathDepth } from '../derivation-path.utils'; import { getBtcSignerLibNetworkConfigByMode } from './bitcoin.network'; @@ -26,7 +26,10 @@ export function getNativeSegwitAddressIndexDerivationPath( return getNativeSegwitAccountDerivationPath(network, accountIndex) + `/0/${addressIndex}`; } -export function deriveNativeSegwitAccountFromRootKeychain(keychain: HDKey, network: NetworkModes) { +export function deriveNativeSegwitAccountFromRootKeychain( + keychain: HDKey, + network: BitcoinNetworkModes +) { if (keychain.depth !== DerivationPathDepth.Root) throw new Error('Keychain passed is not a root'); return (accountIndex: number): BitcoinAccount => ({ type: 'p2wpkh', diff --git a/src/shared/utils.ts b/src/shared/utils.ts index 77611acbe31..b237eb3f168 100644 --- a/src/shared/utils.ts +++ b/src/shared/utils.ts @@ -55,3 +55,5 @@ export function whenNetwork(mode: NetworkModes) { export function isEmptyArray(data: unknown[]) { return data.length === 0; } + +export const defaultWalletKeyId = 'default' as const;