lnmsg.decode_msg: dict values for numbers are int, instead of BE bytes

Will be useful for TLVs where it makes sense to do the conversion in lnmsg,
as it might be more complicated than just int.from_bytes().
This commit is contained in:
SomberNight 2020-03-12 04:08:13 +01:00
parent 4c10a830f3
commit 3a73f6ee5c
No known key found for this signature in database
GPG key ID: B33B5F232C6271E9
5 changed files with 75 additions and 68 deletions

View file

@ -102,14 +102,14 @@ class Policy(NamedTuple):
def from_msg(payload: dict) -> 'Policy': def from_msg(payload: dict) -> 'Policy':
return Policy( return Policy(
key = payload['short_channel_id'] + payload['start_node'], key = payload['short_channel_id'] + payload['start_node'],
cltv_expiry_delta = int.from_bytes(payload['cltv_expiry_delta'], "big"), cltv_expiry_delta = payload['cltv_expiry_delta'],
htlc_minimum_msat = int.from_bytes(payload['htlc_minimum_msat'], "big"), htlc_minimum_msat = payload['htlc_minimum_msat'],
htlc_maximum_msat = int.from_bytes(payload['htlc_maximum_msat'], "big") if 'htlc_maximum_msat' in payload else None, htlc_maximum_msat = payload.get('htlc_maximum_msat', None),
fee_base_msat = int.from_bytes(payload['fee_base_msat'], "big"), fee_base_msat = payload['fee_base_msat'],
fee_proportional_millionths = int.from_bytes(payload['fee_proportional_millionths'], "big"), fee_proportional_millionths = payload['fee_proportional_millionths'],
message_flags = int.from_bytes(payload['message_flags'], "big"), message_flags = int.from_bytes(payload['message_flags'], "big"),
channel_flags = int.from_bytes(payload['channel_flags'], "big"), channel_flags = int.from_bytes(payload['channel_flags'], "big"),
timestamp = int.from_bytes(payload['timestamp'], "big") timestamp = payload['timestamp'],
) )
@staticmethod @staticmethod
@ -154,7 +154,7 @@ class NodeInfo(NamedTuple):
alias = alias.decode('utf8') alias = alias.decode('utf8')
except: except:
alias = '' alias = ''
timestamp = int.from_bytes(payload['timestamp'], "big") timestamp = payload['timestamp']
node_info = NodeInfo(node_id=node_id, features=features, timestamp=timestamp, alias=alias) node_info = NodeInfo(node_id=node_id, features=features, timestamp=timestamp, alias=alias)
return node_info, peer_addrs return node_info, peer_addrs
@ -393,7 +393,7 @@ class ChannelDB(SqlDB):
now = int(time.time()) now = int(time.time())
for payload in payloads: for payload in payloads:
short_channel_id = ShortChannelID(payload['short_channel_id']) short_channel_id = ShortChannelID(payload['short_channel_id'])
timestamp = int.from_bytes(payload['timestamp'], "big") timestamp = payload['timestamp']
if max_age and now - timestamp > max_age: if max_age and now - timestamp > max_age:
expired.append(payload) expired.append(payload)
continue continue
@ -408,7 +408,7 @@ class ChannelDB(SqlDB):
known.append(payload) known.append(payload)
# compare updates to existing database entries # compare updates to existing database entries
for payload in known: for payload in known:
timestamp = int.from_bytes(payload['timestamp'], "big") timestamp = payload['timestamp']
start_node = payload['start_node'] start_node = payload['start_node']
short_channel_id = ShortChannelID(payload['short_channel_id']) short_channel_id = ShortChannelID(payload['short_channel_id'])
key = (start_node, short_channel_id) key = (start_node, short_channel_id)
@ -673,7 +673,7 @@ class ChannelDB(SqlDB):
return return
now = int(time.time()) now = int(time.time())
remote_update_decoded = decode_msg(remote_update_raw)[1] remote_update_decoded = decode_msg(remote_update_raw)[1]
remote_update_decoded['timestamp'] = now.to_bytes(4, byteorder="big") remote_update_decoded['timestamp'] = now
remote_update_decoded['start_node'] = node_id remote_update_decoded['start_node'] = node_id
return Policy.from_msg(remote_update_decoded) return Policy.from_msg(remote_update_decoded)
elif node_id == chan.get_local_pubkey(): # outgoing direction (from us) elif node_id == chan.get_local_pubkey(): # outgoing direction (from us)

View file

@ -218,13 +218,13 @@ class Channel(Logger):
short_channel_id=self.short_channel_id, short_channel_id=self.short_channel_id,
channel_flags=channel_flags, channel_flags=channel_flags,
message_flags=b'\x01', message_flags=b'\x01',
cltv_expiry_delta=lnutil.NBLOCK_OUR_CLTV_EXPIRY_DELTA.to_bytes(2, byteorder="big"), cltv_expiry_delta=lnutil.NBLOCK_OUR_CLTV_EXPIRY_DELTA,
htlc_minimum_msat=self.config[REMOTE].htlc_minimum_msat.to_bytes(8, byteorder="big"), htlc_minimum_msat=self.config[REMOTE].htlc_minimum_msat,
htlc_maximum_msat=htlc_maximum_msat.to_bytes(8, byteorder="big"), htlc_maximum_msat=htlc_maximum_msat,
fee_base_msat=lnutil.OUR_FEE_BASE_MSAT.to_bytes(4, byteorder="big"), fee_base_msat=lnutil.OUR_FEE_BASE_MSAT,
fee_proportional_millionths=lnutil.OUR_FEE_PROPORTIONAL_MILLIONTHS.to_bytes(4, byteorder="big"), fee_proportional_millionths=lnutil.OUR_FEE_PROPORTIONAL_MILLIONTHS,
chain_hash=constants.net.rev_genesis_bytes(), chain_hash=constants.net.rev_genesis_bytes(),
timestamp=now.to_bytes(4, byteorder="big"), timestamp=now,
) )
sighash = sha256d(chan_upd[2 + 64:]) sighash = sha256d(chan_upd[2 + 64:])
sig = ecc.ECPrivkey(self.lnworker.node_keypair.privkey).sign(sighash, ecc.sig_string_from_r_and_s) sig = ecc.ECPrivkey(self.lnworker.node_keypair.privkey).sign(sighash, ecc.sig_string_from_r_and_s)

View file

@ -1,7 +1,7 @@
import os import os
import csv import csv
import io import io
from typing import Callable, Tuple, Any, Dict, List, Sequence, Union from typing import Callable, Tuple, Any, Dict, List, Sequence, Union, Optional
class MalformedMsg(Exception): class MalformedMsg(Exception):
@ -24,8 +24,7 @@ def _assert_can_read_at_least_n_bytes(fd: io.BytesIO, n: int) -> None:
raise UnexpectedEndOfStream(f"cur_pos={cur_pos}. end_pos={end_pos}. wants to read: {n}") raise UnexpectedEndOfStream(f"cur_pos={cur_pos}. end_pos={end_pos}. wants to read: {n}")
# TODO return int when it makes sense def _read_field(*, fd: io.BytesIO, field_type: str, count: int) -> Union[bytes, int]:
def _read_field(*, fd: io.BytesIO, field_type: str, count: int) -> bytes:
if not fd: raise Exception() if not fd: raise Exception()
assert isinstance(count, int) and count >= 0, f"{count!r} must be non-neg int" assert isinstance(count, int) and count >= 0, f"{count!r} must be non-neg int"
if count == 0: if count == 0:
@ -35,10 +34,19 @@ def _read_field(*, fd: io.BytesIO, field_type: str, count: int) -> bytes:
type_len = 1 type_len = 1
elif field_type == 'u16': elif field_type == 'u16':
type_len = 2 type_len = 2
assert count == 1, count
_assert_can_read_at_least_n_bytes(fd, type_len)
return int.from_bytes(fd.read(type_len), byteorder="big", signed=False)
elif field_type == 'u32': elif field_type == 'u32':
type_len = 4 type_len = 4
assert count == 1, count
_assert_can_read_at_least_n_bytes(fd, type_len)
return int.from_bytes(fd.read(type_len), byteorder="big", signed=False)
elif field_type == 'u64': elif field_type == 'u64':
type_len = 8 type_len = 8
assert count == 1, count
_assert_can_read_at_least_n_bytes(fd, type_len)
return int.from_bytes(fd.read(type_len), byteorder="big", signed=False)
# TODO tu16/tu32/tu64 # TODO tu16/tu32/tu64
elif field_type == 'chain_hash': elif field_type == 'chain_hash':
type_len = 32 type_len = 32
@ -203,7 +211,8 @@ class LNSerializer:
try: try:
field_count = int(field_count_str) field_count = int(field_count_str)
except ValueError: except ValueError:
field_count = int.from_bytes(parsed[field_count_str], byteorder="big") field_count = parsed[field_count_str]
assert isinstance(field_count, int)
#print(f">> count={field_count}. parsed={parsed}") #print(f">> count={field_count}. parsed={parsed}")
try: try:
parsed[field_name] = _read_field(fd=fd, parsed[field_name] = _read_field(fd=fd,

View file

@ -180,7 +180,7 @@ class Peer(Logger):
self.ordered_message_queues[chan_id].put_nowait((None, {'error':payload['data']})) self.ordered_message_queues[chan_id].put_nowait((None, {'error':payload['data']}))
def on_ping(self, payload): def on_ping(self, payload):
l = int.from_bytes(payload['num_pong_bytes'], 'big') l = payload['num_pong_bytes']
self.send_message('pong', byteslen=l) self.send_message('pong', byteslen=l)
def on_pong(self, payload): def on_pong(self, payload):
@ -417,8 +417,8 @@ class Peer(Logger):
return ids return ids
def on_reply_channel_range(self, payload): def on_reply_channel_range(self, payload):
first = int.from_bytes(payload['first_blocknum'], 'big') first = payload['first_blocknum']
num = int.from_bytes(payload['number_of_blocks'], 'big') num = payload['number_of_blocks']
complete = bool(int.from_bytes(payload['complete'], 'big')) complete = bool(int.from_bytes(payload['complete'], 'big'))
encoded = payload['encoded_short_ids'] encoded = payload['encoded_short_ids']
ids = self.decode_short_ids(encoded) ids = self.decode_short_ids(encoded)
@ -541,27 +541,27 @@ class Peer(Logger):
) )
payload = await self.wait_for_message('accept_channel', temp_channel_id) payload = await self.wait_for_message('accept_channel', temp_channel_id)
remote_per_commitment_point = payload['first_per_commitment_point'] remote_per_commitment_point = payload['first_per_commitment_point']
funding_txn_minimum_depth = int.from_bytes(payload['minimum_depth'], 'big') funding_txn_minimum_depth = payload['minimum_depth']
if funding_txn_minimum_depth <= 0: if funding_txn_minimum_depth <= 0:
raise Exception(f"minimum depth too low, {funding_txn_minimum_depth}") raise Exception(f"minimum depth too low, {funding_txn_minimum_depth}")
if funding_txn_minimum_depth > 30: if funding_txn_minimum_depth > 30:
raise Exception(f"minimum depth too high, {funding_txn_minimum_depth}") raise Exception(f"minimum depth too high, {funding_txn_minimum_depth}")
remote_dust_limit_sat = int.from_bytes(payload['dust_limit_satoshis'], byteorder='big') remote_dust_limit_sat = payload['dust_limit_satoshis']
remote_reserve_sat = self.validate_remote_reserve(payload["channel_reserve_satoshis"], remote_dust_limit_sat, funding_sat) remote_reserve_sat = self.validate_remote_reserve(payload["channel_reserve_satoshis"], remote_dust_limit_sat, funding_sat)
if remote_dust_limit_sat > remote_reserve_sat: if remote_dust_limit_sat > remote_reserve_sat:
raise Exception(f"Remote Lightning peer reports dust_limit_sat > reserve_sat which is a BOLT-02 protocol violation.") raise Exception(f"Remote Lightning peer reports dust_limit_sat > reserve_sat which is a BOLT-02 protocol violation.")
htlc_min = int.from_bytes(payload['htlc_minimum_msat'], 'big') htlc_min = payload['htlc_minimum_msat']
if htlc_min > MAXIMUM_HTLC_MINIMUM_MSAT_ACCEPTED: if htlc_min > MAXIMUM_HTLC_MINIMUM_MSAT_ACCEPTED:
raise Exception(f"Remote Lightning peer reports htlc_minimum_msat={htlc_min} mSAT," + raise Exception(f"Remote Lightning peer reports htlc_minimum_msat={htlc_min} mSAT," +
f" which is above Electrums required maximum limit of that parameter ({MAXIMUM_HTLC_MINIMUM_MSAT_ACCEPTED} mSAT).") f" which is above Electrums required maximum limit of that parameter ({MAXIMUM_HTLC_MINIMUM_MSAT_ACCEPTED} mSAT).")
remote_max = int.from_bytes(payload['max_htlc_value_in_flight_msat'], 'big') remote_max = payload['max_htlc_value_in_flight_msat']
if remote_max < MINIMUM_MAX_HTLC_VALUE_IN_FLIGHT_ACCEPTED: if remote_max < MINIMUM_MAX_HTLC_VALUE_IN_FLIGHT_ACCEPTED:
raise Exception(f"Remote Lightning peer reports max_htlc_value_in_flight_msat at only {remote_max} mSAT" + raise Exception(f"Remote Lightning peer reports max_htlc_value_in_flight_msat at only {remote_max} mSAT" +
f" which is below Electrums required minimum ({MINIMUM_MAX_HTLC_VALUE_IN_FLIGHT_ACCEPTED} mSAT).") f" which is below Electrums required minimum ({MINIMUM_MAX_HTLC_VALUE_IN_FLIGHT_ACCEPTED} mSAT).")
max_accepted_htlcs = int.from_bytes(payload["max_accepted_htlcs"], 'big') max_accepted_htlcs = payload["max_accepted_htlcs"]
if max_accepted_htlcs > 483: if max_accepted_htlcs > 483:
raise Exception("Remote Lightning peer reports max_accepted_htlcs > 483, which is a BOLT-02 protocol violation.") raise Exception("Remote Lightning peer reports max_accepted_htlcs > 483, which is a BOLT-02 protocol violation.")
remote_to_self_delay = int.from_bytes(payload['to_self_delay'], byteorder='big') remote_to_self_delay = payload['to_self_delay']
if remote_to_self_delay > MAXIMUM_REMOTE_TO_SELF_DELAY_ACCEPTED: if remote_to_self_delay > MAXIMUM_REMOTE_TO_SELF_DELAY_ACCEPTED:
raise Exception(f"Remote Lightning peer reports to_self_delay={remote_to_self_delay}," + raise Exception(f"Remote Lightning peer reports to_self_delay={remote_to_self_delay}," +
f" which is above Electrums required maximum ({MAXIMUM_REMOTE_TO_SELF_DELAY_ACCEPTED})") f" which is above Electrums required maximum ({MAXIMUM_REMOTE_TO_SELF_DELAY_ACCEPTED})")
@ -647,9 +647,9 @@ class Peer(Logger):
# payload['channel_flags'] # payload['channel_flags']
if payload['chain_hash'] != constants.net.rev_genesis_bytes(): if payload['chain_hash'] != constants.net.rev_genesis_bytes():
raise Exception('wrong chain_hash') raise Exception('wrong chain_hash')
funding_sat = int.from_bytes(payload['funding_satoshis'], 'big') funding_sat = payload['funding_satoshis']
push_msat = int.from_bytes(payload['push_msat'], 'big') push_msat = payload['push_msat']
feerate = int.from_bytes(payload['feerate_per_kw'], 'big') feerate = payload['feerate_per_kw']
temp_chan_id = payload['temporary_channel_id'] temp_chan_id = payload['temporary_channel_id']
local_config = self.make_local_config(funding_sat, push_msat, REMOTE) local_config = self.make_local_config(funding_sat, push_msat, REMOTE)
# for the first commitment transaction # for the first commitment transaction
@ -674,11 +674,11 @@ class Peer(Logger):
first_per_commitment_point=per_commitment_point_first, first_per_commitment_point=per_commitment_point_first,
) )
funding_created = await self.wait_for_message('funding_created', temp_chan_id) funding_created = await self.wait_for_message('funding_created', temp_chan_id)
funding_idx = int.from_bytes(funding_created['funding_output_index'], 'big') funding_idx = funding_created['funding_output_index']
funding_txid = bh2u(funding_created['funding_txid'][::-1]) funding_txid = bh2u(funding_created['funding_txid'][::-1])
channel_id, funding_txid_bytes = channel_id_from_funding_tx(funding_txid, funding_idx) channel_id, funding_txid_bytes = channel_id_from_funding_tx(funding_txid, funding_idx)
remote_balance_sat = funding_sat * 1000 - push_msat remote_balance_sat = funding_sat * 1000 - push_msat
remote_dust_limit_sat = int.from_bytes(payload['dust_limit_satoshis'], byteorder='big') # TODO validate remote_dust_limit_sat = payload['dust_limit_satoshis'] # TODO validate
remote_reserve_sat = self.validate_remote_reserve(payload['channel_reserve_satoshis'], remote_dust_limit_sat, funding_sat) remote_reserve_sat = self.validate_remote_reserve(payload['channel_reserve_satoshis'], remote_dust_limit_sat, funding_sat)
remote_config = RemoteConfig( remote_config = RemoteConfig(
payment_basepoint=OnlyPubkeyKeypair(payload['payment_basepoint']), payment_basepoint=OnlyPubkeyKeypair(payload['payment_basepoint']),
@ -686,13 +686,13 @@ class Peer(Logger):
htlc_basepoint=OnlyPubkeyKeypair(payload['htlc_basepoint']), htlc_basepoint=OnlyPubkeyKeypair(payload['htlc_basepoint']),
delayed_basepoint=OnlyPubkeyKeypair(payload['delayed_payment_basepoint']), delayed_basepoint=OnlyPubkeyKeypair(payload['delayed_payment_basepoint']),
revocation_basepoint=OnlyPubkeyKeypair(payload['revocation_basepoint']), revocation_basepoint=OnlyPubkeyKeypair(payload['revocation_basepoint']),
to_self_delay=int.from_bytes(payload['to_self_delay'], 'big'), to_self_delay=payload['to_self_delay'],
dust_limit_sat=remote_dust_limit_sat, dust_limit_sat=remote_dust_limit_sat,
max_htlc_value_in_flight_msat=int.from_bytes(payload['max_htlc_value_in_flight_msat'], 'big'), # TODO validate max_htlc_value_in_flight_msat=payload['max_htlc_value_in_flight_msat'], # TODO validate
max_accepted_htlcs=int.from_bytes(payload['max_accepted_htlcs'], 'big'), # TODO validate max_accepted_htlcs=payload['max_accepted_htlcs'], # TODO validate
initial_msat=remote_balance_sat, initial_msat=remote_balance_sat,
reserve_sat = remote_reserve_sat, reserve_sat = remote_reserve_sat,
htlc_minimum_msat=int.from_bytes(payload['htlc_minimum_msat'], 'big'), # TODO validate htlc_minimum_msat=payload['htlc_minimum_msat'], # TODO validate
next_per_commitment_point=payload['first_per_commitment_point'], next_per_commitment_point=payload['first_per_commitment_point'],
current_per_commitment_point=None, current_per_commitment_point=None,
) )
@ -718,8 +718,7 @@ class Peer(Logger):
chan.set_state(channel_states.OPENING) chan.set_state(channel_states.OPENING)
self.lnworker.add_new_channel(chan) self.lnworker.add_new_channel(chan)
def validate_remote_reserve(self, payload_field: bytes, dust_limit: int, funding_sat: int) -> int: def validate_remote_reserve(self, remote_reserve_sat: int, dust_limit: int, funding_sat: int) -> int:
remote_reserve_sat = int.from_bytes(payload_field, 'big')
if remote_reserve_sat < dust_limit: if remote_reserve_sat < dust_limit:
raise Exception('protocol violation: reserve < dust_limit') raise Exception('protocol violation: reserve < dust_limit')
if remote_reserve_sat > funding_sat/100: if remote_reserve_sat > funding_sat/100:
@ -768,8 +767,8 @@ class Peer(Logger):
f'(next_local_ctn={next_local_ctn}, ' f'(next_local_ctn={next_local_ctn}, '
f'oldest_unrevoked_remote_ctn={oldest_unrevoked_remote_ctn})') f'oldest_unrevoked_remote_ctn={oldest_unrevoked_remote_ctn})')
msg = await self.wait_for_message('channel_reestablish', chan_id) msg = await self.wait_for_message('channel_reestablish', chan_id)
their_next_local_ctn = int.from_bytes(msg["next_commitment_number"], 'big') their_next_local_ctn = msg["next_commitment_number"]
their_oldest_unrevoked_remote_ctn = int.from_bytes(msg["next_revocation_number"], 'big') their_oldest_unrevoked_remote_ctn = msg["next_revocation_number"]
their_local_pcp = msg.get("my_current_per_commitment_point") their_local_pcp = msg.get("my_current_per_commitment_point")
their_claim_of_our_last_per_commitment_secret = msg.get("your_last_per_commitment_secret") their_claim_of_our_last_per_commitment_secret = msg.get("your_last_per_commitment_secret")
self.logger.info(f'channel_reestablish ({chan.get_id_for_log()}): received channel_reestablish with ' self.logger.info(f'channel_reestablish ({chan.get_id_for_log()}): received channel_reestablish with '
@ -1005,7 +1004,7 @@ class Peer(Logger):
return msg_hash, node_signature, bitcoin_signature return msg_hash, node_signature, bitcoin_signature
def on_update_fail_htlc(self, chan: Channel, payload): def on_update_fail_htlc(self, chan: Channel, payload):
htlc_id = int.from_bytes(payload["id"], "big") htlc_id = payload["id"]
reason = payload["reason"] reason = payload["reason"]
self.logger.info(f"on_update_fail_htlc. chan {chan.short_channel_id}. htlc_id {htlc_id}") self.logger.info(f"on_update_fail_htlc. chan {chan.short_channel_id}. htlc_id {htlc_id}")
chan.receive_fail_htlc(htlc_id, error_bytes=reason) # TODO handle exc and maybe fail channel (e.g. bad htlc_id) chan.receive_fail_htlc(htlc_id, error_bytes=reason) # TODO handle exc and maybe fail channel (e.g. bad htlc_id)
@ -1083,7 +1082,7 @@ class Peer(Logger):
def on_update_fulfill_htlc(self, chan: Channel, payload): def on_update_fulfill_htlc(self, chan: Channel, payload):
preimage = payload["payment_preimage"] preimage = payload["payment_preimage"]
payment_hash = sha256(preimage) payment_hash = sha256(preimage)
htlc_id = int.from_bytes(payload["id"], "big") htlc_id = payload["id"]
self.logger.info(f"on_update_fulfill_htlc. chan {chan.short_channel_id}. htlc_id {htlc_id}") self.logger.info(f"on_update_fulfill_htlc. chan {chan.short_channel_id}. htlc_id {htlc_id}")
chan.receive_htlc_settle(preimage, htlc_id) # TODO handle exc and maybe fail channel (e.g. bad htlc_id) chan.receive_htlc_settle(preimage, htlc_id) # TODO handle exc and maybe fail channel (e.g. bad htlc_id)
self.lnworker.save_preimage(payment_hash, preimage) self.lnworker.save_preimage(payment_hash, preimage)
@ -1103,10 +1102,10 @@ class Peer(Logger):
def on_update_add_htlc(self, chan: Channel, payload): def on_update_add_htlc(self, chan: Channel, payload):
payment_hash = payload["payment_hash"] payment_hash = payload["payment_hash"]
htlc_id = int.from_bytes(payload["id"], 'big') htlc_id = payload["id"]
self.logger.info(f"on_update_add_htlc. chan {chan.short_channel_id}. htlc_id {htlc_id}") self.logger.info(f"on_update_add_htlc. chan {chan.short_channel_id}. htlc_id {htlc_id}")
cltv_expiry = int.from_bytes(payload["cltv_expiry"], 'big') cltv_expiry = payload["cltv_expiry"]
amount_msat_htlc = int.from_bytes(payload["amount_msat"], 'big') amount_msat_htlc = payload["amount_msat"]
onion_packet = payload["onion_routing_packet"] onion_packet = payload["onion_routing_packet"]
if chan.get_state() != channel_states.OPEN: if chan.get_state() != channel_states.OPEN:
raise RemoteMisbehaving(f"received update_add_htlc while chan.get_state() != OPEN. state was {chan.get_state()}") raise RemoteMisbehaving(f"received update_add_htlc while chan.get_state() != OPEN. state was {chan.get_state()}")
@ -1258,7 +1257,7 @@ class Peer(Logger):
self.maybe_send_commitment(chan) self.maybe_send_commitment(chan)
def on_update_fee(self, chan: Channel, payload): def on_update_fee(self, chan: Channel, payload):
feerate = int.from_bytes(payload["feerate_per_kw"], "big") feerate = payload["feerate_per_kw"]
chan.update_fee(feerate, False) chan.update_fee(feerate, False)
async def maybe_update_fee(self, chan: Channel): async def maybe_update_fee(self, chan: Channel):
@ -1378,7 +1377,7 @@ class Peer(Logger):
while True: while True:
# FIXME: the remote SHOULD send closing_signed, but some don't. # FIXME: the remote SHOULD send closing_signed, but some don't.
cs_payload = await self.wait_for_message('closing_signed', chan.channel_id) cs_payload = await self.wait_for_message('closing_signed', chan.channel_id)
their_fee = int.from_bytes(cs_payload['fee_satoshis'], 'big') their_fee = cs_payload['fee_satoshis']
if their_fee > max_fee: if their_fee > max_fee:
raise Exception(f'the proposed fee exceeds the base fee of the latest commitment transaction {is_local, their_fee, max_fee}') raise Exception(f'the proposed fee exceeds the base fee of the latest commitment transaction {is_local, their_fee, max_fee}')
their_sig = cs_payload['signature'] their_sig = cs_payload['signature']

View file

@ -57,46 +57,45 @@ class Test_LNRouter(TestCaseForTestnet):
'bitcoin_key_1': b'\x02bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', 'bitcoin_key_2': b'\x02cccccccccccccccccccccccccccccccc', 'bitcoin_key_1': b'\x02bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', 'bitcoin_key_2': b'\x02cccccccccccccccccccccccccccccccc',
'short_channel_id': bfh('0000000000000001'), 'short_channel_id': bfh('0000000000000001'),
'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'chain_hash': BitcoinTestnet.rev_genesis_bytes(),
'len': b'\x00\x00', 'features': b''}, trusted=True) 'len': 0, 'features': b''}, trusted=True)
self.assertEqual(cdb.num_channels, 1) self.assertEqual(cdb.num_channels, 1)
cdb.add_channel_announcement({'node_id_1': b'\x02bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', 'node_id_2': b'\x02eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', cdb.add_channel_announcement({'node_id_1': b'\x02bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', 'node_id_2': b'\x02eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
'bitcoin_key_1': b'\x02bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', 'bitcoin_key_2': b'\x02eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', 'bitcoin_key_1': b'\x02bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', 'bitcoin_key_2': b'\x02eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
'short_channel_id': bfh('0000000000000002'), 'short_channel_id': bfh('0000000000000002'),
'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'chain_hash': BitcoinTestnet.rev_genesis_bytes(),
'len': b'\x00\x00', 'features': b''}, trusted=True) 'len': 0, 'features': b''}, trusted=True)
cdb.add_channel_announcement({'node_id_1': b'\x02aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'node_id_2': b'\x02bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', cdb.add_channel_announcement({'node_id_1': b'\x02aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'node_id_2': b'\x02bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',
'bitcoin_key_1': b'\x02aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'bitcoin_key_2': b'\x02bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', 'bitcoin_key_1': b'\x02aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'bitcoin_key_2': b'\x02bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',
'short_channel_id': bfh('0000000000000003'), 'short_channel_id': bfh('0000000000000003'),
'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'chain_hash': BitcoinTestnet.rev_genesis_bytes(),
'len': b'\x00\x00', 'features': b''}, trusted=True) 'len': 0, 'features': b''}, trusted=True)
cdb.add_channel_announcement({'node_id_1': b'\x02cccccccccccccccccccccccccccccccc', 'node_id_2': b'\x02dddddddddddddddddddddddddddddddd', cdb.add_channel_announcement({'node_id_1': b'\x02cccccccccccccccccccccccccccccccc', 'node_id_2': b'\x02dddddddddddddddddddddddddddddddd',
'bitcoin_key_1': b'\x02cccccccccccccccccccccccccccccccc', 'bitcoin_key_2': b'\x02dddddddddddddddddddddddddddddddd', 'bitcoin_key_1': b'\x02cccccccccccccccccccccccccccccccc', 'bitcoin_key_2': b'\x02dddddddddddddddddddddddddddddddd',
'short_channel_id': bfh('0000000000000004'), 'short_channel_id': bfh('0000000000000004'),
'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'chain_hash': BitcoinTestnet.rev_genesis_bytes(),
'len': b'\x00\x00', 'features': b''}, trusted=True) 'len': 0, 'features': b''}, trusted=True)
cdb.add_channel_announcement({'node_id_1': b'\x02dddddddddddddddddddddddddddddddd', 'node_id_2': b'\x02eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', cdb.add_channel_announcement({'node_id_1': b'\x02dddddddddddddddddddddddddddddddd', 'node_id_2': b'\x02eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
'bitcoin_key_1': b'\x02dddddddddddddddddddddddddddddddd', 'bitcoin_key_2': b'\x02eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', 'bitcoin_key_1': b'\x02dddddddddddddddddddddddddddddddd', 'bitcoin_key_2': b'\x02eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
'short_channel_id': bfh('0000000000000005'), 'short_channel_id': bfh('0000000000000005'),
'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'chain_hash': BitcoinTestnet.rev_genesis_bytes(),
'len': b'\x00\x00', 'features': b''}, trusted=True) 'len': 0, 'features': b''}, trusted=True)
cdb.add_channel_announcement({'node_id_1': b'\x02aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'node_id_2': b'\x02dddddddddddddddddddddddddddddddd', cdb.add_channel_announcement({'node_id_1': b'\x02aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'node_id_2': b'\x02dddddddddddddddddddddddddddddddd',
'bitcoin_key_1': b'\x02aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'bitcoin_key_2': b'\x02dddddddddddddddddddddddddddddddd', 'bitcoin_key_1': b'\x02aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'bitcoin_key_2': b'\x02dddddddddddddddddddddddddddddddd',
'short_channel_id': bfh('0000000000000006'), 'short_channel_id': bfh('0000000000000006'),
'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'chain_hash': BitcoinTestnet.rev_genesis_bytes(),
'len': b'\x00\x00', 'features': b''}, trusted=True) 'len': 0, 'features': b''}, trusted=True)
o = lambda i: i.to_bytes(8, "big") cdb.add_channel_update({'short_channel_id': bfh('0000000000000001'), 'message_flags': b'\x00', 'channel_flags': b'\x00', 'cltv_expiry_delta': 10, 'htlc_minimum_msat': 250, 'fee_base_msat': 100, 'fee_proportional_millionths': 150, 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': 0})
cdb.add_channel_update({'short_channel_id': bfh('0000000000000001'), 'message_flags': b'\x00', 'channel_flags': b'\x00', 'cltv_expiry_delta': o(10), 'htlc_minimum_msat': o(250), 'fee_base_msat': o(100), 'fee_proportional_millionths': o(150), 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': b'\x00\x00\x00\x00'}) cdb.add_channel_update({'short_channel_id': bfh('0000000000000001'), 'message_flags': b'\x00', 'channel_flags': b'\x01', 'cltv_expiry_delta': 10, 'htlc_minimum_msat': 250, 'fee_base_msat': 100, 'fee_proportional_millionths': 150, 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': 0})
cdb.add_channel_update({'short_channel_id': bfh('0000000000000001'), 'message_flags': b'\x00', 'channel_flags': b'\x01', 'cltv_expiry_delta': o(10), 'htlc_minimum_msat': o(250), 'fee_base_msat': o(100), 'fee_proportional_millionths': o(150), 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': b'\x00\x00\x00\x00'}) cdb.add_channel_update({'short_channel_id': bfh('0000000000000002'), 'message_flags': b'\x00', 'channel_flags': b'\x00', 'cltv_expiry_delta': 99, 'htlc_minimum_msat': 250, 'fee_base_msat': 100, 'fee_proportional_millionths': 150, 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': 0})
cdb.add_channel_update({'short_channel_id': bfh('0000000000000002'), 'message_flags': b'\x00', 'channel_flags': b'\x00', 'cltv_expiry_delta': o(99), 'htlc_minimum_msat': o(250), 'fee_base_msat': o(100), 'fee_proportional_millionths': o(150), 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': b'\x00\x00\x00\x00'}) cdb.add_channel_update({'short_channel_id': bfh('0000000000000002'), 'message_flags': b'\x00', 'channel_flags': b'\x01', 'cltv_expiry_delta': 10, 'htlc_minimum_msat': 250, 'fee_base_msat': 100, 'fee_proportional_millionths': 150, 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': 0})
cdb.add_channel_update({'short_channel_id': bfh('0000000000000002'), 'message_flags': b'\x00', 'channel_flags': b'\x01', 'cltv_expiry_delta': o(10), 'htlc_minimum_msat': o(250), 'fee_base_msat': o(100), 'fee_proportional_millionths': o(150), 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': b'\x00\x00\x00\x00'}) cdb.add_channel_update({'short_channel_id': bfh('0000000000000003'), 'message_flags': b'\x00', 'channel_flags': b'\x01', 'cltv_expiry_delta': 10, 'htlc_minimum_msat': 250, 'fee_base_msat': 100, 'fee_proportional_millionths': 150, 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': 0})
cdb.add_channel_update({'short_channel_id': bfh('0000000000000003'), 'message_flags': b'\x00', 'channel_flags': b'\x01', 'cltv_expiry_delta': o(10), 'htlc_minimum_msat': o(250), 'fee_base_msat': o(100), 'fee_proportional_millionths': o(150), 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': b'\x00\x00\x00\x00'}) cdb.add_channel_update({'short_channel_id': bfh('0000000000000003'), 'message_flags': b'\x00', 'channel_flags': b'\x00', 'cltv_expiry_delta': 10, 'htlc_minimum_msat': 250, 'fee_base_msat': 100, 'fee_proportional_millionths': 150, 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': 0})
cdb.add_channel_update({'short_channel_id': bfh('0000000000000003'), 'message_flags': b'\x00', 'channel_flags': b'\x00', 'cltv_expiry_delta': o(10), 'htlc_minimum_msat': o(250), 'fee_base_msat': o(100), 'fee_proportional_millionths': o(150), 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': b'\x00\x00\x00\x00'}) cdb.add_channel_update({'short_channel_id': bfh('0000000000000004'), 'message_flags': b'\x00', 'channel_flags': b'\x01', 'cltv_expiry_delta': 10, 'htlc_minimum_msat': 250, 'fee_base_msat': 100, 'fee_proportional_millionths': 150, 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': 0})
cdb.add_channel_update({'short_channel_id': bfh('0000000000000004'), 'message_flags': b'\x00', 'channel_flags': b'\x01', 'cltv_expiry_delta': o(10), 'htlc_minimum_msat': o(250), 'fee_base_msat': o(100), 'fee_proportional_millionths': o(150), 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': b'\x00\x00\x00\x00'}) cdb.add_channel_update({'short_channel_id': bfh('0000000000000004'), 'message_flags': b'\x00', 'channel_flags': b'\x00', 'cltv_expiry_delta': 10, 'htlc_minimum_msat': 250, 'fee_base_msat': 100, 'fee_proportional_millionths': 150, 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': 0})
cdb.add_channel_update({'short_channel_id': bfh('0000000000000004'), 'message_flags': b'\x00', 'channel_flags': b'\x00', 'cltv_expiry_delta': o(10), 'htlc_minimum_msat': o(250), 'fee_base_msat': o(100), 'fee_proportional_millionths': o(150), 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': b'\x00\x00\x00\x00'}) cdb.add_channel_update({'short_channel_id': bfh('0000000000000005'), 'message_flags': b'\x00', 'channel_flags': b'\x01', 'cltv_expiry_delta': 10, 'htlc_minimum_msat': 250, 'fee_base_msat': 100, 'fee_proportional_millionths': 150, 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': 0})
cdb.add_channel_update({'short_channel_id': bfh('0000000000000005'), 'message_flags': b'\x00', 'channel_flags': b'\x01', 'cltv_expiry_delta': o(10), 'htlc_minimum_msat': o(250), 'fee_base_msat': o(100), 'fee_proportional_millionths': o(150), 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': b'\x00\x00\x00\x00'}) cdb.add_channel_update({'short_channel_id': bfh('0000000000000005'), 'message_flags': b'\x00', 'channel_flags': b'\x00', 'cltv_expiry_delta': 10, 'htlc_minimum_msat': 250, 'fee_base_msat': 100, 'fee_proportional_millionths': 999, 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': 0})
cdb.add_channel_update({'short_channel_id': bfh('0000000000000005'), 'message_flags': b'\x00', 'channel_flags': b'\x00', 'cltv_expiry_delta': o(10), 'htlc_minimum_msat': o(250), 'fee_base_msat': o(100), 'fee_proportional_millionths': o(999), 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': b'\x00\x00\x00\x00'}) cdb.add_channel_update({'short_channel_id': bfh('0000000000000006'), 'message_flags': b'\x00', 'channel_flags': b'\x00', 'cltv_expiry_delta': 10, 'htlc_minimum_msat': 250, 'fee_base_msat': 100, 'fee_proportional_millionths': 99999999, 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': 0})
cdb.add_channel_update({'short_channel_id': bfh('0000000000000006'), 'message_flags': b'\x00', 'channel_flags': b'\x00', 'cltv_expiry_delta': o(10), 'htlc_minimum_msat': o(250), 'fee_base_msat': o(100), 'fee_proportional_millionths': o(99999999), 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': b'\x00\x00\x00\x00'}) cdb.add_channel_update({'short_channel_id': bfh('0000000000000006'), 'message_flags': b'\x00', 'channel_flags': b'\x01', 'cltv_expiry_delta': 10, 'htlc_minimum_msat': 250, 'fee_base_msat': 100, 'fee_proportional_millionths': 150, 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': 0})
cdb.add_channel_update({'short_channel_id': bfh('0000000000000006'), 'message_flags': b'\x00', 'channel_flags': b'\x01', 'cltv_expiry_delta': o(10), 'htlc_minimum_msat': o(250), 'fee_base_msat': o(100), 'fee_proportional_millionths': o(150), 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': b'\x00\x00\x00\x00'})
path = path_finder.find_path_for_payment(b'\x02aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', b'\x02eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', 100000) path = path_finder.find_path_for_payment(b'\x02aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', b'\x02eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', 100000)
self.assertEqual([(b'\x02bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', b'\x00\x00\x00\x00\x00\x00\x00\x03'), self.assertEqual([(b'\x02bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', b'\x00\x00\x00\x00\x00\x00\x00\x03'),
(b'\x02eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', b'\x00\x00\x00\x00\x00\x00\x00\x02'), (b'\x02eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', b'\x00\x00\x00\x00\x00\x00\x00\x02'),