mirror of
https://github.com/LBRYFoundation/LBRY-Vault.git
synced 2025-09-11 04:59:51 +00:00
small clean-up re "extract preimage from on-chain htlc_tx"
related: #6122
This commit is contained in:
parent
5c05c06bf0
commit
62be1cc367
3 changed files with 49 additions and 40 deletions
|
@ -28,6 +28,7 @@ from typing import (Optional, Dict, List, Tuple, NamedTuple, Set, Callable,
|
||||||
import time
|
import time
|
||||||
import threading
|
import threading
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
|
import itertools
|
||||||
|
|
||||||
from aiorpcx import NetAddress
|
from aiorpcx import NetAddress
|
||||||
import attr
|
import attr
|
||||||
|
@ -37,7 +38,7 @@ from . import constants, util
|
||||||
from .util import bfh, bh2u, chunks, TxMinedInfo, PR_PAID
|
from .util import bfh, bh2u, chunks, TxMinedInfo, PR_PAID
|
||||||
from .bitcoin import redeem_script_to_address
|
from .bitcoin import redeem_script_to_address
|
||||||
from .crypto import sha256, sha256d
|
from .crypto import sha256, sha256d
|
||||||
from .transaction import Transaction, PartialTransaction
|
from .transaction import Transaction, PartialTransaction, TxInput
|
||||||
from .logging import Logger
|
from .logging import Logger
|
||||||
from .lnonion import decode_onion_error, OnionFailureCode, OnionRoutingFailureMessage
|
from .lnonion import decode_onion_error, OnionFailureCode, OnionRoutingFailureMessage
|
||||||
from . import lnutil
|
from . import lnutil
|
||||||
|
@ -971,46 +972,37 @@ class Channel(AbstractChannel):
|
||||||
failure_message = OnionRoutingFailureMessage.from_bytes(bytes.fromhex(failure_hex)) if failure_hex else None
|
failure_message = OnionRoutingFailureMessage.from_bytes(bytes.fromhex(failure_hex)) if failure_hex else None
|
||||||
return error_bytes, failure_message
|
return error_bytes, failure_message
|
||||||
|
|
||||||
def extract_preimage_from_htlc_tx(self, tx):
|
def extract_preimage_from_htlc_txin(self, txin: TxInput) -> None:
|
||||||
for _input in tx.inputs():
|
witness = txin.witness_elements()
|
||||||
witness = _input.witness_elements()
|
if len(witness) == 5: # HTLC success tx
|
||||||
if len(witness) == 5:
|
preimage = witness[3]
|
||||||
preimage = witness[3]
|
elif len(witness) == 3: # spending offered HTLC directly from ctx
|
||||||
elif len(witness) == 3:
|
preimage = witness[1]
|
||||||
preimage = witness[1]
|
else:
|
||||||
else:
|
return
|
||||||
continue
|
payment_hash = sha256(preimage)
|
||||||
payment_hash = sha256(preimage)
|
for direction, htlc in itertools.chain(self.hm.get_htlcs_in_oldest_unrevoked_ctx(REMOTE),
|
||||||
for direction, htlc in self.hm.get_htlcs_in_oldest_unrevoked_ctx(REMOTE):
|
self.hm.get_htlcs_in_latest_ctx(REMOTE)):
|
||||||
|
if htlc.payment_hash == payment_hash:
|
||||||
|
is_sent = direction == RECEIVED
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
for direction, htlc in itertools.chain(self.hm.get_htlcs_in_oldest_unrevoked_ctx(LOCAL),
|
||||||
|
self.hm.get_htlcs_in_latest_ctx(LOCAL)):
|
||||||
if htlc.payment_hash == payment_hash:
|
if htlc.payment_hash == payment_hash:
|
||||||
is_sent = direction == RECEIVED
|
is_sent = direction == SENT
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
for direction, htlc in self.hm.get_htlcs_in_latest_ctx(REMOTE):
|
return
|
||||||
if htlc.payment_hash == payment_hash:
|
if self.lnworker.get_preimage(payment_hash) is None:
|
||||||
is_sent = direction == RECEIVED
|
self.logger.info(f'found preimage for {payment_hash.hex()} in witness of length {len(witness)}')
|
||||||
break
|
self.lnworker.save_preimage(payment_hash, preimage)
|
||||||
else:
|
info = self.lnworker.get_payment_info(payment_hash)
|
||||||
for direction, htlc in self.hm.get_htlcs_in_oldest_unrevoked_ctx(LOCAL):
|
if info is not None and info.status != PR_PAID:
|
||||||
if htlc.payment_hash == payment_hash:
|
if is_sent:
|
||||||
is_sent = direction == SENT
|
self.lnworker.payment_sent(self, payment_hash)
|
||||||
break
|
else:
|
||||||
else:
|
self.lnworker.payment_received(self, payment_hash)
|
||||||
for direction, htlc in self.hm.get_htlcs_in_latest_ctx(LOCAL):
|
|
||||||
if htlc.payment_hash == payment_hash:
|
|
||||||
is_sent = direction == SENT
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
continue
|
|
||||||
if self.lnworker.get_preimage(payment_hash) is None:
|
|
||||||
self.logger.info(f'found preimage for {payment_hash.hex()} in witness of length {len(witness)}')
|
|
||||||
self.lnworker.save_preimage(payment_hash, preimage)
|
|
||||||
info = self.lnworker.get_payment_info(payment_hash)
|
|
||||||
if info is not None and info.status != PR_PAID:
|
|
||||||
if is_sent:
|
|
||||||
self.lnworker.payment_sent(self, payment_hash)
|
|
||||||
else:
|
|
||||||
self.lnworker.payment_received(self, payment_hash)
|
|
||||||
|
|
||||||
def balance(self, whose: HTLCOwner, *, ctx_owner=HTLCOwner.LOCAL, ctn: int = None) -> int:
|
def balance(self, whose: HTLCOwner, *, ctx_owner=HTLCOwner.LOCAL, ctn: int = None) -> int:
|
||||||
assert type(whose) is HTLCOwner
|
assert type(whose) is HTLCOwner
|
||||||
|
|
|
@ -13,7 +13,7 @@ from .sql_db import SqlDB, sql
|
||||||
from .wallet_db import WalletDB
|
from .wallet_db import WalletDB
|
||||||
from .util import bh2u, bfh, log_exceptions, ignore_exceptions, TxMinedInfo
|
from .util import bh2u, bfh, log_exceptions, ignore_exceptions, TxMinedInfo
|
||||||
from .address_synchronizer import AddressSynchronizer, TX_HEIGHT_LOCAL, TX_HEIGHT_UNCONF_PARENT, TX_HEIGHT_UNCONFIRMED
|
from .address_synchronizer import AddressSynchronizer, TX_HEIGHT_LOCAL, TX_HEIGHT_UNCONF_PARENT, TX_HEIGHT_UNCONFIRMED
|
||||||
from .transaction import Transaction
|
from .transaction import Transaction, TxOutpoint
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .network import Network
|
from .network import Network
|
||||||
|
@ -387,7 +387,10 @@ class LNWalletWatcher(LNWatcher):
|
||||||
else:
|
else:
|
||||||
self.logger.info(f'(chan {chan.get_id_for_log()}) outpoint already spent {name}: {prevout}')
|
self.logger.info(f'(chan {chan.get_id_for_log()}) outpoint already spent {name}: {prevout}')
|
||||||
keep_watching |= not self.is_deeply_mined(spender_txid)
|
keep_watching |= not self.is_deeply_mined(spender_txid)
|
||||||
chan.extract_preimage_from_htlc_tx(spender_tx)
|
txin_idx = spender_tx.get_input_idx_that_spent_prevout(TxOutpoint.from_str(prevout))
|
||||||
|
assert txin_idx is not None
|
||||||
|
spender_txin = spender_tx.inputs()[txin_idx]
|
||||||
|
chan.extract_preimage_from_htlc_txin(spender_txin)
|
||||||
else:
|
else:
|
||||||
self.logger.info(f'(chan {chan.get_id_for_log()}) trying to redeem {name}: {prevout}')
|
self.logger.info(f'(chan {chan.get_id_for_log()}) trying to redeem {name}: {prevout}')
|
||||||
await self.try_redeem(prevout, sweep_info, name)
|
await self.try_redeem(prevout, sweep_info, name)
|
||||||
|
|
|
@ -953,6 +953,20 @@ class Transaction:
|
||||||
else:
|
else:
|
||||||
raise Exception('output not found', addr)
|
raise Exception('output not found', addr)
|
||||||
|
|
||||||
|
def get_input_idx_that_spent_prevout(self, prevout: TxOutpoint) -> Optional[int]:
|
||||||
|
# build cache if there isn't one yet
|
||||||
|
# note: can become stale and return incorrect data
|
||||||
|
# if the tx is modified later; that's out of scope.
|
||||||
|
if not hasattr(self, '_prevout_to_input_idx'):
|
||||||
|
d = {} # type: Dict[TxOutpoint, int]
|
||||||
|
for i, txin in enumerate(self.inputs()):
|
||||||
|
d[txin.prevout] = i
|
||||||
|
self._prevout_to_input_idx = d
|
||||||
|
idx = self._prevout_to_input_idx.get(prevout)
|
||||||
|
if idx is not None:
|
||||||
|
assert self.inputs()[idx].prevout == prevout
|
||||||
|
return idx
|
||||||
|
|
||||||
|
|
||||||
def convert_raw_tx_to_hex(raw: Union[str, bytes]) -> str:
|
def convert_raw_tx_to_hex(raw: Union[str, bytes]) -> str:
|
||||||
"""Sanitizes tx-describing input (hex/base43/base64) into
|
"""Sanitizes tx-describing input (hex/base43/base64) into
|
||||||
|
|
Loading…
Add table
Reference in a new issue