mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-06-29 18:20:58 +02:00
RPC: getblock: tx fee calculation for verbosity 2 via Undo data
Co-authored-by: Felix Weis <mail@felixweis.com>
This commit is contained in:
@ -18,6 +18,7 @@ class CTransaction;
|
||||
struct CMutableTransaction;
|
||||
class uint256;
|
||||
class UniValue;
|
||||
class CTxUndo;
|
||||
|
||||
// core_read.cpp
|
||||
CScript ParseScript(const std::string& s);
|
||||
@ -45,6 +46,6 @@ std::string EncodeHexTx(const CTransaction& tx, const int serializeFlags = 0);
|
||||
std::string SighashToStr(unsigned char sighash_type);
|
||||
void ScriptPubKeyToUniv(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex);
|
||||
void ScriptToUniv(const CScript& script, UniValue& out, bool include_address);
|
||||
void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry, bool include_hex = true, int serialize_flags = 0);
|
||||
void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry, bool include_hex = true, int serialize_flags = 0, const CTxUndo* txundo = nullptr);
|
||||
|
||||
#endif // BITCOIN_CORE_IO_H
|
||||
|
@ -11,7 +11,9 @@
|
||||
#include <script/standard.h>
|
||||
#include <serialize.h>
|
||||
#include <streams.h>
|
||||
#include <undo.h>
|
||||
#include <univalue.h>
|
||||
#include <util/check.h>
|
||||
#include <util/system.h>
|
||||
#include <util/strencodings.h>
|
||||
|
||||
@ -177,7 +179,7 @@ void ScriptPubKeyToUniv(const CScript& scriptPubKey,
|
||||
out.pushKV("addresses", a);
|
||||
}
|
||||
|
||||
void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry, bool include_hex, int serialize_flags)
|
||||
void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry, bool include_hex, int serialize_flags, const CTxUndo* txundo)
|
||||
{
|
||||
entry.pushKV("txid", tx.GetHash().GetHex());
|
||||
entry.pushKV("hash", tx.GetWitnessHash().GetHex());
|
||||
@ -189,13 +191,20 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry,
|
||||
entry.pushKV("weight", GetTransactionWeight(tx));
|
||||
entry.pushKV("locktime", (int64_t)tx.nLockTime);
|
||||
|
||||
UniValue vin(UniValue::VARR);
|
||||
UniValue vin{UniValue::VARR};
|
||||
|
||||
// If available, use Undo data to calculate the fee. Note that txundo == nullptr
|
||||
// for coinbase transactions and for transactions where undo data is unavailable.
|
||||
const bool calculate_fee = txundo != nullptr;
|
||||
CAmount amt_total_in = 0;
|
||||
CAmount amt_total_out = 0;
|
||||
|
||||
for (unsigned int i = 0; i < tx.vin.size(); i++) {
|
||||
const CTxIn& txin = tx.vin[i];
|
||||
UniValue in(UniValue::VOBJ);
|
||||
if (tx.IsCoinBase())
|
||||
if (tx.IsCoinBase()) {
|
||||
in.pushKV("coinbase", HexStr(txin.scriptSig));
|
||||
else {
|
||||
} else {
|
||||
in.pushKV("txid", txin.prevout.hash.GetHex());
|
||||
in.pushKV("vout", (int64_t)txin.prevout.n);
|
||||
UniValue o(UniValue::VOBJ);
|
||||
@ -210,6 +219,10 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry,
|
||||
}
|
||||
in.pushKV("txinwitness", txinwitness);
|
||||
}
|
||||
if (calculate_fee) {
|
||||
const CTxOut& prev_txout = txundo->vprevout[i].out;
|
||||
amt_total_in += prev_txout.nValue;
|
||||
}
|
||||
in.pushKV("sequence", (int64_t)txin.nSequence);
|
||||
vin.push_back(in);
|
||||
}
|
||||
@ -228,9 +241,19 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry,
|
||||
ScriptPubKeyToUniv(txout.scriptPubKey, o, true);
|
||||
out.pushKV("scriptPubKey", o);
|
||||
vout.push_back(out);
|
||||
|
||||
if (calculate_fee) {
|
||||
amt_total_out += txout.nValue;
|
||||
}
|
||||
}
|
||||
entry.pushKV("vout", vout);
|
||||
|
||||
if (calculate_fee) {
|
||||
const CAmount fee = amt_total_in - amt_total_out;
|
||||
CHECK_NONFATAL(MoneyRange(fee));
|
||||
entry.pushKV("fee", ValueFromAmount(fee));
|
||||
}
|
||||
|
||||
if (!hashBlock.IsNull())
|
||||
entry.pushKV("blockhash", hashBlock.GetHex());
|
||||
|
||||
|
@ -162,16 +162,21 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* tip, const CBlockIn
|
||||
result.pushKV("versionHex", strprintf("%08x", block.nVersion));
|
||||
result.pushKV("merkleroot", block.hashMerkleRoot.GetHex());
|
||||
UniValue txs(UniValue::VARR);
|
||||
for(const auto& tx : block.vtx)
|
||||
{
|
||||
if(txDetails)
|
||||
{
|
||||
if (txDetails) {
|
||||
CBlockUndo blockUndo;
|
||||
const bool have_undo = !IsBlockPruned(blockindex) && UndoReadFromDisk(blockUndo, blockindex);
|
||||
for (size_t i = 0; i < block.vtx.size(); ++i) {
|
||||
const CTransactionRef& tx = block.vtx.at(i);
|
||||
// coinbase transaction (i == 0) doesn't have undo data
|
||||
const CTxUndo* txundo = (have_undo && i) ? &blockUndo.vtxundo.at(i - 1) : nullptr;
|
||||
UniValue objTx(UniValue::VOBJ);
|
||||
TxToUniv(*tx, uint256(), objTx, true, RPCSerializationFlags());
|
||||
TxToUniv(*tx, uint256(), objTx, true, RPCSerializationFlags(), txundo);
|
||||
txs.push_back(objTx);
|
||||
}
|
||||
else
|
||||
} else {
|
||||
for (const CTransactionRef& tx : block.vtx) {
|
||||
txs.push_back(tx->GetHash().GetHex());
|
||||
}
|
||||
}
|
||||
result.pushKV("tx", txs);
|
||||
result.pushKV("time", block.GetBlockTime());
|
||||
@ -926,6 +931,7 @@ static RPCHelpMan getblock()
|
||||
{RPCResult::Type::OBJ, "", "",
|
||||
{
|
||||
{RPCResult::Type::ELISION, "", "The transactions in the format of the getrawtransaction RPC. Different from verbosity = 1 \"tx\" result"},
|
||||
{RPCResult::Type::NUM, "fee", "The transaction fee in " + CURRENCY_UNIT + ", omitted if block undo data is not available"},
|
||||
}},
|
||||
}},
|
||||
{RPCResult::Type::ELISION, "", "Same output as verbosity = 1"},
|
||||
|
Reference in New Issue
Block a user