[kernel] Expose reusable PrecomputedTransactionData in script valid

This commit is contained in:
Josh Doman
2025-12-23 18:48:56 -05:00
parent ead849c9f1
commit 44e006d438
4 changed files with 220 additions and 73 deletions

View File

@@ -494,6 +494,7 @@ struct btck_BlockHash : Handle<btck_BlockHash, uint256> {};
struct btck_TransactionInput : Handle<btck_TransactionInput, CTxIn> {};
struct btck_TransactionOutPoint: Handle<btck_TransactionOutPoint, COutPoint> {};
struct btck_Txid: Handle<btck_Txid, Txid> {};
struct btck_PrecomputedTransactionData : Handle<btck_PrecomputedTransactionData, PrecomputedTransactionData> {};
btck_Transaction* btck_transaction_create(const void* raw_transaction, size_t raw_transaction_len)
{
@@ -607,10 +608,46 @@ void btck_transaction_output_destroy(btck_TransactionOutput* output)
delete output;
}
btck_PrecomputedTransactionData* btck_precomputed_transaction_data_create(
const btck_Transaction* tx_to,
const btck_TransactionOutput** spent_outputs_, size_t spent_outputs_len)
{
try {
const CTransaction& tx{*btck_Transaction::get(tx_to)};
auto txdata{btck_PrecomputedTransactionData::create()};
if (spent_outputs_ != nullptr && spent_outputs_len > 0) {
assert(spent_outputs_len == tx.vin.size());
std::vector<CTxOut> spent_outputs;
spent_outputs.reserve(spent_outputs_len);
for (size_t i = 0; i < spent_outputs_len; i++) {
const CTxOut& tx_out{btck_TransactionOutput::get(spent_outputs_[i])};
spent_outputs.push_back(tx_out);
}
btck_PrecomputedTransactionData::get(txdata).Init(tx, std::move(spent_outputs));
} else {
btck_PrecomputedTransactionData::get(txdata).Init(tx, {});
}
return txdata;
} catch (...) {
return nullptr;
}
}
btck_PrecomputedTransactionData* btck_precomputed_transaction_data_copy(const btck_PrecomputedTransactionData* precomputed_txdata)
{
return btck_PrecomputedTransactionData::copy(precomputed_txdata);
}
void btck_precomputed_transaction_data_destroy(btck_PrecomputedTransactionData* precomputed_txdata)
{
delete precomputed_txdata;
}
int btck_script_pubkey_verify(const btck_ScriptPubkey* script_pubkey,
const int64_t amount,
const btck_Transaction* tx_to,
const btck_TransactionOutput** spent_outputs_, size_t spent_outputs_len,
const btck_PrecomputedTransactionData* precomputed_txdata,
const unsigned int input_index,
const btck_ScriptVerificationFlags flags,
btck_ScriptVerifyStatus* status)
@@ -623,31 +660,18 @@ int btck_script_pubkey_verify(const btck_ScriptPubkey* script_pubkey,
return 0;
}
if (flags & btck_ScriptVerificationFlags_TAPROOT && spent_outputs_ == nullptr) {
const CTransaction& tx{*btck_Transaction::get(tx_to)};
assert(input_index < tx.vin.size());
const PrecomputedTransactionData& txdata{precomputed_txdata ? btck_PrecomputedTransactionData::get(precomputed_txdata) : PrecomputedTransactionData(tx)};
if (flags & btck_ScriptVerificationFlags_TAPROOT && txdata.m_spent_outputs.empty()) {
if (status) *status = btck_ScriptVerifyStatus_ERROR_SPENT_OUTPUTS_REQUIRED;
return 0;
}
if (status) *status = btck_ScriptVerifyStatus_OK;
const CTransaction& tx{*btck_Transaction::get(tx_to)};
std::vector<CTxOut> spent_outputs;
if (spent_outputs_ != nullptr) {
assert(spent_outputs_len == tx.vin.size());
spent_outputs.reserve(spent_outputs_len);
for (size_t i = 0; i < spent_outputs_len; i++) {
const CTxOut& tx_out{btck_TransactionOutput::get(spent_outputs_[i])};
spent_outputs.push_back(tx_out);
}
}
assert(input_index < tx.vin.size());
PrecomputedTransactionData txdata{tx};
if (spent_outputs_ != nullptr && flags & btck_ScriptVerificationFlags_TAPROOT) {
txdata.Init(tx, std::move(spent_outputs));
}
bool result = VerifyScript(tx.vin[input_index].scriptSig,
btck_ScriptPubkey::get(script_pubkey),
&tx.vin[input_index].scriptWitness,