Conversation
|
Cool! I believe this is correct. I'd like to play with this in rust-miniscript but happy to slip it into a release before then. We still have some breaking changes over the next few releases so it's not the end of the world if it turns out we want to iterate on this. (One thing I'm waffling on is whether to use usize here or utACK 62229eeddba69ed5df02a72d35b2e92c8c512c50 though let's get #1627 in first. |
0c4f097 to
8c7a073
Compare
|
Rebased and fixed typos/grammar. Should be ready for review. |
apoelstra
left a comment
There was a problem hiding this comment.
ACK 8c7a0736713ebae7369c53d801766623d3e7b00e
sanket1729
left a comment
There was a problem hiding this comment.
Reviewed the fee calculation carefully, just some comments on the docs
bitcoin/src/blockdata/transaction.rs
Outdated
There was a problem hiding this comment.
Brainstorming if we can make this API a method in Transaction. Almost all users would be creating a tx with an empty witness. And then calling output.map(|o| o.script_pubkey.len()) for the output_scripts_len. Then, setting the fee output accordingly.
I guess it will be really ugly to use for inputs because some of them might have witnesses filled in.
There was a problem hiding this comment.
I also thought about this a bit. I think in a later PR we can maybe make some constructors for these iterators which can be created off of a (potentially incomplete) transaction.
Agree that in the majority of cases users will be starting with some sort of transaction and trying to estimate its final form.
There was a problem hiding this comment.
I had the same idea and was about to make the method for output iterator but realized that I actually don't have this flow because it would require to add an output with bogus amount (presumably 0) and then change it... Which is not really that nice. I prefer to calculate everything first and only then construct the transaction. But I can add the method back if you want, it's one line of code.
There was a problem hiding this comment.
I think it'd be worthwhile, yeah. I think rust-miniscript is going to use this method, and in Miniscript we assume that all inputs and outputs are present, just (potentially) not witnesses.
When creating a transaction one must know the the fee beforehand to set appropriate amounts for outputs and to know the fee, weight is required. So far we only had a method on an already-constructed transaction. This method clearly wasn't helpful when constructing the transaction except for hacks like temporarily adding an all-zeroes signature. This change adds a function that can compute the transaction weight without knowing individual bytes of the scripts, witnesses and other elements. It only needs to know their sizes. To make the API less error-prone a special, trivial, type is also added for computing the lengths of witnesses.
8c7a073 to
cf068d1
Compare
|
Addressed documentation issues. |
In some cases people construct the transaction with a dummy fee output value before calculating the weight. A method to create the iterator over `script_pubkey` lengths is useful in such cases.
|
Seems pretty clearly latest nightly introduced some compiler bug, I've filed ICE bug. |
|
Nightly bug confirmed and should be fixed tomorrow. I don't mind waiting those two days for merge since it looks like there's no conflicting PR but I also wouldn't mind just merging it. |
| /// When signing a transaction one doesn't know the signature before knowing the transaction fee and | ||
| /// the transaction fee is not known before knowing the transaction size which is not known before | ||
| /// knowing the signature. This apparent dependency cycle can be broken by knowing the length of the | ||
| /// signature without knowing the contents of the signature e.g., we know all Schnorr signatures | ||
| /// are 64 bytes long. |
There was a problem hiding this comment.
Hey, I just saw this PR mentioned in the Bitcoin Optech Newsletter, and wanted to point out that there is a trick to avoiding the catch-22 between transaction weight, input count, and fees. When you build a transaction, you know the recipient outputs you wish to create. You also know the size of the metadata (version, input counter, output counter, locktime, optionally witness marker and witness flag). Before building a transaction, you usually also know the feerate that you wish to achieve with the transaction.
This allows you to calculate the transaction weight of the “fixed part” of the transaction, and per the feerate, the necessary fees for that fixed part. For the inputs, you calculate their effective value. For each input you calculate the weight it will take to add the specific input to a transaction, multiply that weight with the feerate, and deduct this “input fee” from that input’s value. After this preprocessing step, when you pick UTXOs to fund the transaction, you count only their effective value towards the target (i.e. recipient amounts plus “fixed parts fees”)—this makes the selection of inputs fee-neutral because the effective value accounts for the input paying for itself. The target can additionally be adjusted for whether you expect to create a change output, how valuable the change should be at least, and what output type the change is intended to have.
I described an efficient transaction building process using UTXO’s effective value here on Stack Exchange.
There was a problem hiding this comment.
Where is the PR mentioned? I don't see it.
Thanks for the idea, we should definitely add support for this. Note that the approach implemented in this PR is still useful when the coin selection is literally "select all". (I have a reasonable use case for this; no, it won't destroy privacy - "all" is normally exactly one UTXO of one address, in rare cases multiple UTXOs of the same address.)
There was a problem hiding this comment.
the very last bullet https://bitcoinops.org/en/newsletters/2023/02/22/
There was a problem hiding this comment.
@Kixunil: Sorry, I was looking at the open Newsletter-PR before the Newsletter got published this morning. :)
When creating a transaction one must know the the fee beforehand to set
appropriate amounts for outputs and to know the fee, weight is required.
So far we only had a method on an already-constructed transaction. This
method clearly wasn't helpful when constructing the transaction except
for hacks like temporarily adding an all-zeroes signature.
This change adds a function that can compute the transaction weight
without knowing individual bytes of the scripts, witnesses and other
elements. It only needs to know their sizes.
To make the API less error-prone a special, trivial, type is also added
for computing the lengths of witnesses.
Based on #1627