policy: GetScriptForTransactionInput to figure out P2SH, witness, taproot

This commit is contained in:
Luke Dashjr 2023-09-04 18:48:00 +00:00 committed by Léo Haf
parent a3068674ff
commit f30200fb0f
Signed by: Retropex
GPG Key ID: F5073C4F4882FFFC
2 changed files with 50 additions and 0 deletions

View File

@ -321,3 +321,50 @@ int64_t GetVirtualTransactionInputSize(const CTxIn& txin, int64_t nSigOpCost, un
{ {
return GetVirtualTransactionSize(GetTransactionInputWeight(txin), nSigOpCost, bytes_per_sigop); return GetVirtualTransactionSize(GetTransactionInputWeight(txin), nSigOpCost, bytes_per_sigop);
} }
std::pair<CScript, unsigned int> GetScriptForTransactionInput(CScript prev_script, const CTxIn& txin)
{
bool p2sh = false;
if (prev_script.IsPayToScriptHash()) {
std::vector <std::vector<unsigned char> > stack;
if (!EvalScript(stack, txin.scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), SigVersion::BASE)) {
return std::make_pair(CScript(), 0);
}
if (stack.empty()) {
return std::make_pair(CScript(), 0);
}
prev_script = CScript(stack.back().begin(), stack.back().end());
p2sh = true;
}
int witnessversion = 0;
std::vector<unsigned char> witnessprogram;
if (!prev_script.IsWitnessProgram(witnessversion, witnessprogram)) {
// For P2SH, scriptSig is always push-only, so the actual script is only the last stack item
// For non-P2SH, prevScript is likely the real script, but not part of this transaction, and scriptSig could very well be executable, so return the latter instead
return std::make_pair(p2sh ? prev_script : txin.scriptSig, WITNESS_SCALE_FACTOR);
}
auto stack = std::span{txin.scriptWitness.stack};
if (witnessversion == 0 && witnessprogram.size() == WITNESS_V0_SCRIPTHASH_SIZE) {
if (stack.empty()) return std::make_pair(CScript(), 0); // invalid
auto& script_data = stack.back();
prev_script = CScript(script_data.begin(), script_data.end());
return std::make_pair(prev_script, 1);
}
if (witnessversion == 1 && witnessprogram.size() == WITNESS_V1_TAPROOT_SIZE && !p2sh) {
if (stack.size() >= 2 && !stack.back().empty() && stack.back()[0] == ANNEX_TAG) {
SpanPopBack(stack);
}
if (stack.size() >= 2) {
SpanPopBack(stack); // Ignore control block
prev_script = CScript(stack.back().begin(), stack.back().end());
return std::make_pair(prev_script, 1);
}
}
return std::make_pair(CScript(), 0);
}

View File

@ -14,6 +14,7 @@
#include <cstdint> #include <cstdint>
#include <string> #include <string>
#include <utility>
class CCoinsViewCache; class CCoinsViewCache;
class CFeeRate; class CFeeRate;
@ -181,4 +182,6 @@ static inline int64_t GetVirtualTransactionInputSize(const CTxIn& tx)
return GetVirtualTransactionInputSize(tx, 0, 0); return GetVirtualTransactionInputSize(tx, 0, 0);
} }
std::pair<CScript, unsigned int> GetScriptForTransactionInput(CScript prev_script, const CTxIn&);
#endif // BITCOIN_POLICY_POLICY_H #endif // BITCOIN_POLICY_POLICY_H