An idea, is to ensure as much as possible that channel funding transactions have a "change" output that is controlled by the built-in onchain wallet.
Then, if the funding transaction takes a long time to confirm on mainnet (due to the well-known congestion problems there), it would be possible to accelerate the channel funding transaction by creating a child transaction from the "change" output. This child transaction would have a larger-than-usual feerate (CPFP) to encourage mining of the channel funding transaction, and pay out to yet another address of the built-in onchain wallet. In addition, the child transaction would be marked RBF so that further increases of the fee can be done.
Using CPFP to speed up the channel funding transaction has the advantage that it requires no change to the Lightning BOLT protocol. Using RBF on the channel funding transaction directly requires that the both ends of the channel sign new versions of the commitment transaction.
While not a priority, I suspect this feature would be necessary before we can practically deploy to mainnet.
At the JSON-RPC level, I imagine:
# open the channel but do not wait to confirm
tx=$(lightning-cli fundchannelasync $node $satoshis)
sleep 1h
# Not yet confirmed even after one hour...?
if [$(lightning-cli fundchannelconfirmed $tx) = False]; then
# If we accelerate, how much more will we spend?
moresatoshis=$(lightning-cli fundchannelaccelerateestimate $tx)
# so expensive! can we afford it?
if [$moresatoshis < $satoshithreshhold]; then
# fine, pay more to speed it up.
lightning-cli fundchannelaccelerate $tx
fi
fi
Further calls to fundchannelaccelerate will be possible and will RBF the child transaction instead.
The fundchannelaccelerate command will silently fail without an error if the specified channel is already confirmed at least once.
Implementation-wise, we would need a new table for pending channel funding transactions. Entries in this table will be removed when the peer enters CHANNELD_NORMAL.
CREATE TABLE funding_tx
( id INTEGER PRIMARY KEY REFERENCES channel(id) ON DELETE CASCADE
, funding_tx_change_outnum INTEGER
, cpfp_feerate INTEGER
);
When initially created only the funding_tx_change_outnum column has a non-null value. The first fundchannelaccelerate will fill in cpfp_feerate, with future calls bumping the feerate and recreating the CPFP acceleration transaction. fundchannelaccelerateestimate will compute a fee based on whether cpfp_feerate exists or not and assuming a simple 1-input 1-output RBF transaction. Care point is when the change output runs out: this will cause acceleration to fail as there is no longer any change to pay with.
Since lightningd will now scan UTXOs that appear onchain we should not use addfunds especially since the child transaction is RBF.
Thinking more, it seems that using RBF for onchain withdrawals requires withdrawals to wait for channel funding to confirm at least once, and channel funding to wait for withdrawals to confirm at least once.
The issue with using RBF is the below race condition:
Thus we cannot spend from the change output of an RBF transaction until the RBF transaction confirms deeply enough. At the minimum, we should suspend fundchannel commands if there are pending RBF withdrawals and there are not enough unspent coins, but the RBF withdrawal change output does have enough coins.
There is also the question of the below race condition:
In the above case we should use the transaction U and not T. Of course, deeper reorgs are also theoretically possible. Note that this is also important when we are receiving funds.
RBF gets complicated, so I suppose there is a reason why it is not well-implemented.
Ideally we should be able to accelerate both withdrawals and channel funding.
CPFP could be useful as a workaround, but I generally don't like it because it's quite expensive. If transaction A paid $1 in fees and is stuck, then in order to increase its effective fee to $1.50, you need to generate a child transaction B with $2 in fees. So you'd be spending $2, whereas RBF would only cost $0.50 (assuming equal size).
It's also cheaper to avoid change outputs when opening a channel, see #665.
I opened #668 to keep track of both approaches.
CPFP+RBF is simpler to implement under our current one-peer-one-channel architecture. Of course we probably want to have multiple channels per peer eventually, there are a few FIXME comments referring to those. Even so CPFP+RBF is still simpler to implement than my full RBF algo.
A more general approach would be to have txaccelerateestimate and txaccelerate. Then, not only fundchannel txid would be accepted, but also withdraw txid (and more generally, txsend/signpsbt txid) as well.
How to implement that is something of an open question however.
We can CPFP by creating a new transaction spending from the change output of any transaction we created ourselves. However, this new CPFP transaction should be RBF-able, so that further txaccelerate would just replace that transaction instead of chaining yet another CPFP on top of it.
But supporting RBF probably means additional complexity in our wallet logic. In particular, if we implement txaccelerate as plugin on top of fundinputs/reserveinputs/unreserveinputs/signpsbt/sendpsbt we have to be able to "unspend" an input in order to sign a higher-fee RBF. I think.
Thoughts @niftynei @rustyrussell ? I think you are the main people hacking around the new PSBT-based wallet bits currently.
Anyway here is a new proposed interface:
txacceleratestart txid => txacc_idStarts a transaction acceleration session. No additional funds will be spent, but creates an object, a txacc session, with a unique txacc_id, for use with other txaccelerate.
The txacc session is automatically destroyed when lightningd shuts down, or when the transaction originally being accelerated has been confirmed.
txaccelerateestimate txacc_id => total_fee delta_fee max_feeFor the given txacc session, gives an estimate on how much more a succeeding txaccelerate will cost. This might change when called multiple times, depending on current mempool/blockchain fee estimation.
max_fee is the amount that can be put into fees. If total_fee reaches max_fee and delta_fee is zero, then it is not possible to accelerate the transaction further, either because of lack of funds in the wallet, or if we are using CPFP to accelerate the transaction and there is insufficient change to accelerate the funds.
This may error with error code TXACCELERATE_ID_NOT_FOUND if the transaction was already confirmed.
txaccelerate txacc_id [total_fee] => total_fee delta_fee max_feeActually attempt to accelerate the transaction originally specified in txacceleratestart. If txaccelerateestimate was called, uses the most recent estimate, otherwise it will perform the estimation and then apply it immediately.
You may override the total_fee from the most recent estimation, providing a total_fee that is equal or larger than the total_fee from the most recent estimation, but less than the max_fee.
This may fail with error code TXACCELERATE_ID_NOT_FOUND if the transaction was already confirmed.
The above interface gives users some protection from lower-level details.
withdraw/txsend/sendpsbt transactions could also be CPFP-ed for now, for simplicity.withdraw/txsend/sendpsbt transaction where all inputs are owned only by our wallet, and which we know to be broadcast already, could in the future be RBFed instead of CPFPed.txid, so using a txacc_id gives the user a wrapper around this.max_fee equal to total_fee, and once the single-shot CPFP has been, uh, shotted, then we set max_fee to total_fee with a delta_fee of 0 to indicate to the user that it cannot be accelerated further. This allows us to provide this interface minimally (just one shot, and the tx has to have a change output we can CPFP on) without having to handle any kind of RBF yet, at least for now.What do you think? @Sjors @niftynei @rustyrussell @cdecker @darosior ?
Hi @rustyrussell @cdecker
Is there any hope to get CPFP or RBF on pending channel open transactions?
The current state of mempool is making this a burning requirement, as a-lot of people inadvertently low ball the channel opening fee and then are stuck in mempool with pending transactions.
This would be an awesome addition to the project and would definitely be helpful in this fee environment
You can do CPFP today if you use an external wallet to make the funding tx
and it has a change output.
RBF has been implemented for experimental dual-funding/v2 opens.
On Fri, Mar 26, 2021 at 18:28 Evan Kaloudis @.*>
wrote:
This would be an awesome addition to the project and would definitely be
helpful in this fee environment—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/ElementsProject/lightning/issues/475#issuecomment-808586617,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AAIMAKPPRS37PWSSS4SSRQTTFUKDJANCNFSM4EJUVVFA
.
The withdraw command worked for me (as CPFP bump).
lightning-cli withdraw NEW_CHANGE_ADDRESS all 100000 0 [FUNDING_UNCONFIRMED_TXID:CURRENT_CHANGE_INDEX]
_* 100000 = 100sat/vbyte_
Most helpful comment
Hi @rustyrussell @cdecker
Is there any hope to get CPFP or RBF on pending channel open transactions?
The current state of mempool is making this a burning requirement, as a-lot of people inadvertently low ball the channel opening fee and then are stuck in mempool with pending transactions.