From 2dbbfb4d30ca16e734e0672aedbfac140547ae32 Mon Sep 17 00:00:00 2001 From: brenzi Date: Thu, 10 Oct 2024 17:31:39 +0200 Subject: [PATCH] aggregate account getters to AccountInfo and rpc `author_getFingerprint` (#1611) * aggregate account getters to AccountInfo * fix clippy and bump version * add explicit fingerprint getter to simplify dynamic UI setup * fix clippy * fix the fix * revert mrenclave fetch logic for teeracle * add parentchains info public getter struct * cleanup * nesting guess-the-number calls and getters --- Cargo.lock | 4 +- app-libs/stf/src/getter.rs | 166 ++++++++------- app-libs/stf/src/guess_the_number.rs | 197 ++++++++++++++++++ app-libs/stf/src/lib.rs | 2 + app-libs/stf/src/trusted_call.rs | 78 +------ cli/Cargo.toml | 2 +- cli/benchmark.sh | 18 +- cli/demo_direct_call.sh | 13 +- cli/demo_shielding_unshielding.sh | 22 +- ...shielding_unshielding_using_shard_vault.sh | 23 +- ...shielding_using_shard_vault_on_target_a.sh | 22 +- cli/demo_sidechain.sh | 22 +- cli/demo_smart_contract.sh | 7 +- cli/src/base_cli/mod.rs | 2 +- cli/src/benchmark/mod.rs | 13 +- .../guess_the_number/commands/get_attempts.rs | 46 ++++ cli/src/guess_the_number/commands/get_info.rs | 7 +- cli/src/guess_the_number/commands/guess.rs | 13 +- cli/src/guess_the_number/commands/mod.rs | 1 + .../commands/push_by_one_day.rs | 13 +- .../guess_the_number/commands/set_winnings.rs | 13 +- cli/src/guess_the_number/mod.rs | 8 +- cli/src/lib.rs | 12 +- .../commands/get_fingerprint.rs | 64 ++++++ .../commands/get_parentchains_info.rs | 36 ++++ cli/src/trusted_base_cli/commands/mod.rs | 3 + cli/src/trusted_base_cli/mod.rs | 15 +- cli/src/trusted_command_utils.rs | 17 +- cli/test_auto_shielding_with_transfer_bob.sh | 10 +- enclave-runtime/Cargo.lock | 2 +- enclave-runtime/Cargo.toml | 2 +- enclave-runtime/src/rpc/common_api.rs | 15 +- enclave-runtime/src/test/direct_rpc_tests.rs | 2 +- .../src/test/state_getter_tests.rs | 10 +- enclave-runtime/src/test/tests_main.rs | 4 +- service/Cargo.toml | 2 +- 36 files changed, 599 insertions(+), 287 deletions(-) create mode 100644 app-libs/stf/src/guess_the_number.rs create mode 100644 cli/src/guess_the_number/commands/get_attempts.rs create mode 100644 cli/src/trusted_base_cli/commands/get_fingerprint.rs create mode 100644 cli/src/trusted_base_cli/commands/get_parentchains_info.rs diff --git a/Cargo.lock b/Cargo.lock index 2956faf6dc..232c42eb76 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2557,7 +2557,7 @@ dependencies = [ [[package]] name = "integritee-cli" -version = "0.14.1" +version = "0.14.2" dependencies = [ "array-bytes 6.1.0", "base58", @@ -2607,7 +2607,7 @@ dependencies = [ [[package]] name = "integritee-service" -version = "0.14.1" +version = "0.14.2" dependencies = [ "anyhow", "async-trait", diff --git a/app-libs/stf/src/getter.rs b/app-libs/stf/src/getter.rs index fc44f99f7f..a478067b57 100644 --- a/app-libs/stf/src/getter.rs +++ b/app-libs/stf/src/getter.rs @@ -16,7 +16,9 @@ */ use codec::{Decode, Encode}; -use ita_sgx_runtime::{Balances, GuessTheNumber, GuessType, System}; +use ita_sgx_runtime::{ + Balances, ParentchainIntegritee, ParentchainTargetA, ParentchainTargetB, System, +}; use itp_stf_interface::ExecuteGetter; use itp_stf_primitives::{ traits::GetterAuthorization, @@ -34,9 +36,13 @@ use ita_sgx_runtime::{AddressMapping, HashedAddressMapping}; #[cfg(feature = "evm")] use crate::evm_helpers::{get_evm_account, get_evm_account_codes, get_evm_account_storages}; -use crate::helpers::wrap_bytes; -use itp_sgx_runtime_primitives::types::{Balance, Moment}; +use crate::{ + guess_the_number::{GuessTheNumberPublicGetter, GuessTheNumberTrustedGetter}, + helpers::{shard_vault, wrap_bytes}, +}; +use itp_sgx_runtime_primitives::types::Moment; use itp_stf_primitives::traits::PoolTransactionValidation; +use itp_types::parentchain::{BlockNumber, Hash, ParentchainId}; #[cfg(feature = "evm")] use sp_core::{H160, H256}; use sp_runtime::transaction_validity::{ @@ -99,9 +105,8 @@ impl PoolTransactionValidation for Getter { pub enum PublicGetter { some_value = 0, total_issuance = 1, - guess_the_number_last_lucky_number = 50, - guess_the_number_last_winning_distance = 51, - guess_the_number_info = 52, + parentchains_info = 10, + guess_the_number(GuessTheNumberPublicGetter) = 50, } #[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] @@ -109,9 +114,8 @@ pub enum PublicGetter { #[repr(u8)] #[allow(clippy::unnecessary_cast)] pub enum TrustedGetter { - free_balance(AccountId) = 0, - reserved_balance(AccountId) = 1, - nonce(AccountId) = 2, + account_info(AccountId) = 0, + guess_the_number(GuessTheNumberTrustedGetter) = 50, #[cfg(feature = "evm")] evm_nonce(AccountId) = 90, #[cfg(feature = "evm")] @@ -123,9 +127,8 @@ pub enum TrustedGetter { impl TrustedGetter { pub fn sender_account(&self) -> &AccountId { match self { - TrustedGetter::free_balance(sender_account) => sender_account, - TrustedGetter::reserved_balance(sender_account) => sender_account, - TrustedGetter::nonce(sender_account) => sender_account, + TrustedGetter::account_info(sender_account) => sender_account, + TrustedGetter::guess_the_number(getter) => getter.sender_account(), #[cfg(feature = "evm")] TrustedGetter::evm_nonce(sender_account) => sender_account, #[cfg(feature = "evm")] @@ -184,26 +187,14 @@ impl ExecuteGetter for Getter { impl ExecuteGetter for TrustedGetterSigned { fn execute(self) -> Option> { match self.getter { - TrustedGetter::free_balance(who) => { - let info = System::account(&who); - debug!("TrustedGetter free_balance"); - debug!("AccountInfo for {} is {:?}", account_id_to_string(&who), info); - std::println!("⣿STF⣿ 🔍 TrustedGetter query: free balance for ⣿⣿⣿ is ⣿⣿⣿",); - Some(info.data.free.encode()) - }, - TrustedGetter::reserved_balance(who) => { + TrustedGetter::account_info(who) => { let info = System::account(&who); - debug!("TrustedGetter reserved_balance"); + debug!("TrustedGetter account_data"); debug!("AccountInfo for {} is {:?}", account_id_to_string(&who), info); - debug!("Account reserved balance is {}", info.data.reserved); - Some(info.data.reserved.encode()) - }, - TrustedGetter::nonce(who) => { - let nonce = System::account_nonce(&who); - debug!("TrustedGetter nonce"); - debug!("Account nonce is {}", nonce); - Some(nonce.encode()) + std::println!("⣿STF⣿ 🔍 TrustedGetter query: account info for ⣿⣿⣿ is ⣿⣿⣿",); + Some(info.encode()) }, + TrustedGetter::guess_the_number(getter) => getter.execute(), #[cfg(feature = "evm")] TrustedGetter::evm_nonce(who) => { let evm_account = get_evm_account(&who); @@ -237,7 +228,13 @@ impl ExecuteGetter for TrustedGetterSigned { } fn get_storage_hashes_to_update(self) -> Vec> { - Vec::new() + let mut key_hashes = Vec::new(); + match self.getter { + TrustedGetter::guess_the_number(getter) => + key_hashes.append(&mut getter.get_storage_hashes_to_update()), + _ => debug!("No storage updates needed..."), + }; + key_hashes } } @@ -246,56 +243,85 @@ impl ExecuteGetter for PublicGetter { match self { PublicGetter::some_value => Some(42u32.encode()), PublicGetter::total_issuance => Some(Balances::total_issuance().encode()), - PublicGetter::guess_the_number_last_lucky_number => { - // todo! return suiting value, not this one - GuessTheNumber::lucky_number().map(|guess| guess.encode()) - }, - PublicGetter::guess_the_number_last_winning_distance => { - // todo! return suiting value, not this one - GuessTheNumber::lucky_number().map(|guess| guess.encode()) - }, - PublicGetter::guess_the_number_info => { - let account = GuessTheNumber::get_pot_account(); - let winnings = GuessTheNumber::winnings(); - let next_round_timestamp = GuessTheNumber::next_round_timestamp(); - let maybe_last_winning_distance = GuessTheNumber::last_winning_distance(); - let last_winners = GuessTheNumber::last_winners(); - let maybe_last_lucky_number = GuessTheNumber::last_lucky_number(); - let info = System::account(&account); - debug!("TrustedGetter GuessTheNumber Pot Info"); - debug!("AccountInfo for pot {} is {:?}", account_id_to_string(&account), info); - std::println!("⣿STF⣿ 🔍 TrustedGetter query: guess-the-number pot info"); - Some( - GuessTheNumberInfo { - account, - balance: info.data.free, - winnings, - next_round_timestamp, - last_winners, - maybe_last_lucky_number, - maybe_last_winning_distance, - } - .encode(), - ) + PublicGetter::parentchains_info => { + let integritee = ParentchainInfo { + id: ParentchainId::Integritee, + genesis_hash: ParentchainIntegritee::parentchain_genesis_hash(), + block_number: ParentchainIntegritee::block_number(), + now: ParentchainIntegritee::now(), + creation_block_number: ParentchainIntegritee::creation_block_number(), + creation_timestamp: ParentchainIntegritee::creation_timestamp(), + }; + let target_a = ParentchainInfo { + id: ParentchainId::TargetA, + genesis_hash: ParentchainTargetA::parentchain_genesis_hash(), + block_number: ParentchainTargetA::block_number(), + now: ParentchainTargetA::now(), + creation_block_number: ParentchainTargetA::creation_block_number(), + creation_timestamp: ParentchainTargetA::creation_timestamp(), + }; + let target_b = ParentchainInfo { + id: ParentchainId::TargetB, + genesis_hash: ParentchainTargetB::parentchain_genesis_hash(), + block_number: ParentchainTargetB::block_number(), + now: ParentchainTargetB::now(), + creation_block_number: ParentchainTargetB::creation_block_number(), + creation_timestamp: ParentchainTargetB::creation_timestamp(), + }; + let parentchains_info = ParentchainsInfo { + integritee, + target_a, + target_b, + shielding_target: shard_vault() + .map(|v| v.1) + .unwrap_or(ParentchainId::Integritee), + }; + Some(parentchains_info.encode()) }, + PublicGetter::guess_the_number(getter) => getter.execute(), } } fn get_storage_hashes_to_update(self) -> Vec> { - Vec::new() + let mut key_hashes = Vec::new(); + match self { + Self::guess_the_number(getter) => + key_hashes.append(&mut getter.get_storage_hashes_to_update()), + _ => debug!("No storage updates needed..."), + }; + key_hashes } } + +/// General public information about the sync status of all parentchains #[derive(Encode, Decode, Debug, Clone, PartialEq, Eq)] -pub struct GuessTheNumberInfo { - pub account: AccountId, - pub balance: Balance, - pub winnings: Balance, - pub next_round_timestamp: Moment, - pub last_winners: Vec, - pub maybe_last_lucky_number: Option, - pub maybe_last_winning_distance: Option, +pub struct ParentchainsInfo { + /// info for the integritee network parentchain + pub integritee: ParentchainInfo, + /// info for the target A parentchain + pub target_a: ParentchainInfo, + /// info for the target B parentchain + pub target_b: ParentchainInfo, + /// which of the parentchains is used as a shielding target? + pub shielding_target: ParentchainId, } +/// General public information about the sync status of a parentchain +#[derive(Encode, Decode, Debug, Clone, PartialEq, Eq)] +pub struct ParentchainInfo { + /// the parentchain id for internal use + id: ParentchainId, + /// the genesis hash of the parentchain + genesis_hash: Option, + /// the last imported parentchain block number + block_number: Option, + /// the timestamp of the last imported parentchain block + now: Option, + /// the parentchain block number which preceded the creation of this shard + creation_block_number: Option, + /// the timestamp of creation for this shard + creation_timestamp: Option, +} mod tests { use super::*; diff --git a/app-libs/stf/src/guess_the_number.rs b/app-libs/stf/src/guess_the_number.rs new file mode 100644 index 0000000000..44fcb7d242 --- /dev/null +++ b/app-libs/stf/src/guess_the_number.rs @@ -0,0 +1,197 @@ +use crate::helpers::enclave_signer_account; +#[cfg(not(feature = "std"))] +use alloc::format; +use codec::{Decode, Encode}; +use frame_support::dispatch::UnfilteredDispatchable; +use ita_sgx_runtime::{GuessTheNumber, GuessType, Runtime, System}; +use itp_node_api::metadata::provider::AccessNodeMetadata; +use itp_node_api_metadata::NodeMetadataTrait; +use itp_sgx_runtime_primitives::types::{Balance, Moment}; +use itp_stf_interface::{ExecuteCall, ExecuteGetter}; +use itp_stf_primitives::error::StfError; +use itp_types::{parentchain::ParentchainCall, AccountId}; +use itp_utils::stringify::account_id_to_string; +use log::{debug, info, trace}; +use sp_runtime::MultiAddress; +use sp_std::{sync::Arc, vec::Vec}; + +/// General public information about the status of the guess-the-number game +#[derive(Encode, Decode, Debug, Clone, PartialEq, Eq)] +pub struct GuessTheNumberInfo { + /// the account of the pot used to payout winnings + pub account: itp_stf_primitives::types::AccountId, + /// the current balance of the pot + pub balance: Balance, + /// the amount which can be won every round + pub winnings: Balance, + /// the time when this round will end and the next round will start + pub next_round_timestamp: Moment, + /// the winners of the previous round + pub last_winners: Vec, + /// the lucky number which the enclave picked at random at the beginning of the last round + pub maybe_last_lucky_number: Option, + /// the distance of the best guess to the lucky_number + pub maybe_last_winning_distance: Option, +} + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] +#[allow(non_camel_case_types)] +#[repr(u8)] +#[allow(clippy::unnecessary_cast)] +pub enum GuessTheNumberTrustedCall { + set_winnings(AccountId, Balance) = 0, + push_by_one_day(AccountId) = 1, + guess(AccountId, GuessType) = 2, +} + +impl GuessTheNumberTrustedCall { + pub fn sender_account(&self) -> &AccountId { + match self { + Self::set_winnings(sender_account, ..) => sender_account, + Self::push_by_one_day(sender_account) => sender_account, + Self::guess(sender_account, ..) => sender_account, + } + } +} + +impl ExecuteCall for GuessTheNumberTrustedCall +where + NodeMetadataRepository: AccessNodeMetadata, + NodeMetadataRepository::MetadataType: NodeMetadataTrait, +{ + type Error = StfError; + + fn execute( + self, + _calls: &mut Vec, + _node_metadata_repo: Arc, + ) -> Result<(), Self::Error> { + match self { + Self::set_winnings(sender, winnings) => { + // authorization happens in pallet itself, we just pass authentication + let origin = ita_sgx_runtime::RuntimeOrigin::signed(sender); + std::println!("⣿STF⣿ guess-the-number set winnings to {}", winnings); + ita_sgx_runtime::GuessTheNumberCall::::set_winnings { winnings } + .dispatch_bypass_filter(origin) + .map_err(|e| { + Self::Error::Dispatch(format!( + "GuessTheNumber Set winnings error: {:?}", + e.error + )) + })?; + Ok::<(), Self::Error>(()) + }, + Self::push_by_one_day(sender) => { + // authorization happens in pallet itself, we just pass authentication + let origin = ita_sgx_runtime::RuntimeOrigin::signed(sender); + std::println!("⣿STF⣿ guess-the-number push by one day"); + ita_sgx_runtime::GuessTheNumberCall::::push_by_one_day {} + .dispatch_bypass_filter(origin) + .map_err(|e| { + Self::Error::Dispatch(format!( + "GuessTheNumber push by one day error: {:?}", + e.error + )) + })?; + Ok::<(), Self::Error>(()) + }, + Self::guess(sender, guess) => { + let origin = ita_sgx_runtime::RuntimeOrigin::signed(sender); + std::println!("⣿STF⣿ guess-the-number: someone is attempting a guess"); + // endow fee to enclave (self) + let fee_recipient: itp_stf_primitives::types::AccountId = enclave_signer_account(); + // fixme: apply fees through standard frame process and tune it + let fee = crate::STF_GUESS_FEE; + info!("guess fee {}", fee); + ita_sgx_runtime::BalancesCall::::transfer { + dest: MultiAddress::Id(fee_recipient), + value: fee, + } + .dispatch_bypass_filter(origin.clone()) + .map_err(|e| { + Self::Error::Dispatch(format!("GuessTheNumber fee error: {:?}", e.error)) + })?; + + ita_sgx_runtime::GuessTheNumberCall::::guess { guess } + .dispatch_bypass_filter(origin) + .map_err(|e| { + Self::Error::Dispatch(format!("GuessTheNumber guess error: {:?}", e.error)) + })?; + Ok::<(), Self::Error>(()) + }, + }?; + Ok(()) + } + + fn get_storage_hashes_to_update(self) -> Vec> { + debug!("No storage updates needed..."); + Vec::new() + } +} + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] +#[allow(non_camel_case_types)] +pub enum GuessTheNumberPublicGetter { + guess_the_number_info = 0, +} + +impl ExecuteGetter for GuessTheNumberPublicGetter { + fn execute(self) -> Option> { + match self { + Self::guess_the_number_info => { + let account = GuessTheNumber::get_pot_account(); + let winnings = GuessTheNumber::winnings(); + let next_round_timestamp = GuessTheNumber::next_round_timestamp(); + let maybe_last_winning_distance = GuessTheNumber::last_winning_distance(); + let last_winners = GuessTheNumber::last_winners(); + let maybe_last_lucky_number = GuessTheNumber::last_lucky_number(); + let info = System::account(&account); + trace!("TrustedGetter GuessTheNumber Pot Info"); + trace!("AccountInfo for pot {} is {:?}", account_id_to_string(&account), info); + std::println!("⣿STF⣿ 🔍 TrustedGetter query: guess-the-number pot info"); + Some( + GuessTheNumberInfo { + account, + balance: info.data.free, + winnings, + next_round_timestamp, + last_winners, + maybe_last_lucky_number, + maybe_last_winning_distance, + } + .encode(), + ) + }, + } + } + + fn get_storage_hashes_to_update(self) -> Vec> { + Vec::new() + } +} + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] +#[allow(non_camel_case_types)] +pub enum GuessTheNumberTrustedGetter { + attempts { origin: AccountId }, +} + +impl GuessTheNumberTrustedGetter { + pub fn sender_account(&self) -> &AccountId { + match self { + Self::attempts { origin, .. } => origin, + } + } +} + +impl ExecuteGetter for GuessTheNumberTrustedGetter { + fn execute(self) -> Option> { + match self { + Self::attempts { origin } => Some(GuessTheNumber::guess_attempts(&origin).encode()), + } + } + + fn get_storage_hashes_to_update(self) -> Vec> { + Vec::new() + } +} diff --git a/app-libs/stf/src/lib.rs b/app-libs/stf/src/lib.rs index f34c06ccfe..322bb82500 100644 --- a/app-libs/stf/src/lib.rs +++ b/app-libs/stf/src/lib.rs @@ -24,6 +24,7 @@ #![cfg_attr(all(not(target_env = "sgx"), not(feature = "std")), no_std)] #![cfg_attr(target_env = "sgx", feature(rustc_private))] +extern crate alloc; #[cfg(all(not(feature = "std"), feature = "sgx"))] extern crate sgx_tstd as std; @@ -34,6 +35,7 @@ pub use trusted_call::*; #[cfg(feature = "evm")] pub mod evm_helpers; pub mod getter; +pub mod guess_the_number; pub mod hash; pub mod helpers; pub mod stf_sgx; diff --git a/app-libs/stf/src/trusted_call.rs b/app-libs/stf/src/trusted_call.rs index 85cc293355..f6c58f3940 100644 --- a/app-libs/stf/src/trusted_call.rs +++ b/app-libs/stf/src/trusted_call.rs @@ -24,6 +24,7 @@ use std::vec::Vec; #[cfg(feature = "evm")] use crate::evm_helpers::{create_code_hash, evm_create2_address, evm_create_address}; use crate::{ + guess_the_number::GuessTheNumberTrustedCall, helpers::{enclave_signer_account, ensure_enclave_signer_account, shard_vault, wrap_bytes}, Getter, }; @@ -33,8 +34,8 @@ use frame_support::{ensure, traits::UnfilteredDispatchable}; use ita_sgx_runtime::{AddressMapping, HashedAddressMapping}; pub use ita_sgx_runtime::{Balance, Index}; use ita_sgx_runtime::{ - GuessType, ParentchainInstanceIntegritee, ParentchainInstanceTargetA, - ParentchainInstanceTargetB, ParentchainIntegritee, Runtime, System, + ParentchainInstanceIntegritee, ParentchainInstanceTargetA, ParentchainInstanceTargetB, + ParentchainIntegritee, Runtime, System, }; use itp_node_api::metadata::{provider::AccessNodeMetadata, NodeMetadataTrait}; use itp_node_api_metadata::{ @@ -71,9 +72,7 @@ pub enum TrustedCall { balance_transfer(AccountId, AccountId, Balance) = 2, balance_unshield(AccountId, AccountId, Balance, ShardIdentifier) = 3, // (AccountIncognito, BeneficiaryPublicAccount, Amount, Shard) balance_shield(AccountId, AccountId, Balance, ParentchainId) = 4, // (Root, AccountIncognito, Amount, origin parentchain) - guess_the_number_set_winnings(AccountId, Balance) = 50, - guess_the_number_push_by_one_day(AccountId) = 51, - guess_the_number(AccountId, GuessType) = 52, + guess_the_number(GuessTheNumberTrustedCall) = 50, #[cfg(feature = "evm")] evm_withdraw(AccountId, H160, Balance) = 90, // (Origin, Address EVM Account, Value) // (Origin, Source, Target, Input, Value, Gas limit, Max fee per gas, Max priority fee per gas, Nonce, Access list) @@ -139,9 +138,7 @@ impl TrustedCall { Self::evm_create(sender_account, ..) => sender_account, #[cfg(feature = "evm")] Self::evm_create2(sender_account, ..) => sender_account, - Self::guess_the_number_set_winnings(sender_account, ..) => sender_account, - Self::guess_the_number_push_by_one_day(sender_account) => sender_account, - Self::guess_the_number(sender_account, ..) => sender_account, + Self::guess_the_number(call) => call.sender_account(), } } } @@ -577,72 +574,19 @@ where info!("Trying to create evm contract with address {:?}", contract_address); Ok(()) }, - TrustedCall::guess_the_number_set_winnings(sender, winnings) => { - // authorization happens in pallet itself, we just pass authentication - let origin = ita_sgx_runtime::RuntimeOrigin::signed(sender); - std::println!("⣿STF⣿ guess-the-number set winnings to {}", winnings); - ita_sgx_runtime::GuessTheNumberCall::::set_winnings { winnings } - .dispatch_bypass_filter(origin) - .map_err(|e| { - Self::Error::Dispatch(format!( - "GuessTheNumber Set winnings error: {:?}", - e.error - )) - })?; - Ok::<(), Self::Error>(()) - }, - TrustedCall::guess_the_number_push_by_one_day(sender) => { - // authorization happens in pallet itself, we just pass authentication - let origin = ita_sgx_runtime::RuntimeOrigin::signed(sender); - std::println!("⣿STF⣿ guess-the-number push by one day"); - ita_sgx_runtime::GuessTheNumberCall::::push_by_one_day {} - .dispatch_bypass_filter(origin) - .map_err(|e| { - Self::Error::Dispatch(format!( - "GuessTheNumber push by one day error: {:?}", - e.error - )) - })?; - Ok::<(), Self::Error>(()) - }, - TrustedCall::guess_the_number(sender, guess) => { - let origin = ita_sgx_runtime::RuntimeOrigin::signed(sender); - std::println!("⣿STF⣿ guess-the-number: someone is attempting a guess"); - // endow fee to enclave (self) - let fee_recipient: AccountId = enclave_signer_account(); - // fixme: apply fees through standard frame process and tune it - let fee = crate::STF_GUESS_FEE; - info!("guess fee {}", fee); - ita_sgx_runtime::BalancesCall::::transfer { - dest: MultiAddress::Id(fee_recipient), - value: fee, - } - .dispatch_bypass_filter(origin.clone()) - .map_err(|e| { - Self::Error::Dispatch(format!("GuessTheNumber fee error: {:?}", e.error)) - })?; - - ita_sgx_runtime::GuessTheNumberCall::::guess { guess } - .dispatch_bypass_filter(origin) - .map_err(|e| { - Self::Error::Dispatch(format!("GuessTheNumber guess error: {:?}", e.error)) - })?; - Ok::<(), Self::Error>(()) - }, + TrustedCall::guess_the_number(call) => call.execute(calls, node_metadata_repo), }?; Ok(()) } fn get_storage_hashes_to_update(self) -> Vec> { - let key_hashes = Vec::new(); + let mut key_hashes = Vec::new(); match self.call { TrustedCall::noop(..) => debug!("No storage updates needed..."), - #[cfg(any(feature = "test", test))] - TrustedCall::balance_set_balance(..) => debug!("No storage updates needed..."), // ROOT call to set some account balance to an arbitrary number - TrustedCall::balance_transfer(..) => debug!("No storage updates needed..."), - TrustedCall::balance_unshield(..) => debug!("No storage updates needed..."), - TrustedCall::balance_shield(..) => debug!("No storage updates needed..."), - TrustedCall::timestamp_set(..) => debug!("No storage updates needed..."), + TrustedCall::guess_the_number(call) => + key_hashes.append(&mut >::get_storage_hashes_to_update(call)), _ => debug!("No storage updates needed..."), }; key_hashes diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 4faebd4da1..b30db1f192 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "integritee-cli" -version = "0.14.1" +version = "0.14.2" authors = ["Integritee AG "] edition = "2021" diff --git a/cli/benchmark.sh b/cli/benchmark.sh index d0ad5a6465..ecd6b79623 100755 --- a/cli/benchmark.sh +++ b/cli/benchmark.sh @@ -1,10 +1,7 @@ #!/bin/bash -while getopts ":m:p:A:u:V:C:" opt; do +while getopts ":p:A:u:V:C:" opt; do case $opt in - m) - READMRENCLAVE=$OPTARG - ;; p) NPORT=$OPTARG ;; @@ -40,16 +37,9 @@ echo "Using trusted-worker uri ${WORKER1URL}:${WORKER1PORT}" CLIENTWORKER1="${CLIENT_BIN} -p ${NPORT} -P ${WORKER1PORT} -u ${NODEURL} -U ${WORKER1URL}" -if [ "$READMRENCLAVE" = "file" ] -then - read -r MRENCLAVE <<< "$(cat ~/mrenclave.b58)" - echo "Reading MRENCLAVE from file: ${MRENCLAVE}" -else - # this will always take the first MRENCLAVE found in the registry !! - read -r MRENCLAVE <<< "$($CLIENTWORKER1 list-workers | awk '/ MRENCLAVE: / { print $2; exit }')" - echo "Reading MRENCLAVE from worker list: ${MRENCLAVE}" -fi -[[ -z $MRENCLAVE ]] && { echo "MRENCLAVE is empty. cannot continue" ; exit 1; } +# we simply believe the enclave here without verifying the teerex RA +MRENCLAVE="$($CLIENTWORKER1 trusted get-fingerprint)" +echo "Using MRENCLAVE: ${MRENCLAVE}" # needed when many clients are started ulimit -S -n 4096 diff --git a/cli/demo_direct_call.sh b/cli/demo_direct_call.sh index 63f48b18a6..29357ac811 100755 --- a/cli/demo_direct_call.sh +++ b/cli/demo_direct_call.sh @@ -16,19 +16,16 @@ # then run this script # usage: -# demo_direct_call.sh -p -P -t -m file +# demo_direct_call.sh -p -P -t # # TEST_BALANCE_RUN is either "first" or "second" -# if -m file is set, the mrenclave will be read from file -while getopts ":m:p:P:t:u:V:C:" opt; do + +while getopts ":p:P:t:u:V:C:" opt; do case $opt in t) TEST=$OPTARG ;; - m) - READ_MRENCLAVE=$OPTARG - ;; p) INTEGRITEE_RPC_PORT=$OPTARG ;; @@ -70,7 +67,9 @@ AMOUNTSHIELD=50000000000 AMOUNTTRANSFER=40000000000 CLIENT="${CLIENT_BIN} -p ${INTEGRITEE_RPC_PORT} -P ${WORKER_1_PORT} -u ${INTEGRITEE_RPC_URL} -U ${WORKER_1_URL}" -read -r MRENCLAVE <<< "$($CLIENT list-workers | awk '/ MRENCLAVE: / { print $2; exit }')" +# we simply believe the enclave here without verifying the teerex RA +MRENCLAVE="$($CLIENT trusted get-fingerprint)" +echo "Using MRENCLAVE: ${MRENCLAVE}" VAULT=$(${CLIENT} trusted get-shard-vault) echo " Vault account = ${VAULT}" diff --git a/cli/demo_shielding_unshielding.sh b/cli/demo_shielding_unshielding.sh index 549d83a87f..97c945a524 100755 --- a/cli/demo_shielding_unshielding.sh +++ b/cli/demo_shielding_unshielding.sh @@ -19,19 +19,16 @@ set -e # then run this script # usage: -# demo_shielding_unshielding.sh -p -P -t -m file +# demo_shielding_unshielding.sh -p -P -t # # TEST_BALANCE_RUN is either "first" or "second" -# if -m file is set, the mrenclave will be read from file -while getopts ":m:p:P:t:u:V:C:" opt; do + +while getopts ":p:P:t:u:V:C:" opt; do case $opt in t) TEST=$OPTARG ;; - m) - READ_MRENCLAVE=$OPTARG - ;; p) INTEGRITEE_RPC_PORT=$OPTARG ;; @@ -135,16 +132,9 @@ echo "* Query on-chain enclave registry:" ${CLIENT} list-workers echo "" -if [ "$READ_MRENCLAVE" = "file" ] -then - read MRENCLAVE <<< $(cat ~/mrenclave.b58) - echo "Reading MRENCLAVE from file: ${MRENCLAVE}" -else - # this will always take the first MRENCLAVE found in the registry !! - read MRENCLAVE <<< $($CLIENT list-workers | awk '/ MRENCLAVE: / { print $2; exit }') - echo "Reading MRENCLAVE from worker list: ${MRENCLAVE}" -fi -[[ -z $MRENCLAVE ]] && { echo "MRENCLAVE is empty. cannot continue" ; exit 1; } +# we simply believe the enclave here without verifying the teerex RA +MRENCLAVE="$($CLIENT trusted get-fingerprint)" +echo "Using MRENCLAVE: ${MRENCLAVE}" echo "* Create a new incognito account for Alice" ICGACCOUNTALICE=//AliceIncognito diff --git a/cli/demo_shielding_unshielding_using_shard_vault.sh b/cli/demo_shielding_unshielding_using_shard_vault.sh index d6a0ae9f0b..b5997f0ed4 100755 --- a/cli/demo_shielding_unshielding_using_shard_vault.sh +++ b/cli/demo_shielding_unshielding_using_shard_vault.sh @@ -19,19 +19,16 @@ set -e # then run this script # usage: -# demo_shielding_unshielding.sh -p -P -t -m file +# demo_shielding_unshielding.sh -p -P -t # # TEST_BALANCE_RUN is either "first" or "second" -# if -m file is set, the mrenclave will be read from file -while getopts ":m:p:P:t:u:V:C:" opt; do + +while getopts ":p:P:t:u:V:C:" opt; do case $opt in t) TEST=$OPTARG ;; - m) - READ_MRENCLAVE=$OPTARG - ;; p) INTEGRITEE_RPC_PORT=$OPTARG ;; @@ -154,17 +151,9 @@ echo "* Query on-chain enclave registry:" ${CLIENT} list-workers echo "" -if [ "$READ_MRENCLAVE" = "file" ] -then - read MRENCLAVE <<< $(cat ~/mrenclave.b58) - echo "Reading MRENCLAVE from file: ${MRENCLAVE}" -else - # this will always take the first MRENCLAVE found in the registry !! - read MRENCLAVE <<< $($CLIENT list-workers | awk '/ MRENCLAVE: / { print $2; exit }') - echo "Reading MRENCLAVE from worker list: ${MRENCLAVE}" -fi -[[ -z $MRENCLAVE ]] && { echo "MRENCLAVE is empty. cannot continue" ; exit 1; } - +# we simply believe the enclave here without verifying the teerex RA +MRENCLAVE="$($CLIENT trusted get-fingerprint)" +echo "Using MRENCLAVE: ${MRENCLAVE}" echo "* Create a new incognito account for Bob" ICGACCOUNTBOB=$(${CLIENT} trusted --mrenclave ${MRENCLAVE} new-account) diff --git a/cli/demo_shielding_unshielding_using_shard_vault_on_target_a.sh b/cli/demo_shielding_unshielding_using_shard_vault_on_target_a.sh index b3b978adc7..9d35558373 100755 --- a/cli/demo_shielding_unshielding_using_shard_vault_on_target_a.sh +++ b/cli/demo_shielding_unshielding_using_shard_vault_on_target_a.sh @@ -19,19 +19,16 @@ set -e # then run this script # usage: -# demo_shielding_unshielding.sh -p -P -t -m file +# demo_shielding_unshielding.sh -p -P -t # # TEST_BALANCE_RUN is either "first" or "second" -# if -m file is set, the mrenclave will be read from file -while getopts ":m:p:P:t:u:V:C:a:A:" opt; do + +while getopts ":p:P:t:u:V:C:a:A:" opt; do case $opt in t) TEST=$OPTARG ;; - m) - READ_MRENCLAVE=$OPTARG - ;; p) INTEGRITEE_RPC_PORT=$OPTARG ;; @@ -166,16 +163,9 @@ echo "* Query on-chain enclave registry:" ${CLIENT} list-workers echo "" -if [ "$READ_MRENCLAVE" = "file" ] -then - read MRENCLAVE <<< $(cat ~/mrenclave.b58) - echo "Reading MRENCLAVE from file: ${MRENCLAVE}" -else - # this will always take the first MRENCLAVE found in the registry !! - read MRENCLAVE <<< $($CLIENT list-workers | awk '/ MRENCLAVE: / { print $2; exit }') - echo "Reading MRENCLAVE from worker list: ${MRENCLAVE}" -fi -[[ -z $MRENCLAVE ]] && { echo "MRENCLAVE is empty. cannot continue" ; exit 1; } +# we simply believe the enclave here without verifying the teerex RA +MRENCLAVE="$($CLIENT trusted get-fingerprint)" +echo "Using MRENCLAVE: ${MRENCLAVE}" echo "* Create a new incognito account for Bob" diff --git a/cli/demo_sidechain.sh b/cli/demo_sidechain.sh index abd92800bc..4f7d7f4ce7 100755 --- a/cli/demo_sidechain.sh +++ b/cli/demo_sidechain.sh @@ -20,16 +20,13 @@ # # usage: # export RUST_LOG_LOG=integritee-cli=info,ita_stf=info -# demo_sidechain.sh -p -A -B -m file +# demo_sidechain.sh -p -A -B # # TEST_BALANCE_RUN is either "first" or "second" -# if -m file is set, the mrenclave will be read from file. +. -while getopts ":m:p:A:B:t:u:W:V:C:" opt; do +while getopts ":p:A:B:t:u:W:V:C:" opt; do case $opt in - m) - READ_MRENCLAVE=$OPTARG - ;; p) INTEGRITEE_RPC_PORT=$OPTARG ;; @@ -85,16 +82,9 @@ AMOUNTTRANSFER=$((2 * UNIT)) CLIENTWORKER1="${CLIENT_BIN} -p ${INTEGRITEE_RPC_PORT} -P ${WORKER_1_PORT} -u ${INTEGRITEE_RPC_URL} -U ${WORKER_1_URL}" CLIENTWORKER2="${CLIENT_BIN} -p ${INTEGRITEE_RPC_PORT} -P ${WORKER_2_PORT} -u ${INTEGRITEE_RPC_URL} -U ${WORKER_2_URL}" -if [ "$READ_MRENCLAVE" = "file" ] -then - read MRENCLAVE <<< $(cat ~/mrenclave.b58) - echo "Reading MRENCLAVE from file: ${MRENCLAVE}" -else - # This will always take the first MRENCLAVE found in the registry !! - read MRENCLAVE <<< $($CLIENTWORKER1 list-workers | awk '/ MRENCLAVE: / { print $2; exit }') - echo "Reading MRENCLAVE from worker list: ${MRENCLAVE}" -fi -[[ -z $MRENCLAVE ]] && { echo "MRENCLAVE is empty. cannot continue" ; exit 1; } +# we simply believe the enclave here without verifying the teerex RA +MRENCLAVE="$($CLIENTWORKER1 trusted get-fingerprint)" +echo "Using MRENCLAVE: ${MRENCLAVE}" VAULT=$(${CLIENTWORKER1} trusted get-shard-vault) echo " Vault account = ${VAULT}" diff --git a/cli/demo_smart_contract.sh b/cli/demo_smart_contract.sh index e41729c12f..1da77c919a 100755 --- a/cli/demo_smart_contract.sh +++ b/cli/demo_smart_contract.sh @@ -62,10 +62,9 @@ echo "Using trusted-worker uri ${WORKER_URL}:${WORKER_PORT}" CLIENTWORKER="${CLIENT_BIN} -p ${INTEGRITEE_RPC_PORT} -P ${WORKER_PORT} -u ${INTEGRITEE_RPC_URL} -U ${WORKER_URL}" - -# this will always take the first MRENCLAVE found in the registry !! -read -r MRENCLAVE <<< "$($CLIENTWORKER list-workers | awk '/ MRENCLAVE: / { print $2; exit }')" -echo "Reading MRENCLAVE from worker list: ${MRENCLAVE}" +# we simply believe the enclave here without verifying the teerex RA +MRENCLAVE="$($CLIENTWORKER trusted get-fingerprint)" +echo "Using MRENCLAVE: ${MRENCLAVE}" ACCOUNTALICE=//Alice diff --git a/cli/src/base_cli/mod.rs b/cli/src/base_cli/mod.rs index 1f400a543d..7b3b36577f 100644 --- a/cli/src/base_cli/mod.rs +++ b/cli/src/base_cli/mod.rs @@ -158,5 +158,5 @@ fn list_workers(cli: &Cli) -> CliResult { enclave.fingerprint().0.to_base58() }) .collect(); - Ok(CliResultOk::MrEnclaveBase58 { mr_enclaves: fingerprints }) + Ok(CliResultOk::FingerprintBase58 { fingerprints }) } diff --git a/cli/src/benchmark/mod.rs b/cli/src/benchmark/mod.rs index bce9ad405c..550bc18cc3 100644 --- a/cli/src/benchmark/mod.rs +++ b/cli/src/benchmark/mod.rs @@ -32,7 +32,7 @@ use itp_stf_primitives::{ types::{KeyPair, TrustedOperation}, }; use itp_types::{ - Balance, ShardIdentifier, TrustedOperationStatus, + AccountInfo, Balance, ShardIdentifier, TrustedOperationStatus, TrustedOperationStatus::{InSidechainBlock, Submitted}, }; use log::*; @@ -261,7 +261,7 @@ fn get_balance( direct_client: &DirectClient, ) -> Option { let getter = Getter::trusted( - TrustedGetter::free_balance(account.public().into()) + TrustedGetter::account_info(account.public().into()) .sign(&KeyPair::Sr25519(Box::new(account.clone()))), ); @@ -281,12 +281,13 @@ fn get_nonce( direct_client: &DirectClient, ) -> Index { let getter = Getter::trusted( - TrustedGetter::nonce(account.public().into()) + TrustedGetter::account_info(account.public().into()) .sign(&KeyPair::Sr25519(Box::new(account.clone()))), ); let getter_start_timer = Instant::now(); - let nonce = get_state::(direct_client, shard, &getter).ok().unwrap_or_default(); + let info = get_state::(direct_client, shard, &getter); + let nonce = info.map(|i| i.nonce).ok().unwrap_or_default(); let getter_execution_time = getter_start_timer.elapsed().as_millis(); info!("Nonce getter execution took {} ms", getter_execution_time,); debug!("Retrieved {:?} nonce for {:?}", nonce, account.public()); @@ -370,8 +371,8 @@ fn is_sidechain_block(s: TrustedOperationStatus) -> bool { fn decode_balance(maybe_encoded_balance: Option>) -> Option { maybe_encoded_balance.and_then(|encoded_balance| { - if let Ok(vd) = Balance::decode(&mut encoded_balance.as_slice()) { - Some(vd) + if let Ok(vd) = AccountInfo::decode(&mut encoded_balance.as_slice()) { + Some(vd.data.free) } else { warn!("Could not decode balance. maybe hasn't been set? {:x?}", encoded_balance); None diff --git a/cli/src/guess_the_number/commands/get_attempts.rs b/cli/src/guess_the_number/commands/get_attempts.rs new file mode 100644 index 0000000000..b98bf1c1fa --- /dev/null +++ b/cli/src/guess_the_number/commands/get_attempts.rs @@ -0,0 +1,46 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ +use crate::{ + trusted_cli::TrustedCli, trusted_command_utils::get_pair_from_str, + trusted_operation::perform_trusted_operation, Cli, CliResult, CliResultOk, +}; +use ita_stf::{ + guess_the_number::GuessTheNumberTrustedGetter, Getter, TrustedCallSigned, TrustedGetter, +}; +use itp_stf_primitives::types::{KeyPair, TrustedOperation}; +use sp_core::Pair; + +#[derive(Parser)] +pub struct GetAttemptsCommand { + /// AccountId in ss58check format, mnemonic or hex seed + account: String, +} + +impl GetAttemptsCommand { + pub(crate) fn run(&self, cli: &Cli, trusted_args: &TrustedCli) -> CliResult { + let who = get_pair_from_str(trusted_args, &self.account); + let top = TrustedOperation::::get(Getter::trusted( + TrustedGetter::guess_the_number(GuessTheNumberTrustedGetter::attempts { + origin: who.public().into(), + }) + .sign(&KeyPair::Sr25519(Box::new(who))), + )); + let attempts = perform_trusted_operation::(cli, trusted_args, &top).unwrap(); + println!("{}", attempts); + Ok(CliResultOk::GuessAttempts { value: attempts }) + } +} diff --git a/cli/src/guess_the_number/commands/get_info.rs b/cli/src/guess_the_number/commands/get_info.rs index ee905ccf7a..a37e9b78f3 100644 --- a/cli/src/guess_the_number/commands/get_info.rs +++ b/cli/src/guess_the_number/commands/get_info.rs @@ -18,7 +18,10 @@ use crate::{ trusted_cli::TrustedCli, trusted_operation::perform_trusted_operation, Cli, CliResult, CliResultOk, }; -use ita_stf::{Getter, GuessTheNumberInfo, PublicGetter, TrustedCallSigned}; +use ita_stf::{ + guess_the_number::{GuessTheNumberInfo, GuessTheNumberPublicGetter}, + Getter, PublicGetter, TrustedCallSigned, +}; use itp_stf_primitives::types::TrustedOperation; use sp_core::crypto::Ss58Codec; @@ -28,7 +31,7 @@ pub struct GetInfoCommand {} impl GetInfoCommand { pub(crate) fn run(&self, cli: &Cli, trusted_args: &TrustedCli) -> CliResult { let top = TrustedOperation::::get(Getter::public( - PublicGetter::guess_the_number_info, + PublicGetter::guess_the_number(GuessTheNumberPublicGetter::guess_the_number_info), )); let info: GuessTheNumberInfo = perform_trusted_operation(cli, trusted_args, &top).unwrap(); println!("{:?}", info); diff --git a/cli/src/guess_the_number/commands/guess.rs b/cli/src/guess_the_number/commands/guess.rs index 53268dbd3f..932d1786e5 100644 --- a/cli/src/guess_the_number/commands/guess.rs +++ b/cli/src/guess_the_number/commands/guess.rs @@ -23,7 +23,9 @@ use crate::{ Cli, CliResult, CliResultOk, }; -use ita_stf::{Getter, Index, TrustedCall, TrustedCallSigned}; +use ita_stf::{ + guess_the_number::GuessTheNumberTrustedCall, Getter, Index, TrustedCall, TrustedCallSigned, +}; use itp_stf_primitives::{ traits::TrustedCallSigning, types::{KeyPair, TrustedOperation}, @@ -48,10 +50,11 @@ impl GuessCommand { let (mrenclave, shard) = get_identifiers(trusted_args); let nonce = get_layer_two_nonce!(signer, cli, trusted_args); - let top: TrustedOperation = - TrustedCall::guess_the_number(signer.public().into(), self.guess) - .sign(&KeyPair::Sr25519(Box::new(signer)), nonce, &mrenclave, &shard) - .into_trusted_operation(trusted_args.direct); + let top: TrustedOperation = TrustedCall::guess_the_number( + GuessTheNumberTrustedCall::guess(signer.public().into(), self.guess), + ) + .sign(&KeyPair::Sr25519(Box::new(signer)), nonce, &mrenclave, &shard) + .into_trusted_operation(trusted_args.direct); Ok(perform_trusted_operation::<()>(cli, trusted_args, &top).map(|_| CliResultOk::None)?) } } diff --git a/cli/src/guess_the_number/commands/mod.rs b/cli/src/guess_the_number/commands/mod.rs index a7616bb61f..83ea322603 100644 --- a/cli/src/guess_the_number/commands/mod.rs +++ b/cli/src/guess_the_number/commands/mod.rs @@ -1,3 +1,4 @@ +pub mod get_attempts; pub mod get_info; pub mod guess; pub mod push_by_one_day; diff --git a/cli/src/guess_the_number/commands/push_by_one_day.rs b/cli/src/guess_the_number/commands/push_by_one_day.rs index 3bcdade0e2..1a1cfb2358 100644 --- a/cli/src/guess_the_number/commands/push_by_one_day.rs +++ b/cli/src/guess_the_number/commands/push_by_one_day.rs @@ -23,7 +23,9 @@ use crate::{ Cli, CliResult, CliResultOk, }; -use ita_stf::{Getter, Index, TrustedCall, TrustedCallSigned}; +use ita_stf::{ + guess_the_number::GuessTheNumberTrustedCall, Getter, Index, TrustedCall, TrustedCallSigned, +}; use itp_stf_primitives::{ traits::TrustedCallSigning, types::{KeyPair, TrustedOperation}, @@ -46,10 +48,11 @@ impl PushByOneDayCommand { let (mrenclave, shard) = get_identifiers(trusted_args); let nonce = get_layer_two_nonce!(signer, cli, trusted_args); - let top: TrustedOperation = - TrustedCall::guess_the_number_push_by_one_day(signer.public().into()) - .sign(&KeyPair::Sr25519(Box::new(signer)), nonce, &mrenclave, &shard) - .into_trusted_operation(trusted_args.direct); + let top: TrustedOperation = TrustedCall::guess_the_number( + GuessTheNumberTrustedCall::push_by_one_day(signer.public().into()), + ) + .sign(&KeyPair::Sr25519(Box::new(signer)), nonce, &mrenclave, &shard) + .into_trusted_operation(trusted_args.direct); Ok(perform_trusted_operation::<()>(cli, trusted_args, &top).map(|_| CliResultOk::None)?) } } diff --git a/cli/src/guess_the_number/commands/set_winnings.rs b/cli/src/guess_the_number/commands/set_winnings.rs index a31b553710..beab2475a2 100644 --- a/cli/src/guess_the_number/commands/set_winnings.rs +++ b/cli/src/guess_the_number/commands/set_winnings.rs @@ -23,7 +23,9 @@ use crate::{ Cli, CliResult, CliResultOk, }; use ita_parentchain_interface::integritee::Balance; -use ita_stf::{Getter, Index, TrustedCall, TrustedCallSigned}; +use ita_stf::{ + guess_the_number::GuessTheNumberTrustedCall, Getter, Index, TrustedCall, TrustedCallSigned, +}; use itp_stf_primitives::{ traits::TrustedCallSigning, types::{KeyPair, TrustedOperation}, @@ -52,10 +54,11 @@ impl SetWinningsCommand { let (mrenclave, shard) = get_identifiers(trusted_args); let nonce = get_layer_two_nonce!(signer, cli, trusted_args); - let top: TrustedOperation = - TrustedCall::guess_the_number_set_winnings(signer.public().into(), self.winnings) - .sign(&KeyPair::Sr25519(Box::new(signer)), nonce, &mrenclave, &shard) - .into_trusted_operation(trusted_args.direct); + let top: TrustedOperation = TrustedCall::guess_the_number( + GuessTheNumberTrustedCall::set_winnings(signer.public().into(), self.winnings), + ) + .sign(&KeyPair::Sr25519(Box::new(signer)), nonce, &mrenclave, &shard) + .into_trusted_operation(trusted_args.direct); Ok(perform_trusted_operation::<()>(cli, trusted_args, &top).map(|_| CliResultOk::None)?) } } diff --git a/cli/src/guess_the_number/mod.rs b/cli/src/guess_the_number/mod.rs index 73b5c59bfe..84b1b21a23 100644 --- a/cli/src/guess_the_number/mod.rs +++ b/cli/src/guess_the_number/mod.rs @@ -15,7 +15,10 @@ */ -use crate::{trusted_cli::TrustedCli, Cli, CliResult}; +use crate::{ + guess_the_number::commands::get_attempts::GetAttemptsCommand, trusted_cli::TrustedCli, Cli, + CliResult, +}; use commands::{ get_info::GetInfoCommand, guess::GuessCommand, push_by_one_day::PushByOneDayCommand, set_winnings::SetWinningsCommand, @@ -33,6 +36,8 @@ pub enum GuessTheNumberCommand { PushByOneDay(PushByOneDayCommand), /// submit a guess as a player Guess(GuessCommand), + /// how many times a player has already submitted a guess this round + GetAttempts(GetAttemptsCommand), } impl GuessTheNumberCommand { @@ -42,6 +47,7 @@ impl GuessTheNumberCommand { GuessTheNumberCommand::SetWinnings(cmd) => cmd.run(cli, trusted_cli), GuessTheNumberCommand::PushByOneDay(cmd) => cmd.run(cli, trusted_cli), GuessTheNumberCommand::Guess(cmd) => cmd.run(cli, trusted_cli), + GuessTheNumberCommand::GetAttempts(cmd) => cmd.run(cli, trusted_cli), } } } diff --git a/cli/src/lib.rs b/cli/src/lib.rs index 0e5d6121d0..b02e3baa7e 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -46,7 +46,7 @@ pub mod commands; use crate::commands::Commands; use clap::Parser; -use ita_stf::GuessTheNumberInfo; +use ita_stf::{guess_the_number::GuessTheNumberInfo, ParentchainsInfo}; use itp_node_api::api_client::Metadata; use sp_application_crypto::KeyTypeId; use sp_core::{H160, H256}; @@ -97,8 +97,8 @@ pub enum CliResultOk { Balance { balance: u128, }, - MrEnclaveBase58 { - mr_enclaves: Vec, + FingerprintBase58 { + fingerprints: Vec, }, Metadata { metadata: Metadata, @@ -113,6 +113,12 @@ pub enum CliResultOk { U32 { value: u32, }, + ParentchainsInfo { + info: ParentchainsInfo, + }, + GuessAttempts { + value: u8, + }, GuessTheNumberPotInfo { info: GuessTheNumberInfo, }, diff --git a/cli/src/trusted_base_cli/commands/get_fingerprint.rs b/cli/src/trusted_base_cli/commands/get_fingerprint.rs new file mode 100644 index 0000000000..d8a6ac3471 --- /dev/null +++ b/cli/src/trusted_base_cli/commands/get_fingerprint.rs @@ -0,0 +1,64 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +use crate::{ + command_utils::get_worker_api_direct, trusted_cli::TrustedCli, Cli, CliError, CliResult, + CliResultOk, +}; +use base58::ToBase58; +use codec::{Decode, Encode}; +use itc_rpc_client::direct_client::DirectApi; +use itp_rpc::{RpcRequest, RpcResponse, RpcReturnValue}; +use itp_types::{DirectRequestStatus, EnclaveFingerprint}; +use itp_utils::FromHexPrefixed; +use log::*; + +#[derive(Parser)] +pub struct GetFingerprintCommand {} + +impl GetFingerprintCommand { + pub(crate) fn run(&self, cli: &Cli, _trusted_args: &TrustedCli) -> CliResult { + let direct_api = get_worker_api_direct(cli); + let rpc_method = "author_getFingerprint".to_owned(); + let jsonrpc_call: String = RpcRequest::compose_jsonrpc_call(rpc_method, vec![]).unwrap(); + let rpc_response_str = direct_api.get(&jsonrpc_call).unwrap(); + // Decode RPC response. + let rpc_response: RpcResponse = serde_json::from_str(&rpc_response_str) + .map_err(|err| CliError::WorkerRpcApi { msg: err.to_string() })?; + let rpc_return_value = RpcReturnValue::from_hex(&rpc_response.result) + // Replace with `inspect_err` once it's stable. + .map_err(|err| { + error!("Failed to decode RpcReturnValue: {:?}", err); + CliError::WorkerRpcApi { msg: "failed to decode RpcReturnValue".to_string() } + })?; + + if rpc_return_value.status == DirectRequestStatus::Error { + error!("{}", String::decode(&mut rpc_return_value.value.as_slice()).unwrap()); + return Err(CliError::WorkerRpcApi { msg: "rpc error".to_string() }) + } + + let fingerprint = EnclaveFingerprint::decode(&mut rpc_return_value.value.as_slice()) + // Replace with `inspect_err` once it's stable. + .map_err(|err| { + error!("Failed to decode fingerprint: {:?}", err); + CliError::WorkerRpcApi { msg: err.to_string() } + })?; + let fingerprint_b58 = fingerprint.encode().to_base58(); + println!("{}", fingerprint_b58); + Ok(CliResultOk::FingerprintBase58 { fingerprints: vec![fingerprint_b58] }) + } +} diff --git a/cli/src/trusted_base_cli/commands/get_parentchains_info.rs b/cli/src/trusted_base_cli/commands/get_parentchains_info.rs new file mode 100644 index 0000000000..fa919f8382 --- /dev/null +++ b/cli/src/trusted_base_cli/commands/get_parentchains_info.rs @@ -0,0 +1,36 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ +use crate::{ + trusted_cli::TrustedCli, trusted_operation::perform_trusted_operation, Cli, CliResult, + CliResultOk, +}; +use ita_stf::{Getter, ParentchainsInfo, PublicGetter, TrustedCallSigned}; +use itp_stf_primitives::types::TrustedOperation; + +#[derive(Parser)] +pub struct GetParentchainsInfoCommand {} + +impl GetParentchainsInfoCommand { + pub(crate) fn run(&self, cli: &Cli, trusted_args: &TrustedCli) -> CliResult { + let top = TrustedOperation::::get(Getter::public( + PublicGetter::parentchains_info, + )); + let info: ParentchainsInfo = perform_trusted_operation(cli, trusted_args, &top).unwrap(); + println!("{:?}", info); + Ok(CliResultOk::ParentchainsInfo { info }) + } +} diff --git a/cli/src/trusted_base_cli/commands/mod.rs b/cli/src/trusted_base_cli/commands/mod.rs index 1e0f5e6c95..39edf5d346 100644 --- a/cli/src/trusted_base_cli/commands/mod.rs +++ b/cli/src/trusted_base_cli/commands/mod.rs @@ -1,7 +1,10 @@ pub mod balance; +pub mod get_fingerprint; +pub mod get_parentchains_info; pub mod get_shard; pub mod get_shard_vault; pub mod get_total_issuance; + pub mod nonce; pub mod transfer; pub mod unshield_funds; diff --git a/cli/src/trusted_base_cli/mod.rs b/cli/src/trusted_base_cli/mod.rs index ba186510f8..d79a397e93 100644 --- a/cli/src/trusted_base_cli/mod.rs +++ b/cli/src/trusted_base_cli/mod.rs @@ -19,9 +19,10 @@ use crate::trusted_base_cli::commands::set_balance::SetBalanceCommand; use crate::{ trusted_base_cli::commands::{ - balance::BalanceCommand, get_shard::GetShardCommand, get_shard_vault::GetShardVaultCommand, - get_total_issuance::GetTotalIssuanceCommand, nonce::NonceCommand, - transfer::TransferCommand, unshield_funds::UnshieldFundsCommand, + balance::BalanceCommand, get_fingerprint::GetFingerprintCommand, + get_parentchains_info::GetParentchainsInfoCommand, get_shard::GetShardCommand, + get_shard_vault::GetShardVaultCommand, get_total_issuance::GetTotalIssuanceCommand, + nonce::NonceCommand, transfer::TransferCommand, unshield_funds::UnshieldFundsCommand, }, trusted_cli::TrustedCli, trusted_command_utils::get_keystore_path, @@ -59,6 +60,9 @@ pub enum TrustedBaseCommand { /// in top pool in consideration Nonce(NonceCommand), + /// get fingerprint (AKA MRENCLAVE) for this worker + GetFingerprint(GetFingerprintCommand), + /// get shard for this worker GetShard(GetShardCommand), @@ -67,6 +71,9 @@ pub enum TrustedBaseCommand { /// get total issuance of this shard's native token GetTotalIssuance(GetTotalIssuanceCommand), + + /// get info for all parentchains' sync status + GetParentchainsInfo(GetParentchainsInfoCommand), } impl TrustedBaseCommand { @@ -80,6 +87,8 @@ impl TrustedBaseCommand { TrustedBaseCommand::Balance(cmd) => cmd.run(cli, trusted_cli), TrustedBaseCommand::UnshieldFunds(cmd) => cmd.run(cli, trusted_cli), TrustedBaseCommand::Nonce(cmd) => cmd.run(cli, trusted_cli), + TrustedBaseCommand::GetFingerprint(cmd) => cmd.run(cli, trusted_cli), + TrustedBaseCommand::GetParentchainsInfo(cmd) => cmd.run(cli, trusted_cli), TrustedBaseCommand::GetShard(cmd) => cmd.run(cli, trusted_cli), TrustedBaseCommand::GetShardVault(cmd) => cmd.run(cli, trusted_cli), TrustedBaseCommand::GetTotalIssuance(cmd) => cmd.run(cli, trusted_cli), diff --git a/cli/src/trusted_command_utils.rs b/cli/src/trusted_command_utils.rs index 17e999194b..9beba38b61 100644 --- a/cli/src/trusted_command_utils.rs +++ b/cli/src/trusted_command_utils.rs @@ -23,12 +23,11 @@ use crate::{ }; use base58::{FromBase58, ToBase58}; use codec::{Decode, Encode}; -use ita_parentchain_interface::integritee::Balance; use ita_stf::{Getter, TrustedCallSigned, TrustedGetter}; use itc_rpc_client::direct_client::DirectApi; use itp_rpc::{RpcRequest, RpcResponse, RpcReturnValue}; use itp_stf_primitives::types::{AccountId, KeyPair, ShardIdentifier, TrustedOperation}; -use itp_types::DirectRequestStatus; +use itp_types::{AccountInfo, DirectRequestStatus}; use itp_utils::{FromHexPrefixed, ToHexPrefixed}; use log::*; use sp_application_crypto::sr25519; @@ -40,16 +39,15 @@ use substrate_client_keystore::LocalKeystore; #[macro_export] macro_rules! get_layer_two_nonce { ($signer_pair:ident, $cli: ident, $trusted_args:ident ) => {{ - use ita_stf::{Getter, TrustedCallSigned, TrustedGetter}; + use ita_stf::{AccountInfo, Getter, TrustedCallSigned, TrustedGetter}; use $crate::trusted_command_utils::get_pending_trusted_calls_for; let top = TrustedOperation::::get(Getter::trusted( - TrustedGetter::nonce($signer_pair.public().into()) + TrustedGetter::account_info($signer_pair.public().into()) .sign(&KeyPair::Sr25519(Box::new($signer_pair.clone()))), )); // final nonce = current system nonce + pending tx count, panic early - let nonce = perform_trusted_operation::($cli, $trusted_args, &top) - .ok() - .unwrap_or_default(); + let info = perform_trusted_operation::($cli, $trusted_args, &top); + let nonce = info.map(|i| i.nonce).ok().unwrap_or_default(); debug!("got system nonce: {:?}", nonce); let pending_tx_count = get_pending_trusted_calls_for($cli, $trusted_args, &$signer_pair.public().into()).len(); @@ -65,9 +63,10 @@ pub(crate) fn get_balance(cli: &Cli, trusted_args: &TrustedCli, arg_who: &str) - debug!("arg_who = {:?}", arg_who); let who = get_pair_from_str(trusted_args, arg_who); let top = TrustedOperation::::get(Getter::trusted( - TrustedGetter::free_balance(who.public().into()).sign(&KeyPair::Sr25519(Box::new(who))), + TrustedGetter::account_info(who.public().into()).sign(&KeyPair::Sr25519(Box::new(who))), )); - perform_trusted_operation::(cli, trusted_args, &top).ok() + let info = perform_trusted_operation::(cli, trusted_args, &top).ok(); + info.map(|i| i.data.free) } pub(crate) fn get_keystore_path(trusted_args: &TrustedCli) -> PathBuf { diff --git a/cli/test_auto_shielding_with_transfer_bob.sh b/cli/test_auto_shielding_with_transfer_bob.sh index 255d3f5bbc..8659670f64 100644 --- a/cli/test_auto_shielding_with_transfer_bob.sh +++ b/cli/test_auto_shielding_with_transfer_bob.sh @@ -4,7 +4,7 @@ set -euo pipefail # Verifies that auto shielding transfers sent to vault account: //Alice are verified from sender //Bob # -while getopts ":m:p:A:u:V:w:x:y:z:C:" opt; do +while getopts ":p:A:u:V:w:x:y:z:C:" opt; do case $opt in p) INTEGRITEE_RPC_PORT=$OPTARG @@ -109,11 +109,9 @@ echo "* Query on-chain enclave registry:" ${CLIENT} list-workers echo "" -# this will always take the first MRENCLAVE found in the registry !! -read MRENCLAVE <<< $($CLIENT list-workers | awk '/ MRENCLAVE: / { print $2; exit }') -echo "Reading MRENCLAVE from worker list: ${MRENCLAVE}" - -[[ -z $MRENCLAVE ]] && { echo "MRENCLAVE is empty. cannot continue" ; exit 1; } +# we simply believe the enclave here without verifying the teerex RA +MRENCLAVE="$($CLIENT trusted get-fingerprint)" +echo "Using MRENCLAVE: ${MRENCLAVE}" VAULTACCOUNT=//Alice ## Sender account to shield for diff --git a/enclave-runtime/Cargo.lock b/enclave-runtime/Cargo.lock index 661bd4c811..cad816292c 100644 --- a/enclave-runtime/Cargo.lock +++ b/enclave-runtime/Cargo.lock @@ -771,7 +771,7 @@ dependencies = [ [[package]] name = "enclave-runtime" -version = "0.14.1" +version = "0.14.2" dependencies = [ "array-bytes 6.2.2", "cid", diff --git a/enclave-runtime/Cargo.toml b/enclave-runtime/Cargo.toml index 6a1869b1a8..df58818904 100644 --- a/enclave-runtime/Cargo.toml +++ b/enclave-runtime/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "enclave-runtime" -version = "0.14.1" +version = "0.14.2" authors = ["Integritee AG "] edition = "2021" diff --git a/enclave-runtime/src/rpc/common_api.rs b/enclave-runtime/src/rpc/common_api.rs index c20dadc6a4..8f08756afb 100644 --- a/enclave-runtime/src/rpc/common_api.rs +++ b/enclave-runtime/src/rpc/common_api.rs @@ -30,12 +30,13 @@ use core::result::Result; use ita_sgx_runtime::Runtime; use ita_stf::{Getter, TrustedCallSigned}; use itc_parentchain::light_client::{concurrent_access::ValidatorAccess, ExtrinsicSender}; +use itp_ocall_api::EnclaveAttestationOCallApi; use itp_primitives_cache::{GetPrimitives, GLOBAL_PRIMITIVES_CACHE}; use itp_rpc::RpcReturnValue; use itp_sgx_crypto::key_repository::AccessPubkey; use itp_stf_executor::{getter_executor::ExecuteGetter, traits::StfShardVaultQuery}; use itp_top_pool_author::traits::AuthorApi; -use itp_types::{DirectRequestStatus, Request, ShardIdentifier, H256}; +use itp_types::{DirectRequestStatus, EnclaveFingerprint, Request, ShardIdentifier, H256}; use itp_utils::{FromHexPrefixed, ToHexPrefixed}; use its_rpc_handler::direct_top_pool_api::add_top_pool_direct_rpc_methods; use jsonrpc_core::{serde_json::json, IoHandler, Params, Value}; @@ -111,6 +112,18 @@ pub fn add_common_api( Ok(json!(json_value.to_hex())) }); + io_handler.add_sync_method("author_getFingerprint", move |_: Params| { + debug!("worker_api_direct rpc was called: author_getFingerprint"); + let mrenclave = get_stf_enclave_signer_from_solo_or_parachain() + .map(|enclave_signer| { + enclave_signer.ocall_api.get_mrenclave_of_self().unwrap_or_default() + }) + .unwrap_or_default(); + let fingerprint = EnclaveFingerprint::from(mrenclave.m); + let json_value = RpcReturnValue::new(fingerprint.encode(), false, DirectRequestStatus::Ok); + Ok(json!(json_value.to_hex())) + }); + io_handler.add_sync_method("author_getMuRaUrl", move |_: Params| { debug!("worker_api_direct rpc was called: author_getMuRaUrl"); let url = match GLOBAL_PRIMITIVES_CACHE.get_mu_ra_url() { diff --git a/enclave-runtime/src/test/direct_rpc_tests.rs b/enclave-runtime/src/test/direct_rpc_tests.rs index a1cf73f21c..2969f1594c 100644 --- a/enclave-runtime/src/test/direct_rpc_tests.rs +++ b/enclave-runtime/src/test/direct_rpc_tests.rs @@ -58,7 +58,7 @@ pub fn get_state_request_works() { let rpc_handler = Arc::new(RpcWsHandler::new(io_handler, watch_extractor, connection_registry)); let getter = Getter::trusted(TrustedGetterSigned::new( - TrustedGetter::nonce(AccountId::new([0u8; 32])), + TrustedGetter::account_info(AccountId::new([0u8; 32])), MultiSignature::Ed25519(Signature::from_raw([0u8; 64])), )); diff --git a/enclave-runtime/src/test/state_getter_tests.rs b/enclave-runtime/src/test/state_getter_tests.rs index 6a96a39503..321f780b8c 100644 --- a/enclave-runtime/src/test/state_getter_tests.rs +++ b/enclave-runtime/src/test/state_getter_tests.rs @@ -20,10 +20,11 @@ use codec::Decode; use ita_sgx_runtime::Runtime; use ita_stf::{ test_genesis::{endowed_account, test_genesis_setup, ENDOWED_ACC_FUNDS}, - Balance, Getter, Stf, TrustedCallSigned, TrustedGetter, + Getter, Stf, TrustedCallSigned, TrustedGetter, }; use itp_sgx_externalities::SgxExternalities; use itp_stf_executor::state_getter::{GetState, StfStateGetter}; +use itp_types::AccountInfo; use sp_core::Pair; type TestState = SgxExternalities; @@ -32,14 +33,15 @@ type TestStfStateGetter = StfStateGetter; pub fn state_getter_works() { let sender = endowed_account(); - let signed_getter = TrustedGetter::free_balance(sender.public().into()).sign(&sender.into()); + let signed_getter = TrustedGetter::account_info(sender.public().into()).sign(&sender.into()); let mut state = test_state(); - let encoded_balance = TestStfStateGetter::get_state(signed_getter.into(), &mut state) + let encoded_info = TestStfStateGetter::get_state(signed_getter.into(), &mut state) .unwrap() .unwrap(); - let balance = Balance::decode(&mut encoded_balance.as_slice()).unwrap(); + let info = AccountInfo::decode(&mut encoded_info.as_slice()).unwrap(); + let balance = info.data.free; assert_eq!(balance, ENDOWED_ACC_FUNDS); } diff --git a/enclave-runtime/src/test/tests_main.rs b/enclave-runtime/src/test/tests_main.rs index 716e448080..6e737d8c59 100644 --- a/enclave-runtime/src/test/tests_main.rs +++ b/enclave-runtime/src/test/tests_main.rs @@ -261,7 +261,7 @@ fn test_submit_trusted_getter_to_top_pool() { let sender = funded_pair(); - let signed_getter = TrustedGetter::free_balance(sender.public().into()).sign(&sender.into()); + let signed_getter = TrustedGetter::account_info(sender.public().into()).sign(&sender.into()); // when submit_operation_to_top_pool( @@ -288,7 +288,7 @@ fn test_differentiate_getter_and_call_works() { // create accounts let sender = funded_pair(); - let signed_getter = TrustedGetter::free_balance(sender.public().into()).sign(&sender.into()); + let signed_getter = TrustedGetter::account_info(sender.public().into()).sign(&sender.into()); let signed_call = TrustedCall::balance_set_balance(sender.public().into(), sender.public().into(), 42, 42) diff --git a/service/Cargo.toml b/service/Cargo.toml index 3b4f37ae00..b14b214b61 100644 --- a/service/Cargo.toml +++ b/service/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "integritee-service" -version = "0.14.1" +version = "0.14.2" authors = ["Integritee AG "] build = "build.rs" edition = "2021"