Skip to content

Commit

Permalink
Merge pull request #65 from darthsiroftardis/get-era-summary
Browse files Browse the repository at this point in the history
Add `get-era-summary` subcommand - Manual Merge as can't disable in flight 18.04 requirement for testing.
  • Loading branch information
sacherjj authored Apr 21, 2023
2 parents 55f445a + 9022224 commit ea5fced
Show file tree
Hide file tree
Showing 7 changed files with 163 additions and 9 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ All notable changes to this project will be documented in this file. The format

## [Unreleased]

### Add
* Added a new subcommand `get-era-summary` which optionally takes a block identifier and returns an era summary from a Casper network.

### Changed
* Update dependencies.

## [1.5.1] - 2023-03-08

Expand Down
8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ doc = false
async-trait = "0.1.51"
base16 = "0.2.1"
base64 = "0.13.0"
casper-execution-engine = "3.0.0"
casper-node = "1.4.13"
casper-hashing = "1.4.3"
casper-types = "1.5.0"
casper-execution-engine = "=3.0.0"
casper-node = "=1.4.13"
casper-hashing = "=1.4.3"
casper-types = "=1.5.0"
clap = "2"
humantime = "2"
jsonrpc-lite = "0.5.0"
Expand Down
52 changes: 50 additions & 2 deletions lib/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,16 @@ mod validation;
use std::{convert::TryInto, fs, io::Cursor};

use jsonrpc_lite::JsonRpc;
use serde::Serialize;
use serde::{Deserialize, Serialize};

use casper_execution_engine::core::engine_state::ExecutableDeployItem;
use casper_hashing::Digest;
use casper_node::rpcs::chain::{BlockIdentifier, EraSummary};
use casper_node::{
rpcs::state::{DictionaryIdentifier, GlobalStateIdentifier},
types::{BlockHash, Deploy},
};
use casper_types::Key;
use casper_types::{Key, ProtocolVersion};

pub use cl_type::help;
pub use deploy::ListDeploysResult;
Expand Down Expand Up @@ -471,6 +472,32 @@ pub async fn get_era_info_by_switch_block(
.await
}

/// Retrieves era information under the stable EraSummary casper_types::Key.
///
/// * `maybe_rpc_id` is the JSON-RPC identifier, applied to the request and returned in the
/// response. If it can be parsed as an `i64` it will be used as a JSON integer. If empty, a
/// random `i64` will be assigned. Otherwise the provided string will be used verbatim.
/// * `node_address` is the hostname or IP and port of the node on which the HTTP service is
/// running, e.g. `"http://127.0.0.1:7777"`.
/// * When `verbosity_level` is `1`, the JSON-RPC request will be printed to `stdout` with long
/// string fields (e.g. hex-formatted raw Wasm bytes) shortened to a string indicating the char
/// count of the field. When `verbosity_level` is greater than `1`, the request will be printed
/// to `stdout` with no abbreviation of long fields. When `verbosity_level` is `0`, the request
/// will not be printed to `stdout`.
/// * `maybe_block_id` must be a hex-encoded, 32-byte hash digest or a `u64` representing the
/// `Block` height or empty. If empty, era information from the latest block will be returned if
/// available.
pub async fn get_era_summary(
maybe_rpc_id: &str,
node_address: &str,
verbosity_level: u64,
maybe_block_id: &str,
) -> Result<JsonRpc> {
RpcCall::new(maybe_rpc_id, node_address, verbosity_level)
.get_era_summary(maybe_block_id)
.await
}

/// Retrieves the bids and validators as of the most recently added `Block`.
///
/// * `maybe_rpc_id` is the JSON-RPC identifier, applied to the request and returned in the
Expand Down Expand Up @@ -1194,6 +1221,27 @@ impl<'a> TryInto<GlobalStateIdentifier> for GlobalStateStrParams<'a> {
}
}

/// Params for "chain_get_era_summary" RPC response.
#[derive(Serialize, Deserialize, Debug)]
#[serde(deny_unknown_fields)]
pub struct GetEraSummaryParams {
/// The block identifier.
pub block_identifier: BlockIdentifier,
}

/// Result for "chain_get_era_summary" RPC response.
#[derive(Serialize, Deserialize, Debug)]
#[serde(deny_unknown_fields)]
pub struct GetEraSummaryResult {
/// The RPC API version.
pub api_version: ProtocolVersion,
/// The era summary.
pub era_summary: EraSummary,
}

/// "chain_get_era_summary" RPC
pub struct GetEraSummary {}

/// When `verbosity_level` is `1`, the value will be printed to `stdout` with long string fields
/// (e.g. hex-formatted raw Wasm bytes) shortened to a string indicating the char count of the
/// field. When `verbosity_level` is greater than `1`, the value will be printed to `stdout` with
Expand Down
20 changes: 19 additions & 1 deletion lib/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,11 @@ use casper_types::{AsymmetricType, Key, PublicKey, URef};
use crate::{
deploy::{DeployExt, DeployParams, SendDeploy, Transfer},
error::{Error, Result},
validation, DictionaryItemStrParams, GlobalStateStrParams,
validation, DictionaryItemStrParams, GetEraSummary, GetEraSummaryParams, GlobalStateStrParams,
};

pub(crate) const GET_ERA_SUMMARY_METHOD: &str = "chain_get_era_summary";

/// Struct representing a single JSON-RPC call to the casper node.
#[derive(Debug)]
pub(crate) struct RpcCall {
Expand Down Expand Up @@ -188,6 +190,17 @@ impl RpcCall {
Ok(response)
}

pub(crate) async fn get_era_summary(self, maybe_block_identifier: &str) -> Result<JsonRpc> {
let response = match Self::block_identifier(maybe_block_identifier)? {
None => GetEraSummary::request(self).await,
Some(block_identifier) => {
let params = GetEraSummaryParams { block_identifier };
GetEraSummary::request_with_map_params(self, params).await
}
}?;
Ok(response)
}

pub(crate) async fn get_auction_info(self, maybe_block_identifier: &str) -> Result<JsonRpc> {
let response = match Self::block_identifier(maybe_block_identifier)? {
None => GetAuctionInfo::request(self).await,
Expand Down Expand Up @@ -479,6 +492,10 @@ impl RpcClient for GetValidatorChanges {
const RPC_METHOD: &'static str = Self::METHOD;
}

impl RpcClient for GetEraSummary {
const RPC_METHOD: &'static str = GET_ERA_SUMMARY_METHOD;
}

pub(crate) trait IntoJsonMap: Serialize {
fn into_json_map(self) -> Map<String, Value>
where
Expand All @@ -504,3 +521,4 @@ impl IntoJsonMap for GetAuctionInfoParams {}
impl IntoJsonMap for GetAccountInfoParams {}
impl IntoJsonMap for GetDictionaryItemParams {}
impl IntoJsonMap for QueryGlobalStateParams {}
impl IntoJsonMap for GetEraSummaryParams {}
46 changes: 46 additions & 0 deletions src/get_era_summary.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use std::str;

use async_trait::async_trait;
use clap::{App, ArgMatches, SubCommand};

use casper_client::{Error, GetEraSummary};

use crate::{command::ClientCommand, common, Success};

enum DisplayOrder {
Verbose,
NodeAddress,
RpcId,
BlockIdentifier,
}

#[async_trait]
impl<'a, 'b> ClientCommand<'a, 'b> for GetEraSummary {
const NAME: &'static str = "get-era-summary";
const ABOUT: &'static str = "Retrieves era information from the network";

fn build(display_order: usize) -> App<'a, 'b> {
SubCommand::with_name(Self::NAME)
.about(Self::ABOUT)
.display_order(display_order)
.arg(common::verbose::arg(DisplayOrder::Verbose as usize))
.arg(common::node_address::arg(
DisplayOrder::NodeAddress as usize,
))
.arg(common::rpc_id::arg(DisplayOrder::RpcId as usize))
.arg(common::block_identifier::arg(
DisplayOrder::BlockIdentifier as usize,
))
}

async fn run(matches: &ArgMatches<'a>) -> Result<Success, Error> {
let maybe_rpc_id = common::rpc_id::get(matches);
let node_address = common::node_address::get(matches);
let verbosity_level = common::verbose::get(matches);
let maybe_block_id = common::block_identifier::get(matches);

casper_client::get_era_summary(maybe_rpc_id, node_address, verbosity_level, maybe_block_id)
.await
.map(Success::from)
}
}
7 changes: 5 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ mod get_auction_info;
mod get_balance;
mod get_dictionary_item;
mod get_era_info_by_switch_block;
mod get_era_summary;
mod get_state_hash;
mod get_validator_changes;
mod keygen;
Expand All @@ -20,7 +21,7 @@ use std::process;
use clap::{crate_version, App};
use once_cell::sync::Lazy;

use casper_client::Error;
use casper_client::{Error, GetEraSummary};
use casper_node::rpcs::{
account::PutDeploy,
chain::{GetBlock, GetBlockTransfers, GetEraInfoBySwitchBlock, GetStateRootHash},
Expand Down Expand Up @@ -69,6 +70,7 @@ enum DisplayOrder {
GetBalance,
GetAccountInfo,
GetEraInfo,
GetEraSummary,
GetAuctionInfo,
GetValidatorChanges,
Keygen,
Expand Down Expand Up @@ -117,6 +119,7 @@ fn cli<'a, 'b>() -> App<'a, 'b> {
.subcommand(
QueryGlobalState::build(DisplayOrder::QueryGlobalState as usize).alias("query-state"),
)
.subcommand(GetEraSummary::build(DisplayOrder::GetEraSummary as usize))
}

#[tokio::main]
Expand Down Expand Up @@ -155,7 +158,7 @@ async fn main() {
(GetDictionaryItem::run(matches).await, matches)
}
(QueryGlobalState::NAME, Some(matches)) => (QueryGlobalState::run(matches).await, matches),

(GetEraSummary::NAME, Some(matches)) => (GetEraSummary::run(matches).await, matches),
_ => {
let _ = cli().print_long_help();
println!();
Expand Down
35 changes: 35 additions & 0 deletions tests/integration_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,12 @@ impl MockServerHandle {
.await
.map(|_| ())
}

async fn get_era_summary(&self, maybe_block_id: &str) -> Result<(), Error> {
casper_client::get_era_summary("1", &self.url(), 0, maybe_block_id)
.await
.map(|_| ())
}
}

impl Drop for MockServerHandle {
Expand Down Expand Up @@ -857,6 +863,35 @@ mod get_validator_changes {
}
}

mod get_era_summary {
use super::*;

use casper_client::GetEraSummaryParams;

const METHOD: &str = "chain_get_era_summary";

#[tokio::test(flavor = "multi_thread")]
async fn should_succeed_without_params() {
let server_handle = MockServerHandle::spawn_without_params(METHOD);
assert!(matches!(server_handle.get_era_summary("").await, Ok(())))
}

#[tokio::test(flavor = "multi_thread")]
async fn should_success_with_valid_block_hash() {
let server_handle = MockServerHandle::spawn::<GetEraSummaryParams>(METHOD);
assert!(matches!(
server_handle.get_era_summary(VALID_STATE_ROOT_HASH).await,
Ok(())
))
}

#[tokio::test(flavor = "multi_thread")]
async fn should_succeed_with_valid_block_height() {
let server_handle = MockServerHandle::spawn::<GetEraSummaryParams>(METHOD);
assert!(matches!(server_handle.get_era_summary("1").await, Ok(())))
}
}

mod make_deploy {
use super::*;

Expand Down

0 comments on commit ea5fced

Please sign in to comment.