mirror of
https://github.com/LBRYFoundation/LBRY-Vault.git
synced 2025-08-23 17:47:31 +00:00
ln: do not use mSAT accuracy for commitment fees
This commit is contained in:
parent
66e7b4d250
commit
9853cc6f31
3 changed files with 24 additions and 14 deletions
|
@ -2,7 +2,7 @@
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
import binascii
|
import binascii
|
||||||
import json
|
import json
|
||||||
from .util import bfh, PrintError
|
from .util import bfh, PrintError, bh2u
|
||||||
from .bitcoin import Hash
|
from .bitcoin import Hash
|
||||||
from .bitcoin import redeem_script_to_address
|
from .bitcoin import redeem_script_to_address
|
||||||
from .crypto import sha256
|
from .crypto import sha256
|
||||||
|
@ -199,14 +199,16 @@ class HTLCStateMachine(PrintError):
|
||||||
|
|
||||||
for_us = False
|
for_us = False
|
||||||
|
|
||||||
|
feerate = self.pending_remote_feerate
|
||||||
|
|
||||||
htlcsigs = []
|
htlcsigs = []
|
||||||
for we_receive, htlcs in zip([True, False], [self.htlcs_in_remote, self.htlcs_in_local]):
|
for we_receive, htlcs in zip([True, False], [self.htlcs_in_remote, self.htlcs_in_local]):
|
||||||
assert len(htlcs) <= 1
|
assert len(htlcs) <= 1
|
||||||
for htlc in htlcs:
|
for htlc in htlcs:
|
||||||
weight = HTLC_SUCCESS_WEIGHT if we_receive else HTLC_TIMEOUT_WEIGHT
|
weight = HTLC_SUCCESS_WEIGHT if we_receive else HTLC_TIMEOUT_WEIGHT
|
||||||
fee = self.remote_state.feerate // 1000 * weight
|
fee = feerate // 1000 * weight
|
||||||
if htlc.amount_msat // 1000 < self.remote_config.dust_limit_sat + fee:
|
if htlc.amount_msat // 1000 < self.remote_config.dust_limit_sat + fee:
|
||||||
print("value too small, skipping. htlc amt: {}, weight: {}, remote feerate {}, remote dust limit {}".format( htlc.amount_msat, weight, self.remote_state.feerate, self.remote_config.dust_limit_sat))
|
print("value too small, skipping. htlc amt: {}, weight: {}, remote feerate {}, remote dust limit {}".format( htlc.amount_msat, weight, feerate, self.remote_config.dust_limit_sat))
|
||||||
continue
|
continue
|
||||||
original_htlc_output_index = 0
|
original_htlc_output_index = 0
|
||||||
args = [self.remote_state.next_per_commitment_point, for_us, we_receive, htlc.amount_msat + htlc.total_fee, htlc.cltv_expiry, htlc.payment_hash, self.pending_remote_commitment, original_htlc_output_index]
|
args = [self.remote_state.next_per_commitment_point, for_us, we_receive, htlc.amount_msat + htlc.total_fee, htlc.cltv_expiry, htlc.payment_hash, self.pending_remote_commitment, original_htlc_output_index]
|
||||||
|
@ -244,7 +246,7 @@ class HTLCStateMachine(PrintError):
|
||||||
preimage_hex = self.pending_local_commitment.serialize_preimage(0)
|
preimage_hex = self.pending_local_commitment.serialize_preimage(0)
|
||||||
pre_hash = Hash(bfh(preimage_hex))
|
pre_hash = Hash(bfh(preimage_hex))
|
||||||
if not ecc.verify_signature(self.remote_config.multisig_key.pubkey, sig, pre_hash):
|
if not ecc.verify_signature(self.remote_config.multisig_key.pubkey, sig, pre_hash):
|
||||||
raise Exception('failed verifying signature of our updated commitment transaction: ' + str(sig))
|
raise Exception('failed verifying signature of our updated commitment transaction: ' + bh2u(sig) + ' preimage is ' + preimage_hex)
|
||||||
|
|
||||||
_, this_point, _ = self.points
|
_, this_point, _ = self.points
|
||||||
|
|
||||||
|
|
|
@ -153,6 +153,7 @@ def make_htlc_tx_output(amount_msat, local_feerate, revocationpubkey, local_dela
|
||||||
p2wsh = bitcoin.redeem_script_to_address('p2wsh', bh2u(script))
|
p2wsh = bitcoin.redeem_script_to_address('p2wsh', bh2u(script))
|
||||||
weight = HTLC_SUCCESS_WEIGHT if success else HTLC_TIMEOUT_WEIGHT
|
weight = HTLC_SUCCESS_WEIGHT if success else HTLC_TIMEOUT_WEIGHT
|
||||||
fee = local_feerate * weight
|
fee = local_feerate * weight
|
||||||
|
fee = fee // 1000 * 1000
|
||||||
final_amount_sat = (amount_msat - fee) // 1000
|
final_amount_sat = (amount_msat - fee) // 1000
|
||||||
assert final_amount_sat > 0, final_amount_sat
|
assert final_amount_sat > 0, final_amount_sat
|
||||||
output = (bitcoin.TYPE_ADDRESS, p2wsh, final_amount_sat)
|
output = (bitcoin.TYPE_ADDRESS, p2wsh, final_amount_sat)
|
||||||
|
@ -242,7 +243,7 @@ def make_htlc_tx_with_open_channel(chan, pcp, for_us, we_receive, amount_msat, c
|
||||||
is_htlc_success = for_us == we_receive
|
is_htlc_success = for_us == we_receive
|
||||||
htlc_tx_output = make_htlc_tx_output(
|
htlc_tx_output = make_htlc_tx_output(
|
||||||
amount_msat = amount_msat,
|
amount_msat = amount_msat,
|
||||||
local_feerate = chan.local_state.feerate if for_us else chan.remote_state.feerate,
|
local_feerate = chan.pending_local_feerate if for_us else chan.pending_remote_feerate,
|
||||||
revocationpubkey=revocation_pubkey,
|
revocationpubkey=revocation_pubkey,
|
||||||
local_delayedpubkey=delayedpubkey,
|
local_delayedpubkey=delayedpubkey,
|
||||||
success = is_htlc_success,
|
success = is_htlc_success,
|
||||||
|
@ -295,13 +296,11 @@ def make_commitment(ctn, local_funding_pubkey, remote_funding_pubkey,
|
||||||
remote_address = make_commitment_output_to_remote_address(remote_payment_pubkey)
|
remote_address = make_commitment_output_to_remote_address(remote_payment_pubkey)
|
||||||
# TODO trim htlc outputs here while also considering 2nd stage htlc transactions
|
# TODO trim htlc outputs here while also considering 2nd stage htlc transactions
|
||||||
fee = local_feerate * overall_weight(len(htlcs))
|
fee = local_feerate * overall_weight(len(htlcs))
|
||||||
assert type(fee) is int
|
fee = fee // 1000 * 1000
|
||||||
we_pay_fee = for_us == we_are_initiator
|
we_pay_fee = for_us == we_are_initiator
|
||||||
to_local_amt = local_amount - (fee if we_pay_fee else 0)
|
to_local_amt = local_amount - (fee if we_pay_fee else 0)
|
||||||
assert type(to_local_amt) is int
|
|
||||||
to_local = (bitcoin.TYPE_ADDRESS, local_address, to_local_amt // 1000)
|
to_local = (bitcoin.TYPE_ADDRESS, local_address, to_local_amt // 1000)
|
||||||
to_remote_amt = remote_amount - (fee if not we_pay_fee else 0)
|
to_remote_amt = remote_amount - (fee if not we_pay_fee else 0)
|
||||||
assert type(to_remote_amt) is int
|
|
||||||
to_remote = (bitcoin.TYPE_ADDRESS, remote_address, to_remote_amt // 1000)
|
to_remote = (bitcoin.TYPE_ADDRESS, remote_address, to_remote_amt // 1000)
|
||||||
c_outputs = [to_local, to_remote]
|
c_outputs = [to_local, to_remote]
|
||||||
for script, msat_amount in htlcs:
|
for script, msat_amount in htlcs:
|
||||||
|
|
|
@ -74,12 +74,12 @@ def bip32(sequence):
|
||||||
assert type(k) is bytes
|
assert type(k) is bytes
|
||||||
return k
|
return k
|
||||||
|
|
||||||
def create_test_channels():
|
def create_test_channels(feerate=6000, local=None, remote=None):
|
||||||
funding_txid = binascii.hexlify(os.urandom(32)).decode("ascii")
|
funding_txid = binascii.hexlify(os.urandom(32)).decode("ascii")
|
||||||
funding_index = 0
|
funding_index = 0
|
||||||
funding_sat = bitcoin.COIN * 10
|
funding_sat = ((local + remote) // 1000) if local is not None and remote is not None else (bitcoin.COIN * 10)
|
||||||
local_amount = (funding_sat * 1000) // 2
|
local_amount = local if local is not None else (funding_sat * 1000 // 2)
|
||||||
remote_amount = (funding_sat * 1000) // 2
|
remote_amount = remote if remote is not None else (funding_sat * 1000 // 2)
|
||||||
alice_raw = [ bip32("m/" + str(i)) for i in range(5) ]
|
alice_raw = [ bip32("m/" + str(i)) for i in range(5) ]
|
||||||
bob_raw = [ bip32("m/" + str(i)) for i in range(5,11) ]
|
bob_raw = [ bip32("m/" + str(i)) for i in range(5,11) ]
|
||||||
alice_privkeys = [lnbase.Keypair(lnbase.privkey_to_pubkey(x), x) for x in alice_raw]
|
alice_privkeys = [lnbase.Keypair(lnbase.privkey_to_pubkey(x), x) for x in alice_raw]
|
||||||
|
@ -97,12 +97,21 @@ def create_test_channels():
|
||||||
|
|
||||||
return \
|
return \
|
||||||
lnhtlc.HTLCStateMachine(
|
lnhtlc.HTLCStateMachine(
|
||||||
create_channel_state(funding_txid, funding_index, funding_sat, 6000, True, local_amount, remote_amount, alice_privkeys, bob_pubkeys, alice_seed, bob_cur, bob_next, b"\x02"*33, l_dust=200, r_dust=1300, l_csv=5, r_csv=4), "alice"), \
|
create_channel_state(funding_txid, funding_index, funding_sat, feerate, True, local_amount, remote_amount, alice_privkeys, bob_pubkeys, alice_seed, bob_cur, bob_next, b"\x02"*33, l_dust=200, r_dust=1300, l_csv=5, r_csv=4), "alice"), \
|
||||||
lnhtlc.HTLCStateMachine(
|
lnhtlc.HTLCStateMachine(
|
||||||
create_channel_state(funding_txid, funding_index, funding_sat, 6000, False, remote_amount, local_amount, bob_privkeys, alice_pubkeys, bob_seed, alice_cur, alice_next, b"\x01"*33, l_dust=1300, r_dust=200, l_csv=4, r_csv=5), "bob")
|
create_channel_state(funding_txid, funding_index, funding_sat, feerate, False, remote_amount, local_amount, bob_privkeys, alice_pubkeys, bob_seed, alice_cur, alice_next, b"\x01"*33, l_dust=1300, r_dust=200, l_csv=4, r_csv=5), "bob")
|
||||||
|
|
||||||
one_bitcoin_in_msat = bitcoin.COIN * 1000
|
one_bitcoin_in_msat = bitcoin.COIN * 1000
|
||||||
|
|
||||||
|
class TestFee(unittest.TestCase):
|
||||||
|
"""
|
||||||
|
test
|
||||||
|
https://github.com/lightningnetwork/lightning-rfc/blob/e0c436bd7a3ed6a028e1cb472908224658a14eca/03-transactions.md#requirements-2
|
||||||
|
"""
|
||||||
|
def test_SimpleAddSettleWorkflow(self):
|
||||||
|
alice_channel, bob_channel = create_test_channels(253, 10000000000, 5000000000)
|
||||||
|
self.assertIn(9999817, [x[2] for x in alice_channel.local_commitment.outputs()])
|
||||||
|
|
||||||
class TestLNBaseHTLCStateMachine(unittest.TestCase):
|
class TestLNBaseHTLCStateMachine(unittest.TestCase):
|
||||||
def assertOutputExistsByValue(self, tx, amt_sat):
|
def assertOutputExistsByValue(self, tx, amt_sat):
|
||||||
for typ, scr, val in tx.outputs():
|
for typ, scr, val in tx.outputs():
|
||||||
|
|
Loading…
Add table
Reference in a new issue