URI: 
       tlnutil.py - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
       tlnutil.py (57914B)
       ---
            1 # Copyright (C) 2018 The Electrum developers
            2 # Distributed under the MIT software license, see the accompanying
            3 # file LICENCE or http://www.opensource.org/licenses/mit-license.php
            4 
            5 from enum import IntFlag, IntEnum
            6 import enum
            7 import json
            8 from collections import namedtuple, defaultdict
            9 from typing import NamedTuple, List, Tuple, Mapping, Optional, TYPE_CHECKING, Union, Dict, Set, Sequence
           10 import re
           11 import time
           12 import attr
           13 from aiorpcx import NetAddress
           14 
           15 from .util import bfh, bh2u, inv_dict, UserFacingException
           16 from .util import list_enabled_bits
           17 from .crypto import sha256
           18 from .transaction import (Transaction, PartialTransaction, PartialTxInput, TxOutpoint,
           19                           PartialTxOutput, opcodes, TxOutput)
           20 from .ecc import CURVE_ORDER, sig_string_from_der_sig, ECPubkey, string_to_number
           21 from . import ecc, bitcoin, crypto, transaction
           22 from .bitcoin import (push_script, redeem_script_to_address, address_to_script,
           23                       construct_witness, construct_script)
           24 from . import segwit_addr
           25 from .i18n import _
           26 from .lnaddr import lndecode
           27 from .bip32 import BIP32Node, BIP32_PRIME
           28 from .transaction import BCDataStream
           29 
           30 if TYPE_CHECKING:
           31     from .lnchannel import Channel, AbstractChannel
           32     from .lnrouter import LNPaymentRoute
           33     from .lnonion import OnionRoutingFailureMessage
           34 
           35 
           36 # defined in BOLT-03:
           37 HTLC_TIMEOUT_WEIGHT = 663
           38 HTLC_SUCCESS_WEIGHT = 703
           39 COMMITMENT_TX_WEIGHT = 724
           40 HTLC_OUTPUT_WEIGHT = 172
           41 
           42 LN_MAX_FUNDING_SAT = pow(2, 24) - 1
           43 LN_MAX_HTLC_VALUE_MSAT = pow(2, 32) - 1
           44 
           45 # dummy address for fee estimation of funding tx
           46 def ln_dummy_address():
           47     return redeem_script_to_address('p2wsh', '')
           48 
           49 from .json_db import StoredObject
           50 
           51 
           52 def channel_id_from_funding_tx(funding_txid: str, funding_index: int) -> Tuple[bytes, bytes]:
           53     funding_txid_bytes = bytes.fromhex(funding_txid)[::-1]
           54     i = int.from_bytes(funding_txid_bytes, 'big') ^ funding_index
           55     return i.to_bytes(32, 'big'), funding_txid_bytes
           56 
           57 hex_to_bytes = lambda v: v if isinstance(v, bytes) else bytes.fromhex(v) if v is not None else None
           58 json_to_keypair = lambda v: v if isinstance(v, OnlyPubkeyKeypair) else Keypair(**v) if len(v)==2 else OnlyPubkeyKeypair(**v)
           59 
           60 
           61 @attr.s
           62 class OnlyPubkeyKeypair(StoredObject):
           63     pubkey = attr.ib(type=bytes, converter=hex_to_bytes)
           64 
           65 @attr.s
           66 class Keypair(OnlyPubkeyKeypair):
           67     privkey = attr.ib(type=bytes, converter=hex_to_bytes)
           68 
           69 @attr.s
           70 class Config(StoredObject):
           71     # shared channel config fields
           72     payment_basepoint = attr.ib(type=OnlyPubkeyKeypair, converter=json_to_keypair)
           73     multisig_key = attr.ib(type=OnlyPubkeyKeypair, converter=json_to_keypair)
           74     htlc_basepoint = attr.ib(type=OnlyPubkeyKeypair, converter=json_to_keypair)
           75     delayed_basepoint = attr.ib(type=OnlyPubkeyKeypair, converter=json_to_keypair)
           76     revocation_basepoint = attr.ib(type=OnlyPubkeyKeypair, converter=json_to_keypair)
           77     to_self_delay = attr.ib(type=int)  # applies to OTHER ctx
           78     dust_limit_sat = attr.ib(type=int)  # applies to SAME ctx
           79     max_htlc_value_in_flight_msat = attr.ib(type=int)  # max val of INCOMING htlcs
           80     max_accepted_htlcs = attr.ib(type=int)  # max num of INCOMING htlcs
           81     initial_msat = attr.ib(type=int)
           82     reserve_sat = attr.ib(type=int)  # applies to OTHER ctx
           83     htlc_minimum_msat = attr.ib(type=int)  # smallest value for INCOMING htlc
           84     upfront_shutdown_script = attr.ib(type=bytes, converter=hex_to_bytes)
           85 
           86     def validate_params(self, *, funding_sat: int) -> None:
           87         conf_name = type(self).__name__
           88         for key in (
           89                 self.payment_basepoint,
           90                 self.multisig_key,
           91                 self.htlc_basepoint,
           92                 self.delayed_basepoint,
           93                 self.revocation_basepoint
           94         ):
           95             if not (len(key.pubkey) == 33 and ecc.ECPubkey.is_pubkey_bytes(key.pubkey)):
           96                 raise Exception(f"{conf_name}. invalid pubkey in channel config")
           97         if self.reserve_sat < self.dust_limit_sat:
           98             raise Exception(f"{conf_name}. MUST set channel_reserve_satoshis greater than or equal to dust_limit_satoshis")
           99         # technically this could be using the lower DUST_LIMIT_DEFAULT_SAT_SEGWIT
          100         # but other implementations are checking against this value too; also let's be conservative
          101         if self.dust_limit_sat < bitcoin.DUST_LIMIT_DEFAULT_SAT_LEGACY:
          102             raise Exception(f"{conf_name}. dust limit too low: {self.dust_limit_sat} sat")
          103         if self.reserve_sat > funding_sat // 100:
          104             raise Exception(f"{conf_name}. reserve too high: {self.reserve_sat}, funding_sat: {funding_sat}")
          105         if self.htlc_minimum_msat > 1_000:
          106             raise Exception(f"{conf_name}. htlc_minimum_msat too high: {self.htlc_minimum_msat} msat")
          107         HTLC_MINIMUM_MSAT_MIN = 0  # should be at least 1 really, but apparently some nodes are sending zero...
          108         if self.htlc_minimum_msat < HTLC_MINIMUM_MSAT_MIN:
          109             raise Exception(f"{conf_name}. htlc_minimum_msat too low: {self.htlc_minimum_msat} msat < {HTLC_MINIMUM_MSAT_MIN}")
          110         if self.max_accepted_htlcs < 1:
          111             raise Exception(f"{conf_name}. max_accepted_htlcs too low: {self.max_accepted_htlcs}")
          112         if self.max_accepted_htlcs > 483:
          113             raise Exception(f"{conf_name}. max_accepted_htlcs too high: {self.max_accepted_htlcs}")
          114         if self.to_self_delay > MAXIMUM_REMOTE_TO_SELF_DELAY_ACCEPTED:
          115             raise Exception(f"{conf_name}. to_self_delay too high: {self.to_self_delay} > {MAXIMUM_REMOTE_TO_SELF_DELAY_ACCEPTED}")
          116         if self.max_htlc_value_in_flight_msat < min(1000 * funding_sat, 100_000_000):
          117             raise Exception(f"{conf_name}. max_htlc_value_in_flight_msat is too small: {self.max_htlc_value_in_flight_msat}")
          118 
          119 
          120 @attr.s
          121 class LocalConfig(Config):
          122     channel_seed = attr.ib(type=bytes, converter=hex_to_bytes)  # type: Optional[bytes]
          123     funding_locked_received = attr.ib(type=bool)
          124     was_announced = attr.ib(type=bool)
          125     current_commitment_signature = attr.ib(type=bytes, converter=hex_to_bytes)
          126     current_htlc_signatures = attr.ib(type=bytes, converter=hex_to_bytes)
          127     per_commitment_secret_seed = attr.ib(type=bytes, converter=hex_to_bytes)
          128 
          129     @classmethod
          130     def from_seed(self, **kwargs):
          131         channel_seed = kwargs['channel_seed']
          132         static_remotekey = kwargs.pop('static_remotekey')
          133         node = BIP32Node.from_rootseed(channel_seed, xtype='standard')
          134         keypair_generator = lambda family: generate_keypair(node, family)
          135         kwargs['per_commitment_secret_seed'] = keypair_generator(LnKeyFamily.REVOCATION_ROOT).privkey
          136         kwargs['multisig_key'] = keypair_generator(LnKeyFamily.MULTISIG)
          137         kwargs['htlc_basepoint'] = keypair_generator(LnKeyFamily.HTLC_BASE)
          138         kwargs['delayed_basepoint'] = keypair_generator(LnKeyFamily.DELAY_BASE)
          139         kwargs['revocation_basepoint'] = keypair_generator(LnKeyFamily.REVOCATION_BASE)
          140         kwargs['payment_basepoint'] = OnlyPubkeyKeypair(static_remotekey) if static_remotekey else keypair_generator(LnKeyFamily.PAYMENT_BASE)
          141         return LocalConfig(**kwargs)
          142 
          143     def validate_params(self, *, funding_sat: int) -> None:
          144         conf_name = type(self).__name__
          145         # run base checks regardless whether LOCAL/REMOTE config
          146         super().validate_params(funding_sat=funding_sat)
          147         # run some stricter checks on LOCAL config (make sure we ourselves do the sane thing,
          148         # even if we are lenient with REMOTE for compatibility reasons)
          149         HTLC_MINIMUM_MSAT_MIN = 1
          150         if self.htlc_minimum_msat < HTLC_MINIMUM_MSAT_MIN:
          151             raise Exception(f"{conf_name}. htlc_minimum_msat too low: {self.htlc_minimum_msat} msat < {HTLC_MINIMUM_MSAT_MIN}")
          152 
          153 @attr.s
          154 class RemoteConfig(Config):
          155     next_per_commitment_point = attr.ib(type=bytes, converter=hex_to_bytes)
          156     current_per_commitment_point = attr.ib(default=None, type=bytes, converter=hex_to_bytes)
          157 
          158 @attr.s
          159 class FeeUpdate(StoredObject):
          160     rate = attr.ib(type=int)  # in sat/kw
          161     ctn_local = attr.ib(default=None, type=int)
          162     ctn_remote = attr.ib(default=None, type=int)
          163 
          164 @attr.s
          165 class ChannelConstraints(StoredObject):
          166     capacity = attr.ib(type=int)  # in sat
          167     is_initiator = attr.ib(type=bool)  # note: sometimes also called "funder"
          168     funding_txn_minimum_depth = attr.ib(type=int)
          169 
          170 
          171 CHANNEL_BACKUP_VERSION = 0
          172 @attr.s
          173 class ChannelBackupStorage(StoredObject):
          174     node_id = attr.ib(type=bytes, converter=hex_to_bytes)
          175     privkey = attr.ib(type=bytes, converter=hex_to_bytes)
          176     funding_txid = attr.ib(type=str)
          177     funding_index = attr.ib(type=int, converter=int)
          178     funding_address = attr.ib(type=str)
          179     host = attr.ib(type=str)
          180     port = attr.ib(type=int, converter=int)
          181     is_initiator = attr.ib(type=bool)
          182     channel_seed = attr.ib(type=bytes, converter=hex_to_bytes)
          183     local_delay = attr.ib(type=int, converter=int)
          184     remote_delay = attr.ib(type=int, converter=int)
          185     remote_payment_pubkey = attr.ib(type=bytes, converter=hex_to_bytes)
          186     remote_revocation_pubkey = attr.ib(type=bytes, converter=hex_to_bytes)
          187 
          188     def funding_outpoint(self):
          189         return Outpoint(self.funding_txid, self.funding_index)
          190 
          191     def channel_id(self):
          192         chan_id, _ = channel_id_from_funding_tx(self.funding_txid, self.funding_index)
          193         return chan_id
          194 
          195     def to_bytes(self) -> bytes:
          196         vds = BCDataStream()
          197         vds.write_int16(CHANNEL_BACKUP_VERSION)
          198         vds.write_boolean(self.is_initiator)
          199         vds.write_bytes(self.privkey, 32)
          200         vds.write_bytes(self.channel_seed, 32)
          201         vds.write_bytes(self.node_id, 33)
          202         vds.write_bytes(bfh(self.funding_txid), 32)
          203         vds.write_int16(self.funding_index)
          204         vds.write_string(self.funding_address)
          205         vds.write_bytes(self.remote_payment_pubkey, 33)
          206         vds.write_bytes(self.remote_revocation_pubkey, 33)
          207         vds.write_int16(self.local_delay)
          208         vds.write_int16(self.remote_delay)
          209         vds.write_string(self.host)
          210         vds.write_int16(self.port)
          211         return bytes(vds.input)
          212 
          213     @staticmethod
          214     def from_bytes(s):
          215         vds = BCDataStream()
          216         vds.write(s)
          217         version = vds.read_int16()
          218         if version != CHANNEL_BACKUP_VERSION:
          219             raise Exception(f"unknown version for channel backup: {version}")
          220         return ChannelBackupStorage(
          221             is_initiator = vds.read_boolean(),
          222             privkey = vds.read_bytes(32).hex(),
          223             channel_seed = vds.read_bytes(32).hex(),
          224             node_id = vds.read_bytes(33).hex(),
          225             funding_txid = vds.read_bytes(32).hex(),
          226             funding_index = vds.read_int16(),
          227             funding_address = vds.read_string(),
          228             remote_payment_pubkey = vds.read_bytes(33).hex(),
          229             remote_revocation_pubkey = vds.read_bytes(33).hex(),
          230             local_delay = vds.read_int16(),
          231             remote_delay = vds.read_int16(),
          232             host = vds.read_string(),
          233             port = vds.read_int16())
          234 
          235 
          236 
          237 class ScriptHtlc(NamedTuple):
          238     redeem_script: bytes
          239     htlc: 'UpdateAddHtlc'
          240 
          241 
          242 # FIXME duplicate of TxOutpoint in transaction.py??
          243 @attr.s
          244 class Outpoint(StoredObject):
          245     txid = attr.ib(type=str)
          246     output_index = attr.ib(type=int)
          247 
          248     def to_str(self):
          249         return "{}:{}".format(self.txid, self.output_index)
          250 
          251 
          252 class HtlcLog(NamedTuple):
          253     success: bool
          254     amount_msat: int  # amount for receiver (e.g. from invoice)
          255     route: Optional['LNPaymentRoute'] = None
          256     preimage: Optional[bytes] = None
          257     error_bytes: Optional[bytes] = None
          258     failure_msg: Optional['OnionRoutingFailureMessage'] = None
          259     sender_idx: Optional[int] = None
          260 
          261     def formatted_tuple(self):
          262         route = self.route
          263         route_str = '%d'%len(route)
          264         short_channel_id = None
          265         if not self.success:
          266             sender_idx = self.sender_idx
          267             failure_msg = self.failure_msg
          268             if sender_idx is not None:
          269                 try:
          270                     short_channel_id = route[sender_idx + 1].short_channel_id
          271                 except IndexError:
          272                     # payment destination reported error
          273                     short_channel_id = _("Destination node")
          274             message = failure_msg.code_name()
          275         else:
          276             short_channel_id = route[-1].short_channel_id
          277             message = _('Success')
          278         chan_str = str(short_channel_id) if short_channel_id else _("Unknown")
          279         return route_str, chan_str, message
          280 
          281 
          282 class LightningError(Exception): pass
          283 class LightningPeerConnectionClosed(LightningError): pass
          284 class UnableToDeriveSecret(LightningError): pass
          285 class HandshakeFailed(LightningError): pass
          286 class ConnStringFormatError(LightningError): pass
          287 class RemoteMisbehaving(LightningError): pass
          288 class UpfrontShutdownScriptViolation(RemoteMisbehaving): pass
          289 
          290 class NotFoundChanAnnouncementForUpdate(Exception): pass
          291 
          292 class PaymentFailure(UserFacingException): pass
          293 class NoPathFound(PaymentFailure):
          294     def __str__(self):
          295         return _('No path found')
          296 
          297 # TODO make some of these values configurable?
          298 REDEEM_AFTER_DOUBLE_SPENT_DELAY = 30
          299 
          300 CHANNEL_OPENING_TIMEOUT = 24*60*60
          301 
          302 MIN_FUNDING_SAT = 200_000
          303 
          304 ##### CLTV-expiry-delta-related values
          305 # see https://github.com/lightningnetwork/lightning-rfc/blob/master/02-peer-protocol.md#cltv_expiry_delta-selection
          306 
          307 # the minimum cltv_expiry accepted for newly received HTLCs
          308 # note: when changing, consider Blockchain.is_tip_stale()
          309 MIN_FINAL_CLTV_EXPIRY_ACCEPTED = 144
          310 # set it a tiny bit higher for invoices as blocks could get mined
          311 # during forward path of payment
          312 MIN_FINAL_CLTV_EXPIRY_FOR_INVOICE = MIN_FINAL_CLTV_EXPIRY_ACCEPTED + 3
          313 
          314 # the deadline for offered HTLCs:
          315 # the deadline after which the channel has to be failed and timed out on-chain
          316 NBLOCK_DEADLINE_AFTER_EXPIRY_FOR_OFFERED_HTLCS = 1
          317 
          318 # the deadline for received HTLCs this node has fulfilled:
          319 # the deadline after which the channel has to be failed and the HTLC fulfilled on-chain before its cltv_expiry
          320 NBLOCK_DEADLINE_BEFORE_EXPIRY_FOR_RECEIVED_HTLCS = 72
          321 
          322 NBLOCK_CLTV_EXPIRY_TOO_FAR_INTO_FUTURE = 28 * 144
          323 
          324 MAXIMUM_REMOTE_TO_SELF_DELAY_ACCEPTED = 2016
          325 
          326 class RevocationStore:
          327     # closely based on code in lightningnetwork/lnd
          328 
          329     START_INDEX = 2 ** 48 - 1
          330 
          331     def __init__(self, storage):
          332         if len(storage) == 0:
          333             storage['index'] = self.START_INDEX
          334             storage['buckets'] = {}
          335         self.storage = storage
          336         self.buckets = storage['buckets']
          337 
          338     def add_next_entry(self, hsh):
          339         index = self.storage['index']
          340         new_element = ShachainElement(index=index, secret=hsh)
          341         bucket = count_trailing_zeros(index)
          342         for i in range(0, bucket):
          343             this_bucket = self.buckets[i]
          344             e = shachain_derive(new_element, this_bucket.index)
          345             if e != this_bucket:
          346                 raise Exception("hash is not derivable: {} {} {}".format(bh2u(e.secret), bh2u(this_bucket.secret), this_bucket.index))
          347         self.buckets[bucket] = new_element
          348         self.storage['index'] = index - 1
          349 
          350     def retrieve_secret(self, index: int) -> bytes:
          351         assert index <= self.START_INDEX, index
          352         for i in range(0, 49):
          353             bucket = self.buckets.get(i)
          354             if bucket is None:
          355                 raise UnableToDeriveSecret()
          356             try:
          357                 element = shachain_derive(bucket, index)
          358             except UnableToDeriveSecret:
          359                 continue
          360             return element.secret
          361         raise UnableToDeriveSecret()
          362 
          363     def __eq__(self, o):
          364         return type(o) is RevocationStore and self.serialize() == o.serialize()
          365 
          366     def __hash__(self):
          367         return hash(json.dumps(self.serialize(), sort_keys=True))
          368 
          369 
          370 def count_trailing_zeros(index):
          371     """ BOLT-03 (where_to_put_secret) """
          372     try:
          373         return list(reversed(bin(index)[2:])).index("1")
          374     except ValueError:
          375         return 48
          376 
          377 def shachain_derive(element, to_index):
          378     def get_prefix(index, pos):
          379         mask = (1 << 64) - 1 - ((1 << pos) - 1)
          380         return index & mask
          381     from_index = element.index
          382     zeros = count_trailing_zeros(from_index)
          383     if from_index != get_prefix(to_index, zeros):
          384         raise UnableToDeriveSecret("prefixes are different; index not derivable")
          385     return ShachainElement(
          386         get_per_commitment_secret_from_seed(element.secret, to_index, zeros),
          387         to_index)
          388 
          389 ShachainElement = namedtuple("ShachainElement", ["secret", "index"])
          390 ShachainElement.__str__ = lambda self: "ShachainElement(" + bh2u(self.secret) + "," + str(self.index) + ")"
          391 
          392 def get_per_commitment_secret_from_seed(seed: bytes, i: int, bits: int = 48) -> bytes:
          393     """Generate per commitment secret."""
          394     per_commitment_secret = bytearray(seed)
          395     for bitindex in range(bits - 1, -1, -1):
          396         mask = 1 << bitindex
          397         if i & mask:
          398             per_commitment_secret[bitindex // 8] ^= 1 << (bitindex % 8)
          399             per_commitment_secret = bytearray(sha256(per_commitment_secret))
          400     bajts = bytes(per_commitment_secret)
          401     return bajts
          402 
          403 def secret_to_pubkey(secret: int) -> bytes:
          404     assert type(secret) is int
          405     return ecc.ECPrivkey.from_secret_scalar(secret).get_public_key_bytes(compressed=True)
          406 
          407 def privkey_to_pubkey(priv: bytes) -> bytes:
          408     return ecc.ECPrivkey(priv[:32]).get_public_key_bytes()
          409 
          410 def derive_pubkey(basepoint: bytes, per_commitment_point: bytes) -> bytes:
          411     p = ecc.ECPubkey(basepoint) + ecc.GENERATOR * ecc.string_to_number(sha256(per_commitment_point + basepoint))
          412     return p.get_public_key_bytes()
          413 
          414 def derive_privkey(secret: int, per_commitment_point: bytes) -> int:
          415     assert type(secret) is int
          416     basepoint_bytes = secret_to_pubkey(secret)
          417     basepoint = secret + ecc.string_to_number(sha256(per_commitment_point + basepoint_bytes))
          418     basepoint %= CURVE_ORDER
          419     return basepoint
          420 
          421 def derive_blinded_pubkey(basepoint: bytes, per_commitment_point: bytes) -> bytes:
          422     k1 = ecc.ECPubkey(basepoint) * ecc.string_to_number(sha256(basepoint + per_commitment_point))
          423     k2 = ecc.ECPubkey(per_commitment_point) * ecc.string_to_number(sha256(per_commitment_point + basepoint))
          424     return (k1 + k2).get_public_key_bytes()
          425 
          426 def derive_blinded_privkey(basepoint_secret: bytes, per_commitment_secret: bytes) -> bytes:
          427     basepoint = ecc.ECPrivkey(basepoint_secret).get_public_key_bytes(compressed=True)
          428     per_commitment_point = ecc.ECPrivkey(per_commitment_secret).get_public_key_bytes(compressed=True)
          429     k1 = ecc.string_to_number(basepoint_secret) * ecc.string_to_number(sha256(basepoint + per_commitment_point))
          430     k2 = ecc.string_to_number(per_commitment_secret) * ecc.string_to_number(sha256(per_commitment_point + basepoint))
          431     sum = (k1 + k2) % ecc.CURVE_ORDER
          432     return int.to_bytes(sum, length=32, byteorder='big', signed=False)
          433 
          434 
          435 def make_htlc_tx_output(amount_msat, local_feerate, revocationpubkey, local_delayedpubkey, success, to_self_delay):
          436     assert type(amount_msat) is int
          437     assert type(local_feerate) is int
          438     assert type(revocationpubkey) is bytes
          439     assert type(local_delayedpubkey) is bytes
          440     script = bfh(construct_script([
          441         opcodes.OP_IF,
          442         revocationpubkey,
          443         opcodes.OP_ELSE,
          444         to_self_delay,
          445         opcodes.OP_CHECKSEQUENCEVERIFY,
          446         opcodes.OP_DROP,
          447         local_delayedpubkey,
          448         opcodes.OP_ENDIF,
          449         opcodes.OP_CHECKSIG,
          450     ]))
          451 
          452     p2wsh = bitcoin.redeem_script_to_address('p2wsh', bh2u(script))
          453     weight = HTLC_SUCCESS_WEIGHT if success else HTLC_TIMEOUT_WEIGHT
          454     fee = local_feerate * weight
          455     fee = fee // 1000 * 1000
          456     final_amount_sat = (amount_msat - fee) // 1000
          457     assert final_amount_sat > 0, final_amount_sat
          458     output = PartialTxOutput.from_address_and_value(p2wsh, final_amount_sat)
          459     return script, output
          460 
          461 def make_htlc_tx_witness(remotehtlcsig: bytes, localhtlcsig: bytes,
          462                          payment_preimage: bytes, witness_script: bytes) -> bytes:
          463     assert type(remotehtlcsig) is bytes
          464     assert type(localhtlcsig) is bytes
          465     assert type(payment_preimage) is bytes
          466     assert type(witness_script) is bytes
          467     return bfh(construct_witness([0, remotehtlcsig, localhtlcsig, payment_preimage, witness_script]))
          468 
          469 def make_htlc_tx_inputs(htlc_output_txid: str, htlc_output_index: int,
          470                         amount_msat: int, witness_script: str) -> List[PartialTxInput]:
          471     assert type(htlc_output_txid) is str
          472     assert type(htlc_output_index) is int
          473     assert type(amount_msat) is int
          474     assert type(witness_script) is str
          475     txin = PartialTxInput(prevout=TxOutpoint(txid=bfh(htlc_output_txid), out_idx=htlc_output_index),
          476                           nsequence=0)
          477     txin.witness_script = bfh(witness_script)
          478     txin.script_sig = b''
          479     txin._trusted_value_sats = amount_msat // 1000
          480     c_inputs = [txin]
          481     return c_inputs
          482 
          483 def make_htlc_tx(*, cltv_expiry: int, inputs: List[PartialTxInput], output: PartialTxOutput) -> PartialTransaction:
          484     assert type(cltv_expiry) is int
          485     c_outputs = [output]
          486     tx = PartialTransaction.from_io(inputs, c_outputs, locktime=cltv_expiry, version=2)
          487     return tx
          488 
          489 def make_offered_htlc(revocation_pubkey: bytes, remote_htlcpubkey: bytes,
          490                       local_htlcpubkey: bytes, payment_hash: bytes) -> bytes:
          491     assert type(revocation_pubkey) is bytes
          492     assert type(remote_htlcpubkey) is bytes
          493     assert type(local_htlcpubkey) is bytes
          494     assert type(payment_hash) is bytes
          495     script = bfh(construct_script([
          496         opcodes.OP_DUP,
          497         opcodes.OP_HASH160,
          498         bitcoin.hash_160(revocation_pubkey),
          499         opcodes.OP_EQUAL,
          500         opcodes.OP_IF,
          501         opcodes.OP_CHECKSIG,
          502         opcodes.OP_ELSE,
          503         remote_htlcpubkey,
          504         opcodes.OP_SWAP,
          505         opcodes.OP_SIZE,
          506         32,
          507         opcodes.OP_EQUAL,
          508         opcodes.OP_NOTIF,
          509         opcodes.OP_DROP,
          510         2,
          511         opcodes.OP_SWAP,
          512         local_htlcpubkey,
          513         2,
          514         opcodes.OP_CHECKMULTISIG,
          515         opcodes.OP_ELSE,
          516         opcodes.OP_HASH160,
          517         crypto.ripemd(payment_hash),
          518         opcodes.OP_EQUALVERIFY,
          519         opcodes.OP_CHECKSIG,
          520         opcodes.OP_ENDIF,
          521         opcodes.OP_ENDIF,
          522     ]))
          523     return script
          524 
          525 def make_received_htlc(revocation_pubkey: bytes, remote_htlcpubkey: bytes,
          526                        local_htlcpubkey: bytes, payment_hash: bytes, cltv_expiry: int) -> bytes:
          527     for i in [revocation_pubkey, remote_htlcpubkey, local_htlcpubkey, payment_hash]:
          528         assert type(i) is bytes
          529     assert type(cltv_expiry) is int
          530 
          531     script = bfh(construct_script([
          532         opcodes.OP_DUP,
          533         opcodes.OP_HASH160,
          534         bitcoin.hash_160(revocation_pubkey),
          535         opcodes.OP_EQUAL,
          536         opcodes.OP_IF,
          537         opcodes.OP_CHECKSIG,
          538         opcodes.OP_ELSE,
          539         remote_htlcpubkey,
          540         opcodes.OP_SWAP,
          541         opcodes.OP_SIZE,
          542         32,
          543         opcodes.OP_EQUAL,
          544         opcodes.OP_IF,
          545         opcodes.OP_HASH160,
          546         crypto.ripemd(payment_hash),
          547         opcodes.OP_EQUALVERIFY,
          548         2,
          549         opcodes.OP_SWAP,
          550         local_htlcpubkey,
          551         2,
          552         opcodes.OP_CHECKMULTISIG,
          553         opcodes.OP_ELSE,
          554         opcodes.OP_DROP,
          555         cltv_expiry,
          556         opcodes.OP_CHECKLOCKTIMEVERIFY,
          557         opcodes.OP_DROP,
          558         opcodes.OP_CHECKSIG,
          559         opcodes.OP_ENDIF,
          560         opcodes.OP_ENDIF,
          561     ]))
          562     return script
          563 
          564 def make_htlc_output_witness_script(is_received_htlc: bool, remote_revocation_pubkey: bytes, remote_htlc_pubkey: bytes,
          565                                     local_htlc_pubkey: bytes, payment_hash: bytes, cltv_expiry: Optional[int]) -> bytes:
          566     if is_received_htlc:
          567         return make_received_htlc(revocation_pubkey=remote_revocation_pubkey,
          568                                   remote_htlcpubkey=remote_htlc_pubkey,
          569                                   local_htlcpubkey=local_htlc_pubkey,
          570                                   payment_hash=payment_hash,
          571                                   cltv_expiry=cltv_expiry)
          572     else:
          573         return make_offered_htlc(revocation_pubkey=remote_revocation_pubkey,
          574                                  remote_htlcpubkey=remote_htlc_pubkey,
          575                                  local_htlcpubkey=local_htlc_pubkey,
          576                                  payment_hash=payment_hash)
          577 
          578 
          579 def get_ordered_channel_configs(chan: 'AbstractChannel', for_us: bool) -> Tuple[Union[LocalConfig, RemoteConfig],
          580                                                                                 Union[LocalConfig, RemoteConfig]]:
          581     conf =       chan.config[LOCAL] if     for_us else chan.config[REMOTE]
          582     other_conf = chan.config[LOCAL] if not for_us else chan.config[REMOTE]
          583     return conf, other_conf
          584 
          585 
          586 def possible_output_idxs_of_htlc_in_ctx(*, chan: 'Channel', pcp: bytes, subject: 'HTLCOwner',
          587                                         htlc_direction: 'Direction', ctx: Transaction,
          588                                         htlc: 'UpdateAddHtlc') -> Set[int]:
          589     amount_msat, cltv_expiry, payment_hash = htlc.amount_msat, htlc.cltv_expiry, htlc.payment_hash
          590     for_us = subject == LOCAL
          591     conf, other_conf = get_ordered_channel_configs(chan=chan, for_us=for_us)
          592 
          593     other_revocation_pubkey = derive_blinded_pubkey(other_conf.revocation_basepoint.pubkey, pcp)
          594     other_htlc_pubkey = derive_pubkey(other_conf.htlc_basepoint.pubkey, pcp)
          595     htlc_pubkey = derive_pubkey(conf.htlc_basepoint.pubkey, pcp)
          596     preimage_script = make_htlc_output_witness_script(is_received_htlc=htlc_direction == RECEIVED,
          597                                                       remote_revocation_pubkey=other_revocation_pubkey,
          598                                                       remote_htlc_pubkey=other_htlc_pubkey,
          599                                                       local_htlc_pubkey=htlc_pubkey,
          600                                                       payment_hash=payment_hash,
          601                                                       cltv_expiry=cltv_expiry)
          602     htlc_address = redeem_script_to_address('p2wsh', bh2u(preimage_script))
          603     candidates = ctx.get_output_idxs_from_address(htlc_address)
          604     return {output_idx for output_idx in candidates
          605             if ctx.outputs()[output_idx].value == htlc.amount_msat // 1000}
          606 
          607 
          608 def map_htlcs_to_ctx_output_idxs(*, chan: 'Channel', ctx: Transaction, pcp: bytes,
          609                                  subject: 'HTLCOwner', ctn: int) -> Dict[Tuple['Direction', 'UpdateAddHtlc'], Tuple[int, int]]:
          610     """Returns a dict from (htlc_dir, htlc) to (ctx_output_idx, htlc_relative_idx)"""
          611     htlc_to_ctx_output_idx_map = {}  # type: Dict[Tuple[Direction, UpdateAddHtlc], int]
          612     unclaimed_ctx_output_idxs = set(range(len(ctx.outputs())))
          613     offered_htlcs = chan.included_htlcs(subject, SENT, ctn=ctn)
          614     offered_htlcs.sort(key=lambda htlc: htlc.cltv_expiry)
          615     received_htlcs = chan.included_htlcs(subject, RECEIVED, ctn=ctn)
          616     received_htlcs.sort(key=lambda htlc: htlc.cltv_expiry)
          617     for direction, htlcs in zip([SENT, RECEIVED], [offered_htlcs, received_htlcs]):
          618         for htlc in htlcs:
          619             cands = sorted(possible_output_idxs_of_htlc_in_ctx(chan=chan,
          620                                                                pcp=pcp,
          621                                                                subject=subject,
          622                                                                htlc_direction=direction,
          623                                                                ctx=ctx,
          624                                                                htlc=htlc))
          625             for ctx_output_idx in cands:
          626                 if ctx_output_idx in unclaimed_ctx_output_idxs:
          627                     unclaimed_ctx_output_idxs.discard(ctx_output_idx)
          628                     htlc_to_ctx_output_idx_map[(direction, htlc)] = ctx_output_idx
          629                     break
          630     # calc htlc_relative_idx
          631     inverse_map = {ctx_output_idx: (direction, htlc)
          632                    for ((direction, htlc), ctx_output_idx) in htlc_to_ctx_output_idx_map.items()}
          633 
          634     return {inverse_map[ctx_output_idx]: (ctx_output_idx, htlc_relative_idx)
          635             for htlc_relative_idx, ctx_output_idx in enumerate(sorted(inverse_map))}
          636 
          637 
          638 def make_htlc_tx_with_open_channel(*, chan: 'Channel', pcp: bytes, subject: 'HTLCOwner', ctn: int,
          639                                    htlc_direction: 'Direction', commit: Transaction, ctx_output_idx: int,
          640                                    htlc: 'UpdateAddHtlc', name: str = None) -> Tuple[bytes, PartialTransaction]:
          641     amount_msat, cltv_expiry, payment_hash = htlc.amount_msat, htlc.cltv_expiry, htlc.payment_hash
          642     for_us = subject == LOCAL
          643     conf, other_conf = get_ordered_channel_configs(chan=chan, for_us=for_us)
          644 
          645     delayedpubkey = derive_pubkey(conf.delayed_basepoint.pubkey, pcp)
          646     other_revocation_pubkey = derive_blinded_pubkey(other_conf.revocation_basepoint.pubkey, pcp)
          647     other_htlc_pubkey = derive_pubkey(other_conf.htlc_basepoint.pubkey, pcp)
          648     htlc_pubkey = derive_pubkey(conf.htlc_basepoint.pubkey, pcp)
          649     # HTLC-success for the HTLC spending from a received HTLC output
          650     # if we do not receive, and the commitment tx is not for us, they receive, so it is also an HTLC-success
          651     is_htlc_success = htlc_direction == RECEIVED
          652     witness_script_of_htlc_tx_output, htlc_tx_output = make_htlc_tx_output(
          653         amount_msat = amount_msat,
          654         local_feerate = chan.get_feerate(subject, ctn=ctn),
          655         revocationpubkey=other_revocation_pubkey,
          656         local_delayedpubkey=delayedpubkey,
          657         success = is_htlc_success,
          658         to_self_delay = other_conf.to_self_delay)
          659     preimage_script = make_htlc_output_witness_script(is_received_htlc=is_htlc_success,
          660                                                       remote_revocation_pubkey=other_revocation_pubkey,
          661                                                       remote_htlc_pubkey=other_htlc_pubkey,
          662                                                       local_htlc_pubkey=htlc_pubkey,
          663                                                       payment_hash=payment_hash,
          664                                                       cltv_expiry=cltv_expiry)
          665     htlc_tx_inputs = make_htlc_tx_inputs(
          666         commit.txid(), ctx_output_idx,
          667         amount_msat=amount_msat,
          668         witness_script=bh2u(preimage_script))
          669     if is_htlc_success:
          670         cltv_expiry = 0
          671     htlc_tx = make_htlc_tx(cltv_expiry=cltv_expiry, inputs=htlc_tx_inputs, output=htlc_tx_output)
          672     return witness_script_of_htlc_tx_output, htlc_tx
          673 
          674 def make_funding_input(local_funding_pubkey: bytes, remote_funding_pubkey: bytes,
          675         funding_pos: int, funding_txid: str, funding_sat: int) -> PartialTxInput:
          676     pubkeys = sorted([bh2u(local_funding_pubkey), bh2u(remote_funding_pubkey)])
          677     # commitment tx input
          678     prevout = TxOutpoint(txid=bfh(funding_txid), out_idx=funding_pos)
          679     c_input = PartialTxInput(prevout=prevout)
          680     c_input.script_type = 'p2wsh'
          681     c_input.pubkeys = [bfh(pk) for pk in pubkeys]
          682     c_input.num_sig = 2
          683     c_input._trusted_value_sats = funding_sat
          684     return c_input
          685 
          686 class HTLCOwner(IntFlag):
          687     LOCAL = 1
          688     REMOTE = -LOCAL
          689 
          690     def inverted(self) -> 'HTLCOwner':
          691         return -self
          692 
          693     def __neg__(self) -> 'HTLCOwner':
          694         return HTLCOwner(super().__neg__())
          695 
          696 
          697 class Direction(IntFlag):
          698     SENT = -1     # in the context of HTLCs: "offered" HTLCs
          699     RECEIVED = 1  # in the context of HTLCs: "received" HTLCs
          700 
          701 SENT = Direction.SENT
          702 RECEIVED = Direction.RECEIVED
          703 
          704 LOCAL = HTLCOwner.LOCAL
          705 REMOTE = HTLCOwner.REMOTE
          706 
          707 def make_commitment_outputs(*, fees_per_participant: Mapping[HTLCOwner, int], local_amount_msat: int, remote_amount_msat: int,
          708         local_script: str, remote_script: str, htlcs: List[ScriptHtlc], dust_limit_sat: int) -> Tuple[List[PartialTxOutput], List[PartialTxOutput]]:
          709     # BOLT-03: "Base commitment transaction fees are extracted from the funder's amount;
          710     #           if that amount is insufficient, the entire amount of the funder's output is used."
          711     #   -> if funder cannot afford feerate, their output might go negative, so take max(0, x) here:
          712     to_local_amt = max(0, local_amount_msat - fees_per_participant[LOCAL])
          713     to_local = PartialTxOutput(scriptpubkey=bfh(local_script), value=to_local_amt // 1000)
          714     to_remote_amt = max(0, remote_amount_msat - fees_per_participant[REMOTE])
          715     to_remote = PartialTxOutput(scriptpubkey=bfh(remote_script), value=to_remote_amt // 1000)
          716 
          717     non_htlc_outputs = [to_local, to_remote]
          718     htlc_outputs = []
          719     for script, htlc in htlcs:
          720         addr = bitcoin.redeem_script_to_address('p2wsh', bh2u(script))
          721         htlc_outputs.append(PartialTxOutput(scriptpubkey=bfh(address_to_script(addr)),
          722                                             value=htlc.amount_msat // 1000))
          723 
          724     # trim outputs
          725     c_outputs_filtered = list(filter(lambda x: x.value >= dust_limit_sat, non_htlc_outputs + htlc_outputs))
          726     return htlc_outputs, c_outputs_filtered
          727 
          728 
          729 def offered_htlc_trim_threshold_sat(*, dust_limit_sat: int, feerate: int) -> int:
          730     # offered htlcs strictly below this amount will be trimmed (from ctx).
          731     # feerate is in sat/kw
          732     # returns value in sat
          733     weight = HTLC_TIMEOUT_WEIGHT
          734     return dust_limit_sat + weight * feerate // 1000
          735 
          736 
          737 def received_htlc_trim_threshold_sat(*, dust_limit_sat: int, feerate: int) -> int:
          738     # received htlcs strictly below this amount will be trimmed (from ctx).
          739     # feerate is in sat/kw
          740     # returns value in sat
          741     weight = HTLC_SUCCESS_WEIGHT
          742     return dust_limit_sat + weight * feerate // 1000
          743 
          744 
          745 def fee_for_htlc_output(*, feerate: int) -> int:
          746     # feerate is in sat/kw
          747     # returns fee in msat
          748     return feerate * HTLC_OUTPUT_WEIGHT
          749 
          750 
          751 def calc_fees_for_commitment_tx(*, num_htlcs: int, feerate: int,
          752                                 is_local_initiator: bool, round_to_sat: bool = True) -> Dict['HTLCOwner', int]:
          753     # feerate is in sat/kw
          754     # returns fees in msats
          755     # note: BOLT-02 specifies that msat fees need to be rounded down to sat.
          756     #       However, the rounding needs to happen for the total fees, so if the return value
          757     #       is to be used as part of additional fee calculation then rounding should be done after that.
          758     overall_weight = COMMITMENT_TX_WEIGHT + num_htlcs * HTLC_OUTPUT_WEIGHT
          759     fee = feerate * overall_weight
          760     if round_to_sat:
          761         fee = fee // 1000 * 1000
          762     return {
          763         LOCAL: fee if is_local_initiator else 0,
          764         REMOTE: fee if not is_local_initiator else 0,
          765     }
          766 
          767 
          768 def make_commitment(
          769         *,
          770         ctn: int,
          771         local_funding_pubkey: bytes,
          772         remote_funding_pubkey: bytes,
          773         remote_payment_pubkey: bytes,
          774         funder_payment_basepoint: bytes,
          775         fundee_payment_basepoint: bytes,
          776         revocation_pubkey: bytes,
          777         delayed_pubkey: bytes,
          778         to_self_delay: int,
          779         funding_txid: str,
          780         funding_pos: int,
          781         funding_sat: int,
          782         local_amount: int,
          783         remote_amount: int,
          784         dust_limit_sat: int,
          785         fees_per_participant: Mapping[HTLCOwner, int],
          786         htlcs: List[ScriptHtlc]
          787 ) -> PartialTransaction:
          788     c_input = make_funding_input(local_funding_pubkey, remote_funding_pubkey,
          789                                  funding_pos, funding_txid, funding_sat)
          790     obs = get_obscured_ctn(ctn, funder_payment_basepoint, fundee_payment_basepoint)
          791     locktime = (0x20 << 24) + (obs & 0xffffff)
          792     sequence = (0x80 << 24) + (obs >> 24)
          793     c_input.nsequence = sequence
          794 
          795     c_inputs = [c_input]
          796 
          797     # commitment tx outputs
          798     local_address = make_commitment_output_to_local_address(revocation_pubkey, to_self_delay, delayed_pubkey)
          799     remote_address = make_commitment_output_to_remote_address(remote_payment_pubkey)
          800     # note: it is assumed that the given 'htlcs' are all non-dust (dust htlcs already trimmed)
          801 
          802     # BOLT-03: "Transaction Input and Output Ordering
          803     #           Lexicographic ordering: see BIP69. In the case of identical HTLC outputs,
          804     #           the outputs are ordered in increasing cltv_expiry order."
          805     # so we sort by cltv_expiry now; and the later BIP69-sort is assumed to be *stable*
          806     htlcs = list(htlcs)
          807     htlcs.sort(key=lambda x: x.htlc.cltv_expiry)
          808 
          809     htlc_outputs, c_outputs_filtered = make_commitment_outputs(
          810         fees_per_participant=fees_per_participant,
          811         local_amount_msat=local_amount,
          812         remote_amount_msat=remote_amount,
          813         local_script=address_to_script(local_address),
          814         remote_script=address_to_script(remote_address),
          815         htlcs=htlcs,
          816         dust_limit_sat=dust_limit_sat)
          817 
          818     assert sum(x.value for x in c_outputs_filtered) <= funding_sat, (c_outputs_filtered, funding_sat)
          819 
          820     # create commitment tx
          821     tx = PartialTransaction.from_io(c_inputs, c_outputs_filtered, locktime=locktime, version=2)
          822     return tx
          823 
          824 def make_commitment_output_to_local_witness_script(
          825         revocation_pubkey: bytes, to_self_delay: int, delayed_pubkey: bytes) -> bytes:
          826     script = bfh(construct_script([
          827         opcodes.OP_IF,
          828         revocation_pubkey,
          829         opcodes.OP_ELSE,
          830         to_self_delay,
          831         opcodes.OP_CHECKSEQUENCEVERIFY,
          832         opcodes.OP_DROP,
          833         delayed_pubkey,
          834         opcodes.OP_ENDIF,
          835         opcodes.OP_CHECKSIG,
          836     ]))
          837     return script
          838 
          839 def make_commitment_output_to_local_address(
          840         revocation_pubkey: bytes, to_self_delay: int, delayed_pubkey: bytes) -> str:
          841     local_script = make_commitment_output_to_local_witness_script(revocation_pubkey, to_self_delay, delayed_pubkey)
          842     return bitcoin.redeem_script_to_address('p2wsh', bh2u(local_script))
          843 
          844 def make_commitment_output_to_remote_address(remote_payment_pubkey: bytes) -> str:
          845     return bitcoin.pubkey_to_address('p2wpkh', bh2u(remote_payment_pubkey))
          846 
          847 def sign_and_get_sig_string(tx: PartialTransaction, local_config, remote_config):
          848     tx.sign({bh2u(local_config.multisig_key.pubkey): (local_config.multisig_key.privkey, True)})
          849     sig = tx.inputs()[0].part_sigs[local_config.multisig_key.pubkey]
          850     sig_64 = sig_string_from_der_sig(sig[:-1])
          851     return sig_64
          852 
          853 def funding_output_script(local_config, remote_config) -> str:
          854     return funding_output_script_from_keys(local_config.multisig_key.pubkey, remote_config.multisig_key.pubkey)
          855 
          856 def funding_output_script_from_keys(pubkey1: bytes, pubkey2: bytes) -> str:
          857     pubkeys = sorted([bh2u(pubkey1), bh2u(pubkey2)])
          858     return transaction.multisig_script(pubkeys, 2)
          859 
          860 
          861 def get_obscured_ctn(ctn: int, funder: bytes, fundee: bytes) -> int:
          862     mask = int.from_bytes(sha256(funder + fundee)[-6:], 'big')
          863     return ctn ^ mask
          864 
          865 def extract_ctn_from_tx(tx: Transaction, txin_index: int, funder_payment_basepoint: bytes,
          866                         fundee_payment_basepoint: bytes) -> int:
          867     tx.deserialize()
          868     locktime = tx.locktime
          869     sequence = tx.inputs()[txin_index].nsequence
          870     obs = ((sequence & 0xffffff) << 24) + (locktime & 0xffffff)
          871     return get_obscured_ctn(obs, funder_payment_basepoint, fundee_payment_basepoint)
          872 
          873 def extract_ctn_from_tx_and_chan(tx: Transaction, chan: 'AbstractChannel') -> int:
          874     funder_conf = chan.config[LOCAL] if     chan.is_initiator() else chan.config[REMOTE]
          875     fundee_conf = chan.config[LOCAL] if not chan.is_initiator() else chan.config[REMOTE]
          876     return extract_ctn_from_tx(tx, txin_index=0,
          877                                funder_payment_basepoint=funder_conf.payment_basepoint.pubkey,
          878                                fundee_payment_basepoint=fundee_conf.payment_basepoint.pubkey)
          879 
          880 def get_ecdh(priv: bytes, pub: bytes) -> bytes:
          881     pt = ECPubkey(pub) * string_to_number(priv)
          882     return sha256(pt.get_public_key_bytes())
          883 
          884 
          885 class LnFeatureContexts(enum.Flag):
          886     INIT = enum.auto()
          887     NODE_ANN = enum.auto()
          888     CHAN_ANN_AS_IS = enum.auto()
          889     CHAN_ANN_ALWAYS_ODD = enum.auto()
          890     CHAN_ANN_ALWAYS_EVEN = enum.auto()
          891     INVOICE = enum.auto()
          892 
          893 LNFC = LnFeatureContexts
          894 
          895 _ln_feature_direct_dependencies = defaultdict(set)  # type: Dict[LnFeatures, Set[LnFeatures]]
          896 _ln_feature_contexts = {}  # type: Dict[LnFeatures, LnFeatureContexts]
          897 
          898 class LnFeatures(IntFlag):
          899     OPTION_DATA_LOSS_PROTECT_REQ = 1 << 0
          900     OPTION_DATA_LOSS_PROTECT_OPT = 1 << 1
          901     _ln_feature_contexts[OPTION_DATA_LOSS_PROTECT_OPT] = (LNFC.INIT | LnFeatureContexts.NODE_ANN)
          902     _ln_feature_contexts[OPTION_DATA_LOSS_PROTECT_REQ] = (LNFC.INIT | LnFeatureContexts.NODE_ANN)
          903 
          904     INITIAL_ROUTING_SYNC = 1 << 3
          905     _ln_feature_contexts[INITIAL_ROUTING_SYNC] = LNFC.INIT
          906 
          907     OPTION_UPFRONT_SHUTDOWN_SCRIPT_REQ = 1 << 4
          908     OPTION_UPFRONT_SHUTDOWN_SCRIPT_OPT = 1 << 5
          909     _ln_feature_contexts[OPTION_UPFRONT_SHUTDOWN_SCRIPT_OPT] = (LNFC.INIT | LNFC.NODE_ANN)
          910     _ln_feature_contexts[OPTION_UPFRONT_SHUTDOWN_SCRIPT_REQ] = (LNFC.INIT | LNFC.NODE_ANN)
          911 
          912     GOSSIP_QUERIES_REQ = 1 << 6
          913     GOSSIP_QUERIES_OPT = 1 << 7
          914     _ln_feature_contexts[GOSSIP_QUERIES_OPT] = (LNFC.INIT | LNFC.NODE_ANN)
          915     _ln_feature_contexts[GOSSIP_QUERIES_REQ] = (LNFC.INIT | LNFC.NODE_ANN)
          916 
          917     VAR_ONION_REQ = 1 << 8
          918     VAR_ONION_OPT = 1 << 9
          919     _ln_feature_contexts[VAR_ONION_OPT] = (LNFC.INIT | LNFC.NODE_ANN | LNFC.INVOICE)
          920     _ln_feature_contexts[VAR_ONION_REQ] = (LNFC.INIT | LNFC.NODE_ANN | LNFC.INVOICE)
          921 
          922     GOSSIP_QUERIES_EX_REQ = 1 << 10
          923     GOSSIP_QUERIES_EX_OPT = 1 << 11
          924     _ln_feature_direct_dependencies[GOSSIP_QUERIES_EX_OPT] = {GOSSIP_QUERIES_OPT}
          925     _ln_feature_contexts[GOSSIP_QUERIES_EX_OPT] = (LNFC.INIT | LNFC.NODE_ANN)
          926     _ln_feature_contexts[GOSSIP_QUERIES_EX_REQ] = (LNFC.INIT | LNFC.NODE_ANN)
          927 
          928     OPTION_STATIC_REMOTEKEY_REQ = 1 << 12
          929     OPTION_STATIC_REMOTEKEY_OPT = 1 << 13
          930     _ln_feature_contexts[OPTION_STATIC_REMOTEKEY_OPT] = (LNFC.INIT | LNFC.NODE_ANN)
          931     _ln_feature_contexts[OPTION_STATIC_REMOTEKEY_REQ] = (LNFC.INIT | LNFC.NODE_ANN)
          932 
          933     PAYMENT_SECRET_REQ = 1 << 14
          934     PAYMENT_SECRET_OPT = 1 << 15
          935     _ln_feature_direct_dependencies[PAYMENT_SECRET_OPT] = {VAR_ONION_OPT}
          936     _ln_feature_contexts[PAYMENT_SECRET_OPT] = (LNFC.INIT | LNFC.NODE_ANN | LNFC.INVOICE)
          937     _ln_feature_contexts[PAYMENT_SECRET_REQ] = (LNFC.INIT | LNFC.NODE_ANN | LNFC.INVOICE)
          938 
          939     BASIC_MPP_REQ = 1 << 16
          940     BASIC_MPP_OPT = 1 << 17
          941     _ln_feature_direct_dependencies[BASIC_MPP_OPT] = {PAYMENT_SECRET_OPT}
          942     _ln_feature_contexts[BASIC_MPP_OPT] = (LNFC.INIT | LNFC.NODE_ANN | LNFC.INVOICE)
          943     _ln_feature_contexts[BASIC_MPP_REQ] = (LNFC.INIT | LNFC.NODE_ANN | LNFC.INVOICE)
          944 
          945     OPTION_SUPPORT_LARGE_CHANNEL_REQ = 1 << 18
          946     OPTION_SUPPORT_LARGE_CHANNEL_OPT = 1 << 19
          947     _ln_feature_contexts[OPTION_SUPPORT_LARGE_CHANNEL_OPT] = (LNFC.INIT | LNFC.NODE_ANN)
          948     _ln_feature_contexts[OPTION_SUPPORT_LARGE_CHANNEL_REQ] = (LNFC.INIT | LNFC.NODE_ANN)
          949 
          950     OPTION_TRAMPOLINE_ROUTING_REQ = 1 << 24
          951     OPTION_TRAMPOLINE_ROUTING_OPT = 1 << 25
          952 
          953     _ln_feature_contexts[OPTION_TRAMPOLINE_ROUTING_REQ] = (LNFC.INIT | LNFC.NODE_ANN | LNFC.INVOICE)
          954     _ln_feature_contexts[OPTION_TRAMPOLINE_ROUTING_OPT] = (LNFC.INIT | LNFC.NODE_ANN | LNFC.INVOICE)
          955 
          956     # temporary
          957     OPTION_TRAMPOLINE_ROUTING_REQ_ECLAIR = 1 << 50
          958     OPTION_TRAMPOLINE_ROUTING_OPT_ECLAIR = 1 << 51
          959 
          960     def validate_transitive_dependencies(self) -> bool:
          961         # for all even bit set, set corresponding odd bit:
          962         features = self  # copy
          963         flags = list_enabled_bits(features)
          964         for flag in flags:
          965             if flag % 2 == 0:
          966                 features |= 1 << get_ln_flag_pair_of_bit(flag)
          967         # Check dependencies. We only check that the direct dependencies of each flag set
          968         # are satisfied: this implies that transitive dependencies are also satisfied.
          969         flags = list_enabled_bits(features)
          970         for flag in flags:
          971             for dependency in _ln_feature_direct_dependencies[1 << flag]:
          972                 if not (dependency & features):
          973                     return False
          974         return True
          975 
          976     def for_init_message(self) -> 'LnFeatures':
          977         features = LnFeatures(0)
          978         for flag in list_enabled_bits(self):
          979             if LnFeatureContexts.INIT & _ln_feature_contexts[1 << flag]:
          980                 features |= (1 << flag)
          981         return features
          982 
          983     def for_node_announcement(self) -> 'LnFeatures':
          984         features = LnFeatures(0)
          985         for flag in list_enabled_bits(self):
          986             if LnFeatureContexts.NODE_ANN & _ln_feature_contexts[1 << flag]:
          987                 features |= (1 << flag)
          988         return features
          989 
          990     def for_invoice(self) -> 'LnFeatures':
          991         features = LnFeatures(0)
          992         for flag in list_enabled_bits(self):
          993             if LnFeatureContexts.INVOICE & _ln_feature_contexts[1 << flag]:
          994                 features |= (1 << flag)
          995         return features
          996 
          997     def for_channel_announcement(self) -> 'LnFeatures':
          998         features = LnFeatures(0)
          999         for flag in list_enabled_bits(self):
         1000             ctxs = _ln_feature_contexts[1 << flag]
         1001             if LnFeatureContexts.CHAN_ANN_AS_IS & ctxs:
         1002                 features |= (1 << flag)
         1003             elif LnFeatureContexts.CHAN_ANN_ALWAYS_EVEN & ctxs:
         1004                 if flag % 2 == 0:
         1005                     features |= (1 << flag)
         1006             elif LnFeatureContexts.CHAN_ANN_ALWAYS_ODD & ctxs:
         1007                 if flag % 2 == 0:
         1008                     flag = get_ln_flag_pair_of_bit(flag)
         1009                 features |= (1 << flag)
         1010         return features
         1011 
         1012     def supports(self, feature: 'LnFeatures') -> bool:
         1013         """Returns whether given feature is enabled.
         1014 
         1015         Helper function that tries to hide the complexity of even/odd bits.
         1016         For example, instead of:
         1017           bool(myfeatures & LnFeatures.VAR_ONION_OPT or myfeatures & LnFeatures.VAR_ONION_REQ)
         1018         you can do:
         1019           myfeatures.supports(LnFeatures.VAR_ONION_OPT)
         1020         """
         1021         enabled_bits = list_enabled_bits(feature)
         1022         if len(enabled_bits) != 1:
         1023             raise ValueError(f"'feature' cannot be a combination of features: {feature}")
         1024         flag = enabled_bits[0]
         1025         our_flags = set(list_enabled_bits(self))
         1026         return (flag in our_flags
         1027                 or get_ln_flag_pair_of_bit(flag) in our_flags)
         1028 
         1029 
         1030 del LNFC  # name is ambiguous without context
         1031 
         1032 # features that are actually implemented and understood in our codebase:
         1033 # (note: this is not what we send in e.g. init!)
         1034 # (note: specify both OPT and REQ here)
         1035 LN_FEATURES_IMPLEMENTED = (
         1036         LnFeatures(0)
         1037         | LnFeatures.OPTION_DATA_LOSS_PROTECT_OPT | LnFeatures.OPTION_DATA_LOSS_PROTECT_REQ
         1038         | LnFeatures.GOSSIP_QUERIES_OPT | LnFeatures.GOSSIP_QUERIES_REQ
         1039         | LnFeatures.OPTION_STATIC_REMOTEKEY_OPT | LnFeatures.OPTION_STATIC_REMOTEKEY_REQ
         1040         | LnFeatures.VAR_ONION_OPT | LnFeatures.VAR_ONION_REQ
         1041         | LnFeatures.PAYMENT_SECRET_OPT | LnFeatures.PAYMENT_SECRET_REQ
         1042         | LnFeatures.BASIC_MPP_OPT | LnFeatures.BASIC_MPP_REQ
         1043         | LnFeatures.OPTION_TRAMPOLINE_ROUTING_OPT | LnFeatures.OPTION_TRAMPOLINE_ROUTING_REQ
         1044 )
         1045 
         1046 
         1047 def get_ln_flag_pair_of_bit(flag_bit: int) -> int:
         1048     """Ln Feature flags are assigned in pairs, one even, one odd. See BOLT-09.
         1049     Return the other flag from the pair.
         1050     e.g. 6 -> 7
         1051     e.g. 7 -> 6
         1052     """
         1053     if flag_bit % 2 == 0:
         1054         return flag_bit + 1
         1055     else:
         1056         return flag_bit - 1
         1057 
         1058 
         1059 
         1060 class IncompatibleOrInsaneFeatures(Exception): pass
         1061 class UnknownEvenFeatureBits(IncompatibleOrInsaneFeatures): pass
         1062 class IncompatibleLightningFeatures(IncompatibleOrInsaneFeatures): pass
         1063 
         1064 
         1065 def ln_compare_features(our_features: 'LnFeatures', their_features: int) -> 'LnFeatures':
         1066     """Returns negotiated features.
         1067     Raises IncompatibleLightningFeatures if incompatible.
         1068     """
         1069     our_flags = set(list_enabled_bits(our_features))
         1070     their_flags = set(list_enabled_bits(their_features))
         1071     # check that they have our required features, and disable the optional features they don't have
         1072     for flag in our_flags:
         1073         if flag not in their_flags and get_ln_flag_pair_of_bit(flag) not in their_flags:
         1074             # they don't have this feature we wanted :(
         1075             if flag % 2 == 0:  # even flags are compulsory
         1076                 raise IncompatibleLightningFeatures(f"remote does not support {LnFeatures(1 << flag)!r}")
         1077             our_features ^= 1 << flag  # disable flag
         1078         else:
         1079             # They too have this flag.
         1080             # For easier feature-bit-testing, if this is an even flag, we also
         1081             # set the corresponding odd flag now.
         1082             if flag % 2 == 0 and our_features & (1 << flag):
         1083                 our_features |= 1 << get_ln_flag_pair_of_bit(flag)
         1084     # check that we have their required features
         1085     for flag in their_flags:
         1086         if flag not in our_flags and get_ln_flag_pair_of_bit(flag) not in our_flags:
         1087             # we don't have this feature they wanted :(
         1088             if flag % 2 == 0:  # even flags are compulsory
         1089                 raise IncompatibleLightningFeatures(f"remote wanted feature we don't have: {LnFeatures(1 << flag)!r}")
         1090     return our_features
         1091 
         1092 
         1093 def validate_features(features: int) -> None:
         1094     """Raises IncompatibleOrInsaneFeatures if
         1095     - a mandatory feature is listed that we don't recognize, or
         1096     - the features are inconsistent
         1097     """
         1098     features = LnFeatures(features)
         1099     enabled_features = list_enabled_bits(features)
         1100     for fbit in enabled_features:
         1101         if (1 << fbit) & LN_FEATURES_IMPLEMENTED == 0 and fbit % 2 == 0:
         1102             raise UnknownEvenFeatureBits(fbit)
         1103     if not features.validate_transitive_dependencies():
         1104         raise IncompatibleOrInsaneFeatures(f"not all transitive dependencies are set. "
         1105                                            f"features={features}")
         1106 
         1107 
         1108 def derive_payment_secret_from_payment_preimage(payment_preimage: bytes) -> bytes:
         1109     """Returns secret to be put into invoice.
         1110     Derivation is deterministic, based on the preimage.
         1111     Crucially the payment_hash must be derived in an independent way from this.
         1112     """
         1113     # Note that this could be random data too, but then we would need to store it.
         1114     # We derive it identically to clightning, so that we cannot be distinguished:
         1115     # https://github.com/ElementsProject/lightning/blob/faac4b28adee5221e83787d64cd5d30b16b62097/lightningd/invoice.c#L115
         1116     modified = bytearray(payment_preimage)
         1117     modified[0] ^= 1
         1118     return sha256(bytes(modified))
         1119 
         1120 
         1121 class LNPeerAddr:
         1122     # note: while not programmatically enforced, this class is meant to be *immutable*
         1123 
         1124     def __init__(self, host: str, port: int, pubkey: bytes):
         1125         assert isinstance(host, str), repr(host)
         1126         assert isinstance(port, int), repr(port)
         1127         assert isinstance(pubkey, bytes), repr(pubkey)
         1128         try:
         1129             net_addr = NetAddress(host, port)  # this validates host and port
         1130         except Exception as e:
         1131             raise ValueError(f"cannot construct LNPeerAddr: invalid host or port (host={host}, port={port})") from e
         1132         # note: not validating pubkey as it would be too expensive:
         1133         # if not ECPubkey.is_pubkey_bytes(pubkey): raise ValueError()
         1134         self.host = host
         1135         self.port = port
         1136         self.pubkey = pubkey
         1137         self._net_addr = net_addr
         1138 
         1139     def __str__(self):
         1140         return '{}@{}'.format(self.pubkey.hex(), self.net_addr_str())
         1141 
         1142     def __repr__(self):
         1143         return f'<LNPeerAddr host={self.host} port={self.port} pubkey={self.pubkey.hex()}>'
         1144 
         1145     def net_addr(self) -> NetAddress:
         1146         return self._net_addr
         1147 
         1148     def net_addr_str(self) -> str:
         1149         return str(self._net_addr)
         1150 
         1151     def __eq__(self, other):
         1152         if not isinstance(other, LNPeerAddr):
         1153             return False
         1154         return (self.host == other.host
         1155                 and self.port == other.port
         1156                 and self.pubkey == other.pubkey)
         1157 
         1158     def __ne__(self, other):
         1159         return not (self == other)
         1160 
         1161     def __hash__(self):
         1162         return hash((self.host, self.port, self.pubkey))
         1163 
         1164 
         1165 def get_compressed_pubkey_from_bech32(bech32_pubkey: str) -> bytes:
         1166     hrp, data_5bits = segwit_addr.bech32_decode(bech32_pubkey)
         1167     if hrp != 'ln':
         1168         raise Exception('unexpected hrp: {}'.format(hrp))
         1169     data_8bits = segwit_addr.convertbits(data_5bits, 5, 8, False)
         1170     # pad with zeroes
         1171     COMPRESSED_PUBKEY_LENGTH = 33
         1172     data_8bits = data_8bits + ((COMPRESSED_PUBKEY_LENGTH - len(data_8bits)) * [0])
         1173     return bytes(data_8bits)
         1174 
         1175 
         1176 def make_closing_tx(local_funding_pubkey: bytes, remote_funding_pubkey: bytes,
         1177                     funding_txid: str, funding_pos: int, funding_sat: int,
         1178                     outputs: List[PartialTxOutput]) -> PartialTransaction:
         1179     c_input = make_funding_input(local_funding_pubkey, remote_funding_pubkey,
         1180         funding_pos, funding_txid, funding_sat)
         1181     c_input.nsequence = 0xFFFF_FFFF
         1182     tx = PartialTransaction.from_io([c_input], outputs, locktime=0, version=2)
         1183     return tx
         1184 
         1185 
         1186 def split_host_port(host_port: str) -> Tuple[str, str]: # port returned as string
         1187     ipv6  = re.compile(r'\[(?P<host>[:0-9a-f]+)\](?P<port>:\d+)?$')
         1188     other = re.compile(r'(?P<host>[^:]+)(?P<port>:\d+)?$')
         1189     m = ipv6.match(host_port)
         1190     if not m:
         1191         m = other.match(host_port)
         1192     if not m:
         1193         raise ConnStringFormatError(_('Connection strings must be in <node_pubkey>@<host>:<port> format'))
         1194     host = m.group('host')
         1195     if m.group('port'):
         1196         port = m.group('port')[1:]
         1197     else:
         1198         port = '9735'
         1199     try:
         1200         int(port)
         1201     except ValueError:
         1202         raise ConnStringFormatError(_('Port number must be decimal'))
         1203     return host, port
         1204 
         1205 def extract_nodeid(connect_contents: str) -> Tuple[bytes, str]:
         1206     rest = None
         1207     try:
         1208         # connection string?
         1209         nodeid_hex, rest = connect_contents.split("@", 1)
         1210     except ValueError:
         1211         try:
         1212             # invoice?
         1213             invoice = lndecode(connect_contents)
         1214             nodeid_bytes = invoice.pubkey.serialize()
         1215             nodeid_hex = bh2u(nodeid_bytes)
         1216         except:
         1217             # node id as hex?
         1218             nodeid_hex = connect_contents
         1219     if rest == '':
         1220         raise ConnStringFormatError(_('At least a hostname must be supplied after the at symbol.'))
         1221     try:
         1222         node_id = bfh(nodeid_hex)
         1223         if len(node_id) != 33:
         1224             raise Exception()
         1225     except:
         1226         raise ConnStringFormatError(_('Invalid node ID, must be 33 bytes and hexadecimal'))
         1227     return node_id, rest
         1228 
         1229 
         1230 # key derivation
         1231 # see lnd/keychain/derivation.go
         1232 class LnKeyFamily(IntEnum):
         1233     MULTISIG = 0 | BIP32_PRIME
         1234     REVOCATION_BASE = 1 | BIP32_PRIME
         1235     HTLC_BASE = 2 | BIP32_PRIME
         1236     PAYMENT_BASE = 3 | BIP32_PRIME
         1237     DELAY_BASE = 4 | BIP32_PRIME
         1238     REVOCATION_ROOT = 5 | BIP32_PRIME
         1239     NODE_KEY = 6
         1240 
         1241 
         1242 def generate_keypair(node: BIP32Node, key_family: LnKeyFamily) -> Keypair:
         1243     node2 = node.subkey_at_private_derivation([key_family, 0, 0])
         1244     k = node2.eckey.get_secret_bytes()
         1245     cK = ecc.ECPrivkey(k).get_public_key_bytes()
         1246     return Keypair(cK, k)
         1247 
         1248 
         1249 
         1250 NUM_MAX_HOPS_IN_PAYMENT_PATH = 20
         1251 NUM_MAX_EDGES_IN_PAYMENT_PATH = NUM_MAX_HOPS_IN_PAYMENT_PATH
         1252 
         1253 
         1254 class ShortChannelID(bytes):
         1255 
         1256     def __repr__(self):
         1257         return f"<ShortChannelID: {format_short_channel_id(self)}>"
         1258 
         1259     def __str__(self):
         1260         return format_short_channel_id(self)
         1261 
         1262     @classmethod
         1263     def from_components(cls, block_height: int, tx_pos_in_block: int, output_index: int) -> 'ShortChannelID':
         1264         bh = block_height.to_bytes(3, byteorder='big')
         1265         tpos = tx_pos_in_block.to_bytes(3, byteorder='big')
         1266         oi = output_index.to_bytes(2, byteorder='big')
         1267         return ShortChannelID(bh + tpos + oi)
         1268 
         1269     @classmethod
         1270     def from_str(cls, scid: str) -> 'ShortChannelID':
         1271         """Parses a formatted scid str, e.g. '643920x356x0'."""
         1272         components = scid.split("x")
         1273         if len(components) != 3:
         1274             raise ValueError(f"failed to parse ShortChannelID: {scid!r}")
         1275         try:
         1276             components = [int(x) for x in components]
         1277         except ValueError:
         1278             raise ValueError(f"failed to parse ShortChannelID: {scid!r}") from None
         1279         return ShortChannelID.from_components(*components)
         1280 
         1281     @classmethod
         1282     def normalize(cls, data: Union[None, str, bytes, 'ShortChannelID']) -> Optional['ShortChannelID']:
         1283         if isinstance(data, ShortChannelID) or data is None:
         1284             return data
         1285         if isinstance(data, str):
         1286             assert len(data) == 16
         1287             return ShortChannelID.fromhex(data)
         1288         if isinstance(data, (bytes, bytearray)):
         1289             assert len(data) == 8
         1290             return ShortChannelID(data)
         1291 
         1292     @property
         1293     def block_height(self) -> int:
         1294         return int.from_bytes(self[:3], byteorder='big')
         1295 
         1296     @property
         1297     def txpos(self) -> int:
         1298         return int.from_bytes(self[3:6], byteorder='big')
         1299 
         1300     @property
         1301     def output_index(self) -> int:
         1302         return int.from_bytes(self[6:8], byteorder='big')
         1303 
         1304 
         1305 def format_short_channel_id(short_channel_id: Optional[bytes]):
         1306     if not short_channel_id:
         1307         return _('Not yet available')
         1308     return str(int.from_bytes(short_channel_id[:3], 'big')) \
         1309         + 'x' + str(int.from_bytes(short_channel_id[3:6], 'big')) \
         1310         + 'x' + str(int.from_bytes(short_channel_id[6:], 'big'))
         1311 
         1312 
         1313 @attr.s(frozen=True)
         1314 class UpdateAddHtlc:
         1315     amount_msat = attr.ib(type=int, kw_only=True)
         1316     payment_hash = attr.ib(type=bytes, kw_only=True, converter=hex_to_bytes, repr=lambda val: val.hex())
         1317     cltv_expiry = attr.ib(type=int, kw_only=True)
         1318     timestamp = attr.ib(type=int, kw_only=True)
         1319     htlc_id = attr.ib(type=int, kw_only=True, default=None)
         1320 
         1321     @classmethod
         1322     def from_tuple(cls, amount_msat, payment_hash, cltv_expiry, htlc_id, timestamp) -> 'UpdateAddHtlc':
         1323         return cls(amount_msat=amount_msat,
         1324                    payment_hash=payment_hash,
         1325                    cltv_expiry=cltv_expiry,
         1326                    htlc_id=htlc_id,
         1327                    timestamp=timestamp)
         1328 
         1329     def to_tuple(self):
         1330         return (self.amount_msat, self.payment_hash, self.cltv_expiry, self.htlc_id, self.timestamp)
         1331 
         1332 
         1333 class OnionFailureCodeMetaFlag(IntFlag):
         1334     BADONION = 0x8000
         1335     PERM     = 0x4000
         1336     NODE     = 0x2000
         1337     UPDATE   = 0x1000
         1338 
         1339 
         1340 class ChannelBlackList:
         1341 
         1342     def __init__(self):
         1343         self.blacklist = dict() # short_chan_id -> timestamp
         1344 
         1345     def add(self, short_channel_id: ShortChannelID):
         1346         now = int(time.time())
         1347         self.blacklist[short_channel_id] = now
         1348 
         1349     def get_current_list(self) -> Set[ShortChannelID]:
         1350         BLACKLIST_DURATION = 3600
         1351         now = int(time.time())
         1352         return set(k for k, t in self.blacklist.items() if now - t < BLACKLIST_DURATION)