aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/node/psbt.cpp12
-rw-r--r--src/rpc/rawtransaction.cpp22
-rwxr-xr-xtest/functional/rpc_psbt.py9
3 files changed, 40 insertions, 3 deletions
diff --git a/src/node/psbt.cpp b/src/node/psbt.cpp
index 9a30c3f083..69fb1a28a9 100644
--- a/src/node/psbt.cpp
+++ b/src/node/psbt.cpp
@@ -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;
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index 6a02984a0e..67235a6942 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -1077,7 +1077,12 @@ UniValue decodepsbt(const JSONRPCRequest& request)
UniValue out(UniValue::VOBJ);
out.pushKV("amount", ValueFromAmount(txout.nValue));
- total_in += 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);
@@ -1087,7 +1092,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;
}
@@ -1203,7 +1214,12 @@ UniValue decodepsbt(const JSONRPCRequest& request)
outputs.push_back(out);
// Fee calculation
- output_value += psbtx.tx->vout[i].nValue;
+ 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) {
diff --git a/test/functional/rpc_psbt.py b/test/functional/rpc_psbt.py
index 2cc9650cb2..5986f197e1 100755
--- a/test/functional/rpc_psbt.py
+++ b/test/functional/rpc_psbt.py
@@ -422,5 +422,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()