From 8cb257c2e89a33ab83ec4087672379bbbdc248b2 Mon Sep 17 00:00:00 2001 From: Toshihito Kikuchi Date: Tue, 18 Apr 2023 15:42:59 -0700 Subject: [PATCH] Pass a correct session end height to `NewSession` With session rollover (#1536), we accept relays for older sessions. For exaple, a node at block 101 accepts a relay for the session height 97. There is a bug in the relay validation function `relay.Validate`. In the example above, the function sees the following values: ``` ctx.BlockHeight() = 101 sessionBlockHeight = r.Proof.SessionBlockHeight = 97 sessionCtx.BlockHeight() = 97 ``` and if the corresponding session is not cached, it passes `sessionCtx` and `ctx` to `NewSession`. This may return a wrong session because the second argument is supposed to be the end of the session, but in this case it's not. The proposed fix is if `ctx` is beyond the relay session, we get a new context of the session end and pass it to `NewSession`. --- x/pocketcore/types/service.go | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/x/pocketcore/types/service.go b/x/pocketcore/types/service.go index c37b6232e..c28d09521 100644 --- a/x/pocketcore/types/service.go +++ b/x/pocketcore/types/service.go @@ -92,8 +92,23 @@ func (r *Relay) Validate(ctx sdk.Ctx, posKeeper PosKeeper, appsKeeper AppsKeeper if err != nil { return sdk.ZeroInt(), sdk.ErrInternal(err.Error()) } + + // With session rollover, the height of `ctx` may already be in the next + // session of the relay's session. In such a case, we need to pass the + // correct context of the session end instead of `ctx`. + sessionEndHeight := + sessionBlockHeight + posKeeper.BlocksPerSession(sessionCtx) - 1 + var sesssionEndCtx sdk.Ctx + if ctx.BlockHeight() > sessionEndHeight { + if sesssionEndCtx, err = ctx.PrevCtx(sessionEndHeight); err != nil { + return sdk.ZeroInt(), sdk.ErrInternal(er.Error()) + } + } else { + sesssionEndCtx = ctx + } + var er sdk.Error - session, er = NewSession(sessionCtx, ctx, posKeeper, header, hex.EncodeToString(bh), int(sessionNodeCount)) + session, er = NewSession(sessionCtx, sesssionEndCtx, posKeeper, header, hex.EncodeToString(bh), int(sessionNodeCount)) if er != nil { return sdk.ZeroInt(), er }