Skip to content

Commit

Permalink
fix: ask for 3 accounts (signer, pda, system_program) when parsing So…
Browse files Browse the repository at this point in the history
…nala inbound signer address (#2787)

* explicitly ask for 3 accounts on solana gateway deposit; use default relayer key path if not set

* add changelog entry and revert the modification on localnet docker file

* add unit test for default relayer key path

* move changelog entry to Fixes section
  • Loading branch information
ws4charlie authored Aug 30, 2024
1 parent 91c323d commit 7b34d1d
Show file tree
Hide file tree
Showing 11 changed files with 117 additions and 92 deletions.
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
* [2654](https://github.com/zeta-chain/node/pull/2654) - add validation for authorization list in when validating genesis state for authorization module
* [2674](https://github.com/zeta-chain/node/pull/2674) - allow operators to vote on ballots associated with discarded keygen without affecting the status of the current keygen.
* [2672](https://github.com/zeta-chain/node/pull/2672) - check observer set for duplicates when adding a new observer or updating an existing one
* [2787](https://github.com/zeta-chain/node/pull/2787) - ask for 3 accounts (signer, pda, system_program) on solana gateway deposit

## v19.0.0

Expand Down
4 changes: 2 additions & 2 deletions cmd/zetaclientd/import_relayer_keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/zeta-chain/zetacore/pkg/chains"
"github.com/zeta-chain/zetacore/pkg/crypto"
zetaos "github.com/zeta-chain/zetacore/pkg/os"
"github.com/zeta-chain/zetacore/zetaclient/config"
"github.com/zeta-chain/zetacore/zetaclient/keys"
)

Expand Down Expand Up @@ -52,8 +53,7 @@ func init() {
RootCmd.AddCommand(CmdRelayerAddress)

// resolve default relayer key path
defaultRelayerKeyPath := "~/.zetacored/relayer-keys"
defaultRelayerKeyPath, err := zetaos.ExpandHomeDir(defaultRelayerKeyPath)
defaultRelayerKeyPath, err := zetaos.ExpandHomeDir(config.DefaultRelayerKeyPath)
if err != nil {
log.Fatal().Err(err).Msg("failed to resolve default relayer key path")
}
Expand Down
1 change: 0 additions & 1 deletion e2e/runner/solana.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ func (r *E2ERunner) CreateDepositInstruction(
accountSlice = append(accountSlice, solana.Meta(signer).WRITE().SIGNER())
accountSlice = append(accountSlice, solana.Meta(pdaComputed).WRITE())
accountSlice = append(accountSlice, solana.Meta(solana.SystemProgramID))
accountSlice = append(accountSlice, solana.Meta(programID))
inst.ProgID = programID
inst.AccountValues = accountSlice

Expand Down
4 changes: 2 additions & 2 deletions pkg/contracts/solana/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ const (
PDASeed = "meta"

// AccountsNumberOfDeposit is the number of accounts required for Solana gateway deposit instruction
// [signer, pda, system_program, gateway_program]
AccountsNumDeposit = 4
// [signer, pda, system_program]
AccountsNumDeposit = 3
)

// DiscriminatorInitialize returns the discriminator for Solana gateway 'initialize' instruction
Expand Down
17 changes: 9 additions & 8 deletions zetaclient/chains/solana/observer/inbound.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,10 +285,13 @@ func (ob *Observer) ParseInboundAsDeposit(
return nil, nil
}

// get the sender address (the signer must exist)
// get the sender address (skip if unable to parse signer address)
sender, err := ob.GetSignerDeposit(tx, &instruction)
if err != nil {
return nil, errors.Wrap(err, "error GetSignerDeposit")
ob.Logger().
Inbound.Err(err).
Msgf("unable to get signer for sig %s instruction %d", tx.Signatures[0], instructionIndex)
return nil, nil
}

// build inbound event
Expand Down Expand Up @@ -323,13 +326,13 @@ func (ob *Observer) ParseInboundAsDepositSPL(
// GetSignerDeposit returns the signer address of the deposit instruction
// Note: solana-go is not able to parse the AccountMeta 'is_signer' ATM. This is a workaround.
func (ob *Observer) GetSignerDeposit(tx *solana.Transaction, inst *solana.CompiledInstruction) (string, error) {
// there should be 4 accounts for a deposit instruction
// there should be 3 accounts for a deposit instruction
if len(inst.Accounts) != solanacontracts.AccountsNumDeposit {
return "", fmt.Errorf("want %d accounts, got %d", solanacontracts.AccountsNumDeposit, len(inst.Accounts))
}

// the accounts are [signer, pda, system_program, gateway_program]
signerIndex, pdaIndex, systemIndex, gatewayIndex := -1, -1, -1, -1
// the accounts are [signer, pda, system_program]
signerIndex, pdaIndex, systemIndex := -1, -1, -1

// try to find the indexes of all above accounts
for _, accIndex := range inst.Accounts {
Expand All @@ -340,8 +343,6 @@ func (ob *Observer) GetSignerDeposit(tx *solana.Transaction, inst *solana.Compil
switch accKey {
case ob.pda:
pdaIndex = accIndexInt
case ob.gatewayID:
gatewayIndex = accIndexInt
case solana.SystemProgramID:
systemIndex = accIndexInt
default:
Expand All @@ -351,7 +352,7 @@ func (ob *Observer) GetSignerDeposit(tx *solana.Transaction, inst *solana.Compil
}

// all above accounts must be found
if signerIndex == -1 || pdaIndex == -1 || systemIndex == -1 || gatewayIndex == -1 {
if signerIndex == -1 || pdaIndex == -1 || systemIndex == -1 {
return "", fmt.Errorf("invalid accounts for deposit instruction")
}

Expand Down
28 changes: 14 additions & 14 deletions zetaclient/chains/solana/observer/inbound_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ var (

func Test_FilterInboundEventAndVote(t *testing.T) {
// load archived inbound vote tx result
// https://explorer.solana.com/tx/5LuQMorgd11p8GWEw6pmyHCDtA26NUyeNFhLWPNk2oBoM9pkag1LzhwGSRos3j4TJLhKjswFhZkGtvSGdLDkmqsk?cluster=devnet
txHash := "5LuQMorgd11p8GWEw6pmyHCDtA26NUyeNFhLWPNk2oBoM9pkag1LzhwGSRos3j4TJLhKjswFhZkGtvSGdLDkmqsk"
// https://explorer.solana.com/tx/MS3MPLN7hkbyCZFwKqXcg8fmEvQMD74fN6Ps2LSWXJoRxPW5ehaxBorK9q1JFVbqnAvu9jXm6ertj7kT7HpYw1j?cluster=devnet
txHash := "MS3MPLN7hkbyCZFwKqXcg8fmEvQMD74fN6Ps2LSWXJoRxPW5ehaxBorK9q1JFVbqnAvu9jXm6ertj7kT7HpYw1j"
chain := chains.SolanaDevnet
txResult := testutils.LoadSolanaInboundTxResult(t, TestDataDir, chain.ChainId, txHash, false)

Expand All @@ -51,8 +51,8 @@ func Test_FilterInboundEventAndVote(t *testing.T) {

func Test_FilterInboundEvents(t *testing.T) {
// load archived inbound deposit tx result
// https://explorer.solana.com/tx/5LuQMorgd11p8GWEw6pmyHCDtA26NUyeNFhLWPNk2oBoM9pkag1LzhwGSRos3j4TJLhKjswFhZkGtvSGdLDkmqsk?cluster=devnet
txHash := "5LuQMorgd11p8GWEw6pmyHCDtA26NUyeNFhLWPNk2oBoM9pkag1LzhwGSRos3j4TJLhKjswFhZkGtvSGdLDkmqsk"
// https://explorer.solana.com/tx/MS3MPLN7hkbyCZFwKqXcg8fmEvQMD74fN6Ps2LSWXJoRxPW5ehaxBorK9q1JFVbqnAvu9jXm6ertj7kT7HpYw1j?cluster=devnet
txHash := "MS3MPLN7hkbyCZFwKqXcg8fmEvQMD74fN6Ps2LSWXJoRxPW5ehaxBorK9q1JFVbqnAvu9jXm6ertj7kT7HpYw1j"
chain := chains.SolanaDevnet
txResult := testutils.LoadSolanaInboundTxResult(t, TestDataDir, chain.ChainId, txHash, false)

Expand All @@ -61,20 +61,20 @@ func Test_FilterInboundEvents(t *testing.T) {

// create observer
chainParams := sample.ChainParams(chain.ChainId)
chainParams.GatewayAddress = GatewayAddressTest
chainParams.GatewayAddress = testutils.GatewayAddresses[chain.ChainId]

ob, err := observer.NewObserver(chain, nil, *chainParams, nil, nil, database, base.DefaultLogger(), nil)
require.NoError(t, err)

// expected result
sender := "AKbG83jg2V65R7XvaPFrnUvUTWsFENEzDPbLJFEiAk6L"
sender := "AS48jKNQsDGkEdDvfwu1QpqjtqbCadrAq9nGXjFmdX3Z"
eventExpected := &clienttypes.InboundEvent{
SenderChainID: chain.ChainId,
Sender: sender,
Receiver: sender,
TxOrigin: sender,
Amount: 1280,
Memo: []byte("hello this is a good memo for you to enjoy"),
Amount: 100000,
Memo: []byte("0x7F8ae2ABb69A558CE6bAd546f25F0464D9e09e5B4955a3F38ff86ae92A914445099caa8eA2B9bA32"),
BlockNumber: txResult.Slot,
TxHash: txHash,
Index: 0, // not a EVM smart contract call
Expand Down Expand Up @@ -156,8 +156,8 @@ func Test_BuildInboundVoteMsgFromEvent(t *testing.T) {

func Test_ParseInboundAsDeposit(t *testing.T) {
// load archived inbound deposit tx result
// https://explorer.solana.com/tx/5LuQMorgd11p8GWEw6pmyHCDtA26NUyeNFhLWPNk2oBoM9pkag1LzhwGSRos3j4TJLhKjswFhZkGtvSGdLDkmqsk?cluster=devnet
txHash := "5LuQMorgd11p8GWEw6pmyHCDtA26NUyeNFhLWPNk2oBoM9pkag1LzhwGSRos3j4TJLhKjswFhZkGtvSGdLDkmqsk"
// https://explorer.solana.com/tx/MS3MPLN7hkbyCZFwKqXcg8fmEvQMD74fN6Ps2LSWXJoRxPW5ehaxBorK9q1JFVbqnAvu9jXm6ertj7kT7HpYw1j?cluster=devnet
txHash := "MS3MPLN7hkbyCZFwKqXcg8fmEvQMD74fN6Ps2LSWXJoRxPW5ehaxBorK9q1JFVbqnAvu9jXm6ertj7kT7HpYw1j"
chain := chains.SolanaDevnet

txResult := testutils.LoadSolanaInboundTxResult(t, TestDataDir, chain.ChainId, txHash, false)
Expand All @@ -169,19 +169,19 @@ func Test_ParseInboundAsDeposit(t *testing.T) {

// create observer
chainParams := sample.ChainParams(chain.ChainId)
chainParams.GatewayAddress = GatewayAddressTest
chainParams.GatewayAddress = testutils.GatewayAddresses[chain.ChainId]
ob, err := observer.NewObserver(chain, nil, *chainParams, nil, nil, database, base.DefaultLogger(), nil)
require.NoError(t, err)

// expected result
sender := "AKbG83jg2V65R7XvaPFrnUvUTWsFENEzDPbLJFEiAk6L"
sender := "AS48jKNQsDGkEdDvfwu1QpqjtqbCadrAq9nGXjFmdX3Z"
eventExpected := &clienttypes.InboundEvent{
SenderChainID: chain.ChainId,
Sender: sender,
Receiver: sender,
TxOrigin: sender,
Amount: 1280,
Memo: []byte("hello this is a good memo for you to enjoy"),
Amount: 100000,
Memo: []byte("0x7F8ae2ABb69A558CE6bAd546f25F0464D9e09e5B4955a3F38ff86ae92A914445099caa8eA2B9bA32"),
BlockNumber: txResult.Slot,
TxHash: txHash,
Index: 0, // not a EVM smart contract call
Expand Down
8 changes: 8 additions & 0 deletions zetaclient/config/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ const (

// KeyringBackendFile is the file Cosmos keyring backend
KeyringBackendFile KeyringBackend = "file"

// DefaultRelayerKeyPath is the default path that relayer keys are stored
DefaultRelayerKeyPath = "~/.zetacored/relayer-keys"
)

// ClientConfiguration is a subset of zetaclient config that is used by zetacore client
Expand Down Expand Up @@ -163,6 +166,11 @@ func (c Config) GetKeyringBackend() KeyringBackend {
func (c Config) GetRelayerKeyPath() string {
c.mu.RLock()
defer c.mu.RUnlock()

// use default path if not configured
if c.RelayerKeyPath == "" {
return DefaultRelayerKeyPath
}
return c.RelayerKeyPath
}

Expand Down
16 changes: 16 additions & 0 deletions zetaclient/config/types_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package config_test

import (
"testing"

"github.com/stretchr/testify/require"
"github.com/zeta-chain/zetacore/zetaclient/config"
)

func Test_GetRelayerKeyPath(t *testing.T) {
// create config
cfg := config.New(false)

// should return default relayer key path
require.Equal(t, config.DefaultRelayerKeyPath, cfg.GetRelayerKeyPath())
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
{
"slot": 321701608,
"blockTime": 1724732369,
"transaction": {
"signatures": [
"MS3MPLN7hkbyCZFwKqXcg8fmEvQMD74fN6Ps2LSWXJoRxPW5ehaxBorK9q1JFVbqnAvu9jXm6ertj7kT7HpYw1j"
],
"message": {
"accountKeys": [
"AS48jKNQsDGkEdDvfwu1QpqjtqbCadrAq9nGXjFmdX3Z",
"2f9SLuUNb7TNeM6gzBwT4ZjbL5ZyKzzHg1Ce9yiquEjj",
"11111111111111111111111111111111",
"ZETAjseVjuFsxdRxo6MmTCvqFwb3ZHUx56Co3vCmGis"
],
"header": {
"numRequiredSignatures": 1,
"numReadonlySignedAccounts": 0,
"numReadonlyUnsignedAccounts": 2
},
"recentBlockhash": "41txNvjedo2eu6aAofQfyLskAcgtrtgch9RpqnrKcv1a",
"instructions": [
{
"programIdIndex": 3,
"accounts": [0, 1, 2],
"data": "4ALHYcAj3zFsNjmfeq7nDK1E8BsxRQRzhLjrqzmjYzL97Qkiz4rP1iQePmFAehfFEET7uczYLhhEVhtndBYNNm6ekHSkgsLzYDeSD2JSudHa6D5tqhVGjvXZ7qEouPiy9eptZfuYHE9X"
}
]
}
},
"meta": {
"err": null,
"fee": 5000,
"preBalances": [9999364000, 1001447680, 1, 1141440],
"postBalances": [9999259000, 1001547680, 1, 1141440],
"innerInstructions": [
{
"index": 0,
"instructions": [
{
"programIdIndex": 2,
"accounts": [0, 1],
"data": "3Bxs4ThwQbE4vyj5"
}
]
}
],
"preTokenBalances": [],
"postTokenBalances": [],
"logMessages": [
"Program ZETAjseVjuFsxdRxo6MmTCvqFwb3ZHUx56Co3vCmGis invoke [1]",
"Program log: Instruction: Deposit",
"Program 11111111111111111111111111111111 invoke [2]",
"Program 11111111111111111111111111111111 success",
"Program log: AS48jKNQsDGkEdDvfwu1QpqjtqbCadrAq9nGXjFmdX3Z deposits 100000 lamports to PDA",
"Program ZETAjseVjuFsxdRxo6MmTCvqFwb3ZHUx56Co3vCmGis consumed 17006 of 200000 compute units",
"Program ZETAjseVjuFsxdRxo6MmTCvqFwb3ZHUx56Co3vCmGis success"
],
"status": { "Ok": null },
"rewards": [],
"loadedAddresses": { "readonly": [], "writable": [] },
"computeUnitsConsumed": 17006
},
"version": 0
}
2 changes: 1 addition & 1 deletion zetaclient/testutils/constant.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const (
// GatewayAddresses contains constants gateway addresses for testing
var GatewayAddresses = map[int64]string{
// Gateway address on Solana devnet
chains.SolanaDevnet.ChainId: "94U5AHQMKkV5txNJ17QPXWoh474PheGou6cNP2FEuL1d",
chains.SolanaDevnet.ChainId: "ZETAjseVjuFsxdRxo6MmTCvqFwb3ZHUx56Co3vCmGis",
}

// ConnectorAddresses contains constants ERC20 connector addresses for testing
Expand Down

0 comments on commit 7b34d1d

Please sign in to comment.