Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: evm signer - tryprocessout #1809

Merged
merged 29 commits into from
Mar 7, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
b2bd171
initial commit
kevinssgh Feb 23, 2024
c1aa5f7
fix lint errors
kevinssgh Feb 23, 2024
da6a663
Merge branch 'develop' into refactor-tryprocessout
kevinssgh Feb 26, 2024
2bcb9ba
add changelog entry
kevinssgh Feb 26, 2024
11ef7c5
fix e2e test case
kevinssgh Feb 26, 2024
92f5e8f
merge develop
kevinssgh Feb 26, 2024
2a440b8
merge develop
kevinssgh Feb 26, 2024
32e218d
update mocks and test files
kevinssgh Feb 28, 2024
53e87b9
fix tryprocessout test case
kevinssgh Feb 29, 2024
95b7f2f
complete evm_signer test cases and remove hardcoded private key
kevinssgh Feb 29, 2024
9715ef2
make generate and lint
kevinssgh Feb 29, 2024
1fe018f
Merge branch 'develop' into refactor-tryprocessout
kevinssgh Feb 29, 2024
6cfd6e9
print error in mock tss signer
kevinssgh Feb 29, 2024
3b8ce2a
integrate develop changes and fix test cases
kevinssgh Feb 29, 2024
68fff48
ran go imports
kevinssgh Feb 29, 2024
aca80ad
addressed comments
kevinssgh Mar 1, 2024
fd2e812
fix e2e test
kevinssgh Mar 1, 2024
51bfa74
addressed more comments
kevinssgh Mar 4, 2024
e69928e
Merge branch 'develop' into refactor-tryprocessout
kevinssgh Mar 4, 2024
8ab5ef0
fix unit tests
kevinssgh Mar 4, 2024
2401f3d
address comments
kevinssgh Mar 5, 2024
4289771
Merge branch 'develop' into refactor-tryprocessout
kevinssgh Mar 5, 2024
f8f83c5
renamed file
kevinssgh Mar 5, 2024
d1f1430
added test cases and converted SetTransactionData into constructor
kevinssgh Mar 6, 2024
908bc52
update comments
kevinssgh Mar 6, 2024
8b07017
Merge branch 'develop' into refactor-tryprocessout
kevinssgh Mar 6, 2024
a05f46d
add unit test
kevinssgh Mar 6, 2024
322ac2d
add more unit tests
kevinssgh Mar 6, 2024
b2fe4d3
Merge branch 'develop' into refactor-tryprocessout
kevinssgh Mar 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
* [1766](https://github.com/zeta-chain/node/pull/1766) - Refactors the `PostTxProcessing` EVM hook functionality to deal with invalid withdraw events
* [1630](https://github.com/zeta-chain/node/pull/1630) - added password prompts for hotkey and tss keyshare in zetaclient
* [1760](https://github.com/zeta-chain/node/pull/1760) - Make staking keeper private in crosschain module
* [1809](https://github.com/zeta-chain/node/pull/1809) - Refactored tryprocessout function in evm signer

### Fixes

Expand Down
5 changes: 3 additions & 2 deletions zetaclient/bitcoin/bitcoin_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@ import (
crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types"
observertypes "github.com/zeta-chain/zetacore/x/observer/types"
"github.com/zeta-chain/zetacore/zetaclient/testutils"
"github.com/zeta-chain/zetacore/zetaclient/testutils/stub"
)

func MockBTCClientMainnet() *BTCChainClient {
return &BTCChainClient{
chain: common.BtcMainnetChain(),
zetaClient: testutils.MockCoreBridge(),
Tss: testutils.NewMockTSSMainnet(),
zetaClient: stub.NewZetaCoreBridge(),
Tss: stub.NewTSSMainnet(),
}
}

Expand Down
3 changes: 2 additions & 1 deletion zetaclient/config/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ type Config struct {

func NewConfig() *Config {
return &Config{
cfgLock: &sync.RWMutex{},
cfgLock: &sync.RWMutex{},
EVMChainConfigs: make(map[int64]*EVMConfig),
}
}

Expand Down
187 changes: 187 additions & 0 deletions zetaclient/evm/base_transaction_data.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
package evm
kevinssgh marked this conversation as resolved.
Show resolved Hide resolved

import (
"context"
"encoding/base64"
"encoding/hex"
"errors"
"fmt"
"math/big"

ethcommon "github.com/ethereum/go-ethereum/common"
"github.com/rs/zerolog"
"github.com/zeta-chain/zetacore/common"
"github.com/zeta-chain/zetacore/x/crosschain/types"
"github.com/zeta-chain/zetacore/zetaclient/interfaces"
)

const (
MinGasLimit = 100_000
MaxGasLimit = 1_000_000
)

// BaseTransactionData is a data structure containing input fields used to construct each type of transaction.
// This is populated using cctx and other input parameters passed to TryProcessOutTx
type BaseTransactionData struct {
kevinssgh marked this conversation as resolved.
Show resolved Hide resolved
srcChainID *big.Int
toChainID *big.Int
sender ethcommon.Address
to ethcommon.Address
asset ethcommon.Address
amount *big.Int
gasPrice *big.Int
gasLimit uint64
message []byte
nonce uint64
height uint64

// cmd field is used to determine whether to execute ERC20 whitelist or migrate TSS funds given that the coin type
// from the cctx is CMD
cmd string

// params field is used to pass input parameters for command requests, currently it is used to pass the ERC20
// contract address when a whitelist command is requested
params string
kevinssgh marked this conversation as resolved.
Show resolved Hide resolved

// sendHash field is the inbound message digest that is sent to the destination contract
sendHash [32]byte

// outboundParams field contains data detailing the receiver chain and outbound transaction
outboundParams *types.OutboundTxParams
}

// SetChainAndSender populates the destination address and Chain ID based on the status of the cross chain tx
// returns true if transaction should be skipped
// returns false otherwise
func (txData *BaseTransactionData) SetChainAndSender(cctx *types.CrossChainTx, logger zerolog.Logger) bool {
switch cctx.CctxStatus.Status {
case types.CctxStatus_PendingRevert:
txData.to = ethcommon.HexToAddress(cctx.InboundTxParams.Sender)
txData.toChainID = big.NewInt(cctx.InboundTxParams.SenderChainId)
logger.Info().Msgf("Abort: reverting inbound")
case types.CctxStatus_PendingOutbound:
txData.to = ethcommon.HexToAddress(cctx.GetCurrentOutTxParam().Receiver)
txData.toChainID = big.NewInt(cctx.GetCurrentOutTxParam().ReceiverChainId)
default:
logger.Info().Msgf("Transaction doesn't need to be processed status: %d", cctx.CctxStatus.Status)
return true
}
return false
}

// SetupGas sets the gas limit and price
func (txData *BaseTransactionData) SetupGas(
cctx *types.CrossChainTx,
logger zerolog.Logger,
client interfaces.EVMRPCClient,
chain *common.Chain,
kevinssgh marked this conversation as resolved.
Show resolved Hide resolved
) error {

txData.gasLimit = cctx.GetCurrentOutTxParam().OutboundTxGasLimit
if txData.gasLimit < MinGasLimit {
txData.gasLimit = MinGasLimit
logger.Warn().Msgf("gasLimit %d is too low; set to %d", cctx.GetCurrentOutTxParam().OutboundTxGasLimit, txData.gasLimit)
}
if txData.gasLimit > MaxGasLimit {
txData.gasLimit = MaxGasLimit
logger.Warn().Msgf("gasLimit %d is too high; set to %d", cctx.GetCurrentOutTxParam().OutboundTxGasLimit, txData.gasLimit)

Check warning on line 87 in zetaclient/evm/base_transaction_data.go

View check run for this annotation

Codecov / codecov/patch

zetaclient/evm/base_transaction_data.go#L86-L87

Added lines #L86 - L87 were not covered by tests
}

// use dynamic gas price for ethereum chains.
// The code below is a fix for https://github.com/zeta-chain/node/issues/1085
// doesn't close directly the issue because we should determine if we want to keep using SuggestGasPrice if no OutboundTxGasPrice
// we should possibly remove it completely and return an error if no OutboundTxGasPrice is provided because it means no fee is processed on ZetaChain
specified, ok := new(big.Int).SetString(cctx.GetCurrentOutTxParam().OutboundTxGasPrice, 10)
if !ok {
if common.IsEthereumChain(chain.ChainId) {
suggested, err := client.SuggestGasPrice(context.Background())
if err != nil {
return errors.Join(err, fmt.Errorf("cannot get gas price from chain %s ", chain))

Check warning on line 99 in zetaclient/evm/base_transaction_data.go

View check run for this annotation

Codecov / codecov/patch

zetaclient/evm/base_transaction_data.go#L97-L99

Added lines #L97 - L99 were not covered by tests
}
txData.gasPrice = roundUpToNearestGwei(suggested)

Check warning on line 101 in zetaclient/evm/base_transaction_data.go

View check run for this annotation

Codecov / codecov/patch

zetaclient/evm/base_transaction_data.go#L101

Added line #L101 was not covered by tests
} else {
return fmt.Errorf("cannot convert gas price %s ", cctx.GetCurrentOutTxParam().OutboundTxGasPrice)
}
} else {
txData.gasPrice = specified
}
return nil
}

// SetTransactionData populates transaction input fields parsed from the cctx and other parameters
// returns
// bool (skipTx) - if the transaction doesn't qualify to be processed the function will return true, meaning that this
//
// cctx will be skipped and false otherwise.
//
// error
func (txData *BaseTransactionData) SetTransactionData(
cctx *types.CrossChainTx,
evmClient *ChainClient,
evmRPC interfaces.EVMRPCClient,
logger zerolog.Logger,
) (bool, error) {

txData.outboundParams = cctx.GetCurrentOutTxParam()
txData.amount = cctx.GetCurrentOutTxParam().Amount.BigInt()
txData.nonce = cctx.GetCurrentOutTxParam().OutboundTxTssNonce
txData.sender = ethcommon.HexToAddress(cctx.InboundTxParams.Sender)
txData.srcChainID = big.NewInt(cctx.InboundTxParams.SenderChainId)
txData.asset = ethcommon.HexToAddress(cctx.InboundTxParams.Asset)

skipTx := txData.SetChainAndSender(cctx, logger)
if skipTx {
return true, nil

Check warning on line 134 in zetaclient/evm/base_transaction_data.go

View check run for this annotation

Codecov / codecov/patch

zetaclient/evm/base_transaction_data.go#L134

Added line #L134 was not covered by tests
}

toChain := common.GetChainFromChainID(txData.toChainID.Int64())
if toChain == nil {
return true, fmt.Errorf("unknown chain: %d", txData.toChainID.Int64())

Check warning on line 139 in zetaclient/evm/base_transaction_data.go

View check run for this annotation

Codecov / codecov/patch

zetaclient/evm/base_transaction_data.go#L139

Added line #L139 was not covered by tests
}

// Get nonce, Early return if the cctx is already processed
nonce := cctx.GetCurrentOutTxParam().OutboundTxTssNonce
included, confirmed, err := evmClient.IsSendOutTxProcessed(cctx, logger)
if err != nil {
return true, errors.New("IsSendOutTxProcessed failed")

Check warning on line 146 in zetaclient/evm/base_transaction_data.go

View check run for this annotation

Codecov / codecov/patch

zetaclient/evm/base_transaction_data.go#L146

Added line #L146 was not covered by tests
}
if included || confirmed {
logger.Info().Msgf("CCTX already processed; exit signer")
return true, nil

Check warning on line 150 in zetaclient/evm/base_transaction_data.go

View check run for this annotation

Codecov / codecov/patch

zetaclient/evm/base_transaction_data.go#L149-L150

Added lines #L149 - L150 were not covered by tests
}

// Set up gas limit and gas price
err = txData.SetupGas(cctx, logger, evmRPC, toChain)
if err != nil {
return true, err

Check warning on line 156 in zetaclient/evm/base_transaction_data.go

View check run for this annotation

Codecov / codecov/patch

zetaclient/evm/base_transaction_data.go#L156

Added line #L156 was not covered by tests
}

// Get sendHash
logger.Info().Msgf("chain %s minting %d to %s, nonce %d, finalized zeta bn %d", toChain, cctx.InboundTxParams.Amount, txData.to.Hex(), nonce, cctx.InboundTxParams.InboundTxFinalizedZetaHeight)
sendHash, err := hex.DecodeString(cctx.Index[2:]) // remove the leading 0x
if err != nil || len(sendHash) != 32 {
return true, fmt.Errorf("decode CCTX %s error", cctx.Index)

Check warning on line 163 in zetaclient/evm/base_transaction_data.go

View check run for this annotation

Codecov / codecov/patch

zetaclient/evm/base_transaction_data.go#L163

Added line #L163 was not covered by tests
}
copy(txData.sendHash[:32], sendHash[:32])

// In case there is a pending transaction, make sure this keysign is a transaction replacement
pendingTx := evmClient.GetPendingTx(nonce)
if pendingTx != nil {
if txData.gasPrice.Cmp(pendingTx.GasPrice()) > 0 {
logger.Info().Msgf("replace pending outTx %s nonce %d using gas price %d", pendingTx.Hash().Hex(), nonce, txData.gasPrice)
} else {
logger.Info().Msgf("please wait for pending outTx %s nonce %d to be included", pendingTx.Hash().Hex(), nonce)
return true, nil

Check warning on line 174 in zetaclient/evm/base_transaction_data.go

View check run for this annotation

Codecov / codecov/patch

zetaclient/evm/base_transaction_data.go#L170-L174

Added lines #L170 - L174 were not covered by tests
}
}

// Base64 decode message
if cctx.GetCurrentOutTxParam().CoinType != common.CoinType_Cmd {
txData.message, err = base64.StdEncoding.DecodeString(cctx.RelayedMessage)
if err != nil {
logger.Err(err).Msgf("decode CCTX.Message %s error", cctx.RelayedMessage)

Check warning on line 182 in zetaclient/evm/base_transaction_data.go

View check run for this annotation

Codecov / codecov/patch

zetaclient/evm/base_transaction_data.go#L182

Added line #L182 was not covered by tests
}
}

return false, nil
}
Loading
Loading