Refresh bolt11 routing hints when channel liquidity changes:
- wallet_db update: separate Invoices and Requests. - do not store bolt11 invoice in Request
This commit is contained in:
@@ -7,6 +7,7 @@ import attr
|
||||
from .json_db import StoredObject
|
||||
from .i18n import _
|
||||
from .util import age, InvoiceError
|
||||
from .lnutil import hex_to_bytes
|
||||
from .lnaddr import lndecode, LnAddr
|
||||
from . import constants
|
||||
from .bitcoin import COIN, TOTAL_COIN_SUPPLY_LIMIT_IN_BTC
|
||||
@@ -83,7 +84,11 @@ LN_EXPIRY_NEVER = 100 * 365 * 24 * 60 * 60 # 100 years
|
||||
|
||||
|
||||
@attr.s
|
||||
class Invoice(StoredObject):
|
||||
class BaseInvoice(StoredObject):
|
||||
"""
|
||||
Base class for Invoice and Request
|
||||
In the code, we use 'invoice' for outgoing payments, and 'request' for incoming payments.
|
||||
"""
|
||||
|
||||
# mandatory fields
|
||||
amount_msat = attr.ib(kw_only=True) # type: Optional[Union[int, str]] # can be '!' or None
|
||||
@@ -101,10 +106,6 @@ class Invoice(StoredObject):
|
||||
bip70 = attr.ib(type=str, kw_only=True) # type: Optional[str]
|
||||
#bip70_requestor = attr.ib(type=str, kw_only=True) # type: Optional[str]
|
||||
|
||||
# lightning only
|
||||
lightning_invoice = attr.ib(type=str, kw_only=True) # type: Optional[str]
|
||||
|
||||
__lnaddr = None
|
||||
|
||||
def is_lightning(self):
|
||||
return self.lightning_invoice is not None
|
||||
@@ -117,15 +118,6 @@ class Invoice(StoredObject):
|
||||
status_str = _('Expires') + ' ' + age(expiration, include_seconds=True)
|
||||
return status_str
|
||||
|
||||
def get_address(self) -> Optional[str]:
|
||||
"""returns the first address, to be displayed in GUI"""
|
||||
address = None
|
||||
if self.outputs:
|
||||
address = self.outputs[0].address if len(self.outputs) > 0 else None
|
||||
if not address and self.is_lightning():
|
||||
address = self._lnaddr.get_fallback_address() or None
|
||||
return address
|
||||
|
||||
def get_outputs(self) -> Sequence[PartialTxOutput]:
|
||||
outputs = self.outputs or []
|
||||
if not outputs:
|
||||
@@ -135,12 +127,6 @@ class Invoice(StoredObject):
|
||||
outputs = [PartialTxOutput.from_address_and_value(address, int(amount))]
|
||||
return outputs
|
||||
|
||||
def can_be_paid_onchain(self) -> bool:
|
||||
if self.is_lightning():
|
||||
return bool(self._lnaddr.get_fallback_address())
|
||||
else:
|
||||
return True
|
||||
|
||||
def get_expiration_date(self):
|
||||
# 0 means never
|
||||
return self.exp + self.time if self.exp else 0
|
||||
@@ -193,12 +179,6 @@ class Invoice(StoredObject):
|
||||
uri = create_bip21_uri(addr, amount, message, extra_query_params=extra)
|
||||
return str(uri)
|
||||
|
||||
@lightning_invoice.validator
|
||||
def _validate_invoice_str(self, attribute, value):
|
||||
if value is not None:
|
||||
lnaddr = lndecode(value) # this checks the str can be decoded
|
||||
self.__lnaddr = lnaddr # save it, just to avoid having to recompute later
|
||||
|
||||
@amount_msat.validator
|
||||
def _validate_amount(self, attribute, value):
|
||||
if value is None:
|
||||
@@ -212,16 +192,6 @@ class Invoice(StoredObject):
|
||||
else:
|
||||
raise InvoiceError(f"unexpected amount: {value!r}")
|
||||
|
||||
@property
|
||||
def _lnaddr(self) -> LnAddr:
|
||||
if self.__lnaddr is None:
|
||||
self.__lnaddr = lndecode(self.lightning_invoice)
|
||||
return self.__lnaddr
|
||||
|
||||
@property
|
||||
def rhash(self) -> str:
|
||||
return self._lnaddr.paymenthash.hex()
|
||||
|
||||
@classmethod
|
||||
def from_bech32(cls, invoice: str) -> 'Invoice':
|
||||
"""Constructs Invoice object from BOLT-11 string.
|
||||
@@ -259,6 +229,48 @@ class Invoice(StoredObject):
|
||||
lightning_invoice=None,
|
||||
)
|
||||
|
||||
def get_id(self) -> str:
|
||||
if self.is_lightning():
|
||||
return self.rhash
|
||||
else: # on-chain
|
||||
return get_id_from_onchain_outputs(outputs=self.get_outputs(), timestamp=self.time)
|
||||
|
||||
@attr.s
|
||||
class Invoice(BaseInvoice):
|
||||
lightning_invoice = attr.ib(type=str, kw_only=True) # type: Optional[str]
|
||||
__lnaddr = None
|
||||
|
||||
def get_address(self) -> Optional[str]:
|
||||
"""returns the first address, to be displayed in GUI"""
|
||||
address = None
|
||||
if self.outputs:
|
||||
address = self.outputs[0].address if len(self.outputs) > 0 else None
|
||||
if not address and self.is_lightning():
|
||||
address = self._lnaddr.get_fallback_address() or None
|
||||
return address
|
||||
|
||||
@property
|
||||
def _lnaddr(self) -> LnAddr:
|
||||
if self.__lnaddr is None:
|
||||
self.__lnaddr = lndecode(self.lightning_invoice)
|
||||
return self.__lnaddr
|
||||
|
||||
@property
|
||||
def rhash(self) -> str:
|
||||
return self._lnaddr.paymenthash.hex()
|
||||
|
||||
@lightning_invoice.validator
|
||||
def _validate_invoice_str(self, attribute, value):
|
||||
if value is not None:
|
||||
lnaddr = lndecode(value) # this checks the str can be decoded
|
||||
self.__lnaddr = lnaddr # save it, just to avoid having to recompute later
|
||||
|
||||
def can_be_paid_onchain(self) -> bool:
|
||||
if self.is_lightning():
|
||||
return bool(self._lnaddr.get_fallback_address())
|
||||
else:
|
||||
return True
|
||||
|
||||
def to_debug_json(self) -> Dict[str, Any]:
|
||||
d = self.to_json()
|
||||
d.update({
|
||||
@@ -274,11 +286,24 @@ class Invoice(StoredObject):
|
||||
d['r_tags'] = [str((a.hex(),b.hex(),c,d,e)) for a,b,c,d,e in ln_routing_info[-1]]
|
||||
return d
|
||||
|
||||
def get_id(self) -> str:
|
||||
if self.is_lightning():
|
||||
return self.rhash
|
||||
else: # on-chain
|
||||
return get_id_from_onchain_outputs(outputs=self.get_outputs(), timestamp=self.time)
|
||||
|
||||
@attr.s
|
||||
class Request(BaseInvoice):
|
||||
payment_hash = attr.ib(type=bytes, kw_only=True, converter=hex_to_bytes) # type: Optional[bytes]
|
||||
|
||||
def is_lightning(self):
|
||||
return self.payment_hash is not None
|
||||
|
||||
def get_address(self) -> Optional[str]:
|
||||
"""returns the first address, to be displayed in GUI"""
|
||||
address = None
|
||||
if self.outputs:
|
||||
address = self.outputs[0].address if len(self.outputs) > 0 else None
|
||||
return address
|
||||
|
||||
@property
|
||||
def rhash(self) -> str:
|
||||
return self.payment_hash.hex()
|
||||
|
||||
|
||||
def get_id_from_onchain_outputs(outputs: List[PartialTxOutput], *, timestamp: int) -> str:
|
||||
|
||||
Reference in New Issue
Block a user