testing: Retry on Tx::Dropped for lightclinet only

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
This commit is contained in:
Alexandru Vasile
2024-03-01 11:25:02 +02:00
parent 3c58c5ec88
commit 0248343a2b
11 changed files with 164 additions and 117 deletions
@@ -2,13 +2,15 @@
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
// see LICENSE for license details.
use crate::{test_context, utils::node_runtime};
use crate::test_context;
use codec::{Compact, Encode};
use futures::StreamExt;
#[cfg(lightclient)]
use subxt::client::OnlineClientT;
#[cfg(fullclient)]
use crate::utils::node_runtime;
#[cfg(fullclient)]
use subxt::config::signed_extensions::{ChargeAssetTxPayment, CheckMortality, CheckNonce};
#[cfg(fullclient)]
@@ -17,9 +19,10 @@ use subxt::config::DefaultExtrinsicParamsBuilder;
use subxt::config::SubstrateConfig;
#[cfg(fullclient)]
use subxt::utils::Era;
#[cfg(fullclient)]
use subxt_signer::sr25519::dev;
use subxt_metadata::Metadata;
use subxt_signer::sr25519::dev;
#[cfg(fullclient)]
#[tokio::test]
@@ -3,7 +3,7 @@
// see LICENSE for license details.
use crate::{
test_context,
submit_tx_wait_for_finalized_success, test_context,
utils::{node_runtime, wait_for_blocks},
};
use codec::{Decode, Encode};
@@ -137,11 +137,7 @@ async fn transaction_validation() {
.await
.expect("validation failed");
signed_extrinsic
.submit_and_watch()
.await
.unwrap()
.wait_for_finalized_success()
submit_tx_wait_for_finalized_success(&signed_extrinsic)
.await
.unwrap();
}
@@ -204,11 +200,7 @@ async fn external_signing() {
.sign_with_address_and_signature(&alice.public_key().into(), &signature.into());
// And now submit it.
extrinsic
.submit_and_watch()
.await
.unwrap()
.wait_for_finalized_success()
submit_tx_wait_for_finalized_success(&extrinsic)
.await
.unwrap();
}
@@ -258,12 +250,13 @@ async fn decode_a_module_error() {
// "unknown" module error from the assets pallet.
let freeze_unknown_asset = node_runtime::tx().assets().freeze(1, alice_addr);
let err = api
let signed_extrinsic = api
.tx()
.sign_and_submit_then_watch_default(&freeze_unknown_asset, &alice)
.create_signed(&freeze_unknown_asset, &alice, Default::default())
.await
.unwrap()
.wait_for_finalized_success()
.unwrap();
let err = submit_tx_wait_for_finalized_success(&signed_extrinsic)
.await
.expect_err("an 'unknown asset' error");
@@ -4,7 +4,7 @@
use crate::{
node_runtime::{self, balances, runtime_types, system},
test_context,
submit_tx_wait_for_finalized_success, test_context,
};
use codec::Decode;
use subxt::{
@@ -48,12 +48,12 @@ async fn tx_basic_transfer() -> Result<(), subxt::Error> {
.balances()
.transfer_allow_death(bob_address, 10_000);
let events = api
let signed_extrinsic = api
.tx()
.sign_and_submit_then_watch_default(&tx, &alice)
.await?
.wait_for_finalized_success()
.create_signed(&tx, &alice, Default::default())
.await?;
let events = submit_tx_wait_for_finalized_success(&signed_extrinsic).await?;
let event = events
.find_first::<balances::events::Transfer>()
.expect("Failed to decode balances::events::Transfer")
@@ -235,11 +235,12 @@ async fn multiple_sequential_transfers_work() -> Result<(), subxt::Error> {
.balances()
.transfer_allow_death(bob_address.clone(), 10_000);
for _ in 0..3 {
api.tx()
.sign_and_submit_then_watch_default(&tx, &alice)
.await?
.wait_for_finalized_success()
let signed_extrinsic = api
.tx()
.create_signed(&tx, &alice, Default::default())
.await?;
submit_tx_wait_for_finalized_success(&signed_extrinsic).await?;
}
let bob_post = api
@@ -282,10 +283,11 @@ async fn storage_balance_lock() -> Result<(), subxt::Error> {
runtime_types::pallet_staking::RewardDestination::Stash,
);
api.tx()
.sign_and_submit_then_watch_default(&tx, &bob_signer)
.await?
.wait_for_finalized_success()
let signed_extrinsic = api
.tx()
.create_signed(&tx, &bob_signer, Default::default())
.await?;
submit_tx_wait_for_finalized_success(&signed_extrinsic)
.await?
.find_first::<system::events::ExtrinsicSuccess>()?
.expect("No ExtrinsicSuccess Event found");
@@ -327,23 +329,24 @@ async fn transfer_error() {
.balances()
.transfer_allow_death(alice_addr, 100_000_000_000_000_000);
api.tx()
.sign_and_submit_then_watch_default(&to_bob_tx, &alice)
let signed_extrinsic = api
.tx()
.create_signed(&to_bob_tx, &alice, Default::default())
.await
.unwrap()
.wait_for_finalized_success()
.unwrap();
submit_tx_wait_for_finalized_success(&signed_extrinsic)
.await
.unwrap();
// When we try giving all of the funds back, Bob doesn't have
// anything left to pay transfer fees, so we hit an error.
let res = api
let signed_extrinsic = api
.tx()
.sign_and_submit_then_watch_default(&to_alice_tx, &bob)
.create_signed(&to_alice_tx, &bob, Default::default())
.await
.unwrap()
.wait_for_finalized_success()
.await;
.unwrap();
let res = submit_tx_wait_for_finalized_success(&signed_extrinsic).await;
assert!(
matches!(
@@ -367,12 +370,13 @@ async fn transfer_implicit_subscription() {
.balances()
.transfer_allow_death(bob.clone().into(), 10_000);
let event = api
let signed_extrinsic = api
.tx()
.sign_and_submit_then_watch_default(&to_bob_tx, &alice)
.create_signed(&to_bob_tx, &alice, Default::default())
.await
.unwrap()
.wait_for_finalized_success()
.unwrap();
let event = submit_tx_wait_for_finalized_success(&signed_extrinsic)
.await
.unwrap()
.find_first::<balances::events::Transfer>()
@@ -9,7 +9,7 @@ use crate::{
runtime_types::{pallet_contracts::wasm::Determinism, sp_weights::weight_v2::Weight},
system,
},
test_context, TestClient, TestConfig, TestContext,
submit_tx_wait_for_finalized_success, test_context, TestClient, TestConfig, TestContext,
};
use subxt::ext::futures::StreamExt;
use subxt::{tx::TxProgress, utils::MultiAddress, Config, Error};
@@ -54,13 +54,12 @@ impl ContractsTestContext {
.contracts()
.upload_code(code, None, Determinism::Enforced);
let events = self
let signed_extrinsic = self
.client()
.tx()
.sign_and_submit_then_watch_default(&upload_tx, &self.signer)
.await?
.wait_for_finalized_success()
.create_signed(&upload_tx, &self.signer, Default::default())
.await?;
let events = submit_tx_wait_for_finalized_success(&signed_extrinsic).await?;
let code_stored = events
.find_first::<events::CodeStored>()?
@@ -84,13 +83,12 @@ impl ContractsTestContext {
vec![], // salt
);
let events = self
let signed_extrinsic = self
.client()
.tx()
.sign_and_submit_then_watch_default(&instantiate_tx, &self.signer)
.await?
.wait_for_finalized_success()
.create_signed(&instantiate_tx, &self.signer, Default::default())
.await?;
let events = submit_tx_wait_for_finalized_success(&signed_extrinsic).await?;
let code_stored = events
.find_first::<events::CodeStored>()?
@@ -127,13 +125,12 @@ impl ContractsTestContext {
salt,
);
let result = self
let signed_extrinsic = self
.client()
.tx()
.sign_and_submit_then_watch_default(&instantiate_tx, &self.signer)
.await?
.wait_for_finalized_success()
.create_signed(&instantiate_tx, &self.signer, Default::default())
.await?;
let result = submit_tx_wait_for_finalized_success(&signed_extrinsic).await?;
tracing::info!("Instantiate result: {:?}", result);
let instantiated = result
@@ -11,7 +11,7 @@ use crate::{
},
staking,
},
test_context,
submit_tx_wait_for_finalized_success, test_context,
};
use assert_matches::assert_matches;
use subxt::error::{DispatchError, Error};
@@ -45,11 +45,12 @@ async fn validate_with_stash_account() {
.staking()
.validate(default_validator_prefs());
api.tx()
.sign_and_submit_then_watch_default(&tx, &alice_stash)
let signed_extrinsic = api
.tx()
.create_signed(&tx, &alice_stash, Default::default())
.await
.unwrap()
.wait_for_finalized_success()
.unwrap();
submit_tx_wait_for_finalized_success(&signed_extrinsic)
.await
.expect("should be successful");
}
@@ -65,12 +66,12 @@ async fn validate_not_possible_for_controller_account() -> Result<(), Error> {
.staking()
.validate(default_validator_prefs());
let announce_validator = api
let signed_extrinsic = api
.tx()
.sign_and_submit_then_watch_default(&tx, &alice)
.await?
.wait_for_finalized_success()
.await;
.create_signed(&tx, &alice, Default::default())
.await?;
let announce_validator = submit_tx_wait_for_finalized_success(&signed_extrinsic).await;
assert_matches!(announce_validator, Err(Error::Runtime(DispatchError::Module(err))) => {
let details = err.details().unwrap();
assert_eq!(details.pallet.name(), "Staking");
@@ -91,11 +92,12 @@ async fn nominate_with_stash_account() {
.staking()
.nominate(vec![bob.public_key().to_address()]);
api.tx()
.sign_and_submit_then_watch_default(&tx, &alice_stash)
let signed_extrinsic = api
.tx()
.create_signed(&tx, &alice_stash, Default::default())
.await
.unwrap()
.wait_for_finalized_success()
.unwrap();
submit_tx_wait_for_finalized_success(&signed_extrinsic)
.await
.expect("should be successful");
}
@@ -112,13 +114,12 @@ async fn nominate_not_possible_for_controller_account() -> Result<(), Error> {
.staking()
.nominate(vec![bob.public_key().to_address()]);
let nomination = api
let signed_extrinsic = api
.tx()
.sign_and_submit_then_watch_default(&tx, &alice)
.create_signed(&tx, &alice, Default::default())
.await
.unwrap()
.wait_for_finalized_success()
.await;
.unwrap();
let nomination = submit_tx_wait_for_finalized_success(&signed_extrinsic).await;
assert_matches!(nomination, Err(Error::Runtime(DispatchError::Module(err))) => {
let details = err.details().unwrap();
@@ -141,11 +142,12 @@ async fn chill_works_for_stash_only() -> Result<(), Error> {
let nominate_tx = node_runtime::tx()
.staking()
.nominate(vec![bob_stash.public_key().to_address()]);
api.tx()
.sign_and_submit_then_watch_default(&nominate_tx, &alice_stash)
.await?
.wait_for_finalized_success()
let signed_extrinsic = api
.tx()
.create_signed(&nominate_tx, &alice_stash, Default::default())
.await?;
submit_tx_wait_for_finalized_success(&signed_extrinsic).await?;
let ledger_addr = node_runtime::storage()
.staking()
@@ -161,12 +163,11 @@ async fn chill_works_for_stash_only() -> Result<(), Error> {
let chill_tx = node_runtime::tx().staking().chill();
let chill = api
let signed_extrinsic = api
.tx()
.sign_and_submit_then_watch_default(&chill_tx, &alice)
.await?
.wait_for_finalized_success()
.await;
.create_signed(&chill_tx, &alice, Default::default())
.await?;
let chill = submit_tx_wait_for_finalized_success(&signed_extrinsic).await;
assert_matches!(chill, Err(Error::Runtime(DispatchError::Module(err))) => {
let details = err.details().unwrap();
@@ -174,13 +175,14 @@ async fn chill_works_for_stash_only() -> Result<(), Error> {
assert_eq!(&details.variant.name, "NotController");
});
let is_chilled = api
let signed_extrinsic = api
.tx()
.sign_and_submit_then_watch_default(&chill_tx, &alice_stash)
.await?
.wait_for_finalized_success()
.create_signed(&chill_tx, &alice_stash, Default::default())
.await?;
let is_chilled = submit_tx_wait_for_finalized_success(&signed_extrinsic)
.await?
.has::<staking::events::Chilled>()?;
assert!(is_chilled);
Ok(())
@@ -197,21 +199,19 @@ async fn tx_bond() -> Result<(), Error> {
.staking()
.bond(100_000_000_000_000, RewardDestination::Stash);
let bond = api
let signed_extrinsic = api
.tx()
.sign_and_submit_then_watch_default(&bond_tx, &alice)
.await?
.wait_for_finalized_success()
.await;
.create_signed(&bond_tx, &alice, Default::default())
.await?;
let bond = submit_tx_wait_for_finalized_success(&signed_extrinsic).await;
assert!(bond.is_ok());
let bond_again = api
let signed_extrinsic = api
.tx()
.sign_and_submit_then_watch_default(&bond_tx, &alice)
.await?
.wait_for_finalized_success()
.await;
.create_signed(&bond_tx, &alice, Default::default())
.await?;
let bond_again = submit_tx_wait_for_finalized_success(&signed_extrinsic).await;
assert_matches!(bond_again, Err(Error::Runtime(DispatchError::Module(err))) => {
let details = err.details().unwrap();
@@ -8,7 +8,7 @@ use crate::{
runtime_types::{self, sp_weights::weight_v2::Weight},
sudo,
},
test_context,
submit_tx_wait_for_finalized_success, test_context,
};
use subxt_signer::sr25519::dev;
@@ -29,11 +29,12 @@ async fn test_sudo() -> Result<(), subxt::Error> {
});
let tx = node_runtime::tx().sudo().sudo(call);
let found_event = api
let signed_extrinsic = api
.tx()
.sign_and_submit_then_watch_default(&tx, &alice)
.await?
.wait_for_finalized_success()
.create_signed(&tx, &alice, Default::default())
.await?;
let found_event = submit_tx_wait_for_finalized_success(&signed_extrinsic)
.await?
.has::<sudo::events::Sudid>()?;
@@ -61,11 +62,12 @@ async fn test_sudo_unchecked_weight() -> Result<(), subxt::Error> {
},
);
let found_event = api
let signed_extrinsic = api
.tx()
.sign_and_submit_then_watch_default(&tx, &alice)
.await?
.wait_for_finalized_success()
.create_signed(&tx, &alice, Default::default())
.await?;
let found_event = submit_tx_wait_for_finalized_success(&signed_extrinsic)
.await?
.has::<sudo::events::Sudid>()?;
@@ -4,7 +4,7 @@
use crate::{
node_runtime::{self, system},
test_context,
submit_tx_wait_for_finalized_success, test_context,
};
use assert_matches::assert_matches;
use subxt_signer::sr25519::dev;
@@ -42,11 +42,12 @@ async fn tx_remark_with_event() -> Result<(), subxt::Error> {
.system()
.remark_with_event(b"remarkable".to_vec());
let found_event = api
let signed_extrinsic = api
.tx()
.sign_and_submit_then_watch_default(&tx, &alice)
.await?
.wait_for_finalized_success()
.create_signed(&tx, &alice, Default::default())
.await?;
let found_event = submit_tx_wait_for_finalized_success(&signed_extrinsic)
.await?
.has::<system::events::Remarked>()?;
@@ -2,7 +2,7 @@
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
// see LICENSE for license details.
use crate::{node_runtime, test_context};
use crate::{node_runtime, submit_tx_wait_for_finalized_success, test_context};
use codec::Encode;
use subxt::utils::AccountId32;
use subxt_signer::sr25519::dev;
@@ -29,11 +29,11 @@ async fn account_nonce() -> Result<(), subxt::Error> {
// Do some transaction to bump the Alice nonce to 1:
let remark_tx = node_runtime::tx().system().remark(vec![1, 2, 3, 4, 5]);
api.tx()
.sign_and_submit_then_watch_default(&remark_tx, &alice)
.await?
.wait_for_finalized_success()
let signed_extrinsic = api
.tx()
.create_signed(&remark_tx, &alice, Default::default())
.await?;
submit_tx_wait_for_finalized_success(&signed_extrinsic).await?;
let runtime_api_call = node_runtime::apis()
.account_nonce_api()
@@ -3,7 +3,10 @@
// see LICENSE for license details.
use crate::{node_runtime, test_context, utils::wait_for_blocks};
#[cfg(fullclient)]
use subxt::utils::AccountId32;
#[cfg(fullclient)]
use subxt_signer::sr25519::dev;
#[tokio::test]
@@ -27,6 +30,7 @@ async fn storage_plain_lookup() -> Result<(), subxt::Error> {
Ok(())
}
#[cfg(fullclient)]
#[tokio::test]
async fn storage_map_lookup() -> Result<(), subxt::Error> {
let ctx = test_context().await;
@@ -60,6 +64,7 @@ async fn storage_map_lookup() -> Result<(), subxt::Error> {
// Here we create a key that looks a bit like a StorageNMap key, but should in fact be
// treated as a StorageKey (ie we should hash both values together with one hasher, rather
// than hash both values separately, or ignore the second value).
#[cfg(fullclient)]
#[tokio::test]
async fn storage_n_mapish_key_is_properly_created() -> Result<(), subxt::Error> {
use codec::Encode;
@@ -4,8 +4,10 @@
mod context;
mod node_proc;
mod tx_retries;
mod wait_for_blocks;
pub use context::*;
pub use node_proc::TestNodeProcess;
pub use tx_retries::*;
pub use wait_for_blocks::wait_for_blocks;
@@ -0,0 +1,40 @@
// Copyright 2019-2024 Parity Technologies (UK) Ltd.
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
// see LICENSE for license details.
use subxt::client::OnlineClientT;
use subxt::tx::SubmittableExtrinsic;
use subxt::Config;
pub async fn submit_tx_wait_for_finalized_success<T, C>(
signed_extrinsic: &SubmittableExtrinsic<T, C>,
) -> Result<subxt::blocks::ExtrinsicEvents<T>, subxt::Error>
where
T: Config,
C: OnlineClientT<T>,
{
let submit = || async {
signed_extrinsic
.submit_and_watch()
.await
.unwrap()
.wait_for_finalized_success()
.await
};
#[cfg(lightclient)]
for _ in 0..2 {
let result = submit().await;
match result {
Ok(tx_in_block) => return Ok(tx_in_block),
Err(subxt::Error::Transaction(subxt::error::TransactionError::Dropped(_))) => {
// Retry if the transaction was dropped.
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
}
Err(other) => return Err(other),
}
}
submit().await
}