Skip to content

Commit 6850d3e

Browse files
committed
Fix tests
1 parent acd92c4 commit 6850d3e

File tree

1 file changed

+82
-80
lines changed
  • crates/anvil-polkadot/src/api_server

1 file changed

+82
-80
lines changed

crates/anvil-polkadot/src/api_server/server.rs

Lines changed: 82 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use crate::{
3737
};
3838
use alloy_dyn_abi::TypedData;
3939
use alloy_eips::{BlockId, BlockNumberOrTag};
40-
use alloy_primitives::{hex, Address, B256, U64, U256};
40+
use alloy_primitives::{Address, B256, U64, U256};
4141
use alloy_rpc_types::{
4242
Filter, TransactionRequest,
4343
anvil::{Forking, Metadata as AnvilMetadata, MineOptions, NodeEnvironment, NodeInfo},
@@ -1887,58 +1887,26 @@ async fn create_online_client(
18871887
)));
18881888
};
18891889

1890-
// In fork mode, fetch metadata from remote RPC to avoid Tokio runtime conflicts
1891-
// Note: Remote metadata may not have ReviveApi, so we skip block processing in fork mode
1892-
if let Some(fork_url) = &substrate_service.fork_url {
1893-
use jsonrpsee::core::client::ClientT;
1894-
use subxt::ext::jsonrpsee::core::params::ArrayParams as RpcParams;
1895-
1896-
let http_client = jsonrpsee::http_client::HttpClientBuilder::default()
1897-
.max_request_size(u32::MAX)
1898-
.max_response_size(u32::MAX)
1899-
.request_timeout(std::time::Duration::from_secs(30))
1900-
.build(fork_url)
1901-
.map_err(|e| Error::InternalError(format!("Failed to build HTTP client: {e}")))?;
1902-
1903-
let runtime_version: polkadot_sdk::sp_version::RuntimeVersion = http_client
1904-
.request("state_getRuntimeVersion", RpcParams::new())
1905-
.await
1906-
.map_err(|e| Error::InternalError(format!("Failed to fetch runtime version: {e}")))?;
1890+
// Fetch runtime version - this works without triggering lazy loading
1891+
let Ok(runtime_version) = substrate_service.client.runtime_version_at(genesis_hash) else {
1892+
return Err(Error::InternalError("Runtime version not found".to_string()));
1893+
};
19071894

1908-
let subxt_runtime_version = SubxtRuntimeVersion {
1909-
spec_version: runtime_version.spec_version,
1910-
transaction_version: runtime_version.transaction_version,
1911-
};
1895+
let subxt_runtime_version = SubxtRuntimeVersion {
1896+
spec_version: runtime_version.spec_version,
1897+
transaction_version: runtime_version.transaction_version,
1898+
};
19121899

1913-
let metadata_hex: String = http_client
1914-
.request("state_getMetadata", RpcParams::new())
1900+
// In fork mode, use OnlineClient::from_rpc_client() which fetches metadata from RPC automatically
1901+
// In normal mode, use local client metadata to avoid unnecessary RPC calls
1902+
if substrate_service.backend.rpc().is_some() {
1903+
// Fork mode: Let OnlineClient fetch metadata from the remote RPC
1904+
// This avoids triggering the lazy loading backend during initialization
1905+
OnlineClient::<SrcChainConfig>::from_rpc_client(rpc_client)
19151906
.await
1916-
.map_err(|e| Error::InternalError(format!("Failed to fetch metadata: {e}")))?;
1917-
1918-
let metadata_bytes = hex::decode(metadata_hex.trim_start_matches("0x"))
1919-
.map_err(|e| Error::InternalError(format!("Failed to decode metadata: {e}")))?;
1920-
1921-
let subxt_metadata = SubxtMetadata::decode(&mut &metadata_bytes[..])
1922-
.map_err(|e| Error::InternalError(format!("Failed to decode metadata: {e}")))?;
1923-
1924-
OnlineClient::<SrcChainConfig>::from_rpc_client_with(
1925-
genesis_hash,
1926-
subxt_runtime_version,
1927-
subxt_metadata,
1928-
rpc_client,
1929-
)
1930-
.map_err(|err| Error::InternalError(format!("Failed to initialize online client: {err}")))
1907+
.map_err(|err| Error::InternalError(format!("Failed to initialize online client from RPC: {err}")))
19311908
} else {
1932-
// Normal mode: use local runtime metadata
1933-
let Ok(runtime_version) = substrate_service.client.runtime_version_at(genesis_hash) else {
1934-
return Err(Error::InternalError("Runtime version not found".to_string()));
1935-
};
1936-
1937-
let subxt_runtime_version = SubxtRuntimeVersion {
1938-
spec_version: runtime_version.spec_version,
1939-
transaction_version: runtime_version.transaction_version,
1940-
};
1941-
1909+
// Normal mode: Use local client runtime API (no lazy loading involved)
19421910
let Ok(supported_metadata_versions) =
19431911
substrate_service.client.runtime_api().metadata_versions(genesis_hash)
19441912
else {
@@ -1954,7 +1922,9 @@ async fn create_online_client(
19541922
.runtime_api()
19551923
.metadata_at_version(genesis_hash, latest_metadata_version)
19561924
.map_err(|_| Error::InternalError("Failed to get runtime API".to_string()))?
1957-
.ok_or_else(|| Error::InternalError(format!("Metadata not found for version {latest_metadata_version}")))?;
1925+
.ok_or_else(|| {
1926+
Error::InternalError(format!("Metadata not found for version {latest_metadata_version}"))
1927+
})?;
19581928

19591929
let subxt_metadata = SubxtMetadata::decode(&mut (*opaque_metadata).as_slice())
19601930
.map_err(|_| Error::InternalError("Unable to decode metadata".to_string()))?;
@@ -1978,22 +1948,57 @@ async fn create_revive_rpc_client(
19781948
keep_latest_n_blocks: Option<usize>,
19791949
in_fork_mode: bool,
19801950
) -> Result<Option<EthRpcClient>> {
1981-
// In fork mode, check if ReviveApi exists in metadata before proceeding
1951+
// In fork mode, try to create the EthRpcClient. If it fails (e.g., ReviveApi not available),
1952+
// return None to indicate limited mode without EVM RPC functionality.
1953+
// This is more robust than checking metadata, which may not include runtime API information.
19821954
if in_fork_mode {
1983-
let metadata = api.metadata();
1984-
let has_revive_api = metadata.runtime_api_traits().any(|trait_metadata| {
1985-
trait_metadata.name() == "ReviveApi"
1986-
});
1987-
1988-
if !has_revive_api {
1989-
tracing::warn!(
1990-
"ReviveApi runtime trait not found in metadata. \
1991-
Forking in limited mode - EVM RPC functionality will not be available."
1992-
);
1993-
return Ok(None);
1955+
// Try to create the client - if ReviveApi doesn't exist, this will fail
1956+
match create_revive_client_impl(
1957+
api.clone(),
1958+
rpc_client.clone(),
1959+
rpc.clone(),
1960+
block_provider.clone(),
1961+
task_spawn_handle.clone(),
1962+
keep_latest_n_blocks,
1963+
)
1964+
.await
1965+
{
1966+
Ok(client) => {
1967+
tracing::info!("ReviveApi available - EVM RPC functionality enabled");
1968+
return Ok(Some(client));
1969+
}
1970+
Err(e) => {
1971+
tracing::warn!(
1972+
"ReviveApi not available in forked chain: {}. \
1973+
Forking in limited mode - EVM RPC functionality will not be available.",
1974+
e
1975+
);
1976+
return Ok(None);
1977+
}
19941978
}
19951979
}
19961980

1981+
// Normal mode: create the client and return errors if it fails
1982+
create_revive_client_impl(
1983+
api,
1984+
rpc_client,
1985+
rpc,
1986+
block_provider,
1987+
task_spawn_handle,
1988+
keep_latest_n_blocks,
1989+
)
1990+
.await
1991+
.map(Some)
1992+
}
1993+
1994+
async fn create_revive_client_impl(
1995+
api: OnlineClient<SrcChainConfig>,
1996+
rpc_client: RpcClient,
1997+
rpc: LegacyRpcMethods<SrcChainConfig>,
1998+
block_provider: SubxtBlockInfoProvider,
1999+
task_spawn_handle: SpawnTaskHandle,
2000+
keep_latest_n_blocks: Option<usize>,
2001+
) -> Result<EthRpcClient> {
19972002
let pool = SqlitePoolOptions::new()
19982003
.max_connections(1)
19992004
// see sqlite in-memory issue: https://github.com/launchbadge/sqlx/issues/2510
@@ -2024,23 +2029,20 @@ async fn create_revive_rpc_client(
20242029
.await
20252030
.map_err(Error::from)?;
20262031

2027-
// Skip block subscription task in fork mode since it requires ReviveApi
2028-
if !in_fork_mode {
2029-
// Capacity is chosen using random.org
2030-
eth_rpc_client.set_block_notifier(Some(tokio::sync::broadcast::channel::<H256>(50).0));
2031-
let eth_rpc_client_clone = eth_rpc_client.clone();
2032-
task_spawn_handle.spawn("block-subscription", "None", async move {
2033-
let eth_rpc_client = eth_rpc_client_clone;
2034-
let best_future =
2035-
eth_rpc_client.subscribe_and_cache_new_blocks(SubscriptionType::BestBlocks);
2036-
let finalized_future =
2037-
eth_rpc_client.subscribe_and_cache_new_blocks(SubscriptionType::FinalizedBlocks);
2038-
let res = tokio::try_join!(best_future, finalized_future).map(|_| ());
2039-
if let Err(err) = res {
2040-
panic!("Block subscription task failed: {err:?}")
2041-
}
2042-
});
2043-
}
2032+
// Capacity is chosen using random.org
2033+
eth_rpc_client.set_block_notifier(Some(tokio::sync::broadcast::channel::<H256>(50).0));
2034+
let eth_rpc_client_clone = eth_rpc_client.clone();
2035+
task_spawn_handle.spawn("block-subscription", "None", async move {
2036+
let eth_rpc_client = eth_rpc_client_clone;
2037+
let best_future =
2038+
eth_rpc_client.subscribe_and_cache_new_blocks(SubscriptionType::BestBlocks);
2039+
let finalized_future =
2040+
eth_rpc_client.subscribe_and_cache_new_blocks(SubscriptionType::FinalizedBlocks);
2041+
let res = tokio::try_join!(best_future, finalized_future).map(|_| ());
2042+
if let Err(err) = res {
2043+
panic!("Block subscription task failed: {err:?}")
2044+
}
2045+
});
20442046

2045-
Ok(Some(eth_rpc_client))
2047+
Ok(eth_rpc_client)
20462048
}

0 commit comments

Comments
 (0)