-
Notifications
You must be signed in to change notification settings - Fork 3.8k
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
ICS07 Tendermint Client implementation #5485
Conversation
This pull request introduces 1 alert when merging 7705818 into 682c8ad - view on LGTM.com new alerts:
|
This pull request introduces 1 alert when merging 062b748 into 682c8ad - view on LGTM.com new alerts:
|
… fedekunze/5476-ics-07-tendermint
Let's use the Tendermint |
… fedekunze/5476-ics-07-tendermint
Update to lite2 verifier blocked on #5527 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just one quick comment rn
Should be unblocked now? |
@@ -119,53 +120,3 @@ func (msg MsgUpdateClient) GetSignBytes() []byte { | |||
func (msg MsgUpdateClient) GetSigners() []sdk.AccAddress { | |||
return []sdk.AccAddress{msg.Signer} | |||
} | |||
|
|||
// MsgSubmitMisbehaviour defines a message to update an IBC client | |||
type MsgSubmitMisbehaviour struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
replaced by evicence
module's MsgSubmitEvidence
|
||
// State verification functions | ||
|
||
VerifyClientConsensusState( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these verification functions the ones needed to complete the handshakes? Might be helpful to annotate the methods with the different places they are anticipated to be used.
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" | ||
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/types" | ||
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/types/errors" | ||
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/types/tendermint" | ||
tendermint "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint" | ||
) | ||
|
||
// CreateClient creates a new client state and populates it with a given consensus | ||
// state as defined in https://github.com/cosmos/ics/tree/master/spec/ics-002-client-semantics#create | ||
func (k Keeper) CreateClient( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this function needs some comments in it. It is quite long...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR is pretty massive. Added a few minor comments.
ctx sdk.Context, connection connection.ConnectionEnd, height uint64, | ||
proof commitment.ProofI, path string, | ||
) bool | ||
GetConnection(ctx sdk.Context, connectionID string) (connectiontypes.ConnectionEnd, bool) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like more comments would be very helpful here.
* Update ICS 7 tests * Fix one problem * Also set consensus state for height 1 * Apply same fixes to ICS 4 tests * Remove unnecessary change * Fix ante tests; remove printfs * Remove printf * Update x/ibc/ante/ante_test.go Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>
* Add skeleton for ValidateBasic tests * Move tests; basic one passes * Add more ValidateBasic tests * Add more ValidateBasic testcases * Fix minor typo * Add `ValidateBasic` tests for Packet * Move to packet_test.go
…/cosmos/cosmos-sdk into fedekunze/5476-ics-07-tendermint
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe with the removal of the Committer
type we lost some correctness properties. Think there are some issues to be resolved here that may need to be reflected up to the spec.
-
Still need a way to retrieve the validatorSet that approved updates to client state. This can be done by persisting in the IBC store (perhaps in ConsensusState) or by passing it in as part of the message (like with
fromValidatorSet
) and verifying against the hash saved in ConsensusState -
Bisection algorithm needs to be enforced for the update functions. This requires access to lastValidatorSet
-
Misbehavior may not be on a height that was explicitly passed in as an update. This can be accounted for by loading last consensus state saved before misbehavior
-
I believe there needs to be a way to submit misbehavior to a frozen connection if it lowers the frozen height. Suppose height is frozen at 15, but there's evidence of misbehavior at 10. User should still be allowed to submit this evidence to lower the frozen height even further.
-
ClientState should have an
UnbondingPeriod
field so that chains have some notion of what the unbonding period is for the connecting chain.
- This can then be used to prevent updates that fastforward height beyond
last_height + unbonding_period
even if the header can be verified by the last ValidatorSet - It can also be used to prevent misbehavior from being submitted at height below
last_height - unbonding_period
since the keys of validator set that early may be compromised and can be used to create fake misbehavior and allow malicious user to freeze a connection. Ex: Chain is at block 1000000, validator set keys at block 1 are no longer used and compromised. User creates fake commit at height 1 with compromised keys and freezes chain all the way back at height 1.
I can work on implementing these changes once i get agreement that the problems i raised are real and consensus on the solutions i propose
if err := header.ValidateBasic(chainID); err != nil { | ||
return err | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like with removing the Committer
interface an important check was removed.
I believe we still need to make sure that this Header will be verified by the last update's ValidatorSet.
To do this, we need a way to retrieve the last ValidatorSet that caused an update on this connection and then call
lastValidatorSet.VerifyFutureCommit(header.ChainID, header.Commit.BlockID, header.Height, header.Commit)
Not sure how to do this with the current datastructures now that Committer is removed. If the full ValidatorSet gets saved in ConsensusState
rather than just the hash then this is possible
The code as is seems like it will allow arbitrary updates to a connection from an arbitrary validatorset.
Need to implement the bisection algorithm for correct and safe updating
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the full ValidatorSet gets saved in ConsensusState rather than just the hash then this is possible
@cwgoes can we update the spec to include the validator set instead of the hash?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure. cosmos/ibc#366. I'll work on this now.
clientState clientexported.ClientState, | ||
consensusState clientexported.ConsensusState, | ||
misbehaviour clientexported.Misbehaviour, | ||
height uint64, // height at which the consensus state was loaded |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't look like it is:
https://github.com/cosmos/cosmos-sdk/pull/5485/files#diff-be64020aa203f351d8bd639c630aa097R124
Since the height passed in is the height of the misbehaviour not the height of the consensusState. While this PR makes them the same height, i believe they may not be in general
} | ||
|
||
committer, found := k.GetCommitter(ctx, misbehaviour.ClientID, uint64(misbehaviour.GetHeight())) | ||
consensusState, found := k.GetConsensusState(ctx, misbehaviour.GetClientID(), uint64(misbehaviour.GetHeight())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The consensusState may not exist for the height where the misbehavior is found.
For example, if there were client state updates at height 10 and height 20, then there will be consensus states in the store at height 10 and 20
However, a misbehavior may have first happened at height 15 forwhich there is no consensus state stored. In this case, the fromValidatorSet
should be the validatorSet from height 10.
And thus the ConsensusState
passed in should also be from height 10
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, so change it tomin(clientState.GetLatestHeight(), misbehaviour.GetHeight())
= min(20, 15)
but that won't work since it'll be still 15... there won't be a consensus state stored at that height.
We'd need to iterate over the keys to get the latest height at which the consensus state was stored that satisfies height <= min(clientState.GetLatestHeight(), misbehaviour.GetHeight())
and min(clientState.GetLatestHeight(), misbehaviour.GetHeight()) - height <= trusting period
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean for the case where there was misbehaviour at height 15 but we are already at height 20? If so, there should be an intermediary set of two conflicting headers, and if we have a consensus state before height 15 stored the evidence should be valid (since both will be valid updates to it). I don't think this requires changes (at least to the spec). This line needs to be changed though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'd need to iterate over the keys to get the latest height at which the consensus state
Yes this is true. This is what the old GetConsensusState
function did under the hood. You could reimplement this (either in GetConsensusState
or in another helper function)
Or you could use the iavlStore.ReverseIterator
and just grab the first element. This should be faster, but i couldn't find how to get this working on my first try hence issue #5365
if we have a consensus state before height 15 stored the evidence should be valid
Yup the evidence will still be valid because the update at 20 must have been valid. However, we still need to iterate through the store to find this past consensus state
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup the evidence will still be valid because the update at 20 must have been valid. However, we still need to iterate through the store to find this past consensus state
Why do we need to iterate? We know what the old height was (from the Evidence
).
Yes, I suggest the latter approach since it saves state space, but we could also store & prune the validator sets, that would be fine as well.
This should be imported from Tendermint with the Tendermint lite client "Verify" function. The
Misbehaviour should be able to load a particular past consensus state, as per the spec. Looking at your comment above, this is not quite what the implementation does - it should be.
I agree (see above comment about "min" for frozen height).
That's probably the right place to put it. Any Tendermint lite client parameters also need to be in the
This should not be necessary to separately check if the Tendermint light client's
Ah yes, I agree with this, it should also be changed in the spec - cosmos/ibc#364. |
* ICS 07 Debugging * WIP Debugging * Foo bar baz, baz bar foo, 🤷♂️ * cleanup print statements * cleanup verification test * add return err for proof verification * cleanup; start handshake testing * connection handshake tests * scopelint * WIP Test refactor * fix ICS03 tests * fix ICS04 tests * nolint Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { | ||
suite.SetupTest() // reset | ||
|
||
tc.malleate() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using the variable on range scope tc
in function literal (from scopelint
)
Will address in a follow up PR
// } | ||
|
||
previousConnection, found := k.GetConnection(ctx, connectionID) | ||
if found && !(previousConnection.State == exported.INIT && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe a good idea to extract this into a function previousConnection.????(exported, counterparty, version)
} | ||
if h.ValidatorSet == nil { | ||
return sdkerrors.Wrap(clienttypes.ErrInvalidHeader, "validator set is nil") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't you wanna check SignedHeader.ValidatorsHash == ValidatorSet.Hash() here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm surprised that the check is not already done on the SignedHeader.ValidateBasic()
@marbar3778 @tessr
Closes: #5312
Closes: #5476
NOTE: this PR is ready for review, pending tests fixes
Please review against each individual ICS specification.
TODO:
x/ibc/03-connection/keeper/handshake_test.go
x/ibc/03-connection/keeper/verify_test.go
x/ibc/04-channel/keeper/handshake_test.go
x/ibc/04-channel/keeper/packet_test.go
(nice-to-have)x/ibc/04-channel/keeper/timeout_test.go
(nice-to-have)fixBlocked by proof verificationx/ibc/07-tendermint/client_state_test.go
(uncomment test cases)Description
x/ibc/07-tendermint/
. Previous tendermint client types (x/ibc/02-client/types/tendermint/
) are now in the former packagex/ibc/02-client/types/errors/
) to client types (x/ibc/02-client/types/errors.go
)switch
statementChannelI
andConnectionI
interfaces tox/ibc/XX-ICS/exported/
to prevent circle depencenciesMsgSubmitMisbehaviour
and replace it for evidence's moduleMsgSubmitEvidence
rc5
)For contributor use:
docs/
) or specification (x/<module>/spec/
)godoc
comments.Unreleased
section inCHANGELOG.md
Files changed
in the Github PR explorerFor admin use:
WIP
,R4R
,docs
, etc)