mirror of
https://github.com/basicswap/basicswap.git
synced 2025-11-05 18:38:09 +01:00
Get Decred account key from seed.
This commit is contained in:
@@ -7,6 +7,8 @@
|
||||
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
import select
|
||||
import unittest
|
||||
|
||||
import basicswap.config as cfg
|
||||
@@ -14,6 +16,7 @@ import basicswap.config as cfg
|
||||
from basicswap.basicswap import (
|
||||
Coins,
|
||||
)
|
||||
from basicswap.util.crypto import hash160
|
||||
from basicswap.interface.dcr.rpc import (
|
||||
callrpc,
|
||||
)
|
||||
@@ -38,6 +41,7 @@ DCR_CLI = os.getenv('DCR_CLI', 'dcrctl' + cfg.bin_suffix)
|
||||
|
||||
DCR_BASE_PORT = 44932
|
||||
DCR_BASE_RPC_PORT = 45932
|
||||
DCR_BASE_WALLET_RPC_PORT = 45952
|
||||
|
||||
|
||||
def make_rpc_func(node_id, base_rpc_port):
|
||||
@@ -50,28 +54,43 @@ def make_rpc_func(node_id, base_rpc_port):
|
||||
return rpc_func
|
||||
|
||||
|
||||
def prepareDCDDataDir(datadir, node_id, conf_file, dir_prefix, base_p2p_port, base_rpc_port, num_nodes=3):
|
||||
def prepareDCDDataDir(datadir, node_id, conf_file, dir_prefix, num_nodes=3):
|
||||
node_dir = os.path.join(datadir, dir_prefix + str(node_id))
|
||||
if not os.path.exists(node_dir):
|
||||
os.makedirs(node_dir)
|
||||
cfg_file_path = os.path.join(node_dir, conf_file)
|
||||
if os.path.exists(cfg_file_path):
|
||||
return
|
||||
config = [
|
||||
'simnet=1\n',
|
||||
'debuglevel=debug\n',
|
||||
f'listen=127.0.0.1:{DCR_BASE_PORT + node_id}\n',
|
||||
f'rpclisten=127.0.0.1:{DCR_BASE_RPC_PORT + node_id}\n',
|
||||
f'rpcuser=test{node_id}\n',
|
||||
f'rpcpass=test_pass{node_id}\n',
|
||||
'notls=1\n',]
|
||||
|
||||
for i in range(0, num_nodes):
|
||||
if node_id == i:
|
||||
continue
|
||||
config.append('addpeer=127.0.0.1:{}\n'.format(DCR_BASE_PORT + i))
|
||||
|
||||
with open(cfg_file_path, 'w+') as fp:
|
||||
config = [
|
||||
'regnet=1\n', # or simnet?
|
||||
'debuglevel=debug\n',
|
||||
f'listen=127.0.0.1:{base_p2p_port + node_id}\n',
|
||||
f'rpclisten=127.0.0.1:{base_rpc_port + node_id}\n',
|
||||
f'rpcuser=test{node_id}\n',
|
||||
f'rpcpass=test_pass{node_id}\n',
|
||||
'notls=1\n',]
|
||||
for line in config:
|
||||
fp.write(line)
|
||||
|
||||
for i in range(0, num_nodes):
|
||||
if node_id == i:
|
||||
continue
|
||||
config.append('addpeer=127.0.0.1:{}\n'.format(base_p2p_port + i))
|
||||
config = [
|
||||
'simnet=1\n',
|
||||
'debuglevel=debug\n',
|
||||
f'rpclisten=127.0.0.1:{DCR_BASE_WALLET_RPC_PORT + node_id}\n',
|
||||
f'rpcconnect=127.0.0.1:{DCR_BASE_RPC_PORT + node_id}\n',
|
||||
f'username=test{node_id}\n',
|
||||
f'password=test_pass{node_id}\n',
|
||||
'noservertls=1\n',
|
||||
'noclienttls=1\n',]
|
||||
|
||||
wallet_cfg_file_path = os.path.join(node_dir, 'dcrwallet.conf')
|
||||
with open(wallet_cfg_file_path, 'w+') as fp:
|
||||
for line in config:
|
||||
fp.write(line)
|
||||
|
||||
@@ -83,6 +102,12 @@ class Test(BaseTest):
|
||||
start_ltc_nodes = False
|
||||
start_xmr_nodes = False
|
||||
|
||||
hex_seeds = [
|
||||
'e8574b2a94404ee62d8acc0258cab4c0defcfab8a5dfc2f4954c1f9d7e09d72a',
|
||||
'10689fc6378e5f318b663560012673441dcdd8d796134e6021a4248cc6342cc6',
|
||||
'efc96ffe4fee469407826841d9700ef0a0735b0aa5ec5e7a4aa9bc1afd9a9a30', # Won't match main seed, as it's set randomly
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def prepareExtraCoins(cls):
|
||||
pass
|
||||
@@ -103,7 +128,7 @@ class Test(BaseTest):
|
||||
def prepareExtraDataDir(cls, i):
|
||||
extra_opts = []
|
||||
if not cls.restore_instance:
|
||||
data_dir = prepareDCDDataDir(cfg.TEST_DATADIRS, i, 'dcrd.conf', 'dcr_', base_p2p_port=DCR_BASE_PORT, base_rpc_port=DCR_BASE_RPC_PORT)
|
||||
data_dir = prepareDCDDataDir(cfg.TEST_DATADIRS, i, 'dcrd.conf', 'dcr_')
|
||||
|
||||
appdata = os.path.join(cfg.TEST_DATADIRS, 'dcr_' + str(i))
|
||||
datadir = os.path.join(appdata, 'data')
|
||||
@@ -113,12 +138,52 @@ class Test(BaseTest):
|
||||
|
||||
waitForRPC(make_rpc_func(i, base_rpc_port=DCR_BASE_RPC_PORT), test_delay_event, rpc_command='getnetworkinfo', max_tries=12)
|
||||
|
||||
logging.info('Creating wallet')
|
||||
extra_opts.append('--pass=test_pass')
|
||||
args = [os.path.join(DCR_BINDIR, DCR_WALLET), '--create'] + extra_opts
|
||||
(pipe_r, pipe_w) = os.pipe() # subprocess.PIPE is buffered, blocks when read
|
||||
p = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=pipe_w, stderr=pipe_w)
|
||||
|
||||
try:
|
||||
while p.poll() is None:
|
||||
while len(select.select([pipe_r], [], [], 0)[0]) == 1:
|
||||
buf = os.read(pipe_r, 1024).decode('utf-8')
|
||||
response = None
|
||||
if 'Use the existing configured private passphrase' in buf:
|
||||
response = b'y\n'
|
||||
elif 'Do you want to add an additional layer of encryption' in buf:
|
||||
response = b'n\n'
|
||||
elif 'Do you have an existing wallet seed' in buf:
|
||||
response = b'y\n'
|
||||
elif 'Enter existing wallet seed' in buf:
|
||||
response = (cls.hex_seeds[i] + '\n').encode('utf-8')
|
||||
else:
|
||||
raise ValueError(f'Unexpected output: {buf}')
|
||||
if response is not None:
|
||||
p.stdin.write(response)
|
||||
p.stdin.flush()
|
||||
test_delay_event.wait(0.1)
|
||||
except Exception as e:
|
||||
logging.error(f'{DCR_WALLET} --create failed: {e}')
|
||||
finally:
|
||||
if p.poll() is None:
|
||||
p.terminate()
|
||||
os.close(pipe_r)
|
||||
os.close(pipe_w)
|
||||
p.stdin.close()
|
||||
|
||||
cls.dcr_daemons.append(startDaemon(appdata, DCR_BINDIR, DCR_WALLET, opts=extra_opts, extra_config={'add_datadir': False, 'stdout_to_file': True, 'stdout_filename': 'dcrwallet_stdout.log'}))
|
||||
logging.info('Started %s %d', DCR_WALLET, cls.dcr_daemons[-1].handle.pid)
|
||||
|
||||
waitForRPC(make_rpc_func(i, base_rpc_port=DCR_BASE_WALLET_RPC_PORT), test_delay_event, rpc_command='getinfo', max_tries=12)
|
||||
|
||||
@classmethod
|
||||
def addCoinSettings(cls, settings, datadir, node_id):
|
||||
settings['chainclients']['decred'] = {
|
||||
'connection_type': 'rpc',
|
||||
'manage_daemon': False,
|
||||
'rpcport': DCR_BASE_RPC_PORT + node_id,
|
||||
'walletrpcport': DCR_BASE_WALLET_RPC_PORT + node_id,
|
||||
'rpcuser': 'test' + str(node_id),
|
||||
'rpcpassword': 'test_pass' + str(node_id),
|
||||
'datadir': os.path.join(datadir, 'dcr_' + str(node_id)),
|
||||
@@ -128,7 +193,7 @@ class Test(BaseTest):
|
||||
'blocks_confirmed': 1,
|
||||
}
|
||||
|
||||
def test_001_decred(self):
|
||||
def test_0001_decred_address(self):
|
||||
logging.info('---------- Test {}'.format(self.test_coin_from.name))
|
||||
|
||||
coin_settings = {'rpcport': 0, 'rpcauth': 'none'}
|
||||
@@ -146,6 +211,26 @@ class Test(BaseTest):
|
||||
data = ci.decode_address(address)
|
||||
assert (data[2:] == pkh)
|
||||
|
||||
def test_001_segwit(self):
|
||||
logging.info('---------- Test {} segwit'.format(self.test_coin_from.name))
|
||||
|
||||
swap_clients = self.swap_clients
|
||||
|
||||
ci = swap_clients[0].ci(self.test_coin_from)
|
||||
assert (ci.using_segwit() is True)
|
||||
|
||||
for i, sc in enumerate(swap_clients):
|
||||
loop_ci = sc.ci(self.test_coin_from)
|
||||
root_key = sc.getWalletKey(Coins.DCR, 1)
|
||||
masterpubkey = loop_ci.rpc_wallet('getmasterpubkey')
|
||||
masterpubkey_data = loop_ci.decode_address(masterpubkey)[4:]
|
||||
|
||||
seed_hash = loop_ci.getSeedHash(root_key)
|
||||
if i == 0:
|
||||
assert (masterpubkey == 'spubVV1z2AFYjVZvzM45FSaWMPRqyUoUwyW78wfANdjdNG6JGCXrr8AbRvUgYb3Lm1iun9CgHew1KswdePryNLKEnBSQ82AjNpYdQgzXPUme9c6')
|
||||
if i < 2:
|
||||
assert (seed_hash == hash160(masterpubkey_data))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
@@ -23,8 +23,10 @@ from coincurve.keys import (
|
||||
PrivateKey)
|
||||
|
||||
from basicswap.util import i2b, h2b
|
||||
from basicswap.util.integer import encode_varint, decode_varint
|
||||
from basicswap.util.address import decodeAddress
|
||||
from basicswap.util.crypto import ripemd160, hash160, blake256
|
||||
from basicswap.util.extkey import ExtKeyPair
|
||||
from basicswap.util.integer import encode_varint, decode_varint
|
||||
from basicswap.util.network import is_private_ip_address
|
||||
from basicswap.util.rfc2440 import rfc2440_hash_password
|
||||
from basicswap.util_xmr import encode_address as xmr_encode_address
|
||||
@@ -312,7 +314,7 @@ class Test(unittest.TestCase):
|
||||
assert ('10.00000000' == format_amount(amount_to_recreate, scale_to))
|
||||
|
||||
coin_settings = {'rpcport': 0, 'rpcauth': 'none', 'walletrpcport': 0, 'walletrpcauth': 'none'}
|
||||
coin_settings.update(self.REQUIRED_SETTINGS)
|
||||
coin_settings.update(REQUIRED_SETTINGS)
|
||||
ci_xmr = XMRInterface(coin_settings, 'regtest')
|
||||
ci_btc = BTCInterface(coin_settings, 'regtest')
|
||||
|
||||
@@ -480,6 +482,37 @@ class Test(unittest.TestCase):
|
||||
for expect_hash, data in test_vectors:
|
||||
assert (blake256(data).hex() == expect_hash)
|
||||
|
||||
def test_extkey(self):
|
||||
|
||||
test_key = 'XPARHAr37YxmFP8wyjkaHAQWmp84GiyLikL7EL8j9BCx4LkB8Q1Bw5Kr8sA1GA3Ym53zNLcaxxFHr6u81JVTeCaD61c6fKS1YRAuti8Zu5SzJCjh'
|
||||
test_key_c0 = 'XPARHAt1XMcNYAwP5wEnQXknBAkGSzaetdZt2eoJZehdB4WXfV1xbSjpgHe44AivmumcSejW5KaYx6L5M6MyR1WyXrsWTwaiUEfHq2RrqCfXj3ZW'
|
||||
test_key_c0_p = 'PPARTKPL4rp5WLnrYP6jZfuRjx6jrmvbsz5QdHofPfFqJdm918mQwdPLq6Dd9TkdbQeKUqjbHWkyzWe7Pftd7itzm7ETEoUMq4cbG4fY9FKH1YSU'
|
||||
test_key_c0h = 'XPARHAt1XMcNgWbv48LwoQbjs1bC8kCXKomzvJLRT5xmbQ2GKf9e8Vfr1MMcfiWJC34RyDp5HvAfjeiNyLDfkFm1UrRCrPkVC9GGaAWa3nXMWew8'
|
||||
|
||||
ek_data = decodeAddress(test_key)[4:]
|
||||
|
||||
ek = ExtKeyPair()
|
||||
ek.decode(ek_data)
|
||||
assert (ek.encode_v() == ek_data)
|
||||
|
||||
m_0 = ek.derive(0)
|
||||
|
||||
ek_c0_data = decodeAddress(test_key_c0)[4:]
|
||||
assert (m_0.encode_v() == ek_c0_data)
|
||||
|
||||
child_no: int = 0 | (1 << 31)
|
||||
m_0h = ek.derive(child_no)
|
||||
|
||||
ek_c0h_data = decodeAddress(test_key_c0h)[4:]
|
||||
assert (m_0h.encode_v() == ek_c0h_data)
|
||||
|
||||
ek.neuter()
|
||||
assert (ek.has_key() is False)
|
||||
m_0 = ek.derive(0)
|
||||
|
||||
ek_c0_p_data = decodeAddress(test_key_c0_p)[4:]
|
||||
assert (m_0.encode_p() == ek_c0_p_data)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user