Skip to content

Commit

Permalink
chore: prune expired 07-tendermint consensus states on duplicate he…
Browse files Browse the repository at this point in the history
…ader updates (#2965)

* move pruning to above duplicate update check

* adding test for pruning on duplicate header update

* adding additional check - assert that a consensus state exists at the prune height
  • Loading branch information
damiannolan authored Dec 22, 2022
1 parent a89d5a7 commit b697a6f
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 2 deletions.
4 changes: 2 additions & 2 deletions modules/light-clients/07-tendermint/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,14 +134,14 @@ func (cs ClientState) UpdateState(ctx sdk.Context, cdc codec.BinaryCodec, client
panic(fmt.Errorf("expected type %T, got %T", &Header{}, clientMsg))
}

cs.pruneOldestConsensusState(ctx, cdc, clientStore)

// check for duplicate update
if consensusState, _ := GetConsensusState(clientStore, cdc, header.GetHeight()); consensusState != nil {
// perform no-op
return []exported.Height{header.GetHeight()}
}

cs.pruneOldestConsensusState(ctx, cdc, clientStore)

height := header.GetHeight().(clienttypes.Height)
if height.GT(cs.LatestHeight) {
cs.LatestHeight = height
Expand Down
42 changes: 42 additions & 0 deletions modules/light-clients/07-tendermint/update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,48 @@ func (suite *TendermintTestSuite) TestUpdateState() {
suite.Require().False(found)
}, true,
},
{
"success with pruned consensus state using duplicate header", func() {
// this height will be expired and pruned
err := path.EndpointA.UpdateClient()
suite.Require().NoError(err)
pruneHeight = path.EndpointA.GetClientState().GetLatestHeight().(clienttypes.Height)

// assert that a consensus state exists at the prune height
consensusState, found := path.EndpointA.Chain.GetConsensusState(path.EndpointA.ClientID, pruneHeight)
suite.Require().True(found)
suite.Require().NotNil(consensusState)

// Increment the time by a week
suite.coordinator.IncrementTimeBy(7 * 24 * time.Hour)

// create the consensus state that can be used as trusted height for next update
err = path.EndpointA.UpdateClient()
suite.Require().NoError(err)

// Increment the time by another week, then update the client.
// This will cause the first two consensus states to become expired.
suite.coordinator.IncrementTimeBy(7 * 24 * time.Hour)
err = path.EndpointA.UpdateClient()
suite.Require().NoError(err)

// use the same header which just updated the client
clientMessage, err = path.EndpointA.Chain.ConstructUpdateTMClientHeader(path.EndpointA.Counterparty.Chain, path.EndpointA.ClientID)
suite.Require().NoError(err)
},
func() {
tmHeader, ok := clientMessage.(*ibctm.Header)
suite.Require().True(ok)

clientState := path.EndpointA.GetClientState()
suite.Require().True(clientState.GetLatestHeight().EQ(tmHeader.GetHeight())) // new update, updated client state should have changed
suite.Require().True(clientState.GetLatestHeight().EQ(consensusHeights[0]))

// ensure consensus state was pruned
_, found := path.EndpointA.Chain.GetConsensusState(path.EndpointA.ClientID, pruneHeight)
suite.Require().False(found)
}, true,
},
{
"invalid ClientMessage type", func() {
clientMessage = &ibctm.Misbehaviour{}
Expand Down

0 comments on commit b697a6f

Please sign in to comment.