lnpeer: new payment secret, derived without preimage.
(this is needed for hold invoices)
This commit is contained in:
@@ -1826,8 +1826,12 @@ class Peer(Logger):
|
||||
raise exc_incorrect_or_unknown_pd
|
||||
preimage = self.lnworker.get_preimage(htlc.payment_hash)
|
||||
if payment_secret_from_onion:
|
||||
if payment_secret_from_onion != derive_payment_secret_from_payment_preimage(preimage):
|
||||
log_fail_reason(f'incorrect payment secret {payment_secret_from_onion.hex()} != {derive_payment_secret_from_payment_preimage(preimage).hex()}')
|
||||
expected_payment_secrets = [self.lnworker.get_payment_secret(htlc.payment_hash)]
|
||||
if preimage:
|
||||
# legacy secret for old invoices
|
||||
expected_payment_secrets.append(derive_payment_secret_from_payment_preimage(preimage))
|
||||
if payment_secret_from_onion not in expected_payment_secrets:
|
||||
log_fail_reason(f'incorrect payment secret {payment_secret_from_onion.hex()} != {expected_payment_secrets[0].hex()}')
|
||||
raise exc_incorrect_or_unknown_pd
|
||||
invoice_msat = info.amount_msat
|
||||
if not (invoice_msat is None or invoice_msat <= total_msat <= 2 * invoice_msat):
|
||||
|
||||
@@ -1538,6 +1538,7 @@ class LnKeyFamily(IntEnum):
|
||||
REVOCATION_ROOT = 5 | BIP32_PRIME
|
||||
NODE_KEY = 6
|
||||
BACKUP_CIPHER = 7 | BIP32_PRIME
|
||||
PAYMENT_SECRET_KEY = 8 | BIP32_PRIME
|
||||
|
||||
|
||||
def generate_keypair(node: BIP32Node, key_family: LnKeyFamily) -> Keypair:
|
||||
|
||||
@@ -217,6 +217,7 @@ class LNWorker(Logger, EventListener, NetworkRetryManager[LNPeerAddr]):
|
||||
self.lock = threading.RLock()
|
||||
self.node_keypair = generate_keypair(BIP32Node.from_xkey(xprv), LnKeyFamily.NODE_KEY)
|
||||
self.backup_key = generate_keypair(BIP32Node.from_xkey(xprv), LnKeyFamily.BACKUP_CIPHER).privkey
|
||||
self.payment_secret_key = generate_keypair(BIP32Node.from_xkey(xprv), LnKeyFamily.PAYMENT_SECRET_KEY).privkey
|
||||
self._peers = {} # type: Dict[bytes, Peer] # pubkey -> Peer # needs self.lock
|
||||
self.taskgroup = OldTaskGroup()
|
||||
self.listen_server = None # type: Optional[asyncio.AbstractServer]
|
||||
@@ -1824,9 +1825,7 @@ class LNWallet(LNWorker):
|
||||
routing_hints, trampoline_hints = self.calc_routing_hints_for_invoice(amount_msat, channels=channels)
|
||||
self.logger.info(f"creating bolt11 invoice with routing_hints: {routing_hints}")
|
||||
invoice_features = self.features.for_invoice()
|
||||
payment_preimage = self.get_preimage(payment_hash)
|
||||
if payment_preimage is None: # e.g. when export/importing requests between wallets
|
||||
raise Exception("missing preimage for payment_hash")
|
||||
payment_secret = self.get_payment_secret(payment_hash)
|
||||
amount_btc = amount_msat/Decimal(COIN*1000) if amount_msat else None
|
||||
if expiry == 0:
|
||||
expiry = LN_EXPIRY_NEVER
|
||||
@@ -1843,12 +1842,15 @@ class LNWallet(LNWorker):
|
||||
+ routing_hints
|
||||
+ trampoline_hints,
|
||||
date=timestamp,
|
||||
payment_secret=derive_payment_secret_from_payment_preimage(payment_preimage))
|
||||
payment_secret=payment_secret)
|
||||
invoice = lnencode(lnaddr, self.node_keypair.privkey)
|
||||
pair = lnaddr, invoice
|
||||
self._bolt11_cache[payment_hash] = pair
|
||||
return pair
|
||||
|
||||
def get_payment_secret(self, payment_hash):
|
||||
return sha256(sha256(self.payment_secret_key) + payment_hash)
|
||||
|
||||
def create_payment_info(self, *, amount_msat: Optional[int], write_to_disk=True) -> bytes:
|
||||
payment_preimage = os.urandom(32)
|
||||
payment_hash = sha256(payment_preimage)
|
||||
|
||||
@@ -138,6 +138,7 @@ class MockLNWallet(Logger, EventListener, NetworkRetryManager[LNPeerAddr]):
|
||||
Logger.__init__(self)
|
||||
NetworkRetryManager.__init__(self, max_retry_delay_normal=1, init_retry_delay_normal=1)
|
||||
self.node_keypair = local_keypair
|
||||
self.payment_secret_key = os.urandom(256) # does not need to be deterministic in tests
|
||||
self._user_dir = tempfile.mkdtemp(prefix="electrum-lnpeer-test-")
|
||||
self.config = SimpleConfig({}, read_user_dir_function=lambda: self._user_dir)
|
||||
self.network = MockNetwork(tx_queue, config=self.config)
|
||||
@@ -239,6 +240,7 @@ class MockLNWallet(Logger, EventListener, NetworkRetryManager[LNPeerAddr]):
|
||||
full_path=full_path)]
|
||||
|
||||
get_payments = LNWallet.get_payments
|
||||
get_payment_secret = LNWallet.get_payment_secret
|
||||
get_payment_info = LNWallet.get_payment_info
|
||||
save_payment_info = LNWallet.save_payment_info
|
||||
set_invoice_status = LNWallet.set_invoice_status
|
||||
|
||||
Reference in New Issue
Block a user