unit tests: tests for both anchors and old ctx types
* in test_lnutil, patch htlc weight to pass original anchor commitment test vectors * activate tests for both commitment types
This commit is contained in:
@@ -28,6 +28,7 @@ class ElectrumTestCase(unittest.IsolatedAsyncioTestCase, Logger):
|
|||||||
"""Base class for our unit tests."""
|
"""Base class for our unit tests."""
|
||||||
|
|
||||||
TESTNET = False
|
TESTNET = False
|
||||||
|
TEST_ANCHOR_CHANNELS = False
|
||||||
# maxDiff = None # for debugging
|
# maxDiff = None # for debugging
|
||||||
|
|
||||||
# some unit tests are modifying globals... so we run sequentially:
|
# some unit tests are modifying globals... so we run sequentially:
|
||||||
|
|||||||
@@ -43,17 +43,16 @@ from electrum.coinchooser import PRNG
|
|||||||
|
|
||||||
from . import ElectrumTestCase
|
from . import ElectrumTestCase
|
||||||
|
|
||||||
TEST_ANCHOR_CHANNELS = True
|
|
||||||
|
|
||||||
one_bitcoin_in_msat = bitcoin.COIN * 1000
|
one_bitcoin_in_msat = bitcoin.COIN * 1000
|
||||||
|
|
||||||
|
|
||||||
def create_channel_state(funding_txid, funding_index, funding_sat, is_initiator,
|
def create_channel_state(funding_txid, funding_index, funding_sat, is_initiator,
|
||||||
local_amount, remote_amount, privkeys, other_pubkeys,
|
local_amount, remote_amount, privkeys, other_pubkeys,
|
||||||
seed, cur, nex, other_node_id, l_dust, r_dust, l_csv,
|
seed, cur, nex, other_node_id, l_dust, r_dust, l_csv,
|
||||||
r_csv, anchor_outputs=TEST_ANCHOR_CHANNELS):
|
r_csv, anchor_outputs):
|
||||||
#assert local_amount > 0
|
#assert local_amount > 0
|
||||||
#assert remote_amount > 0
|
#assert remote_amount > 0
|
||||||
|
|
||||||
channel_id, _ = lnpeer.channel_id_from_funding_tx(funding_txid, funding_index)
|
channel_id, _ = lnpeer.channel_id_from_funding_tx(funding_txid, funding_index)
|
||||||
channel_type = lnutil.ChannelType.OPTION_STATIC_REMOTEKEY
|
channel_type = lnutil.ChannelType.OPTION_STATIC_REMOTEKEY
|
||||||
if anchor_outputs:
|
if anchor_outputs:
|
||||||
@@ -130,7 +129,7 @@ def bip32(sequence):
|
|||||||
def create_test_channels(*, feerate=6000, local_msat=None, remote_msat=None,
|
def create_test_channels(*, feerate=6000, local_msat=None, remote_msat=None,
|
||||||
alice_name="alice", bob_name="bob",
|
alice_name="alice", bob_name="bob",
|
||||||
alice_pubkey=b"\x01"*33, bob_pubkey=b"\x02"*33, random_seed=None,
|
alice_pubkey=b"\x01"*33, bob_pubkey=b"\x02"*33, random_seed=None,
|
||||||
anchor_outputs=TEST_ANCHOR_CHANNELS):
|
anchor_outputs=False):
|
||||||
if random_seed is None: # needed for deterministic randomness
|
if random_seed is None: # needed for deterministic randomness
|
||||||
random_seed = os.urandom(32)
|
random_seed = os.urandom(32)
|
||||||
random_gen = PRNG(random_seed)
|
random_gen = PRNG(random_seed)
|
||||||
@@ -214,10 +213,12 @@ class TestFee(ElectrumTestCase):
|
|||||||
https://github.com/lightningnetwork/lightning-rfc/blob/e0c436bd7a3ed6a028e1cb472908224658a14eca/03-transactions.md#requirements-2
|
https://github.com/lightningnetwork/lightning-rfc/blob/e0c436bd7a3ed6a028e1cb472908224658a14eca/03-transactions.md#requirements-2
|
||||||
"""
|
"""
|
||||||
def test_fee(self):
|
def test_fee(self):
|
||||||
alice_channel, bob_channel = create_test_channels(feerate=253,
|
alice_channel, bob_channel = create_test_channels(
|
||||||
local_msat=10000000000,
|
feerate=253,
|
||||||
remote_msat=5000000000, anchor_outputs=TEST_ANCHOR_CHANNELS)
|
local_msat=10000000000,
|
||||||
expected_value = 9999056 if TEST_ANCHOR_CHANNELS else 9999817
|
remote_msat=5000000000,
|
||||||
|
anchor_outputs=self.TEST_ANCHOR_CHANNELS)
|
||||||
|
expected_value = 9999056 if self.TEST_ANCHOR_CHANNELS else 9999817
|
||||||
self.assertIn(expected_value, [x.value for x in alice_channel.get_latest_commitment(LOCAL).outputs()])
|
self.assertIn(expected_value, [x.value for x in alice_channel.get_latest_commitment(LOCAL).outputs()])
|
||||||
|
|
||||||
class TestChannel(ElectrumTestCase):
|
class TestChannel(ElectrumTestCase):
|
||||||
@@ -231,7 +232,7 @@ class TestChannel(ElectrumTestCase):
|
|||||||
self.assertFalse()
|
self.assertFalse()
|
||||||
|
|
||||||
def assertNumberNonAnchorOutputs(self, number, tx):
|
def assertNumberNonAnchorOutputs(self, number, tx):
|
||||||
self.assertEqual(number, len(tx.outputs()) - (2 if TEST_ANCHOR_CHANNELS else 0))
|
self.assertEqual(number, len(tx.outputs()) - (2 if self.TEST_ANCHOR_CHANNELS else 0))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
@@ -243,7 +244,7 @@ class TestChannel(ElectrumTestCase):
|
|||||||
# Create a test channel which will be used for the duration of this
|
# Create a test channel which will be used for the duration of this
|
||||||
# unittest. The channel will be funded evenly with Alice having 5 BTC,
|
# unittest. The channel will be funded evenly with Alice having 5 BTC,
|
||||||
# and Bob having 5 BTC.
|
# and Bob having 5 BTC.
|
||||||
self.alice_channel, self.bob_channel = create_test_channels(anchor_outputs=TEST_ANCHOR_CHANNELS)
|
self.alice_channel, self.bob_channel = create_test_channels(anchor_outputs=self.TEST_ANCHOR_CHANNELS)
|
||||||
|
|
||||||
self.paymentPreimage = b"\x01" * 32
|
self.paymentPreimage = b"\x01" * 32
|
||||||
paymentHash = bitcoin.sha256(self.paymentPreimage)
|
paymentHash = bitcoin.sha256(self.paymentPreimage)
|
||||||
@@ -566,7 +567,6 @@ class TestChannel(ElectrumTestCase):
|
|||||||
self.assertEqual(bob_channel.total_msat(RECEIVED), one_bitcoin_in_msat, "bob satoshis received incorrect")
|
self.assertEqual(bob_channel.total_msat(RECEIVED), one_bitcoin_in_msat, "bob satoshis received incorrect")
|
||||||
self.assertEqual(bob_channel.total_msat(SENT), 5 * one_bitcoin_in_msat, "bob satoshis sent incorrect")
|
self.assertEqual(bob_channel.total_msat(SENT), 5 * one_bitcoin_in_msat, "bob satoshis sent incorrect")
|
||||||
|
|
||||||
|
|
||||||
def alice_to_bob_fee_update(self, fee=1111):
|
def alice_to_bob_fee_update(self, fee=1111):
|
||||||
aoldctx = self.alice_channel.get_next_commitment(REMOTE).outputs()
|
aoldctx = self.alice_channel.get_next_commitment(REMOTE).outputs()
|
||||||
self.alice_channel.update_fee(fee, True)
|
self.alice_channel.update_fee(fee, True)
|
||||||
@@ -670,9 +670,13 @@ class TestChannel(ElectrumTestCase):
|
|||||||
self.assertIn('Not enough local balance', cm.exception.args[0])
|
self.assertIn('Not enough local balance', cm.exception.args[0])
|
||||||
|
|
||||||
|
|
||||||
|
class TestChannelAnchors(TestChannel):
|
||||||
|
TEST_ANCHOR_CHANNELS = True
|
||||||
|
|
||||||
|
|
||||||
class TestAvailableToSpend(ElectrumTestCase):
|
class TestAvailableToSpend(ElectrumTestCase):
|
||||||
def test_DesyncHTLCs(self):
|
def test_DesyncHTLCs(self):
|
||||||
alice_channel, bob_channel = create_test_channels()
|
alice_channel, bob_channel = create_test_channels(anchor_outputs=self.TEST_ANCHOR_CHANNELS)
|
||||||
self.assertEqual(499986152000 if not alice_channel.has_anchors() else 499980692000, alice_channel.available_to_spend(LOCAL))
|
self.assertEqual(499986152000 if not alice_channel.has_anchors() else 499980692000, alice_channel.available_to_spend(LOCAL))
|
||||||
self.assertEqual(500000000000, bob_channel.available_to_spend(LOCAL))
|
self.assertEqual(500000000000, bob_channel.available_to_spend(LOCAL))
|
||||||
|
|
||||||
@@ -718,9 +722,13 @@ class TestAvailableToSpend(ElectrumTestCase):
|
|||||||
alice_channel.add_htlc(htlc)
|
alice_channel.add_htlc(htlc)
|
||||||
|
|
||||||
|
|
||||||
|
class TestAvailableToSpendAnchors(TestAvailableToSpend):
|
||||||
|
TEST_ANCHOR_CHANNELS = True
|
||||||
|
|
||||||
|
|
||||||
class TestChanReserve(ElectrumTestCase):
|
class TestChanReserve(ElectrumTestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
alice_channel, bob_channel = create_test_channels()
|
alice_channel, bob_channel = create_test_channels(anchor_outputs=False)
|
||||||
alice_min_reserve = int(.5 * one_bitcoin_in_msat // 1000)
|
alice_min_reserve = int(.5 * one_bitcoin_in_msat // 1000)
|
||||||
# We set Bob's channel reserve to a value that is larger than
|
# We set Bob's channel reserve to a value that is larger than
|
||||||
# his current balance in the channel. This will ensure that
|
# his current balance in the channel. This will ensure that
|
||||||
@@ -847,10 +855,15 @@ class TestChanReserve(ElectrumTestCase):
|
|||||||
self.assertEqual(self.alice_channel.available_to_spend(REMOTE), amt2)
|
self.assertEqual(self.alice_channel.available_to_spend(REMOTE), amt2)
|
||||||
self.assertEqual(self.bob_channel.available_to_spend(LOCAL), amt2)
|
self.assertEqual(self.bob_channel.available_to_spend(LOCAL), amt2)
|
||||||
|
|
||||||
|
|
||||||
|
class TestChanReserveAnchors(TestChanReserve):
|
||||||
|
TEST_ANCHOR_CHANNELS = True
|
||||||
|
|
||||||
|
|
||||||
class TestDust(ElectrumTestCase):
|
class TestDust(ElectrumTestCase):
|
||||||
def test_DustLimit(self):
|
def test_DustLimit(self):
|
||||||
"""Test that addition of an HTLC below the dust limit changes the balances."""
|
"""Test that addition of an HTLC below the dust limit changes the balances."""
|
||||||
alice_channel, bob_channel = create_test_channels()
|
alice_channel, bob_channel = create_test_channels(anchor_outputs=self.TEST_ANCHOR_CHANNELS)
|
||||||
dust_limit_alice = alice_channel.config[LOCAL].dust_limit_sat
|
dust_limit_alice = alice_channel.config[LOCAL].dust_limit_sat
|
||||||
dust_limit_bob = bob_channel.config[LOCAL].dust_limit_sat
|
dust_limit_bob = bob_channel.config[LOCAL].dust_limit_sat
|
||||||
self.assertLess(dust_limit_alice, dust_limit_bob)
|
self.assertLess(dust_limit_alice, dust_limit_bob)
|
||||||
@@ -860,7 +873,7 @@ class TestDust(ElectrumTestCase):
|
|||||||
paymentPreimage = b"\x01" * 32
|
paymentPreimage = b"\x01" * 32
|
||||||
paymentHash = bitcoin.sha256(paymentPreimage)
|
paymentHash = bitcoin.sha256(paymentPreimage)
|
||||||
fee_per_kw = alice_channel.get_next_feerate(LOCAL)
|
fee_per_kw = alice_channel.get_next_feerate(LOCAL)
|
||||||
success_weight = effective_htlc_tx_weight(success=True, has_anchors=TEST_ANCHOR_CHANNELS)
|
success_weight = effective_htlc_tx_weight(success=True, has_anchors=self.TEST_ANCHOR_CHANNELS)
|
||||||
# we put a single sat less into the htlc than bob can afford
|
# we put a single sat less into the htlc than bob can afford
|
||||||
# to pay for his htlc success transaction
|
# to pay for his htlc success transaction
|
||||||
below_dust_for_bob = dust_limit_bob - 1
|
below_dust_for_bob = dust_limit_bob - 1
|
||||||
@@ -882,13 +895,13 @@ class TestDust(ElectrumTestCase):
|
|||||||
self.assertNotEqual(bobs_original_outputs, bobs_second_outputs)
|
self.assertNotEqual(bobs_original_outputs, bobs_second_outputs)
|
||||||
# the htlc appears as an output in alice's ctx, as she has a lower
|
# the htlc appears as an output in alice's ctx, as she has a lower
|
||||||
# dust limit (also because her timeout tx costs less)
|
# dust limit (also because her timeout tx costs less)
|
||||||
self.assertEqual(3, len(alice_ctx.outputs()) - (2 if TEST_ANCHOR_CHANNELS else 0))
|
self.assertEqual(3, len(alice_ctx.outputs()) - (2 if self.TEST_ANCHOR_CHANNELS else 0))
|
||||||
# htlc in bob's case goes to miner fees
|
# htlc in bob's case goes to miner fees
|
||||||
self.assertEqual(2, len(bob_ctx.outputs()) - (2 if TEST_ANCHOR_CHANNELS else 0))
|
self.assertEqual(2, len(bob_ctx.outputs()) - (2 if self.TEST_ANCHOR_CHANNELS else 0))
|
||||||
self.assertEqual(htlc_amt, sum(bobs_original_outputs) - sum(bobs_second_outputs))
|
self.assertEqual(htlc_amt, sum(bobs_original_outputs) - sum(bobs_second_outputs))
|
||||||
empty_ctx_fee = lnutil.calc_fees_for_commitment_tx(
|
empty_ctx_fee = lnutil.calc_fees_for_commitment_tx(
|
||||||
num_htlcs=0, feerate=fee_per_kw, is_local_initiator=True,
|
num_htlcs=0, feerate=fee_per_kw, is_local_initiator=True,
|
||||||
round_to_sat=True, has_anchors=TEST_ANCHOR_CHANNELS)[LOCAL] // 1000
|
round_to_sat=True, has_anchors=self.TEST_ANCHOR_CHANNELS)[LOCAL] // 1000
|
||||||
self.assertEqual(empty_ctx_fee + htlc_amt, bob_channel.get_next_fee(LOCAL))
|
self.assertEqual(empty_ctx_fee + htlc_amt, bob_channel.get_next_fee(LOCAL))
|
||||||
|
|
||||||
bob_channel.settle_htlc(paymentPreimage, bob_htlc_id)
|
bob_channel.settle_htlc(paymentPreimage, bob_htlc_id)
|
||||||
@@ -899,12 +912,16 @@ class TestDust(ElectrumTestCase):
|
|||||||
# htlc is added back into the balance
|
# htlc is added back into the balance
|
||||||
self.assertEqual(sum(bobs_original_outputs), sum(bobs_third_outputs))
|
self.assertEqual(sum(bobs_original_outputs), sum(bobs_third_outputs))
|
||||||
# balance shifts in bob's direction after settlement
|
# balance shifts in bob's direction after settlement
|
||||||
self.assertEqual(htlc_amt, bobs_third_outputs[1 + (2 if TEST_ANCHOR_CHANNELS else 0)] - bobs_original_outputs[1 + (2 if TEST_ANCHOR_CHANNELS else 0)])
|
self.assertEqual(htlc_amt, bobs_third_outputs[1 + (2 if self.TEST_ANCHOR_CHANNELS else 0)] - bobs_original_outputs[1 + (2 if self.TEST_ANCHOR_CHANNELS else 0)])
|
||||||
self.assertEqual(2, len(alice_channel.get_next_commitment(LOCAL).outputs()) - (2 if TEST_ANCHOR_CHANNELS else 0))
|
self.assertEqual(2, len(alice_channel.get_next_commitment(LOCAL).outputs()) - (2 if self.TEST_ANCHOR_CHANNELS else 0))
|
||||||
self.assertEqual(2, len(bob_channel.get_next_commitment(LOCAL).outputs()) - (2 if TEST_ANCHOR_CHANNELS else 0))
|
self.assertEqual(2, len(bob_channel.get_next_commitment(LOCAL).outputs()) - (2 if self.TEST_ANCHOR_CHANNELS else 0))
|
||||||
self.assertEqual(htlc_amt, alice_channel.total_msat(SENT) // 1000)
|
self.assertEqual(htlc_amt, alice_channel.total_msat(SENT) // 1000)
|
||||||
|
|
||||||
|
|
||||||
|
class TestDustAnchors(TestDust):
|
||||||
|
TEST_ANCHOR_CHANNELS = True
|
||||||
|
|
||||||
|
|
||||||
def force_state_transition(chanA, chanB):
|
def force_state_transition(chanA, chanB):
|
||||||
chanB.receive_new_commitment(*chanA.sign_next_commitment())
|
chanB.receive_new_commitment(*chanA.sign_next_commitment())
|
||||||
rev = chanB.revoke_current_commitment()
|
rev = chanB.revoke_current_commitment()
|
||||||
|
|||||||
@@ -45,15 +45,12 @@ from electrum.invoices import PR_PAID, PR_UNPAID
|
|||||||
from electrum.interface import GracefulDisconnect
|
from electrum.interface import GracefulDisconnect
|
||||||
from electrum.simple_config import SimpleConfig
|
from electrum.simple_config import SimpleConfig
|
||||||
|
|
||||||
from .test_lnchannel import create_test_channels as create_test_channels_anchors
|
|
||||||
|
|
||||||
|
from .test_lnchannel import create_test_channels
|
||||||
|
from .test_bitcoin import needs_test_with_all_chacha20_implementations
|
||||||
from . import ElectrumTestCase
|
from . import ElectrumTestCase
|
||||||
|
|
||||||
TEST_ANCHOR_CHANNELS = True
|
|
||||||
|
|
||||||
|
|
||||||
def create_test_channels(*args, **kwargs):
|
|
||||||
return create_test_channels_anchors(*args, **kwargs, anchor_outputs=TEST_ANCHOR_CHANNELS)
|
|
||||||
|
|
||||||
|
|
||||||
def keypair():
|
def keypair():
|
||||||
priv = ECPrivkey.generate_random_key().get_secret_bytes()
|
priv = ECPrivkey.generate_random_key().get_secret_bytes()
|
||||||
@@ -155,7 +152,7 @@ class MockLNWallet(Logger, EventListener, NetworkRetryManager[LNPeerAddr]):
|
|||||||
MPP_SPLIT_PART_FRACTION = 1 # this disables the forced splitting
|
MPP_SPLIT_PART_FRACTION = 1 # this disables the forced splitting
|
||||||
MPP_SPLIT_PART_MINAMT_MSAT = 5_000_000
|
MPP_SPLIT_PART_MINAMT_MSAT = 5_000_000
|
||||||
|
|
||||||
def __init__(self, *, local_keypair: Keypair, chans: Iterable['Channel'], tx_queue, name):
|
def __init__(self, *, local_keypair: Keypair, chans: Iterable['Channel'], tx_queue, name, has_anchors):
|
||||||
self.name = name
|
self.name = name
|
||||||
Logger.__init__(self)
|
Logger.__init__(self)
|
||||||
NetworkRetryManager.__init__(self, max_retry_delay_normal=1, init_retry_delay_normal=1)
|
NetworkRetryManager.__init__(self, max_retry_delay_normal=1, init_retry_delay_normal=1)
|
||||||
@@ -181,7 +178,7 @@ class MockLNWallet(Logger, EventListener, NetworkRetryManager[LNPeerAddr]):
|
|||||||
self.features |= LnFeatures.OPTION_CHANNEL_TYPE_OPT
|
self.features |= LnFeatures.OPTION_CHANNEL_TYPE_OPT
|
||||||
self.features |= LnFeatures.OPTION_SCID_ALIAS_OPT
|
self.features |= LnFeatures.OPTION_SCID_ALIAS_OPT
|
||||||
self.features |= LnFeatures.OPTION_STATIC_REMOTEKEY_OPT
|
self.features |= LnFeatures.OPTION_STATIC_REMOTEKEY_OPT
|
||||||
self.config.ENABLE_ANCHOR_CHANNELS = TEST_ANCHOR_CHANNELS
|
self.config.ENABLE_ANCHOR_CHANNELS = has_anchors
|
||||||
self.pending_payments = defaultdict(asyncio.Future)
|
self.pending_payments = defaultdict(asyncio.Future)
|
||||||
for chan in chans:
|
for chan in chans:
|
||||||
chan.lnworker = self
|
chan.lnworker = self
|
||||||
@@ -559,8 +556,8 @@ class TestPeerDirect(TestPeer):
|
|||||||
bob_channel.storage['node_id'] = bob_channel.node_id
|
bob_channel.storage['node_id'] = bob_channel.node_id
|
||||||
t1, t2 = transport_pair(k1, k2, alice_channel.name, bob_channel.name)
|
t1, t2 = transport_pair(k1, k2, alice_channel.name, bob_channel.name)
|
||||||
q1, q2 = asyncio.Queue(), asyncio.Queue()
|
q1, q2 = asyncio.Queue(), asyncio.Queue()
|
||||||
w1 = MockLNWallet(local_keypair=k1, chans=[alice_channel], tx_queue=q1, name=bob_channel.name)
|
w1 = MockLNWallet(local_keypair=k1, chans=[alice_channel], tx_queue=q1, name=bob_channel.name, has_anchors=self.TEST_ANCHOR_CHANNELS)
|
||||||
w2 = MockLNWallet(local_keypair=k2, chans=[bob_channel], tx_queue=q2, name=alice_channel.name)
|
w2 = MockLNWallet(local_keypair=k2, chans=[bob_channel], tx_queue=q2, name=alice_channel.name, has_anchors=self.TEST_ANCHOR_CHANNELS)
|
||||||
self._lnworkers_created.extend([w1, w2])
|
self._lnworkers_created.extend([w1, w2])
|
||||||
p1 = PeerInTests(w1, k2.pubkey, t1)
|
p1 = PeerInTests(w1, k2.pubkey, t1)
|
||||||
p2 = PeerInTests(w2, k1.pubkey, t2)
|
p2 = PeerInTests(w2, k1.pubkey, t2)
|
||||||
@@ -1439,7 +1436,6 @@ class TestPeerForwarding(TestPeer):
|
|||||||
transports = {}
|
transports = {}
|
||||||
workers = {} # type: Dict[str, MockLNWallet]
|
workers = {} # type: Dict[str, MockLNWallet]
|
||||||
peers = {}
|
peers = {}
|
||||||
|
|
||||||
# create channels
|
# create channels
|
||||||
for a, definition in graph_definition.items():
|
for a, definition in graph_definition.items():
|
||||||
for b, channel_def in definition.get('channels', {}).items():
|
for b, channel_def in definition.get('channels', {}).items():
|
||||||
@@ -1450,6 +1446,7 @@ class TestPeerForwarding(TestPeer):
|
|||||||
bob_pubkey=keys[b].pubkey,
|
bob_pubkey=keys[b].pubkey,
|
||||||
local_msat=channel_def['local_balance_msat'],
|
local_msat=channel_def['local_balance_msat'],
|
||||||
remote_msat=channel_def['remote_balance_msat'],
|
remote_msat=channel_def['remote_balance_msat'],
|
||||||
|
anchor_outputs=self.TEST_ANCHOR_CHANNELS
|
||||||
)
|
)
|
||||||
channels[(a, b)], channels[(b, a)] = channel_ab, channel_ba
|
channels[(a, b)], channels[(b, a)] = channel_ab, channel_ba
|
||||||
transport_ab, transport_ba = transport_pair(keys[a], keys[b], channel_ab.name, channel_ba.name)
|
transport_ab, transport_ba = transport_pair(keys[a], keys[b], channel_ab.name, channel_ba.name)
|
||||||
@@ -1463,7 +1460,7 @@ class TestPeerForwarding(TestPeer):
|
|||||||
# create workers and peers
|
# create workers and peers
|
||||||
for a, definition in graph_definition.items():
|
for a, definition in graph_definition.items():
|
||||||
channels_of_node = [c for k, c in channels.items() if k[0] == a]
|
channels_of_node = [c for k, c in channels.items() if k[0] == a]
|
||||||
workers[a] = MockLNWallet(local_keypair=keys[a], chans=channels_of_node, tx_queue=txs_queues[a], name=a)
|
workers[a] = MockLNWallet(local_keypair=keys[a], chans=channels_of_node, tx_queue=txs_queues[a], name=a, has_anchors=self.TEST_ANCHOR_CHANNELS)
|
||||||
self._lnworkers_created.extend(list(workers.values()))
|
self._lnworkers_created.extend(list(workers.values()))
|
||||||
|
|
||||||
# create peers
|
# create peers
|
||||||
@@ -1500,6 +1497,9 @@ class TestPeerForwarding(TestPeer):
|
|||||||
print(f" {keys[a].pubkey.hex()}")
|
print(f" {keys[a].pubkey.hex()}")
|
||||||
return graph
|
return graph
|
||||||
|
|
||||||
|
async def test_payment_multihop(self):
|
||||||
|
graph = self.prepare_chans_and_peers_in_graph(self.GRAPH_DEFINITIONS['square_graph'])
|
||||||
|
|
||||||
async def test_payment_multihop(self):
|
async def test_payment_multihop(self):
|
||||||
graph = self.prepare_chans_and_peers_in_graph(self.GRAPH_DEFINITIONS['square_graph'])
|
graph = self.prepare_chans_and_peers_in_graph(self.GRAPH_DEFINITIONS['square_graph'])
|
||||||
peers = graph.peers.values()
|
peers = graph.peers.values()
|
||||||
@@ -1989,3 +1989,13 @@ class TestPeerForwarding(TestPeer):
|
|||||||
with self.assertRaises(PaymentDone):
|
with self.assertRaises(PaymentDone):
|
||||||
graph = self.create_square_graph(direct=False, is_legacy=False)
|
graph = self.create_square_graph(direct=False, is_legacy=False)
|
||||||
await self._run_trampoline_payment(graph)
|
await self._run_trampoline_payment(graph)
|
||||||
|
|
||||||
|
class TestPeerDirectAnchors(TestPeerDirect):
|
||||||
|
TEST_ANCHOR_CHANNELS = True
|
||||||
|
|
||||||
|
class TestPeerForwardingAnchors(TestPeerForwarding):
|
||||||
|
TEST_ANCHOR_CHANNELS = True
|
||||||
|
|
||||||
|
|
||||||
|
def run(coro):
|
||||||
|
return asyncio.run_coroutine_threadsafe(coro, loop=util.get_asyncio_loop()).result()
|
||||||
|
|||||||
@@ -797,11 +797,21 @@ class TestLNUtil(ElectrumTestCase):
|
|||||||
ref_commit_tx_str = '02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8002c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de84311054a56a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0400473044022051b75c73198c6deee1a875871c3961832909acd297c6b908d59e3319e5185a46022055c419379c5051a78d00dbbce11b5b664a0c22815fbcc6fcef6b1937c383693901483045022100f51d2e566a70ba740fc5d8c0f07b9b93d2ed741c3c0860c613173de7d39e7968022041376d520e9c0e1ad52248ddf4b22e12be8763007df977253ef45a4ca3bdb7c001475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220'
|
ref_commit_tx_str = '02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8002c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de84311054a56a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0400473044022051b75c73198c6deee1a875871c3961832909acd297c6b908d59e3319e5185a46022055c419379c5051a78d00dbbce11b5b664a0c22815fbcc6fcef6b1937c383693901483045022100f51d2e566a70ba740fc5d8c0f07b9b93d2ed741c3c0860c613173de7d39e7968022041376d520e9c0e1ad52248ddf4b22e12be8763007df977253ef45a4ca3bdb7c001475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220'
|
||||||
self.assertEqual(str(our_commit_tx), ref_commit_tx_str)
|
self.assertEqual(str(our_commit_tx), ref_commit_tx_str)
|
||||||
|
|
||||||
@unittest.skip("only valid for original anchor ouputs, "
|
|
||||||
"but invalid due to different fee estimation "
|
|
||||||
"with anchors-zero-fee-htlcs")
|
|
||||||
@disable_ecdsa_r_value_grinding
|
@disable_ecdsa_r_value_grinding
|
||||||
def test_commitment_tx_anchors_test_vectors(self):
|
def test_commitment_tx_anchors_test_vectors(self):
|
||||||
|
# this test is only valid for the original anchor output test vectors (not anchors-zero-fee-htlcs),
|
||||||
|
# therefore we patch the effective htlc tx weight to result in a finite weight
|
||||||
|
from electrum import lnutil
|
||||||
|
effective_htlc_tx_weight_original = lnutil.effective_htlc_tx_weight
|
||||||
|
def effective_htlc_tx_weight_patched(success: bool, has_anchors: bool):
|
||||||
|
return lnutil.HTLC_SUCCESS_WEIGHT_ANCHORS if success else lnutil.HTLC_TIMEOUT_WEIGHT_ANCHORS
|
||||||
|
lnutil.effective_htlc_tx_weight = effective_htlc_tx_weight_patched
|
||||||
|
try:
|
||||||
|
self._test_commitment_tx_anchors_test_vectors()
|
||||||
|
finally:
|
||||||
|
lnutil.effective_htlc_tx_weight = effective_htlc_tx_weight_original
|
||||||
|
|
||||||
|
def _test_commitment_tx_anchors_test_vectors(self):
|
||||||
for test_vector in ANCHOR_TEST_VECTORS:
|
for test_vector in ANCHOR_TEST_VECTORS:
|
||||||
with self.subTest(test_vector['Name']):
|
with self.subTest(test_vector['Name']):
|
||||||
to_local_msat = test_vector['LocalBalance']
|
to_local_msat = test_vector['LocalBalance']
|
||||||
|
|||||||
Reference in New Issue
Block a user