From 50f8db00cac4651238b02d839ecd579a3aa871f0 Mon Sep 17 00:00:00 2001 From: Sergei Shulepov Date: Fri, 23 Feb 2024 22:58:10 +0700 Subject: [PATCH] shim/cli: `query block` --json flag Which allows outputting block data as JSON. --- Cargo.lock | 3 +++ ikura/shim/Cargo.toml | 3 +++ ikura/shim/src/cli.rs | 4 +++ ikura/shim/src/cmd/mod.rs | 2 +- ikura/shim/src/cmd/query/block.rs | 42 +++++++++++++++++-------------- ikura/shim/src/ikura_rpc/mod.rs | 6 +++++ 6 files changed, 40 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index df6cb9f4..7eef865d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4574,10 +4574,13 @@ dependencies = [ "hex", "ikura-nmt", "ikura-primitives", + "ikura-serde-util", "ikura-shim-common-rollkit", "ikura-shim-common-sovereign", "ikura-subxt", "jsonrpsee 0.20.3", + "serde", + "serde_json", "sha2 0.10.8", "subxt", "subxt-signer", diff --git a/ikura/shim/Cargo.toml b/ikura/shim/Cargo.toml index 961eb13e..73c34426 100644 --- a/ikura/shim/Cargo.toml +++ b/ikura/shim/Cargo.toml @@ -11,6 +11,7 @@ edition.workspace = true [dependencies] ikura-nmt = { workspace = true, default-features = true, features = ["serde"] } +ikura-serde-util = { workspace = true } ikura-subxt = { workspace = true } ikura-primitives = { workspace = true, default-features = true } ikura-shim-common-sovereign = { workspace = true, default-features = true, features = ["server"] } @@ -24,6 +25,8 @@ tracing = { workspace = true } tracing-subscriber = { workspace = true, features = ["env-filter"] } tokio = { workspace = true, features = ["rt-multi-thread", "macros", "net"] } async-trait = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } subxt = { workspace = true } subxt-signer = { workspace = true, features = ["subxt"] } sha2 = { workspace = true, default-features = true } diff --git a/ikura/shim/src/cli.rs b/ikura/shim/src/cli.rs index 4e391732..b2142dd6 100644 --- a/ikura/shim/src/cli.rs +++ b/ikura/shim/src/cli.rs @@ -275,6 +275,10 @@ pub mod query { #[clap(flatten)] pub block: BlockParams, + + /// Output the result as JSON. + #[clap(long)] + pub json: bool, } } diff --git a/ikura/shim/src/cmd/mod.rs b/ikura/shim/src/cmd/mod.rs index b3dcafba..d7d49a80 100644 --- a/ikura/shim/src/cmd/mod.rs +++ b/ikura/shim/src/cmd/mod.rs @@ -25,8 +25,8 @@ fn init_logging() -> anyhow::Result<()> { .with_default_directive(tracing_subscriber::filter::LevelFilter::INFO.into()) .from_env_lossy(); tracing_subscriber::registry() - .with(fmt::layer()) .with(filter) + .with(fmt::layer().with_writer(std::io::stderr)) .try_init()?; Ok(()) } diff --git a/ikura/shim/src/cmd/query/block.rs b/ikura/shim/src/cmd/query/block.rs index 43bf6cf8..946781e5 100644 --- a/ikura/shim/src/cmd/query/block.rs +++ b/ikura/shim/src/cmd/query/block.rs @@ -2,29 +2,33 @@ use super::{connect_rpc, get_block_at}; use crate::cli::query::block::Params; pub async fn run(params: Params) -> anyhow::Result<()> { - let Params { rpc, block } = params; + let Params { rpc, block, json } = params; let client = connect_rpc(rpc).await?; let block = get_block_at(&client, block).await?; - println!("Block: #{}", block.number); - println!(" Hash: 0x{}", hex::encode(&block.hash[..])); - println!(" Parent Hash: 0x{}", hex::encode(&block.parent_hash[..])); - println!(" Blobs Root: 0x{}", hex::encode(&block.tree_root.root[..])); - println!(" Min Namespace: {}", block.tree_root.min_ns); - println!(" Max Namespace: {}", block.tree_root.max_ns); - println!(" Timestamp: {}", block.timestamp); - println!( - " Blob Count: {} ({} bytes)", - block.blobs.len(), - block.blobs.iter().map(|b| b.data.len()).sum::(), - ); - for (i, blob) in block.blobs.into_iter().enumerate() { - println!(" Blob #{}", i); - println!(" Extrinsic Index: {}", blob.extrinsic_index); - println!(" Namespace: {}", &blob.namespace); - println!(" Size: {}", blob.data.len()); + if json { + let json = serde_json::to_string_pretty(&block)?; + println!("{}", json); + } else { + println!("Block: #{}", block.number); + println!(" Hash: 0x{}", hex::encode(&block.hash[..])); + println!(" Parent Hash: 0x{}", hex::encode(&block.parent_hash[..])); + println!(" Blobs Root: 0x{}", hex::encode(&block.tree_root.root[..])); + println!(" Min Namespace: {}", block.tree_root.min_ns); + println!(" Max Namespace: {}", block.tree_root.max_ns); + println!(" Timestamp: {}", block.timestamp); + println!( + " Blob Count: {} ({} bytes)", + block.blobs.len(), + block.blobs.iter().map(|b| b.data.len()).sum::(), + ); + for (i, blob) in block.blobs.into_iter().enumerate() { + println!(" Blob #{}", i); + println!(" Extrinsic Index: {}", blob.extrinsic_index); + println!(" Namespace: {}", &blob.namespace); + println!(" Size: {}", blob.data.len()); + } } - Ok(()) } diff --git a/ikura/shim/src/ikura_rpc/mod.rs b/ikura/shim/src/ikura_rpc/mod.rs index f7787374..2737ca9f 100644 --- a/ikura/shim/src/ikura_rpc/mod.rs +++ b/ikura/shim/src/ikura_rpc/mod.rs @@ -368,9 +368,12 @@ mod err { } /// Represents a ikura block. +#[derive(serde::Serialize, serde::Deserialize)] pub struct Block { pub number: u64, + #[serde(with = "ikura_serde_util::bytes32_hex")] pub hash: [u8; 32], + #[serde(with = "ikura_serde_util::bytes32_hex")] pub parent_hash: [u8; 32], pub tree_root: ikura_nmt::TreeRoot, pub timestamp: u64, @@ -398,10 +401,13 @@ impl Block { } /// Represents a blob in a ikura block. +#[derive(serde::Serialize, serde::Deserialize)] pub struct Blob { pub extrinsic_index: u32, pub namespace: Namespace, + #[serde(with = "ikura_serde_util::bytes32_hex")] pub sender: [u8; 32], + #[serde(with = "ikura_serde_util::bytes_hex")] pub data: Vec, }