Motivation

Simple: saving on tx fees. First, the opening tx is smaller - for 1 input and 1 output, is is 111 vb instead of 154 vb. Second, no need to redeem that change output, which saves another 58 vb. (Assuming taproot for the input and change.)

Limitations

My method below only works for fee < 47 sats/vb. And it is rather clumsy.

How

We need 2 terminals, one for creating a tx, another one for opening the channel.
Switch to terminal 1. Choose UTXOS we want to spend. UTXOS="--utxo <TXID>:<OUTPUT_NUM> --utxo <TXID>:<OUTPUT_NUM>"
Now we find out how much exactly we can send (after subtracting fees). We need some dummy P2WKH address (the long, 62 characters). For example, we may copy the destination address of any channel opening, I will use bc1q4n5edfv92ux9vxja2j47xlxd94ae0cq9u6nkz3qu3uh6rnezevqsc8pru0, which corresponds to an already closed channel between Bitrefill Routing and VN.Sovereign. It is possible to batch open several channels this way, but then we would need distinct dummy addresses. Divide your desired fee by 1.48 - so if you want fee 30 sats/vb, 30/1.48 = 20.27 , so we use --fee-rate 20. This math only works for 1 input, you may want try various fee rates.
./bos fund -v --dryrun $UTXOS --fee-rate 20 bc1q4n5edfv92ux9vxja2j47xlxd94ae0cq9u6nkz3qu3uh6rnezevqsc8pru0 MAX-200 send_to: - bc1q4n5edfv92ux9vxja2j47xlxd94ae0cq9u6nkz3qu3uh6rnezevqsc8pru0: 0.06233683 requested_fee_rate: 20 sum_of_outputs: 0.06233683 spending_utxos: - [redacted] fee_tokens_per_vbyte: 29.73 signed_transaction: [redacted]
We cannot spend MAX, we would get error (not enough funds, ironically) we need to spend MAX - 10*<fee_rate>. Watch the send_to: section, whether there is a change output - not our case. Copy the amount and convert it from BTC to sats , we get 0.06233683 BTC = 6233683 sats. Bos always uses 8 decimals, so we can just copy the decimal part.
Switch to terminal 2 and initiate a channel opening with the amount we obtained, and using --external-funding flag. This is a bit counter-intuitive, we are really doing internal funding, just controlled by us. The node ID used is Bitrefill Routing.
./bos open --type public --external-funding --amount 6233683 030c3f19d742ca294a55c00376b3b355c3c90d61c6b6b39554dbc7ac19b141c14f - node: Bitrefill Routing channels_per_peer: 1.09 is_accepting_large_channels: true opening_to: - Bitrefill Routing: 0.06233683 connecting_to: alias: Bitrefill Routing public_key: 030c3f19d742ca294a55c00376b3b355c3c90d61c6b6b39554dbc7ac19b141c14f funding_deadline: Today at 12:56 PM fund: fund bc1qucuz7nufnc5yku7d4dy5ltaspk3u6gpk4cth5687swhssj5mkxks2fa7jr 6233683 bc1qucuz7nufnc5yku7d4dy5ltaspk3u6gpk4cth5687swhssj5mkxks2fa7jr, 0.06233683 ? Enter signed transaction or PSBT that pays 0.06233683 to bc1qucuz7nufnc5yku7d4dy5ltaspk3u6gpk4cth5687swhssj5mkxks2fa7jr or press enter to cancel funding.
Copy the address and amount (line 17) and go back to terminal 1. Use the previous fund command, but delete --dry-run and use the address and amount from previous step instead of dummy address. Triple check here, you are now creating a real tx, although not broadcasting it yet.
./bos fund -v $UTXOS --fee-rate 20 bc1qucuz7nufnc5yku7d4dy5ltaspk3u6gpk4cth5687swhssj5mkxks2fa7jr 6233683 send_to: - bc1qucuz7nufnc5yku7d4dy5ltaspk3u6gpk4cth5687swhssj5mkxks2fa7jr: 0.06233683 requested_fee_rate: 20 sum_of_outputs: 0.06233683 spending_utxos: - [redacted] fee_tokens_per_vbyte: 29.73 signed_transaction: 020... [redacted]
You may check the signed transaction for example by importing it to electrum (menu->tools->load transaction->from text) to check that you are sending to address(es) given by bos open.
Copy the signed transaction to clipboard, switch to terminal 1, and paste it here.

Future

lnd openchannel has a new flag --fundmax, which tries to spend all funds in the lnd's onchain wallet. I tried to "lease" (lock) all my UTXOs except one or two, but it insisted on creating a 100k change as reserve for anchor channels. Even when I left a 100k UTXO unlocked, it spent it and created 100k change.
This PR should implement it directly in lnd.
well done, this is good.
reply
Thanks, means a lot coming from you. I expected negative reactions, "are you crazy? This much work and fiddling?". But it may be more difficult to read it than to actually do it. Maybe those critics will come later. :)
reply
No, why should I critique you for this? Is a solution proposal that have a use case. This is good for node runners. I always try to do this, but in another manner. Is hard to deal with dust utxos when you open channels.
reply
Hehe, I guess I am conditioned by reddit.
Could you write about your method? At least briefly, I know it takes some time to write it properly.
Btw I have another method - export your private keys by chantools genimportscript -/format bitcoin-descriptors, and import the private key you want in e.g. electrum, and then create funding tx with electrum. But this rules out taproot outputs because electrum does not support them. And I tried importing the file from chantools by bitcoin-cli importwallet, but did not succeed.
And I swear I saw a question about this on bitcoin.stackexchange.com some months ago, but tried searching now and did not find it.
reply
If you want to import your LND aezeed into another wallet app, use Sparrow. I explained here (see point 5) how to do it.
But my method is to not use an external wallet app for my LND node. I keep it simple, if I have to open a new channel:
  • always keep ONE UTXO with 100k sats for the fucking stupid anchor reserve. Untouched. Is stupid but there's no other way for the moment.
  • send the amount of sats for the channel to the onchain node wallet, 1 UTXO
  • Calculate exactly the fee in total sats to open that channel and adjust exactly the amount of the channel, slightly lower, in case are necessary some msats in the opening. You can do this in RTL or Thunderhub, puting a higher amount intentionally so will calculate and will give you exactly the difference you will have to deduct for the fee. Then just adjust the amount of the channel deducting the fee that was missing.
Done, will open a channel with the entire UTXO, not touching the anchor UTXO. I hope soon we will have an nice option to "send all" at LN code level.
reply
Sparrow can import azeed? I didn't see such option... But Zap desktop can (via recovery option), trying that now.
Your method involves 1 extra on-chain transaction, which defeats the purpose IMHO. You do avoid the change output, but the on-chain footprint is at least 2*111 = 222 vb for the channel opening.
So perhaps my method is cheaper... and more tedious.
reply
Indeed, Zap desktop can import it directly the seed. With Sparrow you need to do some additional steps. Ah sorry, I forgot to add the link (see point 5). https://darthcoin.substack.com/p/umbrel-btcln-node-shtf-scenario
reply
great, it works in Sparrow. Perhaps you want to update your article, I had to create 2 wallets in Sparrow, one for segwit (m/84'/0'/0' as you mention) and one for taproot (m/86'/0'/0'). Then Sparrow allows fine-grained control, so my original post is now partially obsolete. :)
My updated workflow will be: create a tx to dummy P2WSH address in Sparrow to determine maximum sendable amount, initiate channel opening with this amount (basically the same bos open as in the original post) and send from Sparrow to address given by bos open.
very nice!
reply
Thank you, it is a great idea. I’ll try it, but it looks more difficult than appear 😅