mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-02-04 06:12:07 +01:00
rpc: add "ischange: true" in wallet gettransaction decoded tx output
This commit is contained in:
@@ -21,6 +21,7 @@ class SigningProvider;
|
||||
class uint256;
|
||||
class UniValue;
|
||||
class CTxUndo;
|
||||
class CTxOut;
|
||||
|
||||
/**
|
||||
* Verbose level for block's transaction
|
||||
@@ -46,6 +47,6 @@ std::string FormatScript(const CScript& script);
|
||||
std::string EncodeHexTx(const CTransaction& tx);
|
||||
std::string SighashToStr(unsigned char sighash_type);
|
||||
void ScriptToUniv(const CScript& script, UniValue& out, bool include_hex = true, bool include_address = false, const SigningProvider* provider = nullptr);
|
||||
void TxToUniv(const CTransaction& tx, const uint256& block_hash, UniValue& entry, bool include_hex = true, const CTxUndo* txundo = nullptr, TxVerbosity verbosity = TxVerbosity::SHOW_DETAILS);
|
||||
void TxToUniv(const CTransaction& tx, const uint256& block_hash, UniValue& entry, bool include_hex = true, const CTxUndo* txundo = nullptr, TxVerbosity verbosity = TxVerbosity::SHOW_DETAILS, std::function<bool(const CTxOut&)> is_change_func = {});
|
||||
|
||||
#endif // BITCOIN_CORE_IO_H
|
||||
|
||||
@@ -168,7 +168,7 @@ void ScriptToUniv(const CScript& script, UniValue& out, bool include_hex, bool i
|
||||
out.pushKV("type", GetTxnOutputType(type));
|
||||
}
|
||||
|
||||
void TxToUniv(const CTransaction& tx, const uint256& block_hash, UniValue& entry, bool include_hex, const CTxUndo* txundo, TxVerbosity verbosity)
|
||||
void TxToUniv(const CTransaction& tx, const uint256& block_hash, UniValue& entry, bool include_hex, const CTxUndo* txundo, TxVerbosity verbosity, std::function<bool(const CTxOut&)> is_change_func)
|
||||
{
|
||||
CHECK_NONFATAL(verbosity >= TxVerbosity::SHOW_DETAILS);
|
||||
|
||||
@@ -243,6 +243,11 @@ void TxToUniv(const CTransaction& tx, const uint256& block_hash, UniValue& entry
|
||||
UniValue o(UniValue::VOBJ);
|
||||
ScriptToUniv(txout.scriptPubKey, /*out=*/o, /*include_hex=*/true, /*include_address=*/true);
|
||||
out.pushKV("scriptPubKey", std::move(o));
|
||||
|
||||
if (is_change_func && is_change_func(txout)) {
|
||||
out.pushKV("ischange", true);
|
||||
}
|
||||
|
||||
vout.push_back(std::move(out));
|
||||
|
||||
if (have_undo) {
|
||||
|
||||
@@ -118,6 +118,7 @@ static std::vector<RPCResult> DecodeTxDoc(const std::string& txid_field_doc)
|
||||
{RPCResult::Type::STR_AMOUNT, "value", "The value in " + CURRENCY_UNIT},
|
||||
{RPCResult::Type::NUM, "n", "index"},
|
||||
{RPCResult::Type::OBJ, "scriptPubKey", "", ScriptPubKeyDoc()},
|
||||
{RPCResult::Type::BOOL, "ischange", /*optional=*/true, "Output script is change (only if wallet transaction and true for selected rpcwallet)"},
|
||||
}},
|
||||
}},
|
||||
};
|
||||
|
||||
@@ -796,7 +796,16 @@ RPCHelpMan gettransaction()
|
||||
|
||||
if (verbose) {
|
||||
UniValue decoded(UniValue::VOBJ);
|
||||
TxToUniv(*wtx.tx, /*block_hash=*/uint256(), /*entry=*/decoded, /*include_hex=*/false);
|
||||
TxToUniv(*wtx.tx,
|
||||
/*block_hash=*/uint256(),
|
||||
/*entry=*/decoded,
|
||||
/*include_hex=*/false,
|
||||
/*txundo=*/nullptr,
|
||||
/*verbosity=*/TxVerbosity::SHOW_DETAILS,
|
||||
/*is_change_func=*/[&pwallet](const CTxOut& txout) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) {
|
||||
AssertLockHeld(pwallet->cs_wallet);
|
||||
return OutputIsChange(*pwallet, txout);
|
||||
});
|
||||
entry.pushKV("decoded", std::move(decoded));
|
||||
}
|
||||
|
||||
|
||||
@@ -542,13 +542,16 @@ class WalletTest(BitcoinTestFramework):
|
||||
destination = self.nodes[1].getnewaddress()
|
||||
txid = self.nodes[0].sendtoaddress(destination, 0.123)
|
||||
tx = self.nodes[0].gettransaction(txid=txid, verbose=True)['decoded']
|
||||
output_addresses = [vout['scriptPubKey']['address'] for vout in tx["vout"]]
|
||||
assert len(output_addresses) > 1
|
||||
for address in output_addresses:
|
||||
assert len(tx["vout"]) > 1
|
||||
for vout in tx["vout"]:
|
||||
address = vout['scriptPubKey']['address']
|
||||
ischange = self.nodes[0].getaddressinfo(address)['ischange']
|
||||
assert_equal(ischange, address != destination)
|
||||
if ischange:
|
||||
change = address
|
||||
assert vout["ischange"]
|
||||
else:
|
||||
assert "ischange" not in vout
|
||||
self.nodes[0].setlabel(change, 'foobar')
|
||||
assert_equal(self.nodes[0].getaddressinfo(change)['ischange'], False)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user