11
11
#include < script/standard.h>
12
12
#include < serialize.h>
13
13
#include < streams.h>
14
+ #include < undo.h>
14
15
#include < univalue.h>
16
+ #include < util/check.h>
15
17
#include < util/system.h>
16
18
#include < util/strencodings.h>
17
19
@@ -177,7 +179,7 @@ void ScriptPubKeyToUniv(const CScript& scriptPubKey,
177
179
out.pushKV (" addresses" , a);
178
180
}
179
181
180
- void TxToUniv (const CTransaction& tx, const uint256& hashBlock, UniValue& entry, bool include_hex, int serialize_flags)
182
+ void TxToUniv (const CTransaction& tx, const uint256& hashBlock, UniValue& entry, bool include_hex, int serialize_flags, const CTxUndo* txundo )
181
183
{
182
184
entry.pushKV (" txid" , tx.GetHash ().GetHex ());
183
185
entry.pushKV (" hash" , tx.GetWitnessHash ().GetHex ());
@@ -189,13 +191,20 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry,
189
191
entry.pushKV (" weight" , GetTransactionWeight (tx));
190
192
entry.pushKV (" locktime" , (int64_t )tx.nLockTime );
191
193
192
- UniValue vin (UniValue::VARR);
194
+ UniValue vin{UniValue::VARR};
195
+
196
+ // If available, use Undo data to calculate the fee. Note that txundo == nullptr
197
+ // for coinbase transactions and for transactions where undo data is unavailable.
198
+ const bool calculate_fee = txundo != nullptr ;
199
+ CAmount amt_total_in = 0 ;
200
+ CAmount amt_total_out = 0 ;
201
+
193
202
for (unsigned int i = 0 ; i < tx.vin .size (); i++) {
194
203
const CTxIn& txin = tx.vin [i];
195
204
UniValue in (UniValue::VOBJ);
196
- if (tx.IsCoinBase ())
205
+ if (tx.IsCoinBase ()) {
197
206
in.pushKV (" coinbase" , HexStr (txin.scriptSig ));
198
- else {
207
+ } else {
199
208
in.pushKV (" txid" , txin.prevout .hash .GetHex ());
200
209
in.pushKV (" vout" , (int64_t )txin.prevout .n );
201
210
UniValue o (UniValue::VOBJ);
@@ -210,6 +219,10 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry,
210
219
}
211
220
in.pushKV (" txinwitness" , txinwitness);
212
221
}
222
+ if (calculate_fee) {
223
+ const CTxOut& prev_txout = txundo->vprevout [i].out ;
224
+ amt_total_in += prev_txout.nValue ;
225
+ }
213
226
in.pushKV (" sequence" , (int64_t )txin.nSequence );
214
227
vin.push_back (in);
215
228
}
@@ -228,9 +241,19 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry,
228
241
ScriptPubKeyToUniv (txout.scriptPubKey , o, true );
229
242
out.pushKV (" scriptPubKey" , o);
230
243
vout.push_back (out);
244
+
245
+ if (calculate_fee) {
246
+ amt_total_out += txout.nValue ;
247
+ }
231
248
}
232
249
entry.pushKV (" vout" , vout);
233
250
251
+ if (calculate_fee) {
252
+ const CAmount fee = amt_total_in - amt_total_out;
253
+ CHECK_NONFATAL (MoneyRange (fee));
254
+ entry.pushKV (" fee" , ValueFromAmount (fee));
255
+ }
256
+
234
257
if (!hashBlock.IsNull ())
235
258
entry.pushKV (" blockhash" , hashBlock.GetHex ());
236
259
0 commit comments