Skip to content
Open
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
18 changes: 10 additions & 8 deletions e2e/interchaintestv8/solana/solana.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func (s *Solana) NewTransactionFromInstructions(payerPubKey solana.PublicKey, in
)
}

// SignTx signs a transaction with the provided signers, broadcasts it, and confirms it.
// SignTx signs a transaction with the provided signers, broadcasts it, and confirms it is finalized.
func (s *Solana) SignAndBroadcastTx(ctx context.Context, tx *solana.Transaction, signers ...*solana.Wallet) (solana.Signature, error) {
_, err := s.SignTx(ctx, tx, signers...)
if err != nil {
Expand Down Expand Up @@ -112,6 +112,7 @@ func confirmationStatusLevel(status rpc.ConfirmationStatusType) int {
}
}

// Waits for transaction reaching status
func (s *Solana) WaitForTxStatus(txSig solana.Signature, status rpc.ConfirmationStatusType) error {
return testutil.WaitForCondition(time.Second*30, time.Second, func() (bool, error) {
out, err := s.RPCClient.GetSignatureStatuses(context.TODO(), false, txSig)
Expand Down Expand Up @@ -188,14 +189,13 @@ func (s *Solana) WaitForProgramAvailabilityWithTimeout(ctx context.Context, prog
return false
}

// SignAndBroadcastTxWithRetry retries transaction broadcasting with default timeout
func (s *Solana) SignAndBroadcastTxWithRetry(ctx context.Context, tx *solana.Transaction, signers ...*solana.Wallet) (solana.Signature, error) {
return s.SignAndBroadcastTxWithRetryTimeout(ctx, tx, 30, signers...)
// SignTx signs a transaction with the provided signers, broadcasts it, and confirms it is finalized, retries with default timeout
func (s *Solana) SignAndBroadcastTxWithRetry(ctx context.Context, tx *solana.Transaction, wallet *solana.Wallet) (solana.Signature, error) {
return s.SignAndBroadcastTxWithRetryTimeout(ctx, tx, wallet, 30)
}

// SignAndBroadcastTxWithRetryTimeout retries transaction broadcasting with specified timeout
// It refreshes the blockhash on each attempt to handle expired blockhashes
func (s *Solana) SignAndBroadcastTxWithRetryTimeout(ctx context.Context, tx *solana.Transaction, timeoutSeconds int, signers ...*solana.Wallet) (solana.Signature, error) {
// SignTx signs a transaction with the provided signers, broadcasts it, and confirms it is finalized, retries with timeout
func (s *Solana) SignAndBroadcastTxWithRetryTimeout(ctx context.Context, tx *solana.Transaction, wallet *solana.Wallet, timeoutSeconds int) (solana.Signature, error) {
var lastErr error
for range timeoutSeconds {
// Refresh blockhash on each retry attempt (blockhashes expire after ~60 seconds)
Expand All @@ -207,7 +207,7 @@ func (s *Solana) SignAndBroadcastTxWithRetryTimeout(ctx context.Context, tx *sol
}
tx.Message.RecentBlockhash = recent.Value.Blockhash

sig, err := s.SignAndBroadcastTx(ctx, tx, signers...)
sig, err := s.SignAndBroadcastTx(ctx, tx, wallet)
if err == nil {
return sig, nil
}
Expand All @@ -217,10 +217,12 @@ func (s *Solana) SignAndBroadcastTxWithRetryTimeout(ctx context.Context, tx *sol
return solana.Signature{}, fmt.Errorf("transaction broadcast timed out after %d seconds: %w", timeoutSeconds, lastErr)
}

// SignTx signs a transaction with the provided signers, broadcasts it, and confirms it is in confirmed status
func (s *Solana) SignAndBroadcastTxWithConfirmedStatus(ctx context.Context, tx *solana.Transaction, wallet *solana.Wallet) (solana.Signature, error) {
return s.SignAndBroadcastTxWithOpts(ctx, tx, wallet, rpc.ConfirmationStatusConfirmed)
}

// SignTx signs a transaction with the provided signers, broadcasts it, and confirms it is in requested status
func (s *Solana) SignAndBroadcastTxWithOpts(ctx context.Context, tx *solana.Transaction, wallet *solana.Wallet, status rpc.ConfirmationStatusType) (solana.Signature, error) {
_, err := s.SignTx(ctx, tx, wallet)
if err != nil {
Expand Down
35 changes: 15 additions & 20 deletions e2e/interchaintestv8/solana_gmp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -418,10 +418,9 @@ func (s *IbcEurekaSolanaTestSuite) Test_GMPCounterFromCosmos() {
DstClientId: SolanaClientID,
})
s.Require().NoError(err, "Relayer Update Client failed")
s.Require().NotEmpty(updateResp.Txs, "Relayer Update client should return chunked transactions")
s.Require().NotEmpty(updateResp.Tx, "Relayer Update client should return chunked transactions")

s.submitChunkedUpdateClient(ctx, updateResp, s.SolanaUser)
s.T().Logf("%s: Updated Tendermint client on Solana using %d chunked transactions", userLabel, len(updateResp.Txs))

// Now retrieve and relay the GMP packet
resp, err := s.RelayerClient.RelayByTx(context.Background(), &relayertypes.RelayByTxRequest{
Expand All @@ -432,8 +431,8 @@ func (s *IbcEurekaSolanaTestSuite) Test_GMPCounterFromCosmos() {
DstClientId: SolanaClientID,
})
s.Require().NoError(err)
s.Require().NotEmpty(resp.Txs, "Relay should return chunked transactions")
s.T().Logf("%s: Retrieved %d relay transactions (chunks + final instructions)", userLabel, len(resp.Txs))
s.Require().NotEmpty(resp.Tx, "Relay should return chunked transactions")
s.T().Logf("%s: Retrieved %d relay transactions (chunks + final instructions)", userLabel, len(resp.Tx))

// Execute on Solana using chunked submission
solanaRelayTxSig = s.submitChunkedRelayPackets(ctx, resp, s.SolanaUser)
Expand Down Expand Up @@ -715,10 +714,9 @@ func (s *IbcEurekaSolanaTestSuite) Test_GMPSPLTokenTransferFromCosmos() {
DstClientId: SolanaClientID,
})
s.Require().NoError(err, "Relayer Update Client failed")
s.Require().NotEmpty(updateResp.Txs, "Relayer Update client should return chunked transactions")
s.Require().NotEmpty(updateResp.Tx, "Relayer Update client should return chunked transactions")

s.submitChunkedUpdateClient(ctx, updateResp, s.SolanaUser)
s.T().Logf("Updated Tendermint client on Solana using %d chunked transactions", len(updateResp.Txs))
}))

s.Require().True(s.Run("Retrieve relay tx from relayer", func() {
Expand All @@ -730,8 +728,7 @@ func (s *IbcEurekaSolanaTestSuite) Test_GMPSPLTokenTransferFromCosmos() {
DstClientId: SolanaClientID,
})
s.Require().NoError(err)
s.Require().NotEmpty(resp.Txs, "Relay should return chunked transactions")
s.T().Logf("Retrieved %d relay transactions (chunks + final instructions)", len(resp.Txs))
s.Require().NotEmpty(resp.Tx, "Relay should return chunked transactions")

solanaRelayTxSig = s.submitChunkedRelayPackets(ctx, resp, s.SolanaUser)
s.T().Logf("SPL transfer executed on Solana: %s", solanaRelayTxSig)
Expand Down Expand Up @@ -830,8 +827,8 @@ func (s *IbcEurekaSolanaTestSuite) createSPLTokenMint(ctx context.Context, decim
return solanago.PublicKey{}, err
}

// Sign and broadcast with both payer and mint account (with retry)
_, err = s.SolanaChain.SignAndBroadcastTxWithRetry(ctx, tx, s.SolanaUser, mintAccount)
// Sign and broadcast with both payer and mint account
_, err = s.SolanaChain.SignAndBroadcastTx(ctx, tx, s.SolanaUser, mintAccount)
if err != nil {
return solanago.PublicKey{}, err
}
Expand Down Expand Up @@ -880,8 +877,8 @@ func (s *IbcEurekaSolanaTestSuite) createTokenAccount(ctx context.Context, mint,
return solanago.PublicKey{}, err
}

// Sign and broadcast with both payer and token account (with retry)
_, err = s.SolanaChain.SignAndBroadcastTxWithRetry(ctx, tx, s.SolanaUser, tokenAccount)
// Sign and broadcast with both payer and token account
_, err = s.SolanaChain.SignAndBroadcastTx(ctx, tx, s.SolanaUser, tokenAccount)
if err != nil {
return solanago.PublicKey{}, err
}
Expand Down Expand Up @@ -1198,10 +1195,10 @@ func (s *IbcEurekaSolanaTestSuite) Test_GMPSendCallFromSolana() {
DstClientId: SolanaClientID,
})
s.Require().NoError(err, "Relayer Update Client failed")
s.Require().NotEmpty(resp.Txs, "Relayer Update client should return transactions")
s.Require().NotEmpty(resp.Tx, "Relayer Update client should return transactions")

s.submitChunkedUpdateClient(ctx, resp, s.SolanaUser)
s.T().Logf("Successfully updated Tendermint client on Solana using %d transaction(s)", len(resp.Txs))
s.T().Logf("Successfully updated Tendermint client on Solana using %d transaction(s)", len(resp.Tx))
}))

s.Require().True(s.Run("Relay acknowledgement", func() {
Expand All @@ -1213,8 +1210,7 @@ func (s *IbcEurekaSolanaTestSuite) Test_GMPSendCallFromSolana() {
DstClientId: SolanaClientID,
})
s.Require().NoError(err)
s.Require().NotEmpty(resp.Txs, "Relay should return chunked transactions")
s.T().Logf("Retrieved %d relay transactions (chunks + final instructions)", len(resp.Txs))
s.Require().NotEmpty(resp.Tx, "Relay should return chunked transactions")

sig := s.submitChunkedRelayPackets(ctx, resp, s.SolanaUser)
s.T().Logf("Acknowledgement transaction broadcasted: %s", sig)
Expand Down Expand Up @@ -1417,10 +1413,9 @@ func (s *IbcEurekaSolanaTestSuite) Test_GMPTimeoutFromSolana() {
DstClientId: SolanaClientID,
})
s.Require().NoError(err, "Relayer Update Client failed")
s.Require().NotEmpty(resp.Txs, "Relayer Update client should return transactions")
s.Require().NotEmpty(resp.Tx, "Relayer Update client should return transactions")

s.submitChunkedUpdateClient(ctx, resp, s.SolanaUser)
s.T().Logf("Successfully updated Tendermint client on Solana using %d transaction(s)", len(resp.Txs))
}))

s.Require().True(s.Run("Relay timeout transaction", func() {
Expand All @@ -1432,8 +1427,8 @@ func (s *IbcEurekaSolanaTestSuite) Test_GMPTimeoutFromSolana() {
DstClientId: SolanaClientID,
})
s.Require().NoError(err)
s.Require().NotEmpty(resp.Txs, "Relay should return chunked transactions")
s.T().Logf("Retrieved %d relay transactions (chunks + final instructions)", len(resp.Txs))
s.Require().NotEmpty(resp.Tx, "Relay should return chunked transactions")
s.T().Logf("Retrieved %d relay transactions (chunks + final instructions)", len(resp.Tx))

sig := s.submitChunkedRelayPackets(ctx, resp, s.SolanaUser)
s.T().Logf("Timeout transaction broadcasted: %s", sig)
Expand Down
Loading
Loading