From 6dc68a52977a9abc53ebfe72dd9ce1b718368285 Mon Sep 17 00:00:00 2001 From: Lucas Bertrand Date: Mon, 15 Jan 2024 11:31:44 -0800 Subject: [PATCH 01/12] chore: v12.0.0 changelog (#1578) --- changelog.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/changelog.md b/changelog.md index b1f1596e69..3c8acacc3c 100644 --- a/changelog.md +++ b/changelog.md @@ -2,12 +2,14 @@ ## Unreleased +## Version: v12.0.0 + ### Breaking Changes TSS and chain validation related queries have been moved from `crosschain` module to `observer` module: * `PendingNonces` :Changed from `/zeta-chain/crosschain/pendingNonces/{chain_id}/{address}` to `/zeta-chain/observer/pendingNonces/{chain_id}/{address}` . It returns all the pending nonces for a chain id and address. This returns the current pending nonces for the chain. -* `ChainNonces` : Changed from `/zeta-chain/crosschain/chainNonces/{chain_id}` to`/zeta-chain/observer/chainNonces/{chain_id}` . It returns all the chain nonces for a chain id. This returns the current nonce oof the TSS address for the chain. -* `ChainNoncesAll` :Changed from `/zeta-chain/observer/chainNonces` to `/zeta-chain/observer/chainNonces` . It returns all the chain nonces for all chains. This returns the current nonce of the TSS address for all chains. +* `ChainNonces` : Changed from `/zeta-chain/crosschain/chainNonces/{chain_id}` to`/zeta-chain/observer/chainNonces/{chain_id}` . It returns all the chain nonces for a chain id. This returns the current nonce of the TSS address for the chain. +* `ChainNoncesAll` :Changed from `/zeta-chain/crosschain/chainNonces` to `/zeta-chain/observer/chainNonces` . It returns all the chain nonces for all chains. This returns the current nonce of the TSS address for all chains. All chains now have the same observer set: * `ObserversByChain`: `/zeta-chain/observer/observers_by_chain/{observation_chain}` has been removed and replaced with `/zeta-chain/observer/observer_set`. All chains have the same observer set. @@ -19,7 +21,7 @@ Observer params and core params have been merged into chain params: * `GetCoreParamsByChain`: Renamed into `GetChainParamsForChain`. `/zeta-chain/observer/get_core_params_by_chain` moved to `/zeta-chain/observer/get_chain_params_by_chain`. Getting the correct TSS address for Bitcoin now requires proviidng the Bitcoin chain id: -* `GetTssAddress` : Changed from `/zeta-chain/observer/get_tss_address/` to `/zeta-chain/observer/getTssAddress/{bitcoin_chain_id}` . Optional bitcoing chain id can now now passed as a parameter to fetch the correct tss for required BTC chain.This parameter only affects the BTC tss address in the response. +* `GetTssAddress` : Changed from `/zeta-chain/observer/get_tss_address/` to `/zeta-chain/observer/getTssAddress/{bitcoin_chain_id}` . Optional bitcoin chain id can now be passed as a parameter to fetch the correct tss for required BTC chain. This parameter only affects the BTC tss address in the response. ### Features From a0e4f6269176f02a6f83ff49bf04a3cc6146e913 Mon Sep 17 00:00:00 2001 From: Charlie Chen <34498985+ws4charlie@users.noreply.github.com> Date: Tue, 16 Jan 2024 12:49:25 -0600 Subject: [PATCH 02/12] fix: skip unsupported chain parameters (#1581) Co-authored-by: Lucas Bertrand --- changelog.md | 1 + zetaclient/zetacore_bridge.go | 15 +++++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/changelog.md b/changelog.md index 3c8acacc3c..56dd363d05 100644 --- a/changelog.md +++ b/changelog.md @@ -35,6 +35,7 @@ Getting the correct TSS address for Bitcoin now requires proviidng the Bitcoin c ### Fixes +* [1575](https://github.com/zeta-chain/node/issues/1575) - Skip unsupported chain parameters by IsSupported flag * [1554](https://github.com/zeta-chain/node/pull/1554) - Screen out unconfirmed UTXOs that are not created by TSS itself * [1560](https://github.com/zeta-chain/node/issues/1560) - Zetaclient post evm-chain outtx hashes only when receipt is available * [1516](https://github.com/zeta-chain/node/issues/1516) - Unprivileged outtx tracker removal diff --git a/zetaclient/zetacore_bridge.go b/zetaclient/zetacore_bridge.go index 0a2b3b08c4..bf4466565c 100644 --- a/zetaclient/zetacore_bridge.go +++ b/zetaclient/zetacore_bridge.go @@ -196,7 +196,8 @@ func (b *ZetaCoreBridge) UpdateConfigFromCore(cfg *config.Config, init bool) err return err } if plan != nil && bn == plan.Height-1 { // stop zetaclients; notify operator to upgrade and restart - b.logger.Warn().Msgf("Active upgrade plan detected and upgrade height reached: %s at height %d; ZetaClient is stopped; please kill this process, replace zetaclientd binary with upgraded version, and restart zetaclientd", plan.Name, plan.Height) + b.logger.Warn().Msgf("Active upgrade plan detected and upgrade height reached: %s at height %d; ZetaClient is stopped;"+ + "please kill this process, replace zetaclientd binary with upgraded version, and restart zetaclientd", plan.Name, plan.Height) b.pause <- struct{}{} // notify CoreObserver to stop ChainClients, Signers, and CoreObservder itself } @@ -212,14 +213,16 @@ func (b *ZetaCoreBridge) UpdateConfigFromCore(cfg *config.Config, init bool) err for _, chainParam := range chainParams { err := config.ValidateChainParams(chainParam) if err != nil { - b.logger.Debug().Err(err).Msgf( - "Invalid core params for chain %s", - common.GetChainFromChainID(chainParam.ChainId).ChainName, - ) + b.logger.Warn().Err(err).Msgf("Invalid chain params for chain %d", chainParam.ChainId) + continue + } + if !chainParam.GetIsSupported() { + b.logger.Info().Msgf("Chain %d is not supported yet", chainParam.ChainId) + continue } if common.IsBitcoinChain(chainParam.ChainId) { newBTCParams = chainParam - } else { + } else if common.IsEVMChain(chainParam.ChainId) { newEVMParams[chainParam.ChainId] = chainParam } } From 3f6ea69313a8d0d692a754468430e66fd8269b25 Mon Sep 17 00:00:00 2001 From: lumtis Date: Tue, 16 Jan 2024 16:02:20 -0800 Subject: [PATCH 03/12] remove debug zetaclient1 --- contrib/localnet/scripts/start-zetaclientd-genesis.sh | 2 +- contrib/localnet/scripts/start-zetaclientd.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/localnet/scripts/start-zetaclientd-genesis.sh b/contrib/localnet/scripts/start-zetaclientd-genesis.sh index 7c23cd0673..5f2cadceab 100755 --- a/contrib/localnet/scripts/start-zetaclientd-genesis.sh +++ b/contrib/localnet/scripts/start-zetaclientd-genesis.sh @@ -36,6 +36,6 @@ else SEED=$(curl --retry 10 --retry-delay 5 --retry-connrefused -s zetaclient0:8123/p2p) done rm ~/.tss/* - zetaclientd init --peer /ip4/172.20.0.21/tcp/6668/p2p/"$SEED" --zetacore-url "$node" --chain-id athens_101-1 --operator "$operatorAddress" --log-format=text --public-ip "$MYIP" --log-level 0 --keyring-backend "$BACKEND" + zetaclientd init --peer /ip4/172.20.0.21/tcp/6668/p2p/"$SEED" --zetacore-url "$node" --chain-id athens_101-1 --operator "$operatorAddress" --log-format=text --public-ip "$MYIP" --log-level 1 --keyring-backend "$BACKEND" zetaclientd start fi diff --git a/contrib/localnet/scripts/start-zetaclientd.sh b/contrib/localnet/scripts/start-zetaclientd.sh index 14de0fada6..eecb8b8e5d 100644 --- a/contrib/localnet/scripts/start-zetaclientd.sh +++ b/contrib/localnet/scripts/start-zetaclientd.sh @@ -23,6 +23,6 @@ else zetaclientd init \ --peer /ip4/172.20.0.21/tcp/6668/p2p/$SEED \ --pre-params ~/preParams.json --zetacore-url $node \ - --chain-id athens_101-1 --operator zeta1lz2fqwzjnk6qy48fgj753h48444fxtt7hekp52 --log-level 0 --hotkey=val_grantee_observer + --chain-id athens_101-1 --operator zeta1lz2fqwzjnk6qy48fgj753h48444fxtt7hekp52 --log-level 1 --hotkey=val_grantee_observer zetaclientd start fi From c50af5720333383028f8c1a06924f20e0ea1acc8 Mon Sep 17 00:00:00 2001 From: lumtis Date: Tue, 16 Jan 2024 16:04:20 -0800 Subject: [PATCH 04/12] remove comments --- zetaclient/broadcast.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/zetaclient/broadcast.go b/zetaclient/broadcast.go index f015f2df85..c4fee8c1c9 100644 --- a/zetaclient/broadcast.go +++ b/zetaclient/broadcast.go @@ -53,7 +53,6 @@ func (b *ZetaCoreBridge) Broadcast(gaslimit uint64, authzWrappedMsg sdktypes.Msg b.seqNumber[authzSigner.KeyType] = seqNumber } } - //b.logger.Info().Uint64("account_number", b.accountNumber).Uint64("sequence_number", b.seqNumber).Msg("account info") flags := flag.NewFlagSet("zetacore", 0) @@ -69,12 +68,13 @@ func (b *ZetaCoreBridge) Broadcast(gaslimit uint64, authzWrappedMsg sdktypes.Msg if err != nil { return "", err } + builder.SetGasLimit(gaslimit) + // #nosec G701 always in range fee := sdktypes.NewCoins(sdktypes.NewCoin(config.BaseDenom, cosmos.NewInt(int64(gaslimit)).Mul(cosmos.NewInt(baseGasPrice)))) builder.SetFeeAmount(fee) - //fmt.Printf("signing from name: %s\n", ctx.GetFromName()) err = b.SignTx(factory, ctx.GetFromName(), builder, true, ctx.TxConfig) if err != nil { return "", err @@ -90,6 +90,7 @@ func (b *ZetaCoreBridge) Broadcast(gaslimit uint64, authzWrappedMsg sdktypes.Msg b.logger.Error().Err(err).Msgf("fail to broadcast tx %s", err.Error()) return "", err } + // Code will be the tendermint ABICode , it start at 1 , so if it is an error , code will not be zero if commit.Code > 0 { if commit.Code == 32 { @@ -114,11 +115,8 @@ func (b *ZetaCoreBridge) Broadcast(gaslimit uint64, authzWrappedMsg sdktypes.Msg } return commit.TxHash, fmt.Errorf("fail to broadcast to zetachain,code:%d, log:%s", commit.Code, commit.RawLog) } - //b.logger.Debug().Msgf("Received a TxHash of %v from the metachain, Code %d, log %s", commit.TxHash, commit.Code, commit.Logs) // increment seqNum - //seq := b.seqNumber[authzSigner.KeyType] - //atomic.AddUint64(&seq, 1) b.seqNumber[authzSigner.KeyType] = b.seqNumber[authzSigner.KeyType] + 1 return commit.TxHash, nil From 6d0611347bb0ca0192a0e708cdbd286b12d285ea Mon Sep 17 00:00:00 2001 From: lumtis Date: Tue, 16 Jan 2024 16:05:55 -0800 Subject: [PATCH 05/12] tx resend --- zetaclient/bitcoin_client.go | 2 +- zetaclient/evm_client.go | 6 +- zetaclient/inbound_tracker.go | 8 +-- zetaclient/interfaces.go | 2 +- zetaclient/tx.go | 105 ++++++++++++++++++++++++---------- 5 files changed, 85 insertions(+), 38 deletions(-) diff --git a/zetaclient/bitcoin_client.go b/zetaclient/bitcoin_client.go index a316e3b4ac..f3a2727ed5 100644 --- a/zetaclient/bitcoin_client.go +++ b/zetaclient/bitcoin_client.go @@ -385,7 +385,7 @@ func (ob *BitcoinChainClient) observeInTx() error { // post inbound vote message to zetacore for _, inTx := range inTxs { msg := ob.GetInboundVoteMessageFromBtcEvent(inTx) - zetaHash, ballot, err := ob.zetaClient.PostSend(PostSendEVMGasLimit, msg) + zetaHash, ballot, err := ob.zetaClient.PostSend(PostSendGasLimit, PostSendExecutionGasLimit, msg) if err != nil { ob.logger.WatchInTx.Error().Err(err).Msgf("observeInTxBTC: error posting to zeta core for tx %s", inTx.TxHash) return err // we have to re-scan this block next time diff --git a/zetaclient/evm_client.go b/zetaclient/evm_client.go index 8a68ac121e..7ed012f1db 100644 --- a/zetaclient/evm_client.go +++ b/zetaclient/evm_client.go @@ -971,7 +971,7 @@ func (ob *EVMChainClient) observeZetaSent(startBlock, toBlock uint64) uint64 { "observeZetaSent: error getting inbound vote msg for tx %s chain %d", event.Raw.TxHash.Hex(), ob.chain.ChainId) continue } - zetaHash, ballot, err := ob.zetaClient.PostSend(PostSendNonEVMGasLimit, &msg) + zetaHash, ballot, err := ob.zetaClient.PostSend(PostSendGasLimit, PostSendMessagePassingExecutionGasLimit, &msg) if err != nil { ob.logger.ExternalChainWatcher.Error().Err(err).Msgf( "observeZetaSent: error posting event to zeta core for tx %s at height %d for chain %d", @@ -1050,7 +1050,7 @@ func (ob *EVMChainClient) observeERC20Deposited(startBlock, toBlock uint64) uint "observeERC20Deposited: error getting inbound vote msg for tx %s chain %d", event.Raw.TxHash.Hex(), ob.chain.ChainId) continue } - zetaHash, ballot, err := ob.zetaClient.PostSend(PostSendEVMGasLimit, &msg) + zetaHash, ballot, err := ob.zetaClient.PostSend(PostSendGasLimit, PostSendExecutionGasLimit, &msg) if err != nil { ob.logger.ExternalChainWatcher.Error().Err(err).Msgf( "observeERC20Deposited: error posting event to zeta core for tx %s at height %d for chain %d", @@ -1133,7 +1133,7 @@ func (ob *EVMChainClient) observeTssRecvd(startBlock, toBlock uint64, flags obse if msg == nil { continue } - zetaHash, ballot, err := ob.zetaClient.PostSend(PostSendEVMGasLimit, msg) + zetaHash, ballot, err := ob.zetaClient.PostSend(PostSendGasLimit, PostSendExecutionGasLimit, msg) if err != nil { ob.logger.ExternalChainWatcher.Error().Err(err).Msgf( "observeTssRecvd: error posting to zeta core for tx %s at height %d for chain %d", tx.Hash().Hex(), bn, ob.chain.ChainId) diff --git a/zetaclient/inbound_tracker.go b/zetaclient/inbound_tracker.go index 8a7ebd1147..e671925b91 100644 --- a/zetaclient/inbound_tracker.go +++ b/zetaclient/inbound_tracker.go @@ -114,7 +114,7 @@ func (ob *BitcoinChainClient) CheckReceiptForBtcTxHash(txHash string, vote bool) if !vote { return msg.Digest(), nil } - zetaHash, ballot, err := ob.zetaClient.PostSend(PostSendEVMGasLimit, msg) + zetaHash, ballot, err := ob.zetaClient.PostSend(PostSendGasLimit, PostSendExecutionGasLimit, msg) if err != nil { ob.logger.WatchInTx.Error().Err(err).Msg("error posting to zeta core") return "", err @@ -192,7 +192,7 @@ func (ob *EVMChainClient) CheckReceiptForCoinTypeZeta(txHash string, vote bool) return msg.Digest(), nil } - zetaHash, ballot, err := ob.zetaClient.PostSend(PostSendNonEVMGasLimit, &msg) + zetaHash, ballot, err := ob.zetaClient.PostSend(PostSendGasLimit, PostSendMessagePassingExecutionGasLimit, &msg) if err != nil { ob.logger.ExternalChainWatcher.Error().Err(err).Msg("error posting to zeta core") return "", err @@ -240,7 +240,7 @@ func (ob *EVMChainClient) CheckReceiptForCoinTypeERC20(txHash string, vote bool) return msg.Digest(), nil } - zetaHash, ballot, err := ob.zetaClient.PostSend(PostSendEVMGasLimit, &msg) + zetaHash, ballot, err := ob.zetaClient.PostSend(PostSendGasLimit, PostSendExecutionGasLimit, &msg) if err != nil { ob.logger.ExternalChainWatcher.Error().Err(err).Msg("error posting to zeta core") return "", err @@ -297,7 +297,7 @@ func (ob *EVMChainClient) CheckReceiptForCoinTypeGas(txHash string, vote bool) ( return msg.Digest(), nil } - zetaHash, ballot, err := ob.zetaClient.PostSend(PostSendEVMGasLimit, msg) + zetaHash, ballot, err := ob.zetaClient.PostSend(PostSendGasLimit, PostSendExecutionGasLimit, msg) if err != nil { ob.logger.ExternalChainWatcher.Error().Err(err).Msg("error posting to zeta core") return "", err diff --git a/zetaclient/interfaces.go b/zetaclient/interfaces.go index fe2d0824c1..7d83e471b3 100644 --- a/zetaclient/interfaces.go +++ b/zetaclient/interfaces.go @@ -48,7 +48,7 @@ type ChainSigner interface { // ZetaCoreBridger is the interface to interact with ZetaCore type ZetaCoreBridger interface { - PostSend(zetaGasLimit uint64, msg *crosschaintypes.MsgVoteOnObservedInboundTx) (string, string, error) + PostSend(gasLimit, retryGasLimit uint64, msg *crosschaintypes.MsgVoteOnObservedInboundTx) (string, string, error) PostReceiveConfirmation( sendHash string, outTxHash string, diff --git a/zetaclient/tx.go b/zetaclient/tx.go index 38a02052ed..a737d63298 100644 --- a/zetaclient/tx.go +++ b/zetaclient/tx.go @@ -19,18 +19,38 @@ import ( ) const ( - PostGasPriceGasLimit = 1_500_000 + // DefaultGasLimit is the default gas limit used for broadcasting txs + DefaultGasLimit = 200_000 + + // PostGasPriceGasLimit is the gas limit for voting new gas price + PostGasPriceGasLimit = 1_500_000 + + // AddTxHashToOutTxTrackerGasLimit is the gas limit for adding tx hash to out tx tracker AddTxHashToOutTxTrackerGasLimit = 200_000 - PostNonceGasLimit = 200_000 - PostSendEVMGasLimit = 4_000_000 // likely emit a lot of logs, so costly - PostSendNonEVMGasLimit = 1_000_000 + + // PostSendGasLimit is the gas limit for voting on observed inbound tx + PostSendGasLimit = 400_000 + + // PostSendExecutionGasLimit is the gas limit for voting on observed inbound tx and executing it + PostSendExecutionGasLimit = 4_000_000 + + // PostSendMessagePassingExecutionGasLimit is the gas limit for voting on, and executing ,observed inbound tx related to message passing (coin_type == zeta) + PostSendMessagePassingExecutionGasLimit = 1_000_000 + + // PostReceiveConfirmationGasLimit is the gas limit for voting on observed outbound tx PostReceiveConfirmationGasLimit = 400_000 - PostBlameDataGasLimit = 200_000 - DefaultGasLimit = 200_000 - PostProveOutboundTxGasLimit = 400_000 - DefaultRetryCount = 5 - ExtendedRetryCount = 15 - DefaultRetryInterval = 5 + + // PostBlameDataGasLimit is the gas limit for voting on blames + PostBlameDataGasLimit = 200_000 + + // DefaultRetryCount is the number of retries for broadcasting a tx + DefaultRetryCount = 5 + + // ExtendedRetryCount is an extended number of retries for broadcasting a tx, used in keygen operations + ExtendedRetryCount = 15 + + // DefaultRetryInterval is the interval between retries in seconds + DefaultRetryInterval = 5 ) // GetInBoundVoteMessage returns a new MsgVoteOnObservedInboundTx @@ -126,7 +146,10 @@ func (b *ZetaCoreBridge) AddTxHashToOutTxTracker( return zetaTxHash, nil } -func (b *ZetaCoreBridge) PostSend(zetaGasLimit uint64, msg *types.MsgVoteOnObservedInboundTx) (string, string, error) { +// PostSend posts a vote on an observed inbound tx +// retryGasLimit is the gas limit used to resend the tx if it fails because of insufficient gas +// it is used when the ballot is finalized and the inbound tx needs to be processed +func (b *ZetaCoreBridge) PostSend(gasLimit, retryGasLimit uint64, msg *types.MsgVoteOnObservedInboundTx) (string, string, error) { authzMsg, authzSigner, err := b.WrapMessageWithAuthz(msg) if err != nil { return "", "", err @@ -143,10 +166,10 @@ func (b *ZetaCoreBridge) PostSend(zetaGasLimit uint64, msg *types.MsgVoteOnObser } for i := 0; i < DefaultRetryCount; i++ { - zetaTxHash, err := b.Broadcast(zetaGasLimit, authzMsg, authzSigner) + zetaTxHash, err := b.Broadcast(gasLimit, authzMsg, authzSigner) if err == nil { // monitor the result of the transaction - go b.MonitorTxResult(zetaTxHash, true) + go b.MonitorVoteInboundTxResult(zetaTxHash, retryGasLimit, msg) return zetaTxHash, ballotIndex, nil } @@ -204,14 +227,13 @@ func (b *ZetaCoreBridge) PostReceiveConfirmation( // NewMsgReceiveConfirmation to it. var gasLimit uint64 = PostReceiveConfirmationGasLimit if status == common.ReceiveStatus_Failed { - gasLimit = PostSendEVMGasLimit + gasLimit = PostSendExecutionGasLimit } for i := 0; i < DefaultRetryCount; i++ { zetaTxHash, err := b.Broadcast(gasLimit, authzMsg, authzSigner) if err == nil { - // monitor the result of the transaction - go b.MonitorTxResult(zetaTxHash, true) - + //// monitor the result of the transaction + //go b.MonitorTxResult(zetaTxHash, true) return zetaTxHash, ballotIndex, nil } b.logger.Debug().Err(err).Msgf("PostReceive broadcast fail | Retry count : %d", i+1) @@ -309,15 +331,13 @@ func (b *ZetaCoreBridge) PostAddBlockHeader(chainID int64, blockHash []byte, hei return "", fmt.Errorf("post add block header failed after %d retries", DefaultRetryCount) } -// MonitorTxResult monitors the result of a tx (used for inbound and outbound vote txs) -func (b *ZetaCoreBridge) MonitorTxResult(zetaTxHash string, isInbound bool) { +// MonitorVoteInboundTxResult monitors the result of a tx (used for inbound and outbound vote txs) +// retryGasLimit is the gas limit used to resend the tx if it fails because of insufficient gas +// if retryGasLimit is 0, the tx is not resent +func (b *ZetaCoreBridge) MonitorVoteInboundTxResult(zetaTxHash string, retryGasLimit uint64, msg *types.MsgVoteOnObservedInboundTx) { var lastErr error ticker := 5 * time.Second retry := 10 - prefix := "MonitorOutboundTxResult" - if isInbound { - prefix = "MonitorInboundTxResult" - } for i := 0; i < retry; i++ { time.Sleep(ticker) @@ -326,10 +346,38 @@ func (b *ZetaCoreBridge) MonitorTxResult(zetaTxHash string, isInbound bool) { // the inbound vote tx shouldn't fail to execute if strings.Contains(txResult.RawLog, "failed to execute message") { b.logger.Error().Msgf( - "%s: failed to execute vote, txHash: %s, txResult %s", - prefix, + "MonitorInboundTxResult: failed to execute vote, txHash: %s, log %s", + zetaTxHash, + txResult.RawLog, + ) + } else if strings.Contains(txResult.RawLog, "out of gas") { + b.logger.Error().Msgf( + "MonitorInboundTxResult: out of gas, txHash: %s, log %s", + zetaTxHash, + txResult.RawLog, + ) + // resend the tx with more gas + if retryGasLimit > 0 { + _, _, err := b.PostSend(retryGasLimit, 0, msg) + if err != nil { + b.logger.Error().Err(err).Msgf( + "MonitorInboundTxResult: failed to resend tx, txHash: %s, log %s", + zetaTxHash, + txResult.RawLog, + ) + } else { + b.logger.Info().Msgf( + "MonitorInboundTxResult: successfully resent tx, txHash: %s, log %s", + zetaTxHash, + txResult.RawLog, + ) + } + } + } else { + b.logger.Info().Msgf( + "MonitorInboundTxResult: successful txHash %s, log %s", zetaTxHash, - txResult.String(), + txResult.RawLog, ) } return @@ -337,9 +385,8 @@ func (b *ZetaCoreBridge) MonitorTxResult(zetaTxHash string, isInbound bool) { lastErr = err } - b.logger.Error().Err(lastErr).Msgf( - "%s: unable to query tx result for txHash %s, err %s", - prefix, + b.logger.Info().Err(lastErr).Msgf( + "MonitorInboundTxResult: unable to query tx result for txHash %s, err %s", zetaTxHash, lastErr.Error(), ) From 531ba4562f568a3fb25de41b42aa345ce7cddb0e Mon Sep 17 00:00:00 2001 From: lumtis Date: Tue, 16 Jan 2024 16:46:32 -0800 Subject: [PATCH 06/12] complete renaming --- zetaclient/bitcoin_client.go | 6 ++--- zetaclient/evm_client.go | 32 ++++++++++++------------- zetaclient/inbound_tracker.go | 16 ++++++------- zetaclient/interfaces.go | 4 ++-- zetaclient/tx.go | 36 ++++++++++++++-------------- zetaclient/voter_test.go | 12 +++++----- zetaclient/zetacore_observer_test.go | 8 +++---- 7 files changed, 57 insertions(+), 57 deletions(-) diff --git a/zetaclient/bitcoin_client.go b/zetaclient/bitcoin_client.go index f3a2727ed5..2c91707f32 100644 --- a/zetaclient/bitcoin_client.go +++ b/zetaclient/bitcoin_client.go @@ -385,12 +385,12 @@ func (ob *BitcoinChainClient) observeInTx() error { // post inbound vote message to zetacore for _, inTx := range inTxs { msg := ob.GetInboundVoteMessageFromBtcEvent(inTx) - zetaHash, ballot, err := ob.zetaClient.PostSend(PostSendGasLimit, PostSendExecutionGasLimit, msg) + zetaHash, ballot, err := ob.zetaClient.PostVoteInbound(PostVoteInboundGasLimit, PostVoteInboundExecutionGasLimit, msg) if err != nil { ob.logger.WatchInTx.Error().Err(err).Msgf("observeInTxBTC: error posting to zeta core for tx %s", inTx.TxHash) return err // we have to re-scan this block next time } else if zetaHash != "" { - ob.logger.WatchInTx.Info().Msgf("observeInTxBTC: BTC deposit detected and reported: PostSend zeta tx: %s ballot %s", zetaHash, ballot) + ob.logger.WatchInTx.Info().Msgf("observeInTxBTC: BTC deposit detected and reported: PostVoteInbound zeta tx: %s ballot %s", zetaHash, ballot) } } @@ -470,7 +470,7 @@ func (ob *BitcoinChainClient) IsSendOutTxProcessed(sendHash string, nonce uint64 } logger.Debug().Msgf("Bitcoin outTx confirmed: txid %s, amount %s\n", res.TxID, amountInSat.String()) - zetaHash, ballot, err := ob.zetaClient.PostReceiveConfirmation( + zetaHash, ballot, err := ob.zetaClient.PostVoteOutbound( sendHash, res.TxID, // #nosec G701 always positive diff --git a/zetaclient/evm_client.go b/zetaclient/evm_client.go index 7ed012f1db..263e40a251 100644 --- a/zetaclient/evm_client.go +++ b/zetaclient/evm_client.go @@ -318,7 +318,7 @@ func (ob *EVMChainClient) IsSendOutTxProcessed(sendHash string, nonce uint64, co if receipt.Status == 1 { recvStatus = common.ReceiveStatus_Success } - zetaTxHash, ballot, err := ob.zetaClient.PostReceiveConfirmation( + zetaTxHash, ballot, err := ob.zetaClient.PostVoteOutbound( sendHash, receipt.TxHash.Hex(), receipt.BlockNumber.Uint64(), @@ -340,7 +340,7 @@ func (ob *EVMChainClient) IsSendOutTxProcessed(sendHash string, nonce uint64, co } else if cointype == common.CoinType_Gas { // the outbound is a regular Ether/BNB/Matic transfer; no need to check events if receipt.Status == 1 { - zetaTxHash, ballot, err := ob.zetaClient.PostReceiveConfirmation( + zetaTxHash, ballot, err := ob.zetaClient.PostVoteOutbound( sendHash, receipt.TxHash.Hex(), receipt.BlockNumber.Uint64(), @@ -361,7 +361,7 @@ func (ob *EVMChainClient) IsSendOutTxProcessed(sendHash string, nonce uint64, co return true, true, nil } else if receipt.Status == 0 { // the same as below events flow logger.Info().Msgf("Found (failed tx) sendHash %s on chain %s txhash %s", sendHash, ob.chain.String(), receipt.TxHash.Hex()) - zetaTxHash, ballot, err := ob.zetaClient.PostReceiveConfirmation( + zetaTxHash, ballot, err := ob.zetaClient.PostVoteOutbound( sendHash, receipt.TxHash.Hex(), receipt.BlockNumber.Uint64(), @@ -375,7 +375,7 @@ func (ob *EVMChainClient) IsSendOutTxProcessed(sendHash string, nonce uint64, co common.CoinType_Gas, ) if err != nil { - logger.Error().Err(err).Msgf("PostReceiveConfirmation error in WatchTxHashWithTimeout; zeta tx hash %s cctx %s nonce %d", zetaTxHash, sendHash, nonce) + logger.Error().Err(err).Msgf("PostVoteOutbound error in WatchTxHashWithTimeout; zeta tx hash %s cctx %s nonce %d", zetaTxHash, sendHash, nonce) } else if zetaTxHash != "" { logger.Info().Msgf("Zeta tx hash: %s cctx %s nonce %d ballot %s", zetaTxHash, sendHash, nonce, ballot) } @@ -405,7 +405,7 @@ func (ob *EVMChainClient) IsSendOutTxProcessed(sendHash string, nonce uint64, co sendhash := vLog.Topics[3].Hex() //var rxAddress string = ethcommon.HexToAddress(vLog.Topics[1].Hex()).Hex() mMint := receivedLog.ZetaValue - zetaTxHash, ballot, err := ob.zetaClient.PostReceiveConfirmation( + zetaTxHash, ballot, err := ob.zetaClient.PostVoteOutbound( sendhash, vLog.TxHash.Hex(), vLog.BlockNumber, @@ -442,7 +442,7 @@ func (ob *EVMChainClient) IsSendOutTxProcessed(sendHash string, nonce uint64, co } sendhash := vLog.Topics[2].Hex() mMint := revertedLog.RemainingZetaValue - zetaTxHash, ballot, err := ob.zetaClient.PostReceiveConfirmation( + zetaTxHash, ballot, err := ob.zetaClient.PostVoteOutbound( sendhash, vLog.TxHash.Hex(), vLog.BlockNumber, @@ -470,7 +470,7 @@ func (ob *EVMChainClient) IsSendOutTxProcessed(sendHash string, nonce uint64, co } else if receipt.Status == 0 { //FIXME: check nonce here by getTransaction RPC logger.Info().Msgf("Found (failed tx) sendHash %s on chain %s txhash %s", sendHash, ob.chain.String(), receipt.TxHash.Hex()) - zetaTxHash, ballot, err := ob.zetaClient.PostReceiveConfirmation( + zetaTxHash, ballot, err := ob.zetaClient.PostVoteOutbound( sendHash, receipt.TxHash.Hex(), receipt.BlockNumber.Uint64(), @@ -510,7 +510,7 @@ func (ob *EVMChainClient) IsSendOutTxProcessed(sendHash string, nonce uint64, co } if confHeight <= ob.GetLastBlockHeight() { logger.Info().Msg("Confirmed! Sending PostConfirmation to zetacore...") - zetaTxHash, ballot, err := ob.zetaClient.PostReceiveConfirmation( + zetaTxHash, ballot, err := ob.zetaClient.PostVoteOutbound( sendHash, vLog.TxHash.Hex(), vLog.BlockNumber, @@ -537,7 +537,7 @@ func (ob *EVMChainClient) IsSendOutTxProcessed(sendHash string, nonce uint64, co } } else { logger.Info().Msgf("Found (failed tx) sendHash %s on chain %s txhash %s", sendHash, ob.chain.String(), receipt.TxHash.Hex()) - zetaTxHash, ballot, err := ob.zetaClient.PostReceiveConfirmation( + zetaTxHash, ballot, err := ob.zetaClient.PostVoteOutbound( sendHash, receipt.TxHash.Hex(), receipt.BlockNumber.Uint64(), @@ -551,7 +551,7 @@ func (ob *EVMChainClient) IsSendOutTxProcessed(sendHash string, nonce uint64, co common.CoinType_ERC20, ) if err != nil { - logger.Error().Err(err).Msgf("PostReceiveConfirmation error in WatchTxHashWithTimeout; zeta tx hash %s", zetaTxHash) + logger.Error().Err(err).Msgf("PostVoteOutbound error in WatchTxHashWithTimeout; zeta tx hash %s", zetaTxHash) } else if zetaTxHash != "" { logger.Info().Msgf("Zeta tx hash: %s cctx %s nonce %d ballot %s", zetaTxHash, sendHash, nonce, ballot) } @@ -971,7 +971,7 @@ func (ob *EVMChainClient) observeZetaSent(startBlock, toBlock uint64) uint64 { "observeZetaSent: error getting inbound vote msg for tx %s chain %d", event.Raw.TxHash.Hex(), ob.chain.ChainId) continue } - zetaHash, ballot, err := ob.zetaClient.PostSend(PostSendGasLimit, PostSendMessagePassingExecutionGasLimit, &msg) + zetaHash, ballot, err := ob.zetaClient.PostVoteInbound(PostVoteInboundGasLimit, PostVoteInboundMessagePassingExecutionGasLimit, &msg) if err != nil { ob.logger.ExternalChainWatcher.Error().Err(err).Msgf( "observeZetaSent: error posting event to zeta core for tx %s at height %d for chain %d", @@ -979,7 +979,7 @@ func (ob *EVMChainClient) observeZetaSent(startBlock, toBlock uint64) uint64 { return beingScanned - 1 // we have to re-scan from this block next time } else if zetaHash != "" { ob.logger.ExternalChainWatcher.Info().Msgf( - "observeZetaSent: event detected in tx %s at height %d for chain %d, PostSend zeta tx: %s ballot %s", + "observeZetaSent: event detected in tx %s at height %d for chain %d, PostVoteInbound zeta tx: %s ballot %s", event.Raw.TxHash.Hex(), event.Raw.BlockNumber, ob.chain.ChainId, zetaHash, ballot) } } @@ -1050,7 +1050,7 @@ func (ob *EVMChainClient) observeERC20Deposited(startBlock, toBlock uint64) uint "observeERC20Deposited: error getting inbound vote msg for tx %s chain %d", event.Raw.TxHash.Hex(), ob.chain.ChainId) continue } - zetaHash, ballot, err := ob.zetaClient.PostSend(PostSendGasLimit, PostSendExecutionGasLimit, &msg) + zetaHash, ballot, err := ob.zetaClient.PostVoteInbound(PostVoteInboundGasLimit, PostVoteInboundExecutionGasLimit, &msg) if err != nil { ob.logger.ExternalChainWatcher.Error().Err(err).Msgf( "observeERC20Deposited: error posting event to zeta core for tx %s at height %d for chain %d", @@ -1058,7 +1058,7 @@ func (ob *EVMChainClient) observeERC20Deposited(startBlock, toBlock uint64) uint return beingScanned - 1 // we have to re-scan from this block next time } else if zetaHash != "" { ob.logger.ExternalChainWatcher.Info().Msgf( - "observeERC20Deposited: event detected in tx %s at height %d for chain %d, PostSend zeta tx: %s ballot %s", + "observeERC20Deposited: event detected in tx %s at height %d for chain %d, PostVoteInbound zeta tx: %s ballot %s", event.Raw.TxHash.Hex(), event.Raw.BlockNumber, ob.chain.ChainId, zetaHash, ballot) } } @@ -1133,14 +1133,14 @@ func (ob *EVMChainClient) observeTssRecvd(startBlock, toBlock uint64, flags obse if msg == nil { continue } - zetaHash, ballot, err := ob.zetaClient.PostSend(PostSendGasLimit, PostSendExecutionGasLimit, msg) + zetaHash, ballot, err := ob.zetaClient.PostVoteInbound(PostVoteInboundGasLimit, PostVoteInboundExecutionGasLimit, msg) if err != nil { ob.logger.ExternalChainWatcher.Error().Err(err).Msgf( "observeTssRecvd: error posting to zeta core for tx %s at height %d for chain %d", tx.Hash().Hex(), bn, ob.chain.ChainId) return startBlock - 1 // we have to re-scan this block next time } else if zetaHash != "" { ob.logger.ExternalChainWatcher.Info().Msgf( - "observeTssRecvd: gas asset deposit detected in tx %s at height %d for chain %d, PostSend zeta tx: %s ballot %s", + "observeTssRecvd: gas asset deposit detected in tx %s at height %d for chain %d, PostVoteInbound zeta tx: %s ballot %s", tx.Hash().Hex(), bn, ob.chain.ChainId, zetaHash, ballot) } } diff --git a/zetaclient/inbound_tracker.go b/zetaclient/inbound_tracker.go index e671925b91..6137f9f20a 100644 --- a/zetaclient/inbound_tracker.go +++ b/zetaclient/inbound_tracker.go @@ -114,12 +114,12 @@ func (ob *BitcoinChainClient) CheckReceiptForBtcTxHash(txHash string, vote bool) if !vote { return msg.Digest(), nil } - zetaHash, ballot, err := ob.zetaClient.PostSend(PostSendGasLimit, PostSendExecutionGasLimit, msg) + zetaHash, ballot, err := ob.zetaClient.PostVoteInbound(PostVoteInboundGasLimit, PostVoteInboundExecutionGasLimit, msg) if err != nil { ob.logger.WatchInTx.Error().Err(err).Msg("error posting to zeta core") return "", err } else if ballot == "" { - ob.logger.WatchInTx.Info().Msgf("BTC deposit detected and reported: PostSend zeta tx: %s ballot %s", zetaHash, ballot) + ob.logger.WatchInTx.Info().Msgf("BTC deposit detected and reported: PostVoteInbound zeta tx: %s ballot %s", zetaHash, ballot) } return msg.Digest(), nil } @@ -192,12 +192,12 @@ func (ob *EVMChainClient) CheckReceiptForCoinTypeZeta(txHash string, vote bool) return msg.Digest(), nil } - zetaHash, ballot, err := ob.zetaClient.PostSend(PostSendGasLimit, PostSendMessagePassingExecutionGasLimit, &msg) + zetaHash, ballot, err := ob.zetaClient.PostVoteInbound(PostVoteInboundGasLimit, PostVoteInboundMessagePassingExecutionGasLimit, &msg) if err != nil { ob.logger.ExternalChainWatcher.Error().Err(err).Msg("error posting to zeta core") return "", err } else if zetaHash != "" { - ob.logger.ExternalChainWatcher.Info().Msgf("ZetaSent event detected and reported: PostSend zeta tx: %s ballot %s", zetaHash, ballot) + ob.logger.ExternalChainWatcher.Info().Msgf("ZetaSent event detected and reported: PostVoteInbound zeta tx: %s ballot %s", zetaHash, ballot) } return msg.Digest(), nil @@ -240,12 +240,12 @@ func (ob *EVMChainClient) CheckReceiptForCoinTypeERC20(txHash string, vote bool) return msg.Digest(), nil } - zetaHash, ballot, err := ob.zetaClient.PostSend(PostSendGasLimit, PostSendExecutionGasLimit, &msg) + zetaHash, ballot, err := ob.zetaClient.PostVoteInbound(PostVoteInboundGasLimit, PostVoteInboundExecutionGasLimit, &msg) if err != nil { ob.logger.ExternalChainWatcher.Error().Err(err).Msg("error posting to zeta core") return "", err } else if zetaHash != "" { - ob.logger.ExternalChainWatcher.Info().Msgf("ERC20 Deposit event detected and reported: PostSend zeta tx: %s ballot %s", zetaHash, ballot) + ob.logger.ExternalChainWatcher.Info().Msgf("ERC20 Deposit event detected and reported: PostVoteInbound zeta tx: %s ballot %s", zetaHash, ballot) } return msg.Digest(), nil @@ -297,12 +297,12 @@ func (ob *EVMChainClient) CheckReceiptForCoinTypeGas(txHash string, vote bool) ( return msg.Digest(), nil } - zetaHash, ballot, err := ob.zetaClient.PostSend(PostSendGasLimit, PostSendExecutionGasLimit, msg) + zetaHash, ballot, err := ob.zetaClient.PostVoteInbound(PostVoteInboundGasLimit, PostVoteInboundExecutionGasLimit, msg) if err != nil { ob.logger.ExternalChainWatcher.Error().Err(err).Msg("error posting to zeta core") return "", err } else if zetaHash != "" { - ob.logger.ExternalChainWatcher.Info().Msgf("Gas deposit detected and reported: PostSend zeta tx: %s ballot %s", zetaHash, ballot) + ob.logger.ExternalChainWatcher.Info().Msgf("Gas deposit detected and reported: PostVoteInbound zeta tx: %s ballot %s", zetaHash, ballot) } return msg.Digest(), nil diff --git a/zetaclient/interfaces.go b/zetaclient/interfaces.go index 7d83e471b3..6ca41f59fd 100644 --- a/zetaclient/interfaces.go +++ b/zetaclient/interfaces.go @@ -48,8 +48,8 @@ type ChainSigner interface { // ZetaCoreBridger is the interface to interact with ZetaCore type ZetaCoreBridger interface { - PostSend(gasLimit, retryGasLimit uint64, msg *crosschaintypes.MsgVoteOnObservedInboundTx) (string, string, error) - PostReceiveConfirmation( + PostVoteInbound(gasLimit, retryGasLimit uint64, msg *crosschaintypes.MsgVoteOnObservedInboundTx) (string, string, error) + PostVoteOutbound( sendHash string, outTxHash string, outBlockHeight uint64, diff --git a/zetaclient/tx.go b/zetaclient/tx.go index a737d63298..4f070aa26a 100644 --- a/zetaclient/tx.go +++ b/zetaclient/tx.go @@ -28,17 +28,17 @@ const ( // AddTxHashToOutTxTrackerGasLimit is the gas limit for adding tx hash to out tx tracker AddTxHashToOutTxTrackerGasLimit = 200_000 - // PostSendGasLimit is the gas limit for voting on observed inbound tx - PostSendGasLimit = 400_000 + // PostVoteInboundGasLimit is the gas limit for voting on observed inbound tx + PostVoteInboundGasLimit = 400_000 - // PostSendExecutionGasLimit is the gas limit for voting on observed inbound tx and executing it - PostSendExecutionGasLimit = 4_000_000 + // PostVoteInboundExecutionGasLimit is the gas limit for voting on observed inbound tx and executing it + PostVoteInboundExecutionGasLimit = 4_000_000 - // PostSendMessagePassingExecutionGasLimit is the gas limit for voting on, and executing ,observed inbound tx related to message passing (coin_type == zeta) - PostSendMessagePassingExecutionGasLimit = 1_000_000 + // PostVoteInboundMessagePassingExecutionGasLimit is the gas limit for voting on, and executing ,observed inbound tx related to message passing (coin_type == zeta) + PostVoteInboundMessagePassingExecutionGasLimit = 1_000_000 - // PostReceiveConfirmationGasLimit is the gas limit for voting on observed outbound tx - PostReceiveConfirmationGasLimit = 400_000 + // PostVoteOutboundGasLimit is the gas limit for voting on observed outbound tx + PostVoteOutboundGasLimit = 400_000 // PostBlameDataGasLimit is the gas limit for voting on blames PostBlameDataGasLimit = 200_000 @@ -146,10 +146,10 @@ func (b *ZetaCoreBridge) AddTxHashToOutTxTracker( return zetaTxHash, nil } -// PostSend posts a vote on an observed inbound tx +// PostVoteInbound posts a vote on an observed inbound tx // retryGasLimit is the gas limit used to resend the tx if it fails because of insufficient gas // it is used when the ballot is finalized and the inbound tx needs to be processed -func (b *ZetaCoreBridge) PostSend(gasLimit, retryGasLimit uint64, msg *types.MsgVoteOnObservedInboundTx) (string, string, error) { +func (b *ZetaCoreBridge) PostVoteInbound(gasLimit, retryGasLimit uint64, msg *types.MsgVoteOnObservedInboundTx) (string, string, error) { authzMsg, authzSigner, err := b.WrapMessageWithAuthz(msg) if err != nil { return "", "", err @@ -159,7 +159,7 @@ func (b *ZetaCoreBridge) PostSend(gasLimit, retryGasLimit uint64, msg *types.Msg ballotIndex := msg.Digest() hasVoted, err := b.HasVoted(ballotIndex, msg.Creator) if err != nil { - return "", ballotIndex, errors.Wrapf(err, "PostSend: unable to check if already voted for ballot %s voter %s", ballotIndex, msg.Creator) + return "", ballotIndex, errors.Wrapf(err, "PostVoteInbound: unable to check if already voted for ballot %s voter %s", ballotIndex, msg.Creator) } if hasVoted { return "", ballotIndex, nil @@ -173,13 +173,13 @@ func (b *ZetaCoreBridge) PostSend(gasLimit, retryGasLimit uint64, msg *types.Msg return zetaTxHash, ballotIndex, nil } - b.logger.Debug().Err(err).Msgf("PostSend broadcast fail | Retry count : %d", i+1) + b.logger.Debug().Err(err).Msgf("PostVoteInbound broadcast fail | Retry count : %d", i+1) time.Sleep(DefaultRetryInterval * time.Second) } return "", ballotIndex, fmt.Errorf("post send failed after %d retries", DefaultRetryInterval) } -func (b *ZetaCoreBridge) PostReceiveConfirmation( +func (b *ZetaCoreBridge) PostVoteOutbound( sendHash string, outTxHash string, outBlockHeight uint64, @@ -217,7 +217,7 @@ func (b *ZetaCoreBridge) PostReceiveConfirmation( ballotIndex := msg.Digest() hasVoted, err := b.HasVoted(ballotIndex, msg.Creator) if err != nil { - return "", ballotIndex, errors.Wrapf(err, "PostReceiveConfirmation: unable to check if already voted for ballot %s voter %s", ballotIndex, msg.Creator) + return "", ballotIndex, errors.Wrapf(err, "PostVoteOutbound: unable to check if already voted for ballot %s voter %s", ballotIndex, msg.Creator) } if hasVoted { return "", ballotIndex, nil @@ -225,9 +225,9 @@ func (b *ZetaCoreBridge) PostReceiveConfirmation( // FIXME: remove this gas limit stuff; in the special ante handler with no gas limit, add // NewMsgReceiveConfirmation to it. - var gasLimit uint64 = PostReceiveConfirmationGasLimit + var gasLimit uint64 = PostVoteOutboundGasLimit if status == common.ReceiveStatus_Failed { - gasLimit = PostSendExecutionGasLimit + gasLimit = PostVoteInboundExecutionGasLimit } for i := 0; i < DefaultRetryCount; i++ { zetaTxHash, err := b.Broadcast(gasLimit, authzMsg, authzSigner) @@ -236,7 +236,7 @@ func (b *ZetaCoreBridge) PostReceiveConfirmation( //go b.MonitorTxResult(zetaTxHash, true) return zetaTxHash, ballotIndex, nil } - b.logger.Debug().Err(err).Msgf("PostReceive broadcast fail | Retry count : %d", i+1) + b.logger.Debug().Err(err).Msgf("PostVoteOutbound broadcast fail | Retry count : %d", i+1) time.Sleep(DefaultRetryInterval * time.Second) } return "", ballotIndex, fmt.Errorf("post receive failed after %d retries", DefaultRetryCount) @@ -358,7 +358,7 @@ func (b *ZetaCoreBridge) MonitorVoteInboundTxResult(zetaTxHash string, retryGasL ) // resend the tx with more gas if retryGasLimit > 0 { - _, _, err := b.PostSend(retryGasLimit, 0, msg) + _, _, err := b.PostVoteInbound(retryGasLimit, 0, msg) if err != nil { b.logger.Error().Err(err).Msgf( "MonitorInboundTxResult: failed to resend tx, txHash: %s, log %s", diff --git a/zetaclient/voter_test.go b/zetaclient/voter_test.go index 5df01de806..853c17eea9 100644 --- a/zetaclient/voter_test.go +++ b/zetaclient/voter_test.go @@ -85,20 +85,20 @@ func (s *VoterSuite) SetUpTest(c *C) { func (s *VoterSuite) TestSendVoter(c *C) { b1 := s.bridge1 b2 := s.bridge2 - metaHash, err := b1.PostSend("0xfrom", "Ethereum", "0xfrom", "0xto", "BSC", "123456", "23245", "little message", + metaHash, err := b1.PostVoteInbound("0xfrom", "Ethereum", "0xfrom", "0xto", "BSC", "123456", "23245", "little message", "0xtxhash", 123123, "0xtoken") c.Assert(err, IsNil) - log.Info().Msgf("PostSend metaHash %s", metaHash) + log.Info().Msgf("PostVoteInbound metaHash %s", metaHash) // wait for the next block timer1 := time.NewTimer(2 * time.Second) <-timer1.C - metaHash, err = b2.PostSend("0xfrom", "Ethereum", "0xfrom", "0xto", "BSC", "123456", "23245", "little message", + metaHash, err = b2.PostVoteInbound("0xfrom", "Ethereum", "0xfrom", "0xto", "BSC", "123456", "23245", "little message", "0xtxhash", 123123, "0xtoken") c.Assert(err, IsNil) - log.Info().Msgf("Second PostSend metaHash %s", metaHash) + log.Info().Msgf("Second PostVoteInbound metaHash %s", metaHash) // wait for the next block timer2 := time.NewTimer(2 * time.Second) @@ -111,13 +111,13 @@ func (s *VoterSuite) TestSendVoter(c *C) { send := sends[0] - metaHash, err = b1.PostReceiveConfirmation(send.Index, "0xoutHash", 2123, "23245") + metaHash, err = b1.PostVoteOutbound(send.Index, "0xoutHash", 2123, "23245") c.Assert(err, IsNil) timer3 := time.NewTimer(2 * time.Second) <-timer3.C - metaHash, err = b2.PostReceiveConfirmation(send.Index, "0xoutHash", 2123, "23245") + metaHash, err = b2.PostVoteOutbound(send.Index, "0xoutHash", 2123, "23245") c.Assert(err, IsNil) receives, err := b2.GetAllReceive() diff --git a/zetaclient/zetacore_observer_test.go b/zetaclient/zetacore_observer_test.go index afa8114764..919450d1cb 100644 --- a/zetaclient/zetacore_observer_test.go +++ b/zetaclient/zetacore_observer_test.go @@ -117,18 +117,18 @@ func (s *COSuite) SetUpTest(c *C) { func (s *COSuite) TestSendFlow(c *C) { b1 := s.bridge1 b2 := s.bridge2 - metaHash, err := b1.PostSend(TEST_SENDER, "Ethereum", TEST_SENDER, TEST_RECEIVER, "BSC", "1337", "0", "treat or trick", + metaHash, err := b1.PostVoteInbound(TEST_SENDER, "Ethereum", TEST_SENDER, TEST_RECEIVER, "BSC", "1337", "0", "treat or trick", "0xtxhash", 123123, "0xtoken") c.Assert(err, IsNil) - c.Logf("PostSend metaHash %s", metaHash) + c.Logf("PostVoteInbound metaHash %s", metaHash) timer1 := time.NewTimer(2 * time.Second) <-timer1.C - metaHash, err = b2.PostSend(TEST_SENDER, "Ethereum", TEST_SENDER, TEST_RECEIVER, "BSC", "1337", "0", "treat or trick", + metaHash, err = b2.PostVoteInbound(TEST_SENDER, "Ethereum", TEST_SENDER, TEST_RECEIVER, "BSC", "1337", "0", "treat or trick", "0xtxhash", 123123, "0xtoken") c.Assert(err, IsNil) - c.Logf("Second PostSend metaHash %s", metaHash) + c.Logf("Second PostVoteInbound metaHash %s", metaHash) timer2 := time.NewTimer(2 * time.Second) <-timer2.C From dc0d347ed2a0b5abf1abd8d212a9e1cd6acfad33 Mon Sep 17 00:00:00 2001 From: lumtis Date: Tue, 16 Jan 2024 16:56:28 -0800 Subject: [PATCH 07/12] change log level and create constants --- zetaclient/tx.go | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/zetaclient/tx.go b/zetaclient/tx.go index 4f070aa26a..da8528995c 100644 --- a/zetaclient/tx.go +++ b/zetaclient/tx.go @@ -51,6 +51,12 @@ const ( // DefaultRetryInterval is the interval between retries in seconds DefaultRetryInterval = 5 + + // MonitorTxResultInterval is the interval between retries for monitoring tx result in seconds + MonitorTxResultInterval = 5 + + // MonitorTxResultRetryCount is the number of retries to fetch monitoring tx result + MonitorTxResultRetryCount = 10 ) // GetInBoundVoteMessage returns a new MsgVoteOnObservedInboundTx @@ -336,27 +342,29 @@ func (b *ZetaCoreBridge) PostAddBlockHeader(chainID int64, blockHash []byte, hei // if retryGasLimit is 0, the tx is not resent func (b *ZetaCoreBridge) MonitorVoteInboundTxResult(zetaTxHash string, retryGasLimit uint64, msg *types.MsgVoteOnObservedInboundTx) { var lastErr error - ticker := 5 * time.Second - retry := 10 - for i := 0; i < retry; i++ { - time.Sleep(ticker) + for i := 0; i < MonitorTxResultRetryCount; i++ { + time.Sleep(MonitorTxResultInterval * time.Second) + + // query tx result from ZetaChain txResult, err := b.QueryTxResult(zetaTxHash) + if err == nil { - // the inbound vote tx shouldn't fail to execute if strings.Contains(txResult.RawLog, "failed to execute message") { + // the inbound vote tx shouldn't fail to execute + // this shouldn't happen b.logger.Error().Msgf( "MonitorInboundTxResult: failed to execute vote, txHash: %s, log %s", zetaTxHash, txResult.RawLog, ) } else if strings.Contains(txResult.RawLog, "out of gas") { - b.logger.Error().Msgf( + // if the tx fails with out of gas error, resend the tx with more gas if retryGasLimit > 0 + b.logger.Debug().Msgf( "MonitorInboundTxResult: out of gas, txHash: %s, log %s", zetaTxHash, txResult.RawLog, ) - // resend the tx with more gas if retryGasLimit > 0 { _, _, err := b.PostVoteInbound(retryGasLimit, 0, msg) if err != nil { @@ -374,7 +382,7 @@ func (b *ZetaCoreBridge) MonitorVoteInboundTxResult(zetaTxHash string, retryGasL } } } else { - b.logger.Info().Msgf( + b.logger.Debug().Msgf( "MonitorInboundTxResult: successful txHash %s, log %s", zetaTxHash, txResult.RawLog, @@ -385,7 +393,7 @@ func (b *ZetaCoreBridge) MonitorVoteInboundTxResult(zetaTxHash string, retryGasL lastErr = err } - b.logger.Info().Err(lastErr).Msgf( + b.logger.Error().Err(lastErr).Msgf( "MonitorInboundTxResult: unable to query tx result for txHash %s, err %s", zetaTxHash, lastErr.Error(), From 329891f42a4291e389af5f24a07a2c4629512433 Mon Sep 17 00:00:00 2001 From: lumtis Date: Tue, 16 Jan 2024 16:57:55 -0800 Subject: [PATCH 08/12] increase retry value --- zetaclient/tx.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zetaclient/tx.go b/zetaclient/tx.go index da8528995c..c4c523219f 100644 --- a/zetaclient/tx.go +++ b/zetaclient/tx.go @@ -56,7 +56,7 @@ const ( MonitorTxResultInterval = 5 // MonitorTxResultRetryCount is the number of retries to fetch monitoring tx result - MonitorTxResultRetryCount = 10 + MonitorTxResultRetryCount = 20 ) // GetInBoundVoteMessage returns a new MsgVoteOnObservedInboundTx From 702bf0705594079e5d37f2a66426f84467549155 Mon Sep 17 00:00:00 2001 From: lumtis Date: Tue, 16 Jan 2024 17:12:46 -0800 Subject: [PATCH 09/12] test change gas limit for outbound --- zetaclient/tx.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/zetaclient/tx.go b/zetaclient/tx.go index c4c523219f..20cd51a499 100644 --- a/zetaclient/tx.go +++ b/zetaclient/tx.go @@ -232,14 +232,12 @@ func (b *ZetaCoreBridge) PostVoteOutbound( // FIXME: remove this gas limit stuff; in the special ante handler with no gas limit, add // NewMsgReceiveConfirmation to it. var gasLimit uint64 = PostVoteOutboundGasLimit - if status == common.ReceiveStatus_Failed { - gasLimit = PostVoteInboundExecutionGasLimit - } + //if status == common.ReceiveStatus_Failed { + // gasLimit = PostVoteInboundExecutionGasLimit + //} for i := 0; i < DefaultRetryCount; i++ { zetaTxHash, err := b.Broadcast(gasLimit, authzMsg, authzSigner) if err == nil { - //// monitor the result of the transaction - //go b.MonitorTxResult(zetaTxHash, true) return zetaTxHash, ballotIndex, nil } b.logger.Debug().Err(err).Msgf("PostVoteOutbound broadcast fail | Retry count : %d", i+1) From 81d8e4b6fa640090a44fcdab921a63d4871665a0 Mon Sep 17 00:00:00 2001 From: lumtis Date: Tue, 16 Jan 2024 18:12:37 -0800 Subject: [PATCH 10/12] refactor vote inbound outbound into separate files --- zetaclient/tx.go | 211 --------------------------------- zetaclient/tx_vote_inbound.go | 145 ++++++++++++++++++++++ zetaclient/tx_vote_outbound.go | 137 +++++++++++++++++++++ 3 files changed, 282 insertions(+), 211 deletions(-) create mode 100644 zetaclient/tx_vote_inbound.go create mode 100644 zetaclient/tx_vote_outbound.go diff --git a/zetaclient/tx.go b/zetaclient/tx.go index 20cd51a499..945b28245e 100644 --- a/zetaclient/tx.go +++ b/zetaclient/tx.go @@ -2,15 +2,10 @@ package zetaclient import ( "fmt" - "math/big" - "strings" "time" - "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/authz" - "github.com/pkg/errors" - "github.com/zeta-chain/go-tss/blame" "github.com/zeta-chain/zetacore/common" "github.com/zeta-chain/zetacore/x/crosschain/types" @@ -28,18 +23,6 @@ const ( // AddTxHashToOutTxTrackerGasLimit is the gas limit for adding tx hash to out tx tracker AddTxHashToOutTxTrackerGasLimit = 200_000 - // PostVoteInboundGasLimit is the gas limit for voting on observed inbound tx - PostVoteInboundGasLimit = 400_000 - - // PostVoteInboundExecutionGasLimit is the gas limit for voting on observed inbound tx and executing it - PostVoteInboundExecutionGasLimit = 4_000_000 - - // PostVoteInboundMessagePassingExecutionGasLimit is the gas limit for voting on, and executing ,observed inbound tx related to message passing (coin_type == zeta) - PostVoteInboundMessagePassingExecutionGasLimit = 1_000_000 - - // PostVoteOutboundGasLimit is the gas limit for voting on observed outbound tx - PostVoteOutboundGasLimit = 400_000 - // PostBlameDataGasLimit is the gas limit for voting on blames PostBlameDataGasLimit = 200_000 @@ -59,42 +42,6 @@ const ( MonitorTxResultRetryCount = 20 ) -// GetInBoundVoteMessage returns a new MsgVoteOnObservedInboundTx -func GetInBoundVoteMessage( - sender string, - senderChain int64, - txOrigin string, - receiver string, - receiverChain int64, - amount math.Uint, - message string, - inTxHash string, - inBlockHeight uint64, - gasLimit uint64, - coinType common.CoinType, - asset string, - signerAddress string, - eventIndex uint, -) *types.MsgVoteOnObservedInboundTx { - msg := types.NewMsgVoteOnObservedInboundTx( - signerAddress, - sender, - senderChain, - txOrigin, - receiver, - receiverChain, - amount, - message, - inTxHash, - inBlockHeight, - gasLimit, - coinType, - asset, - eventIndex, - ) - return msg -} - func (b *ZetaCoreBridge) WrapMessageWithAuthz(msg sdk.Msg) (sdk.Msg, AuthZSigner, error) { msgURL := sdk.MsgTypeURL(msg) @@ -152,100 +99,6 @@ func (b *ZetaCoreBridge) AddTxHashToOutTxTracker( return zetaTxHash, nil } -// PostVoteInbound posts a vote on an observed inbound tx -// retryGasLimit is the gas limit used to resend the tx if it fails because of insufficient gas -// it is used when the ballot is finalized and the inbound tx needs to be processed -func (b *ZetaCoreBridge) PostVoteInbound(gasLimit, retryGasLimit uint64, msg *types.MsgVoteOnObservedInboundTx) (string, string, error) { - authzMsg, authzSigner, err := b.WrapMessageWithAuthz(msg) - if err != nil { - return "", "", err - } - - // don't post send if has already voted before - ballotIndex := msg.Digest() - hasVoted, err := b.HasVoted(ballotIndex, msg.Creator) - if err != nil { - return "", ballotIndex, errors.Wrapf(err, "PostVoteInbound: unable to check if already voted for ballot %s voter %s", ballotIndex, msg.Creator) - } - if hasVoted { - return "", ballotIndex, nil - } - - for i := 0; i < DefaultRetryCount; i++ { - zetaTxHash, err := b.Broadcast(gasLimit, authzMsg, authzSigner) - if err == nil { - // monitor the result of the transaction - go b.MonitorVoteInboundTxResult(zetaTxHash, retryGasLimit, msg) - - return zetaTxHash, ballotIndex, nil - } - b.logger.Debug().Err(err).Msgf("PostVoteInbound broadcast fail | Retry count : %d", i+1) - time.Sleep(DefaultRetryInterval * time.Second) - } - return "", ballotIndex, fmt.Errorf("post send failed after %d retries", DefaultRetryInterval) -} - -func (b *ZetaCoreBridge) PostVoteOutbound( - sendHash string, - outTxHash string, - outBlockHeight uint64, - outTxGasUsed uint64, - outTxEffectiveGasPrice *big.Int, - outTxEffectiveGasLimit uint64, - amount *big.Int, - status common.ReceiveStatus, - chain common.Chain, - nonce uint64, - coinType common.CoinType, -) (string, string, error) { - signerAddress := b.keys.GetOperatorAddress().String() - msg := types.NewMsgVoteOnObservedOutboundTx( - signerAddress, - sendHash, - outTxHash, - outBlockHeight, - outTxGasUsed, - math.NewIntFromBigInt(outTxEffectiveGasPrice), - outTxEffectiveGasLimit, - math.NewUintFromBigInt(amount), - status, - chain.ChainId, - nonce, - coinType, - ) - - authzMsg, authzSigner, err := b.WrapMessageWithAuthz(msg) - if err != nil { - return "", "", err - } - - // don't post confirmation if has already voted before - ballotIndex := msg.Digest() - hasVoted, err := b.HasVoted(ballotIndex, msg.Creator) - if err != nil { - return "", ballotIndex, errors.Wrapf(err, "PostVoteOutbound: unable to check if already voted for ballot %s voter %s", ballotIndex, msg.Creator) - } - if hasVoted { - return "", ballotIndex, nil - } - - // FIXME: remove this gas limit stuff; in the special ante handler with no gas limit, add - // NewMsgReceiveConfirmation to it. - var gasLimit uint64 = PostVoteOutboundGasLimit - //if status == common.ReceiveStatus_Failed { - // gasLimit = PostVoteInboundExecutionGasLimit - //} - for i := 0; i < DefaultRetryCount; i++ { - zetaTxHash, err := b.Broadcast(gasLimit, authzMsg, authzSigner) - if err == nil { - return zetaTxHash, ballotIndex, nil - } - b.logger.Debug().Err(err).Msgf("PostVoteOutbound broadcast fail | Retry count : %d", i+1) - time.Sleep(DefaultRetryInterval * time.Second) - } - return "", ballotIndex, fmt.Errorf("post receive failed after %d retries", DefaultRetryCount) -} - func (b *ZetaCoreBridge) SetTSS(tssPubkey string, keyGenZetaHeight int64, status common.ReceiveStatus) (string, error) { signerAddress := b.keys.GetOperatorAddress().String() msg := types.NewMsgCreateTSSVoter(signerAddress, tssPubkey, keyGenZetaHeight, status) @@ -334,67 +187,3 @@ func (b *ZetaCoreBridge) PostAddBlockHeader(chainID int64, blockHash []byte, hei } return "", fmt.Errorf("post add block header failed after %d retries", DefaultRetryCount) } - -// MonitorVoteInboundTxResult monitors the result of a tx (used for inbound and outbound vote txs) -// retryGasLimit is the gas limit used to resend the tx if it fails because of insufficient gas -// if retryGasLimit is 0, the tx is not resent -func (b *ZetaCoreBridge) MonitorVoteInboundTxResult(zetaTxHash string, retryGasLimit uint64, msg *types.MsgVoteOnObservedInboundTx) { - var lastErr error - - for i := 0; i < MonitorTxResultRetryCount; i++ { - time.Sleep(MonitorTxResultInterval * time.Second) - - // query tx result from ZetaChain - txResult, err := b.QueryTxResult(zetaTxHash) - - if err == nil { - if strings.Contains(txResult.RawLog, "failed to execute message") { - // the inbound vote tx shouldn't fail to execute - // this shouldn't happen - b.logger.Error().Msgf( - "MonitorInboundTxResult: failed to execute vote, txHash: %s, log %s", - zetaTxHash, - txResult.RawLog, - ) - } else if strings.Contains(txResult.RawLog, "out of gas") { - // if the tx fails with out of gas error, resend the tx with more gas if retryGasLimit > 0 - b.logger.Debug().Msgf( - "MonitorInboundTxResult: out of gas, txHash: %s, log %s", - zetaTxHash, - txResult.RawLog, - ) - if retryGasLimit > 0 { - _, _, err := b.PostVoteInbound(retryGasLimit, 0, msg) - if err != nil { - b.logger.Error().Err(err).Msgf( - "MonitorInboundTxResult: failed to resend tx, txHash: %s, log %s", - zetaTxHash, - txResult.RawLog, - ) - } else { - b.logger.Info().Msgf( - "MonitorInboundTxResult: successfully resent tx, txHash: %s, log %s", - zetaTxHash, - txResult.RawLog, - ) - } - } - } else { - b.logger.Debug().Msgf( - "MonitorInboundTxResult: successful txHash %s, log %s", - zetaTxHash, - txResult.RawLog, - ) - } - return - } - lastErr = err - } - - b.logger.Error().Err(lastErr).Msgf( - "MonitorInboundTxResult: unable to query tx result for txHash %s, err %s", - zetaTxHash, - lastErr.Error(), - ) - return -} diff --git a/zetaclient/tx_vote_inbound.go b/zetaclient/tx_vote_inbound.go new file mode 100644 index 0000000000..bbdeec2640 --- /dev/null +++ b/zetaclient/tx_vote_inbound.go @@ -0,0 +1,145 @@ +package zetaclient + +import ( + "cosmossdk.io/math" + "fmt" + "github.com/zeta-chain/zetacore/common" + "strings" + "time" + + "github.com/pkg/errors" + + "github.com/zeta-chain/zetacore/x/crosschain/types" +) + +const ( + // PostVoteInboundGasLimit is the gas limit for voting on observed inbound tx + PostVoteInboundGasLimit = 400_000 + + // PostVoteInboundExecutionGasLimit is the gas limit for voting on observed inbound tx and executing it + PostVoteInboundExecutionGasLimit = 4_000_000 + + // PostVoteInboundMessagePassingExecutionGasLimit is the gas limit for voting on, and executing ,observed inbound tx related to message passing (coin_type == zeta) + PostVoteInboundMessagePassingExecutionGasLimit = 1_000_000 +) + +// GetInBoundVoteMessage returns a new MsgVoteOnObservedInboundTx +func GetInBoundVoteMessage( + sender string, + senderChain int64, + txOrigin string, + receiver string, + receiverChain int64, + amount math.Uint, + message string, + inTxHash string, + inBlockHeight uint64, + gasLimit uint64, + coinType common.CoinType, + asset string, + signerAddress string, + eventIndex uint, +) *types.MsgVoteOnObservedInboundTx { + msg := types.NewMsgVoteOnObservedInboundTx( + signerAddress, + sender, + senderChain, + txOrigin, + receiver, + receiverChain, + amount, + message, + inTxHash, + inBlockHeight, + gasLimit, + coinType, + asset, + eventIndex, + ) + return msg +} + +// PostVoteInbound posts a vote on an observed inbound tx +// retryGasLimit is the gas limit used to resend the tx if it fails because of insufficient gas +// it is used when the ballot is finalized and the inbound tx needs to be processed +func (b *ZetaCoreBridge) PostVoteInbound(gasLimit, retryGasLimit uint64, msg *types.MsgVoteOnObservedInboundTx) (string, string, error) { + authzMsg, authzSigner, err := b.WrapMessageWithAuthz(msg) + if err != nil { + return "", "", err + } + + // don't post send if has already voted before + ballotIndex := msg.Digest() + hasVoted, err := b.HasVoted(ballotIndex, msg.Creator) + if err != nil { + return "", ballotIndex, errors.Wrapf(err, "PostVoteInbound: unable to check if already voted for ballot %s voter %s", ballotIndex, msg.Creator) + } + if hasVoted { + return "", ballotIndex, nil + } + + for i := 0; i < DefaultRetryCount; i++ { + zetaTxHash, err := b.Broadcast(gasLimit, authzMsg, authzSigner) + if err == nil { + // monitor the result of the transaction + go b.MonitorVoteInboundTxResult(zetaTxHash, retryGasLimit, msg) + + return zetaTxHash, ballotIndex, nil + } + b.logger.Debug().Err(err).Msgf("PostVoteInbound broadcast fail | Retry count : %d", i+1) + time.Sleep(DefaultRetryInterval * time.Second) + } + return "", ballotIndex, fmt.Errorf("post send failed after %d retries", DefaultRetryInterval) +} + +// MonitorVoteInboundTxResult monitors the result of a vote inbound tx +// retryGasLimit is the gas limit used to resend the tx if it fails because of insufficient gas +// if retryGasLimit is 0, the tx is not resent +func (b *ZetaCoreBridge) MonitorVoteInboundTxResult(zetaTxHash string, retryGasLimit uint64, msg *types.MsgVoteOnObservedInboundTx) { + var lastErr error + + for i := 0; i < MonitorTxResultRetryCount; i++ { + time.Sleep(MonitorTxResultInterval * time.Second) + + // query tx result from ZetaChain + txResult, err := b.QueryTxResult(zetaTxHash) + + if err == nil { + if strings.Contains(txResult.RawLog, "failed to execute message") { + // the inbound vote tx shouldn't fail to execute + // this shouldn't happen + b.logger.Error().Msgf( + "MonitorInboundTxResult: failed to execute vote, txHash: %s, log %s", zetaTxHash, txResult.RawLog, + ) + } else if strings.Contains(txResult.RawLog, "out of gas") { + // if the tx fails with out of gas error, resend the tx with more gas if retryGasLimit > 0 + b.logger.Debug().Msgf( + "MonitorInboundTxResult: out of gas, txHash: %s, log %s", zetaTxHash, txResult.RawLog, + ) + if retryGasLimit > 0 { + _, _, err := b.PostVoteInbound(retryGasLimit, 0, msg) + if err != nil { + b.logger.Error().Err(err).Msgf( + "MonitorInboundTxResult: failed to resend tx, txHash: %s, log %s", zetaTxHash, txResult.RawLog, + ) + } else { + b.logger.Info().Msgf( + "MonitorInboundTxResult: successfully resent tx, txHash: %s, log %s", zetaTxHash, txResult.RawLog, + ) + } + } + } else { + b.logger.Debug().Msgf( + "MonitorInboundTxResult: successful txHash %s, log %s", zetaTxHash, txResult.RawLog, + ) + } + return + } + lastErr = err + } + + b.logger.Error().Err(lastErr).Msgf( + "MonitorInboundTxResult: unable to query tx result for txHash %s, err %s", zetaTxHash, lastErr.Error(), + ) + return +} diff --git a/zetaclient/tx_vote_outbound.go b/zetaclient/tx_vote_outbound.go new file mode 100644 index 0000000000..03a6446f6e --- /dev/null +++ b/zetaclient/tx_vote_outbound.go @@ -0,0 +1,137 @@ +package zetaclient + +import ( + "cosmossdk.io/math" + "fmt" + "github.com/pkg/errors" + "github.com/zeta-chain/zetacore/common" + "github.com/zeta-chain/zetacore/x/crosschain/types" + "math/big" + "time" +) + +const ( + // PostVoteOutboundGasLimit is the gas limit for voting on observed outbound tx + PostVoteOutboundGasLimit = 400_000 + + // PostVoteOutboundRevertGasLimit is the gas limit for voting on observed outbound tx for revert + // The value needs to be higher because reverting implies interacting with the EVM to perform swaps for the gas token + PostVoteOutboundRevertGasLimit = 1_500_000 +) + +// PostVoteOutbound posts a vote on an observed outbound tx +func (b *ZetaCoreBridge) PostVoteOutbound( + sendHash string, + outTxHash string, + outBlockHeight uint64, + outTxGasUsed uint64, + outTxEffectiveGasPrice *big.Int, + outTxEffectiveGasLimit uint64, + amount *big.Int, + status common.ReceiveStatus, + chain common.Chain, + nonce uint64, + coinType common.CoinType, +) (string, string, error) { + signerAddress := b.keys.GetOperatorAddress().String() + msg := types.NewMsgVoteOnObservedOutboundTx( + signerAddress, + sendHash, + outTxHash, + outBlockHeight, + outTxGasUsed, + math.NewIntFromBigInt(outTxEffectiveGasPrice), + outTxEffectiveGasLimit, + math.NewUintFromBigInt(amount), + status, + chain.ChainId, + nonce, + coinType, + ) + + return b.PostVoteOutboundFromMsg(msg) +} + +// PostVoteOutboundFromMsg posts a vote on an observed outbound tx from a MsgVoteOnObservedOutboundTx +func (b *ZetaCoreBridge) PostVoteOutboundFromMsg(msg *types.MsgVoteOnObservedOutboundTx) (string, string, error) { + authzMsg, authzSigner, err := b.WrapMessageWithAuthz(msg) + if err != nil { + return "", "", err + } + + // don't post confirmation if has already voted before + ballotIndex := msg.Digest() + hasVoted, err := b.HasVoted(ballotIndex, msg.Creator) + if err != nil { + return "", ballotIndex, errors.Wrapf(err, "PostVoteOutbound: unable to check if already voted for ballot %s voter %s", ballotIndex, msg.Creator) + } + if hasVoted { + return "", ballotIndex, nil + } + + var gasLimit uint64 = PostVoteOutboundGasLimit + if msg.Status == common.ReceiveStatus_Failed { + gasLimit = PostVoteOutboundRevertGasLimit + } + for i := 0; i < DefaultRetryCount; i++ { + zetaTxHash, err := b.Broadcast(gasLimit, authzMsg, authzSigner) + if err == nil { + return zetaTxHash, ballotIndex, nil + } + b.logger.Debug().Err(err).Msgf("PostVoteOutbound broadcast fail | Retry count : %d", i+1) + time.Sleep(DefaultRetryInterval * time.Second) + } + return "", ballotIndex, fmt.Errorf("post receive failed after %d retries", DefaultRetryCount) +} + +//// MonitorVoteOutboundTxResult monitors the result of a vote outbound tx +//// retryGasLimit is the gas limit used to resend the tx if it fails because of insufficient gas +//// if retryGasLimit is 0, the tx is not resent +//func (b *ZetaCoreBridge) MonitorVoteOutboundTxResult(zetaTxHash string, retryGasLimit uint64, msg *types.MsgVoteOnObservedOutboundTx) { +// var lastErr error +// +// for i := 0; i < MonitorTxResultRetryCount; i++ { +// time.Sleep(MonitorTxResultInterval * time.Second) +// +// // query tx result from ZetaChain +// txResult, err := b.QueryTxResult(zetaTxHash) +// +// if err == nil { +// if strings.Contains(txResult.RawLog, "failed to execute message") { +// // the inbound vote tx shouldn't fail to execute +// // this shouldn't happen +// b.logger.Error().Msgf( +// "MonitorInboundTxResult: failed to execute vote, txHash: %s, log %s", zetaTxHash, txResult.RawLog, +// ) +// } else if strings.Contains(txResult.RawLog, "out of gas") { +// // if the tx fails with out of gas error, resend the tx with more gas if retryGasLimit > 0 +// b.logger.Debug().Msgf( +// "MonitorInboundTxResult: out of gas, txHash: %s, log %s", zetaTxHash, txResult.RawLog, +// ) +// if retryGasLimit > 0 { +// _, _, err := b.PostVoteInbound(retryGasLimit, 0, msg) +// if err != nil { +// b.logger.Error().Err(err).Msgf( +// "MonitorInboundTxResult: failed to resend tx, txHash: %s, log %s", zetaTxHash, txResult.RawLog, +// ) +// } else { +// b.logger.Info().Msgf( +// "MonitorInboundTxResult: successfully resent tx, txHash: %s, log %s", zetaTxHash, txResult.RawLog, +// ) +// } +// } +// } else { +// b.logger.Debug().Msgf( +// "MonitorInboundTxResult: successful txHash %s, log %s", zetaTxHash, txResult.RawLog, +// ) +// } +// return +// } +// lastErr = err +// } +// +// b.logger.Error().Err(lastErr).Msgf( +// "MonitorInboundTxResult: unable to query tx result for txHash %s, err %s", zetaTxHash, lastErr.Error(), +// ) +// return +//} From ea97afa585b1957182a55133ee6f6c513dd11226 Mon Sep 17 00:00:00 2001 From: lumtis Date: Tue, 16 Jan 2024 18:39:01 -0800 Subject: [PATCH 11/12] add monitoring capability for outbound txs --- zetaclient/tx.go | 6 -- zetaclient/tx_vote_inbound.go | 20 +++-- zetaclient/tx_vote_outbound.go | 141 ++++++++++++++++++--------------- 3 files changed, 93 insertions(+), 74 deletions(-) diff --git a/zetaclient/tx.go b/zetaclient/tx.go index 945b28245e..15847c3f80 100644 --- a/zetaclient/tx.go +++ b/zetaclient/tx.go @@ -34,12 +34,6 @@ const ( // DefaultRetryInterval is the interval between retries in seconds DefaultRetryInterval = 5 - - // MonitorTxResultInterval is the interval between retries for monitoring tx result in seconds - MonitorTxResultInterval = 5 - - // MonitorTxResultRetryCount is the number of retries to fetch monitoring tx result - MonitorTxResultRetryCount = 20 ) func (b *ZetaCoreBridge) WrapMessageWithAuthz(msg sdk.Msg) (sdk.Msg, AuthZSigner, error) { diff --git a/zetaclient/tx_vote_inbound.go b/zetaclient/tx_vote_inbound.go index bbdeec2640..1e5807474f 100644 --- a/zetaclient/tx_vote_inbound.go +++ b/zetaclient/tx_vote_inbound.go @@ -1,12 +1,13 @@ package zetaclient import ( - "cosmossdk.io/math" "fmt" - "github.com/zeta-chain/zetacore/common" "strings" "time" + "cosmossdk.io/math" + "github.com/zeta-chain/zetacore/common" + "github.com/pkg/errors" "github.com/zeta-chain/zetacore/x/crosschain/types" @@ -21,6 +22,12 @@ const ( // PostVoteInboundMessagePassingExecutionGasLimit is the gas limit for voting on, and executing ,observed inbound tx related to message passing (coin_type == zeta) PostVoteInboundMessagePassingExecutionGasLimit = 1_000_000 + + // MonitorVoteInboundTxResultInterval is the interval between retries for monitoring tx result in seconds + MonitorVoteInboundTxResultInterval = 5 + + // MonitorVoteInboundTxResultRetryCount is the number of retries to fetch monitoring tx result + MonitorVoteInboundTxResultRetryCount = 20 ) // GetInBoundVoteMessage returns a new MsgVoteOnObservedInboundTx @@ -81,7 +88,7 @@ func (b *ZetaCoreBridge) PostVoteInbound(gasLimit, retryGasLimit uint64, msg *ty for i := 0; i < DefaultRetryCount; i++ { zetaTxHash, err := b.Broadcast(gasLimit, authzMsg, authzSigner) if err == nil { - // monitor the result of the transaction + // monitor the result of the transaction and resend if necessary go b.MonitorVoteInboundTxResult(zetaTxHash, retryGasLimit, msg) return zetaTxHash, ballotIndex, nil @@ -98,8 +105,8 @@ func (b *ZetaCoreBridge) PostVoteInbound(gasLimit, retryGasLimit uint64, msg *ty func (b *ZetaCoreBridge) MonitorVoteInboundTxResult(zetaTxHash string, retryGasLimit uint64, msg *types.MsgVoteOnObservedInboundTx) { var lastErr error - for i := 0; i < MonitorTxResultRetryCount; i++ { - time.Sleep(MonitorTxResultInterval * time.Second) + for i := 0; i < MonitorVoteInboundTxResultRetryCount; i++ { + time.Sleep(MonitorVoteInboundTxResultInterval * time.Second) // query tx result from ZetaChain txResult, err := b.QueryTxResult(zetaTxHash) @@ -112,11 +119,12 @@ func (b *ZetaCoreBridge) MonitorVoteInboundTxResult(zetaTxHash string, retryGasL "MonitorInboundTxResult: failed to execute vote, txHash: %s, log %s", zetaTxHash, txResult.RawLog, ) } else if strings.Contains(txResult.RawLog, "out of gas") { - // if the tx fails with out of gas error, resend the tx with more gas if retryGasLimit > 0 + // if the tx fails with an out of gas error, resend the tx with more gas if retryGasLimit > 0 b.logger.Debug().Msgf( "MonitorInboundTxResult: out of gas, txHash: %s, log %s", zetaTxHash, txResult.RawLog, ) if retryGasLimit > 0 { + // new retryGasLimit set to 0 to prevent reentering this function _, _, err := b.PostVoteInbound(retryGasLimit, 0, msg) if err != nil { b.logger.Error().Err(err).Msgf( diff --git a/zetaclient/tx_vote_outbound.go b/zetaclient/tx_vote_outbound.go index 03a6446f6e..bcf79c69f6 100644 --- a/zetaclient/tx_vote_outbound.go +++ b/zetaclient/tx_vote_outbound.go @@ -1,22 +1,30 @@ package zetaclient import ( - "cosmossdk.io/math" "fmt" + "math/big" + "strings" + "time" + + "cosmossdk.io/math" "github.com/pkg/errors" "github.com/zeta-chain/zetacore/common" "github.com/zeta-chain/zetacore/x/crosschain/types" - "math/big" - "time" ) const ( // PostVoteOutboundGasLimit is the gas limit for voting on observed outbound tx PostVoteOutboundGasLimit = 400_000 - // PostVoteOutboundRevertGasLimit is the gas limit for voting on observed outbound tx for revert + // PostVoteOutboundRevertGasLimit is the gas limit for voting on observed outbound tx for revert (when outbound fails) // The value needs to be higher because reverting implies interacting with the EVM to perform swaps for the gas token PostVoteOutboundRevertGasLimit = 1_500_000 + + // MonitorVoteOutboundTxResultInterval is the interval between retries for monitoring tx result in seconds + MonitorVoteOutboundTxResultInterval = 5 + + // MonitorVoteOutboundTxResultRetryCount is the number of retries to fetch monitoring tx result + MonitorVoteOutboundTxResultRetryCount = 20 ) // PostVoteOutbound posts a vote on an observed outbound tx @@ -49,11 +57,20 @@ func (b *ZetaCoreBridge) PostVoteOutbound( coinType, ) - return b.PostVoteOutboundFromMsg(msg) + // when an outbound fails and a revert is required, the gas limit needs to be higher + // this is because the revert tx needs to interact with the EVM to perform swaps for the gas token + // the higher gas limit is only necessary when the vote is finalized and the outbound is processed + // therefore we use a retryGasLimit with a higher value to resend the tx if it fails (when the vote is finalized) + retryGasLimit := uint64(0) + if msg.Status == common.ReceiveStatus_Failed { + retryGasLimit = PostVoteOutboundRevertGasLimit + } + + return b.PostVoteOutboundFromMsg(PostVoteOutboundGasLimit, retryGasLimit, msg) } // PostVoteOutboundFromMsg posts a vote on an observed outbound tx from a MsgVoteOnObservedOutboundTx -func (b *ZetaCoreBridge) PostVoteOutboundFromMsg(msg *types.MsgVoteOnObservedOutboundTx) (string, string, error) { +func (b *ZetaCoreBridge) PostVoteOutboundFromMsg(gasLimit, retryGasLimit uint64, msg *types.MsgVoteOnObservedOutboundTx) (string, string, error) { authzMsg, authzSigner, err := b.WrapMessageWithAuthz(msg) if err != nil { return "", "", err @@ -68,14 +85,12 @@ func (b *ZetaCoreBridge) PostVoteOutboundFromMsg(msg *types.MsgVoteOnObservedOut if hasVoted { return "", ballotIndex, nil } - - var gasLimit uint64 = PostVoteOutboundGasLimit - if msg.Status == common.ReceiveStatus_Failed { - gasLimit = PostVoteOutboundRevertGasLimit - } for i := 0; i < DefaultRetryCount; i++ { zetaTxHash, err := b.Broadcast(gasLimit, authzMsg, authzSigner) if err == nil { + // monitor the result of the transaction and resend if necessary + go b.MonitorVoteOutboundTxResult(zetaTxHash, retryGasLimit, msg) + return zetaTxHash, ballotIndex, nil } b.logger.Debug().Err(err).Msgf("PostVoteOutbound broadcast fail | Retry count : %d", i+1) @@ -84,54 +99,56 @@ func (b *ZetaCoreBridge) PostVoteOutboundFromMsg(msg *types.MsgVoteOnObservedOut return "", ballotIndex, fmt.Errorf("post receive failed after %d retries", DefaultRetryCount) } -//// MonitorVoteOutboundTxResult monitors the result of a vote outbound tx -//// retryGasLimit is the gas limit used to resend the tx if it fails because of insufficient gas -//// if retryGasLimit is 0, the tx is not resent -//func (b *ZetaCoreBridge) MonitorVoteOutboundTxResult(zetaTxHash string, retryGasLimit uint64, msg *types.MsgVoteOnObservedOutboundTx) { -// var lastErr error -// -// for i := 0; i < MonitorTxResultRetryCount; i++ { -// time.Sleep(MonitorTxResultInterval * time.Second) -// -// // query tx result from ZetaChain -// txResult, err := b.QueryTxResult(zetaTxHash) -// -// if err == nil { -// if strings.Contains(txResult.RawLog, "failed to execute message") { -// // the inbound vote tx shouldn't fail to execute -// // this shouldn't happen -// b.logger.Error().Msgf( -// "MonitorInboundTxResult: failed to execute vote, txHash: %s, log %s", zetaTxHash, txResult.RawLog, -// ) -// } else if strings.Contains(txResult.RawLog, "out of gas") { -// // if the tx fails with out of gas error, resend the tx with more gas if retryGasLimit > 0 -// b.logger.Debug().Msgf( -// "MonitorInboundTxResult: out of gas, txHash: %s, log %s", zetaTxHash, txResult.RawLog, -// ) -// if retryGasLimit > 0 { -// _, _, err := b.PostVoteInbound(retryGasLimit, 0, msg) -// if err != nil { -// b.logger.Error().Err(err).Msgf( -// "MonitorInboundTxResult: failed to resend tx, txHash: %s, log %s", zetaTxHash, txResult.RawLog, -// ) -// } else { -// b.logger.Info().Msgf( -// "MonitorInboundTxResult: successfully resent tx, txHash: %s, log %s", zetaTxHash, txResult.RawLog, -// ) -// } -// } -// } else { -// b.logger.Debug().Msgf( -// "MonitorInboundTxResult: successful txHash %s, log %s", zetaTxHash, txResult.RawLog, -// ) -// } -// return -// } -// lastErr = err -// } -// -// b.logger.Error().Err(lastErr).Msgf( -// "MonitorInboundTxResult: unable to query tx result for txHash %s, err %s", zetaTxHash, lastErr.Error(), -// ) -// return -//} +// MonitorVoteOutboundTxResult monitors the result of a vote outbound tx +// retryGasLimit is the gas limit used to resend the tx if it fails because of insufficient gas +// if retryGasLimit is 0, the tx is not resent +func (b *ZetaCoreBridge) MonitorVoteOutboundTxResult(zetaTxHash string, retryGasLimit uint64, msg *types.MsgVoteOnObservedOutboundTx) { + var lastErr error + + for i := 0; i < MonitorVoteOutboundTxResultRetryCount; i++ { + time.Sleep(MonitorVoteOutboundTxResultInterval * time.Second) + + // query tx result from ZetaChain + txResult, err := b.QueryTxResult(zetaTxHash) + + if err == nil { + if strings.Contains(txResult.RawLog, "failed to execute message") { + // the inbound vote tx shouldn't fail to execute + // this shouldn't happen + b.logger.Error().Msgf( + "MonitorVoteOutboundTxResult: failed to execute vote, txHash: %s, log %s", zetaTxHash, txResult.RawLog, + ) + } else if strings.Contains(txResult.RawLog, "out of gas") { + // if the tx fails with an out of gas error, resend the tx with more gas if retryGasLimit > 0 + b.logger.Debug().Msgf( + "MonitorVoteOutboundTxResult: out of gas, txHash: %s, log %s", zetaTxHash, txResult.RawLog, + ) + if retryGasLimit > 0 { + // new retryGasLimit set to 0 to prevent reentering this function + _, _, err := b.PostVoteOutboundFromMsg(retryGasLimit, 0, msg) + + if err != nil { + b.logger.Error().Err(err).Msgf( + "MonitorVoteOutboundTxResult: failed to resend tx, txHash: %s, log %s", zetaTxHash, txResult.RawLog, + ) + } else { + b.logger.Info().Msgf( + "MonitorVoteOutboundTxResult: successfully resent tx, txHash: %s, log %s", zetaTxHash, txResult.RawLog, + ) + } + } + } else { + b.logger.Debug().Msgf( + "MonitorVoteOutboundTxResult: successful txHash %s, log %s", zetaTxHash, txResult.RawLog, + ) + } + return + } + lastErr = err + } + + b.logger.Error().Err(lastErr).Msgf( + "MonitorVoteOutboundTxResult: unable to query tx result for txHash %s, err %s", zetaTxHash, lastErr.Error(), + ) + return +} From bb6a45cfff271c2de20bd1ec060d6c4fb4f71fda Mon Sep 17 00:00:00 2001 From: lumtis Date: Tue, 16 Jan 2024 18:40:52 -0800 Subject: [PATCH 12/12] changelog --- changelog.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/changelog.md b/changelog.md index 56dd363d05..67f62a348a 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,10 @@ ## Unreleased +### Features + +* [1591](https://github.com/zeta-chain/node/pull/1591) - support lower gas limit for voting on inbound and outbound transactions + ## Version: v12.0.0 ### Breaking Changes