Hey everyone,
I could use some help here. I'm working on creating my own transactions with createrawtransaction, signrawtransactionwithwallet, and sendrawtransaction to deal with the CPFP issue in bitcoin core...
Is there any risk of accidentally making an unspendable output? I've been receiving some payments, and occasionally, folks send them with really low fees. My plan is to consolidate those and pull in the unconfirmed UTXOs from those senders.
But I’m a bit anxious about possibly creating an unspendable output by mistake. The docs don’t really cover this, so I’m guessing it’s not an issue?
I did a test run, and I got this:
"spendable": true,
"solvable": true
when I checked in the receiving wallet. Does this mean the output can definitely be used again?
Thanks in advance!
Hmm, the command accepts addresses so the only way to create an output that your wallet can't spend is if you've mistyped your address but its checksum is valid.
Or if you've indicated a "data" output which surely wont happen by accident.
I'm more concerned on the handling of the change since the value has to be precisely calculated, else, all excess amount will be used as fee.
If in doubt, you can use decoderawtransaction to see the transaction in human-readable json format.
Check the output's address with getaddressinfo command and if you see those results (in your test run) and "iswatchonly": false", then it's good.
Thanks for the reply!
Yeah, I'm decoding the transaction afterwards to see if the transaction makes sense. I'm taking care of the fee, yes. The address I sent too isn't a new address so the `iswatchonly` is false (but then, the wallet I've tested this is a watch only wallet, ... (since it's a live server...)
We have a a few people now and then that send payments with too low a fee and we want to do the "nice" thing to speed them up when we consolidate so they don't have to wait forever. It worked well, but I've tested it on a cheap transaction (less than 100,000sats) and I want to see if there any common pitfalls before I deploy this as a general automated thing.
If Bitcoin Core would support including unconfirmed UTXO (perhaps from the enable(d) coin control features) that would be great. I think the change in the code may be minor, but I'm not a good enough coder to even try setting up compiling it myself.
Back to the topic, I'm actually making two transactions. I'm making one with a dummy 0.00000001 fee first, then see what the vsize is, then applying the correct fee for the final transaction throwing away the first one. Surely there must be a better way ?
And I can see the sendrawtransactions has a failsafe to send transactions with high fees, I've of course set that to a prudent value. The default value of 0.1 BTC/vKB is way too high. The maxburnamount is set to 0.00 but as it's written in the doc it's not a guarantee that the output can be spent under all circumstances.
But yeah, I'm just using these commands (create, sign, and send-raw transaction) and if there is no way I can create an unspendable output this way (considering fee and receive address) then I've something less to worry about.
When you specify specific outputs to use to any of the commands that do coin selection, the resulting transaction will be automatically CPFP'd if any of the selected inputs require it to meet the desired feerate.
You can use the send RPC with inputs specifying the particular inputs you want spent, and outputs with the addresses and amounts that you want to send to. The RPC will take care of choosing any additional coins necessary to meet the spending requirements, calculating and setting the transaction fee, and creating a change output. It will also sign and send the transaction, but you can also have it just return the final transaction to you to be inspected and then you can send it yourself. There's no need to do the raw transaction workflow to do all of coin selection and transaction creation manually.
Thanks, however I seem to be unable to do this via the GUI. Even when selecting outputs manually it only shows those that have confirmations, I cannot choose an output that is unconfirmed.
So it seems CPFP is impossible via the GUI.
I haven't seen what happens if I try to do it via 'sendtoaddress' RPC but I'm pretty sure it will just say "insufficient balance" if I try to include the whole balance of confirmed and unconfirmed UTXO.
I believe creating a rawtransaction is the only way to do CPFP in Bitcoin Core and that's why I've implemented it this way. Please let me know if I'm wrong :-)
Yes, it is not available in the GUI, only the RPC commands.
As I said in my previous post, you can use the send command. This is an entirely different command from sendtoaddress and the *rawtransaction commands.
We should probably look into implementing this feature for the GUI then.
There is a shell you can access from the Tools or the Help menu I think, that lets you type RPC commands without having to shut down the GUI and start the daemon (and then do the same again to get back to the GUI), but I think it might be a good idea to use a checkmark for "Use CPFP for this transaction" that is unselected by default.
Have not tried this ...
CPFP is implemented in Core via the include_unsafe parameter in the fundrawtransaction, send and walletcreatefundedpsbt RPCs
This could be simpler than using createrawtransaction
Merchant-initiated CPFP is a good idea, if you don't mind paying the fee the customer failed to pay, and if you're careful not to pay so much that the fee wipes out the payment - eg when fee rates surge to 600 Sat/vbyte for a few blocks as happened recently
Your CPFP strategy is unlikely to make unspendable transactions in the way you're describing. Testnet is useful to discover consensus-unspendable transactions (bad scripts, and various size limits). Testnet mostly ignores policy rules which might make a transaction policy-unspendable on Mainnet. You can configure a testnet node to implement policy rules, or use Signet instead. Policy rules restrict non-standard transactions, and minor things like large OP_RETURNs or multiple OP_RETURNs. But it's unlikely any of those issues apply to the consolidation/CPFP transactions you're planning to make
cf https://github.com/bitcoin/bitcoin/pull/21359
Thanks a lot, very helpful!
Yeah, I'm actually quite comfortable with createrawtransaction from an API and parameter stand point. What I do is to always display the whole transaction (decoderawtransaction) including all inputs, outputs and fees and a breakdown in percentages to make sure that all is good.
I haven't tried on a bigger transaction and I'm too lazy to set up testnet, all my bitcoin dev was always done live and I've never lost any funds but for this project I'm a bit cautious for obvious reasons. I'm happy to experiment in the 10-20 USD range if blockchain fees allow.
Yes, if consolidating, picking up the fee for 1-2 transaction makes the cost negligible if you're consolidating >50 transactions anyway (and I try to keep them around 100 or a bit less - need to work out what is the best tradeoff in regards to diminishing returns and taking advantage of low blockchain fees at that moment is)
One thing I've not figured out is an easy way to see the size of the transaction beforehand to make a good calculation of the fee. I'm creating two transactions actually, first one with a dummy fee of 1sat, and then replacing this when I know the actual size of transaction and fire off only the latter one.
Thanks, yes I'm doing this but to make it effective, I have to do another transaction with the final vsize...
I was wondering if there is another RPC that would allow me to get the vsize easily without building the transaction first.
There is not.
However, you can use fundrawtransaction which will do size estimation to apply the fees for you, and add a change output if necessary, and add additional inputs if necessary. It will use the inputs that you have already specified in the provided transaction.
Furthermore, as I have said in previous posts, you can do all of this with the send RPC. I don't understand why you are insisting on doing everything by hand the hard (and deprecated) way when everything you want to do is already built in.
Thanks. Yeah if I had known it's deprecated I wouldn't have used it. If it's marked as such, I've overlooked.
But I've already developed it, so ... sunk cost fallacy :-)