Skip to content

Commit

Permalink
[feature] hyperledger-iroha#3231: Monolithic validator (hyperledger-i…
Browse files Browse the repository at this point in the history
…roha#3329)

Signed-off-by: Daniil Polyakov <arjentix@gmail.com>
  • Loading branch information
Arjentix committed Apr 20, 2023
1 parent 6e4bc16 commit a39235d
Show file tree
Hide file tree
Showing 111 changed files with 3,714 additions and 3,184 deletions.
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.

2 changes: 2 additions & 0 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ iroha_p2p = { version = "=2.0.0-pre-rc.13", path = "../p2p" }
iroha_schema_gen = { version = "=2.0.0-pre-rc.13", path = "../schema/gen", optional = true }
iroha_cli_derive = { version = "=2.0.0-pre-rc.13", path = "derive" }
iroha_genesis = { version = "=2.0.0-pre-rc.13", path = "../genesis" }
iroha_wasm_builder = { version = "=2.0.0-pre-rc.13", path = "../wasm_builder" }

async-trait = "0.1.60"
color-eyre = "0.6.2"
Expand All @@ -68,6 +69,7 @@ once_cell = "1.16.0"
owo-colors = { version = "3.5.0", features = ["supports-colors"] }
supports-color = "2.0.0"
thread-local-panic-hook = { version = "0.1.0", optional = true }
tempfile = "3.3.0"

[build-dependencies]
iroha_wasm_builder = { version = "=2.0.0-pre-rc.13", path = "../wasm_builder" }
Expand Down
13 changes: 8 additions & 5 deletions cli/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@
use eyre::{eyre, Result};
use vergen::{vergen, Config};

const PERMISSION_VALIDATORS_PATH: &str = "../permission_validators";
const DEFAULT_PERMISSION_VALIDATOR_PATH: &str = "../default_validator";

fn main() -> Result<()> {
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed={}", PERMISSION_VALIDATORS_PATH);
println!(
"cargo:rerun-if-changed={}",
DEFAULT_PERMISSION_VALIDATOR_PATH
);

extract_git_hash()?;
check_permission_validators()
check_default_validator()
}

fn extract_git_hash() -> Result<()> {
Expand All @@ -21,8 +24,8 @@ fn extract_git_hash() -> Result<()> {
vergen(config).map_err(|err| eyre!(Box::new(err)))
}

fn check_permission_validators() -> Result<()> {
iroha_wasm_builder::Builder::new(PERMISSION_VALIDATORS_PATH)
fn check_default_validator() -> Result<()> {
iroha_wasm_builder::Builder::new(DEFAULT_PERMISSION_VALIDATOR_PATH)
.format()
.check()?;
Ok(())
Expand Down
30 changes: 28 additions & 2 deletions cli/src/samples.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
#![allow(clippy::restriction)]
//! This module contains the sample configurations used for testing and benchmarking throghout Iroha.
use std::{collections::HashSet, str::FromStr};
use std::{collections::HashSet, path::Path, str::FromStr};

use eyre::WrapErr as _;
use iroha_config::{
iroha::{Configuration, ConfigurationProxy},
sumeragi::TrustedPeers,
torii::{uri::DEFAULT_API_URL, DEFAULT_TORII_P2P_ADDR, DEFAULT_TORII_TELEMETRY_URL},
};
use iroha_crypto::{KeyPair, PublicKey};
use iroha_data_model::peer::PeerId;
use iroha_data_model::{peer::PeerId, permission::Validator, prelude::*};

/// Get sample trusted peers. The public key must be the same as `configuration.public_key`
///
Expand Down Expand Up @@ -99,3 +100,28 @@ pub fn get_config(trusted_peers: HashSet<PeerId>, key_pair: Option<KeyPair>) ->
.build()
.expect("Iroha config should build as all required fields were provided")
}

/// Construct validator from path.
///
/// `relative_path` should be relative to `CARGO_MANIFEST_DIR`.
///
/// # Errors
///
/// - Failed to create temp dir for validator output
/// - Failed to build validator
/// - Failed to optimize validator
pub fn construct_validator<P>(relative_path: &P) -> color_eyre::Result<Validator>
where
P: AsRef<Path> + ?Sized,
{
let build_dir =
tempfile::tempdir().wrap_err("Failed to create temp dir for runtime validator output")?;

let wasm_blob = iroha_wasm_builder::Builder::new(relative_path)
.out_dir(build_dir.path())
.build()?
.optimize()?
.into_bytes();

Ok(Validator::new(WasmSmartContract::new(wasm_blob)))
}
2 changes: 1 addition & 1 deletion cli/src/torii/routing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ impl VerifiedQuery {
"Signature public key doesn't correspond to the account.",
)));
}
wsv.validators_view()
wsv.validator_view()
.validate(wsv, &self.payload.account_id, self.payload.query.clone())
.map_err(|err| QueryExecutionFailure::Permission(err.to_string()))?;
Ok((
Expand Down
36 changes: 24 additions & 12 deletions client/benches/torii.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
use std::thread;

use criterion::{criterion_group, criterion_main, Criterion, Throughput};
use iroha::samples::get_config;
use iroha::samples::{construct_validator, get_config};
use iroha_client::client::{asset, Client};
use iroha_config::{base::runtime_upgrades::Reload, logger};
use iroha_crypto::KeyPair;
use iroha_data_model::prelude::*;
use iroha_genesis::{GenesisNetwork, GenesisNetworkTrait, RawGenesisBlock};
use iroha_genesis::{GenesisNetwork, GenesisNetworkTrait, RawGenesisBlockBuilder};
use iroha_primitives::small::SmallStr;
use iroha_version::Encode;
use test_network::{get_key_pair, Peer as TestPeer, PeerBuilder, TestRuntime};
Expand All @@ -26,11 +26,17 @@ fn query_requests(criterion: &mut Criterion) {
let rt = Runtime::test();
let genesis = GenesisNetwork::from_configuration(
true,
RawGenesisBlock::new(
"alice".parse().expect("Valid"),
"wonderland".parse().expect("Valid"),
get_key_pair().public_key().clone(),
),
RawGenesisBlockBuilder::new()
.domain("wonderland".parse().expect("Valid"))
.account(
"alice".parse().expect("Valid"),
get_key_pair().public_key().clone(),
)
.finish_domain()
.validator(
construct_validator("../default_validator").expect("Failed to construct validator"),
)
.build(),
Some(&configuration.genesis),
&configuration.sumeragi.transaction_limits,
)
Expand Down Expand Up @@ -122,11 +128,17 @@ fn instruction_submits(criterion: &mut Criterion) {
);
let genesis = GenesisNetwork::from_configuration(
true,
RawGenesisBlock::new(
"alice".parse().expect("Valid"),
"wonderland".parse().expect("Valid"),
configuration.public_key.clone(),
),
RawGenesisBlockBuilder::new()
.domain("wonderland".parse().expect("Valid"))
.account(
"alice".parse().expect("Valid"),
configuration.public_key.clone(),
)
.finish_domain()
.validator(
construct_validator("../default_validator").expect("Failed to construct validator"),
)
.build(),
Some(&configuration.genesis),
&configuration.sumeragi.transaction_limits,
)
Expand Down
8 changes: 6 additions & 2 deletions client/examples/million_accounts_genesis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use std::{thread, time::Duration};

use iroha::samples::get_config;
use iroha::samples::{construct_validator, get_config};
use iroha_data_model::prelude::*;
use iroha_genesis::{GenesisNetwork, GenesisNetworkTrait, RawGenesisBlock, RawGenesisBlockBuilder};
use test_network::{
Expand All @@ -28,7 +28,11 @@ fn generate_genesis(num_domains: u32) -> RawGenesisBlock {
.finish_domain();
}

builder.build()
builder
.validator(
construct_validator("../default_validator").expect("Failed to construct validator"),
)
.build()
}

fn main_genesis() {
Expand Down
2 changes: 1 addition & 1 deletion client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ impl Client {
&self,
transaction: SignedTransaction,
) -> Result<HashOf<VersionedSignedTransaction>> {
iroha_logger::trace!(tx=?transaction);
iroha_logger::trace!(tx=?transaction, "Submitting");
let (req, hash, resp_handler) =
self.prepare_transaction_request::<DefaultRequestBuilder>(transaction)?;
let response = req
Expand Down
117 changes: 82 additions & 35 deletions client/tests/integration/asset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::{str::FromStr as _, thread};

use eyre::Result;
use iroha_client::client;
use iroha_crypto::{KeyPair, PublicKey};
use iroha_data_model::prelude::*;
use iroha_primitives::fixed::Fixed;
use test_network::*;
Expand Down Expand Up @@ -233,17 +234,57 @@ fn client_add_asset_with_name_length_more_than_limit_should_not_commit_transacti
}

#[allow(unused_must_use)]
#[allow(clippy::too_many_lines)]
#[allow(clippy::expect_fun_call)]
#[test]
fn find_rate_and_make_exchange_isi_should_succeed() {
let (_rt, _peer, test_client) = <PeerBuilder>::new().with_port(10_675).start_with_runtime();

let alice_id: AccountId = "alice@wonderland".parse().expect("Valid.");
let seller_id: AccountId = "seller@company".parse().expect("Valid.");
let buyer_id: AccountId = "buyer@company".parse().expect("Valid.");

let seller_btc: AssetId = "btc#crypto#seller@company".parse().expect("Valid.");
let buyer_eth: AssetId = "eth#crypto#buyer@company".parse().expect("Valid.");

let seller_keypair = KeyPair::generate().expect("Failed to generate seller KeyPair.");
let buyer_keypair = KeyPair::generate().expect("Failed to generate seller KeyPair.");

let register_account = |account_id: AccountId, signature: PublicKey| {
RegisterBox::new(Account::new(account_id, [signature]))
};

let grant_alice_asset_transfer_permission = |asset_id: AssetId, owner_keypair: KeyPair| {
let allow_alice_to_transfer_asset = GrantBox::new(
PermissionToken::new("can_transfer_user_asset".parse().expect("Valid"))
.with_params([("asset_id".parse().expect("Valid"), asset_id.clone().into())]),
alice_id.clone(),
)
.into();

let grant_asset_transfer_tx = TransactionBuilder::new(
asset_id.account_id().clone(),
vec![allow_alice_to_transfer_asset],
100_000,
)
.sign(owner_keypair)
.expect("Failed to sign seller transaction");

test_client
.submit_transaction_blocking(grant_asset_transfer_tx)
.expect(&format!(
"Failed to grant permission alice to transfer {}.",
asset_id
));
};

test_client
.submit_all_blocking(vec![
register::domain("exchange").into(),
register::domain("company").into(),
register::domain("crypto").into(),
register::account("seller", "company").into(),
register::account("buyer", "company").into(),
register_account(seller_id, seller_keypair.public_key().clone()).into(),
register_account(buyer_id, buyer_keypair.public_key().clone()).into(),
register::account("dex", "exchange").into(),
register::asset_definition("btc", "crypto").into(),
register::asset_definition("eth", "crypto").into(),
Expand All @@ -263,43 +304,49 @@ fn find_rate_and_make_exchange_isi_should_succeed() {
IdBox::AssetId(asset_id_new("btc2eth_rate", "exchange", "dex", "exchange")),
)
.into(),
Pair::new(
TransferBox::new(
IdBox::AssetId(asset_id_new("btc", "crypto", "seller", "company")),
EvaluatesTo::new_evaluates_to_value(
Expression::Query(
FindAssetQuantityById::new(asset_id_new(
"btc2eth_rate",
"exchange",
"dex",
"exchange",
))
.into(),
)
])
.expect("Failed to prepare accounts.");

grant_alice_asset_transfer_permission(seller_btc, seller_keypair);
grant_alice_asset_transfer_permission(buyer_eth, buyer_keypair);

test_client
.submit_all_blocking(vec![Pair::new(
TransferBox::new(
IdBox::AssetId(asset_id_new("btc", "crypto", "seller", "company")),
EvaluatesTo::new_evaluates_to_value(
Expression::Query(
FindAssetQuantityById::new(asset_id_new(
"btc2eth_rate",
"exchange",
"dex",
"exchange",
))
.into(),
),
IdBox::AssetId(asset_id_new("btc", "crypto", "buyer", "company")),
)
.into(),
),
TransferBox::new(
IdBox::AssetId(asset_id_new("eth", "crypto", "buyer", "company")),
EvaluatesTo::new_evaluates_to_value(
Expression::Query(
FindAssetQuantityById::new(asset_id_new(
"btc2eth_rate",
"exchange",
"dex",
"exchange",
))
.into(),
)
IdBox::AssetId(asset_id_new("btc", "crypto", "buyer", "company")),
),
TransferBox::new(
IdBox::AssetId(asset_id_new("eth", "crypto", "buyer", "company")),
EvaluatesTo::new_evaluates_to_value(
Expression::Query(
FindAssetQuantityById::new(asset_id_new(
"btc2eth_rate",
"exchange",
"dex",
"exchange",
))
.into(),
),
IdBox::AssetId(asset_id_new("eth", "crypto", "seller", "company")),
)
.into(),
),
)
.into(),
])
.expect("Failed to execute Iroha Special Instruction.");
IdBox::AssetId(asset_id_new("eth", "crypto", "seller", "company")),
),
)
.into()])
.expect("Failed to exchange eth for btc.");

let expected_seller_eth = NumericValue::U32(20);
let expected_buyer_eth = NumericValue::U32(180);
Expand Down
Loading

0 comments on commit a39235d

Please sign in to comment.