This commit is contained in:
tecnovert 2023-08-06 11:29:29 +02:00
parent 7fd60b3e82
commit 877cefb40f
6 changed files with 278 additions and 2 deletions

View file

@ -594,6 +594,9 @@ class BasicSwap(BaseApp):
return DASHInterface(self.coin_clients[coin], self.chain, self) return DASHInterface(self.coin_clients[coin], self.chain, self)
elif coin == Coins.FIRO: elif coin == Coins.FIRO:
return FIROInterface(self.coin_clients[coin], self.chain, self) return FIROInterface(self.coin_clients[coin], self.chain, self)
elif coin == Coins.VEIL:
from .interface.veil import VEILInterface
return VEILInterface(self.coin_clients[coin], self.chain, self)
else: else:
raise ValueError('Unknown coin type') raise ValueError('Unknown coin type')

View file

@ -31,6 +31,7 @@ class Coins(IntEnum):
PIVX = 11 PIVX = 11
DASH = 12 DASH = 12
FIRO = 13 FIRO = 13
VEIL = 14
chainparams = { chainparams = {
@ -327,7 +328,46 @@ chainparams = {
'min_amount': 1000, 'min_amount': 1000,
'max_amount': 100000 * COIN, 'max_amount': 100000 * COIN,
} }
} },
Coins.VEIL: {
'name': 'veil',
'ticker': 'VEIL',
'message_magic': 'Veil Signed Message:\n',
'blocks_target': 120,
'decimal_places': 8,
'has_csv': True,
'has_segwit': False,
'mainnet': {
'rpcport': 58812,
'pubkey_address': 70,
'script_address': 5,
'key_prefix': 128,
'hrp': 'bv',
'bip44': 698,
'min_amount': 1000,
'max_amount': 100000 * COIN,
},
'testnet': {
'rpcport': 58813,
'pubkey_address': 111,
'script_address': 196,
'key_prefix': 239,
'hrp': 'tv',
'bip44': 1,
'min_amount': 1000,
'max_amount': 100000 * COIN,
},
'regtest': {
'rpcport': 58823,
'pubkey_address': 111,
'script_address': 196,
'key_prefix': 239,
'hrp': 'tv',
'bip44': 1,
'min_amount': 1000,
'max_amount': 100000 * COIN,
}
},
} }
ticker_map = {} ticker_map = {}

View file

@ -0,0 +1,19 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (c) 2023 tecnovert
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
from .btc import BTCInterface
from basicswap.chainparams import Coins
class VEILInterface(BTCInterface):
@staticmethod
def coin_type():
return Coins.VEIL
@staticmethod
def txVersion() -> int:
return 2

View file

@ -126,9 +126,10 @@ class Test(BaseTest):
@classmethod @classmethod
def prepareExtraDataDir(cls, i): def prepareExtraDataDir(cls, i):
extra_opts = []
if not cls.restore_instance: if not cls.restore_instance:
seed_hex = cls.firo_seeds[i] seed_hex = cls.firo_seeds[i]
extra_opts = [f'-hdseed={seed_hex}', ] extra_opts.append(f'-hdseed={seed_hex}')
data_dir = prepareDataDir(cfg.TEST_DATADIRS, i, 'firo.conf', 'firo_', base_p2p_port=FIRO_BASE_PORT, base_rpc_port=FIRO_BASE_RPC_PORT) data_dir = prepareDataDir(cfg.TEST_DATADIRS, i, 'firo.conf', 'firo_', base_p2p_port=FIRO_BASE_PORT, base_rpc_port=FIRO_BASE_RPC_PORT)
if os.path.exists(os.path.join(cfg.FIRO_BINDIR, 'firo-wallet')): if os.path.exists(os.path.join(cfg.FIRO_BINDIR, 'firo-wallet')):
callrpc_cli(cfg.FIRO_BINDIR, data_dir, 'regtest', '-wallet=wallet.dat create', 'firo-wallet') callrpc_cli(cfg.FIRO_BINDIR, data_dir, 'regtest', '-wallet=wallet.dat create', 'firo-wallet')

View file

@ -0,0 +1,211 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (c) 2023 tecnovert
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
"""
basicswap]$ python tests/basicswap/extended/test_veil.py
"""
import os
import random
import logging
import unittest
import basicswap.config as cfg
from basicswap.basicswap import (
Coins,
SwapTypes,
BidStates,
)
from basicswap.config import (
bin_suffix,
DEFAULT_TEST_BINDIR,
)
from basicswap.contrib.test_framework.script import (
CScript,
OP_CHECKLOCKTIMEVERIFY,
OP_CHECKSEQUENCEVERIFY,
)
from basicswap.contrib.test_framework.messages import (
ToHex,
FromHex,
CTxIn,
COutPoint,
CTransaction,
CTxInWitness,
)
from basicswap.util import (
COIN,
)
from tests.basicswap.util import (
read_json_api,
)
from basicswap.rpc import (
waitForRPC,
)
from tests.basicswap.common import (
stopDaemons,
prepareDataDir,
make_rpc_func,
wait_for_bid,
wait_for_offer,
wait_for_in_progress,
)
from bin.basicswap_run import startDaemon
from basicswap.contrib.rpcauth import generate_salt, password_to_hmac
from tests.basicswap.test_xmr import BaseTest, test_delay_event, callnoderpc
from tests.basicswap.test_btc_xmr import TestFunctions
# Why won't this work!?
# from tests.basicswap.test_btc_xmr import BasicSwapTest
logger = logging.getLogger()
VEIL_BASE_PORT = 34842
VEIL_BASE_RPC_PORT = 35842
VEIL_BASE_ZMQ_PORT = 36842
VEIL_BINDIR = os.path.expanduser(os.getenv('VEIL_BINDIR', os.path.join(DEFAULT_TEST_BINDIR, 'veil')))
VEILD = os.getenv('VEILD', 'veild' + bin_suffix)
VEIL_CLI = os.getenv('VEIL_CLI', 'veil-cli' + bin_suffix)
VEIL_TX = os.getenv('VEIL_TX', 'veil-tx' + bin_suffix)
#class TestVEIL(BaseTest):
class TestVEIL(TestFunctions):
__test__ = True
test_coin_from = Coins.VEIL
base_rpc_port = VEIL_BASE_RPC_PORT
start_xmr_nodes = False
test_atomic = True
test_xmr = True
veil_daemons = []
veil_addr = None
# Particl node mnemonics are set in test/basicswap/mnemonics.py
veil_seeds = [
'd90b7ed1be614e1c172653aee1f3b6230f43b7fa99cf07fa984a17966ad81de7',
'6c81d6d74ba33a0db9e41518c2b6789fbe938e98018a4597dac661cfc5f2dfc1',
'c5de2be44834e7e47ad7dc8e35c6b77c79f17c6bb40d5509a00fc3dff384a865',
]
@classmethod
def prepareExtraDataDir(cls, i):
extra_opts = []
if not cls.restore_instance:
seed_hex = cls.veil_seeds[i]
extra_opts.append(f'-importseed={seed_hex}')
data_dir = prepareDataDir(cfg.TEST_DATADIRS, i, 'veil.conf', 'veil_', base_p2p_port=VEIL_BASE_PORT, base_rpc_port=VEIL_BASE_RPC_PORT)
cls.veil_daemons.append(startDaemon(os.path.join(cfg.TEST_DATADIRS, 'veil_' + str(i)), VEIL_BINDIR, VEILD, opts=extra_opts))
logging.info('Started %s %d', VEILD, cls.veil_daemons[-1].pid)
waitForRPC(make_rpc_func(i, base_rpc_port=VEIL_BASE_RPC_PORT), max_tries=12)
@classmethod
def addPIDInfo(cls, sc, i):
sc.setDaemonPID(Coins.VEIL, cls.veil_daemons[i].pid)
@classmethod
def prepareExtraCoins(cls):
if cls.restore_instance:
void_block_rewards_pubkey = cls.getRandomPubkey()
cls.veil_addr = cls.swap_clients[0].ci(Coins.VEIL).pubkey_to_address(void_block_rewards_pubkey)
else:
num_blocks = 400
cls.veil_addr = callnoderpc(0, 'getnewminingaddress', ['mining_addr'], base_rpc_port=VEIL_BASE_RPC_PORT)
logging.info('Mining %d VEIL blocks to %s', num_blocks, cls.veil_addr)
callnoderpc(0, 'generatetoaddress', [num_blocks, cls.veil_addr], base_rpc_port=VEIL_BASE_RPC_PORT)
veil_addr1 = callnoderpc(1, 'getnewbasecoinaddress', ['initial addr'], base_rpc_port=VEIL_BASE_RPC_PORT)
for i in range(5):
callnoderpc(0, 'sendtoaddress', [veil_addr1, 1000], base_rpc_port=VEIL_BASE_RPC_PORT)
# Set future block rewards to nowhere (a random address), so wallet balances stay constant
void_block_rewards_pubkey = cls.getRandomPubkey()
cls.veil_addr = cls.swap_clients[0].ci(Coins.VEIL).pubkey_to_address(void_block_rewards_pubkey)
num_blocks = 100
logging.info('Mining %d VEIL blocks to %s', num_blocks, cls.veil_addr)
# callnoderpc(0, 'generatetoaddress', [num_blocks, cls.veil_addr], base_rpc_port=VEIL_BASE_RPC_PORT)
# ERROR: CreateNewBlock: TestBlockValidity failed: time-too-new, block timestamp too far in the future (code 16)
for i in range(num_blocks):
try:
callnoderpc(0, 'generatetoaddress', [1, cls.veil_addr], base_rpc_port=VEIL_BASE_RPC_PORT)
except Exception as e:
test_delay_event.wait(1)
callnoderpc(0, 'generatetoaddress', [1, cls.veil_addr], base_rpc_port=VEIL_BASE_RPC_PORT)
@classmethod
def tearDownClass(cls):
logging.info('Finalising VEIL Test')
super(TestVEIL, cls).tearDownClass()
stopDaemons(cls.veil_daemons)
@classmethod
def addCoinSettings(cls, settings, datadir, node_id):
settings['chainclients']['veil'] = {
'connection_type': 'rpc',
'manage_daemon': False,
'rpcport': VEIL_BASE_RPC_PORT + node_id,
'rpcuser': 'test' + str(node_id),
'rpcpassword': 'test_pass' + str(node_id),
'datadir': os.path.join(datadir, 'veil_' + str(node_id)),
'bindir': VEIL_BINDIR,
'use_csv': True,
'use_segwit': True,
}
@classmethod
def coins_loop(cls):
super(TestVEIL, cls).coins_loop()
callnoderpc(0, 'generatetoaddress', [1, cls.veil_addr], base_rpc_port=VEIL_BASE_RPC_PORT)
def mineBlock(self, num_blocks=1):
self.callnoderpc('generatetoaddress', [num_blocks, self.veil_addr])
def test_002_native_segwit(self):
logging.info('---------- Test {} p2sh native segwit'.format(self.test_coin_from.name))
blockchain_info = self.callnoderpc('getblockchaininfo')
addr_segwit = self.callnoderpc('getnewbasecoinaddress')
addr_info = self.callnoderpc('getaddressinfo', [addr_segwit, ])
assert addr_info['iswitness'] is True
txid = self.callnoderpc('sendtoaddress', [addr_segwit, 1.0])
assert len(txid) == 64
tx_wallet = self.callnoderpc('gettransaction', [txid, ])['hex']
tx = self.callnoderpc('decoderawtransaction', [tx_wallet, ])
self.mineBlock()
ro = self.callnoderpc('scantxoutset', ['start', ['addr({})'.format(addr_segwit)]])
assert (len(ro['unspents']) == 1)
assert (ro['unspents'][0]['txid'] == txid)
prevout_n = -1
for txo in tx['vout']:
if addr_segwit == txo['scriptPubKey']['addresses'][0]:
prevout_n = txo['vout.n']
break
assert prevout_n > -1
tx_funded = self.callnoderpc('createrawtransaction', [[{'txid': txid, 'vout': prevout_n}], {addr_segwit: 0.99}])
tx_signed = self.callnoderpc('signrawtransactionwithwallet', [tx_funded, ])['hex']
tx_funded_decoded = self.callnoderpc('decoderawtransaction', [tx_funded, ])
tx_signed_decoded = self.callnoderpc('decoderawtransaction', [tx_signed, ])
print('[rm] tx_funded_decoded', tx_funded_decoded)
print('[rm] tx_signed_decoded', tx_signed_decoded)
assert tx_funded_decoded['txid'] == tx_signed_decoded['txid']
if __name__ == '__main__':
unittest.main()

View file

@ -346,6 +346,8 @@ class BaseTest(unittest.TestCase):
stream_stdout.setFormatter(formatter) stream_stdout.setFormatter(formatter)
logger.addHandler(stream_stdout) logger.addHandler(stream_stdout)
logging.info('Setting up tests for ' + cls.__name__)
diagrams_dir = 'doc/protocols/sequence_diagrams' diagrams_dir = 'doc/protocols/sequence_diagrams'
cls.states_bidder = extract_states_from_xu_file(os.path.join(diagrams_dir, 'ads.bidder.alt.xu'), 'B') cls.states_bidder = extract_states_from_xu_file(os.path.join(diagrams_dir, 'ads.bidder.alt.xu'), 'B')
cls.states_offerer = extract_states_from_xu_file(os.path.join(diagrams_dir, 'ads.offerer.alt.xu'), 'O') cls.states_offerer = extract_states_from_xu_file(os.path.join(diagrams_dir, 'ads.offerer.alt.xu'), 'O')