pytest: generalize tests.

Anchor outputs break many assumptions in our tests:

1. Remove some hardcoded numbers in favor of a fee calc, so we only have to
   change in one place.
   FIXME: This should also be done for elements!
2. Do binary search to get feerate for a given closing fee.
3. Don't assume output #0: anchor outputs perturb them.
4. Don't assume we can make 1ksat channels (anchors cost 660 sats!).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell
2020-08-14 11:00:39 +09:30
parent f0afd060db
commit 8cf2fff91b
6 changed files with 33 additions and 12 deletions

View File

@@ -4,7 +4,7 @@ from pyln.client import RpcError
from shutil import copyfile
from utils import (
only_one, sync_blockheight, wait_for, DEVELOPER, TIMEOUT,
account_balance, first_channel_id
account_balance, first_channel_id, basic_fee
)
import os
@@ -19,7 +19,7 @@ import unittest
def test_closing(node_factory, bitcoind, chainparams):
l1, l2 = node_factory.line_graph(2)
chan = l1.get_channel_scid(l2)
fee = 5430 if not chainparams['elements'] else 8955
fee = basic_fee(7500) if not chainparams['elements'] else 8955
l1.pay(l2, 200000000)
@@ -358,8 +358,20 @@ def test_closing_specified_destination(node_factory, bitcoind, chainparams):
def closing_negotiation_step(node_factory, bitcoind, chainparams, opts):
orate = 29006 # closing fee negotiation starts at 21000
prate = 27625 # closing fee negotiation starts at 20000
def feerate_for(target, minimum=0, maximum=10000000):
"""Binary search to find feerate"""
assert minimum != maximum
mid = (minimum + maximum) // 2
mid_fee = basic_fee(mid)
if mid_fee > target:
return feerate_for(target, minimum, mid)
elif mid_fee < target:
return feerate_for(target, mid, maximum)
else:
return mid
orate = feerate_for(21000) # closing fee negotiation starts at 21000
prate = feerate_for(20000) # closing fee negotiation starts at 20000
opener, peer = node_factory.line_graph(2, opts=[{'feerates': (orate, orate, orate, orate)},
{'feerates': (prate, prate, prate, prate)}])
@@ -1672,7 +1684,7 @@ def test_onchain_all_dust(node_factory, bitcoind, executor):
l1.wait_for_onchaind_broadcast('IGNORING_TINY_PAYMENT',
'THEIR_UNILATERAL/OUR_HTLC')
l1.daemon.wait_for_log('Ignoring output 0 of .*: THEIR_UNILATERAL/OUR_HTLC')
l1.daemon.wait_for_log('Ignoring output .* of .*: THEIR_UNILATERAL/OUR_HTLC')
# 100 deep and l2 forgets.
bitcoind.generate_block(93)
@@ -2204,7 +2216,7 @@ def test_permfail(node_factory, bitcoind):
return (
len(billboard) == 2
and billboard[0] == 'ONCHAIN:Tracking our own unilateral close'
and re.fullmatch(r'ONCHAIN:.* outputs unresolved: in 4 blocks will spend DELAYED_OUTPUT_TO_US \(.*:0\) using OUR_DELAYED_RETURN_TO_WALLET', billboard[1])
and re.fullmatch(r'ONCHAIN:.* outputs unresolved: in 4 blocks will spend DELAYED_OUTPUT_TO_US \(.*:.*\) using OUR_DELAYED_RETURN_TO_WALLET', billboard[1])
)
wait_for(check_billboard)

View File

@@ -8,7 +8,7 @@ from utils import (
DEVELOPER, only_one, wait_for, sync_blockheight, TIMEOUT,
expected_peer_features, expected_node_features,
expected_channel_features,
check_coin_moves, first_channel_id, account_balance
check_coin_moves, first_channel_id, account_balance, basic_fee
)
from bitcoin.core import CMutableTransaction, CMutableTxOut
@@ -163,7 +163,7 @@ def test_opening_tiny_channel(node_factory):
#
dustlimit = 546
reserves = 2 * dustlimit
min_commit_tx_fees = 5430
min_commit_tx_fees = basic_fee(7500)
min_for_opener = min_commit_tx_fees + dustlimit + 1
l1_min_capacity = 1000 # 1k old default, too small but used at l1 to allow small incoming channels

View File

@@ -2402,7 +2402,7 @@ def test_listtransactions(node_factory):
"""Sanity check for the listtransactions RPC command"""
l1, l2 = node_factory.get_nodes(2, opts=[{}, {}])
wallettxid = l1.openchannel(l2, 10**4)["wallettxid"]
wallettxid = l1.openchannel(l2, 10**5)["wallettxid"]
txids = [i["txid"] for tx in l1.rpc.listtransactions()["transactions"]
for i in tx["inputs"]]
# The txid of the transaction funding the channel is present, and

View File

@@ -1363,7 +1363,7 @@ def test_forward_local_failed_stats(node_factory, bitcoind, executor):
c12 = l1.fund_channel(l2, 10**6)
c23 = l2.fund_channel(l3, 10**6)
c24 = l2.fund_channel(l4, 10**6)
c25 = l2.fund_channel(l5, 10**4)
c25 = l2.fund_channel(l5, 10**4 * 2)
l6.fund_channel(l1, 10**6)
# Make sure routes finalized.

View File

@@ -1211,9 +1211,9 @@ def test_bcli(node_factory, bitcoind, chainparams):
l1.fundwallet(10**5)
l1.connect(l2)
fc = l1.rpc.fundchannel(l2.info["id"], 10**4)
fc = l1.rpc.fundchannel(l2.info["id"], 10**4 * 2)
txo = l1.rpc.call("getutxout", {"txid": fc['txid'], "vout": fc['outnum']})
assert (Millisatoshi(txo["amount"]) == Millisatoshi(10**4 * 10**3)
assert (Millisatoshi(txo["amount"]) == Millisatoshi(10**4 * 2 * 10**3)
and txo["script"].startswith("0020"))
l1.rpc.close(l2.info["id"])
# When output is spent, it should give us null !

View File

@@ -102,3 +102,12 @@ def account_balance(n, account_id):
def first_channel_id(n1, n2):
return only_one(only_one(n1.rpc.listpeers(n2.info['id'])['peers'])['channels'])['channel_id']
def basic_fee(feerate):
if False: # FIXME-anchor
# option_anchor_outputs
weight = 1124
else:
weight = 724
return (weight * feerate) // 1000