Fixes #12429
This value is listed as required in the docs, but not enforced as such. We should update the docs if it's not required.
utACK
I wouldn't mind argument checks for the other prevtx arguments, if none exist, but not a blocker.
@instagibbs Did you have any specific sort of testing in mind? Everything except redeemScript is tested, but redeemScript is not required in all cases.
Scratch that - redeemScript is tested here:
https://github.com/bitcoin/bitcoin/pull/12458/files#diff-01aa7d1d32f1b9e5a836c9c411978918L839
I mean tested inside functional tests, sorry.
It should only be required when signing a segwit input, no?
Agree with sipa. There is no need to enforce amounts for non SW inputs...
Gotcha - I'll revise.
This is up for grabs, fyi.
Thanks @ajtowns for picking this up! Heavily inspired by your work, I updated this PR. Relatively minor differences:
It is perfectly valid to spend UTXOs with value 0.
@Empact 0-value outputs are completely legal and spendable.
@Empact I don't understand. The segwit sighashing scheme in BIP143 requires including the amount into the message being hashing. If the amount is zero, then it simply means the signature must be valid for a signature on a message that includes 0 in that position.
Updated tests as per @MarcoFalke's feedback #13547 (review)
810 | @@ -811,7 +811,7 @@ UniValue SignTransaction(CMutableTransaction& mtx, const UniValue& prevTxsUnival 811 | } 812 | Coin newcoin; 813 | newcoin.out.scriptPubKey = scriptPubKey; 814 | - newcoin.out.nValue = 0; 815 | + newcoin.out.nValue = MAX_MONEY;
I was wondering if MAX_MONEY should be used, because MAX_MONEY (like the value 0 that it replaces) is a valid amount isn't it?
Please feel free to ignore this, but alternatively to express intent more directly,
newcoin.out.nValue = MAX_MONEY;
if (prevOut.exists("amount")) {
newcoin.out.nValue = AmountFromValue(find_value(prevOut, "amount"));
}
can be replaced with a conditional expression:
newcoin.out.nValue = prevOut.exists("amount") ? AmountFromValue(find_value(prevOut, "amount")) : MAX_MONEY;
881 | @@ -882,6 +882,11 @@ UniValue SignTransaction(CMutableTransaction& mtx, const UniValue& prevTxsUnival 882 | } 883 | sigdata = CombineSignatures(prevPubKey, TransactionSignatureChecker(&txConst, i, amount), sigdata, DataFromTransaction(mtx, i)); 884 | 885 | + // amount required for valid segwit signature 886 | + if (amount == MAX_MONEY && !sigdata.scriptWitness.IsNull()) {
Please do ignore this if comparing against MAX_MONEY is valid, but if it isn't and you will be using an amount outside of the range [0,MAX_MONEY] then the boolean expression needs to be addressed. I suspect something along these lines would work:
if (!MoneyRange(amount) && !sigdata.scriptWitness.IsNull()) {
Fixes #12429
Fair enough, added INVALID_MONEY as an alternative magic value.
Thanks @sipa, this confirmation is very valuable.
I tried to set out in #13547 (review) why it was confusing to me. Perhaps, for the avoidance of doubt, it would be good to add your clarification it to the MAX_MONEY documentation.
Apologies for the noise, I hope there was at least some value.
<!--cf906140f33d8803c4a75a2196329ecb-->Needs rebase