diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index 951f7a2888..fa01e0d4e4 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -133,4 +133,4 @@ jobs: - name: Clean Up Workspace if: always() shell: bash - run: rm -rf * \ No newline at end of file + run: sudo rm -rf * || echo "failed to cleanup workspace please investigate" \ No newline at end of file diff --git a/.github/workflows/rc-release.yml b/.github/workflows/rc-release.yml index fcd8faff9c..2e4fbfd194 100644 --- a/.github/workflows/rc-release.yml +++ b/.github/workflows/rc-release.yml @@ -85,4 +85,4 @@ jobs: - name: Clean Up Workspace if: always() shell: bash - run: rm -rf * \ No newline at end of file + run: sudo rm -rf * || echo "failed to clean workspace please investigate" \ No newline at end of file diff --git a/app/ante/ante.go b/app/ante/ante.go index aaedf00dd1..e1077339b4 100644 --- a/app/ante/ante.go +++ b/app/ante/ante.go @@ -19,9 +19,6 @@ import ( "fmt" "runtime/debug" - cctxtypes "github.com/zeta-chain/zetacore/x/crosschain/types" - observertypes "github.com/zeta-chain/zetacore/x/observer/types" - errorsmod "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" errortypes "github.com/cosmos/cosmos-sdk/types/errors" @@ -29,6 +26,8 @@ import ( "github.com/cosmos/cosmos-sdk/x/authz" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" tmlog "github.com/tendermint/tendermint/libs/log" + cctxtypes "github.com/zeta-chain/zetacore/x/crosschain/types" + observertypes "github.com/zeta-chain/zetacore/x/observer/types" ) func ValidateHandlerOptions(options HandlerOptions) error { @@ -97,46 +96,24 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) { // handle as totally normal Cosmos SDK tx switch tx.(type) { case sdk.Tx: + // default: handle as normal Cosmos SDK tx anteHandler = newCosmosAnteHandler(options) - if len(tx.GetMsgs()) != 1 { - break - } - msg := tx.GetMsgs()[0] // now we must have len(tx.GetMsgs()) == 1 - var innerMsg sdk.Msg - innerMsg = msg - if mm, ok := msg.(*authz.MsgExec); ok { // authz tx; look inside it - msgs, err := mm.GetMessages() - if err == nil && len(msgs) == 1 { - innerMsg = msgs[0] - } + // if tx is a system tx, and singer is authorized, use system tx handler + + isAuthorized := func(creator string) bool { + return options.ObserverKeeper.IsAuthorized(ctx, creator) + } + if IsSystemTx(tx, isAuthorized) { + anteHandler = newCosmosAnteHandlerForSystemTx(options) } - isAuthorize := options.ObserverKeeper.IsAuthorized - if mm, ok := innerMsg.(*cctxtypes.MsgGasPriceVoter); ok && isAuthorize(ctx, mm.Creator) { - anteHandler = newCosmosAnteHandlerNoGasFee(options) - break - } else if mm, ok := innerMsg.(*cctxtypes.MsgVoteOnObservedInboundTx); ok && isAuthorize(ctx, mm.Creator) { - anteHandler = newCosmosAnteHandlerNoGasFee(options) - break - } else if mm, ok := innerMsg.(*cctxtypes.MsgVoteOnObservedOutboundTx); ok && isAuthorize(ctx, mm.Creator) { - anteHandler = newCosmosAnteHandlerNoGasFee(options) - break - } else if mm, ok := innerMsg.(*cctxtypes.MsgAddToOutTxTracker); ok && isAuthorize(ctx, mm.Creator) { - anteHandler = newCosmosAnteHandlerNoGasFee(options) - break - } else if mm, ok := innerMsg.(*cctxtypes.MsgCreateTSSVoter); ok && isAuthorize(ctx, mm.Creator) { - anteHandler = newCosmosAnteHandlerNoGasFee(options) - break - } else if mm, ok := innerMsg.(*observertypes.MsgAddBlockHeader); ok && isAuthorize(ctx, mm.Creator) { - anteHandler = newCosmosAnteHandlerNoGasFee(options) - break - } else if mm, ok := innerMsg.(*observertypes.MsgAddBlameVote); ok && isAuthorize(ctx, mm.Creator) { - anteHandler = newCosmosAnteHandlerNoGasFee(options) - break - } else if _, ok := innerMsg.(*stakingtypes.MsgCreateValidator); ok && ctx.BlockHeight() == 0 { - anteHandler = newCosmosAnteHandlerNoGasFee(options) - break + // if tx is MsgCreatorValidator, use the newCosmosAnteHandlerForSystemTx handler to + // exempt gas fee requirement in genesis because it's not possible to pay gas fee in genesis + if len(tx.GetMsgs()) == 1 { + if _, ok := tx.GetMsgs()[0].(*stakingtypes.MsgCreateValidator); ok && ctx.BlockHeight() == 0 { + anteHandler = newCosmosAnteHandlerForSystemTx(options) + } } default: @@ -168,3 +145,41 @@ func Recover(logger tmlog.Logger, err *error) { } } } + +// IsSystemTx determines whether tx is a system tx that's signed by an authorized signer +// system tx are special types of txs (see in the switch below), or such txs wrapped inside a MsgExec +// the parameter isAuthorizedSigner is a caller specified function that determines whether the signer of +// the tx is authorized. +func IsSystemTx(tx sdk.Tx, isAuthorizedSigner func(string) bool) bool { + // the following determines whether the tx is a system tx which will uses different handler + // System txs are always single Msg txs, optionally wrapped by one level of MsgExec + if len(tx.GetMsgs()) != 1 { // this is not a system tx + return false + } + msg := tx.GetMsgs()[0] + + // if wrapped inside a MsgExec, unwrap it and reveal the innerMsg. + var innerMsg sdk.Msg + innerMsg = msg + if mm, ok := msg.(*authz.MsgExec); ok { // authz tx; look inside it + msgs, err := mm.GetMessages() + if err == nil && len(msgs) == 1 { + innerMsg = msgs[0] + } + } + switch innerMsg.(type) { + case *cctxtypes.MsgGasPriceVoter, + *cctxtypes.MsgVoteOnObservedInboundTx, + *cctxtypes.MsgVoteOnObservedOutboundTx, + *cctxtypes.MsgAddToOutTxTracker, + *cctxtypes.MsgCreateTSSVoter, + *observertypes.MsgAddBlockHeader, + *observertypes.MsgAddBlameVote: + signers := innerMsg.GetSigners() + if len(signers) == 1 { + return isAuthorizedSigner(signers[0].String()) + } + } + + return false +} diff --git a/app/ante/ante_test.go b/app/ante/ante_test.go index 53a7d95c85..146e50c6ae 100644 --- a/app/ante/ante_test.go +++ b/app/ante/ante_test.go @@ -1,6 +1,19 @@ package ante_test -import sdk "github.com/cosmos/cosmos-sdk/types" +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/authz" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/stretchr/testify/require" + "github.com/zeta-chain/zetacore/app" + "github.com/zeta-chain/zetacore/app/ante" + "github.com/zeta-chain/zetacore/testutil/sample" + crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" + observertypes "github.com/zeta-chain/zetacore/x/observer/types" +) var _ sdk.AnteHandler = (&MockAnteHandler{}).AnteHandle @@ -16,3 +29,204 @@ func (mah *MockAnteHandler) AnteHandle(ctx sdk.Context, _ sdk.Tx, _ bool) (sdk.C mah.CalledCtx = ctx return ctx, nil } + +func TestIsSystemTx(t *testing.T) { + // system tx types: + // *cctxtypes.MsgGasPriceVoter, + // *cctxtypes.MsgVoteOnObservedInboundTx, + // *cctxtypes.MsgVoteOnObservedOutboundTx, + // *cctxtypes.MsgAddToOutTxTracker, + // *cctxtypes.MsgCreateTSSVoter, + // *observertypes.MsgAddBlockHeader, + // *observertypes.MsgAddBlameVote: + buildTxFromMsg := func(msg sdk.Msg) sdk.Tx { + txBuilder := app.MakeEncodingConfig().TxConfig.NewTxBuilder() + txBuilder.SetMsgs(msg) + return txBuilder.GetTx() + } + buildAuthzTxFromMsg := func(msg sdk.Msg) sdk.Tx { + txBuilder := app.MakeEncodingConfig().TxConfig.NewTxBuilder() + msgExec := authz.NewMsgExec(sample.Bech32AccAddress(), []sdk.Msg{msg}) + txBuilder.SetMsgs(&msgExec) + return txBuilder.GetTx() + } + isAuthorized := func(_ string) bool { + return true + } + isAuthorizedFalse := func(_ string) bool { + return false + } + + tests := []struct { + name string + tx sdk.Tx + isAuthorized func(string) bool + wantIs bool + }{ + { + "MsgCreateTSSVoter", + buildTxFromMsg(&crosschaintypes.MsgCreateTSSVoter{ + Creator: sample.AccAddress(), + TssPubkey: "pubkey1234", + }), + isAuthorizedFalse, + false, + }, + { + "MsgCreateTSSVoter", + buildTxFromMsg(&crosschaintypes.MsgCreateTSSVoter{ + Creator: sample.AccAddress(), + TssPubkey: "pubkey1234", + }), + isAuthorized, + true, + }, + { + "MsgExec{MsgCreateTSSVoter}", + buildAuthzTxFromMsg(&crosschaintypes.MsgCreateTSSVoter{ + Creator: sample.AccAddress(), + TssPubkey: "pubkey1234", + }), + isAuthorized, + + true, + }, + { + "MsgSend", + buildTxFromMsg(&banktypes.MsgSend{}), + isAuthorized, + + false, + }, + { + "MsgExec{MsgSend}", + buildAuthzTxFromMsg(&banktypes.MsgSend{}), + isAuthorized, + + false, + }, + { + "MsgCreateValidator", + buildTxFromMsg(&stakingtypes.MsgCreateValidator{}), + isAuthorized, + + false, + }, + + { + "MsgVoteOnObservedInboundTx", + buildTxFromMsg(&crosschaintypes.MsgVoteOnObservedInboundTx{ + Creator: sample.AccAddress(), + }), + isAuthorized, + + true, + }, + { + "MsgExec{MsgVoteOnObservedInboundTx}", + buildAuthzTxFromMsg(&crosschaintypes.MsgVoteOnObservedInboundTx{ + Creator: sample.AccAddress(), + }), + isAuthorized, + + true, + }, + + { + "MsgVoteOnObservedOutboundTx", + buildTxFromMsg(&crosschaintypes.MsgVoteOnObservedOutboundTx{ + Creator: sample.AccAddress(), + }), + isAuthorized, + + true, + }, + { + "MsgExec{MsgVoteOnObservedOutboundTx}", + buildAuthzTxFromMsg(&crosschaintypes.MsgVoteOnObservedOutboundTx{ + Creator: sample.AccAddress(), + }), + isAuthorized, + + true, + }, + { + "MsgAddToOutTxTracker", + buildTxFromMsg(&crosschaintypes.MsgAddToOutTxTracker{ + Creator: sample.AccAddress(), + }), + isAuthorized, + + true, + }, + { + "MsgExec{MsgAddToOutTxTracker}", + buildAuthzTxFromMsg(&crosschaintypes.MsgAddToOutTxTracker{ + Creator: sample.AccAddress(), + }), + isAuthorized, + + true, + }, + { + "MsgCreateTSSVoter", + buildTxFromMsg(&crosschaintypes.MsgCreateTSSVoter{ + Creator: sample.AccAddress(), + }), + isAuthorized, + + true, + }, + { + "MsgExec{MsgCreateTSSVoter}", + buildAuthzTxFromMsg(&crosschaintypes.MsgCreateTSSVoter{ + Creator: sample.AccAddress(), + }), + isAuthorized, + + true, + }, + { + "MsgAddBlockHeader", + buildTxFromMsg(&observertypes.MsgAddBlockHeader{ + Creator: sample.AccAddress(), + }), + isAuthorized, + + true, + }, + { + "MsgExec{MsgAddBlockHeader}", + buildAuthzTxFromMsg(&observertypes.MsgAddBlockHeader{ + Creator: sample.AccAddress(), + }), + isAuthorized, + + true, + }, + { + "MsgAddBlameVote", + buildTxFromMsg(&observertypes.MsgAddBlameVote{ + Creator: sample.AccAddress(), + }), + isAuthorized, + + true, + }, + { + "MsgExec{MsgAddBlameVote}", + buildAuthzTxFromMsg(&observertypes.MsgAddBlameVote{ + Creator: sample.AccAddress(), + }), + isAuthorized, + + true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + is := ante.IsSystemTx(tt.tx, tt.isAuthorized) + require.Equal(t, tt.wantIs, is) + }) + } +} diff --git a/app/ante/fees.go b/app/ante/fees.go index 468d4a72ee..912ed8e0e2 100644 --- a/app/ante/fees.go +++ b/app/ante/fees.go @@ -29,6 +29,10 @@ import ( evmtypes "github.com/evmos/ethermint/x/evm/types" ) +var ( + GasPriceReductionRate = "0.01" // 1% of regular tx gas price for system txs +) + // MinGasPriceDecorator will check if the transaction's fee is at least as large // as the MinGasPrices param. If fee is too low, decorator returns error and tx // is rejected. This applies for both CheckTx and DeliverTx @@ -92,14 +96,15 @@ func (mpd MinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate return next(ctx, tx, simulate) } - // Short-circuit genesis txs gentx + // Short-circuit genesis txs gentx at block 0 (there is no way to pay fee in genesis file) if len(tx.GetMsgs()) == 1 { - if _, ok := tx.GetMsgs()[0].(*stakingtypes.MsgCreateValidator); ok { + if _, ok := tx.GetMsgs()[0].(*stakingtypes.MsgCreateValidator); ok && ctx.BlockHeight() == 0 { return next(ctx, tx, simulate) } } - minGasPrice = minGasPrice.Mul(sdk.NewDecWithPrec(1, 2)) // + reductionRate := sdk.MustNewDecFromStr(GasPriceReductionRate) + minGasPrice = minGasPrice.Mul(reductionRate) // discounts min gas price for system tx evmParams := mpd.evmKeeper.GetParams(ctx) evmDenom := evmParams.GetEvmDenom() diff --git a/app/ante/handler_options.go b/app/ante/handler_options.go index a9e0d65e74..e46f7b728e 100644 --- a/app/ante/handler_options.go +++ b/app/ante/handler_options.go @@ -115,7 +115,7 @@ func newCosmosAnteHandler(options HandlerOptions) sdk.AnteHandler { } // this applies to special cosmos tx that calls EVM, in which case the EVM overrides the gas limit -func newCosmosAnteHandlerNoGasFee(options HandlerOptions) sdk.AnteHandler { +func newCosmosAnteHandlerForSystemTx(options HandlerOptions) sdk.AnteHandler { return sdk.ChainAnteDecorators( ethante.RejectMessagesDecorator{}, // reject MsgEthereumTxs NewAuthzLimiterDecorator(options.DisabledAuthzMsgs...), diff --git a/changelog.md b/changelog.md index e671a8b481..5f1d3abbce 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,10 @@ ## Unreleased +### Tests + +* [1577](https://github.com/zeta-chain/node/pull/1577) - add chain header tests in E2E tests and fix admin tests + ### Features ### Fixes @@ -10,6 +14,14 @@ * [1588](https://github.com/zeta-chain/node/pull/1588) - fix chain params comparison logic * [1650](https://github.com/zeta-chain/node/pull/1605) - exempt (discounted) *system txs* from min gas price check and gas fee deduction +### CI + +* [1580](https://github.com/zeta-chain/node/pull/1580) - Fix release pipelines cleanup step. + +### Chores + +* [1585](https://github.com/zeta-chain/node/pull/1585) - Updated release instructions + ## Version: v12.0.0 ### Breaking Changes @@ -69,6 +81,7 @@ Getting the correct TSS address for Bitcoin now requires proviidng the Bitcoin c * [1546](https://github.com/zeta-chain/node/pull/1546) - fix reset of pending nonces on genesis import * [1555](https://github.com/zeta-chain/node/pull/1555) - Reduce websocket message limit to 10MB * [1567](https://github.com/zeta-chain/node/pull/1567) - add bitcoin chain id to fetch the tss address rpc endpoint +* [1589](https://github.com/zeta-chain/node/pull/1589) - add bitcoin chain id to `get tss address` and `get tss address historical` cli query ### Refactoring diff --git a/cmd/zetae2e/local/admin.go b/cmd/zetae2e/local/admin.go index 01e5d3ae8f..34900fbaf4 100644 --- a/cmd/zetae2e/local/admin.go +++ b/cmd/zetae2e/local/admin.go @@ -66,7 +66,7 @@ func adminTestRoutine( smoketests.TestUpdateBytecodeName, smoketests.TestDepositEtherLiquidityCapName, ); err != nil { - return fmt.Errorf("admim tests failed: %v", err) + return fmt.Errorf("admin tests failed: %v", err) } adminRunner.Logger.Print("🍾 admin tests completed in %s", time.Since(startTime).String()) diff --git a/cmd/zetae2e/local/bitcoin.go b/cmd/zetae2e/local/bitcoin.go index a27d619138..eaf700465e 100644 --- a/cmd/zetae2e/local/bitcoin.go +++ b/cmd/zetae2e/local/bitcoin.go @@ -59,7 +59,7 @@ func bitcoinTestRoutine( bitcoinRunner.WaitForMinedCCTX(txERC20Deposit) bitcoinRunner.SetupBitcoinAccount(initBitcoinNetwork) - bitcoinRunner.DepositBTC(false) + bitcoinRunner.DepositBTC(true) // run bitcoin test // Note: due to the extensive block generation in Bitcoin localnet, block header test is run first diff --git a/cmd/zetae2e/local/ethereum.go b/cmd/zetae2e/local/ethereum.go index 74a57a6470..90d6a35dfb 100644 --- a/cmd/zetae2e/local/ethereum.go +++ b/cmd/zetae2e/local/ethereum.go @@ -47,7 +47,7 @@ func ethereumTestRoutine( startTime := time.Now() // depositing the necessary tokens on ZetaChain - txEtherDeposit := ethereumRunner.DepositEther(false) + txEtherDeposit := ethereumRunner.DepositEther(true) ethereumRunner.WaitForMinedCCTX(txEtherDeposit) // run ethereum test diff --git a/cmd/zetae2e/local/local.go b/cmd/zetae2e/local/local.go index f1a723f26e..b31c6869d4 100644 --- a/cmd/zetae2e/local/local.go +++ b/cmd/zetae2e/local/local.go @@ -135,7 +135,11 @@ func localE2ETest(cmd *cobra.Command, _ []string) { } testStartTime := time.Now() - logger.Print("starting tests") + logger.Print("starting E2E tests") + + if testAdmin { + logger.Print("⚠️ admin tests enabled") + } // start timer go func() { diff --git a/contrib/localnet/orchestrator/smoketest/smoketests/test_pause_zrc20.go b/contrib/localnet/orchestrator/smoketest/smoketests/test_pause_zrc20.go index 5b6a9700b1..f3579990f2 100644 --- a/contrib/localnet/orchestrator/smoketest/smoketests/test_pause_zrc20.go +++ b/contrib/localnet/orchestrator/smoketest/smoketests/test_pause_zrc20.go @@ -28,7 +28,7 @@ func TestPauseZRC20(sm *runner.SmokeTestRunner) { if receipt.Status == 0 { panic("Vault approval should succeed") } - tx, err = sm.BTCZRC20.Approve(sm.ZevmAuth, vaultAddr, big.NewInt(1e18)) + tx, err = sm.USDTZRC20.Approve(sm.ZevmAuth, vaultAddr, big.NewInt(1e18)) if err != nil { panic(err) } @@ -93,23 +93,23 @@ func TestPauseZRC20(sm *runner.SmokeTestRunner) { } sm.Logger.Info("Operations all failed") - // Check we can still interact with BTC ZRC20 + // Check we can still interact with USDT ZRC20 sm.Logger.Info("Check other ZRC20 can still be operated") - tx, err = sm.BTCZRC20.Transfer(sm.ZevmAuth, sample.EthAddress(), big.NewInt(1e3)) + tx, err = sm.USDTZRC20.Transfer(sm.ZevmAuth, sample.EthAddress(), big.NewInt(1e3)) if err != nil { panic(err) } receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) if receipt.Status == 0 { - panic("BTC transfer should succeed") + panic("USDT transfer should succeed") } - tx, err = vaultContract.Deposit(sm.ZevmAuth, sm.BTCZRC20Addr, big.NewInt(1e3)) + tx, err = vaultContract.Deposit(sm.ZevmAuth, sm.USDTZRC20Addr, big.NewInt(1e3)) if err != nil { panic(err) } receipt = utils.MustWaitForTxReceipt(sm.Ctx, sm.ZevmClient, tx, sm.Logger, sm.ReceiptTimeout) if receipt.Status == 0 { - panic("BTC vault deposit should succeed") + panic("USDT vault deposit should succeed") } // Check deposit revert when paused diff --git a/docs/cli/zetacored/zetacored_query_observer_get-historical-tss-address.md b/docs/cli/zetacored/zetacored_query_observer_get-historical-tss-address.md index 83de26b9dd..d56798a084 100644 --- a/docs/cli/zetacored/zetacored_query_observer_get-historical-tss-address.md +++ b/docs/cli/zetacored/zetacored_query_observer_get-historical-tss-address.md @@ -3,7 +3,7 @@ Query tss address by finalized zeta height (for historical tss addresses) ``` -zetacored query observer get-historical-tss-address [finalizedZetaHeight] [flags] +zetacored query observer get-historical-tss-address [finalizedZetaHeight] [bitcoinChainId] [flags] ``` ### Options diff --git a/docs/cli/zetacored/zetacored_query_observer_get-tss-address.md b/docs/cli/zetacored/zetacored_query_observer_get-tss-address.md index cb763f8510..5c5e68bd14 100644 --- a/docs/cli/zetacored/zetacored_query_observer_get-tss-address.md +++ b/docs/cli/zetacored/zetacored_query_observer_get-tss-address.md @@ -3,7 +3,7 @@ Query current tss address ``` -zetacored query observer get-tss-address [flags] +zetacored query observer get-tss-address [bitcoinChainId]] [flags] ``` ### Options diff --git a/readme.md b/readme.md index b9db6be3c2..a3a931f7fa 100644 --- a/readme.md +++ b/readme.md @@ -81,27 +81,27 @@ to [run the smoke test](./contrib/localnet/README.md). [Discord](https://discord.com/invite/zetachain) | [Telegram](https://t.me/zetachainofficial) | [Website](https://zetachain.com) -## Creating a Release for Mainnet -Creating a release for mainnet is a straightforward process. Here are the steps to follow: -### Steps - - Step 1. Open a Pull Request (PR): Begin by opening a PR from the release candidate branch (e.g., vx.x.x-rc) to the main branch. - - Step 2. Testing and Validation: Allow the automated tests, including smoke tests, linting, and upgrade path testing, to run. Ensure that these tests pass successfully. - - Step 3. Approval Process: Obtain the necessary approvals from relevant stakeholders or team members. - - Step 4. Merging PR: Once all requirements have been met and the PR has received the required approvals, merge the PR. The automation will then be triggered to proceed with the release. - -By following these steps, you can efficiently create a release for Mainnet, ensuring that the code has been thoroughly tested and validated before deployment. - -## Creating a Release for Testnet -Creating a release for testnet is a straightforward process. Here are the steps to follow: +## Creating a Release Candidate +Creating a release candidate for testing is a straightforward process. Here are the steps to follow: ### Steps - Step 1. Create the release candidate tag with the following format (e.g., vx.x.x-rc) ex. v11.0.0-rc. - Step 2. Once a RC branch is created the automation will kickoff to build and upload the release and its binaries. -By following these steps, you can efficiently create a release candidate for testnet for QA and validation. In the future we will make this automatically deploy to testnet when a -rc branch is created. -Currently, raising the proposal to deploy to testnet is a manual process via GitHub Action pipeline located in the infrastructure repo. +By following these steps, you can efficiently create a release candidate for QA and validation. In the future we will make this automatically deploy to a testnet when a -rc branch is created. +Currently, raising the proposal to deploy to testnet is a manual process via GovOps repo. + +## Creating a Release +After the Release Candidate has been fully tested, creating a final release for use on public networks is a straightforward process. Here are the steps to follow: + +### Steps + - Step 1. Open a Pull Request (PR): Begin by opening a PR from the release candidate branch (e.g., vx.x.x-rc) to the main branch. + - Step 2. Testing and Validation: Allow the automated tests, including E2E tests, linting, and upgrade path testing, to run. Ensure that these tests pass successfully. + - Step 3. Approval Process: Obtain the necessary approvals from relevant stakeholders or team members. + - Step 4. Merging PR: Once all requirements have been met and the PR has received the required approvals, merge the PR. The automation will then be triggered to proceed with the release. +By following these steps, you can efficiently create a release, ensuring that the code has been thoroughly tested and validated before deployment to public networks. ## Creating a Hotfix Release Creating a hotfix release is a straightforward process. Here are the steps to follow: diff --git a/x/observer/client/cli/query_get_tss_address.go b/x/observer/client/cli/query_get_tss_address.go index 8bfac0e10f..d37fb95f0c 100644 --- a/x/observer/client/cli/query_get_tss_address.go +++ b/x/observer/client/cli/query_get_tss_address.go @@ -11,9 +11,9 @@ import ( func CmdGetTssAddress() *cobra.Command { cmd := &cobra.Command{ - Use: "get-tss-address", + Use: "get-tss-address [bitcoinChainId]]", Short: "Query current tss address", - Args: cobra.NoArgs, + Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) (err error) { clientCtx, err := client.GetClientTxContext(cmd) @@ -21,8 +21,14 @@ func CmdGetTssAddress() *cobra.Command { return err } queryClient := types.NewQueryClient(clientCtx) - params := &types.QueryGetTssAddressRequest{} + if len(args) == 1 { + bitcoinChainID, err := strconv.ParseInt(args[0], 10, 64) + if err != nil { + return err + } + params.BitcoinChainId = bitcoinChainID + } res, err := queryClient.GetTssAddress(cmd.Context(), params) if err != nil { @@ -40,9 +46,9 @@ func CmdGetTssAddress() *cobra.Command { func CmdGetTssAddressByFinalizedZetaHeight() *cobra.Command { cmd := &cobra.Command{ - Use: "get-historical-tss-address [finalizedZetaHeight]", + Use: "get-historical-tss-address [finalizedZetaHeight] [bitcoinChainId]", Short: "Query tss address by finalized zeta height (for historical tss addresses)", - Args: cobra.ExactArgs(1), + Args: cobra.MaximumNArgs(2), RunE: func(cmd *cobra.Command, args []string) (err error) { clientCtx, err := client.GetClientTxContext(cmd) @@ -58,6 +64,13 @@ func CmdGetTssAddressByFinalizedZetaHeight() *cobra.Command { params := &types.QueryGetTssAddressByFinalizedHeightRequest{ FinalizedZetaHeight: finalizedZetaHeight, } + if len(args) == 2 { + bitcoinChainID, err := strconv.ParseInt(args[1], 10, 64) + if err != nil { + return err + } + params.BitcoinChainId = bitcoinChainID + } res, err := queryClient.GetTssAddressByFinalizedHeight(cmd.Context(), params) if err != nil { diff --git a/zetaclient/broadcast.go b/zetaclient/broadcast.go index a0cfb13e63..8c1a86e70d 100644 --- a/zetaclient/broadcast.go +++ b/zetaclient/broadcast.go @@ -14,6 +14,7 @@ import ( authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" flag "github.com/spf13/pflag" rpchttp "github.com/tendermint/tendermint/rpc/client/http" + "github.com/zeta-chain/zetacore/app/ante" "github.com/zeta-chain/zetacore/cmd/zetacored/config" "github.com/zeta-chain/zetacore/common/cosmos" "github.com/zeta-chain/zetacore/zetaclient/hsm" @@ -41,7 +42,9 @@ func (b *ZetaCoreBridge) Broadcast(gaslimit uint64, authzWrappedMsg sdktypes.Msg if baseGasPrice == 0 { baseGasPrice = DefaultBaseGasPrice // shoudn't happen, but just in case } - baseGasPrice = int64(float64(baseGasPrice) * 0.011) + reductionRate := sdktypes.MustNewDecFromStr(ante.GasPriceReductionRate) + // multiply gas price by the system tx reduction rate + adjustedBaseGasPrice := sdktypes.NewDec(baseGasPrice).Mul(reductionRate) if blockHeight > b.blockHeight { b.blockHeight = blockHeight @@ -73,7 +76,7 @@ func (b *ZetaCoreBridge) Broadcast(gaslimit uint64, authzWrappedMsg sdktypes.Msg builder.SetGasLimit(gaslimit) // #nosec G701 always in range fee := sdktypes.NewCoins(sdktypes.NewCoin(config.BaseDenom, - cosmos.NewInt(int64(gaslimit)).Mul(cosmos.NewInt(baseGasPrice)))) + cosmos.NewInt(int64(gaslimit)).Mul(adjustedBaseGasPrice.Ceil().RoundInt()))) builder.SetFeeAmount(fee) //fmt.Printf("signing from name: %s\n", ctx.GetFromName()) err = b.SignTx(factory, ctx.GetFromName(), builder, true, ctx.TxConfig)