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

feat: observation of inbound SOL token deposit #2465

Merged
merged 42 commits into from
Jul 19, 2024
Merged
Show file tree
Hide file tree
Changes from 41 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
7ee8998
add a cmd as an experimental testbed for solana
brewmaster012 Jun 25, 2024
29de312
cmd(solana): sign ECDSA and build withdraw tx
brewmaster012 Jun 25, 2024
fd648e7
e2e: localnet solana WIP: initialize gateway program
brewmaster012 Jun 28, 2024
bc1fc2c
e2e(solana): start deposit test
brewmaster012 Jun 29, 2024
c7a3b2c
update solana program with chain id commit in TSS signature
brewmaster012 Jul 2, 2024
94f3bbe
fix the initialize of solana program after update the program
brewmaster012 Jul 2, 2024
aee1bd4
zetaclient(solana): observe and filter and parse deposit instruction
brewmaster012 Jul 3, 2024
713e2c4
zetaclient(solana): remember last observed tx to save RPC calls
brewmaster012 Jul 3, 2024
3657a3b
zetaclient(solana): report to zetacored about deposit
brewmaster012 Jul 3, 2024
abb096a
localnet: deploy sol zrc20
brewmaster012 Jul 3, 2024
152e237
merge develop
brewmaster012 Jul 3, 2024
df6412b
use solana chain from merged commits
brewmaster012 Jul 3, 2024
87b52e2
fix solana rpc localnet config
brewmaster012 Jul 3, 2024
60be21c
fix chain params for solana
brewmaster012 Jul 3, 2024
0db1123
Merge branch 'develop' of https://github.com/zeta-chain/node into sol…
ws4charlie Jul 11, 2024
8f1648a
initialted inbound observation on SOL deposit
ws4charlie Jul 11, 2024
46e0eac
Use docker image and add make targets
gartnera Jul 12, 2024
25816b3
polish Solana initialize and deposit E2E tests
ws4charlie Jul 15, 2024
be0388a
Merge branch 'develop' of https://github.com/zeta-chain/node into sol…
ws4charlie Jul 15, 2024
b3f277e
make Solana inbound e2e test passing
ws4charlie Jul 16, 2024
76478d9
clean up unused files; reduce log prints
ws4charlie Jul 16, 2024
73c85f0
added entry to changelog
ws4charlie Jul 16, 2024
0b4d4ff
revert Dockerfile-localnet
ws4charlie Jul 16, 2024
a4bccc4
remove solana-test in Makefile because Solana e2e tests is ran as par…
ws4charlie Jul 16, 2024
eb814a9
polished e2e tests, solana config and chain parameters
ws4charlie Jul 17, 2024
a927628
Merge branch 'develop' of https://github.com/zeta-chain/node into sol…
ws4charlie Jul 17, 2024
97fd399
add issue link for TODO
ws4charlie Jul 17, 2024
b203fd4
remove panics
ws4charlie Jul 17, 2024
2743f9d
move Solana gateway program initialization to the contract setup phase
ws4charlie Jul 17, 2024
7032ee7
refactor e2e clients creation; add context to Solana signature query
ws4charlie Jul 17, 2024
883d04c
Merge branch 'develop' of https://github.com/zeta-chain/node into sol…
ws4charlie Jul 17, 2024
5d0ccbb
fix unit tests
ws4charlie Jul 17, 2024
77953c8
added inbound last_scanned_block_number metrics
ws4charlie Jul 17, 2024
39497f4
integrate solana tests into CI
gartnera Jul 17, 2024
492dcc4
filter at most two events [SOL + SPL] per solana tx to be consistent …
ws4charlie Jul 17, 2024
31d09e3
fix unit test compile
ws4charlie Jul 17, 2024
919260b
use observer context for Solana RPC calls
ws4charlie Jul 18, 2024
36435d0
better format stack information on panic
ws4charlie Jul 18, 2024
f199256
move stack print into logError() to avoid duplicate log print
ws4charlie Jul 18, 2024
da593ce
Fix `bg`
swift1337 Jul 18, 2024
966b56b
fix unit test
ws4charlie Jul 18, 2024
b15c080
rename pdaID as pda to be a more correct Solana terminology
ws4charlie Jul 19, 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
12 changes: 11 additions & 1 deletion .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ on:
type: boolean
required: false
default: false
solana-test:
type: boolean
required: false
default: false

concurrency:
group: e2e-${{ github.head_ref || github.sha }}
Expand All @@ -66,7 +70,7 @@ jobs:
PERFORMANCE_TESTS: ${{ steps.matrix-conditionals.outputs.PERFORMANCE_TESTS }}
STATEFUL_DATA_TESTS: ${{ steps.matrix-conditionals.outputs.STATEFUL_DATA_TESTS }}
TSS_MIGRATION_TESTS: ${{ steps.matrix-conditionals.outputs.TSS_MIGRATION_TESTS }}

SOLANA_TESTS: ${{ steps.matrix-conditionals.outputs.SOLANA_TESTS }}
steps:
# use api rather than event context to avoid race conditions (label added after push)
- id: matrix-conditionals
Expand All @@ -89,6 +93,7 @@ jobs:
core.setOutput('PERFORMANCE_TESTS', labels.includes('PERFORMANCE_TESTS'));
core.setOutput('STATEFUL_DATA_TESTS', labels.includes('STATEFUL_DATA_TESTS'));
core.setOutput('TSS_MIGRATION_TESTS', labels.includes('TSS_MIGRATION_TESTS'));
core.setOutput('SOLANA_TESTS', labels.includes('SOLANA_TESTS'));
} else if (context.eventName === 'merge_group') {
core.setOutput('DEFAULT_TESTS', true);
} else if (context.eventName === 'push' && context.ref === 'refs/heads/develop') {
Expand All @@ -109,6 +114,7 @@ jobs:
core.setOutput('ADMIN_TESTS', true);
core.setOutput('PERFORMANCE_TESTS', true);
core.setOutput('STATEFUL_DATA_TESTS', true);
core.setOutput('SOLANA_TESTS', true);
} else if (context.eventName === 'workflow_dispatch') {
core.setOutput('DEFAULT_TESTS', context.payload.inputs['default-test']);
core.setOutput('UPGRADE_TESTS', context.payload.inputs['upgrade-test']);
Expand All @@ -118,6 +124,7 @@ jobs:
core.setOutput('PERFORMANCE_TESTS', context.payload.inputs['performance-test']);
core.setOutput('STATEFUL_DATA_TESTS', context.payload.inputs['stateful-data-test']);
core.setOutput('TSS_MIGRATION_TESTS', context.payload.inputs['tss-migration-test']);
core.setOutput('SOLANA_TESTS', context.payload.inputs['solana-test']);
}
e2e:
Expand Down Expand Up @@ -150,6 +157,9 @@ jobs:
- make-target: "start-tss-migration-test"
runs-on: ubuntu-20.04
run: ${{ needs.matrix-conditionals.outputs.TSS_MIGRATION_TESTS == 'true' }}
- make-target: "start-solana-test"
runs-on: ubuntu-20.04
run: ${{ needs.matrix-conditionals.outputs.SOLANA_TESTS == 'true' }}
name: ${{ matrix.make-target }}
uses: ./.github/workflows/reusable-e2e.yml
with:
Expand Down
9 changes: 9 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,10 @@ install-zetae2e: go.sum
@go install -mod=readonly $(BUILD_FLAGS) ./cmd/zetae2e
.PHONY: install-zetae2e

solana:
@echo "Building solana docker image"
$(DOCKER) build -t solana-local -f contrib/localnet/solana/Dockerfile contrib/localnet/solana/
lumtis marked this conversation as resolved.
Show resolved Hide resolved

start-e2e-test: zetanode
@echo "--> Starting e2e test"
cd contrib/localnet/ && $(DOCKER) compose up -d
Expand Down Expand Up @@ -259,6 +263,11 @@ start-tss-migration-test: zetanode
export E2E_ARGS="--test-tss-migration" && \
cd contrib/localnet/ && $(DOCKER) compose up -d

start-solana-test: zetanode solana
ws4charlie marked this conversation as resolved.
Show resolved Hide resolved
@echo "--> Starting solana test"
export E2E_ARGS="--skip-regular --test-solana" && \
cd contrib/localnet/ && $(DOCKER) compose --profile solana -f docker-compose.yml up -d

###############################################################################
### Upgrade Tests ###
###############################################################################
Expand Down
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
* [2366](https://github.com/zeta-chain/node/pull/2366) - add migration script for adding authorizations table
* [2372](https://github.com/zeta-chain/node/pull/2372) - add queries for tss fund migration info
* [2416](https://github.com/zeta-chain/node/pull/2416) - add Solana chain information
* [2465](https://github.com/zeta-chain/node/pull/2465) - add Solana inbound SOL token observation

### Refactor

Expand Down
2 changes: 2 additions & 0 deletions cmd/zetaclientd/start_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,10 @@ func maskCfg(cfg config.Config) string {
chain.Endpoint = endpointURL.Hostname()
}

// mask endpoints
maskedCfg.BitcoinConfig.RPCUsername = ""
maskedCfg.BitcoinConfig.RPCPassword = ""
maskedCfg.SolanaConfig.Endpoint = ""

return maskedCfg.String()
}
40 changes: 38 additions & 2 deletions cmd/zetaclientd/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
ethcommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
solrpc "github.com/gagliardetto/solana-go/rpc"
"github.com/rs/zerolog"

"github.com/zeta-chain/zetacore/zetaclient/authz"
Expand All @@ -17,6 +18,7 @@ import (
evmobserver "github.com/zeta-chain/zetacore/zetaclient/chains/evm/observer"
evmsigner "github.com/zeta-chain/zetacore/zetaclient/chains/evm/signer"
"github.com/zeta-chain/zetacore/zetaclient/chains/interfaces"
solanaobserver "github.com/zeta-chain/zetacore/zetaclient/chains/solana/observer"
"github.com/zeta-chain/zetacore/zetaclient/config"
"github.com/zeta-chain/zetacore/zetaclient/context"
"github.com/zeta-chain/zetacore/zetaclient/keys"
Expand Down Expand Up @@ -168,7 +170,7 @@ func CreateChainObserverMap(
}

// BTC observer
_, chainParams, found := appContext.GetBTCChainParams()
_, btcChainParams, found := appContext.GetBTCChainParams()
if !found {
return nil, fmt.Errorf("bitcoin chains params not found")
}
Expand All @@ -184,7 +186,7 @@ func CreateChainObserverMap(
observer, err := btcobserver.NewObserver(
btcChain,
btcClient,
*chainParams,
*btcChainParams,
zetacoreClient,
tss,
dbpath,
Expand All @@ -199,5 +201,39 @@ func CreateChainObserverMap(
}
}

// Solana chain params
_, solChainParams, found := appContext.GetSolanaChainParams()
if !found {
logger.Std.Error().Msg("solana chain params not found")
return observerMap, nil
}

// create Solana chain observer
solChain, solConfig, enabled := appContext.GetSolanaChainAndConfig()
if enabled {
rpcClient := solrpc.New(solConfig.Endpoint)
if rpcClient == nil {
// should never happen
logger.Std.Error().Msg("solana create Solana client error")
return observerMap, nil
}

observer, err := solanaobserver.NewObserver(
solChain,
rpcClient,
*solChainParams,
zetacoreClient,
tss,
dbpath,
logger,
ts,
)
if err != nil {
logger.Std.Error().Err(err).Msg("NewObserver error for solana chain")
} else {
observerMap[solChainParams.ChainId] = observer
}
}

ws4charlie marked this conversation as resolved.
Show resolved Hide resolved
return observerMap, nil
}
76 changes: 49 additions & 27 deletions cmd/zetae2e/config/clients.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/gagliardetto/solana-go/rpc"
"google.golang.org/grpc"

"github.com/zeta-chain/zetacore/e2e/config"
Expand All @@ -18,51 +19,72 @@ import (
observertypes "github.com/zeta-chain/zetacore/x/observer/types"
)

// E2EClients contains all the RPC clients and gRPC clients for E2E tests
type E2EClients struct {
// the RPC clients for external chains in the localnet
BtcRPCClient *rpcclient.Client
SolanaClient *rpc.Client
EvmClient *ethclient.Client
EvmAuth *bind.TransactOpts

// the gRPC clients for ZetaChain
CctxClient crosschaintypes.QueryClient
FungibleClient fungibletypes.QueryClient
AuthClient authtypes.QueryClient
BankClient banktypes.QueryClient
ObserverClient observertypes.QueryClient
LightClient lightclienttypes.QueryClient

// the RPC clients for ZetaChain
ZevmClient *ethclient.Client
ZevmAuth *bind.TransactOpts
}

// getClientsFromConfig get clients from config
func getClientsFromConfig(ctx context.Context, conf config.Config, account config.Account) (
*rpcclient.Client,
*ethclient.Client,
*bind.TransactOpts,
crosschaintypes.QueryClient,
fungibletypes.QueryClient,
authtypes.QueryClient,
banktypes.QueryClient,
observertypes.QueryClient,
lightclienttypes.QueryClient,
*ethclient.Client,
*bind.TransactOpts,
E2EClients,
error,
) {
if conf.RPCs.Solana == "" {
return E2EClients{}, fmt.Errorf("solana rpc is empty")
}
solanaClient := rpc.New(conf.RPCs.Solana)
if solanaClient == nil {
return E2EClients{}, fmt.Errorf("failed to get solana client")
}
btcRPCClient, err := getBtcClient(conf.RPCs.Bitcoin)
if err != nil {
return nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("failed to get btc client: %w", err)
return E2EClients{}, fmt.Errorf("failed to get btc client: %w", err)
}
evmClient, evmAuth, err := getEVMClient(ctx, conf.RPCs.EVM, account)
if err != nil {
return nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("failed to get evm client: %w", err)
return E2EClients{}, fmt.Errorf("failed to get evm client: %w", err)
}
cctxClient, fungibleClient, authClient, bankClient, observerClient, lightclientClient, err := getZetaClients(
conf.RPCs.ZetaCoreGRPC,
)
if err != nil {
return nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("failed to get zeta clients: %w", err)
return E2EClients{}, fmt.Errorf("failed to get zeta clients: %w", err)
}
zevmClient, zevmAuth, err := getEVMClient(ctx, conf.RPCs.Zevm, account)
if err != nil {
return nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("failed to get zevm client: %w", err)
return E2EClients{}, fmt.Errorf("failed to get zevm client: %w", err)
}
return btcRPCClient,
evmClient,
evmAuth,
cctxClient,
fungibleClient,
authClient,
bankClient,
observerClient,
lightclientClient,
zevmClient,
zevmAuth,
nil

return E2EClients{
BtcRPCClient: btcRPCClient,
SolanaClient: solanaClient,
EvmClient: evmClient,
EvmAuth: evmAuth,
CctxClient: cctxClient,
FungibleClient: fungibleClient,
AuthClient: authClient,
BankClient: bankClient,
ObserverClient: observerClient,
LightClient: lightclientClient,
ZevmClient: zevmClient,
ZevmAuth: zevmAuth,
}, nil
}

// getBtcClient get btc client
Expand Down
42 changes: 18 additions & 24 deletions cmd/zetae2e/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,8 @@ func RunnerFromConfig(
logger *runner.Logger,
opts ...runner.E2ERunnerOption,
) (*runner.E2ERunner, error) {
// initialize clients
btcRPCClient,
evmClient,
evmAuth,
cctxClient,
fungibleClient,
authClient,
bankClient,
observerClient,
lightClient,
zevmClient,
zevmAuth,
err := getClientsFromConfig(ctx, conf, account)
// initialize all clients for E2E tests
e2eClients, err := getClientsFromConfig(ctx, conf, account)
if err != nil {
return nil, fmt.Errorf("failed to get clients from config: %w", err)
}
Expand All @@ -41,17 +30,19 @@ func RunnerFromConfig(
name,
ctxCancel,
account,
evmClient,
zevmClient,
cctxClient,
fungibleClient,
authClient,
bankClient,
observerClient,
lightClient,
evmAuth,
zevmAuth,
btcRPCClient,
e2eClients.EvmClient,
e2eClients.ZevmClient,
e2eClients.CctxClient,
e2eClients.FungibleClient,
e2eClients.AuthClient,
e2eClients.BankClient,
e2eClients.ObserverClient,
e2eClients.LightClient,
e2eClients.EvmAuth,
e2eClients.ZevmAuth,
e2eClients.BtcRPCClient,
e2eClients.SolanaClient,

logger,
opts...,
)
Expand All @@ -74,6 +65,8 @@ func RunnerFromConfig(

// ExportContractsFromRunner export contracts from the runner to config using a source config
func ExportContractsFromRunner(r *runner.E2ERunner, conf config.Config) config.Config {
conf.Contracts.Solana.GatewayProgramID = r.GatewayProgram.String()

// copy contracts from deployer runner
conf.Contracts.EVM.ZetaEthAddr = config.DoubleQuotedString(r.ZetaEthAddr.Hex())
conf.Contracts.EVM.ConnectorEthAddr = config.DoubleQuotedString(r.ConnectorEthAddr.Hex())
Expand All @@ -85,6 +78,7 @@ func ExportContractsFromRunner(r *runner.E2ERunner, conf config.Config) config.C
conf.Contracts.ZEVM.ETHZRC20Addr = config.DoubleQuotedString(r.ETHZRC20Addr.Hex())
conf.Contracts.ZEVM.ERC20ZRC20Addr = config.DoubleQuotedString(r.ERC20ZRC20Addr.Hex())
conf.Contracts.ZEVM.BTCZRC20Addr = config.DoubleQuotedString(r.BTCZRC20Addr.Hex())
conf.Contracts.ZEVM.SOLZRC20Addr = config.DoubleQuotedString(r.SOLZRC20Addr.Hex())
conf.Contracts.ZEVM.UniswapFactoryAddr = config.DoubleQuotedString(r.UniswapV2FactoryAddr.Hex())
conf.Contracts.ZEVM.UniswapRouterAddr = config.DoubleQuotedString(r.UniswapV2RouterAddr.Hex())
conf.Contracts.ZEVM.ConnectorZEVMAddr = config.DoubleQuotedString(r.ConnectorZEVMAddr.Hex())
Expand Down
17 changes: 17 additions & 0 deletions cmd/zetae2e/config/contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package config
import (
"fmt"

"github.com/gagliardetto/solana-go"
"github.com/zeta-chain/protocol-contracts/pkg/contracts/evm/erc20custody.sol"
zetaeth "github.com/zeta-chain/protocol-contracts/pkg/contracts/evm/zeta.eth.sol"
zetaconnectoreth "github.com/zeta-chain/protocol-contracts/pkg/contracts/evm/zetaconnector.eth.sol"
Expand All @@ -24,6 +25,11 @@ import (
func setContractsFromConfig(r *runner.E2ERunner, conf config.Config) error {
var err error

// set Solana contracts
if c := conf.Contracts.Solana.GatewayProgramID; c != "" {
r.GatewayProgram = solana.MustPublicKeyFromBase58(c)
}

// set EVM contracts
if c := conf.Contracts.EVM.ZetaEthAddr; c != "" {
r.ZetaEthAddr, err = c.AsEVMAddress()
Expand Down Expand Up @@ -114,6 +120,17 @@ func setContractsFromConfig(r *runner.E2ERunner, conf config.Config) error {
}
}

if c := conf.Contracts.ZEVM.SOLZRC20Addr; c != "" {
r.SOLZRC20Addr, err = c.AsEVMAddress()
if err != nil {
return fmt.Errorf("invalid SOLZRC20Addr: %w", err)
}
r.SOLZRC20, err = zrc20.NewZRC20(r.SOLZRC20Addr, r.ZEVMClient)
if err != nil {
return err
}
}

if c := conf.Contracts.ZEVM.UniswapFactoryAddr; c != "" {
r.UniswapV2FactoryAddr, err = c.AsEVMAddress()
if err != nil {
Expand Down
Loading
Loading