lnutil+lnchannel: add anchors, adapt to_remote
* to_remote has now an additional csv lock of 1 * anchor outputs are added if to_local/remote outputs are present * funder balance is reduced to accomodate anchors
This commit is contained in:
@@ -55,7 +55,7 @@ from .lnutil import (Outpoint, LocalConfig, RemoteConfig, Keypair, OnlyPubkeyKey
|
|||||||
ScriptHtlc, PaymentFailure, calc_fees_for_commitment_tx, RemoteMisbehaving, make_htlc_output_witness_script,
|
ScriptHtlc, PaymentFailure, calc_fees_for_commitment_tx, RemoteMisbehaving, make_htlc_output_witness_script,
|
||||||
ShortChannelID, map_htlcs_to_ctx_output_idxs,
|
ShortChannelID, map_htlcs_to_ctx_output_idxs,
|
||||||
fee_for_htlc_output, offered_htlc_trim_threshold_sat,
|
fee_for_htlc_output, offered_htlc_trim_threshold_sat,
|
||||||
received_htlc_trim_threshold_sat, make_commitment_output_to_remote_address,
|
received_htlc_trim_threshold_sat, make_commitment_output_to_remote_address, FIXED_ANCHOR_SAT,
|
||||||
ChannelType, LNProtocolWarning)
|
ChannelType, LNProtocolWarning)
|
||||||
from .lnsweep import create_sweeptxs_for_our_ctx, create_sweeptxs_for_their_ctx
|
from .lnsweep import create_sweeptxs_for_our_ctx, create_sweeptxs_for_their_ctx
|
||||||
from .lnsweep import create_sweeptx_for_their_revoked_htlc, SweepInfo
|
from .lnsweep import create_sweeptx_for_their_revoked_htlc, SweepInfo
|
||||||
@@ -888,7 +888,7 @@ class Channel(AbstractChannel):
|
|||||||
# TODO: in case of unilateral close with pending HTLCs, this address will be reused
|
# TODO: in case of unilateral close with pending HTLCs, this address will be reused
|
||||||
assert self.is_static_remotekey_enabled()
|
assert self.is_static_remotekey_enabled()
|
||||||
our_payment_pubkey = self.config[LOCAL].payment_basepoint.pubkey
|
our_payment_pubkey = self.config[LOCAL].payment_basepoint.pubkey
|
||||||
addr = make_commitment_output_to_remote_address(our_payment_pubkey)
|
addr = make_commitment_output_to_remote_address(our_payment_pubkey, has_anchors=self.has_anchors())
|
||||||
if self.lnworker:
|
if self.lnworker:
|
||||||
assert self.lnworker.wallet.is_mine(addr)
|
assert self.lnworker.wallet.is_mine(addr)
|
||||||
return addr
|
return addr
|
||||||
@@ -900,7 +900,7 @@ class Channel(AbstractChannel):
|
|||||||
def get_wallet_addresses_channel_might_want_reserved(self) -> Sequence[str]:
|
def get_wallet_addresses_channel_might_want_reserved(self) -> Sequence[str]:
|
||||||
assert self.is_static_remotekey_enabled()
|
assert self.is_static_remotekey_enabled()
|
||||||
our_payment_pubkey = self.config[LOCAL].payment_basepoint.pubkey
|
our_payment_pubkey = self.config[LOCAL].payment_basepoint.pubkey
|
||||||
to_remote_address = make_commitment_output_to_remote_address(our_payment_pubkey)
|
to_remote_address = make_commitment_output_to_remote_address(our_payment_pubkey, has_anchors=self.has_anchors())
|
||||||
return [to_remote_address]
|
return [to_remote_address]
|
||||||
|
|
||||||
def get_feerate(self, subject: HTLCOwner, *, ctn: int) -> int:
|
def get_feerate(self, subject: HTLCOwner, *, ctn: int) -> int:
|
||||||
@@ -1341,7 +1341,7 @@ class Channel(AbstractChannel):
|
|||||||
return len(self.hm.htlcs(LOCAL)) + len(self.hm.htlcs(REMOTE)) > 0
|
return len(self.hm.htlcs(LOCAL)) + len(self.hm.htlcs(REMOTE)) > 0
|
||||||
|
|
||||||
def available_to_spend(self, subject: HTLCOwner, *, strict: bool = True) -> int:
|
def available_to_spend(self, subject: HTLCOwner, *, strict: bool = True) -> int:
|
||||||
"""The usable balance of 'subject' in msat, after taking reserve and fees into
|
"""The usable balance of 'subject' in msat, after taking reserve and fees (and anchors) into
|
||||||
consideration. Note that fees (and hence the result) fluctuate even without user interaction.
|
consideration. Note that fees (and hence the result) fluctuate even without user interaction.
|
||||||
"""
|
"""
|
||||||
assert type(subject) is HTLCOwner
|
assert type(subject) is HTLCOwner
|
||||||
@@ -1367,25 +1367,42 @@ class Channel(AbstractChannel):
|
|||||||
htlc_fee_msat = fee_for_htlc_output(feerate=feerate)
|
htlc_fee_msat = fee_for_htlc_output(feerate=feerate)
|
||||||
htlc_trim_func = received_htlc_trim_threshold_sat if ctx_owner == receiver else offered_htlc_trim_threshold_sat
|
htlc_trim_func = received_htlc_trim_threshold_sat if ctx_owner == receiver else offered_htlc_trim_threshold_sat
|
||||||
htlc_trim_threshold_msat = htlc_trim_func(dust_limit_sat=self.config[ctx_owner].dust_limit_sat, feerate=feerate, has_anchors=self.has_anchors()) * 1000
|
htlc_trim_threshold_msat = htlc_trim_func(dust_limit_sat=self.config[ctx_owner].dust_limit_sat, feerate=feerate, has_anchors=self.has_anchors()) * 1000
|
||||||
if sender == initiator == LOCAL: # see https://github.com/lightningnetwork/lightning-rfc/pull/740
|
|
||||||
|
# the sender cannot spend below its reserve
|
||||||
|
max_send_msat = sender_balance_msat - sender_reserve_msat
|
||||||
|
|
||||||
|
# reserve a fee spike buffer
|
||||||
|
# see https://github.com/lightningnetwork/lightning-rfc/pull/740
|
||||||
|
if sender == initiator == LOCAL:
|
||||||
fee_spike_buffer = calc_fees_for_commitment_tx(
|
fee_spike_buffer = calc_fees_for_commitment_tx(
|
||||||
num_htlcs=num_htlcs_in_ctx + int(not is_htlc_dust) + 1,
|
num_htlcs=num_htlcs_in_ctx + int(not is_htlc_dust) + 1,
|
||||||
feerate=2 * feerate,
|
feerate=2 * feerate,
|
||||||
is_local_initiator=self.constraints.is_initiator,
|
is_local_initiator=self.constraints.is_initiator,
|
||||||
round_to_sat=False,
|
round_to_sat=False,
|
||||||
has_anchors=self.has_anchors()
|
has_anchors=self.has_anchors())[sender]
|
||||||
)[sender]
|
max_send_msat -= fee_spike_buffer
|
||||||
max_send_msat = sender_balance_msat - sender_reserve_msat - fee_spike_buffer
|
# we can't enforce the fee spike buffer on the remote party
|
||||||
else:
|
elif sender == initiator == REMOTE:
|
||||||
max_send_msat = sender_balance_msat - sender_reserve_msat - ctx_fees_msat[sender]
|
max_send_msat -= ctx_fees_msat[sender]
|
||||||
|
|
||||||
|
# initiator pays for anchor outputs
|
||||||
|
if sender == initiator and self.has_anchors():
|
||||||
|
max_send_msat -= 2 * FIXED_ANCHOR_SAT * 1000
|
||||||
|
|
||||||
|
# handle the transaction fees for the HTLC transaction
|
||||||
if is_htlc_dust:
|
if is_htlc_dust:
|
||||||
|
# nobody pays additional HTLC transaction fees
|
||||||
return min(max_send_msat, htlc_trim_threshold_msat - 1)
|
return min(max_send_msat, htlc_trim_threshold_msat - 1)
|
||||||
else:
|
else:
|
||||||
|
# somebody has to pay for the additonal HTLC transaction fees
|
||||||
if sender == initiator:
|
if sender == initiator:
|
||||||
return max_send_msat - htlc_fee_msat
|
return max_send_msat - htlc_fee_msat
|
||||||
else:
|
else:
|
||||||
# the receiver is the initiator, so they need to be able to pay tx fees
|
# check if the receiver can afford to pay for the HTLC transaction fees
|
||||||
if receiver_balance_msat - receiver_reserve_msat - ctx_fees_msat[receiver] - htlc_fee_msat < 0:
|
new_receiver_balance = receiver_balance_msat - receiver_reserve_msat - ctx_fees_msat[receiver] - htlc_fee_msat
|
||||||
|
if self.has_anchors():
|
||||||
|
new_receiver_balance -= 2 * FIXED_ANCHOR_SAT * 1000
|
||||||
|
if new_receiver_balance < 0:
|
||||||
return 0
|
return 0
|
||||||
return max_send_msat
|
return max_send_msat
|
||||||
|
|
||||||
@@ -1629,22 +1646,27 @@ class Channel(AbstractChannel):
|
|||||||
dust_limit_sat=this_config.dust_limit_sat,
|
dust_limit_sat=this_config.dust_limit_sat,
|
||||||
fees_per_participant=onchain_fees,
|
fees_per_participant=onchain_fees,
|
||||||
htlcs=htlcs,
|
htlcs=htlcs,
|
||||||
|
has_anchors=self.has_anchors()
|
||||||
)
|
)
|
||||||
|
|
||||||
def make_closing_tx(self, local_script: bytes, remote_script: bytes,
|
def make_closing_tx(self, local_script: bytes, remote_script: bytes,
|
||||||
fee_sat: int, *, drop_remote = False) -> Tuple[bytes, PartialTransaction]:
|
fee_sat: int, *, drop_remote = False) -> Tuple[bytes, PartialTransaction]:
|
||||||
""" cooperative close """
|
""" cooperative close """
|
||||||
_, outputs = make_commitment_outputs(
|
_, outputs = make_commitment_outputs(
|
||||||
fees_per_participant={
|
fees_per_participant={
|
||||||
LOCAL: fee_sat * 1000 if self.constraints.is_initiator else 0,
|
LOCAL: fee_sat * 1000 if self.constraints.is_initiator else 0,
|
||||||
REMOTE: fee_sat * 1000 if not self.constraints.is_initiator else 0,
|
REMOTE: fee_sat * 1000 if not self.constraints.is_initiator else 0,
|
||||||
},
|
},
|
||||||
local_amount_msat=self.balance(LOCAL),
|
local_amount_msat=self.balance(LOCAL),
|
||||||
remote_amount_msat=self.balance(REMOTE) if not drop_remote else 0,
|
remote_amount_msat=self.balance(REMOTE) if not drop_remote else 0,
|
||||||
local_script=local_script,
|
local_script=local_script,
|
||||||
remote_script=remote_script,
|
remote_script=remote_script,
|
||||||
htlcs=[],
|
htlcs=[],
|
||||||
dust_limit_sat=self.config[LOCAL].dust_limit_sat)
|
dust_limit_sat=self.config[LOCAL].dust_limit_sat,
|
||||||
|
has_anchors=self.has_anchors(),
|
||||||
|
local_anchor_script=None,
|
||||||
|
remote_anchor_script=None,
|
||||||
|
)
|
||||||
|
|
||||||
closing_tx = make_closing_tx(self.config[LOCAL].multisig_key.pubkey,
|
closing_tx = make_closing_tx(self.config[LOCAL].multisig_key.pubkey,
|
||||||
self.config[REMOTE].multisig_key.pubkey,
|
self.config[REMOTE].multisig_key.pubkey,
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ HTLC_SUCCESS_WEIGHT_ANCHORS = 706
|
|||||||
COMMITMENT_TX_WEIGHT = 724
|
COMMITMENT_TX_WEIGHT = 724
|
||||||
COMMITMENT_TX_WEIGHT_ANCHORS = 1124
|
COMMITMENT_TX_WEIGHT_ANCHORS = 1124
|
||||||
HTLC_OUTPUT_WEIGHT = 172
|
HTLC_OUTPUT_WEIGHT = 172
|
||||||
|
FIXED_ANCHOR_SAT = 330
|
||||||
|
|
||||||
LN_MAX_FUNDING_SAT_LEGACY = pow(2, 24) - 1
|
LN_MAX_FUNDING_SAT_LEGACY = pow(2, 24) - 1
|
||||||
DUST_LIMIT_MAX = 1000
|
DUST_LIMIT_MAX = 1000
|
||||||
@@ -992,26 +993,64 @@ RECEIVED = Direction.RECEIVED
|
|||||||
LOCAL = HTLCOwner.LOCAL
|
LOCAL = HTLCOwner.LOCAL
|
||||||
REMOTE = HTLCOwner.REMOTE
|
REMOTE = HTLCOwner.REMOTE
|
||||||
|
|
||||||
def make_commitment_outputs(*, fees_per_participant: Mapping[HTLCOwner, int], local_amount_msat: int, remote_amount_msat: int,
|
|
||||||
local_script: bytes, remote_script: bytes, htlcs: List[ScriptHtlc], dust_limit_sat: int) -> Tuple[List[PartialTxOutput], List[PartialTxOutput]]:
|
|
||||||
# BOLT-03: "Base commitment transaction fees are extracted from the funder's amount;
|
|
||||||
# if that amount is insufficient, the entire amount of the funder's output is used."
|
|
||||||
# -> if funder cannot afford feerate, their output might go negative, so take max(0, x) here:
|
|
||||||
to_local_amt = max(0, local_amount_msat - fees_per_participant[LOCAL])
|
|
||||||
to_local = PartialTxOutput(scriptpubkey=local_script, value=to_local_amt // 1000)
|
|
||||||
to_remote_amt = max(0, remote_amount_msat - fees_per_participant[REMOTE])
|
|
||||||
to_remote = PartialTxOutput(scriptpubkey=remote_script, value=to_remote_amt // 1000)
|
|
||||||
|
|
||||||
non_htlc_outputs = [to_local, to_remote]
|
def make_commitment_outputs(
|
||||||
|
*,
|
||||||
|
fees_per_participant: Mapping[HTLCOwner, int],
|
||||||
|
local_amount_msat: int,
|
||||||
|
remote_amount_msat: int,
|
||||||
|
local_script: bytes,
|
||||||
|
remote_script: bytes,
|
||||||
|
htlcs: List[ScriptHtlc],
|
||||||
|
dust_limit_sat: int,
|
||||||
|
has_anchors: bool,
|
||||||
|
local_anchor_script: Optional[str],
|
||||||
|
remote_anchor_script: Optional[str]
|
||||||
|
) -> Tuple[List[PartialTxOutput], List[PartialTxOutput]]:
|
||||||
|
|
||||||
|
# determine HTLC outputs and trim below dust to know if anchors need to be included
|
||||||
htlc_outputs = []
|
htlc_outputs = []
|
||||||
for script, htlc in htlcs:
|
for script, htlc in htlcs:
|
||||||
addr = bitcoin.redeem_script_to_address('p2wsh', script)
|
addr = bitcoin.redeem_script_to_address('p2wsh', script)
|
||||||
htlc_outputs.append(PartialTxOutput(scriptpubkey=address_to_script(addr),
|
if htlc.amount_msat // 1000 > dust_limit_sat:
|
||||||
value=htlc.amount_msat // 1000))
|
htlc_outputs.append(
|
||||||
|
PartialTxOutput(
|
||||||
|
scriptpubkey=address_to_script(addr),
|
||||||
|
value=htlc.amount_msat // 1000
|
||||||
|
))
|
||||||
|
|
||||||
|
# BOLT-03: "Base commitment transaction fees are extracted from the funder's amount;
|
||||||
|
# if that amount is insufficient, the entire amount of the funder's output is used."
|
||||||
|
non_htlc_outputs = []
|
||||||
|
to_local_amt_msat = local_amount_msat - fees_per_participant[LOCAL]
|
||||||
|
to_remote_amt_msat = remote_amount_msat - fees_per_participant[REMOTE]
|
||||||
|
|
||||||
|
anchor_outputs = []
|
||||||
|
# if no anchor scripts are set, we ignore anchor outputs, useful when this
|
||||||
|
# function is used to determine outputs for a collaborative close
|
||||||
|
if has_anchors and local_anchor_script and remote_anchor_script:
|
||||||
|
local_pays_anchors = bool(fees_per_participant[LOCAL])
|
||||||
|
# we always allocate for two anchor outputs even if they are not added
|
||||||
|
if local_pays_anchors:
|
||||||
|
to_local_amt_msat -= 2 * FIXED_ANCHOR_SAT * 1000
|
||||||
|
else:
|
||||||
|
to_remote_amt_msat -= 2 * FIXED_ANCHOR_SAT * 1000
|
||||||
|
|
||||||
|
# include anchors for outputs that materialize, include both if there are HTLCs present
|
||||||
|
if to_local_amt_msat // 1000 >= dust_limit_sat or htlc_outputs:
|
||||||
|
anchor_outputs.append(PartialTxOutput(scriptpubkey=local_anchor_script, value=FIXED_ANCHOR_SAT))
|
||||||
|
if to_remote_amt_msat // 1000 >= dust_limit_sat or htlc_outputs:
|
||||||
|
anchor_outputs.append(PartialTxOutput(scriptpubkey=remote_anchor_script, value=FIXED_ANCHOR_SAT))
|
||||||
|
|
||||||
|
# if funder cannot afford feerate, their output might go negative, so take max(0, x) here
|
||||||
|
to_local_amt_msat = max(0, to_local_amt_msat)
|
||||||
|
to_remote_amt_msat = max(0, to_remote_amt_msat)
|
||||||
|
non_htlc_outputs.append(PartialTxOutput(scriptpubkey=local_script, value=to_local_amt_msat // 1000))
|
||||||
|
non_htlc_outputs.append(PartialTxOutput(scriptpubkey=remote_script, value=to_remote_amt_msat // 1000))
|
||||||
|
|
||||||
# trim outputs
|
|
||||||
c_outputs_filtered = list(filter(lambda x: x.value >= dust_limit_sat, non_htlc_outputs + htlc_outputs))
|
c_outputs_filtered = list(filter(lambda x: x.value >= dust_limit_sat, non_htlc_outputs + htlc_outputs))
|
||||||
return htlc_outputs, c_outputs_filtered
|
c_outputs = c_outputs_filtered + anchor_outputs
|
||||||
|
return htlc_outputs, c_outputs
|
||||||
|
|
||||||
|
|
||||||
def effective_htlc_tx_weight(success: bool, has_anchors: bool):
|
def effective_htlc_tx_weight(success: bool, has_anchors: bool):
|
||||||
@@ -1086,7 +1125,8 @@ def make_commitment(
|
|||||||
remote_amount: int,
|
remote_amount: int,
|
||||||
dust_limit_sat: int,
|
dust_limit_sat: int,
|
||||||
fees_per_participant: Mapping[HTLCOwner, int],
|
fees_per_participant: Mapping[HTLCOwner, int],
|
||||||
htlcs: List[ScriptHtlc]
|
htlcs: List[ScriptHtlc],
|
||||||
|
has_anchors: bool
|
||||||
) -> PartialTransaction:
|
) -> PartialTransaction:
|
||||||
c_input = make_funding_input(local_funding_pubkey, remote_funding_pubkey,
|
c_input = make_funding_input(local_funding_pubkey, remote_funding_pubkey,
|
||||||
funding_pos, funding_txid, funding_sat)
|
funding_pos, funding_txid, funding_sat)
|
||||||
@@ -1099,7 +1139,12 @@ def make_commitment(
|
|||||||
|
|
||||||
# commitment tx outputs
|
# commitment tx outputs
|
||||||
local_address = make_commitment_output_to_local_address(revocation_pubkey, to_self_delay, delayed_pubkey)
|
local_address = make_commitment_output_to_local_address(revocation_pubkey, to_self_delay, delayed_pubkey)
|
||||||
remote_address = make_commitment_output_to_remote_address(remote_payment_pubkey)
|
remote_address = make_commitment_output_to_remote_address(remote_payment_pubkey, has_anchors)
|
||||||
|
local_anchor_address = None
|
||||||
|
remote_anchor_address = None
|
||||||
|
if has_anchors:
|
||||||
|
local_anchor_address = make_commitment_output_to_anchor_address(local_funding_pubkey)
|
||||||
|
remote_anchor_address = make_commitment_output_to_anchor_address(remote_funding_pubkey)
|
||||||
# note: it is assumed that the given 'htlcs' are all non-dust (dust htlcs already trimmed)
|
# note: it is assumed that the given 'htlcs' are all non-dust (dust htlcs already trimmed)
|
||||||
|
|
||||||
# BOLT-03: "Transaction Input and Output Ordering
|
# BOLT-03: "Transaction Input and Output Ordering
|
||||||
@@ -1116,7 +1161,11 @@ def make_commitment(
|
|||||||
local_script=address_to_script(local_address),
|
local_script=address_to_script(local_address),
|
||||||
remote_script=address_to_script(remote_address),
|
remote_script=address_to_script(remote_address),
|
||||||
htlcs=htlcs,
|
htlcs=htlcs,
|
||||||
dust_limit_sat=dust_limit_sat)
|
dust_limit_sat=dust_limit_sat,
|
||||||
|
has_anchors=has_anchors,
|
||||||
|
local_anchor_script=address_to_script(local_anchor_address) if local_anchor_address else None,
|
||||||
|
remote_anchor_script=address_to_script(remote_anchor_address) if remote_anchor_address else None
|
||||||
|
)
|
||||||
|
|
||||||
assert sum(x.value for x in c_outputs_filtered) <= funding_sat, (c_outputs_filtered, funding_sat)
|
assert sum(x.value for x in c_outputs_filtered) <= funding_sat, (c_outputs_filtered, funding_sat)
|
||||||
|
|
||||||
@@ -1148,8 +1197,39 @@ def make_commitment_output_to_local_address(
|
|||||||
local_script = make_commitment_output_to_local_witness_script(revocation_pubkey, to_self_delay, delayed_pubkey)
|
local_script = make_commitment_output_to_local_witness_script(revocation_pubkey, to_self_delay, delayed_pubkey)
|
||||||
return bitcoin.redeem_script_to_address('p2wsh', local_script)
|
return bitcoin.redeem_script_to_address('p2wsh', local_script)
|
||||||
|
|
||||||
def make_commitment_output_to_remote_address(remote_payment_pubkey: bytes) -> str:
|
def make_commitment_output_to_remote_witness_script(remote_payment_pubkey: bytes) -> bytes:
|
||||||
return bitcoin.pubkey_to_address('p2wpkh', remote_payment_pubkey.hex())
|
assert isinstance(remote_payment_pubkey, bytes)
|
||||||
|
script = construct_script([
|
||||||
|
remote_payment_pubkey,
|
||||||
|
opcodes.OP_CHECKSIGVERIFY,
|
||||||
|
opcodes.OP_1,
|
||||||
|
opcodes.OP_CHECKSEQUENCEVERIFY,
|
||||||
|
])
|
||||||
|
return script
|
||||||
|
|
||||||
|
def make_commitment_output_to_remote_address(remote_payment_pubkey: bytes, has_anchors: bool) -> str:
|
||||||
|
if has_anchors:
|
||||||
|
remote_script = make_commitment_output_to_remote_witness_script(remote_payment_pubkey)
|
||||||
|
return bitcoin.redeem_script_to_address('p2wsh', remote_script.hex())
|
||||||
|
else:
|
||||||
|
return bitcoin.pubkey_to_address('p2wpkh', remote_payment_pubkey.hex())
|
||||||
|
|
||||||
|
def make_commitment_output_to_anchor_witness_script(funding_pubkey: bytes) -> bytes:
|
||||||
|
assert isinstance(funding_pubkey, bytes)
|
||||||
|
script = construct_script([
|
||||||
|
funding_pubkey,
|
||||||
|
opcodes.OP_CHECKSIG,
|
||||||
|
opcodes.OP_IFDUP,
|
||||||
|
opcodes.OP_NOTIF,
|
||||||
|
opcodes.OP_16,
|
||||||
|
opcodes.OP_CHECKSEQUENCEVERIFY,
|
||||||
|
opcodes.OP_ENDIF,
|
||||||
|
])
|
||||||
|
return script
|
||||||
|
|
||||||
|
def make_commitment_output_to_anchor_address(funding_pubkey: bytes) -> str:
|
||||||
|
script = make_commitment_output_to_anchor_witness_script(funding_pubkey)
|
||||||
|
return bitcoin.redeem_script_to_address('p2wsh', script.hex())
|
||||||
|
|
||||||
def sign_and_get_sig_string(tx: PartialTransaction, local_config, remote_config):
|
def sign_and_get_sig_string(tx: PartialTransaction, local_config, remote_config):
|
||||||
tx.sign({local_config.multisig_key.pubkey: local_config.multisig_key.privkey})
|
tx.sign({local_config.multisig_key.pubkey: local_config.multisig_key.privkey})
|
||||||
|
|||||||
@@ -539,7 +539,9 @@ class TestLNUtil(ElectrumTestCase):
|
|||||||
remote_amount=to_remote_msat,
|
remote_amount=to_remote_msat,
|
||||||
dust_limit_sat=local_dust_limit_satoshi,
|
dust_limit_sat=local_dust_limit_satoshi,
|
||||||
fees_per_participant=calc_fees_for_commitment_tx(num_htlcs=len(htlcs), feerate=local_feerate_per_kw, is_local_initiator=True, has_anchors=False),
|
fees_per_participant=calc_fees_for_commitment_tx(num_htlcs=len(htlcs), feerate=local_feerate_per_kw, is_local_initiator=True, has_anchors=False),
|
||||||
htlcs=htlcs)
|
htlcs=htlcs,
|
||||||
|
has_anchors=False
|
||||||
|
)
|
||||||
self.sign_and_insert_remote_sig(our_commit_tx, remote_funding_pubkey, remote_signature, local_funding_pubkey, local_funding_privkey)
|
self.sign_and_insert_remote_sig(our_commit_tx, remote_funding_pubkey, remote_signature, local_funding_pubkey, local_funding_privkey)
|
||||||
self.assertEqual(str(our_commit_tx), output_commit_tx)
|
self.assertEqual(str(our_commit_tx), output_commit_tx)
|
||||||
|
|
||||||
@@ -643,7 +645,9 @@ class TestLNUtil(ElectrumTestCase):
|
|||||||
remote_amount=to_remote_msat,
|
remote_amount=to_remote_msat,
|
||||||
dust_limit_sat=local_dust_limit_satoshi,
|
dust_limit_sat=local_dust_limit_satoshi,
|
||||||
fees_per_participant=calc_fees_for_commitment_tx(num_htlcs=0, feerate=local_feerate_per_kw, is_local_initiator=True, has_anchors=False),
|
fees_per_participant=calc_fees_for_commitment_tx(num_htlcs=0, feerate=local_feerate_per_kw, is_local_initiator=True, has_anchors=False),
|
||||||
htlcs=[])
|
htlcs=[],
|
||||||
|
has_anchors=False
|
||||||
|
)
|
||||||
self.sign_and_insert_remote_sig(our_commit_tx, remote_funding_pubkey, remote_signature, local_funding_pubkey, local_funding_privkey)
|
self.sign_and_insert_remote_sig(our_commit_tx, remote_funding_pubkey, remote_signature, local_funding_pubkey, local_funding_privkey)
|
||||||
|
|
||||||
self.assertEqual(str(our_commit_tx), output_commit_tx)
|
self.assertEqual(str(our_commit_tx), output_commit_tx)
|
||||||
@@ -672,7 +676,9 @@ class TestLNUtil(ElectrumTestCase):
|
|||||||
remote_amount=to_remote_msat,
|
remote_amount=to_remote_msat,
|
||||||
dust_limit_sat=local_dust_limit_satoshi,
|
dust_limit_sat=local_dust_limit_satoshi,
|
||||||
fees_per_participant=calc_fees_for_commitment_tx(num_htlcs=0, feerate=local_feerate_per_kw, is_local_initiator=True, has_anchors=False),
|
fees_per_participant=calc_fees_for_commitment_tx(num_htlcs=0, feerate=local_feerate_per_kw, is_local_initiator=True, has_anchors=False),
|
||||||
htlcs=[])
|
htlcs=[],
|
||||||
|
has_anchors=False
|
||||||
|
)
|
||||||
self.sign_and_insert_remote_sig(our_commit_tx, remote_funding_pubkey, remote_signature, local_funding_pubkey, local_funding_privkey)
|
self.sign_and_insert_remote_sig(our_commit_tx, remote_funding_pubkey, remote_signature, local_funding_pubkey, local_funding_privkey)
|
||||||
|
|
||||||
self.assertEqual(str(our_commit_tx), output_commit_tx)
|
self.assertEqual(str(our_commit_tx), output_commit_tx)
|
||||||
@@ -739,7 +745,9 @@ class TestLNUtil(ElectrumTestCase):
|
|||||||
remote_amount=to_remote_msat,
|
remote_amount=to_remote_msat,
|
||||||
dust_limit_sat=local_dust_limit_satoshi,
|
dust_limit_sat=local_dust_limit_satoshi,
|
||||||
fees_per_participant=calc_fees_for_commitment_tx(num_htlcs=0, feerate=local_feerate_per_kw, is_local_initiator=True, has_anchors=False),
|
fees_per_participant=calc_fees_for_commitment_tx(num_htlcs=0, feerate=local_feerate_per_kw, is_local_initiator=True, has_anchors=False),
|
||||||
htlcs=[])
|
htlcs=[],
|
||||||
|
has_anchors=False
|
||||||
|
)
|
||||||
self.sign_and_insert_remote_sig(our_commit_tx, remote_funding_pubkey, remote_signature, local_funding_pubkey, local_funding_privkey)
|
self.sign_and_insert_remote_sig(our_commit_tx, remote_funding_pubkey, remote_signature, local_funding_pubkey, local_funding_privkey)
|
||||||
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)
|
||||||
|
|||||||
Reference in New Issue
Block a user