diff --git a/lightclient/src/background.rs b/lightclient/src/background.rs index 01614d202e..e662d600ae 100644 --- a/lightclient/src/background.rs +++ b/lightclient/src/background.rs @@ -233,7 +233,7 @@ impl BackgroundTask { /// Parse the response received from the light client and sent it to the appropriate user. fn handle_rpc_response(&mut self, chain_id: smoldot_light::ChainId, response: String) { - tracing::trace!(target: LOG_TARGET, "Received from smoldot response={response} chain={chain_id:?}"); + tracing::trace!(target: LOG_TARGET, "Received from smoldot response={} chain={:?}", if response.len() > 200 { &response[..200] } else { &response }, chain_id); match RpcResponse::from_str(&response) { Ok(RpcResponse::Error { id, error }) => { @@ -420,7 +420,7 @@ impl BackgroundTask { tracing::trace!( target: LOG_TARGET, "Received smoldot RPC chain {:?} result {:?}", - chain, response + chain, if response.len() > 200 { &response[..200] } else { &response } ); self.handle_rpc_response(chain, response); diff --git a/subxt/examples/light_client_parachains.rs b/subxt/examples/light_client_parachains.rs index fde72459ea..b9b3f2cb90 100644 --- a/subxt/examples/light_client_parachains.rs +++ b/subxt/examples/light_client_parachains.rs @@ -8,9 +8,6 @@ use subxt::{ client::{LightClient, RawLightClient}, PolkadotConfig, }; -use sp_core::crypto::{AccountId32, Ss58Codec}; -use std::collections::BTreeSet; -use sp_core::ByteArray; // Generate an interface that we can use from the node's metadata. #[subxt::subxt(runtime_metadata_path = "../artifacts/polkadot_metadata_small.scale")] @@ -89,19 +86,98 @@ async fn main() -> Result<(), Box> { raw_light_client.for_chain(parachain_chain_id).await?; // Step 6. Subscribe to the finalized blocks of the chains. - let key = collectives::storage().fellowship_collective().members_iter(); - let mut query = parachain_api.storage().at_latest().await.unwrap().iter(key).await?; - let mut members = BTreeSet::new(); + let key = collectives::storage() + .fellowship_collective() + .members_iter(); - while let Some(Ok((id, fellow))) = query.next().await { - let account = AccountId32::from_slice(&id[id.len() - 32..]).unwrap(); + let parachain_rpc = raw_light_client + .rpc_client_for_chain(parachain_chain_id) + .await?; - println!("Fetched member: {} rank {}", account.to_ss58check(), fellow.rank); - if members.contains(&account) { - println!("ERROR: Fetched account twice"); + use subxt::backend::legacy::LegacyRpcMethods; + let legacy_rpc: LegacyRpcMethods = LegacyRpcMethods::new(parachain_rpc); + + use subxt::client::OfflineClientT; + let metadata = parachain_api.metadata(); + + let key_bytes = { + use subxt::storage::StorageAddress; + pub(crate) fn write_storage_address_root_bytes( + addr: &Address, + out: &mut Vec, + ) { + out.extend(sp_core_hashing::twox_128(addr.pallet_name().as_bytes())); + out.extend(sp_core_hashing::twox_128(addr.entry_name().as_bytes())); } - members.insert(account); + + let mut bytes = Vec::new(); + write_storage_address_root_bytes(&key, &mut bytes); + key.append_entry_bytes(&metadata, &mut bytes)?; + bytes + }; + + println!(" Smoldot result: "); + let mut set = std::collections::HashSet::new(); + let mut last_key = None; + loop { + let param_start_key = last_key.as_deref(); + println!("New query with {:?}\n", param_start_key); + + let result = legacy_rpc + .state_get_keys_paged(key_bytes.as_slice(), 10, param_start_key, None) + .await?; + for res in result.clone() { + println!("Fetched member: {:?}", res); + + if set.contains(&res) { + println!("ERROR: Fetched account twice"); + } + set.insert(res); + } + + if result.len() < 10 { + break; + } + + last_key = Some(result.last().unwrap().clone()); } + println!(); + // println!(" RPC node result: "); + // { + // use subxt::backend::rpc::RpcClient; + // // First, create a raw RPC client: + // let rpc_client = RpcClient::from_url("wss://polkadot-collectives-rpc.dwellir.com").await?; + // // Use this to construct our RPC methods: + // let legacy_rpc = LegacyRpcMethods::::new(rpc_client.clone()); + + // let mut set = std::collections::HashSet::new(); + // let mut last_key = None; + // loop { + // let param_start_key = last_key.as_deref(); + // println!("New query with {:?}\n", param_start_key); + + // let result = legacy_rpc + // .state_get_keys_paged(key_bytes.as_slice(), 10, param_start_key, None) + // .await?; + // for res in result.clone() { + // println!("Fetched member: {:?}", res); + + // if set.contains(&res) { + // println!("ERROR: Fetched account twice"); + // } + // set.insert(res); + // } + + // if result.is_empty() { + // break; + // } + + // println!(); + + // last_key = Some(result.last().unwrap().clone()); + // } + // } + Ok(()) } diff --git a/subxt/src/client/light_client/mod.rs b/subxt/src/client/light_client/mod.rs index a4b116652e..abe86ae761 100644 --- a/subxt/src/client/light_client/mod.rs +++ b/subxt/src/client/light_client/mod.rs @@ -97,6 +97,16 @@ impl RawLightClient { Ok(LightClient { client, chain_id }) } + + /// Target a different chain identified by the provided chain ID for requests. + pub async fn rpc_client_for_chain( + &self, + chain_id: smoldot::ChainId, + ) -> Result { + let raw_rpc = self.raw_rpc.for_chain(chain_id); + let rpc_client = RpcClient::new(raw_rpc.clone()); + Ok(rpc_client) + } } /// The light-client RPC implementation that is used to connect with the chain. diff --git a/subxt/src/client/light_client/rpc.rs b/subxt/src/client/light_client/rpc.rs index ea9fe996ba..c1e4ca70ae 100644 --- a/subxt/src/client/light_client/rpc.rs +++ b/subxt/src/client/light_client/rpc.rs @@ -74,7 +74,6 @@ impl RpcClientT for LightClientRpc { params: Option>, ) -> RawRpcFuture<'a, Box> { let client = self.clone(); - let chain_id = self.chain_id(); Box::pin(async move { let params = match params { @@ -95,8 +94,6 @@ impl RpcClientT for LightClientRpc { .await .map_err(|_| RpcError::ClientError(Box::new(LightClientError::BackgroundClosed)))?; - tracing::trace!(target: LOG_TARGET, "RPC response={:?} chain={:?}", response, chain_id); - response.map_err(|err| RpcError::ClientError(Box::new(err))) }) }