Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor!: shift from JsonString to JsonValue #5012

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 6 additions & 3 deletions client/tests/integration/multisig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ fn mutlisig() -> Result<()> {
.map(Register::account),
)?;

let call_trigger = ExecuteTrigger::new(multisig_register_trigger_id).with_args(&args);
let call_trigger = ExecuteTrigger::new(multisig_register_trigger_id)
.with_args(serde_json::to_value(&args).unwrap());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks like a step back

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed implicit conversions on purpose.

Before there was From<T: Serialize> for JsonValue, and was able to panic implicitly if for some reason T fails to serialize as JSON. Now it is explicit, at least.

I tried to make emphasis on relying on the "standard" way of working with JSON in Rust, i.e. on serde_json.

Actually, this serde_json::to_value(&args).unwrap() could be shortcut to just json!(&args). And I would strongly prefer that rather than adding some methods to JsonValue, making it unintuitive to use.

test_client.submit_blocking(call_trigger)?;

// Check that multisig account exist
Expand All @@ -107,7 +108,8 @@ fn mutlisig() -> Result<()> {

if let Some((signatory, key_pair)) = signatories_iter.next() {
let args = MultisigArgs::Instructions(isi);
let call_trigger = ExecuteTrigger::new(multisig_trigger_id.clone()).with_args(&args);
let call_trigger = ExecuteTrigger::new(multisig_trigger_id.clone())
.with_args(serde_json::to_value(&args).unwrap());
test_client.submit_transaction_blocking(
&TransactionBuilder::new(test_client.chain.clone(), signatory)
.with_instructions([call_trigger])
Expand All @@ -125,7 +127,8 @@ fn mutlisig() -> Result<()> {

for (signatory, key_pair) in signatories_iter {
let args = MultisigArgs::Vote(isi_hash);
let call_trigger = ExecuteTrigger::new(multisig_trigger_id.clone()).with_args(&args);
let call_trigger = ExecuteTrigger::new(multisig_trigger_id.clone())
.with_args(serde_json::to_value(&args).unwrap());
test_client.submit_transaction_blocking(
&TransactionBuilder::new(test_client.chain.clone(), signatory)
.with_instructions([call_trigger])
Expand Down
15 changes: 6 additions & 9 deletions client/tests/integration/permissions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ fn permissions_differ_not_only_by_names() {
.submit_blocking(SetKeyValue::asset(
mouse_hat_id,
Name::from_str("color").expect("Valid"),
"red".parse::<JsonString>().expect("Valid"),
"red",
))
.expect("Failed to modify Mouse's hats");

Expand All @@ -268,7 +268,7 @@ fn permissions_differ_not_only_by_names() {
let set_shoes_color = SetKeyValue::asset(
mouse_shoes_id.clone(),
Name::from_str("color").expect("Valid"),
"yellow".parse::<JsonString>().expect("Valid"),
"yellow",
);
let _err = client
.submit_blocking(set_shoes_color.clone())
Expand Down Expand Up @@ -316,11 +316,12 @@ fn stored_vs_granted_permission_payload() -> Result<()> {
.expect("Failed to register mouse");

// Allow alice to mint mouse asset and mint initial value
let value_json = JsonString::from_string_unchecked(format!(
let value_json = JsonValue::from_string(format!(
// NOTE: Permissions is created explicitly as a json string to introduce additional whitespace
// This way, if the executor compares permissions just as JSON strings, the test will fail
r##"{{ "asset" : "xor#wonderland#{mouse_id}" }}"##
));
))
.expect("input is a valid JSON");

let mouse_asset = AssetId::new(asset_definition_id, mouse_id.clone());
let allow_alice_to_set_key_value_in_mouse_asset = Grant::account_permission(
Expand All @@ -336,11 +337,7 @@ fn stored_vs_granted_permission_payload() -> Result<()> {
.expect("Failed to grant permission to alice.");

// Check that alice can indeed mint mouse asset
let set_key_value = SetKeyValue::asset(
mouse_asset,
Name::from_str("color")?,
"red".parse::<JsonString>().expect("Valid"),
);
let set_key_value = SetKeyValue::asset(mouse_asset, Name::from_str("color")?, "red");
iroha
.submit_blocking(set_key_value)
.expect("Failed to mint asset for mouse.");
Expand Down
11 changes: 6 additions & 5 deletions client/tests/integration/queries/smart_contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@ fn live_query_is_dropped_after_smart_contract_end() -> Result<()> {
client.build_transaction(WasmSmartContract::from_compiled(wasm), Metadata::default());
client.submit_transaction_blocking(&transaction)?;

let metadata_value: JsonString = client.query_single(FindAccountMetadata::new(
client.account.clone(),
Name::from_str("cursor").unwrap(),
))?;
let asset_cursor = metadata_value.try_into_any()?;
let asset_cursor = client
.query_single(FindAccountMetadata::new(
client.account.clone(),
Name::from_str("cursor").unwrap(),
))?
.try_into_any()?;

// here we are breaking the abstraction preventing us from using a cursor we pulled from the metadata
let err = client
Expand Down
12 changes: 2 additions & 10 deletions client/tests/integration/roles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,7 @@ fn register_and_grant_role_for_metadata_access() -> Result<()> {
test_client.submit_transaction_blocking(&grant_role_tx)?;

// Alice modifies Mouse's metadata
let set_key_value = SetKeyValue::account(
mouse_id,
"key".parse::<Name>()?,
"value".parse::<JsonString>()?,
);
let set_key_value = SetKeyValue::account(mouse_id, "key".parse::<Name>()?, "value");
test_client.submit_blocking(set_key_value)?;

// Making request to find Alice's roles
Expand Down Expand Up @@ -224,11 +220,7 @@ fn grant_revoke_role_permissions() -> Result<()> {
.sign(mouse_keypair.private_key());
test_client.submit_transaction_blocking(&grant_role_tx)?;

let set_key_value = SetKeyValue::account(
mouse_id.clone(),
"key".parse()?,
"value".parse::<JsonString>()?,
);
let set_key_value = SetKeyValue::account(mouse_id.clone(), "key".parse()?, "value");
let can_set_key_value_in_mouse = CanSetKeyValueInAccount {
account: mouse_id.clone(),
};
Expand Down
2 changes: 1 addition & 1 deletion client/tests/integration/sorting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ fn correct_pagination_assets_after_creating_new_one() {
AssetDefinitionId::from_str(&format!("xor{i}#wonderland")).expect("Valid");
let asset_definition = AssetDefinition::store(asset_definition_id.clone());
let mut asset_metadata = Metadata::default();
asset_metadata.insert(sort_by_metadata_key.clone(), i as u32);
asset_metadata.insert(sort_by_metadata_key.clone(), i);
let asset = Asset::new(
AssetId::new(asset_definition_id, account_id.clone()),
AssetValue::Store(asset_metadata),
Expand Down
21 changes: 12 additions & 9 deletions client/tests/integration/transfer_domain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ use iroha_executor_data_model::permission::{
trigger::CanUnregisterUserTrigger,
};
use iroha_genesis::GenesisBlock;
use iroha_primitives::json::JsonString;
use test_network::{Peer as TestPeer, *};
use test_samples::{gen_account_in, ALICE_ID, BOB_ID, SAMPLE_GENESIS_ACCOUNT_ID};
use tokio::runtime::Runtime;
Expand Down Expand Up @@ -74,8 +73,11 @@ fn domain_owner_domain_permissions() -> Result<()> {

// check that "alice@wonderland" as owner of domain can edit metadata in her domain
let key: Name = "key".parse()?;
let value = JsonString::new("value");
test_client.submit_blocking(SetKeyValue::domain(kingdom_id.clone(), key.clone(), value))?;
test_client.submit_blocking(SetKeyValue::domain(
kingdom_id.clone(),
key.clone(),
"value",
))?;
test_client.submit_blocking(RemoveKeyValue::domain(kingdom_id.clone(), key))?;

// check that "alice@wonderland" as owner of domain can grant and revoke domain related permissions
Expand Down Expand Up @@ -111,11 +113,10 @@ fn domain_owner_account_permissions() -> Result<()> {

// check that "alice@wonderland" as owner of domain can edit metadata of account in her domain
let key: Name = "key".parse()?;
let value = JsonString::new("value");
test_client.submit_blocking(SetKeyValue::account(
mad_hatter_id.clone(),
key.clone(),
value,
"value",
))?;
test_client.submit_blocking(RemoveKeyValue::account(mad_hatter_id.clone(), key))?;

Expand Down Expand Up @@ -177,11 +178,10 @@ fn domain_owner_asset_definition_permissions() -> Result<()> {

// check that "alice@wonderland" as owner of domain can edit metadata of asset definition in her domain
let key: Name = "key".parse()?;
let value = JsonString::new("value");
test_client.submit_blocking(SetKeyValue::asset_definition(
coin_id.clone(),
key.clone(),
value,
"value",
))?;
test_client.submit_blocking(RemoveKeyValue::asset_definition(coin_id.clone(), key))?;

Expand Down Expand Up @@ -249,9 +249,12 @@ fn domain_owner_asset_permissions() -> Result<()> {

// check that "alice@wonderland" as owner of domain can edit metadata of store asset in her domain
let key: Name = "key".parse()?;
let value = JsonString::new("value");
let bob_store_id = AssetId::new(store_id, bob_id.clone());
test_client.submit_blocking(SetKeyValue::asset(bob_store_id.clone(), key.clone(), value))?;
test_client.submit_blocking(SetKeyValue::asset(
bob_store_id.clone(),
key.clone(),
"value",
))?;
test_client.submit_blocking(RemoveKeyValue::asset(bob_store_id.clone(), key))?;

// check that "alice@wonderland" as owner of domain can grant and revoke asset related permissions in her domain
Expand Down
9 changes: 3 additions & 6 deletions client/tests/integration/triggers/by_call_trigger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use iroha::{
use iroha_executor_data_model::permission::trigger::CanRegisterUserTrigger;
use iroha_genesis::GenesisBlock;
use iroha_logger::info;
use serde_json::json;
use test_network::{Peer as TestPeer, *};
use test_samples::ALICE_ID;
use tokio::runtime::Runtime;
Expand Down Expand Up @@ -458,11 +459,7 @@ fn trigger_in_genesis_using_base64() -> Result<()> {

// Executing trigger
test_client
.submit_blocking(SetKeyValue::trigger(
trigger_id.clone(),
"VAL".parse()?,
1_u32,
))
.submit_blocking(SetKeyValue::trigger(trigger_id.clone(), "VAL".parse()?, 1))
.unwrap();
let call_trigger = ExecuteTrigger::new(trigger_id);
test_client.submit_blocking(call_trigger)?;
Expand Down Expand Up @@ -685,7 +682,7 @@ fn call_execute_trigger_with_args() -> Result<()> {
test_client.submit_blocking(Register::trigger(trigger))?;

let args: MintRoseArgs = MintRoseArgs { val: 42 };
let call_trigger = ExecuteTrigger::new(trigger_id).with_args(&args);
let call_trigger = ExecuteTrigger::new(trigger_id).with_args(json!(args));
test_client.submit_blocking(call_trigger)?;

let new_value = get_asset_value(&mut test_client, asset_id);
Expand Down
12 changes: 2 additions & 10 deletions client/tests/integration/triggers/time_trigger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,11 +203,7 @@ fn pre_commit_trigger_should_be_executed() -> Result<()> {
prev_value = new_value;

// ISI just to create a new block
let sample_isi = SetKeyValue::account(
account_id.clone(),
"key".parse::<Name>()?,
"value".parse::<JsonString>()?,
);
let sample_isi = SetKeyValue::account(account_id.clone(), "key".parse::<Name>()?, "value");
test_client.submit(sample_isi)?;
}

Expand Down Expand Up @@ -343,11 +339,7 @@ fn submit_sample_isi_on_every_block_commit(
for _ in block_committed_event_listener.take(times) {
std::thread::sleep(timeout);
// ISI just to create a new block
let sample_isi = SetKeyValue::account(
account_id.clone(),
"key".parse::<Name>()?,
JsonString::new("value"),
);
let sample_isi = SetKeyValue::account(account_id.clone(), "key".parse::<Name>()?, "value");
test_client.submit(sample_isi)?;
}

Expand Down
80 changes: 44 additions & 36 deletions client_cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use erased_serde::Serialize;
use error_stack::{fmt::ColorMode, IntoReportCompat, ResultExt};
use eyre::{eyre, Error, Result, WrapErr};
use iroha::{client::Client, config::Config, data_model::prelude::*};
use iroha_primitives::{addr::SocketAddr, json::JsonString};
use iroha_primitives::addr::SocketAddr;
use thiserror::Error;

/// Re-usable clap `--metadata <PATH>` (`-m`) argument.
Expand Down Expand Up @@ -49,25 +49,29 @@ impl MetadataArgs {

/// Re-usable clap `--value <MetadataValue>` (`-v`) argument.
/// Should be combined with `#[command(flatten)]` attr.
#[derive(clap::Args, Debug, Clone, PartialEq, Eq)]
#[derive(clap::Args, Debug, Clone)]
pub struct MetadataValueArg {
/// Wrapper around `MetadataValue` to accept possible values and fallback to json.
/// Value in metadata key-value map, JSON
///
/// The following types are supported:
/// Numbers: decimal with optional point
/// Booleans: false/true
/// Objects: e.g. {"Vec":[{"String":"a"},{"String":"b"}]}
#[arg(short, long)]
value: JsonString,
/// Examples:
///
/// - `--value false`
/// - `--value 42`
/// - `--value '"i am a string"'`
/// - `--value '[1, 2, 3]'`
#[arg(short, long, value_name("JSON VALUE"))]
value: JsonArg,
}

impl FromStr for MetadataValueArg {
type Err = Error;
#[derive(Clone, Debug)]
struct JsonArg(serde_json::Value);

fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(MetadataValueArg {
value: JsonString::from_str(s)?,
})
impl FromStr for JsonArg {
type Err = serde_json::Error;

fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
let value = serde_json::from_str(s)?;
Ok(Self(value))
}
}

Expand Down Expand Up @@ -514,7 +518,7 @@ mod domain {
key,
value: MetadataValueArg { value },
} = self;
let set_key_value = SetKeyValue::domain(id, key, value);
let set_key_value = SetKeyValue::domain(id, key, value.0);
submit([set_key_value], Metadata::default(), context)
.wrap_err("Failed to submit Set instruction")
}
Expand Down Expand Up @@ -967,7 +971,7 @@ mod asset {
value: MetadataValueArg { value },
} = self;

let set = iroha::data_model::isi::SetKeyValue::asset(asset_id, key, value);
let set = iroha::data_model::isi::SetKeyValue::asset(asset_id, key, value.0);
submit([set], Metadata::default(), context)?;
Ok(())
}
Expand Down Expand Up @@ -1199,30 +1203,34 @@ mod json {
}
#[cfg(test)]
mod tests {
use std::str::FromStr;
use clap::Parser;
use serde_json::json;

use super::*;

#[test]
fn parse_value_arg_cases() {
macro_rules! case {
($input:expr, $expected:expr) => {
let MetadataValueArg { value } =
MetadataValueArg::from_str($input).expect("should not fail with valid input");
assert_eq!(value, $expected);
};
fn parse_metadata_value_arg() {
#[derive(Parser)]
struct Args {
#[command(flatten)]
value: MetadataValueArg,
}

// Boolean values
case!("true", JsonString::new(true));
case!("false", JsonString::new(false));

// Numeric values
case!("\"123\"", JsonString::new(numeric!(123)));
case!("\"123.0\"", JsonString::new(numeric!(123.0)));

// JSON Value
let json_str = r#"{"Vec":[{"String":"a"},{"String":"b"}]}"#;
case!(json_str, serde_json::from_str(json_str).unwrap());
for (as_str, as_value) in [
("null", json!(null)),
("false", json!(false)),
("\"i am arg\"", json!("i am arg")),
("[3,2,1]", json!([3, 2, 1])),
] {
let Args {
value:
MetadataValueArg {
value: JsonArg(value),
},
} = Args::try_parse_from(["whatever", "--value", as_str])
.expect("should parse input fine");

assert_eq!(value, as_value);
}
}
}
4 changes: 1 addition & 3 deletions core/src/query/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,6 @@ mod tests {
permission::Permission,
query::parameters::{FetchSize, Pagination, QueryParams, Sorting},
};
use iroha_primitives::json::JsonString;
use nonzero_ext::nonzero;
use test_samples::ALICE_ID;

Expand All @@ -322,8 +321,7 @@ mod tests {
};

// it's not important which type we use here, just to test the flow
let query_output =
(0..100).map(|_| Permission::new(String::default(), JsonString::from(false)));
let query_output = (0..100).map(|_| Permission::new(String::default(), false));
let query_output = crate::smartcontracts::query::apply_query_postprocessing(
query_output,
&query_params,
Expand Down
Loading
Loading