refactor: use SignOptions for SignTransaction

This commit is contained in:
Sjors Provoost
2025-07-04 16:46:49 +02:00
parent dc4a5d1270
commit 5ed41752c5
9 changed files with 18 additions and 13 deletions

View File

@@ -68,7 +68,7 @@ static void SignTransactionSingleInput(benchmark::Bench& bench, InputType input_
const CScript& prev_spk = prev_spks[(iter++) % prev_spks.size()];
coins[prevout] = Coin(CTxOut(10000, prev_spk), /*nHeightIn=*/100, /*fCoinBaseIn=*/false);
std::map<int, bilingual_str> input_errors;
bool complete = SignTransaction(tx, &keystore, coins, SIGHASH_ALL, input_errors);
bool complete = SignTransaction(tx, &keystore, coins, {.sighash_type = SIGHASH_ALL}, input_errors);
assert(complete);
});
}

View File

@@ -77,7 +77,8 @@ static void VerifyScriptBench(benchmark::Bench& bench, ScriptType script_type)
{txSpend.vin[0].prevout, Coin(txCredit.vout[0], /*nHeightIn=*/100, /*fCoinBaseIn=*/false)}
};
std::map<int, bilingual_str> input_errors;
assert(SignTransaction(txSpend, &keystore, coins, SIGHASH_ALL, input_errors));
bool complete = SignTransaction(txSpend, &keystore, coins, {.sighash_type = SIGHASH_ALL}, input_errors);
assert(complete);
// Weak sanity check on witness data to ensure we produced the intended spending type
assert(txSpend.vin[0].scriptWitness.stack.size() == ExpectedWitnessStackSize(script_type));
txdata.Init(txSpend, /*spent_outputs=*/{txCredit.vout[0]});

View File

@@ -318,7 +318,7 @@ void SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore,
// Script verification errors
std::map<int, bilingual_str> input_errors;
bool complete = SignTransaction(mtx, keystore, coins, *nHashType, input_errors);
bool complete = SignTransaction(mtx, keystore, coins, {.sighash_type = *nHashType}, input_errors);
SignTransactionResultToJSON(mtx, complete, coins, input_errors, result);
}

View File

@@ -1006,9 +1006,9 @@ bool IsSegWitOutput(const SigningProvider& provider, const CScript& script)
return false;
}
bool SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore, const std::map<COutPoint, Coin>& coins, int nHashType, std::map<int, bilingual_str>& input_errors)
bool SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore, const std::map<COutPoint, Coin>& coins, const SignOptions& options, std::map<int, bilingual_str>& input_errors)
{
bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
bool fHashSingle = ((options.sighash_type & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
// Use CTransaction for the constant parts of the
// transaction to avoid rehashing.
@@ -1044,7 +1044,7 @@ bool SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore,
SignatureData sigdata = DataFromTransaction(mtx, i, coin->second.out);
// Only sign SIGHASH_SINGLE if there's a corresponding output:
if (!fHashSingle || (i < mtx.vout.size())) {
ProduceSignature(*keystore, MutableTransactionSignatureCreator(mtx, i, amount, &txdata, nHashType), prevPubKey, sigdata);
ProduceSignature(*keystore, MutableTransactionSignatureCreator(mtx, i, amount, &txdata, options.sighash_type), prevPubKey, sigdata);
}
UpdateInput(txin, sigdata);

View File

@@ -25,6 +25,10 @@ struct bilingual_str;
struct CMutableTransaction;
struct SignatureData;
struct SignOptions {
int sighash_type{SIGHASH_DEFAULT};
};
/** Interface for signature creators. */
class BaseSignatureCreator {
public:
@@ -120,6 +124,6 @@ void UpdateInput(CTxIn& input, const SignatureData& data);
bool IsSegWitOutput(const SigningProvider& provider, const CScript& script);
/** Sign the CMutableTransaction */
bool SignTransaction(CMutableTransaction& mtx, const SigningProvider* provider, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors);
bool SignTransaction(CMutableTransaction& mtx, const SigningProvider* provider, const std::map<COutPoint, Coin>& coins, const SignOptions& options, std::map<int, bilingual_str>& input_errors);
#endif // BITCOIN_SCRIPT_SIGN_H

View File

@@ -132,7 +132,7 @@ FUZZ_TARGET(script_sign, .init = initialize_script_sign)
}
std::map<COutPoint, Coin> coins{ConsumeCoins(fuzzed_data_provider)};
std::map<int, bilingual_str> input_errors;
(void)SignTransaction(sign_transaction_tx_to, &provider, coins, fuzzed_data_provider.ConsumeIntegral<int>(), input_errors);
(void)SignTransaction(sign_transaction_tx_to, &provider, coins, {.sighash_type = fuzzed_data_provider.ConsumeIntegral<int>()}, input_errors);
}
}

View File

@@ -481,7 +481,7 @@ std::pair<CMutableTransaction, CAmount> TestChain100Setup::CreateValidTransactio
// - Default signature hashing type
int nHashType = SIGHASH_ALL;
std::map<int, bilingual_str> input_errors;
assert(SignTransaction(mempool_txn, &keystore, input_coins, nHashType, input_errors));
assert(SignTransaction(mempool_txn, &keystore, input_coins, {.sighash_type = nHashType}, input_errors));
CAmount current_fee = inputs_amount - std::accumulate(outputs.begin(), outputs.end(), CAmount(0),
[](const CAmount& acc, const CTxOut& out) {
return acc + out.nValue;
@@ -498,7 +498,7 @@ std::pair<CMutableTransaction, CAmount> TestChain100Setup::CreateValidTransactio
mempool_txn.vout[fee_output.value()].nValue -= deduction;
// Re-sign since an output has changed
input_errors.clear();
assert(SignTransaction(mempool_txn, &keystore, input_coins, nHashType, input_errors));
assert(SignTransaction(mempool_txn, &keystore, input_coins, {.sighash_type = nHashType}, input_errors));
current_fee = target_fee;
}
}

View File

@@ -1285,7 +1285,7 @@ bool DescriptorScriptPubKeyMan::SignTransaction(CMutableTransaction& tx, const s
keys->Merge(std::move(*coin_keys));
}
return ::SignTransaction(tx, keys.get(), coins, sighash, input_errors);
return ::SignTransaction(tx, keys.get(), coins, {.sighash_type = sighash}, input_errors);
}
SigningResult DescriptorScriptPubKeyMan::SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const
@@ -1376,7 +1376,7 @@ std::optional<PSBTError> DescriptorScriptPubKeyMan::FillPSBT(PartiallySignedTran
}
}
PSBTError res = SignPSBTInput(HidingSigningProvider(keys.get(), /*hide_secret=*/!options.sign, /*hide_origin=*/!options.bip32_derivs), psbtx, i, &txdata, options, nullptr);
PSBTError res = SignPSBTInput(HidingSigningProvider(keys.get(), /*hide_secret=*/!options.sign, /*hide_origin=*/!options.bip32_derivs), psbtx, i, &txdata, options, /*out_sigdata=*/nullptr);
if (res != PSBTError::OK && res != PSBTError::INCOMPLETE) {
return res;
}

View File

@@ -55,7 +55,7 @@ static CMutableTransaction TestSimpleSpend(const CTransaction& from, uint32_t in
std::map<COutPoint, Coin> coins;
coins[mtx.vin[0].prevout].out = from.vout[index];
std::map<int, bilingual_str> input_errors;
BOOST_CHECK(SignTransaction(mtx, &keystore, coins, SIGHASH_ALL, input_errors));
BOOST_CHECK(SignTransaction(mtx, &keystore, coins, {.sighash_type = SIGHASH_ALL}, input_errors));
return mtx;
}