From 8c72a5caf1b674348e3b5ffb9eb0c6ccaa29333a Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Fri, 6 Aug 2021 11:20:41 -0700 Subject: [PATCH 1/2] cosmos-sdk-rs: make `Tx::find_by_hash` use the `/tx` endpoint Notably this endpoint provides read-your-writes consistency with regard to transactions, whereas `/tx_search` does not. See also: tendermint/tendermint#6359 --- cosmrs/src/dev.rs | 19 +------------------ cosmrs/src/tx.rs | 16 +++------------- cosmrs/tests/integration.rs | 6 ++++-- 3 files changed, 8 insertions(+), 33 deletions(-) diff --git a/cosmrs/src/dev.rs b/cosmrs/src/dev.rs index a473cea4..94113b4d 100644 --- a/cosmrs/src/dev.rs +++ b/cosmrs/src/dev.rs @@ -3,10 +3,7 @@ //! This module contains support for integration testing against a //! Cosmos SDK-compatible full node (gaia) running inside of Docker. -use crate::{ - rpc::{self, Client}, - tx::{self, Tx}, -}; +use crate::rpc::{self, Client}; use std::{ffi::OsStr, panic, process, str, time::Duration}; use tokio::time; @@ -97,17 +94,3 @@ pub async fn poll_for_first_block(rpc_client: &rpc::HttpClient) { time::sleep(Duration::from_millis(200)).await; } } - -/// Wait for a transaction with the given hash to appear in the blockchain -pub async fn poll_for_tx(rpc_client: &rpc::HttpClient, tx_hash: &tx::Hash) -> Tx { - let attempts = 5; - - for _ in 0..attempts { - // TODO(tarcieri): handle not found errors - if let Ok(tx) = Tx::find_by_hash(rpc_client, tx_hash).await { - return tx; - } - } - - panic!("couldn't find transaction after {} attempts!", attempts); -} diff --git a/cosmrs/src/tx.rs b/cosmrs/src/tx.rs index eb2f570d..349dac9f 100644 --- a/cosmrs/src/tx.rs +++ b/cosmrs/src/tx.rs @@ -162,22 +162,12 @@ impl Tx { /// Use RPC to find a transaction by its hash. #[cfg(feature = "rpc")] #[cfg_attr(docsrs, doc(cfg(feature = "rpc")))] - pub async fn find_by_hash(rpc_client: &C, tx_hash: &Hash) -> Result + pub async fn find_by_hash(rpc_client: &C, tx_hash: Hash) -> Result where C: rpc::Client + Send + Sync, { - let query = rpc::query::Query::from(rpc::query::EventType::Tx) - .and_eq("tx.hash", tx_hash.to_string()); - - let response = rpc_client - .tx_search(query, false, 1, 1, rpc::Order::Ascending) - .await?; - - if response.total_count == 1 { - Tx::from_bytes(response.txs[0].tx.as_bytes()) - } else { - Err(Error::TxNotFound { hash: *tx_hash }.into()) - } + let response = rpc_client.tx(tx_hash, false).await?; + Tx::from_bytes(response.tx.as_bytes()) } } diff --git a/cosmrs/tests/integration.rs b/cosmrs/tests/integration.rs index 748ec4f6..53b50323 100644 --- a/cosmrs/tests/integration.rs +++ b/cosmrs/tests/integration.rs @@ -8,7 +8,7 @@ use cosmrs::{ bank::MsgSend, crypto::secp256k1, dev, rpc, - tx::{self, AccountNumber, Fee, MsgType, SignDoc, SignerInfo}, + tx::{self, AccountNumber, Fee, MsgType, SignDoc, SignerInfo, Tx}, Coin, }; use std::{panic, str}; @@ -93,7 +93,9 @@ fn msg_send() { panic!("deliver_tx failed: {:?}", tx_commit_response.deliver_tx); } - let tx = dev::poll_for_tx(&rpc_client, &tx_commit_response.hash).await; + let tx = Tx::find_by_hash(&rpc_client, tx_commit_response.hash) + .await + .unwrap(); assert_eq!(&tx_body, &tx.body); assert_eq!(&auth_info, &tx.auth_info); }) From b95b14e2274bc8fafd9b47914dac6eb700ccdf79 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Mon, 27 Sep 2021 14:39:24 -0600 Subject: [PATCH 2/2] cosmrs: add back `dev::poll_for_tx` The `/tx` endpoint is still sporadically returning a not found error: https://github.com/cosmos/cosmos-rust/pull/116/checks?check_run_id=3724891908 This adds back the polling behavior to try repeatedly if this occurs --- cosmrs/src/dev.rs | 19 ++++++++++++++++++- cosmrs/tests/integration.rs | 6 ++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/cosmrs/src/dev.rs b/cosmrs/src/dev.rs index 94113b4d..d30c43e6 100644 --- a/cosmrs/src/dev.rs +++ b/cosmrs/src/dev.rs @@ -3,7 +3,10 @@ //! This module contains support for integration testing against a //! Cosmos SDK-compatible full node (gaia) running inside of Docker. -use crate::rpc::{self, Client}; +use crate::{ + rpc::{self, Client}, + tx::{self, Tx}, +}; use std::{ffi::OsStr, panic, process, str, time::Duration}; use tokio::time; @@ -94,3 +97,17 @@ pub async fn poll_for_first_block(rpc_client: &rpc::HttpClient) { time::sleep(Duration::from_millis(200)).await; } } + +/// Wait for a transaction with the given hash to appear in the blockchain +pub async fn poll_for_tx(rpc_client: &rpc::HttpClient, tx_hash: tx::Hash) -> Tx { + let attempts = 5; + + for _ in 0..attempts { + // TODO(tarcieri): handle not found errors + if let Ok(tx) = Tx::find_by_hash(rpc_client, tx_hash).await { + return tx; + } + } + + panic!("couldn't find transaction after {} attempts!", attempts); +} diff --git a/cosmrs/tests/integration.rs b/cosmrs/tests/integration.rs index 53b50323..26d368f7 100644 --- a/cosmrs/tests/integration.rs +++ b/cosmrs/tests/integration.rs @@ -8,7 +8,7 @@ use cosmrs::{ bank::MsgSend, crypto::secp256k1, dev, rpc, - tx::{self, AccountNumber, Fee, MsgType, SignDoc, SignerInfo, Tx}, + tx::{self, AccountNumber, Fee, MsgType, SignDoc, SignerInfo}, Coin, }; use std::{panic, str}; @@ -93,9 +93,7 @@ fn msg_send() { panic!("deliver_tx failed: {:?}", tx_commit_response.deliver_tx); } - let tx = Tx::find_by_hash(&rpc_client, tx_commit_response.hash) - .await - .unwrap(); + let tx = dev::poll_for_tx(&rpc_client, tx_commit_response.hash).await; assert_eq!(&tx_body, &tx.body); assert_eq!(&auth_info, &tx.auth_info); })