don't use fallback feerates in lightning by default
This commit is contained in:
@@ -23,8 +23,8 @@ from .crypto import sha256, sha256d, privkey_to_pubkey
|
||||
from . import bitcoin, util
|
||||
from . import constants
|
||||
from .util import (bfh, log_exceptions, ignore_exceptions, chunks, OldTaskGroup,
|
||||
UnrelatedTransactionException, error_text_bytes_to_safe_str, AsyncHangDetector)
|
||||
from .util import event_listener, EventListener
|
||||
UnrelatedTransactionException, error_text_bytes_to_safe_str, AsyncHangDetector,
|
||||
NoDynamicFeeEstimates, event_listener, EventListener)
|
||||
from . import transaction
|
||||
from .bitcoin import make_op_return, DummyAddress
|
||||
from .transaction import PartialTxOutput, match_script_against_template, Sighash
|
||||
@@ -993,7 +993,9 @@ class Peer(Logger, EventListener):
|
||||
raise Exception('Not a trampoline node: ' + str(self.their_features))
|
||||
|
||||
channel_flags = CF_ANNOUNCE_CHANNEL if public else 0
|
||||
feerate = self.lnworker.current_target_feerate_per_kw()
|
||||
feerate: Optional[int] = self.lnworker.current_target_feerate_per_kw()
|
||||
if feerate is None:
|
||||
raise NoDynamicFeeEstimates()
|
||||
# we set a channel type for internal bookkeeping
|
||||
open_channel_tlvs = {}
|
||||
assert self.their_features.supports(LnFeatures.OPTION_STATIC_REMOTEKEY_OPT)
|
||||
@@ -1598,6 +1600,11 @@ class Peer(Logger, EventListener):
|
||||
# We should let them know:
|
||||
self._send_channel_reestablish(chan)
|
||||
return
|
||||
if self.network.blockchain().is_tip_stale() \
|
||||
or not self.lnworker.wallet.is_up_to_date() \
|
||||
or self.lnworker.current_target_feerate_per_kw() is None:
|
||||
# don't try to reestablish until we can do fee estimation and are up-to-date
|
||||
return
|
||||
# if we get here, we will try to do a proper reestablish
|
||||
if not (ChannelState.PREOPENING < chan.get_state() < ChannelState.FORCE_CLOSING):
|
||||
raise Exception(f"unexpected {chan.get_state()=} for reestablish")
|
||||
@@ -2590,12 +2597,16 @@ class Peer(Logger, EventListener):
|
||||
return
|
||||
if chan.get_state() != ChannelState.OPEN:
|
||||
return
|
||||
feerate_per_kw = self.lnworker.current_target_feerate_per_kw()
|
||||
def does_chan_fee_need_update(chan_feerate: Union[float, int]) -> bool:
|
||||
feerate_per_kw: Optional[int] = self.lnworker.current_target_feerate_per_kw()
|
||||
if feerate_per_kw is None:
|
||||
return
|
||||
def does_chan_fee_need_update(chan_feerate: Union[float, int]) -> Optional[bool]:
|
||||
# We raise fees more aggressively than we lower them. Overpaying is not too bad,
|
||||
# but lowballing can be fatal if we can't even get into the mempool...
|
||||
high_fee = 2 * feerate_per_kw # type: Union[float, int]
|
||||
low_fee = self.lnworker.current_low_feerate_per_kw() # type: Union[float, int]
|
||||
low_fee = self.lnworker.current_low_feerate_per_kw() # type: Optional[Union[float, int]]
|
||||
if low_fee is None:
|
||||
return None
|
||||
low_fee = max(low_fee, 0.75 * feerate_per_kw)
|
||||
# make sure low_feerate and target_feerate are not too close to each other:
|
||||
low_fee = min(low_fee, feerate_per_kw - FEERATE_PER_KW_MIN_RELAY_LIGHTNING)
|
||||
|
||||
@@ -3000,21 +3000,28 @@ class LNWallet(LNWorker):
|
||||
else:
|
||||
await self.taskgroup.spawn(self.reestablish_peer_for_given_channel(chan))
|
||||
|
||||
def current_target_feerate_per_kw(self) -> int:
|
||||
def current_target_feerate_per_kw(self) -> Optional[int]:
|
||||
if self.network.fee_estimates.has_data():
|
||||
feerate_per_kvbyte = self.network.fee_estimates.eta_target_to_fee(FEE_LN_ETA_TARGET)
|
||||
else:
|
||||
if constants.net is not constants.BitcoinRegtest:
|
||||
return None
|
||||
feerate_per_kvbyte = FEERATE_FALLBACK_STATIC_FEE
|
||||
return max(FEERATE_PER_KW_MIN_RELAY_LIGHTNING, feerate_per_kvbyte // 4)
|
||||
|
||||
def current_low_feerate_per_kw(self) -> int:
|
||||
def current_low_feerate_per_kw(self) -> Optional[int]:
|
||||
if constants.net is constants.BitcoinRegtest:
|
||||
feerate_per_kvbyte = 0
|
||||
else:
|
||||
if not self.network.fee_estimates.has_data():
|
||||
return None
|
||||
feerate_per_kvbyte = self.network.fee_estimates.eta_target_to_fee(FEE_LN_LOW_ETA_TARGET) or 0
|
||||
low_feerate_per_kw = max(FEERATE_PER_KW_MIN_RELAY_LIGHTNING, feerate_per_kvbyte // 4)
|
||||
# make sure this is never higher than the target feerate:
|
||||
low_feerate_per_kw = min(low_feerate_per_kw, self.current_target_feerate_per_kw())
|
||||
current_target_feerate = self.current_target_feerate_per_kw()
|
||||
if not current_target_feerate:
|
||||
return None
|
||||
low_feerate_per_kw = min(low_feerate_per_kw, current_target_feerate)
|
||||
return low_feerate_per_kw
|
||||
|
||||
def create_channel_backup(self, channel_id: bytes):
|
||||
|
||||
@@ -44,8 +44,7 @@ from electrum.lnutil import LOCAL, REMOTE
|
||||
from electrum.invoices import PR_PAID, PR_UNPAID, Invoice
|
||||
from electrum.interface import GracefulDisconnect
|
||||
from electrum.simple_config import SimpleConfig
|
||||
from electrum.fee_policy import FeeTimeEstimates
|
||||
|
||||
from electrum.fee_policy import FeeTimeEstimates, FEE_ETA_TARGETS
|
||||
|
||||
from .test_lnchannel import create_test_channels
|
||||
from .test_bitcoin import needs_test_with_all_chacha20_implementations
|
||||
@@ -69,6 +68,7 @@ class MockNetwork:
|
||||
self.lnwatcher = None
|
||||
self.interface = None
|
||||
self.fee_estimates = FeeTimeEstimates()
|
||||
self.populate_fee_estimates()
|
||||
self.config = config
|
||||
self.asyncio_loop = util.get_asyncio_loop()
|
||||
self.channel_db = ChannelDB(self)
|
||||
@@ -95,6 +95,10 @@ class MockNetwork:
|
||||
async def try_broadcasting(self, tx, name):
|
||||
await self.broadcast_transaction(tx)
|
||||
|
||||
def populate_fee_estimates(self):
|
||||
for target in FEE_ETA_TARGETS[:-1]:
|
||||
self.fee_estimates.set_data(target, 50000 // target)
|
||||
|
||||
|
||||
class MockBlockchain:
|
||||
|
||||
@@ -144,6 +148,9 @@ class MockWallet:
|
||||
# note: sweep is not tested here, only in regtest
|
||||
return "tb1qqu5newtapamjchgxf0nty6geuykhvwas45q4q4"
|
||||
|
||||
def is_up_to_date(self):
|
||||
return True
|
||||
|
||||
|
||||
class MockLNGossip:
|
||||
def get_sync_progress_estimate(self):
|
||||
|
||||
Reference in New Issue
Block a user