Skip to content

Commit

Permalink
fix!: unconfirmed pending cctx should prevent further outbound tx sig…
Browse files Browse the repository at this point in the history
…ning (#1370)

* add pending cctx check in add out tx

* cap the size of each outtx tracker to 2

* increase look back to 1000 in CctxAllPending() RPC

* zetaclient: refuse to sign outtx with nonce too big

bigger than 120+earliest pending cctx nonce

* add a FIXME to remove timeout in observeOutTx

* use const variable for better documentation

* update make generate

* fix unit test of AddToOutTxTracker

* fix return code of MsgAddOutTxTracker

---------

Co-authored-by: brewmaster012 <unknown>
Co-authored-by: brewmaster012 <>
  • Loading branch information
brewmaster012 authored Nov 7, 2023
1 parent e8161c5 commit 7f89fae
Show file tree
Hide file tree
Showing 11 changed files with 201 additions and 104 deletions.
4 changes: 4 additions & 0 deletions docs/openapi/openapi.swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50609,6 +50609,10 @@ definitions:
type: object
crosschainMsgAddToOutTxTrackerResponse:
type: object
properties:
is_removed:
type: boolean
title: if the tx was removed from the tracker due to no pending cctx
crosschainMsgCreateTSSVoterResponse:
type: object
crosschainMsgGasPriceVoterResponse:
Expand Down
1 change: 1 addition & 0 deletions docs/spec/crosschain/messages.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

AddToOutTxTracker adds a new record to the outbound transaction tracker.
only the admin policy account and the observer validators are authorized to broadcast this message without proof.
If no pending cctx is found, the tracker is removed, if there is an existed tracker with the nonce & chainID.

```proto
message MsgAddToOutTxTracker {
Expand Down
4 changes: 3 additions & 1 deletion proto/crosschain/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ message MsgAddToOutTxTracker {
int64 tx_index = 7;
}

message MsgAddToOutTxTrackerResponse {}
message MsgAddToOutTxTrackerResponse {
bool is_removed = 1; // if the tx was removed from the tracker due to no pending cctx
}

message MsgRemoveFromOutTxTracker {
string creator = 1;
Expand Down
7 changes: 7 additions & 0 deletions typescript/crosschain/tx_pb.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,13 @@ export declare class MsgAddToOutTxTracker extends Message<MsgAddToOutTxTracker>
* @generated from message zetachain.zetacore.crosschain.MsgAddToOutTxTrackerResponse
*/
export declare class MsgAddToOutTxTrackerResponse extends Message<MsgAddToOutTxTrackerResponse> {
/**
* if the tx was removed from the tracker due to no pending cctx
*
* @generated from field: bool is_removed = 1;
*/
isRemoved: boolean;

constructor(data?: PartialMessage<MsgAddToOutTxTrackerResponse>);

static readonly runtime: typeof proto3;
Expand Down
8 changes: 8 additions & 0 deletions x/crosschain/keeper/cctx_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,11 @@ func (k Keeper) GetRevertGasLimit(ctx sdk.Context, cctx types.CrossChainTx) (uin

return 0, nil
}

func IsPending(cctx types.CrossChainTx) bool {
// pending inbound is not considered a "pending" state because it has not reached consensus yet
if cctx.CctxStatus.Status == types.CctxStatus_PendingOutbound || cctx.CctxStatus.Status == types.CctxStatus_PendingRevert {
return true
}
return false
}
2 changes: 1 addition & 1 deletion x/crosschain/keeper/keeper_cross_chain_tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ func (k Keeper) CctxAllPending(c context.Context, req *types.QueryAllCctxPending
// now query the previous nonces up to 100 prior to find any pending cctx that we might have missed
// need this logic because a confirmation of higher nonce will automatically update the p.NonceLow
// therefore might mask some lower nonce cctx that is still pending.
startNonce := p.NonceLow - 100
startNonce := p.NonceLow - 1000
if startNonce < 0 {
startNonce = 0
}
Expand Down
15 changes: 14 additions & 1 deletion x/crosschain/keeper/msg_server_add_to_outtx_tracker.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (

// AddToOutTxTracker adds a new record to the outbound transaction tracker.
// only the admin policy account and the observer validators are authorized to broadcast this message without proof.
// If no pending cctx is found, the tracker is removed, if there is an existed tracker with the nonce & chainID.
func (k msgServer) AddToOutTxTracker(goCtx context.Context, msg *types.MsgAddToOutTxTracker) (*types.MsgAddToOutTxTrackerResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
chain := k.zetaObserverKeeper.GetParams(ctx).GetChainFromChainID(msg.ChainId)
Expand Down Expand Up @@ -51,6 +52,18 @@ func (k msgServer) AddToOutTxTracker(goCtx context.Context, msg *types.MsgAddToO
isProven = true
}

cctx, err := k.CctxByNonce(ctx, &types.QueryGetCctxByNonceRequest{
ChainID: msg.ChainId,
Nonce: msg.Nonce,
})
if err != nil || cctx == nil || cctx.CrossChainTx == nil {
return nil, cosmoserrors.Wrap(types.ErrCannotFindCctx, "cannot add out tx: no corresponding cctx found")
}
if !IsPending(*cctx.CrossChainTx) {
k.RemoveOutTxTracker(ctx, msg.ChainId, msg.Nonce)
return &types.MsgAddToOutTxTrackerResponse{IsRemoved: true}, nil
}

tracker, found := k.GetOutTxTracker(ctx, msg.ChainId, msg.Nonce)
hash := types.TxHashList{
TxHash: msg.TxHash,
Expand Down Expand Up @@ -84,7 +97,7 @@ func (k msgServer) AddToOutTxTracker(goCtx context.Context, msg *types.MsgAddToO
hash.Proved = true
tracker.HashList = append([]*types.TxHashList{&hash}, tracker.HashList...)
k.Logger(ctx).Info("Proof'd outbound transaction")
} else {
} else if len(tracker.HashList) < 2 {
tracker.HashList = append(tracker.HashList, &hash)
}
k.SetOutTxTracker(ctx, tracker)
Expand Down
28 changes: 21 additions & 7 deletions x/crosschain/keeper/msg_server_add_to_outtx_tracker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func TestMsgServer_AddToOutTxTracker(t *testing.T) {
txIndex, block, header, headerRLP, _, tx, err := sample.Proof()
require.NoError(t, err)
setupVerificationParams(zk, ctx, txIndex, chainID, header, headerRLP, block)
setupTss(k, ctx)
setupTssAndNonceToCctx(k, ctx, chainID, 0)
msgServer := keeper.NewMsgServerImpl(*k)
_, err = msgServer.AddToOutTxTracker(ctx, &types.MsgAddToOutTxTracker{
Creator: admin,
Expand All @@ -47,7 +47,7 @@ func TestMsgServer_AddToOutTxTracker(t *testing.T) {
txIndex, block, header, headerRLP, proof, tx, err := sample.Proof()
require.NoError(t, err)
setupVerificationParams(zk, ctx, txIndex, chainID, header, headerRLP, block)
setupTss(k, ctx)
setupTssAndNonceToCctx(k, ctx, chainID, int64(tx.Nonce()))
msgServer := keeper.NewMsgServerImpl(*k)
_, err = msgServer.AddToOutTxTracker(ctx, &types.MsgAddToOutTxTracker{
Creator: sample.AccAddress(),
Expand All @@ -69,7 +69,7 @@ func TestMsgServer_AddToOutTxTracker(t *testing.T) {
txIndex, block, header, headerRLP, proof, tx, err := sample.Proof()
require.NoError(t, err)
setupVerificationParams(zk, ctx, txIndex, chainID, header, headerRLP, block)
setupTss(k, ctx)
setupTssAndNonceToCctx(k, ctx, chainID, 1)
msgServer := keeper.NewMsgServerImpl(*k)
_, err = msgServer.AddToOutTxTracker(ctx, &types.MsgAddToOutTxTracker{
Creator: sample.AccAddress(),
Expand All @@ -91,7 +91,7 @@ func TestMsgServer_AddToOutTxTracker(t *testing.T) {
txIndex, block, header, headerRLP, proof, tx, err := sample.Proof()
require.NoError(t, err)
setupVerificationParams(zk, ctx, txIndex, chainID, header, headerRLP, block)
setupTss(k, ctx)
setupTssAndNonceToCctx(k, ctx, chainID, int64(tx.Nonce()))
msgServer := keeper.NewMsgServerImpl(*k)
_, err = msgServer.AddToOutTxTracker(ctx, &types.MsgAddToOutTxTracker{
Creator: sample.AccAddress(),
Expand All @@ -113,7 +113,7 @@ func TestMsgServer_AddToOutTxTracker(t *testing.T) {
txIndex, block, header, headerRLP, _, tx, err := sample.Proof()
require.NoError(t, err)
setupVerificationParams(zk, ctx, txIndex, chainID, header, headerRLP, block)
setupTss(k, ctx)
setupTssAndNonceToCctx(k, ctx, chainID, int64(tx.Nonce()))
msgServer := keeper.NewMsgServerImpl(*k)
_, err = msgServer.AddToOutTxTracker(ctx, &types.MsgAddToOutTxTracker{
Creator: sample.AccAddress(),
Expand All @@ -134,7 +134,7 @@ func TestMsgServer_AddToOutTxTracker(t *testing.T) {
txIndex, block, header, headerRLP, proof, tx, err := sample.Proof()
require.NoError(t, err)
setupVerificationParams(zk, ctx, txIndex, chainID, header, headerRLP, block)
setupTss(k, ctx)
setupTssAndNonceToCctx(k, ctx, chainID, int64(tx.Nonce()))
msgServer := keeper.NewMsgServerImpl(*k)
_, err = msgServer.AddToOutTxTracker(ctx, &types.MsgAddToOutTxTracker{
Creator: sample.AccAddress(),
Expand All @@ -151,8 +151,22 @@ func TestMsgServer_AddToOutTxTracker(t *testing.T) {
})
}

func setupTss(k *keeper.Keeper, ctx sdk.Context) {
func setupTssAndNonceToCctx(k *keeper.Keeper, ctx sdk.Context, chainId, nonce int64) {
k.SetTSS(ctx, types.TSS{
TssPubkey: "zetapub1addwnpepq28c57cvcs0a2htsem5zxr6qnlvq9mzhmm76z3jncsnzz32rclangr2g35p",
})
cctx := types.CrossChainTx{
Creator: "any",
Index: "0x123",
CctxStatus: &types.Status{
Status: types.CctxStatus_PendingOutbound,
},
}
k.SetCrossChainTx(ctx, cctx)
k.SetNonceToCctx(ctx, types.NonceToCctx{
ChainId: chainId,
Nonce: nonce,
CctxIndex: "0x123",
Tss: "zetapub1addwnpepq28c57cvcs0a2htsem5zxr6qnlvq9mzhmm76z3jncsnzz32rclangr2g35p",
})
}
Loading

0 comments on commit 7f89fae

Please sign in to comment.