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

Consumer sends invalid validator updates to tendermint, resulting in tm.verifyRemovals fail #230

Closed
danwt opened this issue Jul 13, 2022 · 2 comments · Fixed by #239
Closed
Assignees
Labels
type: bug Issues that need priority attention -- something isn't working

Comments

@danwt
Copy link
Contributor

danwt commented Jul 13, 2022

This tendermint code checks if the validator set updates returned in EndBlock are valid

https://github.com/tendermint/tendermint/blob/85870def7b628effad73af942e638bbddf2ba8fd/types/validator_set.go#L538-L544

func verifyRemovals(deletes []*Validator, vals *ValidatorSet) (votingPower int64, err error) {
	removedVotingPower := int64(0)
	for _, valUpdate := range deletes {
		address := valUpdate.Address
		_, val := vals.GetByAddress(address)
		if val == nil {
			return removedVotingPower, fmt.Errorf("failed to find validator %X to remove", address)

The check can fail on consumer because the passed updates are not filtered correctly.

data, ok := am.keeper.GetPendingChanges(ctx)
if !ok {
return []abci.ValidatorUpdate{}
}
// apply changes to cross-chain validator set
am.keeper.ApplyCCValidatorChanges(ctx, data.ValidatorUpdates)
am.keeper.DeletePendingChanges(ctx)
return data.ValidatorUpdates

The data needs to be modified in here

func (k Keeper) ApplyCCValidatorChanges(ctx sdk.Context, changes []abci.ValidatorUpdate) {
for _, change := range changes {
addr := utils.GetChangePubKeyAddress(change)
val, found := k.GetCCValidator(ctx, addr)
// set new validator bonded
if !found {
if 0 < change.Power {
consAddr := sdk.ConsAddress(addr)
// convert validator pubkey from TM proto to SDK crytpo type
pubkey, err := cryptocodec.FromTmProtoPublicKey(change.GetPubKey())
if err != nil {
panic(err)
}
ccVal, err := types.NewCCValidator(addr, change.Power, pubkey)
if err != nil {
panic(err)
}
k.SetCCValidator(ctx, ccVal)
k.AfterValidatorBonded(ctx, consAddr, nil)
}
continue
}
// remove unbonding existing-validators
if change.Power < 1 {
k.DeleteCCValidator(ctx, addr)
continue
}
// update existing validators power
val.Power = change.Power
k.SetCCValidator(ctx, val)
}
}

See the very closely related spec issue that was fixed already

I can make a PR for this soon.

Found with diff testing.

@danwt danwt self-assigned this Jul 13, 2022
@danwt danwt added type: bug Issues that need priority attention -- something isn't working ccv-core labels Jul 13, 2022
@danwt danwt moved this to Todo in Replicated Security Jul 13, 2022
@sainoe
Copy link
Contributor

sainoe commented Jul 18, 2022

The check can fail on consumer because the passed updates are not filtered correctly.

So Tendermint errors when ValUpdates contains a change that has an unexisting validator in the consumer valset and a voting power equals to 0 ?

@danwt
Copy link
Contributor Author

danwt commented Jul 18, 2022

Yes. Tendermint interprets this as trying to delete a non-existing validator.

The pattern is:

A. Send valUpdate(val=val0, power=0) to tendermint (consumer side)
B. Send valUpdate(val=val0, power=1) to consumer (but consumer does not process it)
C. Send valUpdate(val=val0, power=0) to consumer (but consumer does not process it)
D. Consumer process updates from B,C. They are aggregated to valUpdate(val=val0, power=0)
E. Consumer sends update from D to tendermint

danwt added a commit that referenced this issue Jul 18, 2022
* Filter tendermint updates in consumer endblock

* Improve readability ApplyUpdates

Co-authored-by: Daniel <[email protected]>
Repository owner moved this from Todo to Done in Replicated Security Jul 18, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug Issues that need priority attention -- something isn't working
Projects
No open projects
Status: Done
2 participants