mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-09 19:37:27 -03:00
Decode P2WSH and P2SH if data from prev tx is available on decodingawtransaction functions
This commit is contained in:
parent
018e5fcc46
commit
43dbc696b9
4 changed files with 64 additions and 2 deletions
|
@ -201,23 +201,31 @@ void TxToUniv(const CTransaction& tx, const uint256& block_hash, UniValue& entry
|
|||
o.pushKV("hex", HexStr(txin.scriptSig));
|
||||
in.pushKV("scriptSig", std::move(o));
|
||||
}
|
||||
if (!tx.vin[i].scriptWitness.IsNull()) {
|
||||
|
||||
if (!txin.scriptWitness.IsNull()) {
|
||||
UniValue txinwitness(UniValue::VARR);
|
||||
for (const auto& item : tx.vin[i].scriptWitness.stack) {
|
||||
txinwitness.push_back(HexStr(item));
|
||||
}
|
||||
in.pushKV("txinwitness", std::move(txinwitness));
|
||||
}
|
||||
|
||||
if (have_undo) {
|
||||
const Coin& prev_coin = txundo->vprevout[i];
|
||||
const CTxOut& prev_txout = prev_coin.out;
|
||||
|
||||
amt_total_in += prev_txout.nValue;
|
||||
|
||||
std::pair<CScript, int> script = GetScriptForTransactionInput(prev_txout.scriptPubKey, txin);
|
||||
UniValue redeemScript(UniValue::VOBJ);
|
||||
ScriptToUniv(script.first, redeemScript, false, true);
|
||||
if (script.second != -2) {
|
||||
in.pushKV("redeemScript", std::move(redeemScript));
|
||||
}
|
||||
|
||||
if (verbosity == TxVerbosity::SHOW_DETAILS_AND_PREVOUT) {
|
||||
UniValue o_script_pub_key(UniValue::VOBJ);
|
||||
ScriptToUniv(prev_txout.scriptPubKey, /*out=*/o_script_pub_key, /*include_hex=*/true, /*include_address=*/true);
|
||||
|
||||
UniValue p(UniValue::VOBJ);
|
||||
p.pushKV("generated", bool(prev_coin.fCoinBase));
|
||||
p.pushKV("height", uint64_t(prev_coin.nHeight));
|
||||
|
|
|
@ -119,6 +119,12 @@ static std::vector<RPCResult> DecodeTxDoc(const std::string& txid_field_doc)
|
|||
{
|
||||
{RPCResult::Type::STR_HEX, "hex", "hex-encoded witness data (if any)"},
|
||||
}},
|
||||
{RPCResult::Type::OBJ, "redeemScript", /*optional=*/true, "The decoded redeem script",
|
||||
{
|
||||
{RPCResult::Type::STR, "asm", "Human readable disassembly of the redeem script"},
|
||||
{RPCResult::Type::STR, "desc", "Descriptor of the redeem script"},
|
||||
{RPCResult::Type::STR, "type", "Type of the redeem script"},
|
||||
}},
|
||||
{RPCResult::Type::NUM, "sequence", "The script sequence number"},
|
||||
}},
|
||||
}},
|
||||
|
|
|
@ -10,9 +10,13 @@
|
|||
#include <hash.h>
|
||||
#include <uint256.h>
|
||||
#include <util/hash_type.h>
|
||||
#include<script/interpreter.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
|
||||
|
||||
CScriptID::CScriptID(const CScript& in) : BaseHash(Hash160(in)) {}
|
||||
|
||||
std::string GetOpName(opcodetype opcode)
|
||||
|
@ -387,3 +391,44 @@ bool CheckMinimalPush(const std::vector<unsigned char>& data, opcodetype opcode)
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::pair<CScript, int> GetScriptForTransactionInput(CScript prevScript, const CTxIn& txin)
|
||||
{
|
||||
bool p2sh = false;
|
||||
if (prevScript.IsPayToScriptHash()) {
|
||||
std::vector <std::vector<unsigned char> > stack;
|
||||
if (!EvalScript(stack, txin.scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), SigVersion::BASE)) {
|
||||
return std::make_pair(CScript(), -2);
|
||||
}
|
||||
if (stack.empty()) {
|
||||
return std::make_pair(CScript(), -2);
|
||||
}
|
||||
prevScript = CScript(stack.back().begin(), stack.back().end());
|
||||
p2sh = true;
|
||||
}
|
||||
int witnessversion = 0;
|
||||
std::vector<unsigned char> witnessprogram;
|
||||
if (!prevScript.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 ? prevScript : txin.scriptSig, -1);
|
||||
}
|
||||
Span stack{txin.scriptWitness.stack};
|
||||
if (witnessversion == 0 && witnessprogram.size() == WITNESS_V0_SCRIPTHASH_SIZE) {
|
||||
if (stack.empty()) return std::make_pair(CScript(), -2); // invalid
|
||||
auto& script_data = stack.back();
|
||||
prevScript = CScript(script_data.begin(), script_data.end());
|
||||
return std::make_pair(prevScript, witnessversion);
|
||||
}
|
||||
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
|
||||
prevScript = CScript(stack.back().begin(), stack.back().end());
|
||||
return std::make_pair(prevScript, witnessversion);
|
||||
}
|
||||
}
|
||||
return std::make_pair(CScript(), -2);
|
||||
}
|
|
@ -581,6 +581,9 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class CTxIn;
|
||||
std::pair<CScript, int> GetScriptForTransactionInput(CScript prevScript, const CTxIn& txin);
|
||||
|
||||
struct CScriptWitness
|
||||
{
|
||||
// Note that this encodes the data elements being pushed, rather than
|
||||
|
|
Loading…
Reference in a new issue