Skip to content

Conversation

FelixWeis
Copy link
Contributor

Using block undo data (like in #14802) we can now show fee information for each transaction in a block without the need for additional -txindex and/or a ton of costly lookups. For a start we'll add transaction fee information to getblock verbosity level 2. This comes at a negligible speed penalty (<1%). Optimally, we add a "prevout" KV to each input spent, displaying additional information like value, scriptPubKey and height for each input spent. Because this involves calculating addresses it is a lot more costly (~ 22% slower) so new verbosity level 3 is introduced.

src/bitcoin-cli getblock 00000000000000000007fce39a80dc9110fe8709ee504c01e1f04f1f59be7bbf 2
...
      "fees": 0.00124850,
...

Copy link
Contributor

@promag promag left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concept ACK.

Instead of moving code up, you could forward declare those functions at the top? I have some code nits when this is ready for review.

Needs tests (also in test/functional/feature_pruning.py ?) and release note.

for (size_t i = 0; i < block.vtx.size(); ++i) {

const auto& tx = block.vtx.at(i);
const CTxUndo* ptr_txundo;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error:

error C4703: potentially uninitialized local pointer variable 'ptr_txundo'

Suggestion:

const CTxUndo* tx_undo = tx->IsCoinBase() ? nullptr : &block_undo.vtxundo.at(i - 1);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could (should?) probably just use i instead of IsCoinBase

}
else
} else {
for (size_t i = 0; i < block.vtx.size(); ++i) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could keep the range loop?

}
entry.pushKV("vout", vout);

if (txundo != nullptr && !tx.IsCoinBase()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be enough if (txundo) {?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to remove the assert below too, since fees will be negative on a generation transaction.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also might need to subtract subsidy amount from generation.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nevermind, I see that by initialising txundo to nullptr, this is safe.

p.pushKV("height", (int64_t)prevout.nHeight);
p.pushKV("value", ValueFromAmount(prevout.out.nValue));
p.pushKV("coinbase", (bool)prevout.fCoinBase);
UniValue o(UniValue::VOBJ);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This o shadows o in outer scope :-)

@FelixWeis
Copy link
Contributor Author

thanks for the review, @promag / @practicalswift. yes will get tests. as im not a cpp dev i just wanted to get some quick feedback on feasability and style (optional nullptr in funciton arg etc...)

@DrahtBot
Copy link
Contributor

DrahtBot commented Jun 1, 2019

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #16129 (refactor: Remove unused includes by practicalswift)

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

@DrahtBot
Copy link
Contributor

DrahtBot commented Jun 6, 2019

Needs rebase

@0xB10C
Copy link
Contributor

0xB10C commented Jun 18, 2019

Concept ACK.

UniValue p(UniValue::VOBJ);
p.pushKV("height", (int64_t)prevout.nHeight);
p.pushKV("value", ValueFromAmount(prevout.out.nValue));
p.pushKV("coinbase", (bool)prevout.fCoinBase);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be "generated" or something else - it's never a coinbase itself.

}
entry.pushKV("vout", vout);

if (txundo != nullptr && !tx.IsCoinBase()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to remove the assert below too, since fees will be negative on a generation transaction.

HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
+ HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
},
const RPCHelpMan help{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this all reformatted?

}

UniValue blockToJSON(const CBlock& block, const CBlockIndex* tip, const CBlockIndex* blockindex, bool txDetails)
UniValue blockToJSON(const CBlock& block, const CBlockIndex* tip, const CBlockIndex* blockindex, const int verbosity)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing a bool to int here will silently turn true into 1 and misbehave. Either rename the function, or find a way to make it give a compile error when a boolean is passed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(In fact, this is breaking rest_block in your PR!)

if (txundo != nullptr && !tx.IsCoinBase()) {
CAmount fees = amt_total_in - amt_total_out;
assert(MoneyRange(fees));
entry.pushKV("fees", ValueFromAmount(fees));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably should be "fee"

{

if (verbosity >= 2) {
const CBlockUndo blockUndo = GetUndoChecked(blockindex);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this will fail if the block isn't in the main chain?

@maflcko
Copy link
Member

maflcko commented Nov 18, 2019

@FelixWeis Wen rebase, sir?

I'd like to see this in 0.20.0

@luke-jr
Copy link
Member

luke-jr commented Jan 5, 2020

Addressed issues and at least partially rebased (to 0.19 branch-point) in master...luke-jr:rpc_getblock_prevouts_fees-0.19

@fanquake
Copy link
Member

Being picked up in #18772.

maflcko pushed a commit to maflcko/bitcoin-core that referenced this pull request Dec 24, 2020
…data

66d012a test: RPC: getblock fee calculations (Elliott Jin)
bf7d6e3 RPC: getblock: tx fee calculation for verbosity 2 via Undo data (Elliott Jin)

Pull request description:

  This change is progress towards bitcoin#18771 .  It adapts the fee calculation part of bitcoin#16083 and addresses some feedback.  The additional "verbosity level 3" features are planned for a future PR.

  **Original PR description:**

  > Using block undo data (like in bitcoin#14802) we can now show fee information for each transaction in a block without the need for additional -txindex and/or a ton of costly lookups. For a start we'll add transaction fee information to getblock verbosity level 2. This comes at a negligible speed penalty (<1%).

ACKs for top commit:
  luke-jr:
    tACK 66d012a
  fjahr:
    tACK 66d012a
  MarcoFalke:
    review ACK 66d012a 🗜

Tree-SHA512: be1fe4b866946a8dc36427f7dc72a20e10860e320a28fa49bc85bd2a93a0d699768179be29fa52e18b2ed8505d3ec272e586753ef2239b4230e0aefd233acaa2
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Feb 15, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants