@@ -2481,7 +2481,6 @@ TransactionError CWallet::FillPSBT(PartiallySignedTransaction& psbtx, bool& comp
2481
2481
{
2482
2482
LOCK (cs_wallet);
2483
2483
// Get all of the previous transactions
2484
- complete = true ;
2485
2484
for (unsigned int i = 0 ; i < psbtx.tx ->vin .size (); ++i) {
2486
2485
const CTxIn& txin = psbtx.tx ->vin [i];
2487
2486
PSBTInput& input = psbtx.inputs .at (i);
@@ -2506,13 +2505,22 @@ TransactionError CWallet::FillPSBT(PartiallySignedTransaction& psbtx, bool& comp
2506
2505
input.non_witness_utxo = wtx.tx ;
2507
2506
}
2508
2507
}
2508
+ }
2509
+
2510
+ // Fill in information from ScriptPubKeyMans
2511
+ // Because each ScriptPubKeyMan may be able to fill more than one input, we need to keep track of each ScriptPubKeyMan that has filled this psbt.
2512
+ // Each iteration, we may fill more inputs than the input that is specified in that iteration.
2513
+ // We assume that each input is filled by only one ScriptPubKeyMan
2514
+ std::set<uint256> visited_spk_mans;
2515
+ for (unsigned int i = 0 ; i < psbtx.tx ->vin .size (); ++i) {
2516
+ const CTxIn& txin = psbtx.tx ->vin [i];
2517
+ PSBTInput& input = psbtx.inputs .at (i);
2509
2518
2510
- // Get the Sighash type
2511
- if (sign && input.sighash_type > 0 && input.sighash_type != sighash_type) {
2512
- return TransactionError::SIGHASH_MISMATCH;
2519
+ if (PSBTInputSigned (input)) {
2520
+ continue ;
2513
2521
}
2514
2522
2515
- // Get the scriptPubKey to know which SigningProvider to use
2523
+ // Get the scriptPubKey to know which ScriptPubKeyMan to use
2516
2524
CScript script;
2517
2525
if (!input.witness_utxo .IsNull ()) {
2518
2526
script = input.witness_utxo .scriptPubKey ;
@@ -2523,29 +2531,38 @@ TransactionError CWallet::FillPSBT(PartiallySignedTransaction& psbtx, bool& comp
2523
2531
script = input.non_witness_utxo ->vout [txin.prevout .n ].scriptPubKey ;
2524
2532
} else {
2525
2533
// There's no UTXO so we can just skip this now
2526
- complete = false ;
2527
2534
continue ;
2528
2535
}
2529
2536
SignatureData sigdata;
2530
2537
input.FillSignatureData (sigdata);
2531
- std::unique_ptr<SigningProvider> provider = GetSigningProvider (script, sigdata);
2532
- if (!provider) {
2533
- complete = false ;
2538
+ std::set<ScriptPubKeyMan*> spk_mans = GetScriptPubKeyMans (script, sigdata);
2539
+ if (spk_mans.size () == 0 ) {
2534
2540
continue ;
2535
2541
}
2536
2542
2537
- complete &= SignPSBTInput (HidingSigningProvider (provider.get (), !sign, !bip32derivs), psbtx, i, sighash_type);
2538
- }
2543
+ for (auto & spk_man : spk_mans) {
2544
+ // If we've already been signed by this spk_man, skip it
2545
+ if (visited_spk_mans.count (spk_man->GetID ()) > 0 ) {
2546
+ continue ;
2547
+ }
2548
+
2549
+ // Fill in the information from the spk_man
2550
+ TransactionError res = spk_man->FillPSBT (psbtx, sighash_type, sign, bip32derivs);
2551
+ if (res != TransactionError::OK) {
2552
+ return res;
2553
+ }
2539
2554
2540
- // Fill in the bip32 keypaths and redeemscripts for the outputs so that hardware wallets can identify change
2541
- for (unsigned int i = 0 ; i < psbtx.tx ->vout .size (); ++i) {
2542
- const CTxOut& out = psbtx.tx ->vout .at (i);
2543
- std::unique_ptr<SigningProvider> provider = GetSigningProvider (out.scriptPubKey );
2544
- if (provider) {
2545
- UpdatePSBTOutput (HidingSigningProvider (provider.get (), true , !bip32derivs), psbtx, i);
2555
+ // Add this spk_man to visited_spk_mans so we can skip it later
2556
+ visited_spk_mans.insert (spk_man->GetID ());
2546
2557
}
2547
2558
}
2548
2559
2560
+ // Complete if every input is now signed
2561
+ complete = true ;
2562
+ for (const auto & input : psbtx.inputs ) {
2563
+ complete &= PSBTInputSigned (input);
2564
+ }
2565
+
2549
2566
return TransactionError::OK;
2550
2567
}
2551
2568
0 commit comments