Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Near-Bugfix: Optimization: Minimize the number of times it is checked that no money... #8498

Merged
merged 4 commits into from
Oct 11, 2017

Conversation

jtimon
Copy link
Contributor

@jtimon jtimon commented Aug 11, 2016

...is created by individual transactions to 2 places (but call only once in each):

  • ConnectBlock ( before calculated fees per txs twice )
  • AcceptToMemoryPoolWorker ( before called CheckTxInputs 4 times and calculated
    fees per tx one extra time )

Also call tx.GetValueOut() only once per call of CheckTxInputs (instead of 2)

For more motivation:

https://github.com/bitcoin/bitcoin/blob/master/src/main.cpp#L1493
jtimon/bitcoin@0.13-consensus-inputs...jtimon:0.13-consensus-inputs-comments

EDIT: partially replaces #6445

Near-Bugfix as pointed out in #8498 (comment)

src/main.cpp Outdated
// are the actual inputs available?
if (!inputs.HaveInputs(tx))
return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputs-missingorspent", false,
strprintf("%s: inputs missing/spent", __func__));
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: weird spacing here?

Copy link
Contributor Author

@jtimon jtimon Aug 11, 2016

Choose a reason for hiding this comment

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

Oh, that's how the editor indented by default. That's actually what we have in some other places, but having a glance searching for strprintf in main.cpp I see we're not being consistent with indentation of function calls broken into several lines

Example from the opening parenthesis position:
https://github.com/bitcoin/bitcoin/blob/master/src/main.cpp#L1354
Example 4 spaces from the beginning:
https://github.com/bitcoin/bitcoin/blob/master/src/main.cpp#L1110
Example freestyle:
https://github.com/bitcoin/bitcoin/blob/master/src/main.cpp#L1436

I'm happy to change it for something else, this maybe?

        return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputs-missingorspent", false,
            strprintf("%s: inputs missing/spent", __func__));

EDIT: Actually the indentation is the same as from the place it's taken from: https://github.com/bitcoin/bitcoin/pull/8498/files#diff-7ec3c68a81efff79b6ca22ac1f1eabbaL2417

@jtimon
Copy link
Contributor Author

jtimon commented Sep 1, 2016

Needed rebase. Besides, the previous version contained a bug.

@jtimon
Copy link
Contributor Author

jtimon commented Dec 3, 2016

Needed rebase after renaming main.o, see #9260 (although needed, the rebase was clean in this case)

Copy link
Member

@sipa sipa 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

@@ -646,18 +646,20 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
}
}

// are the actual inputs available?
// This redundant check doesn't trigger the DoS code on purpose; if it did, it would make it easier
// for an attacker to attempt to split the network (Consensus::CheckTxInputs also checks this).
Copy link
Member

Choose a reason for hiding this comment

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

I think you can change the view.HaveInputs(tx) below into a Consensus::CheckTxInputs call, doing some of the checks slightly earlier.

Copy link
Contributor Author

@jtimon jtimon Apr 18, 2017

Choose a reason for hiding this comment

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

Perhaps the new comment could be clearer, but the view.HaveInputs(tx) check below sets state.DoS(0, ...) instead of state.DoS(100, ...) like Consensus::CheckTxInputs would do.
Feel more than free to rephrase it in a way that would have been more clear to you.

@@ -1318,16 +1318,14 @@ int GetSpendHeight(const CCoinsViewCache& inputs)
return pindexPrev->nHeight + 1;
}

namespace Consensus {
bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight)
bool Consensus::CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmount& nFees)
Copy link
Contributor

@dcousens dcousens Apr 9, 2017

Choose a reason for hiding this comment

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

Rather than forcing a bogus nFees (or unused) everywhere, just wrap this function with an overload containing an unused nFees stack variable.

Simpler. Less diff.

Also means anyone reviewing at some later date won't get confused as to whether nFees is actually used or not.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The only place where this makes sense is in txmempool.cpp. There you can do a much nicer wrapper there. The diff won't be smaller in total but there will be more lines in red (which people tend to like). I considered this before and I rembember @sipa said it would be fine to just remove the check in txmempool.cpp but I can't find the comment and he changed his mind about it. I will rewrite this for you to see and I'm happy to squash it.

Copy link
Contributor

@dcousens dcousens left a comment

Choose a reason for hiding this comment

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

utACK, but see comment RE suggested change

@jtimon
Copy link
Contributor Author

jtimon commented Apr 18, 2017

Added a commit that may make @dcousens happier or not, thanks for making me remember.

EDIT: I would be also be happy to take the function out of the consensus namespace "for free" here. That was a mistake on my part.

@jtimon jtimon force-pushed the 0.13-consensus-inputs branch 2 times, most recently from 7a17ce7 to 1590c19 Compare April 19, 2017 15:52
Copy link
Contributor

@ryanofsky ryanofsky left a comment

Choose a reason for hiding this comment

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

utACK 1590c19d3b4fa5d406cf2f91772960e11d0d2cb8

PR was initially confusing to me, but here are my notes on what it does:

  • Changes CheckTxInputs to return DoS level 100 and code REJECT_INVALID instead of 0 and 0.
  • Adds CheckTxInputs nFees in/out argument
  • Removes CheckTxInputs call from CheckInputs. Avoids changing behavior by having the two callers of CheckInputs (AcceptToMemoryPoolWorker and ConnectBlock) call CheckTxInputs themselves.
  • Changes AcceptToMemoryPoolWorker and ConnectBlock to use fees returned by CheckTxInputs instead of computing fees themselves.
  • Updates calls to CheckTxInputs in CTxMemPool::check. No impact there because mempool code ignores returned validation state and fees.

@@ -624,7 +624,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
CCoinsView dummy;
CCoinsViewCache view(&dummy);

CAmount nValueIn = 0;
CAmount nFees = 0;
Copy link
Contributor

Choose a reason for hiding this comment

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

In commit "Optimization: Minimize the number of times it is checked"

Would be good to declare nFees below close to where it is actually used.

@@ -1820,6 +1814,8 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd
blockundo.vtxundo.reserve(block.vtx.size() - 1);
std::vector<PrecomputedTransactionData> txdata;
txdata.reserve(block.vtx.size()); // Required so that pointers to individual PrecomputedTransactionData don't get invalidated
const int nHeight = pindex->pprev == NULL ? 0 : pindex->pprev->nHeight + 1;
const int64_t nSpendHeight = block.vtx.size() > 1 ? GetSpendHeight(view) : nHeight;
Copy link
Contributor

Choose a reason for hiding this comment

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

In commit "Optimization: Minimize the number of times it is checked"

Can you add a comment explaining this line? Why do transactions in a block with vtx.size() of >= 2 have a different spend height than transactions in a block with vtx.size() == 1? Is nSpendHeight even used in a block with vtx.size() == 1?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If the block only has the coinbase tx before GetSpendHeight(view) would have not been called at all and starting doing so seems unnecessarily costly, see https://github.com/bitcoin/bitcoin/blob/master/src/validation.cpp#L1306
I was actually hoping that someone suggested to just remove this local variable directly and just use nHeight directly for the coinbase maturity check, assuming that is safe. I think so but would like others to confirm before trying it.

@jtimon
Copy link
Contributor Author

jtimon commented May 19, 2017

Needed rebase, hopefully fixed all nits.

@ryanofsky
Copy link
Contributor

Tests for this PR seem to be failing currently, maybe due to the SpendHeight change?

Only changes since my previous review were rebasing post-#8329 and the nFees and nSpendHeight changes commented on above.

@jtimon
Copy link
Contributor Author

jtimon commented May 30, 2017

Yes, the problem was in that change but not on stop using GetSpendHeight, just added +1 to the height by mistake. Updated.

@jtimon
Copy link
Contributor Author

jtimon commented Jun 2, 2017

Needed rebase after #10195, it also needs more review now (AcceptToMemoryPoolWorker may return different DoS pnctuation [100 instead of 0] now, happy to fix if that's a problem).

@ryanofsky
Copy link
Contributor

Some discussion of this in IRC https://botbot.me/freenode/bitcoin-core-dev/msg/87002756/

Copy link
Contributor

@ryanofsky ryanofsky left a comment

Choose a reason for hiding this comment

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

utACK 4d9e9a5b7cb3e65bcf96ea5090ab6abaeba27640. Only changes since last review were removing a stray comment and fixing the spendheight failures.

if (!view.HaveInputs(tx))
return state.DoS(100, error("ConnectBlock(): inputs missing/spent"),
REJECT_INVALID, "bad-txns-inputs-missingorspent");
if (!Consensus::CheckTxInputs(tx, state, view, pindex->nHeight, nFees))
Copy link
Contributor

Choose a reason for hiding this comment

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

In commit "Optimization: Minimize the number of times"

If I understand correctly, it would be more correct to pass SpendHeight(view) instead of pindex->nHeight as the nSpendHeight argument, but in this case it doesn't matter because the value is only used for coinbase transactions, and this isn't a coinbase transaction? Or maybe there are other reasons why pindex->nHeight is ok to pass?

Either way, I think this is confusing, and that there should be a comment here explaining the pindex->nHeight value. Or maybe you could delete the nSpendHeight argument and have CheckTxInputs call GetSpendHeight(inputs) when needed. This seems like it would be a simplification and I don't think there should be a performance cost because CheckTxInputs seems to be skipped for coinbase transactions in all cases except for one call that invokes GetSpendHeight anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think it would be more correct (but I'm glad to be corrected) and performance would sufffer.
I think pindex->nHeight because that's actually what we want to validate here. In acceptToMemPool and CTxMemPool::check you don't know the height. Here, nSpendHeight should always be lower or equal to pindex->nHeight.

I'm happy to add a comment but not sure what it should be. Peharps the comment should be in GetSpendHeight instead of ConnectBlock().

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm happy to add a comment but not sure what it should be.

Comment could just say why it is better to pass pindex->nHeight as nSpendHeight here instead of GetSpendHeight(view). If the two values are always equal, or have some other relation, comment could just say what that relationship is. If this is too in the weeds, definitely feel free to skip this. I'm just suggesting what I think would make the code clearer for me.

Alternately, I don't know what you think of my suggestion to eliminate the nSpendHeight argument and just call GetSpendHeight in CheckTxInputs. It does look to me like this would be logically equivalent and not effect performance, though maybe there's another reason not to do it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Part of the optimization here is not calling GetSpendHeight for every tx in the block, and your suggestion would eliminate that part of the optimization.
For the comment, what about "We know the height, so we don't need to GetSpendHeight"?
it if more people agree.
I'm really not sure that comment would add that much value, but I don't mind adding

Copy link
Member

Choose a reason for hiding this comment

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

I agree with @jtimon that it makes more sense for ConnectBlock to pass in pindex->nHeight, rather than get the spend height from the view, even though those are the same. We could add an assert that the view's best block has the same hash as pindex->pprev if that makes the code clearer -- but we have bigger problems than just coinbase maturity if the view is out of sync with our chain!

Copy link
Contributor

@ryanofsky ryanofsky left a comment

Choose a reason for hiding this comment

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

Not sure if this needs more review. This PR has two utACKs from dcousens and me, and a concept ack from sipa.

if (!view.HaveInputs(tx))
return state.DoS(100, error("ConnectBlock(): inputs missing/spent"),
REJECT_INVALID, "bad-txns-inputs-missingorspent");
if (!Consensus::CheckTxInputs(tx, state, view, pindex->nHeight, nFees))
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm happy to add a comment but not sure what it should be.

Comment could just say why it is better to pass pindex->nHeight as nSpendHeight here instead of GetSpendHeight(view). If the two values are always equal, or have some other relation, comment could just say what that relationship is. If this is too in the weeds, definitely feel free to skip this. I'm just suggesting what I think would make the code clearer for me.

Alternately, I don't know what you think of my suggestion to eliminate the nSpendHeight argument and just call GetSpendHeight in CheckTxInputs. It does look to me like this would be logically equivalent and not effect performance, though maybe there's another reason not to do it.

Copy link
Member

@sdaftuar sdaftuar 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. I think this will slightly speed up validation time; I'm doing a benchmark to see if this is observable. Left one request and some style nits below.

@@ -24,7 +26,7 @@ namespace Consensus {
* This does not modify the UTXO set. This does not check scripts and sigs.
* Preconditions: tx.IsCoinBase() is false.
*/
bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight);
bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmount& nFees);
Copy link
Member

Choose a reason for hiding this comment

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

I think it's somewhat confusing that CheckTxInputs() will be doing calculations on accumulated fee values, and not just the particular transaction passed in.

Can we just have CheckTxInputs return the fee of the transaction passed in, and then the caller can decide what additional checks should happen? It would make more sense to me that the MoneyRange() check on total block fees happen in ConnectBlock(), rather than here (though I do think conceptually that is a reasonable check for us to add).

Alternatively, if we decide to go with the accumulated fees being checked here, I'd strongly prefer to rename this variable to something like "accumulated_fees" to make it clear what this is, and update the documentation to explain it. But I'd prefer to move the accumulation to the caller, and leave this function as operating on a single transaction.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If the fee is returned, then we can't also return a bool, and we would need to duplicate the check in ConnectBlock, AcceptToMemeoryPool and CTxMemPool::check. And at that point the additional complexity wouldn't be worth it IMO.

We could also pass a fees input/output parameter that doesn't accumulate (although you can already enjoy that functionality by simply passing 0 to the variable). In that case, the duplication would only need to duplicateMoneyrange check in ConnectBlock, but I don't really see it as an improvement over this.

Agreed, accumulated_fees would be more readable with only 2 more lines needing to change

Copy link
Member

@sipa sipa Jun 27, 2017

Choose a reason for hiding this comment

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

@jtimon You can 'return' the fee in a tuple, or as a pass-by-reference value. So for example CheckTxInputs would have CAmount& return_fee field, and return_fee would just be assigned that transaction's fee. The caller can then do the accumulated_fee += return_fee logic. This involves no duplication, and still makes CheckTxInputs purely operate on data for a single transaction.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If the concern is that the addition with other fees is not done within the function, as documented the caller can set the in/out argument to zero before calling. I could also always return only the value for the single transaction without accumulating anything (although I don't see the gain, it's just more code), at that point the argument would be out only, not in/out.

From there, to return the output argument as a tuple or pair I think it's just making things uglier and unnecessarily complicated.

instead of:

CAmount tx_fee = 0; // You will initialize the variable even if the function starts setting it to zero
if (!CheckTxInputs(..., tx_fee))
   return false;
accumulated_fee += tx_fee;

You would have something like:

struct CheckTxInputsReturn
{
   bool fValid;
   CAmount tx_fee;
}

CheckTxInputsReturn ret = CheckTxInputs(...);
if (!ret.fValid)
   return false;
accumulated_fee += ret.tx_fee;

I think that's incredibly ugly. Specially since I don't see the problem with how it is currently used when you don't want to accumulate any fees:

CAmount tx_fee = 0;
if (!CheckTxInputs(..., tx_fee))
   return false;

Please, I invite you to write your suggestions on top of this and see for yourselves that they are not an improvement but actually the contrary.
If people agree that those IMO much uglier solutions are better, I will squash your suggestions, no problem.

Copy link
Member

Choose a reason for hiding this comment

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

I was just clarifying that @sdaftuar's suggestion does not imply duplication of logic. I personally think that it's a bit cleaner to do the summing of fees outside of the validation of a single function, but it's an unimportant nit for sure.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh, sorry, the duplication comment was a mistake. Before I was checking the moneyRange for the accumulated fees and not just for the single tx fees, and I thought that check would need to be duplicated outside, but that was a change in functionality that I shouldn't be doing (and btw was missed in review).
Pedantically adding that check would be a softfork, but it should be impossible that the MoneyRange check on the accumulated fees fails anyway.

I can not accumulate anything if you guys prefer that, that's a simple change (even though I still can't understand why would you prefer that), reading your previous comment again better, you were also considering the pass by reference (what is done now), not necessarily the tuple (which is what I would be against in principle because of its ugliness).

} // end LOCK(pool.cs)

CAmount nFees = 0;
if (!Consensus::CheckTxInputs(tx, state, view, GetSpendHeight(view), nFees))
Copy link
Member

Choose a reason for hiding this comment

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

style nit: braces for one-line if

if (!inputs.HaveInputs(tx))
return state.Invalid(false, 0, "", "Inputs unavailable");
// are the actual inputs available?
if (!inputs.HaveInputs(tx))
Copy link
Member

Choose a reason for hiding this comment

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

style nit: braces for one-line if

if (!view.HaveInputs(tx))
return state.DoS(100, error("ConnectBlock(): inputs missing/spent"),
REJECT_INVALID, "bad-txns-inputs-missingorspent");
if (!Consensus::CheckTxInputs(tx, state, view, pindex->nHeight, nFees))
Copy link
Member

Choose a reason for hiding this comment

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

I agree with @jtimon that it makes more sense for ConnectBlock to pass in pindex->nHeight, rather than get the spend height from the view, even though those are the same. We could add an assert that the view's best block has the same hash as pindex->pprev if that makes the code clearer -- but we have bigger problems than just coinbase maturity if the view is out of sync with our chain!

if (!view.HaveInputs(tx))
return state.DoS(100, error("ConnectBlock(): inputs missing/spent"),
REJECT_INVALID, "bad-txns-inputs-missingorspent");
if (!Consensus::CheckTxInputs(tx, state, view, pindex->nHeight, nFees))
Copy link
Member

Choose a reason for hiding this comment

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

style nit: curly braces for one-line if

@jtimon
Copy link
Contributor Author

jtimon commented Jun 25, 2017

Hopefully fixed @sdaftuar 's nits.
Also add a third commit to properly indent CheckTxInputs and other minor style fixes like braces for one line ifs while at it.

@jtimon
Copy link
Contributor Author

jtimon commented Jun 27, 2017

Added a couple of commits to be squashed. I wouldn't personally squash the latter but it seems @sdaftuar and @sipa would like it more this way and I don't care. Before squashing I will also move the indentation commit to the first thing.

EDIT: already squashed one, updated OP.

Copy link
Contributor

@TheBlueMatt TheBlueMatt left a comment

Choose a reason for hiding this comment

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

Totally agree with @sipa and @sdaftuar, thanks for making it a non-accumulator. Generally looks good, obviously needs squash.

@@ -22,9 +24,12 @@ namespace Consensus {
/**
* Check whether all inputs of this transaction are valid (no double spends and amounts)
* This does not modify the UTXO set. This does not check scripts and sigs.
* @param[in,out] accumulated_fees this serves to get the fees of the tx as output.
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: extra space at EOL here.

* Preconditions: tx.IsCoinBase() is false.
*/
bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight);
bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmount& accumulated_fees);
Copy link
Contributor

Choose a reason for hiding this comment

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

Need to change var name here, too.

if (!Consensus::CheckTxInputs(tx, state, view, pindex->nHeight, tx_fees)) {
return error("%s: Consensus::CheckTxInputs: %s, %s", __func__, tx.GetHash().ToString(), FormatStateMessage(state));
}
nFees += tx_fees;
Copy link
Contributor

Choose a reason for hiding this comment

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

While you're at it, can you please re-add the MoneyRange checks here that Gavin removed years ago (and maybe update the PR title to indicate that you're fixing Gavin's near-bug while also decreasing the number of CCoinsView map lookups).

Copy link
Contributor

Choose a reason for hiding this comment

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

Specifically, commit 8d7849b broke the check at 8d7849b6db#diff-7ec3c68a81efff79b6ca22ac1f1eabbaR1110 and made it useless, which very narrowly didn't cause a major consensus failure and re-introduction of the original bitcoin-printing overflow bug.

…y is created

by individual transactions to 2 places (but call only once in each):

- ConnectBlock ( before calculated fees per txs twice )
- AcceptToMemoryPoolWorker ( before called CheckTxInputs 4 times and calculated
   fees per tx one extra time )

Also call tx.GetValueOut() only once per call of CheckTxInputs (instead of 2)
in 8d7849b

This can potentially prevent an overflow that could at least in theory
allow the creation of money.
@jtimon
Copy link
Contributor Author

jtimon commented Sep 20, 2017

Fixed 1 commit by @danra

@danra
Copy link
Contributor

danra commented Sep 21, 2017

utACK

@TheBlueMatt
Copy link
Contributor

re-utACK 4e955c5

@laanwj laanwj merged commit 4e955c5 into bitcoin:master Oct 11, 2017
laanwj added a commit that referenced this pull request Oct 11, 2017
…it is checked that no money...

4e955c5 Near-Bugfix: Reestablish consensus check removed in 8d7849b (Jorge Timón)
3e8c916 Introduce CheckInputsAndUpdateCoins static wrapper in txmempool.cpp (Jorge Timón)
832e074 Optimization: Minimize the number of times it is checked that no money is created (Jorge Timón)
3f0ee3e Proper indentation for CheckTxInputs and other minor fixes (Jorge Timón)

Pull request description:

  ...is created by individual transactions to 2 places (but call only once in each):

  - ConnectBlock ( before calculated fees per txs twice )
  - AcceptToMemoryPoolWorker ( before called CheckTxInputs 4 times and calculated
     fees per tx one extra time )

  Also call tx.GetValueOut() only once per call of CheckTxInputs (instead of 2)

  For more motivation:

  ~~https://github.com/bitcoin/bitcoin/blob/master/src/main.cpp#L1493~~
  jtimon/bitcoin@0.13-consensus-inputs...jtimon:0.13-consensus-inputs-comments

  EDIT: partially replaces #6445

  Near-Bugfix as pointed out in #8498 (comment)

Tree-SHA512: c71188e7c7c2425c9170ed7b803896755a92fd22f43b136eedaa6e554106696f0b10271d0ef0d0127c1eaafbc31d12eb19143df4f1b6882feecedf6ef05ea346
domob1812 added a commit to domob1812/namecoin-core that referenced this pull request Oct 15, 2017
Rename assert_raises_jsonrpc to assert_raises_rpc_error in Namecoin
tests for upstream refactoring.

Adapt verification of names for bitcoin/bitcoin#8498.

Conflicts:
	src/consensus/tx_verify.cpp
	src/consensus/tx_verify.h
	src/txmempool.cpp
	src/validation.cpp
	src/wallet/rpcdump.cpp
	test/functional/bumpfee.py
	test/util/data/txcreatemultisig1.json
codablock pushed a commit to codablock/dash that referenced this pull request Sep 30, 2019
… times it is checked that no money...

4e955c5 Near-Bugfix: Reestablish consensus check removed in 8d7849b (Jorge Timón)
3e8c916 Introduce CheckInputsAndUpdateCoins static wrapper in txmempool.cpp (Jorge Timón)
832e074 Optimization: Minimize the number of times it is checked that no money is created (Jorge Timón)
3f0ee3e Proper indentation for CheckTxInputs and other minor fixes (Jorge Timón)

Pull request description:

  ...is created by individual transactions to 2 places (but call only once in each):

  - ConnectBlock ( before calculated fees per txs twice )
  - AcceptToMemoryPoolWorker ( before called CheckTxInputs 4 times and calculated
     fees per tx one extra time )

  Also call tx.GetValueOut() only once per call of CheckTxInputs (instead of 2)

  For more motivation:

  ~~https://github.com/bitcoin/bitcoin/blob/master/src/main.cpp#L1493~~
  jtimon/bitcoin@0.13-consensus-inputs...jtimon:0.13-consensus-inputs-comments

  EDIT: partially replaces bitcoin#6445

  Near-Bugfix as pointed out in bitcoin#8498 (comment)

Tree-SHA512: c71188e7c7c2425c9170ed7b803896755a92fd22f43b136eedaa6e554106696f0b10271d0ef0d0127c1eaafbc31d12eb19143df4f1b6882feecedf6ef05ea346
codablock pushed a commit to codablock/dash that referenced this pull request Oct 2, 2019
… times it is checked that no money...

4e955c5 Near-Bugfix: Reestablish consensus check removed in 8d7849b (Jorge Timón)
3e8c916 Introduce CheckInputsAndUpdateCoins static wrapper in txmempool.cpp (Jorge Timón)
832e074 Optimization: Minimize the number of times it is checked that no money is created (Jorge Timón)
3f0ee3e Proper indentation for CheckTxInputs and other minor fixes (Jorge Timón)

Pull request description:

  ...is created by individual transactions to 2 places (but call only once in each):

  - ConnectBlock ( before calculated fees per txs twice )
  - AcceptToMemoryPoolWorker ( before called CheckTxInputs 4 times and calculated
     fees per tx one extra time )

  Also call tx.GetValueOut() only once per call of CheckTxInputs (instead of 2)

  For more motivation:

  ~~https://github.com/bitcoin/bitcoin/blob/master/src/main.cpp#L1493~~
  jtimon/bitcoin@0.13-consensus-inputs...jtimon:0.13-consensus-inputs-comments

  EDIT: partially replaces bitcoin#6445

  Near-Bugfix as pointed out in bitcoin#8498 (comment)

Tree-SHA512: c71188e7c7c2425c9170ed7b803896755a92fd22f43b136eedaa6e554106696f0b10271d0ef0d0127c1eaafbc31d12eb19143df4f1b6882feecedf6ef05ea346
codablock pushed a commit to codablock/dash that referenced this pull request Oct 2, 2019
… times it is checked that no money...

4e955c5 Near-Bugfix: Reestablish consensus check removed in 8d7849b (Jorge Timón)
3e8c916 Introduce CheckInputsAndUpdateCoins static wrapper in txmempool.cpp (Jorge Timón)
832e074 Optimization: Minimize the number of times it is checked that no money is created (Jorge Timón)
3f0ee3e Proper indentation for CheckTxInputs and other minor fixes (Jorge Timón)

Pull request description:

  ...is created by individual transactions to 2 places (but call only once in each):

  - ConnectBlock ( before calculated fees per txs twice )
  - AcceptToMemoryPoolWorker ( before called CheckTxInputs 4 times and calculated
     fees per tx one extra time )

  Also call tx.GetValueOut() only once per call of CheckTxInputs (instead of 2)

  For more motivation:

  ~~https://github.com/bitcoin/bitcoin/blob/master/src/main.cpp#L1493~~
  jtimon/bitcoin@0.13-consensus-inputs...jtimon:0.13-consensus-inputs-comments

  EDIT: partially replaces bitcoin#6445

  Near-Bugfix as pointed out in bitcoin#8498 (comment)

Tree-SHA512: c71188e7c7c2425c9170ed7b803896755a92fd22f43b136eedaa6e554106696f0b10271d0ef0d0127c1eaafbc31d12eb19143df4f1b6882feecedf6ef05ea346
UdjinM6 added a commit to UdjinM6/dash that referenced this pull request Oct 2, 2019
…umber of times it is checked that no money..."

This reverts commit 56d28c5.
UdjinM6 pushed a commit to UdjinM6/dash that referenced this pull request Oct 3, 2019
… times it is checked that no money...

4e955c5 Near-Bugfix: Reestablish consensus check removed in 8d7849b (Jorge Timón)
3e8c916 Introduce CheckInputsAndUpdateCoins static wrapper in txmempool.cpp (Jorge Timón)
832e074 Optimization: Minimize the number of times it is checked that no money is created (Jorge Timón)
3f0ee3e Proper indentation for CheckTxInputs and other minor fixes (Jorge Timón)

Pull request description:

  ...is created by individual transactions to 2 places (but call only once in each):

  - ConnectBlock ( before calculated fees per txs twice )
  - AcceptToMemoryPoolWorker ( before called CheckTxInputs 4 times and calculated
     fees per tx one extra time )

  Also call tx.GetValueOut() only once per call of CheckTxInputs (instead of 2)

  For more motivation:

  ~~https://github.com/bitcoin/bitcoin/blob/master/src/main.cpp#L1493~~
  jtimon/bitcoin@0.13-consensus-inputs...jtimon:0.13-consensus-inputs-comments

  EDIT: partially replaces bitcoin#6445

  Near-Bugfix as pointed out in bitcoin#8498 (comment)

Tree-SHA512: c71188e7c7c2425c9170ed7b803896755a92fd22f43b136eedaa6e554106696f0b10271d0ef0d0127c1eaafbc31d12eb19143df4f1b6882feecedf6ef05ea346
codablock pushed a commit to codablock/dash that referenced this pull request Oct 3, 2019
… times it is checked that no money...

4e955c5 Near-Bugfix: Reestablish consensus check removed in 8d7849b (Jorge Timón)
3e8c916 Introduce CheckInputsAndUpdateCoins static wrapper in txmempool.cpp (Jorge Timón)
832e074 Optimization: Minimize the number of times it is checked that no money is created (Jorge Timón)
3f0ee3e Proper indentation for CheckTxInputs and other minor fixes (Jorge Timón)

Pull request description:

  ...is created by individual transactions to 2 places (but call only once in each):

  - ConnectBlock ( before calculated fees per txs twice )
  - AcceptToMemoryPoolWorker ( before called CheckTxInputs 4 times and calculated
     fees per tx one extra time )

  Also call tx.GetValueOut() only once per call of CheckTxInputs (instead of 2)

  For more motivation:

  ~~https://github.com/bitcoin/bitcoin/blob/master/src/main.cpp#L1493~~
  jtimon/bitcoin@0.13-consensus-inputs...jtimon:0.13-consensus-inputs-comments

  EDIT: partially replaces bitcoin#6445

  Near-Bugfix as pointed out in bitcoin#8498 (comment)

Tree-SHA512: c71188e7c7c2425c9170ed7b803896755a92fd22f43b136eedaa6e554106696f0b10271d0ef0d0127c1eaafbc31d12eb19143df4f1b6882feecedf6ef05ea346
codablock pushed a commit to codablock/dash that referenced this pull request Oct 3, 2019
… times it is checked that no money...

4e955c5 Near-Bugfix: Reestablish consensus check removed in 8d7849b (Jorge Timón)
3e8c916 Introduce CheckInputsAndUpdateCoins static wrapper in txmempool.cpp (Jorge Timón)
832e074 Optimization: Minimize the number of times it is checked that no money is created (Jorge Timón)
3f0ee3e Proper indentation for CheckTxInputs and other minor fixes (Jorge Timón)

Pull request description:

  ...is created by individual transactions to 2 places (but call only once in each):

  - ConnectBlock ( before calculated fees per txs twice )
  - AcceptToMemoryPoolWorker ( before called CheckTxInputs 4 times and calculated
     fees per tx one extra time )

  Also call tx.GetValueOut() only once per call of CheckTxInputs (instead of 2)

  For more motivation:

  ~~https://github.com/bitcoin/bitcoin/blob/master/src/main.cpp#L1493~~
  jtimon/bitcoin@0.13-consensus-inputs...jtimon:0.13-consensus-inputs-comments

  EDIT: partially replaces bitcoin#6445

  Near-Bugfix as pointed out in bitcoin#8498 (comment)

Tree-SHA512: c71188e7c7c2425c9170ed7b803896755a92fd22f43b136eedaa6e554106696f0b10271d0ef0d0127c1eaafbc31d12eb19143df4f1b6882feecedf6ef05ea346
charlesrocket pushed a commit to AXErunners/axe that referenced this pull request Dec 19, 2019
…it is checked that no money...

4e955c5 Near-Bugfix: Reestablish consensus check removed in 8d7849b (Jorge Timón)
3e8c916 Introduce CheckInputsAndUpdateCoins static wrapper in txmempool.cpp (Jorge Timón)
832e074 Optimization: Minimize the number of times it is checked that no money is created (Jorge Timón)
3f0ee3e Proper indentation for CheckTxInputs and other minor fixes (Jorge Timón)

Pull request description:

  ...is created by individual transactions to 2 places (but call only once in each):

  - ConnectBlock ( before calculated fees per txs twice )
  - AcceptToMemoryPoolWorker ( before called CheckTxInputs 4 times and calculated
     fees per tx one extra time )

  Also call tx.GetValueOut() only once per call of CheckTxInputs (instead of 2)

  For more motivation:

  ~~https://github.com/bitcoin/bitcoin/blob/master/src/main.cpp#L1493~~
  jtimon/bitcoin@0.13-consensus-inputs...jtimon:0.13-consensus-inputs-comments

  EDIT: partially replaces #6445

  Near-Bugfix as pointed out in bitcoin/bitcoin#8498 (comment)

Tree-SHA512: c71188e7c7c2425c9170ed7b803896755a92fd22f43b136eedaa6e554106696f0b10271d0ef0d0127c1eaafbc31d12eb19143df4f1b6882feecedf6ef05ea346
barrystyle pushed a commit to PACGlobalOfficial/PAC that referenced this pull request Jan 22, 2020
… times it is checked that no money...

4e955c5 Near-Bugfix: Reestablish consensus check removed in 8d7849b (Jorge Timón)
3e8c916 Introduce CheckInputsAndUpdateCoins static wrapper in txmempool.cpp (Jorge Timón)
832e074 Optimization: Minimize the number of times it is checked that no money is created (Jorge Timón)
3f0ee3e Proper indentation for CheckTxInputs and other minor fixes (Jorge Timón)

Pull request description:

  ...is created by individual transactions to 2 places (but call only once in each):

  - ConnectBlock ( before calculated fees per txs twice )
  - AcceptToMemoryPoolWorker ( before called CheckTxInputs 4 times and calculated
     fees per tx one extra time )

  Also call tx.GetValueOut() only once per call of CheckTxInputs (instead of 2)

  For more motivation:

  ~~https://github.com/bitcoin/bitcoin/blob/master/src/main.cpp#L1493~~
  jtimon/bitcoin@0.13-consensus-inputs...jtimon:0.13-consensus-inputs-comments

  EDIT: partially replaces bitcoin#6445

  Near-Bugfix as pointed out in bitcoin#8498 (comment)

Tree-SHA512: c71188e7c7c2425c9170ed7b803896755a92fd22f43b136eedaa6e554106696f0b10271d0ef0d0127c1eaafbc31d12eb19143df4f1b6882feecedf6ef05ea346
maflcko pushed a commit that referenced this pull request May 4, 2020
b56607a Remove CCoinsViewCache::GetValueIn(...) (practicalswift)

Pull request description:

  Remove `CCoinsViewCache::GetValueIn(...)`.

  Fixes #18858.

  It seems like `GetValueIn` was added in #748 ("Pay-to-script-hash (OP_EVAL replacement)", merged in 2012) and the last use in validation code was removed in #8498 ("Near-Bugfix: Optimization: Minimize the number of times it is checked that no money...", merged in 2017).

  `CCoinsViewCache::GetValueIn(…)` performs money summation like this:

  ```c++
  CAmount CCoinsViewCache::GetValueIn(const CTransaction& tx) const
  {
      if (tx.IsCoinBase())
          return 0;

      CAmount nResult = 0;
      for (unsigned int i = 0; i < tx.vin.size(); i++)
          nResult += AccessCoin(tx.vin[i].prevout).out.nValue;

      return nResult;
  }
  ```

  Note that no check is done to make sure that the resulting `nResult` is such that it stays within the money bounds (`MoneyRange(nResult)`), or that the summation does not trigger a signed integer overflow.

  Proof of concept output:

  ```
  coins.cpp:243:17: runtime error: signed integer overflow: 9223200000000000000 + 2100000000000000 cannot be represented in type 'long'
  GetValueIn = -9221444073709551616
  ```

  Proof of concept code:

  ```c++
  CMutableTransaction mutable_transaction;
  mutable_transaction.vin.resize(4393);

  Coin coin;
  coin.out.nValue = MAX_MONEY;
  assert(MoneyRange(coin.out.nValue));

  CCoinsCacheEntry coins_cache_entry;
  coins_cache_entry.coin = coin;
  coins_cache_entry.flags = CCoinsCacheEntry::DIRTY;

  CCoinsView backend_coins_view;
  CCoinsViewCache coins_view_cache{&backend_coins_view};
  CCoinsMap coins_map;
  coins_map.emplace(COutPoint{}, std::move(coins_cache_entry));
  coins_view_cache.BatchWrite(coins_map, {});

  const CAmount total_value_in = coins_view_cache.GetValueIn(CTransaction{mutable_transaction});
  std::cout << "GetValueIn = " << total_value_in << std::endl;
  ```

ACKs for top commit:
  MarcoFalke:
    ACK b56607a
  promag:
    Code review ACK b56607a.
  jb55:
    ACK b56607a
  hebasto:
    ACK b56607a, I have not tested the code, but I have reviewed it and it looks OK, I agree it can be merged.

Tree-SHA512: 2c8402b5753ec96703d12c57c3eda8eccf999ed3519134a87faaf0838cfe44b94ef384296af2a524c06c8756c0245418d181af9083548e360905fac9d79215e6
ComputerCraftr pushed a commit to ComputerCraftr/bitcoin that referenced this pull request Jun 10, 2020
b56607a Remove CCoinsViewCache::GetValueIn(...) (practicalswift)

Pull request description:

  Remove `CCoinsViewCache::GetValueIn(...)`.

  Fixes bitcoin#18858.

  It seems like `GetValueIn` was added in bitcoin#748 ("Pay-to-script-hash (OP_EVAL replacement)", merged in 2012) and the last use in validation code was removed in bitcoin#8498 ("Near-Bugfix: Optimization: Minimize the number of times it is checked that no money...", merged in 2017).

  `CCoinsViewCache::GetValueIn(…)` performs money summation like this:

  ```c++
  CAmount CCoinsViewCache::GetValueIn(const CTransaction& tx) const
  {
      if (tx.IsCoinBase())
          return 0;

      CAmount nResult = 0;
      for (unsigned int i = 0; i < tx.vin.size(); i++)
          nResult += AccessCoin(tx.vin[i].prevout).out.nValue;

      return nResult;
  }
  ```

  Note that no check is done to make sure that the resulting `nResult` is such that it stays within the money bounds (`MoneyRange(nResult)`), or that the summation does not trigger a signed integer overflow.

  Proof of concept output:

  ```
  coins.cpp:243:17: runtime error: signed integer overflow: 9223200000000000000 + 2100000000000000 cannot be represented in type 'long'
  GetValueIn = -9221444073709551616
  ```

  Proof of concept code:

  ```c++
  CMutableTransaction mutable_transaction;
  mutable_transaction.vin.resize(4393);

  Coin coin;
  coin.out.nValue = MAX_MONEY;
  assert(MoneyRange(coin.out.nValue));

  CCoinsCacheEntry coins_cache_entry;
  coins_cache_entry.coin = coin;
  coins_cache_entry.flags = CCoinsCacheEntry::DIRTY;

  CCoinsView backend_coins_view;
  CCoinsViewCache coins_view_cache{&backend_coins_view};
  CCoinsMap coins_map;
  coins_map.emplace(COutPoint{}, std::move(coins_cache_entry));
  coins_view_cache.BatchWrite(coins_map, {});

  const CAmount total_value_in = coins_view_cache.GetValueIn(CTransaction{mutable_transaction});
  std::cout << "GetValueIn = " << total_value_in << std::endl;
  ```

ACKs for top commit:
  MarcoFalke:
    ACK b56607a
  promag:
    Code review ACK b56607a.
  jb55:
    ACK b56607a
  hebasto:
    ACK b56607a, I have not tested the code, but I have reviewed it and it looks OK, I agree it can be merged.

Tree-SHA512: 2c8402b5753ec96703d12c57c3eda8eccf999ed3519134a87faaf0838cfe44b94ef384296af2a524c06c8756c0245418d181af9083548e360905fac9d79215e6
ComputerCraftr pushed a commit to ComputerCraftr/bitcoin that referenced this pull request Jun 10, 2020
b56607a Remove CCoinsViewCache::GetValueIn(...) (practicalswift)

Pull request description:

  Remove `CCoinsViewCache::GetValueIn(...)`.

  Fixes bitcoin#18858.

  It seems like `GetValueIn` was added in bitcoin#748 ("Pay-to-script-hash (OP_EVAL replacement)", merged in 2012) and the last use in validation code was removed in bitcoin#8498 ("Near-Bugfix: Optimization: Minimize the number of times it is checked that no money...", merged in 2017).

  `CCoinsViewCache::GetValueIn(…)` performs money summation like this:

  ```c++
  CAmount CCoinsViewCache::GetValueIn(const CTransaction& tx) const
  {
      if (tx.IsCoinBase())
          return 0;

      CAmount nResult = 0;
      for (unsigned int i = 0; i < tx.vin.size(); i++)
          nResult += AccessCoin(tx.vin[i].prevout).out.nValue;

      return nResult;
  }
  ```

  Note that no check is done to make sure that the resulting `nResult` is such that it stays within the money bounds (`MoneyRange(nResult)`), or that the summation does not trigger a signed integer overflow.

  Proof of concept output:

  ```
  coins.cpp:243:17: runtime error: signed integer overflow: 9223200000000000000 + 2100000000000000 cannot be represented in type 'long'
  GetValueIn = -9221444073709551616
  ```

  Proof of concept code:

  ```c++
  CMutableTransaction mutable_transaction;
  mutable_transaction.vin.resize(4393);

  Coin coin;
  coin.out.nValue = MAX_MONEY;
  assert(MoneyRange(coin.out.nValue));

  CCoinsCacheEntry coins_cache_entry;
  coins_cache_entry.coin = coin;
  coins_cache_entry.flags = CCoinsCacheEntry::DIRTY;

  CCoinsView backend_coins_view;
  CCoinsViewCache coins_view_cache{&backend_coins_view};
  CCoinsMap coins_map;
  coins_map.emplace(COutPoint{}, std::move(coins_cache_entry));
  coins_view_cache.BatchWrite(coins_map, {});

  const CAmount total_value_in = coins_view_cache.GetValueIn(CTransaction{mutable_transaction});
  std::cout << "GetValueIn = " << total_value_in << std::endl;
  ```

ACKs for top commit:
  MarcoFalke:
    ACK b56607a
  promag:
    Code review ACK b56607a.
  jb55:
    ACK b56607a
  hebasto:
    ACK b56607a, I have not tested the code, but I have reviewed it and it looks OK, I agree it can be merged.

Tree-SHA512: 2c8402b5753ec96703d12c57c3eda8eccf999ed3519134a87faaf0838cfe44b94ef384296af2a524c06c8756c0245418d181af9083548e360905fac9d79215e6
Fabcien pushed a commit to Bitcoin-ABC/bitcoin-abc that referenced this pull request Jan 27, 2021
Summary:
> Fixes #18858.
>
> It seems like `GetValueIn` was added in PR748 ("Pay-to-script-hash (OP_EVAL replacement)", merged in 2012) and the last use in validation code was removed in [[bitcoin/bitcoin#8498 | PR8498]] ("Near-Bugfix: Optimization: Minimize the number of times it is checked that no money...", merged in 2017).

This is a backport of Core [[bitcoin/bitcoin#18859 | PR18859]]

Test Plan: nja all check-all`

Reviewers: #bitcoin_abc, majcosta

Reviewed By: #bitcoin_abc, majcosta

Differential Revision: https://reviews.bitcoinabc.org/D9071
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Sep 8, 2021
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.

10 participants