mirror of
https://github.com/basicswap/basicswap.git
synced 2025-11-05 10:28:10 +01:00
Decred test_008_gettxout
This commit is contained in:
@@ -7,8 +7,8 @@
|
||||
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
import select
|
||||
import subprocess
|
||||
import unittest
|
||||
|
||||
import basicswap.config as cfg
|
||||
@@ -29,11 +29,12 @@ from basicswap.interface.dcr.messages import (
|
||||
from tests.basicswap.common import (
|
||||
stopDaemons,
|
||||
waitForRPC,
|
||||
wait_for_balance,
|
||||
)
|
||||
from tests.basicswap.util import (
|
||||
read_json_api,
|
||||
REQUIRED_SETTINGS,
|
||||
)
|
||||
|
||||
from tests.basicswap.test_xmr import BaseTest, test_delay_event
|
||||
from basicswap.interface.dcr import DCRInterface
|
||||
from basicswap.interface.dcr.messages import CTransaction, CTxIn, COutPoint
|
||||
@@ -107,7 +108,7 @@ def prepareDCDDataDir(datadir, node_id, conf_file, dir_prefix, num_nodes=3):
|
||||
|
||||
class Test(BaseTest):
|
||||
__test__ = True
|
||||
test_coin_from = Coins.DCR
|
||||
test_coin = Coins.DCR
|
||||
dcr_daemons = []
|
||||
start_ltc_nodes = False
|
||||
start_xmr_nodes = False
|
||||
@@ -122,7 +123,7 @@ class Test(BaseTest):
|
||||
@classmethod
|
||||
def prepareExtraCoins(cls):
|
||||
if not cls.restore_instance:
|
||||
ci0 = cls.swap_clients[0].ci(cls.test_coin_from)
|
||||
ci0 = cls.swap_clients[0].ci(cls.test_coin)
|
||||
assert (ci0.rpc_wallet('getnewaddress') == cls.dcr_mining_addr)
|
||||
cls.dcr_ticket_account = ci0.rpc_wallet('getaccount', [cls.dcr_mining_addr, ])
|
||||
ci0.rpc('generate', [110,])
|
||||
@@ -140,7 +141,7 @@ class Test(BaseTest):
|
||||
@classmethod
|
||||
def coins_loop(cls):
|
||||
super(Test, cls).coins_loop()
|
||||
ci0 = cls.swap_clients[0].ci(cls.test_coin_from)
|
||||
ci0 = cls.swap_clients[0].ci(cls.test_coin)
|
||||
|
||||
num_passed: int = 0
|
||||
for i in range(5):
|
||||
@@ -148,7 +149,10 @@ class Test(BaseTest):
|
||||
ci0.rpc_wallet('purchaseticket', [cls.dcr_ticket_account, 0.1, 0])
|
||||
num_passed += 1
|
||||
except Exception as e:
|
||||
logging.warning('coins_loop purchaseticket {}'.format(e))
|
||||
if 'double spend' in str(e):
|
||||
pass
|
||||
else:
|
||||
logging.warning('coins_loop purchaseticket {}'.format(e))
|
||||
|
||||
try:
|
||||
if num_passed >= 5:
|
||||
@@ -230,8 +234,30 @@ class Test(BaseTest):
|
||||
'blocks_confirmed': 1,
|
||||
}
|
||||
|
||||
def prepare_balance(self, coin, amount: float, port_target_node: int, port_take_from_node: int, test_balance: bool = True) -> None:
|
||||
delay_iterations = 20
|
||||
delay_time = 3
|
||||
coin_ticker: str = coin.name
|
||||
balance_type: str = 'balance'
|
||||
address_type: str = 'deposit_address'
|
||||
js_w = read_json_api(port_target_node, 'wallets')
|
||||
current_balance: float = float(js_w[coin_ticker][balance_type])
|
||||
if test_balance and current_balance >= amount:
|
||||
return
|
||||
post_json = {
|
||||
'value': amount,
|
||||
'address': js_w[coin_ticker][address_type],
|
||||
'subfee': False,
|
||||
}
|
||||
json_rv = read_json_api(port_take_from_node, 'wallets/{}/withdraw'.format(coin_ticker.lower()), post_json)
|
||||
assert (len(json_rv['txid']) == 64)
|
||||
wait_for_amount: float = amount
|
||||
if not test_balance:
|
||||
wait_for_amount += current_balance
|
||||
wait_for_balance(test_delay_event, 'http://127.0.0.1:{}/json/wallets/{}'.format(port_target_node, coin_ticker.lower()), balance_type, wait_for_amount, iterations=delay_iterations, delay_time=delay_time)
|
||||
|
||||
def test_0001_decred_address(self):
|
||||
logging.info('---------- Test {}'.format(self.test_coin_from.name))
|
||||
logging.info('---------- Test {}'.format(self.test_coin.name))
|
||||
|
||||
coin_settings = {'rpcport': 0, 'rpcauth': 'none'}
|
||||
coin_settings.update(REQUIRED_SETTINGS)
|
||||
@@ -249,7 +275,7 @@ class Test(BaseTest):
|
||||
assert (data[2:] == pkh)
|
||||
|
||||
for i, sc in enumerate(self.swap_clients):
|
||||
loop_ci = sc.ci(self.test_coin_from)
|
||||
loop_ci = sc.ci(self.test_coin)
|
||||
root_key = sc.getWalletKey(Coins.DCR, 1)
|
||||
masterpubkey = loop_ci.rpc_wallet('getmasterpubkey')
|
||||
masterpubkey_data = loop_ci.decode_address(masterpubkey)[4:]
|
||||
@@ -261,13 +287,13 @@ class Test(BaseTest):
|
||||
assert (seed_hash == hash160(masterpubkey_data))
|
||||
|
||||
def test_001_segwit(self):
|
||||
logging.info('---------- Test {} segwit'.format(self.test_coin_from.name))
|
||||
logging.info('---------- Test {} segwit'.format(self.test_coin.name))
|
||||
|
||||
swap_clients = self.swap_clients
|
||||
ci0 = swap_clients[0].ci(self.test_coin_from)
|
||||
ci0 = swap_clients[0].ci(self.test_coin)
|
||||
assert (ci0.using_segwit() is True)
|
||||
|
||||
addr_out = ci0.rpc_wallet('getnewaddress')
|
||||
addr_out = ci0.getNewAddress()
|
||||
addr_info = ci0.rpc_wallet('validateaddress', [addr_out,])
|
||||
assert (addr_info['isvalid'] is True)
|
||||
assert (addr_info['ismine'] is True)
|
||||
@@ -294,13 +320,13 @@ class Test(BaseTest):
|
||||
assert (f_decoded['txid'] == ctx.TxHash().hex())
|
||||
|
||||
def test_003_signature_hash(self):
|
||||
logging.info('---------- Test {} signature_hash'.format(self.test_coin_from.name))
|
||||
logging.info('---------- Test {} signature_hash'.format(self.test_coin.name))
|
||||
# Test that signing a transaction manually produces the same result when signed with the wallet
|
||||
|
||||
swap_clients = self.swap_clients
|
||||
ci0 = swap_clients[0].ci(self.test_coin_from)
|
||||
ci0 = swap_clients[0].ci(self.test_coin)
|
||||
|
||||
utxos = ci0.rpc_wallet('listunspent')
|
||||
utxos = ci0.getNewAddress()
|
||||
addr_out = ci0.rpc_wallet('getnewaddress')
|
||||
rtx = ci0.rpc_wallet('createrawtransaction', [[], {addr_out: 2.0}])
|
||||
|
||||
@@ -342,15 +368,18 @@ class Test(BaseTest):
|
||||
assert (len(sent_txid) == 64)
|
||||
|
||||
def test_004_csv(self):
|
||||
logging.info('---------- Test {} csv'.format(self.test_coin_from.name))
|
||||
logging.info('---------- Test {} csv'.format(self.test_coin.name))
|
||||
swap_clients = self.swap_clients
|
||||
ci0 = swap_clients[0].ci(self.test_coin_from)
|
||||
ci0 = swap_clients[0].ci(self.test_coin)
|
||||
|
||||
script = bytearray()
|
||||
push_script_data(script, bytes((3,)))
|
||||
script += OP_CHECKSEQUENCEVERIFY.to_bytes(1)
|
||||
|
||||
script_dest = ci0.getScriptDest(script)
|
||||
script_info = ci0.rpc_wallet('decodescript', [script_dest.hex(),])
|
||||
script_addr = ci0.encodeScriptDest(script_dest)
|
||||
assert (script_info['addresses'][0] == script_addr)
|
||||
|
||||
prevout_amount: int = ci0.make_int(1.1)
|
||||
tx = CTransaction()
|
||||
@@ -388,7 +417,7 @@ class Test(BaseTest):
|
||||
push_script_data(signature_script, script)
|
||||
tx_spend.vin[0].signature_script = signature_script
|
||||
|
||||
addr_out = ci0.rpc_wallet('getnewaddress')
|
||||
addr_out = ci0.getNewAddress()
|
||||
pkh = ci0.decode_address(addr_out)[2:]
|
||||
|
||||
tx_spend.vout.append(ci0.txoType()())
|
||||
@@ -399,6 +428,7 @@ class Test(BaseTest):
|
||||
|
||||
try:
|
||||
sent_spend_txid = ci0.rpc_wallet('sendrawtransaction', [tx_spend_hex, ])
|
||||
logging.info('Sent tx spending csv output, txid: {}'.format(sent_spend_txid))
|
||||
except Exception as e:
|
||||
assert ('transaction sequence locks on inputs not met' in str(e))
|
||||
else:
|
||||
@@ -415,6 +445,135 @@ class Test(BaseTest):
|
||||
|
||||
assert (sent_spend_txid is not None)
|
||||
|
||||
def test_005_watchonly(self):
|
||||
logging.info('---------- Test {} watchonly'.format(self.test_coin.name))
|
||||
|
||||
swap_clients = self.swap_clients
|
||||
ci0 = swap_clients[0].ci(self.test_coin)
|
||||
ci1 = swap_clients[1].ci(self.test_coin)
|
||||
|
||||
addr = ci0.getNewAddress()
|
||||
pkh = ci0.decode_address(addr)[2:]
|
||||
addr_info = ci0.rpc_wallet('validateaddress', [addr,])
|
||||
|
||||
addr_script = ci0.getPubkeyHashDest(pkh).hex()
|
||||
script_info = ci0.rpc_wallet('decodescript', [addr_script,])
|
||||
assert (addr in script_info['addresses'])
|
||||
|
||||
# Importscript doesn't import an address
|
||||
ci1.rpc_wallet('importscript', [addr_script,])
|
||||
addr_info1 = ci1.rpc_wallet('validateaddress', [addr,])
|
||||
assert (addr_info1.get('ismine', False) is False)
|
||||
|
||||
# Would need to run a second wallet daemon?
|
||||
try:
|
||||
ro = ci1.rpc_wallet('importpubkey', [addr_info['pubkey'],])
|
||||
except Exception as e:
|
||||
assert ('public keys may only be imported by watching-only wallets' in str(e))
|
||||
else:
|
||||
logging.info('Expected importpubkey to fail on non watching-only wallet')
|
||||
|
||||
chain_height_last = ci1.getChainHeight()
|
||||
txid = ci0.rpc_wallet('sendtoaddress', [addr, 1])
|
||||
|
||||
found_txid = None
|
||||
for i in range(20):
|
||||
if found_txid is not None:
|
||||
break
|
||||
|
||||
chain_height_now = ci1.getChainHeight()
|
||||
while chain_height_last <= chain_height_now:
|
||||
if found_txid is not None:
|
||||
break
|
||||
try:
|
||||
check_hash = ci1.rpc('getblockhash', [chain_height_last + 1, ])
|
||||
except Exception as e:
|
||||
logging.warning('getblockhash {} failed {}'.format(chain_height_last + 1, e))
|
||||
test_delay_event.wait(1)
|
||||
break
|
||||
|
||||
chain_height_last += 1
|
||||
check_hash = ci1.rpc('getblockhash', [chain_height_last, ])
|
||||
block_tx = ci1.rpc('getblock', [check_hash, True, True])
|
||||
for tx in block_tx['rawtx']:
|
||||
if found_txid is not None:
|
||||
break
|
||||
for txo in tx['vout']:
|
||||
if addr_script == txo['scriptPubKey']['hex']:
|
||||
found_txid = tx['txid']
|
||||
logging.info('found_txid {}'.format(found_txid))
|
||||
break
|
||||
|
||||
test_delay_event.wait(1)
|
||||
|
||||
assert (found_txid is not None)
|
||||
|
||||
def test_008_gettxout(self):
|
||||
logging.info('---------- Test {} gettxout'.format(self.test_coin.name))
|
||||
|
||||
ci0 = self.swap_clients[0].ci(self.test_coin)
|
||||
|
||||
addr = ci0.getNewAddress()
|
||||
|
||||
test_amount: float = 1.0
|
||||
txid = ci0.withdrawCoin(test_amount, addr)
|
||||
assert len(txid) == 64
|
||||
|
||||
unspents = None
|
||||
for i in range(30):
|
||||
unspents = ci0.rpc_wallet('listunspent', [0, 999999999, [addr,]])
|
||||
if unspents is None:
|
||||
unspents = []
|
||||
if len(unspents) > 0:
|
||||
break
|
||||
test_delay_event.wait(1)
|
||||
assert (len(unspents) == 1)
|
||||
utxo = unspents[0]
|
||||
|
||||
txout = ci0.rpc('gettxout', [utxo['txid'], utxo['vout'], utxo['tree']])
|
||||
|
||||
# Lock utxo so it's not spent for tickets, while waiting for depth
|
||||
rv = ci0.rpc_wallet('lockunspent', [False, [utxo, ]])
|
||||
|
||||
def wait_for_depth():
|
||||
for i in range(20):
|
||||
logging.info('Waiting for txout depth, iter {}'.format(i))
|
||||
txout = ci0.rpc('gettxout', [utxo['txid'], utxo['vout'], utxo['tree']])
|
||||
if txout['confirmations'] > 0:
|
||||
return txout
|
||||
test_delay_event.wait(1)
|
||||
raise ValueError('prevout not confirmed')
|
||||
txout = wait_for_depth()
|
||||
assert (txout['confirmations'] > 0)
|
||||
assert (addr in txout['scriptPubKey']['addresses'])
|
||||
|
||||
addr_out = ci0.getNewAddress()
|
||||
rtx = ci0.rpc_wallet('createrawtransaction', [[utxo, ], {addr_out: test_amount - 0.0001}])
|
||||
stx = ci0.rpc_wallet('signrawtransaction', [rtx])
|
||||
|
||||
chain_height_before_send = ci0.getChainHeight()
|
||||
sent_txid = ci0.rpc_wallet('sendrawtransaction', [stx['hex'], ])
|
||||
|
||||
# NOTE: UTXO is still found when spent in the mempool (tested in loop, not delay from wallet to core)
|
||||
txout = ci0.rpc('gettxout', [utxo['txid'], utxo['vout'], utxo['tree']])
|
||||
assert (addr in txout['scriptPubKey']['addresses'])
|
||||
|
||||
for i in range(20):
|
||||
txout = ci0.rpc('gettxout', [utxo['txid'], utxo['vout'], utxo['tree']])
|
||||
if txout is None:
|
||||
logging.info('txout spent, height before spent {}, height spent {}'.format(chain_height_before_send, ci0.getChainHeight()))
|
||||
break
|
||||
test_delay_event.wait(1)
|
||||
assert (txout is None)
|
||||
|
||||
logging.info('Testing getProofOfFunds')
|
||||
require_amount: int = ci0.make_int(1)
|
||||
funds_proof = ci0.getProofOfFunds(require_amount, 'test'.encode('utf-8'))
|
||||
|
||||
logging.info('Testing verifyProofOfFunds')
|
||||
amount_proved = ci0.verifyProofOfFunds(funds_proof[0], funds_proof[1], funds_proof[2], 'test'.encode('utf-8'))
|
||||
assert (amount_proved >= require_amount)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
@@ -13,10 +13,10 @@ from basicswap.db import (
|
||||
Concepts,
|
||||
)
|
||||
from basicswap.basicswap import (
|
||||
Coins,
|
||||
SwapTypes,
|
||||
BidStates,
|
||||
Coins,
|
||||
DebugTypes,
|
||||
SwapTypes,
|
||||
)
|
||||
from basicswap.basicswap_util import (
|
||||
TxLockTypes,
|
||||
|
||||
Reference in New Issue
Block a user