RPC: getblock: tx fee calculation for verbosity 2 via Undo data

Co-authored-by: Felix Weis <mail@felixweis.com>
This commit is contained in:
Elliott Jin
2020-10-09 08:50:44 -07:00
parent cce1513179
commit bf7d6e31b1
3 changed files with 41 additions and 11 deletions

View File

@@ -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());