lnutil: make UpdateAddHtlc dataclass
it is straightforward to move UpdateAddHtlc away from attr to a dataclass without requiring any db update.
This commit is contained in:
@@ -27,6 +27,7 @@ import os
|
||||
import binascii
|
||||
from pprint import pformat
|
||||
import logging
|
||||
import dataclasses
|
||||
|
||||
from electrum import bitcoin
|
||||
from electrum import lnpeer
|
||||
@@ -257,31 +258,34 @@ class TestChannel(ElectrumTestCase):
|
||||
|
||||
self.paymentPreimage = b"\x01" * 32
|
||||
paymentHash = bitcoin.sha256(self.paymentPreimage)
|
||||
self.htlc_dict = {
|
||||
'payment_hash': paymentHash,
|
||||
'amount_msat': one_bitcoin_in_msat,
|
||||
'cltv_abs': 5,
|
||||
'timestamp': 0,
|
||||
}
|
||||
self.htlc = UpdateAddHtlc(
|
||||
payment_hash=paymentHash,
|
||||
amount_msat=one_bitcoin_in_msat,
|
||||
cltv_abs=5,
|
||||
timestamp=0,
|
||||
)
|
||||
|
||||
# First Alice adds the outgoing HTLC to her local channel's state
|
||||
# update log. Then Alice sends this wire message over to Bob who adds
|
||||
# this htlc to his remote state update log.
|
||||
self.aliceHtlcIndex = self.alice_channel.add_htlc(self.htlc_dict).htlc_id
|
||||
self.aliceHtlcIndex = self.alice_channel.add_htlc(self.htlc).htlc_id
|
||||
self.assertNotEqual(list(self.alice_channel.hm.htlcs_by_direction(REMOTE, RECEIVED, 1).values()), [])
|
||||
|
||||
before = self.bob_channel.balance_minus_outgoing_htlcs(REMOTE)
|
||||
beforeLocal = self.bob_channel.balance_minus_outgoing_htlcs(LOCAL)
|
||||
|
||||
self.bobHtlcIndex = self.bob_channel.receive_htlc(self.htlc_dict).htlc_id
|
||||
self.bobHtlcIndex = self.bob_channel.receive_htlc(self.htlc).htlc_id
|
||||
|
||||
self.htlc = self.bob_channel.hm.log[REMOTE]['adds'][0]
|
||||
|
||||
def test_concurrent_reversed_payment(self):
|
||||
self.htlc_dict['payment_hash'] = bitcoin.sha256(32 * b'\x02')
|
||||
self.htlc_dict['amount_msat'] += 1000
|
||||
self.bob_channel.add_htlc(self.htlc_dict)
|
||||
self.alice_channel.receive_htlc(self.htlc_dict)
|
||||
self.htlc = dataclasses.replace(
|
||||
self.htlc,
|
||||
payment_hash=bitcoin.sha256(32 * b'\x02'),
|
||||
amount_msat=self.htlc.amount_msat + 1000,
|
||||
)
|
||||
self.bob_channel.add_htlc(self.htlc)
|
||||
self.alice_channel.receive_htlc(self.htlc)
|
||||
|
||||
self.assertNumberNonAnchorOutputs(2, self.alice_channel.get_latest_commitment(LOCAL))
|
||||
self.assertNumberNonAnchorOutputs(3, self.alice_channel.get_next_commitment(LOCAL))
|
||||
@@ -561,9 +565,12 @@ class TestChannel(ElectrumTestCase):
|
||||
tx6 = str(alice_channel.force_close_tx())
|
||||
self.assertNotEqual(tx5, tx6)
|
||||
|
||||
self.htlc_dict['amount_msat'] *= 5
|
||||
bob_index = bob_channel.add_htlc(self.htlc_dict).htlc_id
|
||||
alice_index = alice_channel.receive_htlc(self.htlc_dict).htlc_id
|
||||
self.htlc = dataclasses.replace(
|
||||
self.htlc,
|
||||
amount_msat=self.htlc.amount_msat * 5,
|
||||
)
|
||||
bob_index = bob_channel.add_htlc(self.htlc).htlc_id
|
||||
alice_index = alice_channel.receive_htlc(self.htlc).htlc_id
|
||||
|
||||
force_state_transition(bob_channel, alice_channel)
|
||||
|
||||
@@ -662,18 +669,26 @@ class TestChannel(ElectrumTestCase):
|
||||
self.alice_to_bob_fee_update(0)
|
||||
force_state_transition(self.alice_channel, self.bob_channel)
|
||||
|
||||
self.htlc_dict['payment_hash'] = bitcoin.sha256(32 * b'\x02')
|
||||
self.alice_channel.add_htlc(self.htlc_dict)
|
||||
self.htlc_dict['payment_hash'] = bitcoin.sha256(32 * b'\x03')
|
||||
self.alice_channel.add_htlc(self.htlc_dict)
|
||||
self.htlc = dataclasses.replace(
|
||||
self.htlc,
|
||||
payment_hash=bitcoin.sha256(32 * b'\x02'),
|
||||
)
|
||||
self.alice_channel.add_htlc(self.htlc)
|
||||
self.htlc = dataclasses.replace(
|
||||
self.htlc,
|
||||
payment_hash=bitcoin.sha256(32 * b'\x03'),
|
||||
)
|
||||
self.alice_channel.add_htlc(self.htlc)
|
||||
# now there are three htlcs (one was in setUp)
|
||||
|
||||
# Alice now has an available balance of 2 BTC. We'll add a new HTLC of
|
||||
# value 2 BTC, which should make Alice's balance negative (since she
|
||||
# has to pay a commitment fee).
|
||||
new = dict(self.htlc_dict)
|
||||
new['amount_msat'] *= 2.5
|
||||
new['payment_hash'] = bitcoin.sha256(32 * b'\x04')
|
||||
new = dataclasses.replace(
|
||||
self.htlc,
|
||||
amount_msat=int(self.htlc.amount_msat * 2.5),
|
||||
payment_hash=bitcoin.sha256(32 * b'\x04'),
|
||||
)
|
||||
with self.assertRaises(lnutil.PaymentFailure) as cm:
|
||||
self.alice_channel.add_htlc(new)
|
||||
self.assertIn('Not enough local balance', cm.exception.args[0])
|
||||
@@ -822,14 +837,14 @@ class TestChanReserve(ElectrumTestCase):
|
||||
# Bob: 5.0
|
||||
paymentPreimage = b"\x01" * 32
|
||||
paymentHash = bitcoin.sha256(paymentPreimage)
|
||||
htlc_dict = {
|
||||
'payment_hash': paymentHash,
|
||||
'amount_msat': int(.5 * one_bitcoin_in_msat),
|
||||
'cltv_abs': 5,
|
||||
'timestamp': 0,
|
||||
}
|
||||
self.alice_channel.add_htlc(htlc_dict)
|
||||
self.bob_channel.receive_htlc(htlc_dict)
|
||||
htlc = UpdateAddHtlc(
|
||||
payment_hash=paymentHash,
|
||||
amount_msat=int(.5 * one_bitcoin_in_msat),
|
||||
cltv_abs=5,
|
||||
timestamp=0,
|
||||
)
|
||||
self.alice_channel.add_htlc(htlc)
|
||||
self.bob_channel.receive_htlc(htlc)
|
||||
# Force a state transition, making sure this HTLC is considered valid
|
||||
# even though the channel reserves are not met.
|
||||
force_state_transition(self.alice_channel, self.bob_channel)
|
||||
@@ -847,10 +862,10 @@ class TestChanReserve(ElectrumTestCase):
|
||||
# Alice: 4.5
|
||||
# Bob: 5.0
|
||||
with self.assertRaises(lnutil.PaymentFailure):
|
||||
htlc_dict['payment_hash'] = bitcoin.sha256(32 * b'\x02')
|
||||
self.bob_channel.add_htlc(htlc_dict)
|
||||
htlc = dataclasses.replace(htlc, payment_hash=bitcoin.sha256(32 * b'\x02'))
|
||||
self.bob_channel.add_htlc(htlc)
|
||||
with self.assertRaises(lnutil.RemoteMisbehaving):
|
||||
self.alice_channel.receive_htlc(htlc_dict)
|
||||
self.alice_channel.receive_htlc(htlc)
|
||||
|
||||
def part2(self):
|
||||
paymentPreimage = b"\x01" * 32
|
||||
@@ -861,22 +876,22 @@ class TestChanReserve(ElectrumTestCase):
|
||||
# Resulting balances:
|
||||
# Alice: 1.5
|
||||
# Bob: 9.5
|
||||
htlc_dict = {
|
||||
'payment_hash': paymentHash,
|
||||
'amount_msat': int(3.5 * one_bitcoin_in_msat),
|
||||
'cltv_abs': 5,
|
||||
}
|
||||
self.alice_channel.add_htlc(htlc_dict)
|
||||
self.bob_channel.receive_htlc(htlc_dict)
|
||||
htlc = UpdateAddHtlc(
|
||||
payment_hash=paymentHash,
|
||||
amount_msat=int(3.5 * one_bitcoin_in_msat),
|
||||
cltv_abs=5,
|
||||
)
|
||||
self.alice_channel.add_htlc(htlc)
|
||||
self.bob_channel.receive_htlc(htlc)
|
||||
# Add a second HTLC of 1 BTC. This should fail because it will take
|
||||
# Alice's balance all the way down to her channel reserve, but since
|
||||
# she is the initiator the additional transaction fee makes her
|
||||
# balance dip below.
|
||||
htlc_dict['amount_msat'] = one_bitcoin_in_msat
|
||||
htlc = dataclasses.replace(htlc, amount_msat=one_bitcoin_in_msat)
|
||||
with self.assertRaises(lnutil.PaymentFailure):
|
||||
self.alice_channel.add_htlc(htlc_dict)
|
||||
self.alice_channel.add_htlc(htlc)
|
||||
with self.assertRaises(lnutil.RemoteMisbehaving):
|
||||
self.bob_channel.receive_htlc(htlc_dict)
|
||||
self.bob_channel.receive_htlc(htlc)
|
||||
|
||||
def part3(self):
|
||||
# Add a HTLC of 2 BTC to Alice, and the settle it.
|
||||
@@ -885,14 +900,14 @@ class TestChanReserve(ElectrumTestCase):
|
||||
# Bob: 7.0
|
||||
paymentPreimage = b"\x01" * 32
|
||||
paymentHash = bitcoin.sha256(paymentPreimage)
|
||||
htlc_dict = {
|
||||
'payment_hash': paymentHash,
|
||||
'amount_msat': int(2 * one_bitcoin_in_msat),
|
||||
'cltv_abs': 5,
|
||||
'timestamp': 0,
|
||||
}
|
||||
alice_idx = self.alice_channel.add_htlc(htlc_dict).htlc_id
|
||||
bob_idx = self.bob_channel.receive_htlc(htlc_dict).htlc_id
|
||||
htlc = UpdateAddHtlc(
|
||||
payment_hash=paymentHash,
|
||||
amount_msat=int(2 * one_bitcoin_in_msat),
|
||||
cltv_abs=5,
|
||||
timestamp=0,
|
||||
)
|
||||
alice_idx = self.alice_channel.add_htlc(htlc).htlc_id
|
||||
bob_idx = self.bob_channel.receive_htlc(htlc).htlc_id
|
||||
force_state_transition(self.alice_channel, self.bob_channel)
|
||||
self.check_bals(one_bitcoin_in_msat * 3
|
||||
- self.alice_channel.get_next_fee(LOCAL),
|
||||
@@ -906,9 +921,9 @@ class TestChanReserve(ElectrumTestCase):
|
||||
# And now let Bob add an HTLC of 1 BTC. This will take Bob's balance
|
||||
# all the way down to his channel reserve, but since he is not paying
|
||||
# the fee this is okay.
|
||||
htlc_dict['amount_msat'] = one_bitcoin_in_msat
|
||||
self.bob_channel.add_htlc(htlc_dict)
|
||||
self.alice_channel.receive_htlc(htlc_dict)
|
||||
htlc = dataclasses.replace(htlc, amount_msat=one_bitcoin_in_msat)
|
||||
self.bob_channel.add_htlc(htlc)
|
||||
self.alice_channel.receive_htlc(htlc)
|
||||
force_state_transition(self.alice_channel, self.bob_channel)
|
||||
self.check_bals(one_bitcoin_in_msat * 3 \
|
||||
- self.alice_channel.get_next_fee(LOCAL),
|
||||
@@ -943,12 +958,12 @@ class TestDust(ElectrumTestCase):
|
||||
# to pay for his htlc success transaction
|
||||
below_dust_for_bob = dust_limit_bob - 1
|
||||
htlc_amt = below_dust_for_bob + success_weight * (fee_per_kw // 1000)
|
||||
htlc = {
|
||||
'payment_hash': paymentHash,
|
||||
'amount_msat': 1000 * htlc_amt,
|
||||
'cltv_abs': 5, # consistent with channel policy
|
||||
'timestamp': 0,
|
||||
}
|
||||
htlc = UpdateAddHtlc(
|
||||
payment_hash=paymentHash,
|
||||
amount_msat=1000 * htlc_amt,
|
||||
cltv_abs=5, # consistent with channel policy
|
||||
timestamp=0,
|
||||
)
|
||||
|
||||
# add the htlc
|
||||
alice_htlc_id = alice_channel.add_htlc(htlc).htlc_id
|
||||
|
||||
Reference in New Issue
Block a user