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)