Browse Source
We're going to add some more. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>htlc_accepted_hook
Rusty Russell
6 years ago
2 changed files with 186 additions and 179 deletions
@ -0,0 +1,186 @@ |
|||
from decimal import Decimal |
|||
from fixtures import * # noqa: F401,F403 |
|||
from flaky import flaky # noqa: F401 |
|||
from lightning import RpcError |
|||
from utils import only_one, wait_for |
|||
|
|||
import pytest |
|||
import time |
|||
|
|||
|
|||
def test_withdraw(node_factory, bitcoind): |
|||
amount = 1000000 |
|||
# Don't get any funds from previous runs. |
|||
l1 = node_factory.get_node(random_hsm=True) |
|||
l2 = node_factory.get_node(random_hsm=True) |
|||
addr = l1.rpc.newaddr()['bech32'] |
|||
|
|||
# Add some funds to withdraw later |
|||
for i in range(10): |
|||
l1.bitcoin.rpc.sendtoaddress(addr, amount / 10**8 + 0.01) |
|||
|
|||
bitcoind.generate_block(1) |
|||
wait_for(lambda: len(l1.rpc.listfunds()['outputs']) == 10) |
|||
|
|||
# Reach around into the db to check that outputs were added |
|||
assert l1.db_query('SELECT COUNT(*) as c FROM outputs WHERE status=0')[0]['c'] == 10 |
|||
|
|||
waddr = l1.bitcoin.rpc.getnewaddress() |
|||
# Now attempt to withdraw some (making sure we collect multiple inputs) |
|||
with pytest.raises(RpcError): |
|||
l1.rpc.withdraw('not an address', amount) |
|||
with pytest.raises(RpcError): |
|||
l1.rpc.withdraw(waddr, 'not an amount') |
|||
with pytest.raises(RpcError): |
|||
l1.rpc.withdraw(waddr, -amount) |
|||
with pytest.raises(RpcError, match=r'Cannot afford transaction'): |
|||
l1.rpc.withdraw(waddr, amount * 100) |
|||
|
|||
out = l1.rpc.withdraw(waddr, 2 * amount) |
|||
|
|||
# Make sure bitcoind received the withdrawal |
|||
unspent = l1.bitcoin.rpc.listunspent(0) |
|||
withdrawal = [u for u in unspent if u['txid'] == out['txid']] |
|||
|
|||
assert(withdrawal[0]['amount'] == Decimal('0.02')) |
|||
|
|||
# Now make sure two of them were marked as spent |
|||
assert l1.db_query('SELECT COUNT(*) as c FROM outputs WHERE status=2')[0]['c'] == 2 |
|||
|
|||
# Now send some money to l2. |
|||
# lightningd uses P2SH-P2WPKH |
|||
waddr = l2.rpc.newaddr('bech32')['bech32'] |
|||
l1.rpc.withdraw(waddr, 2 * amount) |
|||
bitcoind.generate_block(1) |
|||
|
|||
# Make sure l2 received the withdrawal. |
|||
wait_for(lambda: len(l2.rpc.listfunds()['outputs']) == 1) |
|||
outputs = l2.db_query('SELECT value FROM outputs WHERE status=0;') |
|||
assert only_one(outputs)['value'] == 2 * amount |
|||
|
|||
# Now make sure an additional two of them were marked as spent |
|||
assert l1.db_query('SELECT COUNT(*) as c FROM outputs WHERE status=2')[0]['c'] == 4 |
|||
|
|||
# Simple test for withdrawal to P2WPKH |
|||
# Address from: https://bc-2.jp/tools/bech32demo/index.html |
|||
waddr = 'bcrt1qw508d6qejxtdg4y5r3zarvary0c5xw7kygt080' |
|||
with pytest.raises(RpcError): |
|||
l1.rpc.withdraw('xx1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx', 2 * amount) |
|||
with pytest.raises(RpcError): |
|||
l1.rpc.withdraw('tb1pw508d6qejxtdg4y5r3zarvary0c5xw7kdl9fad', 2 * amount) |
|||
with pytest.raises(RpcError): |
|||
l1.rpc.withdraw('tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxxxxxx', 2 * amount) |
|||
l1.rpc.withdraw(waddr, 2 * amount) |
|||
bitcoind.generate_block(1) |
|||
# Now make sure additional two of them were marked as spent |
|||
assert l1.db_query('SELECT COUNT(*) as c FROM outputs WHERE status=2')[0]['c'] == 6 |
|||
|
|||
# Simple test for withdrawal to P2WSH |
|||
# Address from: https://bc-2.jp/tools/bech32demo/index.html |
|||
waddr = 'bcrt1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qzf4jry' |
|||
with pytest.raises(RpcError): |
|||
l1.rpc.withdraw('xx1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7', 2 * amount) |
|||
with pytest.raises(RpcError): |
|||
l1.rpc.withdraw('tb1prp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qsm03tq', 2 * amount) |
|||
with pytest.raises(RpcError): |
|||
l1.rpc.withdraw('tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qxxxxxx', 2 * amount) |
|||
l1.rpc.withdraw(waddr, 2 * amount) |
|||
bitcoind.generate_block(1) |
|||
# Now make sure additional two of them were marked as spent |
|||
assert l1.db_query('SELECT COUNT(*) as c FROM outputs WHERE status=2')[0]['c'] == 8 |
|||
|
|||
# failure testing for invalid SegWit addresses, from BIP173 |
|||
# HRP character out of range |
|||
with pytest.raises(RpcError): |
|||
l1.rpc.withdraw(' 1nwldj5', 2 * amount) |
|||
# overall max length exceeded |
|||
with pytest.raises(RpcError): |
|||
l1.rpc.withdraw('an84characterslonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio1569pvx', 2 * amount) |
|||
# No separator character |
|||
with pytest.raises(RpcError): |
|||
l1.rpc.withdraw('pzry9x0s0muk', 2 * amount) |
|||
# Empty HRP |
|||
with pytest.raises(RpcError): |
|||
l1.rpc.withdraw('1pzry9x0s0muk', 2 * amount) |
|||
# Invalid witness version |
|||
with pytest.raises(RpcError): |
|||
l1.rpc.withdraw('BC13W508D6QEJXTDG4Y5R3ZARVARY0C5XW7KN40WF2', 2 * amount) |
|||
# Invalid program length for witness version 0 (per BIP141) |
|||
with pytest.raises(RpcError): |
|||
l1.rpc.withdraw('BC1QR508D6QEJXTDG4Y5R3ZARVARYV98GJ9P', 2 * amount) |
|||
# Mixed case |
|||
with pytest.raises(RpcError): |
|||
l1.rpc.withdraw('tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sL5k7', 2 * amount) |
|||
# Non-zero padding in 8-to-5 conversion |
|||
with pytest.raises(RpcError): |
|||
l1.rpc.withdraw('tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3pjxtptv', 2 * amount) |
|||
|
|||
# Should have 6 outputs available. |
|||
assert l1.db_query('SELECT COUNT(*) as c FROM outputs WHERE status=0')[0]['c'] == 6 |
|||
|
|||
# Test withdrawal to self. |
|||
l1.rpc.withdraw(l1.rpc.newaddr('bech32')['bech32'], 'all', minconf=0) |
|||
bitcoind.generate_block(1) |
|||
assert l1.db_query('SELECT COUNT(*) as c FROM outputs WHERE status=0')[0]['c'] == 1 |
|||
|
|||
l1.rpc.withdraw(waddr, 'all', minconf=0) |
|||
assert l1.db_query('SELECT COUNT(*) as c FROM outputs WHERE status=0')[0]['c'] == 0 |
|||
|
|||
# This should fail, can't even afford fee. |
|||
with pytest.raises(RpcError, match=r'Cannot afford transaction'): |
|||
l1.rpc.withdraw(waddr, 'all') |
|||
|
|||
|
|||
def test_minconf_withdraw(node_factory, bitcoind): |
|||
"""Issue 2518: ensure that ridiculous confirmation levels don't overflow |
|||
|
|||
The number of confirmations is used to compute a maximum height that is to |
|||
be accepted. If the current height is smaller than the number of |
|||
confirmations we wrap around and just select everything. The fix is to |
|||
clamp the maxheight parameter to a positive small number. |
|||
|
|||
""" |
|||
amount = 1000000 |
|||
# Don't get any funds from previous runs. |
|||
l1 = node_factory.get_node(random_hsm=True) |
|||
addr = l1.rpc.newaddr()['bech32'] |
|||
|
|||
# Add some funds to withdraw later |
|||
for i in range(10): |
|||
l1.bitcoin.rpc.sendtoaddress(addr, amount / 10**8 + 0.01) |
|||
|
|||
bitcoind.generate_block(1) |
|||
|
|||
wait_for(lambda: len(l1.rpc.listfunds()['outputs']) == 10) |
|||
with pytest.raises(RpcError): |
|||
l1.rpc.withdraw(destination=addr, satoshi=10000, feerate='normal', minconf=9999999) |
|||
|
|||
|
|||
def test_addfunds_from_block(node_factory, bitcoind): |
|||
"""Send funds to the daemon without telling it explicitly |
|||
""" |
|||
# Previous runs with same bitcoind can leave funds! |
|||
l1 = node_factory.get_node(random_hsm=True) |
|||
|
|||
addr = l1.rpc.newaddr()['bech32'] |
|||
bitcoind.rpc.sendtoaddress(addr, 0.1) |
|||
bitcoind.generate_block(1) |
|||
|
|||
wait_for(lambda: len(l1.rpc.listfunds()['outputs']) == 1) |
|||
|
|||
outputs = l1.db_query('SELECT value FROM outputs WHERE status=0;') |
|||
assert only_one(outputs)['value'] == 10000000 |
|||
|
|||
# The address we detect must match what was paid to. |
|||
output = only_one(l1.rpc.listfunds()['outputs']) |
|||
assert output['address'] == addr |
|||
|
|||
# Send all our money to a P2WPKH address this time. |
|||
addr = l1.rpc.newaddr("bech32")['bech32'] |
|||
l1.rpc.withdraw(addr, "all") |
|||
bitcoind.generate_block(1) |
|||
time.sleep(1) |
|||
|
|||
# The address we detect must match what was paid to. |
|||
output = only_one(l1.rpc.listfunds()['outputs']) |
|||
assert output['address'] == addr |
Loading…
Reference in new issue