mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 07:01:05 +00:00
rpc: stabilize chainhead backend (#1802)
* rpc: stabilize ChainHeadBackend * remove noise from example * add missing features * make tests compile * make tests compile v2 * revert stop event * feature-gate runtime * Update subxt/Cargo.toml * add docsrs feature stuff * Update subxt/src/backend/chain_head/mod.rs * Update subxt/src/backend/chain_head/mod.rs * Update subxt/src/backend/chain_head/mod.rs
This commit is contained in:
@@ -77,8 +77,8 @@ async fn storage_iter() {
|
||||
async fn storage_child_values_same_across_backends() {
|
||||
let ctx = test_context().await;
|
||||
|
||||
let unstable_client = ctx.unstable_client().await;
|
||||
let legacy_client = ctx.legacy_client().await;
|
||||
let chainhead_client = ctx.chainhead_backend().await;
|
||||
let legacy_client = ctx.legacy_backend().await;
|
||||
|
||||
let addr = node_runtime::storage().system().account_iter();
|
||||
let block_ref = legacy_client
|
||||
@@ -88,7 +88,7 @@ async fn storage_child_values_same_across_backends() {
|
||||
.unwrap()
|
||||
.reference();
|
||||
|
||||
let a: Vec<_> = unstable_client
|
||||
let a: Vec<_> = chainhead_client
|
||||
.storage()
|
||||
.at(block_ref.clone())
|
||||
.iter(addr.clone())
|
||||
@@ -215,9 +215,9 @@ async fn external_signing() {
|
||||
}
|
||||
|
||||
#[cfg(fullclient)]
|
||||
// TODO: Investigate and fix this test failure when using the UnstableBackend.
|
||||
// TODO: Investigate and fix this test failure when using the ChainHeadBackend.
|
||||
// (https://github.com/paritytech/subxt/issues/1308)
|
||||
#[cfg(not(feature = "unstable-backend-client"))]
|
||||
#[cfg(legacy_backend)]
|
||||
#[subxt_test]
|
||||
async fn submit_large_extrinsic() {
|
||||
let ctx = test_context().await;
|
||||
@@ -415,8 +415,8 @@ async fn partial_fee_estimate_correct() {
|
||||
#[subxt_test]
|
||||
async fn legacy_and_unstable_block_subscription_reconnect() {
|
||||
let ctx = test_context_reconnecting_rpc_client().await;
|
||||
let api = ctx.unstable_client().await;
|
||||
let unstable_client_blocks = move |num: usize| {
|
||||
let api = ctx.chainhead_backend().await;
|
||||
let chainhead_client_blocks = move |num: usize| {
|
||||
let api = api.clone();
|
||||
async move {
|
||||
let mut missed_blocks = false;
|
||||
@@ -445,17 +445,17 @@ async fn legacy_and_unstable_block_subscription_reconnect() {
|
||||
}
|
||||
};
|
||||
|
||||
let (blocks, _) = unstable_client_blocks(3).await;
|
||||
let (blocks, _) = chainhead_client_blocks(3).await;
|
||||
let blocks: HashSet<String> = HashSet::from_iter(blocks.into_iter());
|
||||
|
||||
assert!(blocks.len() == 3);
|
||||
|
||||
let ctx = ctx.restart().await;
|
||||
|
||||
// Make client aware that connection was dropped and force them to reconnect
|
||||
let _ = ctx.unstable_client().await.backend().genesis_hash().await;
|
||||
// Make client aware that connection was dropped and force them to reconnect
|
||||
let _ = ctx.chainhead_backend().await.backend().genesis_hash().await;
|
||||
|
||||
let (unstable_blocks, blocks_missed) = unstable_client_blocks(6).await;
|
||||
let (unstable_blocks, blocks_missed) = chainhead_client_blocks(6).await;
|
||||
|
||||
if !blocks_missed {
|
||||
let unstable_blocks: HashSet<String> = HashSet::from_iter(unstable_blocks.into_iter());
|
||||
|
||||
@@ -13,7 +13,7 @@ use assert_matches::assert_matches;
|
||||
use codec::Encode;
|
||||
use futures::Stream;
|
||||
use subxt::{
|
||||
backend::unstable::rpc_methods::{
|
||||
backend::chain_head::rpc_methods::{
|
||||
FollowEvent, Initialized, MethodResponse, RuntimeEvent, RuntimeVersionEvent, StorageQuery,
|
||||
StorageQueryType,
|
||||
},
|
||||
@@ -27,7 +27,7 @@ use subxt_signer::sr25519::dev;
|
||||
#[subxt_test]
|
||||
async fn chainhead_v1_follow() {
|
||||
let ctx = test_context().await;
|
||||
let rpc = ctx.unstable_rpc_methods().await;
|
||||
let rpc = ctx.chainhead_rpc_methods().await;
|
||||
let legacy_rpc = ctx.legacy_rpc_methods().await;
|
||||
|
||||
// Check subscription with runtime updates set on false.
|
||||
@@ -67,7 +67,7 @@ async fn chainhead_v1_follow() {
|
||||
#[subxt_test]
|
||||
async fn chainhead_v1_body() {
|
||||
let ctx = test_context().await;
|
||||
let rpc = ctx.unstable_rpc_methods().await;
|
||||
let rpc = ctx.chainhead_rpc_methods().await;
|
||||
|
||||
let mut blocks = rpc.chainhead_v1_follow(false).await.unwrap();
|
||||
let event = blocks.next().await.unwrap().unwrap();
|
||||
@@ -95,7 +95,7 @@ async fn chainhead_v1_body() {
|
||||
#[subxt_test]
|
||||
async fn chainhead_v1_header() {
|
||||
let ctx = test_context().await;
|
||||
let rpc = ctx.unstable_rpc_methods().await;
|
||||
let rpc = ctx.chainhead_rpc_methods().await;
|
||||
let legacy_rpc = ctx.legacy_rpc_methods().await;
|
||||
|
||||
let mut blocks = rpc.chainhead_v1_follow(false).await.unwrap();
|
||||
@@ -124,7 +124,7 @@ async fn chainhead_v1_header() {
|
||||
async fn chainhead_v1_storage() {
|
||||
let ctx = test_context().await;
|
||||
let api = ctx.client();
|
||||
let rpc = ctx.unstable_rpc_methods().await;
|
||||
let rpc = ctx.chainhead_rpc_methods().await;
|
||||
|
||||
let mut blocks = rpc.chainhead_v1_follow(false).await.unwrap();
|
||||
let event = blocks.next().await.unwrap().unwrap();
|
||||
@@ -169,7 +169,7 @@ async fn chainhead_v1_storage() {
|
||||
#[subxt_test]
|
||||
async fn chainhead_v1_call() {
|
||||
let ctx = test_context().await;
|
||||
let rpc = ctx.unstable_rpc_methods().await;
|
||||
let rpc = ctx.chainhead_rpc_methods().await;
|
||||
|
||||
let mut blocks = rpc.chainhead_v1_follow(true).await.unwrap();
|
||||
let event = blocks.next().await.unwrap().unwrap();
|
||||
@@ -206,7 +206,7 @@ async fn chainhead_v1_call() {
|
||||
#[subxt_test]
|
||||
async fn chainhead_v1_unpin() {
|
||||
let ctx = test_context().await;
|
||||
let rpc = ctx.unstable_rpc_methods().await;
|
||||
let rpc = ctx.chainhead_rpc_methods().await;
|
||||
|
||||
let mut blocks = rpc.chainhead_v1_follow(true).await.unwrap();
|
||||
let event = blocks.next().await.unwrap().unwrap();
|
||||
@@ -226,7 +226,7 @@ async fn chainhead_v1_unpin() {
|
||||
async fn chainspec_v1_genesishash() {
|
||||
let ctx = test_context().await;
|
||||
let old_rpc = ctx.legacy_rpc_methods().await;
|
||||
let rpc = ctx.unstable_rpc_methods().await;
|
||||
let rpc = ctx.chainhead_rpc_methods().await;
|
||||
|
||||
let a = old_rpc.genesis_hash().await.unwrap();
|
||||
let b = rpc.chainspec_v1_genesis_hash().await.unwrap();
|
||||
@@ -239,7 +239,7 @@ async fn chainspec_v1_genesishash() {
|
||||
async fn chainspec_v1_chainname() {
|
||||
let ctx = test_context().await;
|
||||
let old_rpc = ctx.legacy_rpc_methods().await;
|
||||
let rpc = ctx.unstable_rpc_methods().await;
|
||||
let rpc = ctx.chainhead_rpc_methods().await;
|
||||
|
||||
let a = old_rpc.system_chain().await.unwrap();
|
||||
let b = rpc.chainspec_v1_chain_name().await.unwrap();
|
||||
@@ -252,7 +252,7 @@ async fn chainspec_v1_chainname() {
|
||||
async fn chainspec_v1_properties() {
|
||||
let ctx = test_context().await;
|
||||
let old_rpc = ctx.legacy_rpc_methods().await;
|
||||
let rpc = ctx.unstable_rpc_methods().await;
|
||||
let rpc = ctx.chainhead_rpc_methods().await;
|
||||
|
||||
let a = old_rpc.system_properties().await.unwrap();
|
||||
let b = rpc.chainspec_v1_properties().await.unwrap();
|
||||
@@ -264,7 +264,7 @@ async fn chainspec_v1_properties() {
|
||||
#[subxt_test]
|
||||
async fn transactionwatch_v1_submit_and_watch() {
|
||||
let ctx = test_context().await;
|
||||
let rpc = ctx.unstable_rpc_methods().await;
|
||||
let rpc = ctx.chainhead_rpc_methods().await;
|
||||
|
||||
// Build and sign some random tx, just to get some appropriate bytes:
|
||||
let payload = node_runtime::tx().system().remark(b"hello".to_vec());
|
||||
@@ -327,7 +327,7 @@ async fn transaction_v1_broadcast() {
|
||||
|
||||
let ctx = test_context().await;
|
||||
let api = ctx.client();
|
||||
let rpc = ctx.unstable_rpc_methods().await;
|
||||
let rpc = ctx.chainhead_rpc_methods().await;
|
||||
|
||||
let tx_payload = node_runtime::tx()
|
||||
.balances()
|
||||
@@ -391,7 +391,7 @@ async fn transaction_v1_stop() {
|
||||
let bob_address: MultiAddress<AccountId32, u32> = bob.public_key().into();
|
||||
|
||||
let ctx = test_context().await;
|
||||
let rpc = ctx.unstable_rpc_methods().await;
|
||||
let rpc = ctx.chainhead_rpc_methods().await;
|
||||
|
||||
// Cannot stop an operation that was not started.
|
||||
let _err = rpc
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
|
||||
// see LICENSE for license details.
|
||||
|
||||
#[cfg(all(feature = "unstable-light-client", feature = "unstable-backend-client"))]
|
||||
#[cfg(all(feature = "unstable-light-client", feature = "chainhead-backend"))]
|
||||
compile_error!(
|
||||
"The features 'unstable-light-client' and 'unstable-backend-client' cannot be used together"
|
||||
"The features 'unstable-light-client' and 'chainhead-backend' cannot be used together"
|
||||
);
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -31,8 +31,8 @@ use crate::utils::node_runtime;
|
||||
use codec::Compact;
|
||||
use futures::StreamExt;
|
||||
use std::sync::Arc;
|
||||
use subxt::backend::chain_head::ChainHeadBackend;
|
||||
use subxt::backend::rpc::RpcClient;
|
||||
use subxt::backend::unstable::UnstableBackend;
|
||||
use subxt::{client::OnlineClient, config::PolkadotConfig, lightclient::LightClient};
|
||||
use subxt_metadata::Metadata;
|
||||
|
||||
@@ -184,7 +184,7 @@ async fn run_test(backend: BackendType) -> Result<(), subxt::Error> {
|
||||
|
||||
let api = match backend {
|
||||
BackendType::Unstable => {
|
||||
let (backend, mut driver) = UnstableBackend::builder().build(RpcClient::new(rpc));
|
||||
let (backend, mut driver) = ChainHeadBackend::builder().build(RpcClient::new(rpc));
|
||||
tokio::spawn(async move {
|
||||
while let Some(val) = driver.next().await {
|
||||
if let Err(e) = val {
|
||||
|
||||
@@ -9,7 +9,7 @@ use std::time::Duration;
|
||||
use substrate_runner::SubstrateNode;
|
||||
use subxt::backend::rpc::reconnecting_rpc_client::{ExponentialBackoff, RpcClientBuilder};
|
||||
use subxt::{
|
||||
backend::{legacy, rpc, unstable},
|
||||
backend::{chain_head, legacy, rpc},
|
||||
Config, OnlineClient,
|
||||
};
|
||||
|
||||
@@ -41,8 +41,8 @@ pub struct TestNodeProcess<R: Config> {
|
||||
proc: Option<SubstrateNode>,
|
||||
|
||||
// Lazily construct these when asked for.
|
||||
unstable_client: RefCell<Option<OnlineClient<R>>>,
|
||||
legacy_client: RefCell<Option<OnlineClient<R>>>,
|
||||
chainhead_backend: RefCell<Option<OnlineClient<R>>>,
|
||||
legacy_backend: RefCell<Option<OnlineClient<R>>>,
|
||||
|
||||
rpc_client: rpc::RpcClient,
|
||||
client: OnlineClient<R>,
|
||||
@@ -78,38 +78,38 @@ where
|
||||
}
|
||||
|
||||
/// Hand back an RPC client connected to the test node which exposes the unstable RPC methods.
|
||||
pub async fn unstable_rpc_methods(&self) -> unstable::UnstableRpcMethods<R> {
|
||||
pub async fn chainhead_rpc_methods(&self) -> chain_head::ChainHeadRpcMethods<R> {
|
||||
let rpc_client = self.rpc_client.clone();
|
||||
unstable::UnstableRpcMethods::new(rpc_client)
|
||||
chain_head::ChainHeadRpcMethods::new(rpc_client)
|
||||
}
|
||||
|
||||
/// Always return a client using the unstable backend.
|
||||
/// Always return a client using the chainhead backend.
|
||||
/// Only use for comparing backends; use [`TestNodeProcess::client()`] normally,
|
||||
/// which enables us to run each test against both backends.
|
||||
pub async fn unstable_client(&self) -> OnlineClient<R> {
|
||||
if self.unstable_client.borrow().is_none() {
|
||||
let c = build_unstable_client(self.rpc_client.clone())
|
||||
pub async fn chainhead_backend(&self) -> OnlineClient<R> {
|
||||
if self.chainhead_backend.borrow().is_none() {
|
||||
let c = build_chainhead_backend(self.rpc_client.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
self.unstable_client.replace(Some(c));
|
||||
self.chainhead_backend.replace(Some(c));
|
||||
}
|
||||
self.unstable_client.borrow().as_ref().unwrap().clone()
|
||||
self.chainhead_backend.borrow().as_ref().unwrap().clone()
|
||||
}
|
||||
|
||||
/// Always return a client using the legacy backend.
|
||||
/// Only use for comparing backends; use [`TestNodeProcess::client()`] normally,
|
||||
/// which enables us to run each test against both backends.
|
||||
pub async fn legacy_client(&self) -> OnlineClient<R> {
|
||||
if self.legacy_client.borrow().is_none() {
|
||||
let c = build_legacy_client(self.rpc_client.clone()).await.unwrap();
|
||||
self.legacy_client.replace(Some(c));
|
||||
pub async fn legacy_backend(&self) -> OnlineClient<R> {
|
||||
if self.legacy_backend.borrow().is_none() {
|
||||
let c = build_legacy_backend(self.rpc_client.clone()).await.unwrap();
|
||||
self.legacy_backend.replace(Some(c));
|
||||
}
|
||||
self.legacy_client.borrow().as_ref().unwrap().clone()
|
||||
self.legacy_backend.borrow().as_ref().unwrap().clone()
|
||||
}
|
||||
|
||||
/// Returns the subxt client connected to the running node. This client
|
||||
/// will use the legacy backend by default or the unstable backend if the
|
||||
/// "unstable-backend-client" feature is enabled, so that we can run each
|
||||
/// will use the legacy backend by default or the chainhead backend if the
|
||||
/// "chainhead-backend" feature is enabled, so that we can run each
|
||||
/// test against both.
|
||||
pub fn client(&self) -> OnlineClient<R> {
|
||||
self.client.clone()
|
||||
@@ -187,38 +187,38 @@ impl TestNodeProcessBuilder {
|
||||
let ws_url = get_url(proc.as_ref().map(|p| p.ws_port()));
|
||||
let rpc_client = match self.rpc_client {
|
||||
RpcClientKind::Legacy => build_rpc_client(&ws_url).await,
|
||||
RpcClientKind::UnstableReconnecting => build_unstable_rpc_client(&ws_url).await,
|
||||
RpcClientKind::UnstableReconnecting => build_reconnecting_rpc_client(&ws_url).await,
|
||||
}
|
||||
.map_err(|e| format!("Failed to connect to node at {ws_url}: {e}"))?;
|
||||
|
||||
// Cache whatever client we build, and None for the other.
|
||||
#[allow(unused_assignments, unused_mut)]
|
||||
let mut unstable_client = None;
|
||||
let mut chainhead_backend = None;
|
||||
#[allow(unused_assignments, unused_mut)]
|
||||
let mut legacy_client = None;
|
||||
let mut legacy_backend = None;
|
||||
|
||||
#[cfg(lightclient)]
|
||||
let client = build_light_client(&proc).await?;
|
||||
|
||||
#[cfg(feature = "unstable-backend-client")]
|
||||
#[cfg(chainhead_backend)]
|
||||
let client = {
|
||||
let client = build_unstable_client(rpc_client.clone()).await?;
|
||||
unstable_client = Some(client.clone());
|
||||
let client = build_chainhead_backend(rpc_client.clone()).await?;
|
||||
chainhead_backend = Some(client.clone());
|
||||
client
|
||||
};
|
||||
|
||||
#[cfg(all(not(lightclient), not(feature = "unstable-backend-client")))]
|
||||
#[cfg(all(not(lightclient), legacy_backend))]
|
||||
let client = {
|
||||
let client = build_legacy_client(rpc_client.clone()).await?;
|
||||
legacy_client = Some(client.clone());
|
||||
let client = build_legacy_backend(rpc_client.clone()).await?;
|
||||
legacy_backend = Some(client.clone());
|
||||
client
|
||||
};
|
||||
|
||||
Ok(TestNodeProcess {
|
||||
proc,
|
||||
client,
|
||||
legacy_client: RefCell::new(legacy_client),
|
||||
unstable_client: RefCell::new(unstable_client),
|
||||
legacy_backend: RefCell::new(legacy_backend),
|
||||
chainhead_backend: RefCell::new(chainhead_backend),
|
||||
rpc_client,
|
||||
})
|
||||
}
|
||||
@@ -232,7 +232,7 @@ async fn build_rpc_client(ws_url: &str) -> Result<rpc::RpcClient, String> {
|
||||
Ok(rpc_client)
|
||||
}
|
||||
|
||||
async fn build_unstable_rpc_client(ws_url: &str) -> Result<rpc::RpcClient, String> {
|
||||
async fn build_reconnecting_rpc_client(ws_url: &str) -> Result<rpc::RpcClient, String> {
|
||||
let client = RpcClientBuilder::new()
|
||||
.retry_policy(ExponentialBackoff::from_millis(100).max_delay(Duration::from_secs(10)))
|
||||
.build(ws_url.to_string())
|
||||
@@ -242,7 +242,7 @@ async fn build_unstable_rpc_client(ws_url: &str) -> Result<rpc::RpcClient, Strin
|
||||
Ok(rpc::RpcClient::new(client))
|
||||
}
|
||||
|
||||
async fn build_legacy_client<T: Config>(
|
||||
async fn build_legacy_backend<T: Config>(
|
||||
rpc_client: rpc::RpcClient,
|
||||
) -> Result<OnlineClient<T>, String> {
|
||||
let backend = legacy::LegacyBackend::builder().build(rpc_client);
|
||||
@@ -253,23 +253,10 @@ async fn build_legacy_client<T: Config>(
|
||||
Ok(client)
|
||||
}
|
||||
|
||||
async fn build_unstable_client<T: Config>(
|
||||
async fn build_chainhead_backend<T: Config>(
|
||||
rpc_client: rpc::RpcClient,
|
||||
) -> Result<OnlineClient<T>, String> {
|
||||
let (backend, mut driver) = unstable::UnstableBackend::builder().build(rpc_client);
|
||||
|
||||
// The unstable backend needs driving:
|
||||
tokio::spawn(async move {
|
||||
use futures::StreamExt;
|
||||
while let Some(val) = driver.next().await {
|
||||
if let Err(e) = val {
|
||||
// This is a test; bail if something does wrong and try to
|
||||
// ensure that the message makes it to some logs.
|
||||
eprintln!("Error driving unstable backend in tests (will panic): {e}");
|
||||
panic!("Error driving unstable backend in tests: {e}");
|
||||
}
|
||||
}
|
||||
});
|
||||
let backend = chain_head::ChainHeadBackend::builder().build_with_background_driver(rpc_client);
|
||||
|
||||
let client = OnlineClient::from_backend(Arc::new(backend))
|
||||
.await
|
||||
@@ -323,5 +310,5 @@ async fn build_light_client<T: Config>(
|
||||
.map_err(|e| format!("Light client: cannot add relay chain: {e}"))?;
|
||||
|
||||
// Instantiate subxt client from this.
|
||||
build_unstable_client(rpc.into()).await
|
||||
build_chainhead_backend(rpc.into()).await
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user