diff --git a/src/node/psbt.cpp b/src/node/psbt.cpp --- 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 #include #include #include @@ -30,6 +31,11 @@ // 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 { @@ -87,9 +93,20 @@ } if (calc_fee) { // Get the output amount - Amount out_amt = std::accumulate( - psbtx.tx->vout.begin(), psbtx.tx->vout.end(), Amount::zero(), - [](Amount a, const CTxOut &b) { return a += b.nValue; }); + Amount out_amt = + std::accumulate(psbtx.tx->vout.begin(), psbtx.tx->vout.end(), + Amount::zero(), [](Amount a, const CTxOut &b) { + if (!MoneyRange(a) || !MoneyRange(b.nValue) || + !MoneyRange(a + b.nValue)) { + return -1 * SATOSHI; + } + return a += b.nValue; + }); + if (!MoneyRange(out_amt)) { + result.SetInvalid( + strprintf("PSBT is not valid. Output amount invalid")); + return result; + } // Get the fee Amount fee = in_amt - out_amt; diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -1246,7 +1246,13 @@ 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); @@ -1357,7 +1363,13 @@ 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 --- a/test/functional/rpc_psbt.py +++ b/test/functional/rpc_psbt.py @@ -380,6 +380,22 @@ 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/////AgD5ApUAAAAAFgAUKNw0x8HRctAgmvoevm4u1SbN7XL87QKVAAAAABYAFPck4gF7iL4NL4wtfRAKgQbghiTUAAAAAAABAB8AgIFq49AHABYAFJUDtxf2PHo641HEOBOAIvFMNTr2AAAA') + assert_equal(analysis['next'], 'creator') + assert_equal( + analysis['error'], + 'PSBT is not valid. Input 0 has invalid value') + + analysis = self.nodes[0].analyzepsbt( + 'cHNidP8BAHECAAAAAfA00BFgAm6tp86RowwH6BMImQNL5zXUcTT97XoLGz0BAAAAAAD/////AgCAgWrj0AcAFgAUKNw0x8HRctAgmvoevm4u1SbN7XL87QKVAAAAABYAFPck4gF7iL4NL4wtfRAKgQbghiTUAAAAAAABAB8A8gUqAQAAABYAFJUDtxf2PHo641HEOBOAIvFMNTr2AAAA') + assert_equal(analysis['next'], 'creator') + assert_equal( + analysis['error'], + 'PSBT is not valid. Output amount invalid') + if __name__ == '__main__': PSBTTest().main()