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

IBC client - evidence module route #5305

Closed
wants to merge 10 commits into from
Closed

Conversation

fedekunze
Copy link
Collaborator

@fedekunze fedekunze commented Nov 12, 2019

  • Targeted PR against correct branch (see CONTRIBUTING.md)

  • Linked to github-issue with discussion and accepted design OR link to spec that describes this work.

  • Wrote tests

  • Updated relevant documentation (docs/)

  • Added a relevant changelog entry to the Unreleased section in CHANGELOG.md

  • Re-reviewed Files changed in the github PR explorer


For Admin Use:

  • Added appropriate labels to PR (ex. wip, ready-for-review, docs)
  • Reviewers Assigned
  • Squashed all commits, uses message "Merge pull request #XYZ: [title]" (coding standards)

@fedekunze fedekunze self-assigned this Nov 12, 2019
@fedekunze fedekunze changed the base branch from master to ibc-alpha November 12, 2019 17:27
@fedekunze fedekunze added R4R and removed WIP labels Nov 13, 2019
@fedekunze fedekunze marked this pull request as ready for review November 13, 2019 11:09
@fedekunze
Copy link
Collaborator Author

@cwgoes do we want to check every n blocks if there's existent client misbehavior stored in order to freeze the client without submitting a new transaction (i.e having a BeginBlock logic for that)?

@cwgoes
Copy link
Contributor

cwgoes commented Nov 13, 2019

@cwgoes do we want to check every n blocks if there's existent client misbehavior stored in order to freeze the client without submitting a new transaction (i.e having a BeginBlock logic for that)?

I'm a bit lost. If we ever detect misbehaviour (which requires submitting a transaction) we should freeze the client immediately. What are the two separate transactions involved in your scenario?

@cwgoes cwgoes mentioned this pull request Nov 13, 2019
7 tasks
TotalPower int64 `json:"total_power" yaml:"total_power"`
// Misbehaviour contains an evidence that a
type Misbehaviour struct {
*Evidence
Copy link
Member

Choose a reason for hiding this comment

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

Why does Misbehaviour contain ChainID when Evidence already has ChainID field?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Misbehaviour contains only the ClientID

}
if ev.ValidatorPower <= 0 {
return sdk.ConvertError(errors.ErrInvalidEvidence(errors.DefaultCodespace, fmt.Sprintf("Invalid Validator Power: %d", ev.ValidatorPower)))
if err := m.Evidence.ValidateBasic(); err != nil {
Copy link
Member

Choose a reason for hiding this comment

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

needs to also check m.ChainID == m.Evidence.ChainID

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

see comment above

x/ibc/02-client/types/tendermint/evidence_test.go Outdated Show resolved Hide resolved
//
// NOTE: In the first implementation, only Tendermint misbehaviour evidence is
// supported.
func (k Keeper) CheckMisbehaviourAndUpdateState(ctx sdk.Context, evidence evidenceexported.Evidence) error {
Copy link
Member

Choose a reason for hiding this comment

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

This doesn't make sense to me. My understanding is that the client should be frozen if the entire chain breaks the consensus protocol. For example:

  1. ChainA is running light client of ChainB
  2. ChainB validator set commits 2 different blocks for the same height (violation of consensus protocol)
  3. Evidence of this violation is submitted to ChainA
  4. ChainA freezes light client of ChainB

The code here looks like it will freeze the client as soon as someone posts evidence of a single validator double signing. This doesn't make sense since it won't disrupt consensus, so long as validator power < 1/3 of total.

Thus, with code as is, a single slash event of a double-signing validator on chainB (which is still considered honest execution of Byzantine consensus protocol) will cause IBC client to freeze. Thus, a chainA no longer has any Byzantine tolerance for chainB; which doesn't seem like the intended behavior from looking at spec

@cwgoes

Copy link
Member

Choose a reason for hiding this comment

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

I believe the Evidence should be changed from embedding a single tendermint.DoubleVoteEvidence to including two different block headers that got committed by ChainB's validatorSet but are for same height

Copy link
Member

Choose a reason for hiding this comment

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

Haha, i think i was the one to commit this mistake to the code in the first place 😆. Will put up PR for proposed fix, once i get an ACK that the problem i point out is correct

Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

Further thinking here after prototyping solution:

  1. The Evidence interface defined in x/evidence isn't well suited to use here, since that is Evidence against a single malicious validator. Whereas I believe the Evidence that should freeze a ICS-02 client is evidence of a malicious chain. We should have some other primitive defined in x/ibc to deal with malicious chains.

  2. The overloading of the term Evidence to describe evidence against validators and evidence against chains is confusing. I think we should have a different word to talk about malicious chains and the associated proofs, (Violation maybe)?

Proposals:

A) evidence module is adjusted to handle both malicious-validator evidence and malicious-chain evidence

B) malicious-chain evidence types and functions are implemented within x/ibc since that is the only place they will be used.

I'm partial to proposal B myself and removing any dependence of x/evidence from x/ibc for now, but interested to hear what others think. Note: validator-specific evidence isn't relevant in IBC for version 1.0.0, but will later be useful once we implement shared-security across chains.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I believe the Evidence should be changed from embedding a single tendermint.DoubleVoteEvidence to including two different block headers that got committed by ChainB's validatorSet but are for same height

yeah, that's how it is defined on the spec:

interface Evidence {
  h1: Header
  h2: Header
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The Evidence interface defined in x/evidence isn't well suited to use here, since that is Evidence against a single malicious validator. Whereas I believe the Evidence that should freeze a ICS-02 client is evidence of a malicious chain. We should have some other primitive defined in x/ibc to deal with malicious chains.

A) evidence module is adjusted to handle both malicious-validator evidence and malicious-chain evidence

I think we should implement a general Evidence interface that only contains the following methods:

// Evidence defines the contract which concrete evidence types of misbehavior
// must implement.
type Evidence interface {
	Route() string
	Type() string
	String() string
	Hash() cmn.HexBytes
	ValidateBasic() error
}

Probably the byzantine validator related methods from the current Evidence interface should be abstracted into another interface:

        // The consensus address of the malicious validator at time of infraction
	GetConsensusAddress() sdk.ConsAddress

	// Height at which the infraction occurred
	GetHeight() int64

	// The total power of the malicious validator at time of infraction
	GetValidatorPower() int64

	// The total validator set power at time of infraction
	GetTotalPower() int64

And ICS02 should implement the Evidence interface from the spec (2 headers) as well as the general interface

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The overloading of the term Evidence to describe evidence against validators and evidence against chains is confusing. I think we should have a different word to talk about malicious chains and the associated proofs, (Violation maybe)?

Agree, ICS02 introduces the term of a client Misbehaviour, which is what I implemented in this PR

Copy link
Contributor

Choose a reason for hiding this comment

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

The Evidence interface defined in x/evidence isn't well suited to use here, since that is Evidence against a single malicious validator. Whereas I believe the Evidence that should freeze a ICS-02 client is evidence of a malicious chain. We should have some other primitive defined in x/ibc to deal with malicious chains.

A) evidence module is adjusted to handle both malicious-validator evidence and malicious-chain evidence

I think we should implement a general Evidence interface that only contains the following methods:

// Evidence defines the contract which concrete evidence types of misbehavior
// must implement.
type Evidence interface {
	Route() string
	Type() string
	String() string
	Hash() cmn.HexBytes
	ValidateBasic() error
}

Probably the byzantine validator related methods from the current Evidence interface should be abstracted into another interface:

        // The consensus address of the malicious validator at time of infraction
	GetConsensusAddress() sdk.ConsAddress

	// Height at which the infraction occurred
	GetHeight() int64

	// The total power of the malicious validator at time of infraction
	GetValidatorPower() int64

	// The total validator set power at time of infraction
	GetTotalPower() int64

And ICS02 should implement the Evidence interface from the spec (2 headers) as well as the general interface

This approach seems OK to me. Conceivably other modules might want to handle such misbehaviour as well (e.g. if someone had purchased insurance that pays out if a validator set breaks safety).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Conceivably other modules might want to handle such misbehaviour as well (e.g. if someone had purchased insurance that pays out if a validator set breaks safety).

afaik we haven't implemented slashing logic for this type of misbehaviour (if that's what you're referring with "handle such misbehaviour")

Copy link
Contributor

@cwgoes cwgoes left a comment

Choose a reason for hiding this comment

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

See responses to @AdityaSripal's comments

//
// NOTE: In the first implementation, only Tendermint misbehaviour evidence is
// supported.
func (k Keeper) CheckMisbehaviourAndUpdateState(ctx sdk.Context, evidence evidenceexported.Evidence) error {
Copy link
Contributor

Choose a reason for hiding this comment

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

This doesn't make sense to me. My understanding is that the client should be frozen if the entire chain breaks the consensus protocol. For example:

  1. ChainA is running light client of ChainB
  2. ChainB validator set commits 2 different blocks for the same height (violation of consensus protocol)
  3. Evidence of this violation is submitted to ChainA
  4. ChainA freezes light client of ChainB

The code here looks like it will freeze the client as soon as someone posts evidence of a single validator double signing. This doesn't make sense since it won't disrupt consensus, so long as validator power < 1/3 of total.

Thus, with code as is, a single slash event of a double-signing validator on chainB (which is still considered honest execution of Byzantine consensus protocol) will cause IBC client to freeze. Thus, a chainA no longer has any Byzantine tolerance for chainB; which doesn't seem like the intended behavior from looking at spec

@cwgoes

Yes, this is right. Although it is also possible to choose thresholds other than 1/3 (perhaps gaining some extra precautionary safety at the expense of liveness), we should initially freeze the client if and only if two valid headers were committed at the same height.

//
// NOTE: In the first implementation, only Tendermint misbehaviour evidence is
// supported.
func (k Keeper) CheckMisbehaviourAndUpdateState(ctx sdk.Context, evidence evidenceexported.Evidence) error {
Copy link
Contributor

Choose a reason for hiding this comment

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

Further thinking here after prototyping solution:

  1. The Evidence interface defined in x/evidence isn't well suited to use here, since that is Evidence against a single malicious validator. Whereas I believe the Evidence that should freeze a ICS-02 client is evidence of a malicious chain. We should have some other primitive defined in x/ibc to deal with malicious chains.
  2. The overloading of the term Evidence to describe evidence against validators and evidence against chains is confusing. I think we should have a different word to talk about malicious chains and the associated proofs, (Violation maybe)?

Proposals:

A) evidence module is adjusted to handle both malicious-validator evidence and malicious-chain evidence

B) malicious-chain evidence types and functions are implemented within x/ibc since that is the only place they will be used.

I'm partial to proposal B myself and removing any dependence of x/evidence from x/ibc for now, but interested to hear what others think. Note: validator-specific evidence isn't relevant in IBC for version 1.0.0, but will later be useful once we implement shared-security across chains.

A new term might be a helpful differentiator. Malicious-chain evidence (or violation) types will be used by both the IBC on-chain light clients and Tendermint light clients (e.g. if you run gaiacli in proper verification mode), so we should find a way to share the definitions between those two, ideally.

Co-Authored-By: Aditya <adityasripal@gmail.com>
@fedekunze
Copy link
Collaborator Author

Will put up PR for proposed fix, once i get an ACK that the problem i point out is correct

@AdityaSripal should we block this PR until your fix is merged to ibc-alpha? cc: @cwgoes

@AdityaSripal
Copy link
Member

AdityaSripal commented Nov 15, 2019

ill make the PR against this branch since it already incorporates the interface from x/evidence.

Don't think its a huge deal if this gets merged first. but would be slightly more convenient to block

@alexanderbez alexanderbez mentioned this pull request Nov 21, 2019
30 tasks
@fedekunze fedekunze mentioned this pull request Nov 22, 2019
5 tasks
@fedekunze
Copy link
Collaborator Author

moved to #5321

@fedekunze fedekunze closed this Nov 22, 2019
@fedekunze fedekunze deleted the fedekuze/ibc-evidence branch November 22, 2019 12:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants