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 2 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
12 changes: 12 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# CHANGELOG

## Unreleased

### Features

### Tests

### Refactor

### 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
18 changes: 12 additions & 6 deletions zetaclient/chains/solana/observer/inbound.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,17 +100,23 @@ func (ob *Observer) ObserveInbound(ctx context.Context) error {

// process successfully signature only
if sig.Err == nil {
txResult, err := ob.solClient.GetTransaction(ctx, sig.Signature, &rpc.GetTransactionOpts{})
maxTxVersion := rpc.MaxSupportedTransactionVersion0
txResult, err := solanarpc.GetTransactionWithMaxVersion(ctx, ob.solClient, sig.Signature, &maxTxVersion)
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 {
// we have to re-scan this signature on next ticker
return errors.Wrapf(err, "error FilterInboundEventAndVote for chain %d sig %s", chainID, sigString)
switch {
case txResult == nil:
ob.Logger().Inbound.Warn().Msgf("ObserveInbound: skip unsupported transaction sig %s", sigString)
ws4charlie marked this conversation as resolved.
Show resolved Hide resolved
default:
// filter inbound events and vote
err = ob.FilterInboundEventsAndVote(ctx, txResult)
if err != nil {
// we have to re-scan this signature on next ticker
return errors.Wrapf(err, "error FilterInboundEventAndVote for chain %d sig %s", chainID, sigString)
}
ws4charlie marked this conversation as resolved.
Show resolved Hide resolved
}
}

Expand Down
24 changes: 24 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 @@ package rpc

import (
"context"
"strings"
"time"

"github.com/gagliardetto/solana-go"
Expand All @@ -18,6 +19,10 @@ const (
// 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

// JSONRPCErrorCodeUnsupportedTransactionVersion
ws4charlie marked this conversation as resolved.
Show resolved Hide resolved
// see: https://github.com/solana-labs/solana/blob/master/rpc/src/rpc.rs#L7276
ErrorCodeUnsupportedTransactionVersion = "-32015"
ws4charlie marked this conversation as resolved.
Show resolved Hide resolved
)

// GetFirstSignatureForAddress searches the first signature for the given address.
Expand Down Expand Up @@ -122,6 +127,25 @@ func GetSignaturesForAddressUntil(
return allSignatures, nil
}

// GetTransactionWithMaxVersion fetches a transaction with the given signature and max version.
func GetTransactionWithMaxVersion(
ws4charlie marked this conversation as resolved.
Show resolved Hide resolved
ctx context.Context,
client interfaces.SolanaRPCClient,
signature solana.Signature,
maxTxVersion *uint64,
) (*rpc.GetTransactionResult, error) {
txResult, err := client.GetTransaction(ctx, signature, &rpc.GetTransactionOpts{
MaxSupportedTransactionVersion: maxTxVersion,
})

// skip unsupported transaction version error
if err != nil && strings.Contains(err.Error(), ErrorCodeUnsupportedTransactionVersion) {
return nil, nil
ws4charlie marked this conversation as resolved.
Show resolved Hide resolved
}

return txResult, err
}

// 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
31 changes: 31 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,42 @@ 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.GetTransactionWithMaxVersion(
ctx,
client,
txSig,
&solanarpc.MaxSupportedTransactionVersion0,
)
require.NoError(t, err)
require.NotNil(t, txResult)
})

t.Run("should skip the transaction if the version is not supported", func(t *testing.T) {
ctx := context.Background()
txResult, err := rpc.GetTransactionWithMaxVersion(ctx, client, txSig, nil)
require.NoError(t, err)
ws4charlie marked this conversation as resolved.
Show resolved Hide resolved
require.Nil(t, txResult)
})
}

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