A PR by Andrew Chow to allow the (RPC) user to specify the weights of external inputs when funding a transaction. Participants discussed what exactly are external inputs, why we might need to specify weights and talked through implementation details.
- external input is an input that the wallet is unable to solve for, where solving means that if it had private keys available, a spending transaction could be created. This usually means that the wallet is unaware of those inputs as it is not watching for them, but there are some cases where the wallet may be watching for those inputs but lack solving data.
What are some use cases of allowing external inputs to be used in send
, walletcreatefundedpsbt
, fundrawtransaction
, and bumpfee
? 🔗
- Spending Lightning HTLCs inputs, spending from a commitment transaction (ie not a collaborative 2-of-2 close).
Why might a user want to specify input weights instead of using the existing solving_data
option? 🔗
- Because the external inputs functionality supports only the set of standard scripts that Bitcoin Core would be able to sign too. So this is not applicable to more complex scripts because Core doesn't know what the input will look like.
- It's about knowing what the input will look like, so future Miniscript support will help as miniscript will be provided as
solving_data
, but miniscript does not cover all cases either.
Why does FundTransaction()
need to know the external inputs ahead of time at all? 🔗
- We need to be able to estimate fees when setting the inputs for a transaction. When we're funding the transaction, we're trying to put fees on it to reach a target feerate. If we don't know what the weight will be, we won't know how much in fees to put on it.
- A known scriptPubKey can have an unknown scriptSig length. E.g. if you know a P2SH scriptPubKey, you don't know how long the scriptSig is going to be (script is unknown until input is spent).
The RPCs will throw a JSONRPCError: RPC_INVALID_PARAMETER
if the specified weight is below 165. Why can’t the weight of an input be less than 165? (Hint: see the definition of GetTransactionInputWeight() and witness serialization specified in BIP144). 🔗
- 165 is the smallest possible input, which is a completely empty input.
- Calculations:
- an empty input = (size of outpoint + sequence + empty scriptSig) * 4
- the outpoint = txid + txindex in vout
- = (32 txid + 4 txindex + 1 scriptlen + 4 sequenco_no) * 4 = 164 weight units
- +1 byte for empty witness that requires 1 byte to encode its size (which is 0)
- = 165 weight units
- an empty input = (size of outpoint + sequence + empty scriptSig) * 4
In the interface modified by this PR, how would a user call {send
, walletcreatefundedpsbt
, fundrawtransaction
} to specify a maximum input weight? 🔗
- With a new argument called
input_weights
which is expected to contain an array of dicts, which should include the fieldstxid
,vout
, and the explicitly definedweight
of that tx. In other words, a mapping from outpoint to max weight.
What is a Compact Size Unsigned Integer? Where is it used in the Bitcoin protocol? 🔗
- It's a type of variable-length integer to indicate the number of bytes in a following piece of data. Usually used to encode things like how many stack elements you have, how many bytes something is, etc.
- Presumably because you save a lot of space when you're encoding small numbers, i.e. while you want to be able to encode large numbers, in the vast majority of cases you only need 1 byte to encode size.
- The Bitcoin P2P protocol only has one variable-length integer serialization format, namely the "compactsize" one. But it internally has another, more complex but slightly smaller one, which is used in its UTXO set database serialization. The latter is called VarInt in the codebase. But CompactSize is also "a" varint format, and is often referred to as such.
- Originally CompactSize Unsigned Integers were only used for the length of vectors or other things, not as a generic number encoding. The BIP-152 compact block encoding however started using the compactsize encode for non-length things.