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

fix: support tracker processing for v2 inbounds #3179

Merged
merged 10 commits into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Unreleased

### Features

* [2984](https://github.com/zeta-chain/node/pull/2984) - add Whitelist message ability to whitelist SPL tokens on Solana
* [3091](https://github.com/zeta-chain/node/pull/3091) - improve build reproducability. `make release{,-build-only}` checksums should now be stable.
* [3124](https://github.com/zeta-chain/node/pull/3124) - integrate SPL deposits
Expand All @@ -15,20 +16,23 @@
* [3154](https://github.com/zeta-chain/node/pull/3154) - configure Solana gateway program id for E2E tests

### Refactor

* [3118](https://github.com/zeta-chain/node/pull/3118) - zetaclient: remove hsm signer
* [3122](https://github.com/zeta-chain/node/pull/3122) - improve & refactor zetaclientd cli
* [3125](https://github.com/zeta-chain/node/pull/3125) - drop support for header proofs
* [3131](https://github.com/zeta-chain/node/pull/3131) - move app context update from zetacore client
* [3137](https://github.com/zeta-chain/node/pull/3137) - remove chain.Chain from zetaclientd config

### Fixes

* [3117](https://github.com/zeta-chain/node/pull/3117) - register messages for emissions module to legacy amino codec.
* [3041](https://github.com/zeta-chain/node/pull/3041) - replace libp2p public DHT with private gossip peer discovery and connection gater for inbound connections
* [3106](https://github.com/zeta-chain/node/pull/3106) - prevent blocked CCTX on out of gas during omnichain calls
* [3139](https://github.com/zeta-chain/node/pull/3139) - fix config resolution in orchestrator
* [3149](https://github.com/zeta-chain/node/pull/3149) - abort the cctx if dust amount is detected in the revert outbound
* [3155](https://github.com/zeta-chain/node/pull/3155) - fix potential panic in the Bitcoin inscription parsing
* [3162](https://github.com/zeta-chain/node/pull/3162) - skip depositor fee calculation if transaction does not involve TSS address
* [3179](https://github.com/zeta-chain/node/pull/3179) - support inbound trackers for v2 cctx

## v21.0.0

Expand Down
4 changes: 3 additions & 1 deletion cmd/zetae2e/config/local.yml
Original file line number Diff line number Diff line change
Expand Up @@ -110,13 +110,15 @@ contracts:
wzeta: "0x5F0b1a82749cb4E2278EC87F8BF6B618dC71a8bf"
test_dapp: "0xA8D5060feb6B456e886F023709A2795373691E63"
gateway: "0xa825eAa55b497AF892faca73a3797046C10B7c23"
test_dapp_v2: "0xBFF76e77D56B3C1202107f059425D56f0AEF87Ed"
evm:
zeta_eth: "0x733aB8b06DDDEf27Eaa72294B0d7c9cEF7f12db9"
connector_eth: "0xD28D6A0b8189305551a0A8bd247a6ECa9CE781Ca"
custody: "0xff3135df4F2775f4091b81f4c7B6359CfA07862a"
custody: "0x784aE8B474aebabB74526701146a708734f6931c"
erc20: "0xbD1e64A22B9F92D9Ce81aA9B4b0fFacd80215564"
test_dapp: "0xBFF76e77D56B3C1202107f059425D56f0AEF87Ed"
gateway: "0xF0deebCB0E9C829519C4baa794c5445171973826"
test_dapp_v2: "0xa825eAa55b497AF892faca73a3797046C10B7c23"
solana:
gateway_program_id: "94U5AHQMKkV5txNJ17QPXWoh474PheGou6cNP2FEuL1d"
spl: ""
26 changes: 26 additions & 0 deletions cmd/zetae2e/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import (
"github.com/zeta-chain/node/e2e/config"
"github.com/zeta-chain/node/e2e/e2etests"
"github.com/zeta-chain/node/e2e/runner"
"github.com/zeta-chain/node/e2e/txserver"
"github.com/zeta-chain/node/e2e/utils"
fungibletypes "github.com/zeta-chain/node/x/fungible/types"
observertypes "github.com/zeta-chain/node/x/observer/types"
)
Expand Down Expand Up @@ -104,6 +106,29 @@ func runE2ETest(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

var runnerOpts []runner.E2ERunnerOption

// if keys are defined for all policy accounts, we initialize a ZETA tx server allowing to send admin actions
emergencyKey := conf.PolicyAccounts.EmergencyPolicyAccount.RawPrivateKey.String()
operationalKey := conf.PolicyAccounts.OperationalPolicyAccount.RawPrivateKey.String()
adminKey := conf.PolicyAccounts.AdminPolicyAccount.RawPrivateKey.String()
lumtis marked this conversation as resolved.
Show resolved Hide resolved
if emergencyKey != "" && operationalKey != "" && adminKey != "" {
zetaTxServer, err := txserver.NewZetaTxServer(
conf.RPCs.ZetaCoreRPC,
[]string{utils.EmergencyPolicyName, utils.OperationalPolicyName, utils.AdminPolicyName},
[]string{
emergencyKey,
operationalKey,
adminKey,
},
conf.ZetaChainID,
)
if err != nil {
return err
}
runnerOpts = append(runnerOpts, runner.WithZetaTxServer(zetaTxServer))
}

// initialize deployer runner with config
testRunner, err := zetae2econfig.RunnerFromConfig(
ctx,
Expand All @@ -112,6 +137,7 @@ func runE2ETest(cmd *cobra.Command, args []string) error {
conf,
conf.DefaultAccount,
logger,
runnerOpts...,
)
if err != nil {
return err
Expand Down
13 changes: 10 additions & 3 deletions e2e/e2etests/e2etests.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,10 @@ const (
Miscellaneous tests
Test various functionalities not related to assets
*/
TestContextUpgradeName = "context_upgrade"
TestMyTestName = "my_test"
TestDonationEtherName = "donation_ether"
TestContextUpgradeName = "context_upgrade"
TestMyTestName = "my_test"
TestDonationEtherName = "donation_ether"
TestInboundTrackersName = "inbound_trackers"

/*
Stress tests
Expand Down Expand Up @@ -737,6 +738,12 @@ var AllE2ETests = []runner.E2ETest{
},
TestDonationEther,
),
runner.NewE2ETest(
TestInboundTrackersName,
"test processing inbound trackers for observation",
[]runner.ArgDefinition{},
TestInboundTrackers,
),
/*
Stress tests
*/
Expand Down
87 changes: 87 additions & 0 deletions e2e/e2etests/test_inbound_trackers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package e2etests

import (
"math/big"

"github.com/stretchr/testify/require"
"github.com/zeta-chain/protocol-contracts/v2/pkg/gatewayevm.sol"

"github.com/zeta-chain/node/e2e/runner"
"github.com/zeta-chain/node/e2e/utils"
"github.com/zeta-chain/node/pkg/coin"
crosschaintypes "github.com/zeta-chain/node/x/crosschain/types"
)

// TestInboundTrackers tests inbound trackers processing in ZetaClient
// It run deposits, send inbound trackers and check cctxs are mined
// IMPORTANT: the test requires inbound observation to be disabled, the following line should be uncommented:
// https://github.com/zeta-chain/node/blob/9dcb42729653e033f5ba60a77dc37e5e19b092ad/zetaclient/chains/evm/observer/inbound.go#L210
func TestInboundTrackers(r *runner.E2ERunner, args []string) {
require.Len(r, args, 0)

amount := big.NewInt(1e17)

addTrackerAndWaitForCCTX := func(coinType coin.CoinType, txHash string) {
r.AddInboundTracker(coinType, txHash)
cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, txHash, r.CctxClient, r.Logger, r.CctxTimeout)
require.EqualValues(r, crosschaintypes.CctxStatus_OutboundMined, cctx.CctxStatus.Status)
r.Logger.CCTX(*cctx, "cctx")
}

// send v1 eth deposit
r.Logger.Print("🏃test v1 eth deposit")
lumtis marked this conversation as resolved.
Show resolved Hide resolved
txHash := r.DepositEtherWithAmount(amount)
addTrackerAndWaitForCCTX(coin.CoinType_Gas, txHash.Hex())
r.Logger.Print("🍾v1 eth deposit observed")

// send v1 erc20 deposit
r.Logger.Print("🏃test v1 erc20 deposit")
txHash = r.DepositERC20WithAmountAndMessage(r.EVMAddress(), amount, []byte{})
addTrackerAndWaitForCCTX(coin.CoinType_ERC20, txHash.Hex())
r.Logger.Print("🍾v1 erc20 deposit observed")

// send v2 eth deposit
r.Logger.Print("🏃test v2 eth deposit")
tx := r.V2ETHDeposit(r.EVMAddress(), amount, gatewayevm.RevertOptions{OnRevertGasLimit: big.NewInt(0)})
addTrackerAndWaitForCCTX(coin.CoinType_Gas, tx.Hash().Hex())
r.Logger.Print("🍾v2 eth deposit observed")

// send v2 eth deposit and call
r.Logger.Print("🏃test v2 eth eposit and call")
tx = r.V2ETHDepositAndCall(
r.TestDAppV2ZEVMAddr,
amount,
[]byte(randomPayload(r)),
gatewayevm.RevertOptions{OnRevertGasLimit: big.NewInt(0)},
)
addTrackerAndWaitForCCTX(coin.CoinType_Gas, tx.Hash().Hex())
r.Logger.Print("🍾v2 eth deposit and call observed")

// send v2 erc20 deposit
r.Logger.Print("🏃test v2 erc20 deposit")
r.ApproveERC20OnEVM(r.GatewayEVMAddr)
tx = r.V2ERC20Deposit(r.EVMAddress(), amount, gatewayevm.RevertOptions{OnRevertGasLimit: big.NewInt(0)})
addTrackerAndWaitForCCTX(coin.CoinType_Gas, tx.Hash().Hex())
r.Logger.Print("🍾v2 erc20 deposit observed")

// send v2 erc20 deposit and call
r.Logger.Print("🏃test v2 erc20 deposit and call")
tx = r.V2ERC20DepositAndCall(
r.TestDAppV2ZEVMAddr,
amount,
[]byte(randomPayload(r)),
gatewayevm.RevertOptions{OnRevertGasLimit: big.NewInt(0)},
)
addTrackerAndWaitForCCTX(coin.CoinType_Gas, tx.Hash().Hex())
r.Logger.Print("🍾v2 erc20 deposit and call observed")

// send v2 call
r.Logger.Print("🏃test v2 call")
tx = r.V2EVMToZEMVCall(
r.TestDAppV2ZEVMAddr,
[]byte(randomPayload(r)),
gatewayevm.RevertOptions{OnRevertGasLimit: big.NewInt(0)},
)
addTrackerAndWaitForCCTX(coin.CoinType_NoAssetCall, tx.Hash().Hex())
r.Logger.Print("🍾v2 call observed")
}
18 changes: 18 additions & 0 deletions e2e/runner/zeta.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (

"github.com/zeta-chain/node/e2e/utils"
"github.com/zeta-chain/node/pkg/chains"
"github.com/zeta-chain/node/pkg/coin"
"github.com/zeta-chain/node/pkg/retry"
"github.com/zeta-chain/node/x/crosschain/types"
observertypes "github.com/zeta-chain/node/x/observer/types"
Expand Down Expand Up @@ -332,3 +333,20 @@ func (r *E2ERunner) skipChainOperations(chainID int64) bool {

return skip
}

// AddInboundTracker adds an inbound tracker from the tx hash
func (r *E2ERunner) AddInboundTracker(coinType coin.CoinType, txHash string) {
require.NotNil(r, r.ZetaTxServer)

chainID, err := r.EVMClient.ChainID(r.Ctx)
require.NoError(r, err)

msg := types.NewMsgAddInboundTracker(
r.ZetaTxServer.MustGetAccountAddressFromName(utils.EmergencyPolicyName),
chainID.Int64(),
coinType,
txHash,
)
_, err = r.ZetaTxServer.BroadcastTx(utils.EmergencyPolicyName, msg)
require.NoError(r, err)
}
lumtis marked this conversation as resolved.
Show resolved Hide resolved
2 changes: 1 addition & 1 deletion zetaclient/chains/base/observer.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ func (ob *Observer) WithZetacoreClient(client interfaces.ZetacoreClient) *Observ
return ob
}

// Tss returns the tss signer for the observer.
// TSS returns the tss signer for the observer.
func (ob *Observer) TSS() interfaces.TSSSigner {
return ob.tss
}
Expand Down
52 changes: 35 additions & 17 deletions zetaclient/chains/evm/observer/inbound.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@
if err != nil {
return err
}

for _, tracker := range trackers {
// query tx and receipt
tx, _, err := ob.TransactionByHash(tracker.TxHash)
Expand All @@ -144,24 +145,35 @@
}
ob.Logger().Inbound.Info().Msgf("checking tracker for inbound %s chain %d", tracker.TxHash, ob.Chain().ChainId)

// check and vote on inbound tx
switch tracker.CoinType {
case coin.CoinType_Zeta:
_, err = ob.CheckAndVoteInboundTokenZeta(ctx, tx, receipt, true)
case coin.CoinType_ERC20:
_, err = ob.CheckAndVoteInboundTokenERC20(ctx, tx, receipt, true)
case coin.CoinType_Gas:
_, err = ob.CheckAndVoteInboundTokenGas(ctx, tx, receipt, true)
default:
return fmt.Errorf(
"unknown coin type %s for inbound %s chain %d",
tracker.CoinType,
tx.Hash,
ob.Chain().ChainId,
)
}
// if the transaction is sent to the gateway, this is a v2 inbound
gatewayAddr, gateway, err := ob.GetGatewayContract()

Check warning on line 149 in zetaclient/chains/evm/observer/inbound.go

View check run for this annotation

Codecov / codecov/patch

zetaclient/chains/evm/observer/inbound.go#L148-L149

Added lines #L148 - L149 were not covered by tests
if err != nil {
return errors.Wrapf(err, "error checking and voting for inbound %s chain %d", tx.Hash, ob.Chain().ChainId)
ob.Logger().Inbound.Debug().Err(err).Msg("error getting gateway contract for processing inbound tracker")
}
if err == nil && tx != nil && ethcommon.HexToAddress(tx.To) == gatewayAddr {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit

The tx != nil check should, IMO, be moved up to line 127 where TransactionByHash() is called or removed at all. The reason being, that if tx == nil, the else branch is entered

} else {
// check and vote on inbound tx
switch tracker.CoinType {
case coin.CoinType_Zeta:
_, err = ob.CheckAndVoteInboundTokenZeta(ctx, tx, receipt, true)
case coin.CoinType_ERC20:
_, err = ob.CheckAndVoteInboundTokenERC20(ctx, tx, receipt, true)
case coin.CoinType_Gas:
_, err = ob.CheckAndVoteInboundTokenGas(ctx, tx, receipt, true)
default:
return fmt.Errorf(
"unknown coin type %s for inbound %s chain %d",
tracker.CoinType,
tx.Hash,
ob.Chain().ChainId,
)
}
if err != nil {
return errors.Wrapf(err, "error checking and voting for inbound %s chain %d", tx.Hash, ob.Chain().ChainId)
}
}

which internally also accesses tx. For example, in

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, the idea to touch the other v1 logic as less as possible so not having the check in this workflow

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only transactions directly calling the gateway contract (i.e., ethcommon.HexToAddress(tx.To) == gatewayAddr) can be successfully processed. But what about transactions where the gateway contract was called by another contract (i.e., tx.To != gatewayAddr)? Is it intentional to exclude such transactions?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No good point, we will need this as well

if err := ob.ProcessInboundTrackerV2(ctx, gateway, tx, receipt); err != nil {
return err
}
} else {
// check and vote on inbound tx
switch tracker.CoinType {
case coin.CoinType_Zeta:
_, err = ob.CheckAndVoteInboundTokenZeta(ctx, tx, receipt, true)
case coin.CoinType_ERC20:
_, err = ob.CheckAndVoteInboundTokenERC20(ctx, tx, receipt, true)
case coin.CoinType_Gas:
_, err = ob.CheckAndVoteInboundTokenGas(ctx, tx, receipt, true)
default:
return fmt.Errorf(
"unknown coin type %s for inbound %s chain %d",
tracker.CoinType,
tx.Hash,
ob.Chain().ChainId,
)

Check warning on line 172 in zetaclient/chains/evm/observer/inbound.go

View check run for this annotation

Codecov / codecov/patch

zetaclient/chains/evm/observer/inbound.go#L151-L172

Added lines #L151 - L172 were not covered by tests
}
if err != nil {
return errors.Wrapf(err, "error checking and voting for inbound %s chain %d", tx.Hash, ob.Chain().ChainId)
}

Check warning on line 176 in zetaclient/chains/evm/observer/inbound.go

View check run for this annotation

Codecov / codecov/patch

zetaclient/chains/evm/observer/inbound.go#L174-L176

Added lines #L174 - L176 were not covered by tests
}
}
return nil
Expand All @@ -186,6 +198,12 @@
// increment prom counter
metrics.GetBlockByNumberPerChain.WithLabelValues(ob.Chain().Name).Inc()

// uncomment this line to stop observing inbound and test observation with inbound trackers
// https://github.com/zeta-chain/node/blob/3879b5ef8b418542c82a4383263604222f0605c6/e2e/e2etests/test_inbound_trackers.go#L19
// TODO: implement a better way to disable inbound observation
// https://github.com/zeta-chain/node/issues/3186
//return nil
lumtis marked this conversation as resolved.
Show resolved Hide resolved

Check warning on line 206 in zetaclient/chains/evm/observer/inbound.go

View check run for this annotation

Codecov / codecov/patch

zetaclient/chains/evm/observer/inbound.go#L201-L206

Added lines #L201 - L206 were not covered by tests
// skip if current height is too low
if blockNumber < ob.ChainParams().ConfirmationCount {
return fmt.Errorf("observeInbound: skipping observer, current block number %d is too low", blockNumber)
Expand Down
Loading
Loading