Don't calculate tx fees for PSBTs with invalid money values
In decodepsbt if an invalid amount is seen, don't calculate the fee but still show the invalid value in the decode. In analyze psbt, if an invalid amount is seen, set the next step to be the creator as the creator needs to remake the transaction so that it is valid. Github-Pull: #17156 Rebased-From: f1ef7f0aa46338f4cd8de79696027a1bf868f359
This commit is contained in:
parent
178a834687
commit
1cf77a2dc3
3 changed files with 40 additions and 3 deletions
|
@ -2,6 +2,7 @@
|
|||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <amount.h>
|
||||
#include <coins.h>
|
||||
#include <consensus/tx_verify.h>
|
||||
#include <node/psbt.h>
|
||||
|
@ -31,6 +32,10 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
|
|||
// Check for a UTXO
|
||||
CTxOut utxo;
|
||||
if (psbtx.GetInputUTXO(utxo, i)) {
|
||||
if (!MoneyRange(utxo.nValue) || !MoneyRange(in_amt + utxo.nValue)) {
|
||||
result.SetInvalid(strprintf("PSBT is not valid. Input %u has invalid value", i));
|
||||
return result;
|
||||
}
|
||||
in_amt += utxo.nValue;
|
||||
input_analysis.has_utxo = true;
|
||||
} else {
|
||||
|
@ -85,9 +90,16 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
|
|||
// Get the output amount
|
||||
CAmount out_amt = std::accumulate(psbtx.tx->vout.begin(), psbtx.tx->vout.end(), CAmount(0),
|
||||
[](CAmount a, const CTxOut& b) {
|
||||
if (!MoneyRange(a) || !MoneyRange(b.nValue) || !MoneyRange(a + b.nValue)) {
|
||||
return CAmount(-1);
|
||||
}
|
||||
return a += b.nValue;
|
||||
}
|
||||
);
|
||||
if (!MoneyRange(out_amt)) {
|
||||
result.SetInvalid(strprintf("PSBT is not valid. Output amount invalid"));
|
||||
return result;
|
||||
}
|
||||
|
||||
// Get the fee
|
||||
CAmount fee = in_amt - out_amt;
|
||||
|
|
|
@ -1074,7 +1074,12 @@ UniValue decodepsbt(const JSONRPCRequest& request)
|
|||
UniValue out(UniValue::VOBJ);
|
||||
|
||||
out.pushKV("amount", ValueFromAmount(txout.nValue));
|
||||
if (MoneyRange(txout.nValue) && MoneyRange(total_in + txout.nValue)) {
|
||||
total_in += txout.nValue;
|
||||
} else {
|
||||
// Hack to just not show fee later
|
||||
have_all_utxos = false;
|
||||
}
|
||||
|
||||
UniValue o(UniValue::VOBJ);
|
||||
ScriptToUniv(txout.scriptPubKey, o, true);
|
||||
|
@ -1084,7 +1089,13 @@ UniValue decodepsbt(const JSONRPCRequest& request)
|
|||
UniValue non_wit(UniValue::VOBJ);
|
||||
TxToUniv(*input.non_witness_utxo, uint256(), non_wit, false);
|
||||
in.pushKV("non_witness_utxo", non_wit);
|
||||
total_in += input.non_witness_utxo->vout[psbtx.tx->vin[i].prevout.n].nValue;
|
||||
CAmount utxo_val = input.non_witness_utxo->vout[psbtx.tx->vin[i].prevout.n].nValue;
|
||||
if (MoneyRange(utxo_val) && MoneyRange(total_in + utxo_val)) {
|
||||
total_in += utxo_val;
|
||||
} else {
|
||||
// Hack to just not show fee later
|
||||
have_all_utxos = false;
|
||||
}
|
||||
} else {
|
||||
have_all_utxos = false;
|
||||
}
|
||||
|
@ -1200,7 +1211,12 @@ UniValue decodepsbt(const JSONRPCRequest& request)
|
|||
outputs.push_back(out);
|
||||
|
||||
// Fee calculation
|
||||
if (MoneyRange(psbtx.tx->vout[i].nValue) && MoneyRange(output_value + psbtx.tx->vout[i].nValue)) {
|
||||
output_value += psbtx.tx->vout[i].nValue;
|
||||
} else {
|
||||
// Hack to just not show fee later
|
||||
have_all_utxos = false;
|
||||
}
|
||||
}
|
||||
result.pushKV("outputs", outputs);
|
||||
if (have_all_utxos) {
|
||||
|
|
|
@ -421,5 +421,14 @@ class PSBTTest(BitcoinTestFramework):
|
|||
assert_equal(analysis['next'], 'creator')
|
||||
assert_equal(analysis['error'], 'PSBT is not valid. Input 0 spends unspendable output')
|
||||
|
||||
self.log.info("PSBT with invalid values should have error message and Creator as next")
|
||||
analysis = self.nodes[0].analyzepsbt('cHNidP8BAHECAAAAAfA00BFgAm6tp86RowwH6BMImQNL5zXUcTT97XoLGz0BAAAAAAD/////AgD5ApUAAAAAFgAUKNw0x8HRctAgmvoevm4u1SbN7XL87QKVAAAAABYAFPck4gF7iL4NL4wtfRAKgQbghiTUAAAAAAABAR8AgIFq49AHABYAFJUDtxf2PHo641HEOBOAIvFMNTr2AAAA')
|
||||
assert_equal(analysis['next'], 'creator')
|
||||
assert_equal(analysis['error'], 'PSBT is not valid. Input 0 has invalid value')
|
||||
|
||||
analysis = self.nodes[0].analyzepsbt('cHNidP8BAHECAAAAAfA00BFgAm6tp86RowwH6BMImQNL5zXUcTT97XoLGz0BAAAAAAD/////AgCAgWrj0AcAFgAUKNw0x8HRctAgmvoevm4u1SbN7XL87QKVAAAAABYAFPck4gF7iL4NL4wtfRAKgQbghiTUAAAAAAABAR8A8gUqAQAAABYAFJUDtxf2PHo641HEOBOAIvFMNTr2AAAA')
|
||||
assert_equal(analysis['next'], 'creator')
|
||||
assert_equal(analysis['error'], 'PSBT is not valid. Output amount invalid')
|
||||
|
||||
if __name__ == '__main__':
|
||||
PSBTTest().main()
|
||||
|
|
Loading…
Reference in a new issue