diff --git a/src/node/psbt.cpp b/src/node/psbt.cpp --- a/src/node/psbt.cpp +++ b/src/node/psbt.cpp @@ -18,9 +18,7 @@ PSBTAnalysis result; bool calc_fee = true; - bool all_final = true; - bool only_missing_sigs = true; - bool only_missing_final = false; + Amount in_amt{Amount::zero()}; result.inputs.resize(psbtx.tx->vin.size()); @@ -29,6 +27,9 @@ PSBTInput &input = psbtx.inputs[i]; PSBTInputAnalysis &input_analysis = result.inputs[i]; + // We set next role here and ratchet backwards as required + input_analysis.next = PSBTRole::EXTRACTOR; + // Check for a UTXO CTxOut utxo; if (psbtx.GetInputUTXO(utxo, i)) { @@ -55,7 +56,6 @@ // Check if it is final if (!utxo.IsNull() && !PSBTInputSigned(input)) { input_analysis.is_final = false; - all_final = false; // Figure out what is missing SignatureData outdata; @@ -76,11 +76,9 @@ !outdata.missing_sigs.empty()) { input_analysis.next = PSBTRole::SIGNER; } else { - only_missing_sigs = false; input_analysis.next = PSBTRole::UPDATER; } } else { - only_missing_final = true; input_analysis.next = PSBTRole::FINALIZER; } } else if (!utxo.IsNull()) { @@ -88,10 +86,14 @@ } } - if (all_final) { - only_missing_sigs = false; - result.next = PSBTRole::EXTRACTOR; + // Calculate next role for PSBT by grabbing "minumum" PSBTInput next role + result.next = PSBTRole::EXTRACTOR; + for (size_t i = 0; i < psbtx.tx->vin.size(); ++i) { + PSBTInputAnalysis &input_analysis = result.inputs[i]; + result.next = std::min(result.next, input_analysis.next); } + assert(result.next > PSBTRole::CREATOR); + if (calc_fee) { // Get the output amount Amount out_amt = @@ -143,18 +145,6 @@ CFeeRate feerate(fee, size); result.estimated_feerate = feerate; } - - if (only_missing_sigs) { - result.next = PSBTRole::SIGNER; - } else if (only_missing_final) { - result.next = PSBTRole::FINALIZER; - } else if (all_final) { - result.next = PSBTRole::EXTRACTOR; - } else { - result.next = PSBTRole::UPDATER; - } - } else { - result.next = PSBTRole::UPDATER; } return result; 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 @@ -514,6 +514,12 @@ assert_equal(analysis["next"], "creator") assert_equal(analysis["error"], "PSBT is not valid. Input 0 has invalid value") + self.log.info( + "PSBT with signed, but not finalized, inputs should have Finalizer as next" + ) + analysis = self.nodes[0].analyzepsbt(finalizers[0]["finalize"]) + assert_equal(analysis["next"], "finalizer") + analysis = self.nodes[0].analyzepsbt( "cHNidP8BAHECAAAAAfA00BFgAm6tp86RowwH6BMImQNL5zXUcTT97XoLGz0BAAAAAAD/////AgCAgWrj0AcAFgAUKNw0x8HRctAgmvoevm4u1SbN7XL87QKVAAAAABYAFPck4gF7iL4NL4wtfRAKgQbghiTUAAAAAAABAB8A8gUqAQAAABYAFJUDtxf2PHo641HEOBOAIvFMNTr2AAAA" )