electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

lnutil.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)