mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 15:14:23 +01:00
Make Python code conform to the Python PEP 8 style guide
This commit is contained in:
committed by
Christian Decker
parent
0ac5e93065
commit
ae7d857c44
@@ -1,16 +1,13 @@
|
|||||||
from concurrent.futures import ThreadPoolExecutor
|
|
||||||
from lightning import LightningRpc
|
|
||||||
from test_lightningd import NodeFactory
|
|
||||||
import logging
|
import logging
|
||||||
import pytest
|
import pytest
|
||||||
import random
|
import random
|
||||||
import utils
|
import utils
|
||||||
|
|
||||||
from concurrent import futures
|
from concurrent import futures
|
||||||
|
from test_lightningd import NodeFactory
|
||||||
from time import time
|
from time import time
|
||||||
from tqdm import tqdm
|
from tqdm import tqdm
|
||||||
|
|
||||||
|
|
||||||
num_workers = 480
|
num_workers = 480
|
||||||
num_payments = 10000
|
num_payments = 10000
|
||||||
|
|
||||||
@@ -21,6 +18,7 @@ def executor():
|
|||||||
yield ex
|
yield ex
|
||||||
ex.shutdown(wait=False)
|
ex.shutdown(wait=False)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def bitcoind():
|
def bitcoind():
|
||||||
bitcoind = utils.BitcoinD(rpcport=28332)
|
bitcoind = utils.BitcoinD(rpcport=28332)
|
||||||
@@ -42,12 +40,14 @@ def bitcoind():
|
|||||||
bitcoind.proc.kill()
|
bitcoind.proc.kill()
|
||||||
bitcoind.proc.wait()
|
bitcoind.proc.wait()
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def node_factory(request, bitcoind, executor):
|
def node_factory(request, bitcoind, executor):
|
||||||
nf = NodeFactory(request.node.name, bitcoind, executor)
|
nf = NodeFactory(request.node.name, bitcoind, executor)
|
||||||
yield nf
|
yield nf
|
||||||
nf.killall()
|
nf.killall()
|
||||||
|
|
||||||
|
|
||||||
def test_single_hop(node_factory, executor):
|
def test_single_hop(node_factory, executor):
|
||||||
l1 = node_factory.get_node()
|
l1 = node_factory.get_node()
|
||||||
l2 = node_factory.get_node()
|
l2 = node_factory.get_node()
|
||||||
@@ -74,6 +74,7 @@ def test_single_hop(node_factory, executor):
|
|||||||
diff = time() - start_time
|
diff = time() - start_time
|
||||||
print("Done. %d payments performed in %f seconds (%f payments per second)" % (num_payments, diff, num_payments / diff))
|
print("Done. %d payments performed in %f seconds (%f payments per second)" % (num_payments, diff, num_payments / diff))
|
||||||
|
|
||||||
|
|
||||||
def test_single_payment(node_factory, benchmark):
|
def test_single_payment(node_factory, benchmark):
|
||||||
l1 = node_factory.get_node()
|
l1 = node_factory.get_node()
|
||||||
l2 = node_factory.get_node()
|
l2 = node_factory.get_node()
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
from concurrent import futures
|
from concurrent import futures
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from hashlib import sha256
|
|
||||||
from lightning import LightningRpc
|
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
import json
|
import json
|
||||||
@@ -19,7 +17,9 @@ import tempfile
|
|||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
import utils
|
import utils
|
||||||
|
from lightning import LightningRpc
|
||||||
|
|
||||||
bitcoind = None
|
bitcoind = None
|
||||||
TEST_DIR = tempfile.mkdtemp(prefix='lightning-')
|
TEST_DIR = tempfile.mkdtemp(prefix='lightning-')
|
||||||
@@ -33,9 +33,11 @@ if TEST_DEBUG:
|
|||||||
logging.basicConfig(level=logging.DEBUG, stream=sys.stdout)
|
logging.basicConfig(level=logging.DEBUG, stream=sys.stdout)
|
||||||
logging.info("Tests running in '%s'", TEST_DIR)
|
logging.info("Tests running in '%s'", TEST_DIR)
|
||||||
|
|
||||||
|
|
||||||
def to_json(arg):
|
def to_json(arg):
|
||||||
return json.loads(json.dumps(arg))
|
return json.loads(json.dumps(arg))
|
||||||
|
|
||||||
|
|
||||||
def setupBitcoind(directory):
|
def setupBitcoind(directory):
|
||||||
global bitcoind
|
global bitcoind
|
||||||
bitcoind = utils.BitcoinD(bitcoin_dir=directory, rpcport=28332)
|
bitcoind = utils.BitcoinD(bitcoin_dir=directory, rpcport=28332)
|
||||||
@@ -105,7 +107,7 @@ class NodeFactory(object):
|
|||||||
TEST_DIR, self.testname, "lightning-{}/".format(node_id))
|
TEST_DIR, self.testname, "lightning-{}/".format(node_id))
|
||||||
|
|
||||||
socket_path = os.path.join(lightning_dir, "lightning-rpc").format(node_id)
|
socket_path = os.path.join(lightning_dir, "lightning-rpc").format(node_id)
|
||||||
port = 16330+node_id
|
port = 16330 + node_id
|
||||||
daemon = utils.LightningD(lightning_dir, self.bitcoind.bitcoin_dir, port=port, random_hsm=random_hsm)
|
daemon = utils.LightningD(lightning_dir, self.bitcoind.bitcoin_dir, port=port, random_hsm=random_hsm)
|
||||||
# If we have a disconnect string, dump it to a file for daemon.
|
# If we have a disconnect string, dump it to a file for daemon.
|
||||||
if disconnect:
|
if disconnect:
|
||||||
@@ -192,10 +194,10 @@ class BaseLightningDTests(unittest.TestCase):
|
|||||||
def printValgrindErrors(self, node):
|
def printValgrindErrors(self, node):
|
||||||
errors, fname = self.getValgrindErrors(node)
|
errors, fname = self.getValgrindErrors(node)
|
||||||
if errors:
|
if errors:
|
||||||
print("-"*31, "Valgrind errors", "-"*32)
|
print("-" * 31, "Valgrind errors", "-" * 32)
|
||||||
print("Valgrind error file:", fname)
|
print("Valgrind error file:", fname)
|
||||||
print(errors)
|
print(errors)
|
||||||
print("-"*80)
|
print("-" * 80)
|
||||||
return 1 if errors else 0
|
return 1 if errors else 0
|
||||||
|
|
||||||
def getCrashLog(self, node):
|
def getCrashLog(self, node):
|
||||||
@@ -211,10 +213,10 @@ class BaseLightningDTests(unittest.TestCase):
|
|||||||
def printCrashLog(self, node):
|
def printCrashLog(self, node):
|
||||||
errors, fname = self.getCrashLog(node)
|
errors, fname = self.getCrashLog(node)
|
||||||
if errors:
|
if errors:
|
||||||
print("-"*10, "{} (last 50 lines)".format(fname), "-"*10)
|
print("-" * 10, "{} (last 50 lines)".format(fname), "-" * 10)
|
||||||
for l in errors[-50:]:
|
for l in errors[-50:]:
|
||||||
print(l, end='')
|
print(l, end='')
|
||||||
print("-"*80)
|
print("-" * 80)
|
||||||
return 1 if errors else 0
|
return 1 if errors else 0
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
@@ -249,7 +251,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
|
|
||||||
l1.daemon.wait_for_log('WIRE_GOSSIPCTL_HAND_BACK_PEER')
|
l1.daemon.wait_for_log('WIRE_GOSSIPCTL_HAND_BACK_PEER')
|
||||||
l2.daemon.wait_for_log('WIRE_GOSSIPCTL_HAND_BACK_PEER')
|
l2.daemon.wait_for_log('WIRE_GOSSIPCTL_HAND_BACK_PEER')
|
||||||
return l1,l2
|
return l1, l2
|
||||||
|
|
||||||
# Waits until l1 notices funds
|
# Waits until l1 notices funds
|
||||||
def give_funds(self, l1, satoshi):
|
def give_funds(self, l1, satoshi):
|
||||||
@@ -289,13 +291,13 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
"""
|
"""
|
||||||
nodes = [self.node_factory.get_node() for _ in range(n)]
|
nodes = [self.node_factory.get_node() for _ in range(n)]
|
||||||
|
|
||||||
for i in range(len(nodes)-1):
|
for i in range(len(nodes) - 1):
|
||||||
nodes[i].rpc.connect(
|
nodes[i].rpc.connect(
|
||||||
nodes[i+1].info['id'],
|
nodes[i + 1].info['id'],
|
||||||
'localhost',
|
'localhost',
|
||||||
nodes[i+1].info['port']
|
nodes[i + 1].info['port']
|
||||||
)
|
)
|
||||||
self.fund_channel(nodes[i], nodes[i+1], 10**6)
|
self.fund_channel(nodes[i], nodes[i + 1], 10**6)
|
||||||
|
|
||||||
return nodes
|
return nodes
|
||||||
|
|
||||||
@@ -307,9 +309,9 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
assert ldst.rpc.listinvoices(label)['invoices'][0]['status'] == 'unpaid'
|
assert ldst.rpc.listinvoices(label)['invoices'][0]['status'] == 'unpaid'
|
||||||
|
|
||||||
routestep = {
|
routestep = {
|
||||||
'msatoshi' : amt,
|
'msatoshi': amt,
|
||||||
'id' : ldst.info['id'],
|
'id': ldst.info['id'],
|
||||||
'delay' : 5,
|
'delay': 5,
|
||||||
'channel': '1:1:1'
|
'channel': '1:1:1'
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -332,8 +334,8 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
bitcoind.generate_block(5)
|
bitcoind.generate_block(5)
|
||||||
# Could happen in any order...
|
# Could happen in any order...
|
||||||
l1.daemon.wait_for_logs(['Received channel_update for channel {}\\(0\\)'.format(c)
|
l1.daemon.wait_for_logs(['Received channel_update for channel {}\\(0\\)'.format(c)
|
||||||
for c in channel_ids]
|
for c in channel_ids] +
|
||||||
+ ['Received channel_update for channel {}\\(1\\)'.format(c)
|
['Received channel_update for channel {}\\(1\\)'.format(c)
|
||||||
for c in channel_ids])
|
for c in channel_ids])
|
||||||
|
|
||||||
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
||||||
@@ -379,7 +381,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
assert b11.count('1') == 1
|
assert b11.count('1') == 1
|
||||||
|
|
||||||
def test_invoice_expiry(self):
|
def test_invoice_expiry(self):
|
||||||
l1,l2 = self.connect()
|
l1, l2 = self.connect()
|
||||||
|
|
||||||
chanid = self.fund_channel(l1, l2, 10**6)
|
chanid = self.fund_channel(l1, l2, 10**6)
|
||||||
|
|
||||||
@@ -432,7 +434,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
self.assertRaises(ValueError, w3.result)
|
self.assertRaises(ValueError, w3.result)
|
||||||
|
|
||||||
def test_connect(self):
|
def test_connect(self):
|
||||||
l1,l2 = self.connect()
|
l1, l2 = self.connect()
|
||||||
|
|
||||||
# These should be in gossipd.
|
# These should be in gossipd.
|
||||||
assert l1.rpc.getpeer(l2.info['id'])['state'] == 'GOSSIPING'
|
assert l1.rpc.getpeer(l2.info['id'])['state'] == 'GOSSIPING'
|
||||||
@@ -713,7 +715,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
self.assertRaises(ValueError, l1.rpc.decodepay, '1111111')
|
self.assertRaises(ValueError, l1.rpc.decodepay, '1111111')
|
||||||
|
|
||||||
def test_sendpay(self):
|
def test_sendpay(self):
|
||||||
l1,l2 = self.connect()
|
l1, l2 = self.connect()
|
||||||
|
|
||||||
self.fund_channel(l1, l2, 10**6)
|
self.fund_channel(l1, l2, 10**6)
|
||||||
|
|
||||||
@@ -722,9 +724,9 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
assert l2.rpc.listinvoices('testpayment2')['invoices'][0]['status'] == 'unpaid'
|
assert l2.rpc.listinvoices('testpayment2')['invoices'][0]['status'] == 'unpaid'
|
||||||
|
|
||||||
routestep = {
|
routestep = {
|
||||||
'msatoshi' : amt,
|
'msatoshi': amt,
|
||||||
'id' : l2.info['id'],
|
'id': l2.info['id'],
|
||||||
'delay' : 5,
|
'delay': 5,
|
||||||
'channel': '1:1:1'
|
'channel': '1:1:1'
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -786,10 +788,10 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
# Overpaying by "only" a factor of 2 succeeds.
|
# Overpaying by "only" a factor of 2 succeeds.
|
||||||
rhash = l2.rpc.invoice(amt, 'testpayment3', 'desc')['payment_hash']
|
rhash = l2.rpc.invoice(amt, 'testpayment3', 'desc')['payment_hash']
|
||||||
assert l2.rpc.listinvoices('testpayment3')['invoices'][0]['status'] == 'unpaid'
|
assert l2.rpc.listinvoices('testpayment3')['invoices'][0]['status'] == 'unpaid'
|
||||||
routestep = { 'msatoshi' : amt * 2, 'id' : l2.info['id'], 'delay' : 5, 'channel': '1:1:1'}
|
routestep = {'msatoshi': amt * 2, 'id': l2.info['id'], 'delay': 5, 'channel': '1:1:1'}
|
||||||
preimage3 = l1.rpc.sendpay(to_json([routestep]), rhash)
|
preimage3 = l1.rpc.sendpay(to_json([routestep]), rhash)
|
||||||
assert l2.rpc.listinvoices('testpayment3')['invoices'][0]['status'] == 'paid'
|
assert l2.rpc.listinvoices('testpayment3')['invoices'][0]['status'] == 'paid'
|
||||||
assert l2.rpc.listinvoices('testpayment3')['invoices'][0]['msatoshi_received'] == amt*2
|
assert l2.rpc.listinvoices('testpayment3')['invoices'][0]['msatoshi_received'] == amt * 2
|
||||||
|
|
||||||
# Test listpayments
|
# Test listpayments
|
||||||
payments = l1.rpc.listpayments()['payments']
|
payments = l1.rpc.listpayments()['payments']
|
||||||
@@ -810,7 +812,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
assert payments[0]['payment_preimage'] == preimage3['preimage']
|
assert payments[0]['payment_preimage'] == preimage3['preimage']
|
||||||
|
|
||||||
def test_sendpay_cant_afford(self):
|
def test_sendpay_cant_afford(self):
|
||||||
l1,l2 = self.connect()
|
l1, l2 = self.connect()
|
||||||
|
|
||||||
# Note, this is in SATOSHI, rest are in MILLISATOSHI!
|
# Note, this is in SATOSHI, rest are in MILLISATOSHI!
|
||||||
self.fund_channel(l1, l2, 10**6)
|
self.fund_channel(l1, l2, 10**6)
|
||||||
@@ -834,12 +836,12 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
self.assertRaises(ValueError, self.pay, l2, l1, available - reserve)
|
self.assertRaises(ValueError, self.pay, l2, l1, available - reserve)
|
||||||
|
|
||||||
# But this should work.
|
# But this should work.
|
||||||
self.pay(l2, l1, available - reserve*2)
|
self.pay(l2, l1, available - reserve * 2)
|
||||||
|
|
||||||
def test_pay0(self):
|
def test_pay0(self):
|
||||||
"""Test paying 0 amount
|
"""Test paying 0 amount
|
||||||
"""
|
"""
|
||||||
l1,l2 = self.connect()
|
l1, l2 = self.connect()
|
||||||
# Set up channel.
|
# Set up channel.
|
||||||
chanid = self.fund_channel(l1, l2, 10**6)
|
chanid = self.fund_channel(l1, l2, 10**6)
|
||||||
self.wait_for_routes(l1, [chanid])
|
self.wait_for_routes(l1, [chanid])
|
||||||
@@ -849,10 +851,10 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
rhash = inv['payment_hash']
|
rhash = inv['payment_hash']
|
||||||
|
|
||||||
routestep = {
|
routestep = {
|
||||||
'msatoshi' : 0,
|
'msatoshi': 0,
|
||||||
'id' : l2.info['id'],
|
'id': l2.info['id'],
|
||||||
'delay' : 10,
|
'delay': 10,
|
||||||
'channel' : chanid
|
'channel': chanid
|
||||||
}
|
}
|
||||||
|
|
||||||
# Amount must be nonzero!
|
# Amount must be nonzero!
|
||||||
@@ -860,7 +862,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
l1.rpc.sendpay, to_json([routestep]), rhash)
|
l1.rpc.sendpay, to_json([routestep]), rhash)
|
||||||
|
|
||||||
def test_pay(self):
|
def test_pay(self):
|
||||||
l1,l2 = self.connect()
|
l1, l2 = self.connect()
|
||||||
|
|
||||||
chanid = self.fund_channel(l1, l2, 10**6)
|
chanid = self.fund_channel(l1, l2, 10**6)
|
||||||
|
|
||||||
@@ -903,7 +905,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
assert l1.rpc.listpayments(inv)['payments'][0]['payment_preimage'] == preimage['preimage']
|
assert l1.rpc.listpayments(inv)['payments'][0]['payment_preimage'] == preimage['preimage']
|
||||||
|
|
||||||
def test_pay_optional_args(self):
|
def test_pay_optional_args(self):
|
||||||
l1,l2 = self.connect()
|
l1, l2 = self.connect()
|
||||||
|
|
||||||
chanid = self.fund_channel(l1, l2, 10**6)
|
chanid = self.fund_channel(l1, l2, 10**6)
|
||||||
|
|
||||||
@@ -957,7 +959,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
c = self.fund_channel(lsrc, ldst, 10000000)
|
c = self.fund_channel(lsrc, ldst, 10000000)
|
||||||
self.wait_for_routes(lpayer, [c])
|
self.wait_for_routes(lpayer, [c])
|
||||||
|
|
||||||
## Setup
|
# Setup
|
||||||
# Construct lightningd
|
# Construct lightningd
|
||||||
l1 = self.node_factory.get_node()
|
l1 = self.node_factory.get_node()
|
||||||
l2 = self.node_factory.get_node()
|
l2 = self.node_factory.get_node()
|
||||||
@@ -975,7 +977,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
fund_from_to_payer(l4, l1, l1)
|
fund_from_to_payer(l4, l1, l1)
|
||||||
fund_from_to_payer(l4, l2, l1)
|
fund_from_to_payer(l4, l2, l1)
|
||||||
|
|
||||||
## Test
|
# Test
|
||||||
inv = l4.rpc.invoice(1234567, 'inv', 'for testing')['bolt11']
|
inv = l4.rpc.invoice(1234567, 'inv', 'for testing')['bolt11']
|
||||||
l1.rpc.pay(inv)
|
l1.rpc.pay(inv)
|
||||||
|
|
||||||
@@ -996,7 +998,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
l2.daemon.wait_for_log('to_self_delay 100 larger than 99')
|
l2.daemon.wait_for_log('to_self_delay 100 larger than 99')
|
||||||
|
|
||||||
def test_closing(self):
|
def test_closing(self):
|
||||||
l1,l2 = self.connect()
|
l1, l2 = self.connect()
|
||||||
|
|
||||||
self.fund_channel(l1, l2, 10**6)
|
self.fund_channel(l1, l2, 10**6)
|
||||||
self.pay(l1, l2, 200000000)
|
self.pay(l1, l2, 200000000)
|
||||||
@@ -1075,9 +1077,8 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
|
|
||||||
# Default feerate = 15000/7500/1000
|
# Default feerate = 15000/7500/1000
|
||||||
# It will start at the second number, accepting anything above the first.
|
# It will start at the second number, accepting anything above the first.
|
||||||
feerates=[ [ 20000, 15000, 7400 ],
|
feerates = [[20000, 15000, 7400], [8000, 1001, 100]]
|
||||||
[ 8000, 1001, 100 ] ]
|
amounts = [0, 545999, 546000]
|
||||||
amounts = [ 0, 545999, 546000 ]
|
|
||||||
num_peers = len(feerates) * len(amounts)
|
num_peers = len(feerates) * len(amounts)
|
||||||
self.give_funds(l1, (10**6) * num_peers + 10000 * num_peers)
|
self.give_funds(l1, (10**6) * num_peers + 10000 * num_peers)
|
||||||
|
|
||||||
@@ -1102,8 +1103,8 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
bitcoind.generate_block(6)
|
bitcoind.generate_block(6)
|
||||||
|
|
||||||
# Now wait for them all to hit normal state, do payments
|
# Now wait for them all to hit normal state, do payments
|
||||||
l1.daemon.wait_for_logs(['update for channel .* now ACTIVE'] * num_peers
|
l1.daemon.wait_for_logs(['update for channel .* now ACTIVE'] * num_peers +
|
||||||
+ ['to CHANNELD_NORMAL'] * num_peers)
|
['to CHANNELD_NORMAL'] * num_peers)
|
||||||
for p in peers:
|
for p in peers:
|
||||||
if p.amount != 0:
|
if p.amount != 0:
|
||||||
self.pay(l1, p, 100000000)
|
self.pay(l1, p, 100000000)
|
||||||
@@ -1123,10 +1124,10 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
|
|
||||||
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
||||||
def test_permfail(self):
|
def test_permfail(self):
|
||||||
l1,l2 = self.connect()
|
l1, l2 = self.connect()
|
||||||
|
|
||||||
self.fund_channel(l1, l2, 10**6)
|
self.fund_channel(l1, l2, 10**6)
|
||||||
self.pay(l1,l2,200000000)
|
self.pay(l1, l2, 200000000)
|
||||||
|
|
||||||
# Make sure l2 has received sig with 0 htlcs!
|
# Make sure l2 has received sig with 0 htlcs!
|
||||||
l2.daemon.wait_for_log('Received commit_sig with 0 htlc sigs')
|
l2.daemon.wait_for_log('Received commit_sig with 0 htlc sigs')
|
||||||
@@ -1222,10 +1223,10 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
||||||
def test_onchain_unwatch(self):
|
def test_onchain_unwatch(self):
|
||||||
"""Onchaind should not watch random spends"""
|
"""Onchaind should not watch random spends"""
|
||||||
l1,l2 = self.connect()
|
l1, l2 = self.connect()
|
||||||
|
|
||||||
self.fund_channel(l1, l2, 10**6)
|
self.fund_channel(l1, l2, 10**6)
|
||||||
self.pay(l1,l2,200000000)
|
self.pay(l1, l2, 200000000)
|
||||||
|
|
||||||
l1.rpc.dev_fail(l2.info['id'])
|
l1.rpc.dev_fail(l2.info['id'])
|
||||||
l1.daemon.wait_for_log('Failing due to dev-fail command')
|
l1.daemon.wait_for_log('Failing due to dev-fail command')
|
||||||
@@ -1281,9 +1282,9 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
# Must be dust!
|
# Must be dust!
|
||||||
rhash = l2.rpc.invoice(1, 'onchain_dust_out', 'desc')['payment_hash']
|
rhash = l2.rpc.invoice(1, 'onchain_dust_out', 'desc')['payment_hash']
|
||||||
routestep = {
|
routestep = {
|
||||||
'msatoshi' : 1,
|
'msatoshi': 1,
|
||||||
'id' : l2.info['id'],
|
'id': l2.info['id'],
|
||||||
'delay' : 5,
|
'delay': 5,
|
||||||
'channel': '1:1:1'
|
'channel': '1:1:1'
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1334,9 +1335,9 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
rhash = l2.rpc.invoice(10**8, 'onchain_timeout', 'desc')['payment_hash']
|
rhash = l2.rpc.invoice(10**8, 'onchain_timeout', 'desc')['payment_hash']
|
||||||
# We underpay, so it fails.
|
# We underpay, so it fails.
|
||||||
routestep = {
|
routestep = {
|
||||||
'msatoshi' : 10**8 - 1,
|
'msatoshi': 10**8 - 1,
|
||||||
'id' : l2.info['id'],
|
'id': l2.info['id'],
|
||||||
'delay' : 5,
|
'delay': 5,
|
||||||
'channel': '1:1:1'
|
'channel': '1:1:1'
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1468,7 +1469,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
self.fund_channel(l1, l2, 10**6)
|
self.fund_channel(l1, l2, 10**6)
|
||||||
|
|
||||||
# Now, this will get stuck due to l1 commit being disabled..
|
# Now, this will get stuck due to l1 commit being disabled..
|
||||||
t = self.pay(l1,l2,100000000,async=True)
|
t = self.pay(l1, l2, 100000000, async=True)
|
||||||
|
|
||||||
assert len(l1.getactivechannels()) == 1
|
assert len(l1.getactivechannels()) == 1
|
||||||
assert len(l2.getactivechannels()) == 1
|
assert len(l2.getactivechannels()) == 1
|
||||||
@@ -1630,7 +1631,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
self.fund_channel(l1, l2, 10**6)
|
self.fund_channel(l1, l2, 10**6)
|
||||||
|
|
||||||
# This will fail at l2's end.
|
# This will fail at l2's end.
|
||||||
t=self.pay(l1, l2, 200000000, async=True)
|
t = self.pay(l1, l2, 200000000, async=True)
|
||||||
|
|
||||||
l2.daemon.wait_for_log('dev_disconnect permfail')
|
l2.daemon.wait_for_log('dev_disconnect permfail')
|
||||||
l2.daemon.wait_for_log('sendrawtx exit 0')
|
l2.daemon.wait_for_log('sendrawtx exit 0')
|
||||||
@@ -1672,7 +1673,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
self.fund_channel(l2, l1, 10**6)
|
self.fund_channel(l2, l1, 10**6)
|
||||||
|
|
||||||
# This will fail at l2's end.
|
# This will fail at l2's end.
|
||||||
t=self.pay(l2,l1,200000000,async=True)
|
t = self.pay(l2, l1, 200000000, async=True)
|
||||||
|
|
||||||
l2.daemon.wait_for_log('dev_disconnect permfail')
|
l2.daemon.wait_for_log('dev_disconnect permfail')
|
||||||
l2.daemon.wait_for_log('sendrawtx exit 0')
|
l2.daemon.wait_for_log('sendrawtx exit 0')
|
||||||
@@ -1726,13 +1727,13 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
# Outgoing should be active, but not public.
|
# Outgoing should be active, but not public.
|
||||||
channels = l1.rpc.listchannels()['channels']
|
channels = l1.rpc.listchannels()['channels']
|
||||||
assert len(channels) == 1
|
assert len(channels) == 1
|
||||||
assert channels[0]['active'] == True
|
assert channels[0]['active'] is True
|
||||||
assert channels[0]['public'] == False
|
assert channels[0]['public'] is False
|
||||||
|
|
||||||
channels = l2.rpc.listchannels()['channels']
|
channels = l2.rpc.listchannels()['channels']
|
||||||
assert len(channels) == 1
|
assert len(channels) == 1
|
||||||
assert channels[0]['active'] == True
|
assert channels[0]['active'] is True
|
||||||
assert channels[0]['public'] == False
|
assert channels[0]['public'] is False
|
||||||
|
|
||||||
# Now proceed to funding-depth and do a full gossip round
|
# Now proceed to funding-depth and do a full gossip round
|
||||||
l1.bitcoin.generate_block(5)
|
l1.bitcoin.generate_block(5)
|
||||||
@@ -1764,9 +1765,9 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
if DEVELOPER:
|
if DEVELOPER:
|
||||||
assert n1['alias'] == 'JUNIORBEAM'
|
assert n1['alias'] == 'JUNIORBEAM'
|
||||||
assert n1['color'] == '0266e4'
|
assert n1['color'] == '0266e4'
|
||||||
if not 'alias' in n2:
|
if 'alias' not in n2:
|
||||||
assert not 'color' in n2
|
assert 'color' not in n2
|
||||||
assert not 'addresses' in n2
|
assert 'addresses' not in n2
|
||||||
else:
|
else:
|
||||||
assert n2['alias'] == 'SILENTARTIST'
|
assert n2['alias'] == 'SILENTARTIST'
|
||||||
assert n2['color'] == '022d22'
|
assert n2['color'] == '022d22'
|
||||||
@@ -1794,9 +1795,9 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
l1.bitcoin.rpc.generate(6)
|
l1.bitcoin.rpc.generate(6)
|
||||||
|
|
||||||
# Channels should be activated locally
|
# Channels should be activated locally
|
||||||
wait_for(lambda: [c['active'] for c in l1.rpc.listchannels()['channels']] == [True]*4)
|
wait_for(lambda: [c['active'] for c in l1.rpc.listchannels()['channels']] == [True] * 4)
|
||||||
wait_for(lambda: [c['active'] for c in l2.rpc.listchannels()['channels']] == [True]*4)
|
wait_for(lambda: [c['active'] for c in l2.rpc.listchannels()['channels']] == [True] * 4)
|
||||||
wait_for(lambda: [c['active'] for c in l3.rpc.listchannels()['channels']] == [True]*4)
|
wait_for(lambda: [c['active'] for c in l3.rpc.listchannels()['channels']] == [True] * 4)
|
||||||
|
|
||||||
# All of them should send a keepalive message
|
# All of them should send a keepalive message
|
||||||
l1.daemon.wait_for_logs([
|
l1.daemon.wait_for_logs([
|
||||||
@@ -1858,7 +1859,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
|
|
||||||
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
||||||
def test_ping(self):
|
def test_ping(self):
|
||||||
l1,l2 = self.connect()
|
l1, l2 = self.connect()
|
||||||
|
|
||||||
# Test gossip pinging.
|
# Test gossip pinging.
|
||||||
self.ping_tests(l1, l2)
|
self.ping_tests(l1, l2)
|
||||||
@@ -1903,8 +1904,8 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
l1 = nodes[0]
|
l1 = nodes[0]
|
||||||
l5 = nodes[4]
|
l5 = nodes[4]
|
||||||
|
|
||||||
for i in range(len(nodes)-1):
|
for i in range(len(nodes) - 1):
|
||||||
src, dst = nodes[i], nodes[i+1]
|
src, dst = nodes[i], nodes[i + 1]
|
||||||
src.rpc.connect(dst.info['id'], 'localhost', dst.info['port'])
|
src.rpc.connect(dst.info['id'], 'localhost', dst.info['port'])
|
||||||
src.openchannel(dst, 20000)
|
src.openchannel(dst, 20000)
|
||||||
|
|
||||||
@@ -1914,7 +1915,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
def settle_gossip(n):
|
def settle_gossip(n):
|
||||||
"""Wait for gossip to settle at the node
|
"""Wait for gossip to settle at the node
|
||||||
"""
|
"""
|
||||||
expected_connections = 2*(len(nodes) - 1)
|
expected_connections = 2 * (len(nodes) - 1)
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
# Wait at most 10 seconds, broadcast interval is 1 second
|
# Wait at most 10 seconds, broadcast interval is 1 second
|
||||||
while time.time() - start_time < 10:
|
while time.time() - start_time < 10:
|
||||||
@@ -1930,19 +1931,19 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
# Deep check that all channels are in there
|
# Deep check that all channels are in there
|
||||||
comb = []
|
comb = []
|
||||||
for i in range(len(nodes) - 1):
|
for i in range(len(nodes) - 1):
|
||||||
comb.append((nodes[i].info['id'], nodes[i+1].info['id']))
|
comb.append((nodes[i].info['id'], nodes[i + 1].info['id']))
|
||||||
comb.append((nodes[i+1].info['id'], nodes[i].info['id']))
|
comb.append((nodes[i + 1].info['id'], nodes[i].info['id']))
|
||||||
|
|
||||||
for n in nodes:
|
for n in nodes:
|
||||||
seen = []
|
seen = []
|
||||||
channels = n.rpc.listchannels()['channels']
|
channels = n.rpc.listchannels()['channels']
|
||||||
for c in channels:
|
for c in channels:
|
||||||
seen.append((c['source'],c['destination']))
|
seen.append((c['source'], c['destination']))
|
||||||
assert set(seen) == set(comb)
|
assert set(seen) == set(comb)
|
||||||
|
|
||||||
def test_forward(self):
|
def test_forward(self):
|
||||||
# Connect 1 -> 2 -> 3.
|
# Connect 1 -> 2 -> 3.
|
||||||
l1,l2 = self.connect()
|
l1, l2 = self.connect()
|
||||||
l3 = self.node_factory.get_node()
|
l3 = self.node_factory.get_node()
|
||||||
ret = l2.rpc.connect(l3.info['id'], 'localhost', l3.info['port'])
|
ret = l2.rpc.connect(l3.info['id'], 'localhost', l3.info['port'])
|
||||||
|
|
||||||
@@ -1970,14 +1971,14 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
amt = 100000000
|
amt = 100000000
|
||||||
fee = amt * 10 // 1000000 + 1
|
fee = amt * 10 // 1000000 + 1
|
||||||
|
|
||||||
baseroute = [ { 'msatoshi' : amt + fee,
|
baseroute = [{'msatoshi': amt + fee,
|
||||||
'id' : l2.info['id'],
|
'id': l2.info['id'],
|
||||||
'delay' : 12,
|
'delay': 12,
|
||||||
'channel' : chanid1 },
|
'channel': chanid1},
|
||||||
{ 'msatoshi' : amt,
|
{'msatoshi': amt,
|
||||||
'id' : l3.info['id'],
|
'id': l3.info['id'],
|
||||||
'delay' : 6,
|
'delay': 6,
|
||||||
'channel' : chanid2 } ]
|
'channel': chanid2}]
|
||||||
|
|
||||||
# Unknown other peer
|
# Unknown other peer
|
||||||
route = copy.deepcopy(baseroute)
|
route = copy.deepcopy(baseroute)
|
||||||
@@ -2064,7 +2065,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
# here for simplicity:
|
# here for simplicity:
|
||||||
|
|
||||||
# FIXME: Add shadow route
|
# FIXME: Add shadow route
|
||||||
shadow_route=0
|
shadow_route = 0
|
||||||
route = l2.rpc.getroute(l3.info['id'], 4999999, 1)["route"]
|
route = l2.rpc.getroute(l3.info['id'], 4999999, 1)["route"]
|
||||||
assert len(route) == 1
|
assert len(route) == 1
|
||||||
|
|
||||||
@@ -2359,7 +2360,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
for d in disconnects:
|
for d in disconnects:
|
||||||
l1.rpc.connect(l2.info['id'], 'localhost', l2.info['port'])
|
l1.rpc.connect(l2.info['id'], 'localhost', l2.info['port'])
|
||||||
self.assertRaises(ValueError, l1.rpc.fundchannel, l2.info['id'], 20000)
|
self.assertRaises(ValueError, l1.rpc.fundchannel, l2.info['id'], 20000)
|
||||||
assert l1.rpc.getpeer(l2.info['id']) == None
|
assert l1.rpc.getpeer(l2.info['id']) is None
|
||||||
|
|
||||||
# This one will succeed.
|
# This one will succeed.
|
||||||
l1.rpc.connect(l2.info['id'], 'localhost', l2.info['port'])
|
l1.rpc.connect(l2.info['id'], 'localhost', l2.info['port'])
|
||||||
@@ -2383,7 +2384,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
for d in disconnects:
|
for d in disconnects:
|
||||||
l1.rpc.connect(l2.info['id'], 'localhost', l2.info['port'])
|
l1.rpc.connect(l2.info['id'], 'localhost', l2.info['port'])
|
||||||
self.assertRaises(ValueError, l1.rpc.fundchannel, l2.info['id'], 20000)
|
self.assertRaises(ValueError, l1.rpc.fundchannel, l2.info['id'], 20000)
|
||||||
assert l1.rpc.getpeer(l2.info['id']) == None
|
assert l1.rpc.getpeer(l2.info['id']) is None
|
||||||
|
|
||||||
# This one will succeed.
|
# This one will succeed.
|
||||||
l1.rpc.connect(l2.info['id'], 'localhost', l2.info['port'])
|
l1.rpc.connect(l2.info['id'], 'localhost', l2.info['port'])
|
||||||
@@ -2407,7 +2408,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
self.assertRaises(ValueError, l1.rpc.fundchannel, l2.info['id'], 20000)
|
self.assertRaises(ValueError, l1.rpc.fundchannel, l2.info['id'], 20000)
|
||||||
|
|
||||||
# Fundee remembers, funder doesn't.
|
# Fundee remembers, funder doesn't.
|
||||||
assert l1.rpc.getpeer(l2.info['id']) == None
|
assert l1.rpc.getpeer(l2.info['id']) is None
|
||||||
assert l2.rpc.getpeer(l1.info['id'])['id'] == l1.info['id']
|
assert l2.rpc.getpeer(l1.info['id'])['id'] == l1.info['id']
|
||||||
|
|
||||||
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
||||||
@@ -2447,7 +2448,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
|
|
||||||
# l2 closes on l1, l1 forgets.
|
# l2 closes on l1, l1 forgets.
|
||||||
self.assertRaises(ValueError, l1.rpc.fundchannel, l2.info['id'], 20000)
|
self.assertRaises(ValueError, l1.rpc.fundchannel, l2.info['id'], 20000)
|
||||||
assert l1.rpc.getpeer(l2.info['id']) == None
|
assert l1.rpc.getpeer(l2.info['id']) is None
|
||||||
|
|
||||||
# Reconnect.
|
# Reconnect.
|
||||||
l1.rpc.connect(l2.info['id'], 'localhost', l2.info['port'])
|
l1.rpc.connect(l2.info['id'], 'localhost', l2.info['port'])
|
||||||
@@ -2492,9 +2493,9 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
rhash = l2.rpc.invoice(amt, 'test_reconnect_sender_add1', 'desc')['payment_hash']
|
rhash = l2.rpc.invoice(amt, 'test_reconnect_sender_add1', 'desc')['payment_hash']
|
||||||
assert l2.rpc.listinvoices('test_reconnect_sender_add1')['invoices'][0]['status'] == 'unpaid'
|
assert l2.rpc.listinvoices('test_reconnect_sender_add1')['invoices'][0]['status'] == 'unpaid'
|
||||||
|
|
||||||
route = [ { 'msatoshi' : amt, 'id' : l2.info['id'], 'delay' : 5, 'channel': '1:1:1'} ]
|
route = [{'msatoshi': amt, 'id': l2.info['id'], 'delay': 5, 'channel': '1:1:1'}]
|
||||||
|
|
||||||
for i in range(0,len(disconnects)):
|
for i in range(0, len(disconnects)):
|
||||||
self.assertRaises(ValueError, l1.rpc.sendpay, to_json(route), rhash)
|
self.assertRaises(ValueError, l1.rpc.sendpay, to_json(route), rhash)
|
||||||
# Wait for reconnection.
|
# Wait for reconnection.
|
||||||
l1.daemon.wait_for_log('Already have funding locked in')
|
l1.daemon.wait_for_log('Already have funding locked in')
|
||||||
@@ -2520,12 +2521,12 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
rhash = l2.rpc.invoice(amt, 'testpayment', 'desc')['payment_hash']
|
rhash = l2.rpc.invoice(amt, 'testpayment', 'desc')['payment_hash']
|
||||||
assert l2.rpc.listinvoices('testpayment')['invoices'][0]['status'] == 'unpaid'
|
assert l2.rpc.listinvoices('testpayment')['invoices'][0]['status'] == 'unpaid'
|
||||||
|
|
||||||
route = [ { 'msatoshi' : amt, 'id' : l2.info['id'], 'delay' : 5, 'channel': '1:1:1'} ]
|
route = [{'msatoshi': amt, 'id': l2.info['id'], 'delay': 5, 'channel': '1:1:1'}]
|
||||||
|
|
||||||
# This will send commit, so will reconnect as required.
|
# This will send commit, so will reconnect as required.
|
||||||
l1.rpc.sendpay(to_json(route), rhash)
|
l1.rpc.sendpay(to_json(route), rhash)
|
||||||
# Should have printed this for every reconnect.
|
# Should have printed this for every reconnect.
|
||||||
for i in range(0,len(disconnects)):
|
for i in range(0, len(disconnects)):
|
||||||
l1.daemon.wait_for_log('Already have funding locked in')
|
l1.daemon.wait_for_log('Already have funding locked in')
|
||||||
|
|
||||||
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
||||||
@@ -2546,7 +2547,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
rhash = l2.rpc.invoice(amt, 'testpayment2', 'desc')['payment_hash']
|
rhash = l2.rpc.invoice(amt, 'testpayment2', 'desc')['payment_hash']
|
||||||
assert l2.rpc.listinvoices('testpayment2')['invoices'][0]['status'] == 'unpaid'
|
assert l2.rpc.listinvoices('testpayment2')['invoices'][0]['status'] == 'unpaid'
|
||||||
|
|
||||||
route = [ { 'msatoshi' : amt, 'id' : l2.info['id'], 'delay' : 5, 'channel': '1:1:1'} ]
|
route = [{'msatoshi': amt, 'id': l2.info['id'], 'delay': 5, 'channel': '1:1:1'}]
|
||||||
l1.rpc.sendpay(to_json(route), rhash)
|
l1.rpc.sendpay(to_json(route), rhash)
|
||||||
for i in range(len(disconnects)):
|
for i in range(len(disconnects)):
|
||||||
l1.daemon.wait_for_log('Already have funding locked in')
|
l1.daemon.wait_for_log('Already have funding locked in')
|
||||||
@@ -2576,7 +2577,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
rhash = l2.rpc.invoice(amt, 'testpayment2', 'desc')['payment_hash']
|
rhash = l2.rpc.invoice(amt, 'testpayment2', 'desc')['payment_hash']
|
||||||
assert l2.rpc.listinvoices('testpayment2')['invoices'][0]['status'] == 'unpaid'
|
assert l2.rpc.listinvoices('testpayment2')['invoices'][0]['status'] == 'unpaid'
|
||||||
|
|
||||||
route = [ { 'msatoshi' : amt, 'id' : l2.info['id'], 'delay' : 5, 'channel': '1:1:1'} ]
|
route = [{'msatoshi': amt, 'id': l2.info['id'], 'delay': 5, 'channel': '1:1:1'}]
|
||||||
l1.rpc.sendpay(to_json(route), rhash)
|
l1.rpc.sendpay(to_json(route), rhash)
|
||||||
for i in range(len(disconnects)):
|
for i in range(len(disconnects)):
|
||||||
l1.daemon.wait_for_log('Already have funding locked in')
|
l1.daemon.wait_for_log('Already have funding locked in')
|
||||||
@@ -2592,7 +2593,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
l1.rpc.connect(l2.info['id'], 'localhost', l2.info['port'])
|
l1.rpc.connect(l2.info['id'], 'localhost', l2.info['port'])
|
||||||
|
|
||||||
self.fund_channel(l1, l2, 10**6)
|
self.fund_channel(l1, l2, 10**6)
|
||||||
self.pay(l1,l2,200000000)
|
self.pay(l1, l2, 200000000)
|
||||||
|
|
||||||
assert l1.bitcoin.rpc.getmempoolinfo()['size'] == 0
|
assert l1.bitcoin.rpc.getmempoolinfo()['size'] == 0
|
||||||
|
|
||||||
@@ -2620,7 +2621,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
l1.rpc.connect(l2.info['id'], 'localhost', l2.info['port'])
|
l1.rpc.connect(l2.info['id'], 'localhost', l2.info['port'])
|
||||||
|
|
||||||
self.fund_channel(l1, l2, 10**6)
|
self.fund_channel(l1, l2, 10**6)
|
||||||
self.pay(l1,l2,200000000)
|
self.pay(l1, l2, 200000000)
|
||||||
|
|
||||||
assert l1.bitcoin.rpc.getmempoolinfo()['size'] == 0
|
assert l1.bitcoin.rpc.getmempoolinfo()['size'] == 0
|
||||||
|
|
||||||
@@ -2693,7 +2694,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
self.assertRaises(ValueError, l1.rpc.withdraw, waddr, 'not an amount')
|
self.assertRaises(ValueError, l1.rpc.withdraw, waddr, 'not an amount')
|
||||||
self.assertRaises(ValueError, l1.rpc.withdraw, waddr, -amount)
|
self.assertRaises(ValueError, l1.rpc.withdraw, waddr, -amount)
|
||||||
|
|
||||||
out = l1.rpc.withdraw(waddr, 2*amount)
|
out = l1.rpc.withdraw(waddr, 2 * amount)
|
||||||
|
|
||||||
# Make sure bitcoind received the withdrawal
|
# Make sure bitcoind received the withdrawal
|
||||||
unspent = l1.bitcoin.rpc.listunspent(0)
|
unspent = l1.bitcoin.rpc.listunspent(0)
|
||||||
@@ -2710,13 +2711,13 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
# Now send some money to l2.
|
# Now send some money to l2.
|
||||||
# lightningd uses P2SH-P2WPKH
|
# lightningd uses P2SH-P2WPKH
|
||||||
waddr = l2.rpc.newaddr()['address']
|
waddr = l2.rpc.newaddr()['address']
|
||||||
out = l1.rpc.withdraw(waddr, 2*amount)
|
out = l1.rpc.withdraw(waddr, 2 * amount)
|
||||||
l1.bitcoin.rpc.generate(1)
|
l1.bitcoin.rpc.generate(1)
|
||||||
|
|
||||||
# Make sure l2 received the withdrawal.
|
# Make sure l2 received the withdrawal.
|
||||||
wait_for(lambda: len(l2.rpc.listfunds()['outputs']) == 1)
|
wait_for(lambda: len(l2.rpc.listfunds()['outputs']) == 1)
|
||||||
outputs = l2.db_query('SELECT value FROM outputs WHERE status=0;')
|
outputs = l2.db_query('SELECT value FROM outputs WHERE status=0;')
|
||||||
assert len(outputs) == 1 and outputs[0]['value'] == 2*amount
|
assert len(outputs) == 1 and outputs[0]['value'] == 2 * amount
|
||||||
|
|
||||||
# Now make sure an additional two of them were marked as spent
|
# Now make sure an additional two of them were marked as spent
|
||||||
c = db.cursor()
|
c = db.cursor()
|
||||||
@@ -2726,10 +2727,10 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
# Simple test for withdrawal to P2WPKH
|
# Simple test for withdrawal to P2WPKH
|
||||||
# Address from: https://bc-2.jp/tools/bech32demo/index.html
|
# Address from: https://bc-2.jp/tools/bech32demo/index.html
|
||||||
waddr = 'tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx'
|
waddr = 'tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx'
|
||||||
self.assertRaises(ValueError, l1.rpc.withdraw, 'xx1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx', 2*amount)
|
self.assertRaises(ValueError, l1.rpc.withdraw, 'xx1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx', 2 * amount)
|
||||||
self.assertRaises(ValueError, l1.rpc.withdraw, 'tb1pw508d6qejxtdg4y5r3zarvary0c5xw7kdl9fad', 2*amount)
|
self.assertRaises(ValueError, l1.rpc.withdraw, 'tb1pw508d6qejxtdg4y5r3zarvary0c5xw7kdl9fad', 2 * amount)
|
||||||
self.assertRaises(ValueError, l1.rpc.withdraw, 'tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxxxxxx', 2*amount)
|
self.assertRaises(ValueError, l1.rpc.withdraw, 'tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxxxxxx', 2 * amount)
|
||||||
out = l1.rpc.withdraw(waddr, 2*amount)
|
out = l1.rpc.withdraw(waddr, 2 * amount)
|
||||||
l1.bitcoin.rpc.generate(1)
|
l1.bitcoin.rpc.generate(1)
|
||||||
# Now make sure additional two of them were marked as spent
|
# Now make sure additional two of them were marked as spent
|
||||||
c = db.cursor()
|
c = db.cursor()
|
||||||
@@ -2739,10 +2740,10 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
# Simple test for withdrawal to P2WSH
|
# Simple test for withdrawal to P2WSH
|
||||||
# Address from: https://bc-2.jp/tools/bech32demo/index.html
|
# Address from: https://bc-2.jp/tools/bech32demo/index.html
|
||||||
waddr = 'tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7'
|
waddr = 'tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7'
|
||||||
self.assertRaises(ValueError, l1.rpc.withdraw, 'xx1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7', 2*amount)
|
self.assertRaises(ValueError, l1.rpc.withdraw, 'xx1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7', 2 * amount)
|
||||||
self.assertRaises(ValueError, l1.rpc.withdraw, 'tb1prp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qsm03tq', 2*amount)
|
self.assertRaises(ValueError, l1.rpc.withdraw, 'tb1prp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qsm03tq', 2 * amount)
|
||||||
self.assertRaises(ValueError, l1.rpc.withdraw, 'tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qxxxxxx', 2*amount)
|
self.assertRaises(ValueError, l1.rpc.withdraw, 'tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qxxxxxx', 2 * amount)
|
||||||
out = l1.rpc.withdraw(waddr, 2*amount)
|
out = l1.rpc.withdraw(waddr, 2 * amount)
|
||||||
l1.bitcoin.rpc.generate(1)
|
l1.bitcoin.rpc.generate(1)
|
||||||
# Now make sure additional two of them were marked as spent
|
# Now make sure additional two of them were marked as spent
|
||||||
c = db.cursor()
|
c = db.cursor()
|
||||||
@@ -2751,21 +2752,21 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
|
|
||||||
# failure testing for invalid SegWit addresses, from BIP173
|
# failure testing for invalid SegWit addresses, from BIP173
|
||||||
# HRP character out of range
|
# HRP character out of range
|
||||||
self.assertRaises(ValueError, l1.rpc.withdraw, ' 1nwldj5', 2*amount)
|
self.assertRaises(ValueError, l1.rpc.withdraw, ' 1nwldj5', 2 * amount)
|
||||||
# overall max length exceeded
|
# overall max length exceeded
|
||||||
self.assertRaises(ValueError, l1.rpc.withdraw, 'an84characterslonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio1569pvx', 2*amount)
|
self.assertRaises(ValueError, l1.rpc.withdraw, 'an84characterslonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio1569pvx', 2 * amount)
|
||||||
# No separator character
|
# No separator character
|
||||||
self.assertRaises(ValueError, l1.rpc.withdraw, 'pzry9x0s0muk', 2*amount)
|
self.assertRaises(ValueError, l1.rpc.withdraw, 'pzry9x0s0muk', 2 * amount)
|
||||||
# Empty HRP
|
# Empty HRP
|
||||||
self.assertRaises(ValueError, l1.rpc.withdraw, '1pzry9x0s0muk', 2*amount)
|
self.assertRaises(ValueError, l1.rpc.withdraw, '1pzry9x0s0muk', 2 * amount)
|
||||||
# Invalid witness version
|
# Invalid witness version
|
||||||
self.assertRaises(ValueError, l1.rpc.withdraw, 'BC13W508D6QEJXTDG4Y5R3ZARVARY0C5XW7KN40WF2', 2*amount)
|
self.assertRaises(ValueError, l1.rpc.withdraw, 'BC13W508D6QEJXTDG4Y5R3ZARVARY0C5XW7KN40WF2', 2 * amount)
|
||||||
# Invalid program length for witness version 0 (per BIP141)
|
# Invalid program length for witness version 0 (per BIP141)
|
||||||
self.assertRaises(ValueError, l1.rpc.withdraw, 'BC1QR508D6QEJXTDG4Y5R3ZARVARYV98GJ9P', 2*amount)
|
self.assertRaises(ValueError, l1.rpc.withdraw, 'BC1QR508D6QEJXTDG4Y5R3ZARVARYV98GJ9P', 2 * amount)
|
||||||
# Mixed case
|
# Mixed case
|
||||||
self.assertRaises(ValueError, l1.rpc.withdraw, 'tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sL5k7', 2*amount)
|
self.assertRaises(ValueError, l1.rpc.withdraw, 'tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sL5k7', 2 * amount)
|
||||||
# Non-zero padding in 8-to-5 conversion
|
# Non-zero padding in 8-to-5 conversion
|
||||||
self.assertRaises(ValueError, l1.rpc.withdraw, 'tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3pjxtptv', 2*amount)
|
self.assertRaises(ValueError, l1.rpc.withdraw, 'tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3pjxtptv', 2 * amount)
|
||||||
|
|
||||||
# Should have 6 outputs available.
|
# Should have 6 outputs available.
|
||||||
c = db.cursor()
|
c = db.cursor()
|
||||||
@@ -2788,7 +2789,6 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
self.assertRaises(ValueError, l1.rpc.withdraw, waddr, 'all')
|
self.assertRaises(ValueError, l1.rpc.withdraw, waddr, 'all')
|
||||||
l1.daemon.wait_for_log('Cannot afford fee')
|
l1.daemon.wait_for_log('Cannot afford fee')
|
||||||
|
|
||||||
|
|
||||||
def test_funding_change(self):
|
def test_funding_change(self):
|
||||||
"""Add some funds, fund a channel, and make sure we remember the change
|
"""Add some funds, fund a channel, and make sure we remember the change
|
||||||
"""
|
"""
|
||||||
@@ -2826,7 +2826,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
|
|
||||||
# Fail because l1 dislikes l2's huge locktime.
|
# Fail because l1 dislikes l2's huge locktime.
|
||||||
self.assertRaisesRegex(ValueError, r'to_self_delay \d+ larger than \d+',
|
self.assertRaisesRegex(ValueError, r'to_self_delay \d+ larger than \d+',
|
||||||
l1.rpc.fundchannel, l2.info['id'], int(funds/10))
|
l1.rpc.fundchannel, l2.info['id'], int(funds / 10))
|
||||||
assert l1.rpc.listpeers()['peers'][0]['connected']
|
assert l1.rpc.listpeers()['peers'][0]['connected']
|
||||||
assert l2.rpc.listpeers()['peers'][0]['connected']
|
assert l2.rpc.listpeers()['peers'][0]['connected']
|
||||||
|
|
||||||
@@ -2844,7 +2844,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
assert l2.rpc.listpeers()['peers'][0]['connected']
|
assert l2.rpc.listpeers()['peers'][0]['connected']
|
||||||
|
|
||||||
# This works.
|
# This works.
|
||||||
l1.rpc.fundchannel(l2.info['id'], int(funds/10))
|
l1.rpc.fundchannel(l2.info['id'], int(funds / 10))
|
||||||
|
|
||||||
def test_funding_toolarge(self):
|
def test_funding_toolarge(self):
|
||||||
"""Try to create a giant channel"""
|
"""Try to create a giant channel"""
|
||||||
@@ -2868,7 +2868,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
assert 'Funding satoshi must be <= 16777215' in str(err)
|
assert 'Funding satoshi must be <= 16777215' in str(err)
|
||||||
|
|
||||||
# This should work.
|
# This should work.
|
||||||
amount = amount-1
|
amount = amount - 1
|
||||||
l1.rpc.fundchannel(l2.info['id'], amount)
|
l1.rpc.fundchannel(l2.info['id'], amount)
|
||||||
|
|
||||||
def test_lockin_between_restart(self):
|
def test_lockin_between_restart(self):
|
||||||
@@ -2962,7 +2962,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
print(" ".join(l2.daemon.cmd_line + ['--dev-debugger=channeld']))
|
print(" ".join(l2.daemon.cmd_line + ['--dev-debugger=channeld']))
|
||||||
|
|
||||||
# Wait for l1 to notice
|
# Wait for l1 to notice
|
||||||
wait_for(lambda: not 'connected' in l1.rpc.listpeers()['peers'][0]['channels'][0])
|
wait_for(lambda: 'connected' not in l1.rpc.listpeers()['peers'][0]['channels'][0])
|
||||||
|
|
||||||
# Now restart l2 and it should reload peers/channels from the DB
|
# Now restart l2 and it should reload peers/channels from the DB
|
||||||
l2.daemon.start()
|
l2.daemon.start()
|
||||||
@@ -3194,7 +3194,6 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
|
|
||||||
self.assertRaises(ValueError, l2.rpc.waitanyinvoice, 'non-number')
|
self.assertRaises(ValueError, l2.rpc.waitanyinvoice, 'non-number')
|
||||||
|
|
||||||
|
|
||||||
def test_waitanyinvoice_reversed(self):
|
def test_waitanyinvoice_reversed(self):
|
||||||
"""Test waiting for invoices, where they are paid in reverse order
|
"""Test waiting for invoices, where they are paid in reverse order
|
||||||
to when they are created.
|
to when they are created.
|
||||||
@@ -3258,8 +3257,8 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
self.wait_for_routes(l1, [chanid])
|
self.wait_for_routes(l1, [chanid])
|
||||||
|
|
||||||
# Make payments.
|
# Make payments.
|
||||||
self.pay(l1,l2,200000000)
|
self.pay(l1, l2, 200000000)
|
||||||
self.pay(l2,l1,100000000)
|
self.pay(l2, l1, 100000000)
|
||||||
|
|
||||||
# Now shutdown cleanly.
|
# Now shutdown cleanly.
|
||||||
l1.rpc.close(l2.info['id'])
|
l1.rpc.close(l2.info['id'])
|
||||||
@@ -3311,7 +3310,6 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
l1.daemon.wait_for_log(' to CLOSINGD_COMPLETE')
|
l1.daemon.wait_for_log(' to CLOSINGD_COMPLETE')
|
||||||
l2.daemon.wait_for_log(' to CLOSINGD_COMPLETE')
|
l2.daemon.wait_for_log(' to CLOSINGD_COMPLETE')
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
||||||
def test_fee_limits(self):
|
def test_fee_limits(self):
|
||||||
# FIXME: Test case where opening denied.
|
# FIXME: Test case where opening denied.
|
||||||
@@ -3371,8 +3369,8 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
# Wait for reconnect....
|
# Wait for reconnect....
|
||||||
l1.daemon.wait_for_log('Applying feerate 14000 to LOCAL')
|
l1.daemon.wait_for_log('Applying feerate 14000 to LOCAL')
|
||||||
|
|
||||||
self.pay(l1,l2,200000000)
|
self.pay(l1, l2, 200000000)
|
||||||
self.pay(l2,l1,100000000)
|
self.pay(l2, l1, 100000000)
|
||||||
|
|
||||||
# They should both have gotten commits with correct feerate.
|
# They should both have gotten commits with correct feerate.
|
||||||
assert l1.daemon.is_in_log('got commitsig [0-9]*: feerate 14000')
|
assert l1.daemon.is_in_log('got commitsig [0-9]*: feerate 14000')
|
||||||
@@ -3417,7 +3415,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
pid2 = re.search(r'pid ([0-9]*),', pidline).group(1)
|
pid2 = re.search(r'pid ([0-9]*),', pidline).group(1)
|
||||||
l2.daemon.wait_for_log(' to CHANNELD_NORMAL')
|
l2.daemon.wait_for_log(' to CHANNELD_NORMAL')
|
||||||
|
|
||||||
fut = self.pay(l1,l2,200000000,async=True)
|
fut = self.pay(l1, l2, 200000000, async=True)
|
||||||
|
|
||||||
# WIRE_UPDATE_ADD_HTLC = 128 = 0x0080
|
# WIRE_UPDATE_ADD_HTLC = 128 = 0x0080
|
||||||
l1.daemon.wait_for_log(r'channeld.*:\[OUT\] 0080')
|
l1.daemon.wait_for_log(r'channeld.*:\[OUT\] 0080')
|
||||||
@@ -3428,7 +3426,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
# Send it sigusr1: should turn off logging.
|
# Send it sigusr1: should turn off logging.
|
||||||
subprocess.run(['kill', '-USR1', pid1])
|
subprocess.run(['kill', '-USR1', pid1])
|
||||||
|
|
||||||
self.pay(l1,l2,200000000)
|
self.pay(l1, l2, 200000000)
|
||||||
|
|
||||||
assert not l1.daemon.is_in_log(r'channeld.*:\[OUT\] 0080',
|
assert not l1.daemon.is_in_log(r'channeld.*:\[OUT\] 0080',
|
||||||
start=l1.daemon.logsearch_start)
|
start=l1.daemon.logsearch_start)
|
||||||
@@ -3442,7 +3440,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
|
|
||||||
# Turn on in l2 channel logging.
|
# Turn on in l2 channel logging.
|
||||||
subprocess.run(['kill', '-USR1', pid2])
|
subprocess.run(['kill', '-USR1', pid2])
|
||||||
self.pay(l1,l2,200000000)
|
self.pay(l1, l2, 200000000)
|
||||||
|
|
||||||
# Now it should find it.
|
# Now it should find it.
|
||||||
peerlog = l2.rpc.listpeers(l1.info['id'], "io")['peers'][0]['log']
|
peerlog = l2.rpc.listpeers(l1.info['id'], "io")['peers'][0]['log']
|
||||||
@@ -3452,7 +3450,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
||||||
def test_pay_disconnect(self):
|
def test_pay_disconnect(self):
|
||||||
"""If the remote node has disconnected, we fail payment, but can try again when it reconnects"""
|
"""If the remote node has disconnected, we fail payment, but can try again when it reconnects"""
|
||||||
l1,l2 = self.connect()
|
l1, l2 = self.connect()
|
||||||
|
|
||||||
chanid = self.fund_channel(l1, l2, 10**6)
|
chanid = self.fund_channel(l1, l2, 10**6)
|
||||||
|
|
||||||
@@ -3491,10 +3489,10 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
assert configs['bitcoin-datadir'] == bitcoind.bitcoin_dir
|
assert configs['bitcoin-datadir'] == bitcoind.bitcoin_dir
|
||||||
assert configs['lightning-dir'] == l1.daemon.lightning_dir
|
assert configs['lightning-dir'] == l1.daemon.lightning_dir
|
||||||
assert configs['port'] == l1.info['port']
|
assert configs['port'] == l1.info['port']
|
||||||
assert configs['allow-deprecated-apis'] == False
|
assert configs['allow-deprecated-apis'] is False
|
||||||
assert configs['override-fee-rates'] == '15000/7500/1000'
|
assert configs['override-fee-rates'] == '15000/7500/1000'
|
||||||
assert configs['network'] == 'regtest'
|
assert configs['network'] == 'regtest'
|
||||||
assert configs['ignore-fee-limits'] == False
|
assert configs['ignore-fee-limits'] is False
|
||||||
|
|
||||||
# Test one at a time.
|
# Test one at a time.
|
||||||
for c in configs.keys():
|
for c in configs.keys():
|
||||||
@@ -3523,7 +3521,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
channels = l1.rpc.listpeers()['peers'][0]['channels']
|
channels = l1.rpc.listpeers()['peers'][0]['channels']
|
||||||
assert len(channels) == 3
|
assert len(channels) == 3
|
||||||
# Most in state ONCHAIND_MUTUAL, last is CLOSINGD_COMPLETE
|
# Most in state ONCHAIND_MUTUAL, last is CLOSINGD_COMPLETE
|
||||||
for i in range(len(channels)-1):
|
for i in range(len(channels) - 1):
|
||||||
assert channels[i]['state'] == 'ONCHAIND_MUTUAL'
|
assert channels[i]['state'] == 'ONCHAIND_MUTUAL'
|
||||||
assert channels[-1]['state'] == 'CLOSINGD_COMPLETE'
|
assert channels[-1]['state'] == 'CLOSINGD_COMPLETE'
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
from bitcoin.rpc import RawProxy as BitcoinProxy
|
import binascii
|
||||||
from lightning import LightningRpc
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
@@ -8,7 +6,8 @@ import sqlite3
|
|||||||
import subprocess
|
import subprocess
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
import binascii
|
|
||||||
|
from bitcoin.rpc import RawProxy as BitcoinProxy
|
||||||
|
|
||||||
|
|
||||||
BITCOIND_CONFIG = {
|
BITCOIND_CONFIG = {
|
||||||
@@ -28,6 +27,7 @@ LIGHTNINGD_CONFIG = {
|
|||||||
|
|
||||||
DEVELOPER = os.getenv("DEVELOPER", "0") == "1"
|
DEVELOPER = os.getenv("DEVELOPER", "0") == "1"
|
||||||
|
|
||||||
|
|
||||||
def write_config(filename, opts):
|
def write_config(filename, opts):
|
||||||
with open(filename, 'w') as f:
|
with open(filename, 'w') as f:
|
||||||
for k, v in opts.items():
|
for k, v in opts.items():
|
||||||
@@ -109,7 +109,7 @@ class TailableProc(object):
|
|||||||
self.running = False
|
self.running = False
|
||||||
self.proc.stdout.close()
|
self.proc.stdout.close()
|
||||||
|
|
||||||
def is_in_log(self, regex, start = 0):
|
def is_in_log(self, regex, start=0):
|
||||||
"""Look for `regex` in the logs."""
|
"""Look for `regex` in the logs."""
|
||||||
|
|
||||||
ex = re.compile(regex)
|
ex = re.compile(regex)
|
||||||
@@ -135,7 +135,6 @@ class TailableProc(object):
|
|||||||
exs = [re.compile(r) for r in regexs]
|
exs = [re.compile(r) for r in regexs]
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
pos = self.logsearch_start
|
pos = self.logsearch_start
|
||||||
initial_pos = len(self.logs)
|
|
||||||
while True:
|
while True:
|
||||||
if timeout is not None and time.time() > start_time + timeout:
|
if timeout is not None and time.time() > start_time + timeout:
|
||||||
print("Time-out: can't find {} in logs".format(exs))
|
print("Time-out: can't find {} in logs".format(exs))
|
||||||
@@ -152,7 +151,7 @@ class TailableProc(object):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
for r in exs.copy():
|
for r in exs.copy():
|
||||||
self.logsearch_start = pos+1
|
self.logsearch_start = pos + 1
|
||||||
if r.search(self.logs[pos]):
|
if r.search(self.logs[pos]):
|
||||||
logging.debug("Found '%s' in logs", r)
|
logging.debug("Found '%s' in logs", r)
|
||||||
exs.remove(r)
|
exs.remove(r)
|
||||||
@@ -178,7 +177,7 @@ class SimpleBitcoinProxy:
|
|||||||
library to close, reopen and reauth upon failure.
|
library to close, reopen and reauth upon failure.
|
||||||
"""
|
"""
|
||||||
def __init__(self, btc_conf_file, *args, **kwargs):
|
def __init__(self, btc_conf_file, *args, **kwargs):
|
||||||
self.__btc_conf_file__= btc_conf_file
|
self.__btc_conf_file__ = btc_conf_file
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
if name.startswith('__') and name.endswith('__'):
|
if name.startswith('__') and name.endswith('__'):
|
||||||
@@ -240,6 +239,7 @@ class BitcoinD(TailableProc):
|
|||||||
# lightning-4 => 0382ce59ebf18be7d84677c2e35f23294b9992ceca95491fcf8a56c6cb2d9de199 aka JUNIORFELONY #0382ce
|
# lightning-4 => 0382ce59ebf18be7d84677c2e35f23294b9992ceca95491fcf8a56c6cb2d9de199 aka JUNIORFELONY #0382ce
|
||||||
# lightning-5 => 032cf15d1ad9c4a08d26eab1918f732d8ef8fdc6abb9640bf3db174372c491304e aka SOMBERFIRE #032cf1
|
# lightning-5 => 032cf15d1ad9c4a08d26eab1918f732d8ef8fdc6abb9640bf3db174372c491304e aka SOMBERFIRE #032cf1
|
||||||
|
|
||||||
|
|
||||||
class LightningD(TailableProc):
|
class LightningD(TailableProc):
|
||||||
def __init__(self, lightning_dir, bitcoin_dir, port=9735, random_hsm=False):
|
def __init__(self, lightning_dir, bitcoin_dir, port=9735, random_hsm=False):
|
||||||
TailableProc.__init__(self, lightning_dir)
|
TailableProc.__init__(self, lightning_dir)
|
||||||
@@ -281,6 +281,7 @@ class LightningD(TailableProc):
|
|||||||
self.proc.wait(timeout)
|
self.proc.wait(timeout)
|
||||||
return self.proc.returncode
|
return self.proc.returncode
|
||||||
|
|
||||||
|
|
||||||
class LightningNode(object):
|
class LightningNode(object):
|
||||||
def __init__(self, daemon, rpc, btc, executor, may_fail=False):
|
def __init__(self, daemon, rpc, btc, executor, may_fail=False):
|
||||||
self.rpc = rpc
|
self.rpc = rpc
|
||||||
@@ -316,7 +317,7 @@ class LightningNode(object):
|
|||||||
|
|
||||||
self.bitcoin.generate_block(1)
|
self.bitcoin.generate_block(1)
|
||||||
|
|
||||||
#fut.result(timeout=5)
|
# fut.result(timeout=5)
|
||||||
|
|
||||||
# Now wait for confirmation
|
# Now wait for confirmation
|
||||||
self.daemon.wait_for_log(" to CHANNELD_NORMAL|STATE_NORMAL")
|
self.daemon.wait_for_log(" to CHANNELD_NORMAL|STATE_NORMAL")
|
||||||
|
|||||||
@@ -3,10 +3,11 @@
|
|||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import copy
|
import copy
|
||||||
from collections import namedtuple
|
|
||||||
import fileinput
|
import fileinput
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
from collections import namedtuple
|
||||||
|
|
||||||
Enumtype = namedtuple('Enumtype', ['name', 'value'])
|
Enumtype = namedtuple('Enumtype', ['name', 'value'])
|
||||||
|
|
||||||
type2size = {
|
type2size = {
|
||||||
@@ -36,8 +37,9 @@ varlen_structs = [
|
|||||||
'wirestring',
|
'wirestring',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class FieldType(object):
|
class FieldType(object):
|
||||||
def __init__(self,name):
|
def __init__(self, name):
|
||||||
self.name = name
|
self.name = name
|
||||||
|
|
||||||
def is_assignable(self):
|
def is_assignable(self):
|
||||||
@@ -96,6 +98,7 @@ sizetypemap = {
|
|||||||
1: FieldType('u8')
|
1: FieldType('u8')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# It would be nicer if we had put '*u8' in spec and disallowed bare lenvar.
|
# It would be nicer if we had put '*u8' in spec and disallowed bare lenvar.
|
||||||
# In practice we only recognize lenvar when it's the previous field.
|
# In practice we only recognize lenvar when it's the previous field.
|
||||||
|
|
||||||
@@ -129,7 +132,7 @@ class Field(object):
|
|||||||
# Bolts use just a number: Guess type based on size.
|
# Bolts use just a number: Guess type based on size.
|
||||||
if options.bolt:
|
if options.bolt:
|
||||||
base_size = int(size)
|
base_size = int(size)
|
||||||
self.fieldtype = Field._guess_type(message,self.name,base_size)
|
self.fieldtype = Field._guess_type(message, self.name, base_size)
|
||||||
# There are some arrays which we have to guess, based on sizes.
|
# There are some arrays which we have to guess, based on sizes.
|
||||||
tsize = FieldType._typesize(self.fieldtype.name)
|
tsize = FieldType._typesize(self.fieldtype.name)
|
||||||
if base_size % tsize != 0:
|
if base_size % tsize != 0:
|
||||||
@@ -144,11 +147,11 @@ class Field(object):
|
|||||||
self.fieldtype = FieldType(size)
|
self.fieldtype = FieldType(size)
|
||||||
|
|
||||||
def basetype(self):
|
def basetype(self):
|
||||||
base=self.fieldtype.name
|
base = self.fieldtype.name
|
||||||
if base.startswith('struct '):
|
if base.startswith('struct '):
|
||||||
base=base[7:]
|
base = base[7:]
|
||||||
elif base.startswith('enum '):
|
elif base.startswith('enum '):
|
||||||
base=base[5:]
|
base = base[5:]
|
||||||
return base
|
return base
|
||||||
|
|
||||||
def is_padding(self):
|
def is_padding(self):
|
||||||
@@ -185,7 +188,7 @@ class Field(object):
|
|||||||
if base_size in sizetypemap:
|
if base_size in sizetypemap:
|
||||||
return sizetypemap[base_size]
|
return sizetypemap[base_size]
|
||||||
|
|
||||||
raise ValueError('Unknown size {} for {}'.format(base_size,fieldname))
|
raise ValueError('Unknown size {} for {}'.format(base_size, fieldname))
|
||||||
|
|
||||||
fromwire_impl_templ = """bool fromwire_{name}({ctx}const void *p{args})
|
fromwire_impl_templ = """bool fromwire_{name}({ctx}const void *p{args})
|
||||||
{{
|
{{
|
||||||
@@ -234,8 +237,9 @@ printwire_impl_templ = """void printwire_{name}(const u8 *cursor)
|
|||||||
}}
|
}}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
class Message(object):
|
class Message(object):
|
||||||
def __init__(self,name,enum,comments):
|
def __init__(self, name, enum, comments):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.enum = enum
|
self.enum = enum
|
||||||
self.comments = comments
|
self.comments = comments
|
||||||
@@ -252,13 +256,13 @@ class Message(object):
|
|||||||
if f.is_array() or f.is_variable_size():
|
if f.is_array() or f.is_variable_size():
|
||||||
raise ValueError('Field {} has non-simple length variable {}'
|
raise ValueError('Field {} has non-simple length variable {}'
|
||||||
.format(field.name, field.lenvar))
|
.format(field.name, field.lenvar))
|
||||||
f.is_len_var = True;
|
f.is_len_var = True
|
||||||
f.lenvar_for = field
|
f.lenvar_for = field
|
||||||
return
|
return
|
||||||
raise ValueError('Field {} unknown length variable {}'
|
raise ValueError('Field {} unknown length variable {}'
|
||||||
.format(field.name, field.lenvar))
|
.format(field.name, field.lenvar))
|
||||||
|
|
||||||
def addField(self,field):
|
def addField(self, field):
|
||||||
# We assume field lengths are 16 bit, to avoid overflow issues and
|
# We assume field lengths are 16 bit, to avoid overflow issues and
|
||||||
# massive allocations.
|
# massive allocations.
|
||||||
if field.is_variable_size():
|
if field.is_variable_size():
|
||||||
@@ -285,7 +289,7 @@ class Message(object):
|
|||||||
subcalls.append('\t\tfromwire_{}(&cursor, &plen, {} + i);'
|
subcalls.append('\t\tfromwire_{}(&cursor, &plen, {} + i);'
|
||||||
.format(basetype, name))
|
.format(basetype, name))
|
||||||
|
|
||||||
def print_fromwire(self,is_header):
|
def print_fromwire(self, is_header):
|
||||||
ctx_arg = 'const tal_t *ctx, ' if self.has_variable_fields else ''
|
ctx_arg = 'const tal_t *ctx, ' if self.has_variable_fields else ''
|
||||||
|
|
||||||
args = []
|
args = []
|
||||||
@@ -296,7 +300,7 @@ class Message(object):
|
|||||||
elif f.is_array():
|
elif f.is_array():
|
||||||
args.append(', {} {}[{}]'.format(f.fieldtype.name, f.name, f.num_elems))
|
args.append(', {} {}[{}]'.format(f.fieldtype.name, f.name, f.num_elems))
|
||||||
else:
|
else:
|
||||||
ptrs='*'
|
ptrs = '*'
|
||||||
# If we're handing a variable array, we need a ptr-to-ptr.
|
# If we're handing a variable array, we need a ptr-to-ptr.
|
||||||
if f.is_variable_size():
|
if f.is_variable_size():
|
||||||
ptrs += '*'
|
ptrs += '*'
|
||||||
@@ -311,7 +315,7 @@ class Message(object):
|
|||||||
|
|
||||||
subcalls = []
|
subcalls = []
|
||||||
for f in self.fields:
|
for f in self.fields:
|
||||||
basetype=f.basetype()
|
basetype = f.basetype()
|
||||||
|
|
||||||
for c in f.comments:
|
for c in f.comments:
|
||||||
subcalls.append('\t/*{} */'.format(c))
|
subcalls.append('\t/*{} */'.format(c))
|
||||||
@@ -331,7 +335,7 @@ class Message(object):
|
|||||||
subcalls.append('\t*{} = {} ? tal_arr(ctx, {}, {}) : NULL;'
|
subcalls.append('\t*{} = {} ? tal_arr(ctx, {}, {}) : NULL;'
|
||||||
.format(f.name, f.lenvar, typename, f.lenvar))
|
.format(f.name, f.lenvar, typename, f.lenvar))
|
||||||
|
|
||||||
self.print_fromwire_array(subcalls, basetype, f, '*'+f.name,
|
self.print_fromwire_array(subcalls, basetype, f, '*' + f.name,
|
||||||
f.lenvar)
|
f.lenvar)
|
||||||
elif f.is_assignable():
|
elif f.is_assignable():
|
||||||
subcalls.append("\t//3th case {name}".format(name=f.name))
|
subcalls.append("\t//3th case {name}".format(name=f.name))
|
||||||
@@ -371,7 +375,7 @@ class Message(object):
|
|||||||
subcalls.append('\t\ttowire_{}(&p, {} + i);'
|
subcalls.append('\t\ttowire_{}(&p, {} + i);'
|
||||||
.format(basetype, f.name))
|
.format(basetype, f.name))
|
||||||
|
|
||||||
def print_towire(self,is_header):
|
def print_towire(self, is_header):
|
||||||
template = towire_header_templ if is_header else towire_impl_templ
|
template = towire_header_templ if is_header else towire_impl_templ
|
||||||
args = []
|
args = []
|
||||||
for f in self.fields:
|
for f in self.fields:
|
||||||
@@ -391,15 +395,15 @@ class Message(object):
|
|||||||
if f.is_len_var:
|
if f.is_len_var:
|
||||||
field_decls.append('\t{0} {1} = tal_count({2});'.format(
|
field_decls.append('\t{0} {1} = tal_count({2});'.format(
|
||||||
f.fieldtype.name, f.name, f.lenvar_for.name
|
f.fieldtype.name, f.name, f.lenvar_for.name
|
||||||
));
|
))
|
||||||
|
|
||||||
subcalls = []
|
subcalls = []
|
||||||
for f in self.fields:
|
for f in self.fields:
|
||||||
basetype=f.fieldtype.name
|
basetype = f.fieldtype.name
|
||||||
if basetype.startswith('struct '):
|
if basetype.startswith('struct '):
|
||||||
basetype=basetype[7:]
|
basetype = basetype[7:]
|
||||||
elif basetype.startswith('enum '):
|
elif basetype.startswith('enum '):
|
||||||
basetype=basetype[5:]
|
basetype = basetype[5:]
|
||||||
|
|
||||||
for c in f.comments:
|
for c in f.comments:
|
||||||
subcalls.append('\t/*{} */'.format(c))
|
subcalls.append('\t/*{} */'.format(c))
|
||||||
@@ -438,13 +442,13 @@ class Message(object):
|
|||||||
subcalls.append('\tprintf("[");')
|
subcalls.append('\tprintf("[");')
|
||||||
subcalls.append('\tfor (size_t i = 0; i < {}; i++) {{'
|
subcalls.append('\tfor (size_t i = 0; i < {}; i++) {{'
|
||||||
.format(num_elems))
|
.format(num_elems))
|
||||||
subcalls.append('\t\t{} v;'.format(f.fieldtype.name));
|
subcalls.append('\t\t{} v;'.format(f.fieldtype.name))
|
||||||
if f.fieldtype.is_assignable():
|
if f.fieldtype.is_assignable():
|
||||||
subcalls.append('\t\tv = fromwire_{}(&cursor, plen);'
|
subcalls.append('\t\tv = fromwire_{}(&cursor, plen);'
|
||||||
.format(name,basetype))
|
.format(name, basetype))
|
||||||
else:
|
else:
|
||||||
# We don't handle this yet!
|
# We don't handle this yet!
|
||||||
assert not basetype in varlen_structs
|
assert(basetype not in varlen_structs)
|
||||||
|
|
||||||
subcalls.append('\t\tfromwire_{}(&cursor, &plen, &v);'
|
subcalls.append('\t\tfromwire_{}(&cursor, &plen, &v);'
|
||||||
.format(basetype))
|
.format(basetype))
|
||||||
@@ -455,13 +459,13 @@ class Message(object):
|
|||||||
subcalls.append('\t}')
|
subcalls.append('\t}')
|
||||||
subcalls.append('\tprintf("]");')
|
subcalls.append('\tprintf("]");')
|
||||||
|
|
||||||
def print_printwire(self,is_header):
|
def print_printwire(self, is_header):
|
||||||
template = printwire_header_templ if is_header else printwire_impl_templ
|
template = printwire_header_templ if is_header else printwire_impl_templ
|
||||||
fields = ['\t{} {};\n'.format(f.fieldtype.name, f.name) for f in self.fields if f.is_len_var]
|
fields = ['\t{} {};\n'.format(f.fieldtype.name, f.name) for f in self.fields if f.is_len_var]
|
||||||
|
|
||||||
subcalls = []
|
subcalls = []
|
||||||
for f in self.fields:
|
for f in self.fields:
|
||||||
basetype=f.basetype()
|
basetype = f.basetype()
|
||||||
|
|
||||||
for c in f.comments:
|
for c in f.comments:
|
||||||
subcalls.append('\t/*{} */'.format(c))
|
subcalls.append('\t/*{} */'.format(c))
|
||||||
@@ -489,9 +493,9 @@ class Message(object):
|
|||||||
.format(f.fieldtype.name, f.name, basetype))
|
.format(f.fieldtype.name, f.name, basetype))
|
||||||
else:
|
else:
|
||||||
# Don't handle these yet.
|
# Don't handle these yet.
|
||||||
assert not basetype in varlen_structs
|
assert(basetype not in varlen_structs)
|
||||||
subcalls.append('\t{} {};'.
|
subcalls.append('\t{} {};'.
|
||||||
format(f.fieldtype.name, f.name));
|
format(f.fieldtype.name, f.name))
|
||||||
subcalls.append('\tfromwire_{}(&cursor, &plen, &{});'
|
subcalls.append('\tfromwire_{}(&cursor, &plen, &{});'
|
||||||
.format(basetype, f.name))
|
.format(basetype, f.name))
|
||||||
|
|
||||||
@@ -506,6 +510,7 @@ class Message(object):
|
|||||||
subcalls='\n'.join(subcalls)
|
subcalls='\n'.join(subcalls)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def find_message(messages, name):
|
def find_message(messages, name):
|
||||||
for m in messages:
|
for m in messages:
|
||||||
if m.name == name:
|
if m.name == name:
|
||||||
@@ -513,6 +518,7 @@ def find_message(messages, name):
|
|||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def find_message_with_option(messages, optional_messages, name, option):
|
def find_message_with_option(messages, optional_messages, name, option):
|
||||||
fullname = name + "_" + option.replace('-', '_')
|
fullname = name + "_" + option.replace('-', '_')
|
||||||
|
|
||||||
@@ -563,8 +569,8 @@ for line in fileinput.input(options.files):
|
|||||||
|
|
||||||
if len(parts) == 2:
|
if len(parts) == 2:
|
||||||
# eg commit_sig,132
|
# eg commit_sig,132
|
||||||
messages.append(Message(parts[0],Enumtype("WIRE_" + parts[0].upper(), parts[1]), comments))
|
messages.append(Message(parts[0], Enumtype("WIRE_" + parts[0].upper(), parts[1]), comments))
|
||||||
comments=[]
|
comments = []
|
||||||
prevfield = None
|
prevfield = None
|
||||||
else:
|
else:
|
||||||
if len(parts) == 4:
|
if len(parts) == 4:
|
||||||
@@ -586,7 +592,7 @@ for line in fileinput.input(options.files):
|
|||||||
# time (multiple fields can use the same lenvar).
|
# time (multiple fields can use the same lenvar).
|
||||||
if not f.lenvar:
|
if not f.lenvar:
|
||||||
prevfield = parts[2]
|
prevfield = parts[2]
|
||||||
comments=[]
|
comments = []
|
||||||
|
|
||||||
header_template = """/* This file was generated by generate-wire.py */
|
header_template = """/* This file was generated by generate-wire.py */
|
||||||
/* Do not modify this file! Modify the _csv file it was generated from. */
|
/* Do not modify this file! Modify the _csv file it was generated from. */
|
||||||
@@ -678,7 +684,7 @@ for m in messages:
|
|||||||
enums += '\t{} = {},\n'.format(m.enum.name, m.enum.value)
|
enums += '\t{} = {},\n'.format(m.enum.name, m.enum.value)
|
||||||
includes = '\n'.join(includes)
|
includes = '\n'.join(includes)
|
||||||
cases = ['case {enum.name}: return "{enum.name}";'.format(enum=m.enum) for m in messages]
|
cases = ['case {enum.name}: return "{enum.name}";'.format(enum=m.enum) for m in messages]
|
||||||
printcases = ['case {enum.name}: printf("{enum.name}:\\n"); printwire_{name}(msg); return;'.format(enum=m.enum,name=m.name) for m in messages]
|
printcases = ['case {enum.name}: printf("{enum.name}:\\n"); printwire_{name}(msg); return;'.format(enum=m.enum, name=m.name) for m in messages]
|
||||||
|
|
||||||
if options.printwire:
|
if options.printwire:
|
||||||
decls = [m.print_printwire(options.header) for m in messages + messages_with_option]
|
decls = [m.print_printwire(options.header) for m in messages + messages_with_option]
|
||||||
|
|||||||
Reference in New Issue
Block a user