Skip to content

Commit

Permalink
test: add tx priority checks to e2e tests (#2184)
Browse files Browse the repository at this point in the history
  • Loading branch information
skosito authored May 16, 2024
1 parent 2e7dac2 commit adcb33c
Show file tree
Hide file tree
Showing 9 changed files with 255 additions and 104 deletions.
1 change: 1 addition & 0 deletions app/ante/ante.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ func IsSystemTx(tx sdk.Tx, isAuthorizedSigner func(string) bool) bool {
*crosschaintypes.MsgVoteOnObservedInboundTx,
*crosschaintypes.MsgVoteOnObservedOutboundTx,
*crosschaintypes.MsgAddToOutTxTracker,
*crosschaintypes.MsgAddToInTxTracker,
*observertypes.MsgVoteBlockHeader,
*observertypes.MsgVoteTSS,
*observertypes.MsgAddBlameVote:
Expand Down
19 changes: 19 additions & 0 deletions app/ante/ante_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ func TestIsSystemTx(t *testing.T) {
// *cctxtypes.MsgVoteOnObservedInboundTx,
// *cctxtypes.MsgVoteOnObservedOutboundTx,
// *cctxtypes.MsgAddToOutTxTracker,
// *cctxtypes.MsgAddToInTxTracker,
// *observertypes.MsgVoteBlockHeader,
// *observertypes.MsgVoteTSS,
// *observertypes.MsgAddBlameVote:
Expand Down Expand Up @@ -168,6 +169,24 @@ func TestIsSystemTx(t *testing.T) {

true,
},
{
"MsgAddToInTxTracker",
buildTxFromMsg(&crosschaintypes.MsgAddToInTxTracker{
Creator: sample.AccAddress(),
}),
isAuthorized,

true,
},
{
"MsgExec{MsgAddToInTxTracker}",
buildAuthzTxFromMsg(&crosschaintypes.MsgAddToInTxTracker{
Creator: sample.AccAddress(),
}),
isAuthorized,

true,
},
{
"MsgVoteTSS",
buildTxFromMsg(&observertypes.MsgVoteTSS{
Expand Down
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
### Tests

* [2047](https://github.com/zeta-chain/node/pull/2047) - fix liquidity cap advanced test
* [2184](https://github.com/zeta-chain/node/pull/2184) - add tx priority checks to e2e tests

### Fixes

Expand Down
37 changes: 37 additions & 0 deletions cmd/zetae2e/local/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package local

import (
"path/filepath"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/spf13/cobra"
"github.com/zeta-chain/zetacore/app"
"github.com/zeta-chain/zetacore/e2e/config"
)

// GetConfig returns config from file from the command line flag
func GetConfig(cmd *cobra.Command) (config.Config, error) {
configFile, err := cmd.Flags().GetString(FlagConfigFile)
if err != nil {
return config.Config{}, err
}

// use default config if no config file is specified
if configFile == "" {
return config.DefaultConfig(), nil
}

configFile, err = filepath.Abs(configFile)
if err != nil {
return config.Config{}, err
}

return config.ReadConfig(configFile)
}

// setCosmosConfig set account prefix to zeta
func setCosmosConfig() {
cosmosConf := sdk.GetConfig()
cosmosConf.SetBech32PrefixForAccount(app.Bech32PrefixAccAddr, app.Bech32PrefixAccPub)
cosmosConf.Seal()
}
39 changes: 39 additions & 0 deletions cmd/zetae2e/local/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/zeta-chain/zetacore/e2e/runner"
"github.com/zeta-chain/zetacore/e2e/utils"
"github.com/zeta-chain/zetacore/pkg/chains"
crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types"
"golang.org/x/sync/errgroup"
)

Expand Down Expand Up @@ -331,8 +332,23 @@ func localE2ETest(cmd *cobra.Command, _ []string) {
eg.Go(miscTestRoutine(conf, deployerRunner, verbose, e2etests.TestMyTestName))
}

// while tests are executed, monitor blocks in parallel to check if system txs are on top and they have biggest priority
txPriorityErrCh := make(chan error, 1)
ctx, monitorPriorityCancel := context.WithCancel(context.Background())
go monitorTxPriorityInBlocks(ctx, conf, txPriorityErrCh)

if err := eg.Wait(); err != nil {
deployerRunner.CtxCancel()
monitorPriorityCancel()
logger.Print("❌ %v", err)
logger.Print("❌ e2e tests failed after %s", time.Since(testStartTime).String())
os.Exit(1)
}

// if all tests pass, cancel txs priority monitoring and check if tx priority is not correct in some blocks
logger.Print("⏳ e2e tests passed, checking tx priority")
monitorPriorityCancel()
if err := <-txPriorityErrCh; err != nil {
logger.Print("❌ %v", err)
logger.Print("❌ e2e tests failed after %s", time.Since(testStartTime).String())
os.Exit(1)
Expand All @@ -353,3 +369,26 @@ func localE2ETest(cmd *cobra.Command, _ []string) {

os.Exit(0)
}

// waitKeygenHeight waits for keygen height
func waitKeygenHeight(
ctx context.Context,
cctxClient crosschaintypes.QueryClient,
logger *runner.Logger,
) {
// wait for keygen to be completed
keygenHeight := int64(60)
logger.Print("⏳ wait height %v for keygen to be completed", keygenHeight)
for {
time.Sleep(2 * time.Second)
response, err := cctxClient.LastZetaHeight(ctx, &crosschaintypes.QueryLastZetaHeightRequest{})
if err != nil {
logger.Error("cctxClient.LastZetaHeight error: %s", err)
continue
}
if response.Height >= keygenHeight {
break
}
logger.Info("Last ZetaHeight: %d", response.Height)
}
}
113 changes: 113 additions & 0 deletions cmd/zetae2e/local/monitor_priority_txs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package local

import (
"context"
"errors"
"strings"
"time"

"github.com/cometbft/cometbft/abci/types"
rpchttp "github.com/cometbft/cometbft/rpc/client/http"
coretypes "github.com/cometbft/cometbft/rpc/core/types"
"github.com/zeta-chain/zetacore/e2e/config"
)

// monitorTxPriorityInBlocks checks for transaction priorities in blocks and reports errors
func monitorTxPriorityInBlocks(ctx context.Context, conf config.Config, errCh chan error) {
rpcClient, err := rpchttp.New(conf.RPCs.ZetaCoreRPC, "/websocket")
if err != nil {
errCh <- err
return
}

ticker := time.NewTicker(2 * time.Second)
defer ticker.Stop()

for {
select {
case <-ctx.Done():
errCh <- nil
case <-ticker.C:
processBlockTxs(ctx, rpcClient, errCh)
}
}
}

// processBlockTxs fetches the latest block and evaluates transaction priorities
func processBlockTxs(ctx context.Context, rpc *rpchttp.HTTP, errCh chan error) {
block, err := rpc.Block(ctx, nil)
if err != nil {
errCh <- err
return
}

nonSystemTxFound := false
for _, tx := range block.Block.Txs {
txResult, err := rpc.Tx(ctx, tx.Hash(), false)
if err != nil {
continue
}
processTx(txResult, &nonSystemTxFound, errCh)
}
}

// processTx handles the processing of each transaction and its events
func processTx(txResult *coretypes.ResultTx, nonSystemTxFound *bool, errCh chan error) {
for _, event := range txResult.TxResult.Events {
for _, attr := range event.Attributes {
// skip attrs with empty value
if attr.Value == "\"\"" {
continue
}

// skip internal events with msg_type_url key, because they are not representing sdk msgs
if strings.Contains(attr.Value, ".internal.") {
continue
}
switch attr.Key {
// if attr key is msg_type_url, check if it's one of system txs, otherwise mark it as non system tx
case "msg_type_url":
if isMsgTypeURLSystemTx(attr) {
// a non system tx has been found in the block before a system tx
if *nonSystemTxFound {
errCh <- errors.New("wrong tx priority, system tx not on top")
return
}
} else {
*nonSystemTxFound = true
}
// if attr key is action, check if tx is ethermint non system tx and if it is, mark it
case "action":
if isActionNonSystemTx(attr) {
*nonSystemTxFound = true
}
}
}
}
}

func isMsgTypeURLSystemTx(attr types.EventAttribute) bool {
// type urls in attr.Value are in double quotes, so it needs to be formatted like this
systemTxsMsgTypeUrls := []string{
"\"/zetachain.zetacore.crosschain.MsgVoteOnObservedOutboundTx\"",
"\"/zetachain.zetacore.crosschain.MsgVoteOnObservedInboundTx\"",
"\"/zetachain.zetacore.crosschain.MsgVoteGasPrice\"",
"\"/zetachain.zetacore.crosschain.MsgAddToOutTxTracker\"",
"\"/zetachain.zetacore.crosschain.MsgAddToInTxTracker\"",
"\"/zetachain.zetacore.observer.MsgVoteBlockHeader\"",
"\"/zetachain.zetacore.observer.MsgVoteTSS\"",
"\"/zetachain.zetacore.observer.MsgAddBlameVote\"",
}

for _, url := range systemTxsMsgTypeUrls {
if url == attr.Value {
return true
}
}

return false
}

func isActionNonSystemTx(attr types.EventAttribute) bool {
return attr.Value == "/ethermint.evm.v1.MsgEthereumTx"
}
4 changes: 2 additions & 2 deletions cmd/zetae2e/local/performance.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func ethereumDepositPerformanceRoutine(
}

if err := r.RunE2ETests(tests); err != nil {
return fmt.Errorf("misc tests failed: %v", err)
return fmt.Errorf("ethereum deposit performance test failed: %v", err)
}

r.Logger.Print("🍾 Ethereum deposit performance test completed in %s", time.Since(startTime).String())
Expand Down Expand Up @@ -117,7 +117,7 @@ func ethereumWithdrawPerformanceRoutine(
}

if err := r.RunE2ETests(tests); err != nil {
return fmt.Errorf("misc tests failed: %v", err)
return fmt.Errorf("ethereum withdraw performance test failed: %v", err)
}

r.Logger.Print("🍾 Ethereum withdraw performance test completed in %s", time.Since(startTime).String())
Expand Down
43 changes: 43 additions & 0 deletions cmd/zetae2e/local/test_runner.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package local

import (
ethcommon "github.com/ethereum/go-ethereum/common"
zetae2econfig "github.com/zeta-chain/zetacore/cmd/zetae2e/config"
"github.com/zeta-chain/zetacore/e2e/config"
"github.com/zeta-chain/zetacore/e2e/runner"
"github.com/zeta-chain/zetacore/e2e/utils"
)

// initTestRunner initializes a runner form tests
// it creates a runner with an account and copy contracts from deployer runner
func initTestRunner(
name string,
conf config.Config,
deployerRunner *runner.E2ERunner,
userAddress ethcommon.Address,
userPrivKey string,
logger *runner.Logger,
) (*runner.E2ERunner, error) {
// initialize runner for test
testRunner, err := zetae2econfig.RunnerFromConfig(
deployerRunner.Ctx,
name,
deployerRunner.CtxCancel,
conf,
userAddress,
userPrivKey,
utils.FungibleAdminName,
FungibleAdminMnemonic,
logger,
)
if err != nil {
return nil, err
}

// copy contracts from deployer runner
if err := testRunner.CopyAddressesFrom(deployerRunner); err != nil {
return nil, err
}

return testRunner, nil
}
Loading

0 comments on commit adcb33c

Please sign in to comment.