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: skip solana unsupported transaction version #3206

Merged
merged 8 commits into from
Nov 25, 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 @@ -10,6 +10,10 @@

* [3170](https://github.com/zeta-chain/node/pull/3170) - revamp TSS package in zetaclient

### Fixes

* [3206](https://github.com/zeta-chain/node/pull/3206) - skip Solana unsupported transaction version to not block inbound observation

## v23.0.0

### Features
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ require (
github.com/emicklei/proto v1.11.1
github.com/ethereum/go-ethereum v1.13.15
github.com/fatih/color v1.14.1
github.com/gagliardetto/solana-go v1.10.0
github.com/gagliardetto/solana-go v1.12.0
github.com/golang/mock v1.6.0
github.com/golang/protobuf v1.5.4
github.com/gorilla/mux v1.8.0
Expand Down Expand Up @@ -282,7 +282,7 @@ require (
github.com/zondax/hid v0.9.2 // indirect
github.com/zondax/ledger-go v0.14.3 // indirect
go.etcd.io/bbolt v1.4.0-alpha.0.0.20240404170359-43604f3112c5 // indirect
go.mongodb.org/mongo-driver v1.11.0 // indirect
go.mongodb.org/mongo-driver v1.12.2 // indirect
go.nhat.io/matcher/v2 v2.0.0 // indirect
go.nhat.io/wait v0.1.0 // indirect
go.opencensus.io v0.24.0 // indirect
Expand Down
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,8 @@ github.com/gagliardetto/gofuzz v1.2.2 h1:XL/8qDMzcgvR4+CyRQW9UGdwPRPMHVJfqQ/uMvS
github.com/gagliardetto/gofuzz v1.2.2/go.mod h1:bkH/3hYLZrMLbfYWA0pWzXmi5TTRZnu4pMGZBkqMKvY=
github.com/gagliardetto/solana-go v1.10.0 h1:lDuHGC+XLxw9j8fCHBZM9tv4trI0PVhev1m9NAMaIdM=
github.com/gagliardetto/solana-go v1.10.0/go.mod h1:afBEcIRrDLJst3lvAahTr63m6W2Ns6dajZxe2irF7Jg=
github.com/gagliardetto/solana-go v1.12.0 h1:rzsbilDPj6p+/DOPXBMLhwMZeBgeRuXjm5zQFCoXgsg=
github.com/gagliardetto/solana-go v1.12.0/go.mod h1:l/qqqIN6qJJPtxW/G1PF4JtcE3Zg2vD2EliZrr9Gn5k=
github.com/gagliardetto/treeout v0.1.4 h1:ozeYerrLCmCubo1TcIjFiOWTTGteOOHND1twdFpgwaw=
github.com/gagliardetto/treeout v0.1.4/go.mod h1:loUefvXTrlRG5rYmJmExNryyBRh8f89VZhmMOyCyqok=
github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61/go.mod h1:Q0X6pkwTILDlzrGEckF6HKjXe48EgsY/l7K7vhY4MW8=
Expand Down Expand Up @@ -1501,7 +1503,9 @@ github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV
github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
Expand Down Expand Up @@ -1545,6 +1549,8 @@ go.etcd.io/bbolt v1.4.0-alpha.0.0.20240404170359-43604f3112c5/go.mod h1:eW0HG9/o
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
go.mongodb.org/mongo-driver v1.11.0 h1:FZKhBSTydeuffHj9CBjXlR8vQLee1cQyTWYPA6/tqiE=
go.mongodb.org/mongo-driver v1.11.0/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8=
go.mongodb.org/mongo-driver v1.12.2 h1:gbWY1bJkkmUB9jjZzcdhOL8O85N9H+Vvsf2yFN0RDws=
go.mongodb.org/mongo-driver v1.12.2/go.mod h1:/rGBTebI3XYboVmgz+Wv3Bcbl3aD0QF9zl6kDDw18rQ=
go.nhat.io/aferomock v0.4.0 h1:gs3nJzIqAezglUuaPfautAmZwulwRWLcfSSzdK4YCC0=
go.nhat.io/aferomock v0.4.0/go.mod h1:msi5MDOtJ/AroUa/lDc3jVGOILM4SKP//4yBRImOvkI=
go.nhat.io/grpcmock v0.25.0 h1:zk03vvA60w7UrnurZbqL4wxnjmJz1Kuyb7ig2MF+n4c=
Expand Down
23 changes: 0 additions & 23 deletions pkg/crypto/privkey.go

This file was deleted.

67 changes: 0 additions & 67 deletions pkg/crypto/privkey_test.go

This file was deleted.

35 changes: 22 additions & 13 deletions zetaclient/chains/solana/observer/inbound.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,30 +100,39 @@

// process successfully signature only
if sig.Err == nil {
txResult, err := ob.solClient.GetTransaction(ctx, sig.Signature, &rpc.GetTransactionOpts{})
if err != nil {
// we have to re-scan this signature on next ticker
return errors.Wrapf(err, "error GetTransaction for chain %d sig %s", chainID, sigString)
}

// filter inbound events and vote
err = ob.FilterInboundEventsAndVote(ctx, txResult)
if err != nil {
txResult, err := solanarpc.GetTransaction(ctx, ob.solClient, sig.Signature)
switch {
case errors.Is(err, solanarpc.ErrUnsupportedTxVersion):
ob.Logger().Inbound.Warn().
Stringer("tx.signature", sig.Signature).
Msg("ObserveInbound: skip unsupported transaction")

Check warning on line 108 in zetaclient/chains/solana/observer/inbound.go

View check run for this annotation

Codecov / codecov/patch

zetaclient/chains/solana/observer/inbound.go#L103-L108

Added lines #L103 - L108 were not covered by tests
// just save the sig to last scanned txs
case err != nil:

Check warning on line 110 in zetaclient/chains/solana/observer/inbound.go

View check run for this annotation

Codecov / codecov/patch

zetaclient/chains/solana/observer/inbound.go#L110

Added line #L110 was not covered by tests
// we have to re-scan this signature on next ticker
return errors.Wrapf(err, "error FilterInboundEventAndVote for chain %d sig %s", chainID, sigString)
return errors.Wrapf(err, "error GetTransaction for sig %s", sigString)
default:
// filter inbound events and vote
if err = ob.FilterInboundEventsAndVote(ctx, txResult); err != nil {
// we have to re-scan this signature on next ticker
return errors.Wrapf(err, "error FilterInboundEventAndVote for sig %s", sigString)
}

Check warning on line 118 in zetaclient/chains/solana/observer/inbound.go

View check run for this annotation

Codecov / codecov/patch

zetaclient/chains/solana/observer/inbound.go#L112-L118

Added lines #L112 - L118 were not covered by tests
}
}

// signature scanned; save last scanned signature to both memory and db, ignore db error
if err := ob.SaveLastTxScanned(sigString, sig.Slot); err != nil {
if err = ob.SaveLastTxScanned(sigString, sig.Slot); err != nil {

Check warning on line 123 in zetaclient/chains/solana/observer/inbound.go

View check run for this annotation

Codecov / codecov/patch

zetaclient/chains/solana/observer/inbound.go#L123

Added line #L123 was not covered by tests
ob.Logger().
Inbound.Error().
Err(err).
Msgf("ObserveInbound: error saving last sig %s for chain %d", sigString, chainID)
Str("tx.signature", sigString).
Msg("ObserveInbound: error saving last sig")

Check warning on line 128 in zetaclient/chains/solana/observer/inbound.go

View check run for this annotation

Codecov / codecov/patch

zetaclient/chains/solana/observer/inbound.go#L127-L128

Added lines #L127 - L128 were not covered by tests
}

ob.Logger().
Inbound.Info().
Msgf("ObserveInbound: last scanned sig is %s for chain %d in slot %d", sigString, chainID, sig.Slot)
Str("tx.signature", sigString).
Uint64("tx.slot", sig.Slot).
Msg("ObserveInbound: last scanned sig")

Check warning on line 135 in zetaclient/chains/solana/observer/inbound.go

View check run for this annotation

Codecov / codecov/patch

zetaclient/chains/solana/observer/inbound.go#L133-L135

Added lines #L133 - L135 were not covered by tests

// take a rest if max signatures per ticker is reached
if len(signatures)-i >= MaxSignaturesPerTicker {
Expand Down
28 changes: 28 additions & 0 deletions zetaclient/chains/solana/rpc/rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import (
"context"
"strings"
"time"

"github.com/gagliardetto/solana-go"
Expand All @@ -18,8 +19,14 @@
// RPCAlertLatency is the default threshold for RPC latency to be considered unhealthy and trigger an alert.
// The 'HEALTH_CHECK_SLOT_DISTANCE' is default to 150 slots, which is 150 * 0.4s = 60s
RPCAlertLatency = time.Duration(60) * time.Second

// see: https://github.com/solana-labs/solana/blob/master/rpc/src/rpc.rs#L7276
errorCodeUnsupportedTransactionVersion = "-32015"
)

// ErrUnsupportedTxVersion is returned when the transaction version is not supported by zetaclient
var ErrUnsupportedTxVersion = errors.New("unsupported tx version")

// GetFirstSignatureForAddress searches the first signature for the given address.
// Note: make sure that the rpc provider used has enough transaction history.
func GetFirstSignatureForAddress(
Expand Down Expand Up @@ -122,6 +129,27 @@
return allSignatures, nil
}

// GetTransaction fetches a transaction with the given signature.
// Note that it might return ErrUnsupportedTxVersion (for tx that we don't support yet).
func GetTransaction(
ctx context.Context,
client interfaces.SolanaRPCClient,
sig solana.Signature,
) (*rpc.GetTransactionResult, error) {
txResult, err := client.GetTransaction(ctx, sig, &rpc.GetTransactionOpts{
MaxSupportedTransactionVersion: &rpc.MaxSupportedTransactionVersion0,
})

switch {
case err != nil && strings.Contains(err.Error(), errorCodeUnsupportedTransactionVersion):
return nil, ErrUnsupportedTxVersion
case err != nil:
return nil, err
default:
return txResult, nil

Check warning on line 149 in zetaclient/chains/solana/rpc/rpc.go

View check run for this annotation

Codecov / codecov/patch

zetaclient/chains/solana/rpc/rpc.go#L138-L149

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

// CheckRPCStatus checks the RPC status of the solana chain
func CheckRPCStatus(ctx context.Context, client interfaces.SolanaRPCClient, privnet bool) (time.Time, error) {
// query solana health (always return "ok" unless --trusted-validator is provided)
Expand Down
19 changes: 19 additions & 0 deletions zetaclient/chains/solana/rpc/rpc_live_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,30 @@ func Test_SolanaRPCLive(t *testing.T) {
return
}

LiveTest_GetTransactionWithVersion(t)
LiveTest_GetFirstSignatureForAddress(t)
LiveTest_GetSignaturesForAddressUntil(t)
LiveTest_CheckRPCStatus(t)
}

func LiveTest_GetTransactionWithVersion(t *testing.T) {
// create a Solana devnet RPC client
client := solanarpc.New(solanarpc.DevNet_RPC)

// example transaction of version "0"
// https://explorer.solana.com/tx/Wqgj7hAaUUSfLzieN912G7GxyGHijzBZgY135NtuFtPRjevK8DnYjWwQZy7LAKFQZu582wsjuab2QP27VMUJzAi?cluster=devnet
txSig := solana.MustSignatureFromBase58(
"Wqgj7hAaUUSfLzieN912G7GxyGHijzBZgY135NtuFtPRjevK8DnYjWwQZy7LAKFQZu582wsjuab2QP27VMUJzAi",
)

t.Run("should get the transaction if the version is supported", func(t *testing.T) {
ctx := context.Background()
txResult, err := rpc.GetTransaction(ctx, client, txSig)
require.NoError(t, err)
require.NotNil(t, txResult)
})
}

func LiveTest_GetFirstSignatureForAddress(t *testing.T) {
// create a Solana devnet RPC client
client := solanarpc.New(solanarpc.DevNet_RPC)
Expand Down
4 changes: 2 additions & 2 deletions zetaclient/chains/solana/signer/signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import (
"github.com/zeta-chain/node/pkg/chains"
"github.com/zeta-chain/node/pkg/coin"
contracts "github.com/zeta-chain/node/pkg/contracts/solana"
"github.com/zeta-chain/node/pkg/crypto"
"github.com/zeta-chain/node/x/crosschain/types"
observertypes "github.com/zeta-chain/node/x/observer/types"
"github.com/zeta-chain/node/zetaclient/chains/base"
Expand Down Expand Up @@ -86,10 +85,11 @@ func NewSigner(

// construct Solana private key if present
if relayerKey != nil {
signer.relayerKey, err = crypto.SolanaPrivateKeyFromString(relayerKey.PrivateKey)
privKey, err := solana.PrivateKeyFromBase58(relayerKey.PrivateKey)
if err != nil {
return nil, errors.Wrap(err, "unable to construct solana private key")
}
signer.relayerKey = &privKey
logger.Std.Info().Msgf("Solana relayer address: %s", signer.relayerKey.PublicKey())
} else {
logger.Std.Info().Msg("Solana relayer key is not provided")
Expand Down
5 changes: 3 additions & 2 deletions zetaclient/keys/relayer_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"os"
"path/filepath"

"github.com/gagliardetto/solana-go"
"github.com/pkg/errors"

"github.com/zeta-chain/node/pkg/chains"
Expand All @@ -23,7 +24,7 @@ func (rk RelayerKey) ResolveAddress(network chains.Network) (string, string, err

switch network {
case chains.Network_solana:
privKey, err := crypto.SolanaPrivateKeyFromString(rk.PrivateKey)
privKey, err := solana.PrivateKeyFromBase58(rk.PrivateKey)
if err != nil {
return "", "", errors.Wrap(err, "unable to construct solana private key")
}
Expand Down Expand Up @@ -128,7 +129,7 @@ func ReadRelayerKeyFromFile(fileName string) (*RelayerKey, error) {
func IsRelayerPrivateKeyValid(privateKey string, network chains.Network) bool {
switch network {
case chains.Network_solana:
_, err := crypto.SolanaPrivateKeyFromString(privateKey)
_, err := solana.PrivateKeyFromBase58(privateKey)
if err != nil {
return false
}
Expand Down
Loading