Builds on #7184
Adds a commit to keep the mempool consistent with respect to sequence locked txs in the event of a reorg
as said squashes to clean up the history can happen after review. As mentiooned before, I still don't see how maaku@sequencenumbers...morcos achieves its alleged goal.
rebased
I think this PR is too complicated for fixing the perf issue, if https://github.com/NicolasDorier/bitcoin/compare/67646e099c13...b2a27a71823b is correct, it would be simpler to review. Regardless if we use #7184 or not.
@NicolasDorier I agree. Maybe more importantly, all the extra complexity is outside of the consensus critical code. Maybe you should consider opening a PR for your solution? In this thread we should focus on the code of this PR. We have #7176 to discuss the different solutions more generally.
Is this supposed to fix the performance issues of CNB without touching miner.cpp, or are this just preparations without the actual performance solution?
@jtimon This fixes the performance issues by never introducing them into CNB in the first place. #7184 on its own has performance issues with reorgs. @NicolasDorier You think just the second commit here is significantly more complicated than your final commit in #7190?
squashed a bug fix (wasn't actually skipping the work it was supposed to)
I like the fact you separate CheckLockTime (if you rename IsFinalTx) and CheckSequenceLockTime, but I really don't like the LockPoints structure. I'm still reviewing if commit 2 might not result in mempool finality corruption, I really don't find it obvious.
btw can you rename IsFinalTx to CheckLockTime as you said you wanted to do ?
@NicolasDorier My approach and yours are not that different.
Ok I'm getting it. Seems like it can work. You forget to check SequenceLockTime in rpcwallet.cpp, wallet.cpp.
@NicolasDorier I left that out on purpose. See #7184. It might need to be added back in but it wasn't really clear to me how that code ever gets hit. I've tried asking about it on IRC a couple of times. But it doesn't seem possible to me to generate a wallet tx which is sequence locked except in the event of a reorg, at which point the tx won't be in your mempool anyway.
Ok, I don't really understand those implication yet.
Will you rename to IsFinalTx to CheckLockTime and CheckSequenceLocks to CheckSequenceLockTime ?
I remember having done this remark already: and I was still not too much convinced by your response, I'm saying it here so other reviewer can dig in about it:
My main doubt is that there is a case where the nHeight/nTime of LockPoint should be invalidated but is not. Imagine you have a tx spending unconf coin C1 when tip is B1 and height X. MaxInputHash would be equals to hash(B1).
Now if B2 is found at height X+1, C1 still unconf, since B1 is still in the chain the LockPoint is not invalidated. My worry is that LockPoint SHOULD be invalidated as the prevHeights vector for calculating the LockPoint would not be the same anymore (the assumed height of C1 would be X+2 instead of X+1). The value of nHeight/nTime in the LockPoint would be impacted by it. I am still not entirely clear if it would have a chance of corrupting the mempool with an invalid tx though. (which would give problem to GBT which now rely on a coherent mempool)
@NicolasDorier Yes sorry I hate the way those get lost. Here is your old comment: https://github.com/morcos/bitcoin/commit/f8b6614#commitcomment-15979134
I ended up punting on building the infrastructure to accept sequence locked txs that were not yet final. I have the code written to do it, but it requires slight changes to the BIP 68 code and I didn't want to hold up merger for something of dubious value. But then I forgot to go back and clarify why the code here is safe.
I've now added a commit with what is hopefully a detailed explanation. And in the process I actually made it more efficient by eliminating the mempool input heights instead of capping them which will make recalculations on reorg even less frequent.
Good explanation, seems ok to me, I'll test a bit though.
just changed a couple words in the comment
you may optimize even more: Only take the heights which correspond to an input who has a LockSequence for maxInputHeight calculation.
@NicolasDorier that's already done. CalculateSequenceLocks already sets heights for non sequence locked inputs to 0.
Code review ACK (apart from comment nit). Testing...
Tested ACK (hacked up some extra tests to bip68-sequence.py to exercise the reorg logic) 5912944f4d5eeb4078a5bb658ad09ef7eabbf53b
comment nit addressed
Kicked Travis
178 | + update_lock_points(LockPoints _lp) : lp(_lp) { } 179 | + 180 | + void operator() (CTxMemPoolEntry &e) { e.UpdateLockPoints(lp); } 181 | + 182 | +private: 183 | + LockPoints lp;
I believe it suffices to turn this into a const reference.
60 | @@ -61,6 +61,11 @@ void CTxMemPoolEntry::UpdateFeeDelta(int64_t newFeeDelta) 61 | feeDelta = newFeeDelta; 62 | } 63 | 64 | +void CTxMemPoolEntry::UpdateLockPoints(LockPoints& lp)
Make input argument const?
If I've done something wrong it was by mistake I'm new and trying to learn. Sorry if I messed up
Please explain all my mistakes please as this should help the future
utACK ddb4dab
If I've done something wrong it was by mistake I'm new and trying to learn. Sorry if I messed up
What happened exactly? If you have specific questions about development and review process feel free to mail me on laanwj@gmail.com
ut/code review ACK ddb4dab
43 | + int height; 44 | + int64_t time; 45 | + // As long as the current chain descends from the highest height block 46 | + // containing one of the inputs used in the calculation, then the cached 47 | + // values are still valid even after a reorg. 48 | + uint256 maxInputHash;
Did you consider storing a CBlockIndex* here instead of a uint256? (may be a stupid suggestion, but from what I see the only thing you do is look it back up in mapBlockIndex)
hmm... i feel like we did consider that, but i can't see now why that wouldn't work. maybe it didn't work with some previous iteration. it makes sense to switch to that if we can't see any problems with it.
right, I don't see any problems with it at least: as I see it it'd simplify the code, reduce storage requirement for LockPoints, and makes the same (valid) assumption that a block index entry never goes away
Concept ACK, started reviewing more deeply.
Obtain LockPoints to store in CTxMemPoolEntry and during a reorg, evaluate whether they are still valid and if not, recalculate them.
Squashed from e6cc06b which contained the switch to CBlockIndex*'s
utACK 982670c
Removed 'needs backport' label per previous comment