mirror of
https://github.com/LBRYFoundation/LBRY-Vault.git
synced 2025-09-01 09:45:18 +00:00
lnhtlc: only store feerate once, don't store heights since we do not roll back
This commit is contained in:
parent
e8471e483b
commit
b26dc66567
4 changed files with 43 additions and 63 deletions
|
@ -530,7 +530,7 @@ class Peer(PrintError):
|
|||
chan.set_state('DISCONNECTED')
|
||||
self.network.trigger_callback('channel', chan)
|
||||
|
||||
def make_local_config(self, funding_sat, push_msat, initiator: HTLCOwner, feerate):
|
||||
def make_local_config(self, funding_sat, push_msat, initiator: HTLCOwner):
|
||||
# key derivation
|
||||
channel_counter = self.lnworker.get_and_inc_counter_for_channel_keys()
|
||||
keypair_generator = lambda family: generate_keypair(self.lnworker.ln_keystore, family, channel_counter)
|
||||
|
@ -552,7 +552,6 @@ class Peer(PrintError):
|
|||
ctn=-1,
|
||||
next_htlc_id=0,
|
||||
amount_msat=initial_msat,
|
||||
feerate=feerate,
|
||||
)
|
||||
per_commitment_secret_seed = keypair_generator(LnKeyFamily.REVOCATION_ROOT).privkey
|
||||
return local_config, per_commitment_secret_seed
|
||||
|
@ -561,7 +560,7 @@ class Peer(PrintError):
|
|||
async def channel_establishment_flow(self, password, funding_sat, push_msat, temp_channel_id):
|
||||
await self.initialized
|
||||
feerate = self.current_feerate_per_kw()
|
||||
local_config, per_commitment_secret_seed = self.make_local_config(funding_sat, push_msat, LOCAL, feerate)
|
||||
local_config, per_commitment_secret_seed = self.make_local_config(funding_sat, push_msat, LOCAL)
|
||||
# for the first commitment transaction
|
||||
per_commitment_secret_first = get_per_commitment_secret_from_seed(per_commitment_secret_seed, RevocationStore.START_INDEX)
|
||||
per_commitment_point_first = secret_to_pubkey(int.from_bytes(per_commitment_secret_first, 'big'))
|
||||
|
@ -611,7 +610,6 @@ class Peer(PrintError):
|
|||
ctn = -1,
|
||||
amount_msat=push_msat,
|
||||
next_htlc_id = 0,
|
||||
feerate=feerate,
|
||||
|
||||
next_per_commitment_point=remote_per_commitment_point,
|
||||
current_per_commitment_point=None,
|
||||
|
@ -640,7 +638,7 @@ class Peer(PrintError):
|
|||
current_commitment_signature = None,
|
||||
current_htlc_signatures = None,
|
||||
),
|
||||
"constraints": ChannelConstraints(capacity=funding_sat, is_initiator=True, funding_txn_minimum_depth=funding_txn_minimum_depth),
|
||||
"constraints": ChannelConstraints(capacity=funding_sat, is_initiator=True, funding_txn_minimum_depth=funding_txn_minimum_depth, feerate=feerate),
|
||||
"remote_commitment_to_be_revoked": None,
|
||||
}
|
||||
m = HTLCStateMachine(chan)
|
||||
|
@ -675,7 +673,7 @@ class Peer(PrintError):
|
|||
feerate = int.from_bytes(payload['feerate_per_kw'], 'big')
|
||||
|
||||
temp_chan_id = payload['temporary_channel_id']
|
||||
local_config, per_commitment_secret_seed = self.make_local_config(funding_sat * 1000, push_msat, REMOTE, feerate)
|
||||
local_config, per_commitment_secret_seed = self.make_local_config(funding_sat * 1000, push_msat, REMOTE)
|
||||
|
||||
# for the first commitment transaction
|
||||
per_commitment_secret_first = get_per_commitment_secret_from_seed(per_commitment_secret_seed, RevocationStore.START_INDEX)
|
||||
|
@ -723,7 +721,6 @@ class Peer(PrintError):
|
|||
ctn = -1,
|
||||
amount_msat=remote_balance_sat,
|
||||
next_htlc_id = 0,
|
||||
feerate=feerate,
|
||||
|
||||
next_per_commitment_point=payload['first_per_commitment_point'],
|
||||
current_per_commitment_point=None,
|
||||
|
@ -737,7 +734,7 @@ class Peer(PrintError):
|
|||
current_commitment_signature = None,
|
||||
current_htlc_signatures = None,
|
||||
),
|
||||
"constraints": ChannelConstraints(capacity=funding_sat, is_initiator=False, funding_txn_minimum_depth=min_depth),
|
||||
"constraints": ChannelConstraints(capacity=funding_sat, is_initiator=False, funding_txn_minimum_depth=min_depth, feerate=feerate),
|
||||
"remote_commitment_to_be_revoked": None,
|
||||
}
|
||||
m = HTLCStateMachine(chan)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# ported from lnd 42de4400bff5105352d0552155f73589166d162b
|
||||
from collections import namedtuple
|
||||
from collections import namedtuple, defaultdict
|
||||
import binascii
|
||||
import json
|
||||
from enum import Enum, auto
|
||||
|
@ -34,26 +34,14 @@ FUNDEE_SIGNED = FeeUpdateProgress.FUNDEE_SIGNED
|
|||
FUNDEE_ACKED = FeeUpdateProgress.FUNDEE_ACKED
|
||||
FUNDER_SIGNED = FeeUpdateProgress.FUNDER_SIGNED
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
class FeeUpdate:
|
||||
class FeeUpdate(defaultdict):
|
||||
def __init__(self, chan, rate):
|
||||
super().__init__(lambda: False)
|
||||
self.rate = rate
|
||||
self.progress = {FUNDEE_SIGNED: None, FUNDEE_ACKED: None, FUNDER_SIGNED: None}
|
||||
self.chan = chan
|
||||
|
||||
def set(self, field):
|
||||
self.progress[field] = self.chan.current_height[LOCAL if self.chan.constraints.is_initiator else REMOTE]
|
||||
|
||||
def had(self, field):
|
||||
"""
|
||||
returns true when the progress field given has been
|
||||
set at the current commitment number of the funder
|
||||
"""
|
||||
return self.progress[field] is not None
|
||||
|
||||
def pending_feerate(self, subject):
|
||||
if self.had(FUNDEE_ACKED):
|
||||
if self[FUNDEE_ACKED]:
|
||||
return self.rate
|
||||
if subject == REMOTE and self.chan.constraints.is_initiator:
|
||||
return self.rate
|
||||
|
@ -230,9 +218,9 @@ class HTLCStateMachine(PrintError):
|
|||
|
||||
for pending_fee in self.fee_mgr:
|
||||
if not self.constraints.is_initiator:
|
||||
pending_fee.set(FUNDEE_SIGNED)
|
||||
if self.constraints.is_initiator and pending_fee.had(FUNDEE_ACKED):
|
||||
pending_fee.set(FUNDER_SIGNED)
|
||||
pending_fee[FUNDEE_SIGNED] = True
|
||||
if self.constraints.is_initiator and pending_fee[FUNDEE_ACKED]:
|
||||
pending_fee[FUNDER_SIGNED] = True
|
||||
|
||||
self.process_new_offchain_ctx(pending_remote_commitment, ours=False)
|
||||
|
||||
|
@ -283,9 +271,9 @@ class HTLCStateMachine(PrintError):
|
|||
|
||||
for pending_fee in self.fee_mgr:
|
||||
if not self.constraints.is_initiator:
|
||||
pending_fee.set(FUNDEE_SIGNED)
|
||||
if self.constraints.is_initiator and pending_fee.had(FUNDEE_ACKED):
|
||||
pending_fee.set(FUNDER_SIGNED)
|
||||
pending_fee[FUNDEE_SIGNED] = True
|
||||
if self.constraints.is_initiator and pending_fee[FUNDEE_ACKED]:
|
||||
pending_fee[FUNDER_SIGNED] = True
|
||||
|
||||
self.process_new_offchain_ctx(pending_local_commitment, ours=True)
|
||||
|
||||
|
@ -305,25 +293,23 @@ class HTLCStateMachine(PrintError):
|
|||
|
||||
last_secret, this_point, next_point = self.points
|
||||
|
||||
new_local_feerate = self.config[LOCAL].feerate
|
||||
new_remote_feerate = self.config[REMOTE].feerate
|
||||
new_feerate = self.constraints.feerate
|
||||
|
||||
for pending_fee in self.fee_mgr[:]:
|
||||
if not self.constraints.is_initiator and pending_fee.had(FUNDEE_SIGNED):
|
||||
new_local_feerate = new_remote_feerate = pending_fee.rate
|
||||
if not self.constraints.is_initiator and pending_fee[FUNDEE_SIGNED]:
|
||||
new_feerate = pending_fee.rate
|
||||
self.fee_mgr.remove(pending_fee)
|
||||
print("FEERATE CHANGE COMPLETE (non-initiator)")
|
||||
if self.constraints.is_initiator and pending_fee.had(FUNDER_SIGNED):
|
||||
new_local_feerate = new_remote_feerate = pending_fee.rate
|
||||
if self.constraints.is_initiator and pending_fee[FUNDER_SIGNED]:
|
||||
new_feerate = pending_fee.rate
|
||||
self.fee_mgr.remove(pending_fee)
|
||||
print("FEERATE CHANGE COMPLETE (initiator)")
|
||||
|
||||
self.config[LOCAL]=self.config[LOCAL]._replace(
|
||||
ctn=self.config[LOCAL].ctn + 1,
|
||||
feerate=new_local_feerate
|
||||
)
|
||||
self.config[REMOTE]=self.config[REMOTE]._replace(
|
||||
feerate=new_remote_feerate
|
||||
self.constraints=self.constraints._replace(
|
||||
feerate=new_feerate
|
||||
)
|
||||
|
||||
self.local_commitment = self.pending_local_commitment
|
||||
|
@ -427,7 +413,7 @@ class HTLCStateMachine(PrintError):
|
|||
|
||||
for pending_fee in self.fee_mgr:
|
||||
if self.constraints.is_initiator:
|
||||
pending_fee.set(FUNDEE_ACKED)
|
||||
pending_fee[FUNDEE_ACKED] = True
|
||||
|
||||
self.local_commitment = self.pending_local_commitment
|
||||
self.remote_commitment = self.pending_remote_commitment
|
||||
|
@ -471,18 +457,13 @@ class HTLCStateMachine(PrintError):
|
|||
return self.make_commitment(REMOTE, this_point)
|
||||
|
||||
def pending_feerate(self, subject):
|
||||
candidate = None
|
||||
candidate = self.constraints.feerate
|
||||
for pending_fee in self.fee_mgr:
|
||||
x = pending_fee.pending_feerate(subject)
|
||||
if x is not None:
|
||||
candidate = x
|
||||
|
||||
feerate = candidate if candidate is not None else self._committed_feerate[subject]
|
||||
return feerate
|
||||
|
||||
@property
|
||||
def _committed_feerate(self):
|
||||
return {LOCAL: self.config[LOCAL].feerate, REMOTE: self.config[REMOTE].feerate}
|
||||
return candidate
|
||||
|
||||
@property
|
||||
def pending_local_commitment(self):
|
||||
|
|
|
@ -26,7 +26,6 @@ common = [
|
|||
('ctn' , int),
|
||||
('amount_msat' , int),
|
||||
('next_htlc_id' , int),
|
||||
('feerate' , int),
|
||||
('payment_basepoint' , Keypair),
|
||||
('multisig_key' , Keypair),
|
||||
('htlc_basepoint' , Keypair),
|
||||
|
@ -49,7 +48,7 @@ LocalConfig = NamedTuple('LocalConfig', common + [
|
|||
('current_htlc_signatures', List[bytes]),
|
||||
])
|
||||
|
||||
ChannelConstraints = namedtuple("ChannelConstraints", ["capacity", "is_initiator", "funding_txn_minimum_depth"])
|
||||
ChannelConstraints = namedtuple("ChannelConstraints", ["capacity", "is_initiator", "funding_txn_minimum_depth", "feerate"])
|
||||
|
||||
ScriptHtlc = namedtuple('ScriptHtlc', ['redeem_script', 'htlc'])
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@ def create_channel_state(funding_txid, funding_index, funding_sat, local_feerate
|
|||
initial_msat=remote_amount,
|
||||
ctn = 0,
|
||||
next_htlc_id = 0,
|
||||
feerate=local_feerate,
|
||||
amount_msat=remote_amount,
|
||||
|
||||
next_per_commitment_point=nex,
|
||||
|
@ -54,7 +53,6 @@ def create_channel_state(funding_txid, funding_index, funding_sat, local_feerate
|
|||
initial_msat=local_amount,
|
||||
ctn = 0,
|
||||
next_htlc_id = 0,
|
||||
feerate=local_feerate,
|
||||
amount_msat=local_amount,
|
||||
|
||||
per_commitment_secret_seed=seed,
|
||||
|
@ -63,7 +61,12 @@ def create_channel_state(funding_txid, funding_index, funding_sat, local_feerate
|
|||
current_commitment_signature=None,
|
||||
current_htlc_signatures=None,
|
||||
),
|
||||
"constraints":lnbase.ChannelConstraints(capacity=funding_sat, is_initiator=is_initiator, funding_txn_minimum_depth=3),
|
||||
"constraints":lnbase.ChannelConstraints(
|
||||
capacity=funding_sat,
|
||||
is_initiator=is_initiator,
|
||||
funding_txn_minimum_depth=3,
|
||||
feerate=local_feerate,
|
||||
),
|
||||
"node_id":other_node_id,
|
||||
"remote_commitment_to_be_revoked": None,
|
||||
'onion_keys': {},
|
||||
|
@ -271,20 +274,20 @@ class TestLNBaseHTLCStateMachine(unittest.TestCase):
|
|||
|
||||
bob_channel.receive_new_commitment(alice_sig, alice_htlc_sigs)
|
||||
|
||||
self.assertNotEqual(fee, bob_channel.config[LOCAL].feerate)
|
||||
self.assertNotEqual(fee, bob_channel.constraints.feerate)
|
||||
rev, _ = bob_channel.revoke_current_commitment()
|
||||
self.assertEqual(fee, bob_channel.config[LOCAL].feerate)
|
||||
self.assertEqual(fee, bob_channel.constraints.feerate)
|
||||
|
||||
bob_sig, bob_htlc_sigs = bob_channel.sign_next_commitment()
|
||||
alice_channel.receive_revocation(rev)
|
||||
alice_channel.receive_new_commitment(bob_sig, bob_htlc_sigs)
|
||||
|
||||
self.assertNotEqual(fee, alice_channel.config[LOCAL].feerate)
|
||||
self.assertNotEqual(fee, alice_channel.constraints.feerate)
|
||||
rev, _ = alice_channel.revoke_current_commitment()
|
||||
self.assertEqual(fee, alice_channel.config[LOCAL].feerate)
|
||||
self.assertEqual(fee, alice_channel.constraints.feerate)
|
||||
|
||||
bob_channel.receive_revocation(rev)
|
||||
self.assertEqual(fee, bob_channel.config[REMOTE].feerate)
|
||||
self.assertEqual(fee, bob_channel.constraints.feerate)
|
||||
|
||||
|
||||
def test_UpdateFeeReceiverCommits(self):
|
||||
|
@ -300,20 +303,20 @@ class TestLNBaseHTLCStateMachine(unittest.TestCase):
|
|||
alice_sig, alice_htlc_sigs = alice_channel.sign_next_commitment()
|
||||
bob_channel.receive_new_commitment(alice_sig, alice_htlc_sigs)
|
||||
|
||||
self.assertNotEqual(fee, bob_channel.config[LOCAL].feerate)
|
||||
self.assertNotEqual(fee, bob_channel.constraints.feerate)
|
||||
bob_revocation, _ = bob_channel.revoke_current_commitment()
|
||||
self.assertEqual(fee, bob_channel.config[LOCAL].feerate)
|
||||
self.assertEqual(fee, bob_channel.constraints.feerate)
|
||||
|
||||
bob_sig, bob_htlc_sigs = bob_channel.sign_next_commitment()
|
||||
alice_channel.receive_revocation(bob_revocation)
|
||||
alice_channel.receive_new_commitment(bob_sig, bob_htlc_sigs)
|
||||
|
||||
self.assertNotEqual(fee, alice_channel.config[LOCAL].feerate)
|
||||
self.assertNotEqual(fee, alice_channel.constraints.feerate)
|
||||
alice_revocation, _ = alice_channel.revoke_current_commitment()
|
||||
self.assertEqual(fee, alice_channel.config[LOCAL].feerate)
|
||||
self.assertEqual(fee, alice_channel.constraints.feerate)
|
||||
|
||||
bob_channel.receive_revocation(alice_revocation)
|
||||
self.assertEqual(fee, bob_channel.config[REMOTE].feerate)
|
||||
self.assertEqual(fee, bob_channel.constraints.feerate)
|
||||
|
||||
|
||||
|
||||
|
@ -323,7 +326,7 @@ class TestLNHTLCDust(unittest.TestCase):
|
|||
|
||||
paymentPreimage = b"\x01" * 32
|
||||
paymentHash = bitcoin.sha256(paymentPreimage)
|
||||
fee_per_kw = alice_channel.config[LOCAL].feerate
|
||||
fee_per_kw = alice_channel.constraints.feerate
|
||||
self.assertEqual(fee_per_kw, 6000)
|
||||
htlcAmt = 500 + lnutil.HTLC_TIMEOUT_WEIGHT * (fee_per_kw // 1000)
|
||||
self.assertEqual(htlcAmt, 4478)
|
||||
|
|
Loading…
Add table
Reference in a new issue