jam_tooling/
rpc.rs

1use crate::{CodeInfo, Error};
2use codec::{Compact, Decode, Encode};
3use corevm_host::StorageKey;
4use jam_program_blob::{read_metadata, ConventionalMetadata as Metadata, CrateInfo};
5use jam_std_common::{RpcClient, Service, SyncStatus};
6use jam_types::{CodeHash, Hash, HeaderHash, ServiceId};
7use jsonrpsee::ws_client::WsClient;
8
9pub async fn query_service(
10	rpc: &WsClient,
11	head: HeaderHash,
12	id: ServiceId,
13) -> Result<(Service, CodeInfo<CrateInfo>, Option<CodeInfo<CrateInfo>>), anyhow::Error> {
14	use CodeInfo::*;
15	let req = rpc.service_data(head, id).await?.ok_or(Error::ServiceNotFound)?;
16	let info = Service::decode(&mut &req[..]).map_err(Error::InvalidServiceEncoding)?;
17	let maybe_code = rpc.service_preimage(head, id, info.code_hash.0).await?;
18	let meta = match maybe_code {
19		None => CodeNotProvided(info.code_hash),
20		Some(code) => match <(Compact<u32>, Metadata)>::decode(&mut &code[..]).ok().map(|x| x.1) {
21			None => Undefined(info.code_hash),
22			Some(Metadata::Info(crate_info)) => Known(crate_info),
23		},
24	};
25	let inner_meta = match &meta {
26		Known(info) if info.name == "corevm" => {
27			if let Some(inner_code) =
28				rpc.service_value(head, id, StorageKey::GuestCode.encode()).await?
29			{
30				let (file_hash, code_host) = <(CodeHash, ServiceId)>::decode(&mut &inner_code[..])
31					.map_err(Error::InvalidServiceEncoding)?;
32				log::info!("inner file hash: {file_hash}, service id: {code_host}");
33				let maybe_file_chunk = rpc.service_preimage(head, code_host, file_hash.0).await?;
34				Some(match maybe_file_chunk {
35					None => CodeNotProvided(file_hash),
36					Some(data) => {
37						let _next_hash = Hash::try_from(&data[..32]).expect("fixed length");
38						let code = &data[32..];
39						match read_metadata(&mut &code[..]) {
40							Err(_) => Undefined(file_hash),
41							Ok(Metadata::Info(crate_info)) => Known(crate_info),
42						}
43					},
44				})
45			} else {
46				None
47			}
48		},
49		_ => None,
50	};
51	Ok((info, meta, inner_meta))
52}
53
54pub async fn wait_for_sync(rpc: &WsClient) -> Result<(), anyhow::Error> {
55	let mut sync_state = rpc.subscribe_sync_status().await?;
56	loop {
57		let status = sync_state.next().await;
58		match status {
59			Some(Ok(SyncStatus::Completed)) => break,
60			Some(Ok(_)) => continue,
61			Some(Err(e)) => return Err(e)?,
62			None => break,
63		}
64	}
65	// Wait for any non-genesis block to be finalized
66	let mut final_block = rpc.subscribe_finalized_block().await?;
67	loop {
68		let status = final_block.next().await;
69		match status {
70			Some(Ok(block)) if block.slot > 0 => break,
71			Some(Ok(_)) => continue,
72			Some(Err(e)) => return Err(e)?,
73			None => break,
74		}
75	}
76	Ok(())
77}