-
Notifications
You must be signed in to change notification settings - Fork 585
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
testing/ - Fix chain.LastHeader callsite #1668
Conversation
Codecov Report
Additional details and impacted files@@ Coverage Diff @@
## main #1668 +/- ##
==========================================
+ Coverage 80.06% 80.35% +0.28%
==========================================
Files 165 207 +42
Lines 12381 16880 +4499
==========================================
+ Hits 9913 13564 +3651
- Misses 2000 2755 +755
- Partials 468 561 +93
|
Hi Dan, thanks for the detailed explanation!! Since the bug is quite subtle, I think it would be very helpful to see a test case written that would fail with the current test library. That would make it a lot easier to verify the existence of bug and fix. Thanks! |
Many thanks @danwt 🙏 I agree with @AdityaSripal that'd be nice to have a test case which shows the existence of the bug. I guess the general idea for the function is that it should:
whereas currently we
but the bug lies in the fact that the application changes should change the value of the next validator set The changes make sense to me |
Hey, I will try to provide a small replication at some point but it will take a little bit. Thanks. |
Just curious why this got closed. Is it still an issue? |
Oh no, I had a PR from my clone and I deleted the clone by accident (I was doing house cleaning). I'll see if I can retrieve it. |
Hi @danwt, just spent a little time revisiting this issue. Any luck on providing a small replication? I have a hard time verifying the bug via logical reasoning. From my understanding, begin block in the staking module sets the current validator set for the block, while end block obtains a list of changes, applies them and returns the changes. I believe once a header begin block is being called, the header has already been committed to by the validator set (they agreed on the included txs for the next blocks execution). See my #1169 (comment) here. But something doesn't add up for me here. If end block returns already applied changes, then as you say, the validator set of h + 1 should be the validator set + applied changes. But as this comment says, it appears to be a n + 2 situation. Ah, maybe it is this:
Is historical info correct? Is there something I am missing, cc @AdityaSripal |
Oh yea, here we can see the historical info has the header and val set. I'd be interested to know if I'm still not sure about the returned end block changes already being reflected in the next block or not |
I think this might be related to #3900, if state changes are being applied in |
Hi @danwt, I am going to close this issue. Thanks for your report. I have opened #3997 which explicitly mimics the flow of ABCI calls. I believe that code has the correct handling of the validator set + applying the validator set changes. I don't think there is an issue though in the existing code, as validator set updates must occur after a block application logic. That is, the header should be committed first with the validator set + next validator set, then execute app logic which returns set changes applied in the next block (when proposing the block) The testing pkg I think in its current state is somewhat hard to follow as it does things mostly correct but not perfect. I have proposed naming changes (LatestCommittedHeader, CurrentUncommittedHeader), which hopefully should clear things up |
Sounds good 👍 |
Bug
The way the light client works is:
When an
UpdateClient
operation completes and a headerH0
with heighth0
,valset
v0
andnextValset
nV0
becomes trusted the client storesnV0
as thetrustedValset
forh0
. A futureUpdateClient
operation might occur with headerH1
, heighth1
(h0
<h1
) and citingh0
as the trusted height. For this operation to succeed thetrustedValset
included inH1
must equalnV0
.The bug is in the code: suppose an attempted execution following the above pattern. Suppose the header
H0
is trusted by the light client. This header was created from the fieldchain.LastHeader
which is updated too early and thus has an incorrectnextValSet
. Thus the fieldnextValset
is set tov0
and notnV0
. This is trusted by the client so the client will expect a future headerH1
to havetrustedValset
equal tov0
. But thistrustedValset
is correctly queried hereibc-go/testing/chain.go
Line 411 in 527a11a
using historical info, set by the staking module based on the correct notion of
nextVals
. Thus there is a mismatch. It will trigger thisibc-go/modules/light-clients/07-tendermint/types/update.go
Line 155 in 527a11a
I can replicate this bug but it is a bit involved. I will update this PR with more info if wanted when I have time.
Extra info
See also
ValidatorHash
andNextValidatorHash
herehttps://github.com/tendermint/tendermint/blob/master/spec/core/data_structures.md#header=
as well as here in tendermint
thus
Vals
andNextVals
should be the same for both fields hereibc-go/testing/chain.go
Lines 56 to 57 in 527a11a
which they are not.
*PS: I wonder if there is a 'two wrongs make a right' thing going on somewhere in testing/, generally