Allow Decred wallets derived from the legacy extkey.

When importing from seed dcrwallet creates two accounts, one each on coin_id 20 and 42.

Can't see how to force slip44 upgrade to run in dcrwallet, checking for either key instead.
This commit is contained in:
tecnovert 2024-05-27 15:44:48 +02:00
parent 57bc1d5ccf
commit b077561a6f
5 changed files with 24 additions and 6 deletions

View file

@ -1055,11 +1055,21 @@ class BasicSwap(BaseApp):
self.log.error(traceback.format_exc()) self.log.error(traceback.format_exc())
return return
legacy_root_hash = None
if coin_type == Coins.DCR:
legacy_root_hash = ci.getSeedHash(root_key, 20)
try: try:
session = self.openSession() session = self.openSession()
key_str = 'main_wallet_seedid_' + db_key_coin_name key_str = 'main_wallet_seedid_' + db_key_coin_name
self.setStringKV(key_str, root_hash.hex(), session) self.setStringKV(key_str, root_hash.hex(), session)
if coin_type == Coins.DCR:
# TODO: How to force getmasterpubkey to always return the new slip44 (42) key
key_str = 'main_wallet_seedid_alt_' + db_key_coin_name
self.setStringKV(key_str, legacy_root_hash.hex(), session)
session.commit() # else get error database is locked!?
# Clear any saved addresses # Clear any saved addresses
self.clearStringKV('receive_addr_' + db_key_coin_name, session) self.clearStringKV('receive_addr_' + db_key_coin_name, session)
self.clearStringKV('stealth_addr_' + db_key_coin_name, session) self.clearStringKV('stealth_addr_' + db_key_coin_name, session)
@ -2035,6 +2045,13 @@ class BasicSwap(BaseApp):
if ci.checkExpectedSeed(expect_seedid): if ci.checkExpectedSeed(expect_seedid):
ci.setWalletSeedWarning(False) ci.setWalletSeedWarning(False)
return True return True
if c == Coins.DCR:
# Try the legacy extkey
expect_seedid = self.getStringKV('main_wallet_seedid_alt_' + ci.coin_name().lower())
if ci.checkExpectedSeed(expect_seedid):
ci.setWalletSeedWarning(False)
self.log.warning('{} is using the legacy extkey.'.format(ci.coin_name()))
return True
self.log.warning('Wallet for coin {} not derived from swap seed.'.format(ci.coin_name())) self.log.warning('Wallet for coin {} not derived from swap seed.'.format(ci.coin_name()))
return False return False

View file

@ -7,10 +7,10 @@
import os import os
CONFIG_FILENAME = 'basicswap.json' CONFIG_FILENAME = 'basicswap.json'
BASICSWAP_DATADIR = os.getenv('BASICSWAP_DATADIR', '~/.basicswap') BASICSWAP_DATADIR = os.getenv('BASICSWAP_DATADIR', os.path.join('~', '.basicswap'))
DEFAULT_ALLOW_CORS = False DEFAULT_ALLOW_CORS = False
TEST_DATADIRS = os.path.expanduser(os.getenv('DATADIRS', '/tmp/basicswap')) TEST_DATADIRS = os.path.expanduser(os.getenv('DATADIRS', '/tmp/basicswap'))
DEFAULT_TEST_BINDIR = os.path.expanduser(os.getenv('DEFAULT_TEST_BINDIR', '~/.basicswap/bin')) DEFAULT_TEST_BINDIR = os.path.expanduser(os.getenv('DEFAULT_TEST_BINDIR', os.path.join('~', '.basicswap', 'bin')))
bin_suffix = ('.exe' if os.name == 'nt' else '') bin_suffix = ('.exe' if os.name == 'nt' else '')
PARTICL_BINDIR = os.path.expanduser(os.getenv('PARTICL_BINDIR', os.path.join(DEFAULT_TEST_BINDIR, 'particl'))) PARTICL_BINDIR = os.path.expanduser(os.getenv('PARTICL_BINDIR', os.path.join(DEFAULT_TEST_BINDIR, 'particl')))

View file

@ -400,14 +400,14 @@ class DCRInterface(Secp256k1Interface):
default_account_bal = balances['balances'][0] # 0 always default? default_account_bal = balances['balances'][0] # 0 always default?
return self.make_int(default_account_bal['spendable']) return self.make_int(default_account_bal['spendable'])
def getSeedHash(self, seed: bytes) -> bytes: def getSeedHash(self, seed: bytes, coin_type_id=None) -> bytes:
# m / purpose' / coin_type' / account' / change / address_index # m / purpose' / coin_type' / account' / change / address_index
# m/44'/coin_type'/0'/0/0 # m/44'/coin_type'/0'/0/0
ek = ExtKeyPair(self.coin_type()) ek = ExtKeyPair(self.coin_type())
ek.set_seed(seed) ek.set_seed(seed)
coin_type = self.chainparams_network()['bip44'] coin_type = self.chainparams_network()['bip44'] if coin_type_id is None else coin_type_id
ek_purpose = ek.derive(44 | (1 << 31)) ek_purpose = ek.derive(44 | (1 << 31))
ek_coin = ek_purpose.derive(coin_type | (1 << 31)) ek_coin = ek_purpose.derive(coin_type | (1 << 31))
ek_account = ek_coin.derive(0 | (1 << 31)) ek_account = ek_coin.derive(0 | (1 << 31))

View file

@ -18,7 +18,6 @@ def createDCRWallet(args, hex_seed, logging, delay_event):
while p.poll() is None: while p.poll() is None:
while len(select.select([pipe_r], [], [], 0)[0]) == 1: while len(select.select([pipe_r], [], [], 0)[0]) == 1:
buf = os.read(pipe_r, 1024).decode('utf-8') buf = os.read(pipe_r, 1024).decode('utf-8')
logging.debug(f'dcrwallet {buf}')
response = None response = None
if 'Use the existing configured private passphrase' in buf: if 'Use the existing configured private passphrase' in buf:
response = b'y\n' response = b'y\n'

View file

@ -1285,6 +1285,7 @@ def initialise_wallets(particl_wallet_mnemonic, with_coins, data_dir, settings,
swap_client = None swap_client = None
daemons = [] daemons = []
daemon_args = ['-noconnect', '-nodnsseed'] daemon_args = ['-noconnect', '-nodnsseed']
generated_mnemonic: bool = False
coins_failed_to_initialise = [] coins_failed_to_initialise = []
@ -1359,6 +1360,7 @@ def initialise_wallets(particl_wallet_mnemonic, with_coins, data_dir, settings,
logger.info('Loading Particl mnemonic') logger.info('Loading Particl mnemonic')
if particl_wallet_mnemonic is None: if particl_wallet_mnemonic is None:
particl_wallet_mnemonic = swap_client.callcoinrpc(Coins.PART, 'mnemonic', ['new'])['mnemonic'] particl_wallet_mnemonic = swap_client.callcoinrpc(Coins.PART, 'mnemonic', ['new'])['mnemonic']
generated_mnemonic = True
swap_client.callcoinrpc(Coins.PART, 'extkeyimportmaster', [particl_wallet_mnemonic]) swap_client.callcoinrpc(Coins.PART, 'extkeyimportmaster', [particl_wallet_mnemonic])
# Particl wallet must be unlocked to call getWalletKey # Particl wallet must be unlocked to call getWalletKey
if WALLET_ENCRYPTION_PWD != '': if WALLET_ENCRYPTION_PWD != '':
@ -1400,7 +1402,7 @@ def initialise_wallets(particl_wallet_mnemonic, with_coins, data_dir, settings,
print('WARNING - dcrwallet requires the password to be entered at the first startup when encrypted.\nPlease use basicswap-run with --startonlycoin=decred and the WALLET_ENCRYPTION_PWD environment var set for the initial sync.') print('WARNING - dcrwallet requires the password to be entered at the first startup when encrypted.\nPlease use basicswap-run with --startonlycoin=decred and the WALLET_ENCRYPTION_PWD environment var set for the initial sync.')
if particl_wallet_mnemonic is not None: if particl_wallet_mnemonic is not None:
if particl_wallet_mnemonic: if generated_mnemonic:
# Print directly to stdout for tests # Print directly to stdout for tests
print('IMPORTANT - Save your particl wallet recovery phrase:\n{}\n'.format(particl_wallet_mnemonic)) print('IMPORTANT - Save your particl wallet recovery phrase:\n{}\n'.format(particl_wallet_mnemonic))