mirror of
https://github.com/basicswap/basicswap.git
synced 2024-12-22 11:39:34 +00:00
Integrate Decred with wallet encryption.
dcrwallet requires the password to be entered at the first startup when encrypted. basicswap-run with --startonlycoin=decred and the WALLET_ENCRYPTION_PWD environment var set can be used for the initial sync.
This commit is contained in:
parent
fcf234ef34
commit
76445146fb
7 changed files with 102 additions and 10 deletions
|
@ -6861,6 +6861,12 @@ class BasicSwap(BaseApp):
|
|||
self.ci(coin).setAnonTxRingSize(new_anon_tx_ring_size)
|
||||
break
|
||||
|
||||
if 'wallet_pwd' in data:
|
||||
new_wallet_pwd = data['wallet_pwd']
|
||||
if settings_cc.get('wallet_pwd', '') != new_wallet_pwd:
|
||||
settings_changed = True
|
||||
settings_cc['wallet_pwd'] = new_wallet_pwd
|
||||
|
||||
if settings_changed:
|
||||
settings_path = os.path.join(self.data_dir, cfg.CONFIG_FILENAME)
|
||||
settings_path_new = settings_path + '.new'
|
||||
|
|
|
@ -1379,7 +1379,7 @@ class BTCInterface(Secp256k1Interface):
|
|||
return True
|
||||
return False
|
||||
|
||||
def isWalletEncryptedLocked(self):
|
||||
def isWalletEncryptedLocked(self) -> (bool, bool):
|
||||
wallet_info = self.rpc_wallet('getwalletinfo')
|
||||
encrypted = 'unlocked_until' in wallet_info
|
||||
locked = encrypted and wallet_info['unlocked_until'] <= 0
|
||||
|
|
|
@ -320,6 +320,44 @@ class DCRInterface(Secp256k1Interface):
|
|||
# Load with --create
|
||||
pass
|
||||
|
||||
def isWalletEncrypted(self) -> bool:
|
||||
return True
|
||||
|
||||
def isWalletLocked(self) -> bool:
|
||||
walletislocked = self.rpc_wallet('walletislocked')
|
||||
return walletislocked
|
||||
|
||||
def isWalletEncryptedLocked(self) -> (bool, bool):
|
||||
walletislocked = self.rpc_wallet('walletislocked')
|
||||
return True, walletislocked
|
||||
|
||||
def changeWalletPassword(self, old_password: str, new_password: str):
|
||||
self._log.info('changeWalletPassword - {}'.format(self.ticker()))
|
||||
if old_password == '':
|
||||
# Read initial pwd from settings
|
||||
settings = self._sc.getChainClientSettings(self.coin_type())
|
||||
old_password = settings['wallet_pwd']
|
||||
self.rpc_wallet('walletpassphrasechange', [old_password, new_password])
|
||||
|
||||
# Lock wallet to match other coins
|
||||
self.rpc_wallet('walletlock')
|
||||
|
||||
# Clear initial password
|
||||
self._sc.editSettings(self.coin_name().lower(), {'wallet_pwd': ''})
|
||||
|
||||
def unlockWallet(self, password: str):
|
||||
if password == '':
|
||||
return
|
||||
self._log.info('unlockWallet - {}'.format(self.ticker()))
|
||||
|
||||
# Max timeout value, ~3 years
|
||||
self.rpc_wallet('walletpassphrase', [password, 100000000])
|
||||
self._sc.checkWalletSeed(self.coin_type())
|
||||
|
||||
def lockWallet(self):
|
||||
self._log.info('lockWallet - {}'.format(self.ticker()))
|
||||
self.rpc_wallet('walletlock')
|
||||
|
||||
def getWalletSeedID(self):
|
||||
masterpubkey = self.rpc_wallet('getmasterpubkey')
|
||||
masterpubkey_data = self.decode_address(masterpubkey)[4:]
|
||||
|
|
|
@ -1311,8 +1311,10 @@ def initialise_wallets(particl_wallet_mnemonic, with_coins, data_dir, settings,
|
|||
if c == Coins.DCR:
|
||||
if coin_settings['manage_wallet_daemon']:
|
||||
from basicswap.interface.dcr.util import createDCRWallet
|
||||
|
||||
dcr_password = coin_settings['wallet_pwd'] if WALLET_ENCRYPTION_PWD == '' else WALLET_ENCRYPTION_PWD
|
||||
extra_opts = ['--appdata="{}"'.format(coin_settings['datadir']),
|
||||
'--pass={}'.format(coin_settings['wallet_pwd']),
|
||||
'--pass={}'.format(dcr_password),
|
||||
]
|
||||
|
||||
filename = 'dcrwallet' + ('.exe' if os.name == 'nt' else '')
|
||||
|
@ -1381,6 +1383,9 @@ def initialise_wallets(particl_wallet_mnemonic, with_coins, data_dir, settings,
|
|||
else:
|
||||
print(f'WARNING - Failed to initialise wallet for {getCoinName(c)}: {e}')
|
||||
|
||||
if 'decred' in with_coins and WALLET_ENCRYPTION_PWD != '':
|
||||
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:
|
||||
# Print directly to stdout for tests
|
||||
|
@ -1693,7 +1698,7 @@ def main():
|
|||
'connection_type': 'rpc' if 'decred' in with_coins else 'none',
|
||||
'manage_daemon': True if ('decred' in with_coins and DCR_RPC_HOST == '127.0.0.1') else False,
|
||||
'manage_wallet_daemon': True if ('decred' in with_coins and DCR_WALLET_RPC_HOST == '127.0.0.1') else False,
|
||||
'wallet_pwd': DCR_WALLET_PWD,
|
||||
'wallet_pwd': DCR_WALLET_PWD if WALLET_ENCRYPTION_PWD == '' else '',
|
||||
'rpchost': DCR_RPC_HOST,
|
||||
'rpcport': DCR_RPC_PORT + port_offset,
|
||||
'walletrpchost': DCR_WALLET_RPC_HOST,
|
||||
|
|
|
@ -40,7 +40,7 @@ class Daemon:
|
|||
|
||||
|
||||
def is_known_coin(coin_name: str) -> bool:
|
||||
for k, v in chainparams:
|
||||
for k, v in chainparams.items():
|
||||
if coin_name == v['name']:
|
||||
return True
|
||||
return False
|
||||
|
@ -169,7 +169,11 @@ def runClient(fp, data_dir, chain, start_only_coins):
|
|||
pids_path = os.path.join(data_dir, '.pids')
|
||||
|
||||
if os.getenv('WALLET_ENCRYPTION_PWD', '') != '':
|
||||
raise ValueError('Please unset the WALLET_ENCRYPTION_PWD environment variable.')
|
||||
if 'decred' in start_only_coins:
|
||||
# Workaround for dcrwallet requiring password for initial startup
|
||||
logger.warning('Allowing set WALLET_ENCRYPTION_PWD var with --startonlycoin=decred.')
|
||||
else:
|
||||
raise ValueError('Please unset the WALLET_ENCRYPTION_PWD environment variable.')
|
||||
|
||||
if not os.path.exists(settings_path):
|
||||
raise ValueError('Settings file not found: ' + str(settings_path))
|
||||
|
@ -255,7 +259,11 @@ def runClient(fp, data_dir, chain, start_only_coins):
|
|||
filename = 'dcrwallet' + ('.exe' if os.name == 'nt' else '')
|
||||
|
||||
wallet_pwd = v['wallet_pwd']
|
||||
extra_opts.append(f'--pass="{wallet_pwd}"')
|
||||
if wallet_pwd == '':
|
||||
# Only set when in startonlycoin mode
|
||||
wallet_pwd = os.getenv('WALLET_ENCRYPTION_PWD', '')
|
||||
if wallet_pwd != '':
|
||||
extra_opts.append(f'--pass="{wallet_pwd}"')
|
||||
extra_config = {'add_datadir': False, 'stdout_to_file': True, 'stdout_filename': 'dcrwallet_stdout.log'}
|
||||
daemons.append(startDaemon(appdata, v['bindir'], filename, opts=extra_opts, extra_config=extra_config))
|
||||
pid = daemons[-1].handle.pid
|
||||
|
|
|
@ -594,6 +594,7 @@ class Test(BaseTest):
|
|||
'rpcpassword': 'test_pass' + str(node_id),
|
||||
'datadir': os.path.join(datadir, 'dcr_' + str(node_id)),
|
||||
'bindir': DCR_BINDIR,
|
||||
'wallet_pwd': 'test_pass',
|
||||
'use_csv': True,
|
||||
'use_segwit': True,
|
||||
'blocks_confirmed': 1,
|
||||
|
@ -942,8 +943,41 @@ class Test(BaseTest):
|
|||
amount_proved = ci0.verifyProofOfFunds(funds_proof[0], funds_proof[1], funds_proof[2], 'test'.encode('utf-8'))
|
||||
assert (amount_proved >= require_amount)
|
||||
|
||||
def test_009_wallet_encryption(self):
|
||||
logging.info('---------- Test {} wallet encryption'.format(self.test_coin.name))
|
||||
|
||||
for coin in ('part', 'dcr', 'xmr'):
|
||||
jsw = read_json_api(1800, f'wallets/{coin}')
|
||||
assert (jsw['encrypted'] is (True if coin == 'dcr' else False))
|
||||
assert (jsw['locked'] is False)
|
||||
|
||||
read_json_api(1800, 'setpassword', {'oldpassword': '', 'newpassword': 'notapassword123'})
|
||||
|
||||
# Entire system is locked with Particl wallet
|
||||
jsw = read_json_api(1800, 'wallets/dcr')
|
||||
assert ('Coin must be unlocked' in jsw['error'])
|
||||
|
||||
read_json_api(1800, 'unlock', {'coin': 'part', 'password': 'notapassword123'})
|
||||
|
||||
for coin in ('dcr', 'xmr'):
|
||||
jsw = read_json_api(1800, f'wallets/{coin}')
|
||||
assert (jsw['encrypted'] is True)
|
||||
assert (jsw['locked'] is True)
|
||||
|
||||
read_json_api(1800, 'lock', {'coin': 'part'})
|
||||
jsw = read_json_api(1800, 'wallets/part')
|
||||
assert ('Coin must be unlocked' in jsw['error'])
|
||||
|
||||
read_json_api(1800, 'setpassword', {'oldpassword': 'notapassword123', 'newpassword': 'notapassword456'})
|
||||
read_json_api(1800, 'unlock', {'password': 'notapassword456'})
|
||||
|
||||
for coin in ('part', 'dcr', 'xmr'):
|
||||
jsw = read_json_api(1800, f'wallets/{coin}')
|
||||
assert (jsw['encrypted'] is True)
|
||||
assert (jsw['locked'] is False)
|
||||
|
||||
def test_010_txn_size(self):
|
||||
logging.info('---------- Test {} txn_size'.format(self.test_coin.name))
|
||||
logging.info('---------- Test {} txn size'.format(self.test_coin.name))
|
||||
|
||||
swap_clients = self.swap_clients
|
||||
ci = swap_clients[0].ci(self.test_coin)
|
||||
|
|
|
@ -250,9 +250,10 @@ class Test(unittest.TestCase):
|
|||
self.update_thread_dcr = threading.Thread(target=updateThreadDCR, args=(self,))
|
||||
self.update_thread_dcr.start()
|
||||
|
||||
# Lower output split threshold for more stakeable outputs
|
||||
for i in range(NUM_NODES):
|
||||
callpartrpc(i, 'walletsettings', ['stakingoptions', {'stakecombinethreshold': 100, 'stakesplitthreshold': 200}])
|
||||
if RESET_TEST:
|
||||
# Lower output split threshold for more stakeable outputs
|
||||
for i in range(NUM_NODES):
|
||||
callpartrpc(i, 'walletsettings', ['stakingoptions', {'stakecombinethreshold': 100, 'stakesplitthreshold': 200}])
|
||||
self.update_thread = threading.Thread(target=updateThread, args=(self,))
|
||||
self.update_thread.start()
|
||||
|
||||
|
|
Loading…
Reference in a new issue