diff --git a/gn-client/artifacts/metadata.scale b/gn-client/artifacts/metadata.scale index 4288c615..0c59d56f 100644 Binary files a/gn-client/artifacts/metadata.scale and b/gn-client/artifacts/metadata.scale differ diff --git a/gn-client/examples/guild/common.rs b/gn-client/examples/guild/common.rs index d417ea06..19778703 100644 --- a/gn-client/examples/guild/common.rs +++ b/gn-client/examples/guild/common.rs @@ -13,6 +13,9 @@ use sp_keyring::AccountKeyring; use std::collections::BTreeMap; use std::sync::Arc; +const RETRIES: u8 = 10; +const SLEEP_DURATION_MS: u64 = 1000; + pub struct Accounts { pub substrate: Arc, pub eth: LocalWallet, @@ -68,23 +71,78 @@ pub async fn prefunded_accounts( } #[cfg(not(feature = "external-oracle"))] -pub async fn register_operators(api: Api, accounts: impl Iterator) { - let register_operator_futures = accounts - .map(|account| { +pub async fn register_operators( + api: Api, + root: Arc, + accounts: impl Iterator, +) { + println!("registring operators"); + for (i, account) in accounts.enumerate() { + let payload = tx::register_operator(account.substrate.account_id()); + tx::send_tx_in_block(api.clone(), &tx::sudo(payload), Arc::clone(&root)) + .await + .unwrap(); + println!("\toperator {i} registered"); + } + + println!("operator registrations in block"); +} + +#[cfg(not(feature = "external-oracle"))] +pub async fn activate_operators(api: Api, accounts: impl Iterator) { + println!("activating operators"); + let tx_futures = accounts + .map(|acc| { tx::send_owned_tx( api.clone(), - tx::register_operator(), - Arc::clone(&account.substrate), + tx::activate_operator(), + Arc::clone(&acc.substrate), TxStatus::InBlock, ) }) .collect::>(); - try_join_all(register_operator_futures) - .await - .expect("failed to register operators"); + try_join_all(tx_futures).await.unwrap(); - println!("operator registrations in block"); + println!("operators activated"); +} + +pub async fn wait_for_active_operator(api: Api) { + let mut i = 0; + loop { + let active_operators = query::active_operators(api.clone()) + .await + .expect("failed to fetch active operators"); + if active_operators.is_empty() { + i += 1; + println!("waiting for active operators"); + if i == RETRIES { + panic!("no active operators found"); + } + tokio::time::sleep(std::time::Duration::from_millis(SLEEP_DURATION_MS)).await; + } else { + println!("found an active operator"); + break; + } + } +} + +pub async fn wait_for_oracle_answers(api: Api) { + let mut i = 0; + loop { + let oracle_requests = query::oracle_requests(api.clone(), PAGE_SIZE) + .await + .expect("failed to fetch oracle requests"); + if !oracle_requests.is_empty() { + i += 1; + if i == RETRIES { + panic!("ran out of retries while checking oracle requests") + } + tokio::time::sleep(std::time::Duration::from_millis(SLEEP_DURATION_MS)).await; + } else { + break; + } + } } pub async fn create_dummy_guilds( diff --git a/gn-client/examples/guild/join.rs b/gn-client/examples/guild/join.rs index b1f43efe..c121ea8b 100644 --- a/gn-client/examples/guild/join.rs +++ b/gn-client/examples/guild/join.rs @@ -7,47 +7,33 @@ use gn_common::pad::padded_id; use gn_test_data::*; use std::sync::Arc; -const RETRIES: u8 = 10; -const SLEEP_DURATION_MS: u64 = 500; - -pub async fn join(api: Api, alice: Arc) { - let operators = prefunded_accounts(api.clone(), Arc::clone(&alice), N_TEST_ACCOUNTS).await; +pub async fn join(api: Api, root: Arc) { + let operators = prefunded_accounts(api.clone(), Arc::clone(&root), N_TEST_ACCOUNTS).await; #[cfg(not(feature = "external-oracle"))] { - let registering_operators = operators.values(); - register_operators(api.clone(), registering_operators).await; - let registered_operators = query::registered_operators(api.clone()) + register_operators(api.clone(), Arc::clone(&root), operators.values()).await; + activate_operators(api.clone(), operators.values()).await; + let active_operators = query::active_operators(api.clone()) .await - .expect("failed to fetch registered operators"); + .expect("failed to fetch active operators"); - for registered in ®istered_operators { - if registered != alice.account_id() { - assert!(operators.get(registered).is_some()); - } + for active in &active_operators { + assert!(operators.get(active).is_some()); } } + #[cfg(not(feature = "external-oracle"))] + { + wait_for_active_operator(api.clone()).await; + } + register_users(api.clone(), &operators).await; #[cfg(not(feature = "external-oracle"))] send_dummy_oracle_answers(api.clone(), &operators).await; // wait for all transactions to be finalized - let mut i = 0; - loop { - let oracle_requests = query::oracle_requests(api.clone(), PAGE_SIZE) - .await - .expect("failed to fetch oracle requests"); - if !oracle_requests.is_empty() { - i += 1; - if i == RETRIES { - panic!("ran out of retries while checking oracle requests") - } - tokio::time::sleep(std::time::Duration::from_millis(SLEEP_DURATION_MS)).await; - } else { - break; - } - } + wait_for_oracle_answers(api.clone()).await; for (i, (id, accounts)) in operators.iter().enumerate() { let user_identity = query::user_identity(api.clone(), id) @@ -63,7 +49,7 @@ pub async fn join(api: Api, alice: Arc) { assert_eq!(user_identity, expected); } - create_dummy_guilds(api.clone(), alice, operators.values()).await; + create_dummy_guilds(api.clone(), root, operators.values()).await; join_guilds(api.clone(), &operators).await; diff --git a/gn-client/examples/guild/main.rs b/gn-client/examples/guild/main.rs index f1adc017..7c6c2449 100644 --- a/gn-client/examples/guild/main.rs +++ b/gn-client/examples/guild/main.rs @@ -1,5 +1,6 @@ mod common; mod join; +mod register; mod token; use common::api_with_alice; @@ -12,6 +13,7 @@ use std::str::FromStr; enum Example { Join, Token, + Register, } impl FromStr for Example { @@ -19,6 +21,7 @@ impl FromStr for Example { fn from_str(s: &str) -> Result { match s { "join" => Ok(Self::Join), + "register" => Ok(Self::Register), "token" => Ok(Self::Token), _ => Err(format!("no example with name {s}")), } @@ -52,6 +55,7 @@ async fn main() { match opt.example { Example::Join => join::join(api, alice).await, + Example::Register => register::register(api, alice).await, Example::Token => token::token(api, alice).await, } } diff --git a/gn-client/examples/guild/register.rs b/gn-client/examples/guild/register.rs new file mode 100644 index 00000000..47342abe --- /dev/null +++ b/gn-client/examples/guild/register.rs @@ -0,0 +1,14 @@ +use gn_client::{ + tx::{self, Signer}, + Api, +}; + +use std::sync::Arc; + +pub async fn register(api: Api, root: Arc) { + let payload = tx::register_operator(root.account_id()); + tx::send_tx_in_block(api, &tx::sudo(payload), root) + .await + .unwrap(); + println!("root registered as operator"); +} diff --git a/gn-client/examples/guild/token.rs b/gn-client/examples/guild/token.rs index ba706d92..07e830a7 100644 --- a/gn-client/examples/guild/token.rs +++ b/gn-client/examples/guild/token.rs @@ -1,4 +1,3 @@ -#[cfg(not(feature = "external-oracle"))] use crate::common::*; use ethers::types::{Address, U256}; use gn_client::{ @@ -29,7 +28,7 @@ const GNOSIS_ERC721_ID_1: &str = "5819774"; const ADDRESS: &str = "e43878ce78934fe8007748ff481f03b8ee3b97de"; const SIGNATURE: &str = "a7d8263c96a8bb689d462b2782a45b81f02777607c27d1b322a1c46910482e274320fbf353a543a1504dc3c0ded9c2930dffc4b15541d97da7b240f40416f12a1b"; -pub async fn token(api: Api, alice: Arc) { +pub async fn token(api: Api, root: Arc) { let mut signature = [0u8; 65]; hex::decode_to_slice(SIGNATURE, &mut signature).expect("this should not fail"); signature[64] -= 27; // ethereum's eip-115 normalization stuff @@ -37,30 +36,32 @@ pub async fn token(api: Api, alice: Arc) { hex::decode_to_slice(ADDRESS, &mut address).expect("this should not fail"); #[cfg(not(feature = "external-oracle"))] - let operators = prefunded_accounts(api.clone(), Arc::clone(&alice), N_TEST_ACCOUNTS).await; + let operators = prefunded_accounts(api.clone(), Arc::clone(&root), N_TEST_ACCOUNTS).await; #[cfg(not(feature = "external-oracle"))] { - let registering_operators = operators.values(); - register_operators(api.clone(), registering_operators).await; - let registered_operators = query::registered_operators(api.clone()) + register_operators(api.clone(), Arc::clone(&root), operators.values()).await; + activate_operators(api.clone(), operators.values()).await; + let active_operators = query::active_operators(api.clone()) .await - .expect("failed to fetch registered operators"); + .expect("failed to fetch active operators"); - for registered in ®istered_operators { - if registered != alice.account_id() { - assert!(operators.get(registered).is_some()); - } + for active in &active_operators { + assert!(operators.get(active).is_some()); } } - // register alice with test evm address + signature + #[cfg(feature = "external-oracle")] + { + wait_for_active_operator(api.clone()).await; + } + // register root with test evm address + signature let evm_identity = IdentityWithAuth::Ecdsa(Identity::Address20(address), EcdsaSignature(signature)); let index = 0; let tx_payload = tx::register(evm_identity, index); - tx::send_tx_in_block(api.clone(), &tx_payload, Arc::clone(&alice)) + tx::send_tx_in_block(api.clone(), &tx_payload, Arc::clone(&root)) .await .expect("failed to register"); @@ -68,7 +69,7 @@ pub async fn token(api: Api, alice: Arc) { send_dummy_oracle_answers(api.clone(), &operators).await; loop { - let user_identity = query::user_identity(api.clone(), alice.account_id()) + let user_identity = query::user_identity(api.clone(), root.account_id()) .await .expect("failed to fetch user identities"); if user_identity.len() == 1 { @@ -137,28 +138,28 @@ pub async fn token(api: Api, alice: Arc) { }; let tx_payload = tx::create_guild(TOKEN_GUILD, vec![1, 2, 3]); - tx::send_tx_in_block(api.clone(), &tx_payload, Arc::clone(&alice)) + tx::send_tx_in_block(api.clone(), &tx_payload, Arc::clone(&root)) .await .expect("failed to create guild"); println!("GUILD CREATED"); let tx_payload = tx::create_unfiltered_role(TOKEN_GUILD, FIRST_ROLE, first_reqs).unwrap(); - tx::send_tx_in_block(api.clone(), &tx_payload, Arc::clone(&alice)) + tx::send_tx_in_block(api.clone(), &tx_payload, Arc::clone(&root)) .await .expect("failed to create guild"); println!("FIRST ROLE CREATED"); let tx_payload = tx::create_unfiltered_role(TOKEN_GUILD, SECOND_ROLE, second_reqs).unwrap(); - tx::send_tx_in_block(api.clone(), &tx_payload, Arc::clone(&alice)) + tx::send_tx_in_block(api.clone(), &tx_payload, Arc::clone(&root)) .await .expect("failed to create guild"); println!("SECOND ROLE CREATED"); let tx_payload = tx::join(TOKEN_GUILD, FIRST_ROLE, None); - tx::send_tx_in_block(api.clone(), &tx_payload, Arc::clone(&alice)) + tx::send_tx_in_block(api.clone(), &tx_payload, Arc::clone(&root)) .await .expect("failed to join guild"); @@ -175,7 +176,7 @@ pub async fn token(api: Api, alice: Arc) { .await .expect("failed to query members"); if members.len() == 1 { - assert_eq!(members.get(0).unwrap(), alice.account_id()); + assert_eq!(members.get(0).unwrap(), root.account_id()); break; } } @@ -183,7 +184,7 @@ pub async fn token(api: Api, alice: Arc) { println!("FIRST_ROLE JOINED"); let tx_payload = tx::join(TOKEN_GUILD, SECOND_ROLE, None); - tx::send_tx_in_block(api.clone(), &tx_payload, Arc::clone(&alice)) + tx::send_tx_in_block(api.clone(), &tx_payload, Arc::clone(&root)) .await .expect("failed to join guild"); @@ -200,7 +201,7 @@ pub async fn token(api: Api, alice: Arc) { .await .expect("failed to query members"); if members.len() == 1 { - assert_eq!(members.get(0).unwrap(), alice.account_id()); + assert_eq!(members.get(0).unwrap(), root.account_id()); break; } } diff --git a/gn-client/src/query/functions.rs b/gn-client/src/query/functions.rs index 725e609e..fded2380 100644 --- a/gn-client/src/query/functions.rs +++ b/gn-client/src/query/functions.rs @@ -9,8 +9,8 @@ use subxt::storage::address::{StorageHasher, StorageMapKey}; use std::collections::BTreeMap; -pub async fn registered_operators(api: Api) -> Result, SubxtError> { - let operators = runtime::storage().oracle().operators(); +pub async fn active_operators(api: Api) -> Result, SubxtError> { + let operators = runtime::storage().oracle().active_operators(); Ok(api .storage() .at(None) @@ -20,6 +20,17 @@ pub async fn registered_operators(api: Api) -> Result, SubxtError .unwrap_or_default()) } +pub async fn is_operator_registered(api: Api, id: &AccountId) -> Result { + let operator = runtime::storage().oracle().registered_operators(id); + Ok(api + .storage() + .at(None) + .await? + .fetch(&operator) + .await? + .is_some()) +} + pub async fn user_identity(api: Api, user_id: &AccountId) -> Result, SubxtError> { let mut i = 0u8; let mut identities = Vec::new(); diff --git a/gn-client/src/tx/mod.rs b/gn-client/src/tx/mod.rs index c448b69c..28eff8a2 100644 --- a/gn-client/src/tx/mod.rs +++ b/gn-client/src/tx/mod.rs @@ -16,18 +16,35 @@ use gn_common::identity::{Identity, IdentityWithAuth}; use gn_common::merkle::Proof as MerkleProof; use gn_common::{GuildName, RoleName}; use gn_engine::RequirementsWithLogic; -use subxt::tx::TxPayload; +use subxt::dynamic::Value; +use subxt::tx::{DynamicTxPayload, TxPayload}; use std::sync::Arc; +pub fn sudo<'a>(call: DynamicTxPayload<'_>) -> DynamicTxPayload<'a> { + subxt::dynamic::tx("Sudo", "sudo", vec![("call", call.into_value())]) +} + pub fn fund_account(account: &AccountId, amount: u128) -> impl TxPayload { runtime::tx() .balances() .transfer(MultiAddress::Id(account.clone()), amount) } -pub fn register_operator() -> impl TxPayload { - runtime::tx().oracle().register_operator() +pub fn register_operator<'a>(operator: &AccountId) -> DynamicTxPayload<'a> { + subxt::dynamic::tx( + "Oracle", + "register_operator", + vec![("operator", Value::from_bytes(operator))], + ) +} + +pub fn activate_operator() -> impl TxPayload { + runtime::tx().oracle().activate_operator() +} + +pub fn deactivate_operator() -> impl TxPayload { + runtime::tx().oracle().deactivate_operator() } pub fn oracle_callback(request_id: u64, data: Vec) -> impl TxPayload { diff --git a/gn-common/Cargo.toml b/gn-common/Cargo.toml index a05d15e1..77886f93 100644 --- a/gn-common/Cargo.toml +++ b/gn-common/Cargo.toml @@ -13,6 +13,7 @@ std = [ "schnorrkel/std", "sha3/std", ] +test-sig = [] [dependencies] binary-merkle-tree = { version = "4.0.0", default-features = false } diff --git a/gn-common/src/identity/auth.rs b/gn-common/src/identity/auth.rs index 0cae82ef..715b20f0 100644 --- a/gn-common/src/identity/auth.rs +++ b/gn-common/src/identity/auth.rs @@ -102,6 +102,34 @@ pub fn eth_hash_message>(message: M) -> [u8; 32] { keccak256(ð_message) } +#[cfg(any(test, feature = "test-sig"))] +pub fn sign_prehashed(seed: [u8; 32], message: [u8; 32]) -> EcdsaSignature { + let secret = secp256k1::SecretKey::from_slice(&seed).expect("seed is 32 bytes; qed"); + let message = Message::from_slice(&message).expect("Message is 32 bytes; qed"); + + let (rec_id, sig) = Secp256k1::signing_only() + .sign_ecdsa_recoverable(&message, &secret) + .serialize_compact(); + let mut sig_bytes = [0u8; 65]; + sig_bytes[64] = rec_id.to_i32() as u8; + sig_bytes[0..64].copy_from_slice(&sig); + EcdsaSignature(sig_bytes) +} + +#[cfg(any(test, feature = "test-sig"))] +pub fn test_ecdsa_id_with_auth>( + seed: [u8; 32], + msg: M, +) -> (Identity, EcdsaSignature) { + let prehashed = eth_hash_message(msg); + let signature = sign_prehashed(seed, prehashed); + let pubkey = recover_prehashed(prehashed, &signature).unwrap(); + let address: [u8; 20] = keccak256(&pubkey.serialize_uncompressed()[1..])[12..] + .try_into() + .unwrap(); + (Identity::Address20(address), signature) +} + #[cfg(test)] mod test { use super::*; @@ -151,7 +179,10 @@ mod test { let id_with_auth = IdentityWithAuth::Ecdsa(sp_address, sp_signature); assert!(id_with_auth.verify(&msg)); - assert!(!id_with_auth.verify(b"wrong msg")) + assert!(!id_with_auth.verify(b"wrong msg")); + + let (address, signature) = test_ecdsa_id_with_auth(seed, &msg); + assert!(IdentityWithAuth::Ecdsa(address, signature).verify(&msg)); } #[tokio::test] diff --git a/gn-oracle/src/main.rs b/gn-oracle/src/main.rs index fa03d910..c5f05aff 100644 --- a/gn-oracle/src/main.rs +++ b/gn-oracle/src/main.rs @@ -39,9 +39,9 @@ struct Opt { /// Set operator account #[structopt(long = "id", default_value = "alice")] id: String, - /// Register as an oracle operator before starting to listen to events + /// Activate operator before starting to listen to events #[structopt(long)] - register: bool, + activate: bool, } #[tokio::main] @@ -54,7 +54,7 @@ async fn main() { // TODO: this will be read from the oracle's wallet for testing purposes we // are choosing from pre-funded accounts - let signer = Arc::new(Signer::new( + let operator = Arc::new(Signer::new( match opt.id.to_lowercase().as_str() { "bob" => AccountKeyring::Bob, "charlie" => AccountKeyring::Charlie, @@ -70,12 +70,29 @@ async fn main() { .await .expect("failed to start api client"); - if opt.register { - tx::send_tx_in_block(api.clone(), &tx::register_operator(), Arc::clone(&signer)) + if !query::is_operator_registered(api.clone(), operator.account_id()) + .await + .expect("failed to fetch operator info") + { + panic!("{} is not registered as an operator", operator.account_id()); + } + + if opt.activate { + tx::send_tx_in_block(api.clone(), &tx::activate_operator(), Arc::clone(&operator)) .await - .expect("failed to register operator"); + .expect("failed to activate operator"); - log::info!("operator registration request submitted"); + log::info!("operator activation request submitted"); + } + + let active = query::active_operators(api.clone()) + .await + .expect("failed to fetch active operators"); + if !active.contains(operator.account_id()) { + panic!( + "{} not activated. Run oracle with the '--activate' flag", + operator.account_id() + ); } let mut subscription = api @@ -95,7 +112,7 @@ async fn main() { event_details.as_event::().ok().flatten() }) .for_each(|oracle_request| { - submit_answer(api.clone(), Arc::clone(&signer), oracle_request) + submit_answer(api.clone(), Arc::clone(&operator), oracle_request) }); } Err(err) => log::error!("invalid block events: {err}"), diff --git a/gn-pallets/pallet-guild/Cargo.toml b/gn-pallets/pallet-guild/Cargo.toml index 7dffbc6c..dd662c1e 100644 --- a/gn-pallets/pallet-guild/Cargo.toml +++ b/gn-pallets/pallet-guild/Cargo.toml @@ -5,12 +5,16 @@ version = "0.0.0-alpha" [features] default = ["std"] -runtime-benchmarks = [] +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "gn-common/test-sig", +] std = [ "gn-common/std", "pallet-oracle/std", "parity-scale-codec/std", "scale-info/std", + "frame-benchmarking?/std", "frame-support/std", "frame-system/std", "sp-io/std", @@ -27,7 +31,11 @@ pallet-oracle = { version = "0.0.0-alpha", path = "../pallet-oracle", default-fe parity-scale-codec = { workspace = true, features = ["derive"] } scale-info = { workspace = true, features = ["derive"] } +# substrate pallets +pallet-balances = { workspace = true, optional = true } + # substrate frame +frame-benchmarking = { workspace = true, optional = true } frame-support = { workspace = true } frame-system = { workspace = true } @@ -38,6 +46,5 @@ sp-std = { workspace = true } [dev-dependencies] pallet-balances = { workspace = true, features = ["default"] } pallet-randomness-collective-flip = { workspace = true, features = ["default"] } -sp-core = { workspace = true, features = ["default"] } -sp-io = { workspace = true, features = ["default"] } +sp-core = { workspace = true } sp-runtime = { workspace = true, features = ["default"] } diff --git a/gn-pallets/pallet-guild/src/benchmark.rs b/gn-pallets/pallet-guild/src/benchmark.rs new file mode 100644 index 00000000..28fb8b8b --- /dev/null +++ b/gn-pallets/pallet-guild/src/benchmark.rs @@ -0,0 +1,260 @@ +use super::*; +use crate::Pallet as Guild; + +use frame_benchmarking::{account, benchmarks, whitelisted_caller}; +use frame_support::traits::Get; +use frame_system::RawOrigin; +use gn_common::filter::{Guild as GuildFilter, Logic as FilterLogic}; +use gn_common::identity::*; +use gn_common::merkle::Proof as MerkleProof; +use sp_std::vec; + +const ACCOUNT: &str = "account"; +const SEED: u32 = 999; + +benchmarks! { + register { + let caller: T::AccountId = whitelisted_caller(); + let (identity, signature) = id_with_auth::(&caller); + let identity_with_auth = IdentityWithAuth::Ecdsa(identity, signature); + let index = 1; + }: _(RawOrigin::Signed(caller.clone()), identity_with_auth, index) + verify { + assert_eq!(Guild::::user_data(caller, index), Some(identity)); + } + create_guild { + let n in 0 .. ::MaxSerializedLen::get(); + + let caller: T::AccountId = whitelisted_caller(); + let guild_name = [0u8; 32]; + let metadata = vec![0u8; n as usize]; + }: _(RawOrigin::Signed(caller), guild_name, metadata) + verify { + assert!(Guild::::guild_id(guild_name).is_some()); + } + create_free_role { + let caller: T::AccountId = whitelisted_caller(); + let guild_name = [0u8; 32]; + let role_name = [0u8; 32]; + init_guild::(&caller, guild_name); + }: _(RawOrigin::Signed(caller), guild_name, role_name) + verify { + let guild_id = Guild::::guild_id(guild_name).unwrap(); + assert!(Guild::::role_id(guild_id, role_name).is_some()); + } + + create_role_with_allowlist { + let n in 1 .. ::MaxAllowlistLen::get(); + let r in 0 .. ::MaxReqsPerRole::get(); + let s in 0 .. ::MaxSerializedLen::get(); + + let caller: T::AccountId = whitelisted_caller(); + let guild_name = [0u8; 32]; + let role_name = [0u8; 32]; + init_guild::(&caller, guild_name); + + let allowlist = vec![Identity::Other([0u8; 64]); n as usize]; + let logic = vec![100u8; s as usize]; + let req = vec![200u8; s as usize]; + let serialized_requirements = (vec![req; r as usize], logic); + }: _(RawOrigin::Signed(caller), guild_name, role_name, allowlist, FilterLogic::And, Some(serialized_requirements)) + verify { + let guild_id = Guild::::guild_id(guild_name).unwrap(); + assert!(Guild::::role_id(guild_id, role_name).is_some()); + } + + create_child_role { + let r in 0 .. ::MaxReqsPerRole::get(); + let s in 0 .. ::MaxSerializedLen::get(); + + let caller: T::AccountId = whitelisted_caller(); + let guild_name = [0u8; 32]; + let role_name = [0u8; 32]; + let free_role_name = [1u8; 32]; + init_guild::(&caller, guild_name); + Guild::::create_free_role( + RawOrigin::Signed(caller.clone()).into(), + guild_name, + free_role_name, + ).unwrap(); + + let logic = vec![100u8; s as usize]; + let req = vec![200u8; s as usize]; + let serialized_requirements = (vec![req; r as usize], logic); + let filter = GuildFilter { + name: guild_name, + role: Some(free_role_name), + }; + }: _(RawOrigin::Signed(caller), guild_name, role_name, filter, FilterLogic::And, Some(serialized_requirements)) + verify { + let guild_id = Guild::::guild_id(guild_name).unwrap(); + assert!(Guild::::role_id(guild_id, role_name).is_some()); + } + + create_unfiltered_role { + let r in 0 .. ::MaxReqsPerRole::get(); + let s in 0 .. ::MaxSerializedLen::get(); + + let caller: T::AccountId = whitelisted_caller(); + let guild_name = [0u8; 32]; + let role_name = [0u8; 32]; + init_guild::(&caller, guild_name); + let logic = vec![100u8; s as usize]; + let req = vec![200u8; s as usize]; + let serialized_requirements = (vec![req; r as usize], logic); + }: _(RawOrigin::Signed(caller), guild_name, role_name, serialized_requirements) + verify { + let guild_id = Guild::::guild_id(guild_name).unwrap(); + assert!(Guild::::role_id(guild_id, role_name).is_some()); + } + + join { + let n = ::MaxAllowlistLen::get() as usize; + + // identity + let caller: T::AccountId = whitelisted_caller(); + let (identity, signature) = id_with_auth::(&caller); + let identity_with_auth = IdentityWithAuth::Ecdsa(identity, signature); + Guild::::register( + RawOrigin::Signed(caller.clone()).into(), + identity_with_auth, + 0, + ).unwrap(); + + // guild + let guild_name = [0u8; 32]; + let role_name = [0u8; 32]; + init_guild::(&caller, guild_name); + let mut allowlist = vec![Identity::Address20([0u8; 20]); n - 1]; + allowlist.push(identity); + + Guild::::create_role_with_allowlist( + RawOrigin::Signed(caller.clone()).into(), + guild_name, + role_name, + allowlist.clone(), + FilterLogic::And, + None, + ).unwrap(); + + // proof to the last element + let proof = MerkleProof::new(&allowlist, n - 1, 0); + + }: _(RawOrigin::Signed(caller.clone()), guild_name, role_name, Some(proof)) + verify { + let guild_id = Guild::::guild_id(guild_name).unwrap(); + let role_id = Guild::::role_id(guild_id, role_name).unwrap(); + assert!(Guild::::member(role_id, caller).is_some()); + } + + leave { + let caller: T::AccountId = whitelisted_caller(); + let (identity, signature) = id_with_auth::(&caller); + let identity_with_auth = IdentityWithAuth::Ecdsa(identity, signature); + + Guild::::register( + RawOrigin::Signed(caller.clone()).into(), + identity_with_auth, + 0, + ).unwrap(); + + let guild_name = [0u8; 32]; + let role_name = [0u8; 32]; + init_guild::(&caller, guild_name); + Guild::::create_free_role( + RawOrigin::Signed(caller.clone()).into(), + guild_name, + role_name, + ).unwrap(); + + Guild::::join( + RawOrigin::Signed(caller.clone()).into(), + guild_name, + role_name, + None, + ).unwrap(); + }: _(RawOrigin::Signed(caller.clone()), guild_name, role_name) + verify { + let guild_id = Guild::::guild_id(guild_name).unwrap(); + let role_id = Guild::::role_id(guild_id, role_name).unwrap(); + assert!(Guild::::member(role_id, caller).is_none()); + } + + request_oracle_check { + let r = ::MaxReqsPerRole::get() as usize; + let s = ::MaxSerializedLen::get() as usize; + + let caller: T::AccountId = whitelisted_caller(); + let keeper: T::AccountId = account(ACCOUNT, 123, SEED); + let operator: T::AccountId = account(ACCOUNT, 222, SEED); + let (identity, signature) = id_with_auth::(&caller); + let identity_with_auth = IdentityWithAuth::Ecdsa(identity, signature); + + pallet_oracle::Pallet::::register_operator( + RawOrigin::Root.into(), + operator.clone() + ).unwrap(); + pallet_oracle::Pallet::::activate_operator( + RawOrigin::Signed(operator.clone()).into(), + ).unwrap(); + Guild::::register( + RawOrigin::Signed(caller.clone()).into(), + identity_with_auth, + 0, + ).unwrap(); + + let guild_name = [0u8; 32]; + let role_name = [0u8; 32]; + init_guild::(&caller, guild_name); + + let logic = vec![100u8; s]; + let req = vec![200u8; s]; + let serialized_requirements = (vec![req; r], logic); + + Guild::::create_unfiltered_role( + RawOrigin::Signed(caller.clone()).into(), + guild_name, + role_name, + serialized_requirements, + ).unwrap(); + + Guild::::join( + RawOrigin::Signed(caller.clone()).into(), + guild_name, + role_name, + None, + ).unwrap(); + + pallet_oracle::Pallet::::callback( + RawOrigin::Signed(operator).into(), + 0, + vec![1] + ).unwrap(); + + }: _(RawOrigin::Signed(keeper.clone()), caller.clone(), guild_name, role_name) + verify { + let guild_id = Guild::::guild_id(guild_name).unwrap(); + let role_id = Guild::::role_id(guild_id, role_name).unwrap(); + assert!(Guild::::member(role_id, caller).is_some()); + } + + impl_benchmark_test_suite!(Guild, crate::mock::new_test_ext(), crate::mock::TestRuntime, extra = false); +} + +fn init_guild(caller: &T::AccountId, guild_name: [u8; 32]) { + frame_system::Pallet::::set_block_number(::BlockNumber::from( + 1u32, + )); + let metadata = vec![0u8; ::MaxSerializedLen::get() as usize]; + Guild::::create_guild( + RawOrigin::Signed(caller.clone()).into(), + guild_name, + metadata, + ) + .unwrap(); +} + +fn id_with_auth(caller: &T::AccountId) -> (Identity, EcdsaSignature) { + let seed = [2u8; 32]; + gn_common::identity::test_ecdsa_id_with_auth(seed, gn_common::utils::verification_msg(caller)) +} diff --git a/gn-pallets/pallet-guild/src/benchmarking.rs b/gn-pallets/pallet-guild/src/benchmarking.rs deleted file mode 100644 index 8b137891..00000000 --- a/gn-pallets/pallet-guild/src/benchmarking.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/gn-pallets/pallet-guild/src/lib.rs b/gn-pallets/pallet-guild/src/lib.rs index 9a29f092..6dc28ef3 100644 --- a/gn-pallets/pallet-guild/src/lib.rs +++ b/gn-pallets/pallet-guild/src/lib.rs @@ -6,7 +6,7 @@ pub use pallet::*; #[cfg(feature = "runtime-benchmarks")] -mod benchmarking; +mod benchmark; #[cfg(test)] mod mock; #[cfg(test)] @@ -150,7 +150,7 @@ pub mod pallet { #[pallet::call] impl Pallet { #[pallet::call_index(0)] - #[pallet::weight(1000)] + #[pallet::weight((::WeightInfo::register(), Pays::No))] pub fn register( origin: OriginFor, identity_with_auth: IdentityWithAuth, @@ -201,7 +201,7 @@ pub mod pallet { } #[pallet::call_index(1)] - #[pallet::weight(10000000)] + #[pallet::weight((::WeightInfo::join(), Pays::No))] pub fn join( origin: OriginFor, guild_name: GuildName, @@ -284,7 +284,7 @@ pub mod pallet { } #[pallet::call_index(2)] - #[pallet::weight(10000000)] + #[pallet::weight((::WeightInfo::leave(), Pays::No))] pub fn leave( origin: OriginFor, guild_name: GuildName, @@ -298,7 +298,7 @@ pub mod pallet { } #[pallet::call_index(3)] - #[pallet::weight(10000000)] + #[pallet::weight(::WeightInfo::request_oracle_check())] pub fn request_oracle_check( origin: OriginFor, account: T::AccountId, @@ -353,7 +353,7 @@ pub mod pallet { } #[pallet::call_index(4)] - #[pallet::weight(10000000)] + #[pallet::weight((::WeightInfo::create_guild(metadata.len() as u32), Pays::No))] pub fn create_guild( origin: OriginFor, guild_name: GuildName, @@ -387,7 +387,7 @@ pub mod pallet { } #[pallet::call_index(5)] - #[pallet::weight(10000000)] + #[pallet::weight((::WeightInfo::create_free_role(), Pays::No))] pub fn create_free_role( origin: OriginFor, guild_name: GuildName, @@ -398,7 +398,14 @@ pub mod pallet { } #[pallet::call_index(6)] - #[pallet::weight(10000000)] + #[pallet::weight(( + ::WeightInfo::create_role_with_allowlist( + allowlist.len() as u32, + T::MaxReqsPerRole::get(), + T::MaxSerializedLen::get() + ), + Pays::No + ))] pub fn create_role_with_allowlist( origin: OriginFor, guild_name: GuildName, @@ -422,7 +429,13 @@ pub mod pallet { } #[pallet::call_index(7)] - #[pallet::weight(10000000)] + #[pallet::weight(( + ::WeightInfo::create_child_role( + T::MaxReqsPerRole::get(), + T::MaxSerializedLen::get() + ), + Pays::No + ))] pub fn create_child_role( origin: OriginFor, guild_name: GuildName, @@ -444,7 +457,13 @@ pub mod pallet { } #[pallet::call_index(8)] - #[pallet::weight(10000000)] + #[pallet::weight(( + ::WeightInfo::create_unfiltered_role( + requirements.0.len() as u32, + T::MaxSerializedLen::get() + ), + Pays::No + ))] pub fn create_unfiltered_role( origin: OriginFor, guild_name: GuildName, @@ -456,7 +475,7 @@ pub mod pallet { } #[pallet::call_index(9)] - #[pallet::weight(0)] + #[pallet::weight((0, DispatchClass::Operational, Pays::No))] pub fn callback(origin: OriginFor, result: SerializedData) -> DispatchResult { // NOTE this ensures that only the root can call this function via // a callback, see `frame_system::RawOrigin` diff --git a/gn-pallets/pallet-guild/src/mock.rs b/gn-pallets/pallet-guild/src/mock.rs index e2b39d9e..a3128767 100644 --- a/gn-pallets/pallet-guild/src/mock.rs +++ b/gn-pallets/pallet-guild/src/mock.rs @@ -1,6 +1,7 @@ pub use crate as pallet_guild; use frame_support::parameter_types; +use frame_support::traits::{OnFinalize, OnInitialize}; use sp_core::H256; use sp_runtime::testing::Header; use sp_runtime::traits::{BlakeTwo256, ConstU32, ConstU64, IdentityLookup}; @@ -87,6 +88,7 @@ impl pallet_guild::Config for TestRuntime { impl pallet_oracle::Config for TestRuntime { type Currency = pallet_balances::Pallet; type Callback = pallet_guild::Call; + type MaxOperators = ConstU32<10>; type MinimumFee = MinimumFee; type RuntimeEvent = RuntimeEvent; type ValidityPeriod = ValidityPeriod; @@ -94,3 +96,22 @@ impl pallet_oracle::Config for TestRuntime { } impl pallet_randomness_collective_flip::Config for TestRuntime {} + +pub fn new_test_ext() -> sp_io::TestExternalities { + let mut ext: sp_io::TestExternalities = frame_system::GenesisConfig::default() + .build_storage::() + .unwrap() + .into(); + ext.execute_with(|| { + init_chain(); + }); + ext +} + +fn init_chain() { + for i in 0..2 { + System::set_block_number(i); + >::on_initialize(i); + >::on_finalize(i); + } +} diff --git a/gn-pallets/pallet-guild/src/test/guild_and_role.rs b/gn-pallets/pallet-guild/src/test/guild_and_role.rs index 4aaf1d4f..f10b7bf5 100644 --- a/gn-pallets/pallet-guild/src/test/guild_and_role.rs +++ b/gn-pallets/pallet-guild/src/test/guild_and_role.rs @@ -4,7 +4,6 @@ use gn_common::filter::{Filter, Guild as GuildFilter, Logic as FilterLogic}; #[test] fn guild_creation() { new_test_ext().execute_with(|| { - init_chain(); let signer = 4; let guild_name = [99u8; 32]; let max_serialized_len = @@ -44,7 +43,6 @@ fn guild_creation() { #[test] fn guild_with_free_roles() { new_test_ext().execute_with(|| { - init_chain(); let signer = 1; let guild_name = [11u8; 32]; let mut role_name = [22u8; 32]; @@ -141,7 +139,6 @@ fn role_with_allowlist_filter() { let mut role_id_1 = Default::default(); ext.execute_with(|| { - init_chain(); let signer = 1; let guild_name = [11u8; 32]; let role_name_0 = [0u8; 32]; @@ -279,7 +276,6 @@ fn role_with_allowlist_filter() { #[test] fn role_with_guild_filter() { new_test_ext().execute_with(|| { - init_chain(); let signer = 1; let guild_name_0 = [0u8; 32]; let guild_name_1 = [1u8; 32]; @@ -402,7 +398,6 @@ fn role_with_guild_filter() { #[test] fn unfiltered_role() { new_test_ext().execute_with(|| { - init_chain(); let signer = 1; let guild_name = [0u8; 32]; let role_name = [2u8; 32]; diff --git a/gn-pallets/pallet-guild/src/test/helpers.rs b/gn-pallets/pallet-guild/src/test/helpers.rs index d7861781..a0ba6ce3 100644 --- a/gn-pallets/pallet-guild/src/test/helpers.rs +++ b/gn-pallets/pallet-guild/src/test/helpers.rs @@ -2,26 +2,9 @@ use super::*; use gn_common::identity::{eth_hash_message, recover_prehashed, EcdsaSignature}; use sp_core::Pair as PairT; -const STARTING_BLOCK_NUM: u64 = 2; - pub const METADATA: &[u8] = &[12u8; ::MaxSerializedLen::get() as usize]; -pub fn new_test_ext() -> sp_io::TestExternalities { - frame_system::GenesisConfig::default() - .build_storage::() - .unwrap() - .into() -} - -pub fn init_chain() { - for i in 0..STARTING_BLOCK_NUM { - System::set_block_number(i); - >::on_initialize(i); - >::on_finalize(i); - } -} - pub fn last_event() -> pallet_guild::Event { System::events() .into_iter() diff --git a/gn-pallets/pallet-guild/src/test/join_and_leave.rs b/gn-pallets/pallet-guild/src/test/join_and_leave.rs index 6db42b95..f8b2ca26 100644 --- a/gn-pallets/pallet-guild/src/test/join_and_leave.rs +++ b/gn-pallets/pallet-guild/src/test/join_and_leave.rs @@ -5,7 +5,6 @@ use gn_common::merkle::Proof as MerkleProof; #[test] fn join_and_leave_free_role() { new_test_ext().execute_with(|| { - init_chain(); let owner = 0; let user = 1; let guild_name = [0u8; 32]; @@ -87,7 +86,6 @@ fn join_and_leave_role_with_allowlist() { let mut ext = new_test_ext(); ext.execute_with(|| { - init_chain(); // user 1 registers let (address, signature) = dummy_ecdsa_id_with_auth(user_1, [1u8; 32]); allowlist.push(address); @@ -230,7 +228,6 @@ fn join_and_leave_role_with_filter() { }; new_test_ext().execute_with(|| { - init_chain(); dummy_guild(owner, g0); dummy_guild(owner, g1); ::create_free_role(RuntimeOrigin::signed(owner), g0, g0r0).unwrap(); @@ -339,7 +336,6 @@ fn join_and_leave_unfiltered_role() { let role_name = [1u8; 32]; new_test_ext().execute_with(|| { - init_chain(); let mut request_id = 0; // new guild with unfiltered role @@ -356,7 +352,8 @@ fn join_and_leave_unfiltered_role() { let role_id = ::role_id(guild_id, role_name).unwrap(); // register oracle operator - ::register_operator(RuntimeOrigin::signed(operator)).unwrap(); + ::register_operator(RuntimeOrigin::root(), operator).unwrap(); + ::activate_operator(RuntimeOrigin::signed(operator)).unwrap(); // register identity that requires oracle check ::register( RuntimeOrigin::signed(user), @@ -437,7 +434,6 @@ fn role_with_filtered_requirements() { let filter_logic_2 = FilterLogic::Or; new_test_ext().execute_with(|| { - init_chain(); let mut request_id = 0; // create guild with three roles @@ -468,8 +464,8 @@ fn role_with_filtered_requirements() { let role_id_2 = ::role_id(guild_id, role_name_2).unwrap(); // register oracle operator - ::register_operator(RuntimeOrigin::signed(operator)).unwrap(); - + ::register_operator(RuntimeOrigin::root(), operator).unwrap(); + ::activate_operator(RuntimeOrigin::signed(operator)).unwrap(); // register identity that requires oracle check ::register( RuntimeOrigin::signed(user), diff --git a/gn-pallets/pallet-guild/src/test/mod.rs b/gn-pallets/pallet-guild/src/test/mod.rs index 32538d49..b96958bb 100644 --- a/gn-pallets/pallet-guild/src/test/mod.rs +++ b/gn-pallets/pallet-guild/src/test/mod.rs @@ -8,7 +8,6 @@ use helpers::*; use crate::mock::*; type AccountId = ::AccountId; -use frame_support::traits::{OnFinalize, OnInitialize}; use gn_common::{ identity::{Identity, IdentityWithAuth}, GuildName, RequestData, @@ -20,8 +19,6 @@ use sp_runtime::DispatchError; #[test] fn callback_can_only_be_called_by_root() { new_test_ext().execute_with(|| { - init_chain(); - let register_no_access = dummy_answer( vec![u8::from(false)], 0, diff --git a/gn-pallets/pallet-guild/src/test/register.rs b/gn-pallets/pallet-guild/src/test/register.rs index efe6293c..7b9cf1c9 100644 --- a/gn-pallets/pallet-guild/src/test/register.rs +++ b/gn-pallets/pallet-guild/src/test/register.rs @@ -5,7 +5,6 @@ use sp_core::Pair as PairT; #[test] fn unsuccessful_registrations() { new_test_ext().execute_with(|| { - init_chain(); let user = 0; let max_identities = ::MaxIdentities::get(); @@ -40,7 +39,7 @@ fn unsuccessful_registrations() { IdentityWithAuth::Other(Identity::Other([0u8; 64]), [0u8; 64]), max_identities - 1, ), - "NoRegisteredOperators", + "NoActiveOperators", ), ( ::register( @@ -97,7 +96,6 @@ fn unsuccessful_registrations() { #[test] fn successful_on_chain_registrations() { new_test_ext().execute_with(|| { - init_chain(); let user = 1; let mut index = 0; @@ -156,7 +154,6 @@ fn successful_on_chain_registrations() { #[test] fn successful_off_chain_registrations() { new_test_ext().execute_with(|| { - init_chain(); let operator = 0; let user = 1; let id_zero = Identity::Other([0u8; 64]); @@ -167,7 +164,8 @@ fn successful_off_chain_registrations() { let id_auth_one = IdentityWithAuth::Other(id_one, auth); // register an operator first - ::register_operator(RuntimeOrigin::signed(operator)).unwrap(); + ::register_operator(RuntimeOrigin::root(), operator).unwrap(); + ::activate_operator(RuntimeOrigin::signed(operator)).unwrap(); // user registers id that requires off-chain verification ::register(RuntimeOrigin::signed(user), id_auth_zero, index).unwrap(); // pallet receives a dummy oracle answer @@ -209,7 +207,6 @@ fn successful_off_chain_registrations() { #[test] fn successful_idenity_overrides() { new_test_ext().execute_with(|| { - init_chain(); let operator = 0; let user = 2; let seed = [12u8; 32]; @@ -223,8 +220,8 @@ fn successful_idenity_overrides() { let index = 1; // register an operator first - ::register_operator(RuntimeOrigin::signed(operator)).unwrap(); - + ::register_operator(RuntimeOrigin::root(), operator).unwrap(); + ::activate_operator(RuntimeOrigin::signed(operator)).unwrap(); // user registers an off-chain-verified identity let identity_with_auth = IdentityWithAuth::Other(id_zero, auth); let request_data: RequestData = RequestData::Register { diff --git a/gn-pallets/pallet-guild/src/weights.rs b/gn-pallets/pallet-guild/src/weights.rs index 7995a0dd..709e1432 100644 --- a/gn-pallets/pallet-guild/src/weights.rs +++ b/gn-pallets/pallet-guild/src/weights.rs @@ -1,29 +1,14 @@ -// This file is part of Substrate. -// Copyright (C) 2022 Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// 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. - -//! Autogenerated weights for pallet_guild +//! Autogenerated weights for `pallet_guild` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-27, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! HOSTNAME: `turbineblade`, CPU: `AMD Ryzen 5 3600 6-Core Processor` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 19.0.0 +//! DATE: 2023-02-22, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `razorblade`, CPU: `Intel(R) Core(TM) i5-10210U CPU @ 1.60GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/release/node-template +// ./target/release/gn-node // benchmark // pallet // --chain @@ -38,10 +23,8 @@ // 50 // --repeat // 20 -// --template -// frame-weight-template.hbs // --output -// ./pallets/pallet-guild/src/weights.rs +// ./gn-pallets/pallet-guild/src/weights.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,63 +33,414 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use sp_std::marker::PhantomData; -/// Weight functions needed for pallet_guild. pub trait WeightInfo { - fn create_guild(r: u64, ) -> Weight; - fn join_guild() -> Weight; + fn register() -> Weight; + fn create_guild(n: u32, ) -> Weight; + fn create_free_role() -> Weight; + fn create_role_with_allowlist(n: u32, r: u32, _s: u32, ) -> Weight; + fn create_child_role(r: u32, s: u32, ) -> Weight; + fn create_unfiltered_role(r: u32, s: u32, ) -> Weight; + fn join() -> Weight; + fn leave() -> Weight; + fn request_oracle_check() -> Weight; } -/// Weights for pallet_guild using the Substrate node and recommended hardware. +/// Weight functions for `pallet_guild`. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - // Storage: Guild Guilds (r:1 w:1) - // Storage: Guild Roles (r:0 w:2) - /// The range of component `r` is `[0, 100]`. - fn create_guild(r: u64, ) -> Weight { - Weight::from_parts(19_413_000, 19_413_000) - // Standard Error: 3_000 - .saturating_add(Weight::from_parts(2_651_000, 2_651_000).saturating_mul(r)) - .saturating_add(T::DbWeight::get().reads(1)) + /// Storage: Guild UserData (r:0 w:1) + /// Proof Skipped: Guild UserData (max_values: None, max_size: None, mode: Measured) + fn register() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 369_767 nanoseconds. + Weight::from_ref_time(392_263_000) .saturating_add(T::DbWeight::get().writes(1)) - .saturating_add(T::DbWeight::get().writes(r)) - } - // Storage: Guild Roles (r:1 w:0) - // Storage: Guild NextRequestIdentifier (r:1 w:1) - // Storage: Chainlink Operators (r:1 w:0) - // Storage: Chainlink NextOperator (r:1 w:1) - // Storage: Chainlink NextRequestIdentifier (r:1 w:1) - // Storage: Guild JoinRequests (r:0 w:1) - // Storage: Chainlink Requests (r:0 w:1) - fn join_guild() -> Weight { - Weight::from_parts(53_270_000, 53_270_000) + } + /// Storage: Guild GuildIdMap (r:1 w:1) + /// Proof Skipped: Guild GuildIdMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild Nonce (r:1 w:1) + /// Proof Skipped: Guild Nonce (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) + /// Proof: RandomnessCollectiveFlip RandomMaterial (max_values: Some(1), max_size: Some(2594), added: 3089, mode: MaxEncodedLen) + /// Storage: Guild Guilds (r:0 w:1) + /// Proof Skipped: Guild Guilds (max_values: None, max_size: None, mode: Measured) + /// The range of component `n` is `[0, 256]`. + fn create_guild(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `115` + // Estimated: `6404` + // Minimum execution time: 26_721 nanoseconds. + Weight::from_parts(39_154_463, 6404) + // Standard Error: 3_905 + .saturating_add(Weight::from_ref_time(2_434).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: Guild GuildIdMap (r:1 w:0) + /// Proof Skipped: Guild GuildIdMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild RoleIdMap (r:1 w:1) + /// Proof Skipped: Guild RoleIdMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild Guilds (r:1 w:1) + /// Proof Skipped: Guild Guilds (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild Nonce (r:1 w:1) + /// Proof Skipped: Guild Nonce (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) + /// Proof: RandomnessCollectiveFlip RandomMaterial (max_values: Some(1), max_size: Some(2594), added: 3089, mode: MaxEncodedLen) + /// Storage: Guild Roles (r:0 w:1) + /// Proof Skipped: Guild Roles (max_values: None, max_size: None, mode: Measured) + fn create_free_role() -> Weight { + // Proof Size summary in bytes: + // Measured: `678` + // Estimated: `14399` + // Minimum execution time: 46_699 nanoseconds. + Weight::from_parts(52_729_000, 14399) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: Guild GuildIdMap (r:1 w:0) + /// Proof Skipped: Guild GuildIdMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild RoleIdMap (r:1 w:1) + /// Proof Skipped: Guild RoleIdMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild Guilds (r:1 w:1) + /// Proof Skipped: Guild Guilds (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild Nonce (r:1 w:1) + /// Proof Skipped: Guild Nonce (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) + /// Proof: RandomnessCollectiveFlip RandomMaterial (max_values: Some(1), max_size: Some(2594), added: 3089, mode: MaxEncodedLen) + /// Storage: Guild Roles (r:0 w:1) + /// Proof Skipped: Guild Roles (max_values: None, max_size: None, mode: Measured) + /// The range of component `n` is `[1, 128]`. + /// The range of component `r` is `[0, 10]`. + /// The range of component `s` is `[0, 256]`. + fn create_role_with_allowlist(n: u32, r: u32, _s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `678` + // Estimated: `14399` + // Minimum execution time: 77_201 nanoseconds. + Weight::from_parts(85_825_100, 14399) + // Standard Error: 32_487 + .saturating_add(Weight::from_ref_time(1_613_995).saturating_mul(n.into())) + // Standard Error: 392_769 + .saturating_add(Weight::from_ref_time(514_801).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: Guild GuildIdMap (r:1 w:0) + /// Proof Skipped: Guild GuildIdMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild RoleIdMap (r:2 w:1) + /// Proof Skipped: Guild RoleIdMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild Guilds (r:1 w:1) + /// Proof Skipped: Guild Guilds (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild Nonce (r:1 w:1) + /// Proof Skipped: Guild Nonce (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) + /// Proof: RandomnessCollectiveFlip RandomMaterial (max_values: Some(1), max_size: Some(2594), added: 3089, mode: MaxEncodedLen) + /// Storage: Guild Roles (r:0 w:1) + /// Proof Skipped: Guild Roles (max_values: None, max_size: None, mode: Measured) + /// The range of component `r` is `[0, 10]`. + /// The range of component `s` is `[0, 256]`. + fn create_child_role(r: u32, s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `894` + // Estimated: `17954` + // Minimum execution time: 53_095 nanoseconds. + Weight::from_parts(46_540_343, 17954) + // Standard Error: 138_192 + .saturating_add(Weight::from_ref_time(2_136_397).saturating_mul(r.into())) + // Standard Error: 5_670 + .saturating_add(Weight::from_ref_time(52_708).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: Guild GuildIdMap (r:1 w:0) + /// Proof Skipped: Guild GuildIdMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild RoleIdMap (r:1 w:1) + /// Proof Skipped: Guild RoleIdMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild Guilds (r:1 w:1) + /// Proof Skipped: Guild Guilds (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild Nonce (r:1 w:1) + /// Proof Skipped: Guild Nonce (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) + /// Proof: RandomnessCollectiveFlip RandomMaterial (max_values: Some(1), max_size: Some(2594), added: 3089, mode: MaxEncodedLen) + /// Storage: Guild Roles (r:0 w:1) + /// Proof Skipped: Guild Roles (max_values: None, max_size: None, mode: Measured) + /// The range of component `r` is `[0, 10]`. + /// The range of component `s` is `[0, 256]`. + fn create_unfiltered_role(r: u32, s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `678` + // Estimated: `14399` + // Minimum execution time: 44_245 nanoseconds. + Weight::from_parts(55_627_418, 14399) + // Standard Error: 119_983 + .saturating_add(Weight::from_ref_time(266_588).saturating_mul(r.into())) + // Standard Error: 4_923 + .saturating_add(Weight::from_ref_time(20_540).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: Guild GuildIdMap (r:1 w:0) + /// Proof Skipped: Guild GuildIdMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild RoleIdMap (r:1 w:0) + /// Proof Skipped: Guild RoleIdMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild UserData (r:2 w:0) + /// Proof Skipped: Guild UserData (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild Roles (r:1 w:0) + /// Proof Skipped: Guild Roles (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild Members (r:0 w:1) + /// Proof Skipped: Guild Members (max_values: None, max_size: None, mode: Measured) + fn join() -> Weight { + // Proof Size summary in bytes: + // Measured: `656` + // Estimated: `15655` + // Minimum execution time: 54_580 nanoseconds. + Weight::from_parts(61_062_000, 15655) .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(5)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Guild GuildIdMap (r:1 w:0) + /// Proof Skipped: Guild GuildIdMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild RoleIdMap (r:1 w:0) + /// Proof Skipped: Guild RoleIdMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild UserData (r:1 w:0) + /// Proof Skipped: Guild UserData (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild Members (r:0 w:1) + /// Proof Skipped: Guild Members (max_values: None, max_size: None, mode: Measured) + fn leave() -> Weight { + // Proof Size summary in bytes: + // Measured: `579` + // Estimated: `9741` + // Minimum execution time: 35_492 nanoseconds. + Weight::from_parts(36_401_000, 9741) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Guild GuildIdMap (r:1 w:0) + /// Proof Skipped: Guild GuildIdMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild RoleIdMap (r:1 w:0) + /// Proof Skipped: Guild RoleIdMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild UserData (r:1 w:0) + /// Proof Skipped: Guild UserData (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild Members (r:1 w:0) + /// Proof Skipped: Guild Members (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild Roles (r:1 w:0) + /// Proof Skipped: Guild Roles (max_values: None, max_size: None, mode: Measured) + /// Storage: Oracle ActiveOperators (r:1 w:0) + /// Proof Skipped: Oracle ActiveOperators (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Oracle NextOperator (r:1 w:1) + /// Proof Skipped: Oracle NextOperator (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Oracle NextRequestIdentifier (r:1 w:1) + /// Proof Skipped: Oracle NextRequestIdentifier (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Oracle Requests (r:0 w:1) + /// Proof Skipped: Oracle Requests (max_values: None, max_size: None, mode: Measured) + fn request_oracle_check() -> Weight { + // Proof Size summary in bytes: + // Measured: `3784` + // Estimated: `47916` + // Minimum execution time: 69_099 nanoseconds. + Weight::from_parts(78_144_000, 47916) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(3)) } } -// For backwards compatibility and tests impl WeightInfo for () { - // Storage: Guild Guilds (r:1 w:1) - // Storage: Guild Roles (r:0 w:2) - /// The range of component `r` is `[0, 100]`. - fn create_guild(r: u64, ) -> Weight { - Weight::from_parts(19_413_000, 19_413_000) - // Standard Error: 3_000 - .saturating_add(Weight::from_parts(2_651_000, 2_651_000).saturating_mul(r)) - .saturating_add(RocksDbWeight::get().reads(1)) + /// Storage: Guild UserData (r:0 w:1) + /// Proof Skipped: Guild UserData (max_values: None, max_size: None, mode: Measured) + fn register() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 369_767 nanoseconds. + Weight::from_ref_time(392_263_000) .saturating_add(RocksDbWeight::get().writes(1)) - .saturating_add(RocksDbWeight::get().writes(r)) - } - // Storage: Guild Roles (r:1 w:0) - // Storage: Guild NextRequestIdentifier (r:1 w:1) - // Storage: Chainlink Operators (r:1 w:0) - // Storage: Chainlink NextOperator (r:1 w:1) - // Storage: Chainlink NextRequestIdentifier (r:1 w:1) - // Storage: Guild JoinRequests (r:0 w:1) - // Storage: Chainlink Requests (r:0 w:1) - fn join_guild() -> Weight { - Weight::from_parts(53_270_000, 53_270_000) + } + /// Storage: Guild GuildIdMap (r:1 w:1) + /// Proof Skipped: Guild GuildIdMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild Nonce (r:1 w:1) + /// Proof Skipped: Guild Nonce (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) + /// Proof: RandomnessCollectiveFlip RandomMaterial (max_values: Some(1), max_size: Some(2594), added: 3089, mode: MaxEncodedLen) + /// Storage: Guild Guilds (r:0 w:1) + /// Proof Skipped: Guild Guilds (max_values: None, max_size: None, mode: Measured) + /// The range of component `n` is `[0, 256]`. + fn create_guild(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `115` + // Estimated: `6404` + // Minimum execution time: 26_721 nanoseconds. + Weight::from_parts(39_154_463, 6404) + // Standard Error: 3_905 + .saturating_add(Weight::from_ref_time(2_434).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(3)) + .saturating_add(RocksDbWeight::get().writes(3)) + } + /// Storage: Guild GuildIdMap (r:1 w:0) + /// Proof Skipped: Guild GuildIdMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild RoleIdMap (r:1 w:1) + /// Proof Skipped: Guild RoleIdMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild Guilds (r:1 w:1) + /// Proof Skipped: Guild Guilds (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild Nonce (r:1 w:1) + /// Proof Skipped: Guild Nonce (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) + /// Proof: RandomnessCollectiveFlip RandomMaterial (max_values: Some(1), max_size: Some(2594), added: 3089, mode: MaxEncodedLen) + /// Storage: Guild Roles (r:0 w:1) + /// Proof Skipped: Guild Roles (max_values: None, max_size: None, mode: Measured) + fn create_free_role() -> Weight { + // Proof Size summary in bytes: + // Measured: `678` + // Estimated: `14399` + // Minimum execution time: 46_699 nanoseconds. + Weight::from_parts(52_729_000, 14399) + .saturating_add(RocksDbWeight::get().reads(5)) + .saturating_add(RocksDbWeight::get().writes(4)) + } + /// Storage: Guild GuildIdMap (r:1 w:0) + /// Proof Skipped: Guild GuildIdMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild RoleIdMap (r:1 w:1) + /// Proof Skipped: Guild RoleIdMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild Guilds (r:1 w:1) + /// Proof Skipped: Guild Guilds (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild Nonce (r:1 w:1) + /// Proof Skipped: Guild Nonce (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) + /// Proof: RandomnessCollectiveFlip RandomMaterial (max_values: Some(1), max_size: Some(2594), added: 3089, mode: MaxEncodedLen) + /// Storage: Guild Roles (r:0 w:1) + /// Proof Skipped: Guild Roles (max_values: None, max_size: None, mode: Measured) + /// The range of component `n` is `[1, 128]`. + /// The range of component `r` is `[0, 10]`. + /// The range of component `s` is `[0, 256]`. + fn create_role_with_allowlist(n: u32, r: u32, _s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `678` + // Estimated: `14399` + // Minimum execution time: 77_201 nanoseconds. + Weight::from_parts(85_825_100, 14399) + // Standard Error: 32_487 + .saturating_add(Weight::from_ref_time(1_613_995).saturating_mul(n.into())) + // Standard Error: 392_769 + .saturating_add(Weight::from_ref_time(514_801).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(5)) + .saturating_add(RocksDbWeight::get().writes(4)) + } + /// Storage: Guild GuildIdMap (r:1 w:0) + /// Proof Skipped: Guild GuildIdMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild RoleIdMap (r:2 w:1) + /// Proof Skipped: Guild RoleIdMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild Guilds (r:1 w:1) + /// Proof Skipped: Guild Guilds (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild Nonce (r:1 w:1) + /// Proof Skipped: Guild Nonce (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) + /// Proof: RandomnessCollectiveFlip RandomMaterial (max_values: Some(1), max_size: Some(2594), added: 3089, mode: MaxEncodedLen) + /// Storage: Guild Roles (r:0 w:1) + /// Proof Skipped: Guild Roles (max_values: None, max_size: None, mode: Measured) + /// The range of component `r` is `[0, 10]`. + /// The range of component `s` is `[0, 256]`. + fn create_child_role(r: u32, s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `894` + // Estimated: `17954` + // Minimum execution time: 53_095 nanoseconds. + Weight::from_parts(46_540_343, 17954) + // Standard Error: 138_192 + .saturating_add(Weight::from_ref_time(2_136_397).saturating_mul(r.into())) + // Standard Error: 5_670 + .saturating_add(Weight::from_ref_time(52_708).saturating_mul(s.into())) + .saturating_add(RocksDbWeight::get().reads(6)) + .saturating_add(RocksDbWeight::get().writes(4)) + } + /// Storage: Guild GuildIdMap (r:1 w:0) + /// Proof Skipped: Guild GuildIdMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild RoleIdMap (r:1 w:1) + /// Proof Skipped: Guild RoleIdMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild Guilds (r:1 w:1) + /// Proof Skipped: Guild Guilds (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild Nonce (r:1 w:1) + /// Proof Skipped: Guild Nonce (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) + /// Proof: RandomnessCollectiveFlip RandomMaterial (max_values: Some(1), max_size: Some(2594), added: 3089, mode: MaxEncodedLen) + /// Storage: Guild Roles (r:0 w:1) + /// Proof Skipped: Guild Roles (max_values: None, max_size: None, mode: Measured) + /// The range of component `r` is `[0, 10]`. + /// The range of component `s` is `[0, 256]`. + fn create_unfiltered_role(r: u32, s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `678` + // Estimated: `14399` + // Minimum execution time: 44_245 nanoseconds. + Weight::from_parts(55_627_418, 14399) + // Standard Error: 119_983 + .saturating_add(Weight::from_ref_time(266_588).saturating_mul(r.into())) + // Standard Error: 4_923 + .saturating_add(Weight::from_ref_time(20_540).saturating_mul(s.into())) + .saturating_add(RocksDbWeight::get().reads(5)) + .saturating_add(RocksDbWeight::get().writes(4)) + } + /// Storage: Guild GuildIdMap (r:1 w:0) + /// Proof Skipped: Guild GuildIdMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild RoleIdMap (r:1 w:0) + /// Proof Skipped: Guild RoleIdMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild UserData (r:2 w:0) + /// Proof Skipped: Guild UserData (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild Roles (r:1 w:0) + /// Proof Skipped: Guild Roles (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild Members (r:0 w:1) + /// Proof Skipped: Guild Members (max_values: None, max_size: None, mode: Measured) + fn join() -> Weight { + // Proof Size summary in bytes: + // Measured: `656` + // Estimated: `15655` + // Minimum execution time: 54_580 nanoseconds. + Weight::from_parts(61_062_000, 15655) .saturating_add(RocksDbWeight::get().reads(5)) - .saturating_add(RocksDbWeight::get().writes(5)) + .saturating_add(RocksDbWeight::get().writes(1)) + } + /// Storage: Guild GuildIdMap (r:1 w:0) + /// Proof Skipped: Guild GuildIdMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild RoleIdMap (r:1 w:0) + /// Proof Skipped: Guild RoleIdMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild UserData (r:1 w:0) + /// Proof Skipped: Guild UserData (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild Members (r:0 w:1) + /// Proof Skipped: Guild Members (max_values: None, max_size: None, mode: Measured) + fn leave() -> Weight { + // Proof Size summary in bytes: + // Measured: `579` + // Estimated: `9741` + // Minimum execution time: 35_492 nanoseconds. + Weight::from_parts(36_401_000, 9741) + .saturating_add(RocksDbWeight::get().reads(3)) + .saturating_add(RocksDbWeight::get().writes(1)) + } + /// Storage: Guild GuildIdMap (r:1 w:0) + /// Proof Skipped: Guild GuildIdMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild RoleIdMap (r:1 w:0) + /// Proof Skipped: Guild RoleIdMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild UserData (r:1 w:0) + /// Proof Skipped: Guild UserData (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild Members (r:1 w:0) + /// Proof Skipped: Guild Members (max_values: None, max_size: None, mode: Measured) + /// Storage: Guild Roles (r:1 w:0) + /// Proof Skipped: Guild Roles (max_values: None, max_size: None, mode: Measured) + /// Storage: Oracle ActiveOperators (r:1 w:0) + /// Proof Skipped: Oracle ActiveOperators (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Oracle NextOperator (r:1 w:1) + /// Proof Skipped: Oracle NextOperator (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Oracle NextRequestIdentifier (r:1 w:1) + /// Proof Skipped: Oracle NextRequestIdentifier (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Oracle Requests (r:0 w:1) + /// Proof Skipped: Oracle Requests (max_values: None, max_size: None, mode: Measured) + fn request_oracle_check() -> Weight { + // Proof Size summary in bytes: + // Measured: `3784` + // Estimated: `47916` + // Minimum execution time: 69_099 nanoseconds. + Weight::from_parts(78_144_000, 47916) + .saturating_add(RocksDbWeight::get().reads(8)) + .saturating_add(RocksDbWeight::get().writes(3)) } } diff --git a/gn-pallets/pallet-oracle/Cargo.toml b/gn-pallets/pallet-oracle/Cargo.toml index 3de19f2b..f56326da 100644 --- a/gn-pallets/pallet-oracle/Cargo.toml +++ b/gn-pallets/pallet-oracle/Cargo.toml @@ -3,16 +3,16 @@ edition = "2021" name = "pallet-oracle" version = "0.0.0-alpha" -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - [features] default = ["std"] -runtime-benchmarks = [] +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", +] std = [ "gn-common/std", "parity-scale-codec/std", "scale-info/std", + "frame-benchmarking?/std", "frame-support/std", "frame-system/std", "sp-std/std", @@ -27,8 +27,11 @@ gn-common = { version = "0.0.0-alpha", path = "../../gn-common", default-feature parity-scale-codec = { workspace = true, features = ["derive"] } scale-info = { workspace = true, features = ["derive"] } +# substrate pallets +pallet-balances = { workspace = true, optional = true } + # substrate frame -#frame-benchmarking = { workspace = true, optional = true } +frame-benchmarking = { workspace = true, optional = true } frame-support = { workspace = true } frame-system = { workspace = true } diff --git a/gn-pallets/pallet-oracle/src/benchmark.rs b/gn-pallets/pallet-oracle/src/benchmark.rs new file mode 100644 index 00000000..3e230c11 --- /dev/null +++ b/gn-pallets/pallet-oracle/src/benchmark.rs @@ -0,0 +1,122 @@ +use super::*; +use crate::Pallet as Oracle; + +use frame_benchmarking::{account, benchmarks, whitelisted_caller}; +use frame_support::dispatch::{ + DispatchResultWithPostInfo, PostDispatchInfo, UnfilteredDispatchable, +}; +use frame_support::pallet_prelude::Pays; +use frame_support::traits::{Currency, Get}; +use frame_system::RawOrigin; +use parity_scale_codec::{Decode, Encode, EncodeLike}; +use scale_info::TypeInfo; +use sp_std::{vec, vec::Vec}; + +const ACCOUNT: &str = "operator"; +const SEED: u32 = 999; + +benchmarks! { + register_operator { + let max_operators = ::MaxOperators::get(); + let n in 1 .. ::MaxOperators::get() - 1 => register_operators::(n); + let operator: T::AccountId = account(ACCOUNT, max_operators - 1, SEED); + }: _(RawOrigin::Root, operator.clone()) + verify { + assert!(Oracle::::operator(operator).is_some()); + } + deregister_operator { + let max_operators = ::MaxOperators::get(); + let n in 1 .. ::MaxOperators::get() - 1; + let operators = register_operators::(n); + }: _(RawOrigin::Root, operators[0].clone()) + verify { + assert!(Oracle::::operator(operators[0].clone()).is_none()); + } + activate_operator { + let n in 1 .. ::MaxOperators::get(); + let mut operators = register_operators::(n); + for operator in operators.iter().skip(1) { + Oracle::::activate_operator(RawOrigin::Signed(operator.clone()).into()).unwrap(); + } + }: _(RawOrigin::Signed(operators[0].clone())) + verify { + operators.sort(); + assert_eq!(Oracle::::active_operators(), operators); + } + deactivate_operator { + let n in 1 .. ::MaxOperators::get(); + let operators = register_operators::(n); + for operator in &operators { + Oracle::::activate_operator(RawOrigin::Signed(operator.clone()).into()).unwrap(); + } + }: _(RawOrigin::Signed(operators[0].clone())) + verify { + assert!(!Oracle::::active_operators().contains(&operators[0])); + } + initiate_request { + let n in 50 .. 1000; + let caller: T::AccountId = whitelisted_caller(); + let operator: T::AccountId = account(ACCOUNT, 1, SEED); + + T::Currency::make_free_balance_be( + &caller, + >::Balance::from(100u32) + ); + + Oracle::::register_operator(RawOrigin::Root.into(), operator.clone())?; + Oracle::::activate_operator(RawOrigin::Signed(operator).into())?; + + let data = vec![128; n as usize]; + let fee = T::Currency::minimum_balance(); + let callback = MockCallback::::test(); + }: _(RawOrigin::Signed(caller), callback, data, fee) + verify { + assert_eq!(Oracle::::request_identifier(), 1); + assert_eq!(Oracle::::next_operator(), 1); + } + + impl_benchmark_test_suite!(Oracle, crate::mock::new_test_ext(), crate::mock::TestRuntime, extra = false); +} + +fn register_operators(n: u32) -> Vec { + let operators: Vec = (0..n).map(|i| account(ACCOUNT, i, SEED)).collect(); + + for operator in &operators { + Oracle::::register_operator(RawOrigin::Root.into(), operator.clone()).unwrap(); + } + + operators +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeInfo, Encode, Decode)] +pub struct MockCallback(pub core::marker::PhantomData); + +impl EncodeLike<()> for MockCallback {} + +impl CallbackWithParameter for MockCallback { + fn with_result(&self, result: Vec) -> Option { + if result == [0, 0] { + None + } else { + Some(Self(core::marker::PhantomData)) + } + } +} + +impl UnfilteredDispatchable for MockCallback { + type RuntimeOrigin = ::RuntimeOrigin; + fn dispatch_bypass_filter(self, _origin: Self::RuntimeOrigin) -> DispatchResultWithPostInfo { + Ok(PostDispatchInfo { + actual_weight: None, + pays_fee: Pays::No, + }) + } +} + +impl MockCallback { + pub fn test() -> ::Callback { + let mut enc = vec![9]; + enc.extend(vec![1u8, 2, 3].encode()); + Decode::decode(&mut &enc[..]).unwrap() + } +} diff --git a/gn-pallets/pallet-oracle/src/benchmarking.rs b/gn-pallets/pallet-oracle/src/benchmarking.rs deleted file mode 100644 index 8b137891..00000000 --- a/gn-pallets/pallet-oracle/src/benchmarking.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/gn-pallets/pallet-oracle/src/lib.rs b/gn-pallets/pallet-oracle/src/lib.rs index ad2eeffb..b0d14858 100644 --- a/gn-pallets/pallet-oracle/src/lib.rs +++ b/gn-pallets/pallet-oracle/src/lib.rs @@ -20,12 +20,12 @@ #![deny(unused_crate_dependencies)] #[cfg(feature = "runtime-benchmarks")] -mod benchmarking; +mod benchmark; #[cfg(test)] mod mock; #[cfg(test)] mod test; -mod weights; +pub mod weights; pub use pallet::*; @@ -58,6 +58,8 @@ pub mod pallet { // Period during which a request is valid #[pallet::constant] type ValidityPeriod: Get; + #[pallet::constant] + type MaxOperators: Get; type WeightInfo: WeightInfo; } @@ -73,10 +75,12 @@ pub mod pallet { #[pallet::error] pub enum Error { - /// No oracle operator has registered yet - NoRegisteredOperators, + /// No oracle operator has been activated yet + NoActiveOperators, /// An operator is already registered. OperatorAlreadyRegistered, + /// An operator is already activated. + OperatorAlreadyActivated, /// Callback cannot be deserialized UnknownCallback, /// Manipulating an unknown operator @@ -89,6 +93,8 @@ pub mod pallet { InsufficientFee, /// Reserved balance is less than the specified fee for the request InsufficientReservedBalance, + /// Max allowed number of operators already registered + MaxOperatorsRegistered, } #[pallet::event] @@ -108,10 +114,14 @@ pub mod pallet { fee: BalanceOf, result: SpVec, }, - /// A new operator has been registered + /// A new operator has been registered by the root OperatorRegistered(T::AccountId), - /// An existing operator has been unregistered + /// An existing operator has been deregistered by the root OperatorDeregistered(T::AccountId), + /// A registered operator has been activated + OperatorActivated(T::AccountId), + /// A registered operator has been deactivated + OperatorDeactivated(T::AccountId), /// A request didn't receive any result in time KillRequest(RequestIdentifier), KillRequestFailed(RequestIdentifier), @@ -126,8 +136,17 @@ pub mod pallet { /// an operator registers/deregisters. However, these events are /// anticipated to be much less frequent than user request events. #[pallet::storage] - #[pallet::getter(fn operators)] - pub type Operators = StorageValue<_, SpVec, ValueQuery>; + #[pallet::getter(fn operator)] + pub type RegisteredOperators = + StorageMap<_, Blake2_128Concat, T::AccountId, (), OptionQuery>; + + #[pallet::storage] + #[pallet::getter(fn num_registered_operators)] + pub type NumRegisteredOperators = StorageValue<_, u32, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn active_operators)] + pub type ActiveOperators = StorageValue<_, SpVec, ValueQuery>; #[pallet::storage] #[pallet::getter(fn request_identifier)] @@ -173,34 +192,83 @@ pub mod pallet { #[pallet::call] impl Pallet { /// Register a new Operator. - /// - /// Fails with `OperatorAlreadyRegistered` if this Operator (identified - /// by `origin`) has already been registered. #[pallet::call_index(0)] - #[pallet::weight(T::WeightInfo::register_operator())] - pub fn register_operator(origin: OriginFor) -> DispatchResult { - let who: ::AccountId = ensure_signed(origin)?; + #[pallet::weight(T::WeightInfo::register_operator(T::MaxOperators::get()))] + pub fn register_operator(origin: OriginFor, operator: T::AccountId) -> DispatchResult { + ensure_root(origin)?; + + ensure!( + Self::num_registered_operators() < T::MaxOperators::get(), + Error::::MaxOperatorsRegistered + ); + + ensure!( + !RegisteredOperators::::contains_key(&operator), + Error::::OperatorAlreadyRegistered + ); + + RegisteredOperators::::insert(&operator, ()); + NumRegisteredOperators::::mutate(|val| *val += 1); + Self::deposit_event(Event::OperatorRegistered(operator)); + Ok(()) + } + + /// Deregisters an already registered Operator + #[pallet::call_index(1)] + #[pallet::weight(T::WeightInfo::deregister_operator(T::MaxOperators::get()))] + pub fn deregister_operator(origin: OriginFor, operator: T::AccountId) -> DispatchResult { + ensure_root(origin)?; + + ensure!( + RegisteredOperators::::take(&operator).is_some(), + Error::::UnknownOperator + ); - Operators::::try_mutate(|operators| { - if operators.binary_search(&who).is_ok() { - Err(Error::::OperatorAlreadyRegistered.into()) + ActiveOperators::::mutate(|operators| { + if let Ok(index) = operators.binary_search(&operator) { + operators.remove(index); + } + }); + + NumRegisteredOperators::::mutate(|val| *val -= 1); + Self::deposit_event(Event::OperatorDeregistered(operator)); + Ok(()) + } + + #[pallet::call_index(2)] + #[pallet::weight((T::WeightInfo::activate_operator(T::MaxOperators::get()), Pays::No))] + pub fn activate_operator(origin: OriginFor) -> DispatchResult { + let operator = ensure_signed(origin)?; + + ensure!( + RegisteredOperators::::contains_key(&operator), + Error::::UnknownOperator + ); + + ActiveOperators::::try_mutate(|operators| { + if operators.binary_search(&operator).is_ok() { + Err(Error::::OperatorAlreadyActivated.into()) } else { - operators.push(who.clone()); - Self::deposit_event(Event::OperatorRegistered(who)); + operators.push(operator.clone()); + operators.sort(); // needed for binary search + Self::deposit_event(Event::OperatorActivated(operator)); Ok(()) } }) } - /// Deregisters an already registered Operator - #[pallet::call_index(1)] - #[pallet::weight(T::WeightInfo::deregister_operator())] - pub fn deregister_operator(origin: OriginFor) -> DispatchResult { - let who: ::AccountId = ensure_signed(origin)?; - - Operators::::try_mutate(|operators| { - if let Ok(index) = operators.binary_search(&who) { - Self::deposit_event(Event::OperatorDeregistered(operators.remove(index))); + #[pallet::call_index(3)] + #[pallet::weight((T::WeightInfo::deactivate_operator(T::MaxOperators::get()), Pays::No))] + pub fn deactivate_operator(origin: OriginFor) -> DispatchResult { + let operator = ensure_signed(origin)?; + ensure!( + RegisteredOperators::::contains_key(&operator), + Error::::UnknownOperator + ); + ActiveOperators::::try_mutate(|operators| { + if let Ok(index) = operators.binary_search(&operator) { + operators.remove(index); + Self::deposit_event(Event::OperatorDeactivated(operator)); Ok(()) } else { Err(Error::::UnknownOperator.into()) @@ -220,20 +288,19 @@ pub mod pallet { /// to listen to `OracleRequest` events. This event contains all the /// required information to perform the request and provide back /// the result. - // TODO check weight - #[pallet::call_index(2)] - #[pallet::weight(50_000)] + #[pallet::call_index(4)] + #[pallet::weight((T::WeightInfo::initiate_request(data.len() as u32), Pays::No))] pub fn initiate_request( origin: OriginFor, callback: ::Callback, data: Vec, fee: BalanceOf, ) -> DispatchResult { - let who: ::AccountId = ensure_signed(origin)?; + let requester = ensure_signed(origin)?; - let operators = Operators::::get(); + let operators = ActiveOperators::::get(); if operators.is_empty() { - return Err(Error::::NoRegisteredOperators.into()); + return Err(Error::::NoActiveOperators.into()); } let next_operator = NextOperator::::get(); let operator = operators[next_operator as usize % operators.len()].clone(); @@ -246,7 +313,7 @@ pub mod pallet { // amount of fee is a good idea to disincentivize spam requests ensure!(fee >= T::MinimumFee::get(), Error::::InsufficientFee); - T::Currency::reserve(&who, fee)?; + T::Currency::reserve(&requester, fee)?; let request_id = NextRequestIdentifier::::get(); // Using `wrapping_add` to start at 0 when it reaches `u64::max_value()`. @@ -260,7 +327,7 @@ pub mod pallet { let now = frame_system::Pallet::::block_number(); let request = OracleRequest:: { - requester: who, + requester, operator: operator.clone(), callback: callback.clone(), data, @@ -285,23 +352,17 @@ pub mod pallet { /// back the result. Result is then dispatched back to the originator's /// callback. The fee reserved during `initiate_request` is transferred /// as soon as this callback is called. - //TODO check weight - #[pallet::call_index(3)] - #[pallet::weight(50_000)] + #[pallet::call_index(5)] + #[pallet::weight((0, DispatchClass::Operational, Pays::No))] pub fn callback( origin: OriginFor, request_id: RequestIdentifier, result: Vec, ) -> DispatchResult { - let who: ::AccountId = ensure_signed(origin)?; + let signer = ensure_signed(origin)?; - ensure!( - Requests::::contains_key(request_id), - Error::::UnknownRequest - ); - // Unwrap is fine here because we check its existence in the previous line - let request = Requests::::get(request_id).unwrap(); - ensure!(request.operator == who, Error::::WrongOperator); + let request = Requests::::get(request_id).ok_or(Error::::UnknownRequest)?; + ensure!(request.operator == signer, Error::::WrongOperator); // NOTE: This should not be possible technically but it is here to be safe ensure!( diff --git a/gn-pallets/pallet-oracle/src/mock.rs b/gn-pallets/pallet-oracle/src/mock.rs index a39b0558..0ee15276 100644 --- a/gn-pallets/pallet-oracle/src/mock.rs +++ b/gn-pallets/pallet-oracle/src/mock.rs @@ -1,3 +1,7 @@ +// This is to suppress weird unused warnings when run with the +// `runtime-benchmarks` feature flag enabled. It probably emanates from the +// `impl_benchmark_test_suite` macro. +#![cfg_attr(feature = "runtime-benchmarks", allow(unused))] pub use crate as pallet_oracle; use frame_support::dispatch::{ @@ -32,6 +36,7 @@ parameter_types! { pub const ExistentialDeposit: Balance = 1; pub const MinimumFee: Balance = 1; pub const ValidityPeriod: u64 = 10; + pub const MaxOperators: u32 = 4; } impl frame_system::Config for TestRuntime { @@ -77,27 +82,28 @@ impl pallet_oracle::Config for TestRuntime { type WeightInfo = (); type RuntimeEvent = RuntimeEvent; type Currency = pallet_balances::Pallet; - type Callback = MockCallback; + type Callback = MockCallback; type ValidityPeriod = ValidityPeriod; + type MaxOperators = MaxOperators; type MinimumFee = MinimumFee; } #[derive(Clone, Copy, Debug, PartialEq, Eq, TypeInfo, Encode, Decode)] -pub struct MockCallback(pub bool); +pub struct MockCallback(pub core::marker::PhantomData); -impl EncodeLike for MockCallback {} +impl EncodeLike<()> for MockCallback {} -impl pallet_oracle::CallbackWithParameter for MockCallback { +impl pallet_oracle::CallbackWithParameter for MockCallback { fn with_result(&self, result: SpVec) -> Option { if result == [0, 0] { None } else { - Some(Self(true)) + Some(Self(core::marker::PhantomData)) } } } -impl UnfilteredDispatchable for MockCallback { +impl UnfilteredDispatchable for MockCallback { type RuntimeOrigin = ::RuntimeOrigin; fn dispatch_bypass_filter(self, _origin: Self::RuntimeOrigin) -> DispatchResultWithPostInfo { Ok(PostDispatchInfo { @@ -106,3 +112,26 @@ impl UnfilteredDispatchable for MockCallback { }) } } + +impl MockCallback { + pub fn test() -> Self { + Self(core::marker::PhantomData) + } +} + +pub const GENESIS_BALANCE: ::Balance = 10; +pub const ACCOUNT_0: ::AccountId = 0; +pub const ACCOUNT_1: ::AccountId = 1; + +pub fn new_test_ext() -> sp_io::TestExternalities { + let mut storage = frame_system::GenesisConfig::default() + .build_storage::() + .unwrap(); + pallet_balances::GenesisConfig:: { + balances: vec![(ACCOUNT_0, GENESIS_BALANCE), (ACCOUNT_1, GENESIS_BALANCE)], + } + .assimilate_storage(&mut storage) + .unwrap(); + + sp_io::TestExternalities::new(storage) +} diff --git a/gn-pallets/pallet-oracle/src/test/helpers.rs b/gn-pallets/pallet-oracle/src/test/helpers.rs index 94e61cc5..f46b986a 100644 --- a/gn-pallets/pallet-oracle/src/test/helpers.rs +++ b/gn-pallets/pallet-oracle/src/test/helpers.rs @@ -1,23 +1,6 @@ use super::{pallet_oracle, RuntimeEvent, System, TestRuntime}; use frame_support::dispatch::DispatchError; -pub const GENESIS_BALANCE: ::Balance = 10; -pub const ACCOUNT_0: ::AccountId = 0; -pub const ACCOUNT_1: ::AccountId = 1; - -pub fn new_test_ext() -> sp_io::TestExternalities { - let mut storage = frame_system::GenesisConfig::default() - .build_storage::() - .unwrap(); - pallet_balances::GenesisConfig:: { - balances: vec![(ACCOUNT_0, GENESIS_BALANCE), (ACCOUNT_1, GENESIS_BALANCE)], - } - .assimilate_storage(&mut storage) - .unwrap(); - - sp_io::TestExternalities::new(storage) -} - pub fn last_event() -> pallet_oracle::Event { System::events() .into_iter() @@ -39,6 +22,7 @@ pub fn minimum_fee() -> ::Balance { pub fn error_msg<'a>(error: DispatchError) -> &'a str { match error { DispatchError::Module(module_error) => module_error.message.unwrap(), + DispatchError::BadOrigin => "BadOrigin", _ => panic!("unexpected error"), } } diff --git a/gn-pallets/pallet-oracle/src/test/mod.rs b/gn-pallets/pallet-oracle/src/test/mod.rs index 16e66c7f..7222d690 100644 --- a/gn-pallets/pallet-oracle/src/test/mod.rs +++ b/gn-pallets/pallet-oracle/src/test/mod.rs @@ -6,53 +6,205 @@ use frame_support::traits::OnFinalize; use pallet_oracle::Event as OracleEvent; use parity_scale_codec::{Decode, Encode}; +#[test] +fn invalid_transactions_fail() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + let failing_transactions = vec![ + ( + ::register_operator(RuntimeOrigin::none(), 0), + "BadOrigin", + ), + ( + ::register_operator(RuntimeOrigin::signed(0), 0), + "BadOrigin", + ), + ( + ::deregister_operator(RuntimeOrigin::none(), 0), + "BadOrigin", + ), + ( + ::deregister_operator(RuntimeOrigin::signed(1), 0), + "BadOrigin", + ), + ( + ::activate_operator(RuntimeOrigin::signed(1)), + "UnknownOperator", + ), + ( + ::deactivate_operator(RuntimeOrigin::signed(1)), + "UnknownOperator", + ), + ( + ::deregister_operator(RuntimeOrigin::root(), 1), + "UnknownOperator", + ), + ( + ::initiate_request( + RuntimeOrigin::signed(1), + MockCallback::test(), + vec![], + minimum_fee(), + ), + "NoActiveOperators", + ), + ( + ::callback(RuntimeOrigin::signed(ACCOUNT_0), 0, 10.encode()), + "UnknownRequest", + ), + ]; + + for (tx, raw_error_msg) in failing_transactions { + assert_eq!(error_msg(tx.unwrap_err()), raw_error_msg); + } + }); +} + #[test] fn operator_registration_valid() { new_test_ext().execute_with(|| { // This is required for some reason otherwise the last_event() method fails System::set_block_number(1); - - assert!(::operators().is_empty()); - assert!(::register_operator(RuntimeOrigin::signed(1)).is_ok()); - assert_eq!(last_event(), OracleEvent::OperatorRegistered(1)); - assert_eq!(::operators(), vec![1]); + let operator = 1; + assert_eq!(::num_registered_operators(), 0); + assert!(::register_operator(RuntimeOrigin::root(), operator).is_ok()); + assert!(::operator(operator).is_some()); + assert_eq!(::num_registered_operators(), 1); + assert_eq!(last_event(), OracleEvent::OperatorRegistered(operator)); }); } #[test] fn operator_registration_invalid_operator_already_registered() { new_test_ext().execute_with(|| { - assert!(::register_operator(RuntimeOrigin::signed(1)).is_ok()); - assert_eq!(::operators(), vec![1]); + let operator_1 = 1; + let operator_2 = 2; + assert!(::register_operator(RuntimeOrigin::root(), operator_1).is_ok()); + assert!(::operator(operator_1).is_some()); + assert_eq!(::num_registered_operators(), 1); // Operator already registered error - let error = ::register_operator(RuntimeOrigin::signed(1)).unwrap_err(); + let error = ::register_operator(RuntimeOrigin::root(), operator_1).unwrap_err(); assert_eq!(error_msg(error), "OperatorAlreadyRegistered"); - assert_eq!(::operators(), vec![1]); + assert!(::operator(operator_1).is_some()); + assert_eq!(::num_registered_operators(), 1); + + assert!(::register_operator(RuntimeOrigin::root(), operator_2).is_ok()); + assert!(::operator(operator_1).is_some()); + assert!(::operator(operator_2).is_some()); + assert_eq!(::num_registered_operators(), 2); }); } #[test] -fn operator_unregistration_valid() { +fn operator_deregistration_valid() { new_test_ext().execute_with(|| { - // This is required for some reason otherwise the last_event() method fails System::set_block_number(1); + let operator_0 = 0; + let operator_1 = 1; + let operator_2 = 2; + + assert!(::register_operator(RuntimeOrigin::root(), operator_1).is_ok()); + assert!(::deregister_operator(RuntimeOrigin::root(), operator_1).is_ok()); + assert_eq!(::num_registered_operators(), 0); - assert!(::register_operator(RuntimeOrigin::signed(1)).is_ok()); - assert!(::deregister_operator(RuntimeOrigin::signed(1)).is_ok()); - assert!(::operators().is_empty()); + assert_eq!(last_event(), OracleEvent::OperatorDeregistered(operator_1)); - assert_eq!(last_event(), OracleEvent::OperatorDeregistered(1)); + assert!(::register_operator(RuntimeOrigin::root(), operator_2).is_ok()); + assert!(::register_operator(RuntimeOrigin::root(), operator_0).is_ok()); + assert!(::register_operator(RuntimeOrigin::root(), operator_1).is_ok()); + assert!(::deregister_operator(RuntimeOrigin::root(), operator_0).is_ok()); + assert_eq!(::num_registered_operators(), 2); + assert!(::operator(operator_1).is_some()); + assert!(::operator(operator_2).is_some()); + + assert_eq!(last_event(), OracleEvent::OperatorDeregistered(operator_0)); }); } #[test] -fn operator_unregistration_invalid_unknown_operator() { +fn operator_activation_and_deactivation() { new_test_ext().execute_with(|| { - // Unknown operator error - let error = ::deregister_operator(RuntimeOrigin::signed(1)).unwrap_err(); - assert_eq!(error_msg(error), "UnknownOperator"); - assert!(::operators().is_empty()); + System::set_block_number(1); + let operator_0 = 0; + let operator_1 = 1; + let operator_2 = 2; + let operator_3 = 3; + let operator_4 = 4; + + ::register_operator(RuntimeOrigin::root(), operator_0).unwrap(); + ::register_operator(RuntimeOrigin::root(), operator_1).unwrap(); + ::register_operator(RuntimeOrigin::root(), operator_2).unwrap(); + + ::activate_operator(RuntimeOrigin::signed(operator_2)).unwrap(); + ::activate_operator(RuntimeOrigin::signed(operator_0)).unwrap(); + ::activate_operator(RuntimeOrigin::signed(operator_1)).unwrap(); + + assert_eq!(last_event(), OracleEvent::OperatorActivated(operator_1)); + assert_eq!( + ::active_operators(), + vec![operator_0, operator_1, operator_2] + ); + assert_eq!(::num_registered_operators(), 3); + + // deactivate operator_0 + ::deactivate_operator(RuntimeOrigin::signed(operator_0)).unwrap(); + + assert_eq!(last_event(), OracleEvent::OperatorDeactivated(operator_0)); + assert_eq!(::active_operators(), vec![operator_1, operator_2]); + assert_eq!(::num_registered_operators(), 3); + + // activate all registered operators (reactivate operator_0 + ::register_operator(RuntimeOrigin::root(), operator_3).unwrap(); + assert_eq!(::num_registered_operators(), 4); + ::activate_operator(RuntimeOrigin::signed(operator_3)).unwrap(); + ::activate_operator(RuntimeOrigin::signed(operator_0)).unwrap(); + assert_eq!( + ::active_operators(), + vec![operator_0, operator_1, operator_2, operator_3] + ); + + // not yet registered operator tries to activate + assert_eq!( + error_msg(::activate_operator(RuntimeOrigin::signed(operator_4)).unwrap_err()), + "UnknownOperator" + ); + + // deregister an activated operator + ::deregister_operator(RuntimeOrigin::root(), operator_1).unwrap(); + assert_eq!(::num_registered_operators(), 3); + assert_eq!( + ::active_operators(), + vec![operator_0, operator_2, operator_3] + ); + assert_eq!( + error_msg( + ::deactivate_operator(RuntimeOrigin::signed(operator_1)).unwrap_err() + ), + "UnknownOperator" + ); + // deregister a deactivated operator + ::deactivate_operator(RuntimeOrigin::signed(operator_2)).unwrap(); + assert_eq!(::active_operators(), vec![operator_0, operator_3]); + assert_eq!(::num_registered_operators(), 3); + ::deregister_operator(RuntimeOrigin::root(), operator_2).unwrap(); + assert_eq!(::num_registered_operators(), 2); + // deregistered tries to re-activate again + assert_eq!( + error_msg(::activate_operator(RuntimeOrigin::signed(operator_2)).unwrap_err()), + "UnknownOperator" + ); + // register a new operator + ::register_operator(RuntimeOrigin::root(), operator_4).unwrap(); + assert_eq!(::num_registered_operators(), 3); + ::register_operator(RuntimeOrigin::root(), operator_2).unwrap(); + assert_eq!(::num_registered_operators(), 4); + ::activate_operator(RuntimeOrigin::signed(operator_4)).unwrap(); + ::activate_operator(RuntimeOrigin::signed(operator_2)).unwrap(); + assert_eq!( + ::active_operators(), + vec![operator_0, operator_2, operator_3, operator_4] + ); }); } @@ -60,23 +212,25 @@ fn operator_unregistration_invalid_unknown_operator() { fn initiate_requests_valid() { new_test_ext().execute_with(|| { System::set_block_number(1); - let callback = MockCallback(false); + let callback = MockCallback::test(); let fee = minimum_fee(); let parameters = ("a", "b"); let data = parameters.encode(); let result = vec![10, 0, 0, 0]; let request_id = 0; - assert!(::register_operator(RuntimeOrigin::signed(ACCOUNT_0)).is_ok()); + ::register_operator(RuntimeOrigin::root(), ACCOUNT_0).unwrap(); assert_eq!(last_event(), OracleEvent::OperatorRegistered(ACCOUNT_0)); + ::activate_operator(RuntimeOrigin::signed(ACCOUNT_0)).unwrap(); + assert_eq!(last_event(), OracleEvent::OperatorActivated(ACCOUNT_0)); - assert!(::initiate_request( + ::initiate_request( RuntimeOrigin::signed(ACCOUNT_1), callback, data.clone(), fee, ) - .is_ok()); + .unwrap(); assert_eq!( last_event(), @@ -111,27 +265,44 @@ fn linear_request_delegation() { new_test_ext().execute_with(|| { System::set_block_number(1); + let operator = 9; let operator_0 = 10; let operator_1 = 11; let operator_2 = 12; let operator_3 = 13; let data = vec![]; - let callback = MockCallback(true); + let callback = MockCallback::test(); let fee = minimum_fee(); let mut request_id = 0; - assert!(::register_operator(RuntimeOrigin::signed(operator_0)).is_ok()); - assert!(::register_operator(RuntimeOrigin::signed(operator_1)).is_ok()); - assert!(::register_operator(RuntimeOrigin::signed(operator_2)).is_ok()); - assert!(::register_operator(RuntimeOrigin::signed(operator_3)).is_ok()); + ::register_operator(RuntimeOrigin::root(), operator).unwrap(); + ::register_operator(RuntimeOrigin::root(), operator_0).unwrap(); + ::register_operator(RuntimeOrigin::root(), operator_1).unwrap(); + ::register_operator(RuntimeOrigin::root(), operator_2).unwrap(); + assert_eq!( + error_msg(::register_operator(RuntimeOrigin::root(), operator_3).unwrap_err()), + "MaxOperatorsRegistered" + ); + assert_eq!( + ::num_registered_operators(), + ::MaxOperators::get() + ); + ::deregister_operator(RuntimeOrigin::root(), operator).unwrap(); + ::register_operator(RuntimeOrigin::root(), operator_3).unwrap(); + + // activate operators + ::activate_operator(RuntimeOrigin::signed(operator_0)).unwrap(); + ::activate_operator(RuntimeOrigin::signed(operator_1)).unwrap(); + ::activate_operator(RuntimeOrigin::signed(operator_2)).unwrap(); + ::activate_operator(RuntimeOrigin::signed(operator_3)).unwrap(); - assert!(::initiate_request( + ::initiate_request( RuntimeOrigin::signed(ACCOUNT_0), callback, data.clone(), fee, ) - .is_ok()); + .unwrap(); assert_eq!( last_event(), @@ -144,13 +315,13 @@ fn linear_request_delegation() { ); request_id += 1; - assert!(::initiate_request( + ::initiate_request( RuntimeOrigin::signed(ACCOUNT_0), callback, data.clone(), fee, ) - .is_ok()); + .unwrap(); assert_eq!( last_event(), @@ -163,13 +334,13 @@ fn linear_request_delegation() { ); request_id += 1; - assert!(::initiate_request( + ::initiate_request( RuntimeOrigin::signed(ACCOUNT_0), callback, data.clone(), fee, ) - .is_ok()); + .unwrap(); assert_eq!( last_event(), @@ -182,13 +353,13 @@ fn linear_request_delegation() { ); request_id += 1; - assert!(::initiate_request( + ::initiate_request( RuntimeOrigin::signed(ACCOUNT_0), callback, data.clone(), fee, ) - .is_ok()); + .unwrap(); assert_eq!( last_event(), @@ -201,10 +372,13 @@ fn linear_request_delegation() { ); request_id += 1; - assert!( - ::initiate_request(RuntimeOrigin::signed(ACCOUNT_0), callback, data, fee,) - .is_ok() - ); + ::initiate_request( + RuntimeOrigin::signed(ACCOUNT_0), + callback, + data.clone(), + fee, + ) + .unwrap(); assert_eq!( last_event(), @@ -215,30 +389,74 @@ fn linear_request_delegation() { fee, } ); - }); -} -#[test] -fn initiate_requests_invalid_unknown_operator() { - new_test_ext().execute_with(|| { - let error = ::initiate_request( + request_id += 1; + + // operator_1, and operator_2 deactivates + ::deactivate_operator(RuntimeOrigin::signed(operator_1)).unwrap(); + ::deactivate_operator(RuntimeOrigin::signed(operator_2)).unwrap(); + ::initiate_request( RuntimeOrigin::signed(ACCOUNT_0), - MockCallback(false), - vec![], - minimum_fee(), + callback, + data.clone(), + fee, ) - .unwrap_err(); - assert_eq!(error_msg(error), "NoRegisteredOperators"); + .unwrap(); + assert_eq!( + last_event(), + OracleEvent::OracleRequest { + request_id, + operator: operator_3, + callback, + fee, + } + ); + + request_id += 1; + + // operator_0 is deregistered by root + ::deregister_operator(RuntimeOrigin::root(), operator_0).unwrap(); + assert_eq!(::active_operators(), vec![operator_3]); + ::initiate_request( + RuntimeOrigin::signed(ACCOUNT_0), + callback, + data.clone(), + fee, + ) + .unwrap(); + assert_eq!( + last_event(), + OracleEvent::OracleRequest { + request_id, + operator: operator_3, + callback, + fee, + } + ); + + request_id += 1; + + ::initiate_request(RuntimeOrigin::signed(ACCOUNT_0), callback, data, fee).unwrap(); + assert_eq!( + last_event(), + OracleEvent::OracleRequest { + request_id, + operator: operator_3, + callback, + fee, + } + ); }); } #[test] fn initiate_requests_invalid_insufficient_fee() { new_test_ext().execute_with(|| { - assert!(::register_operator(RuntimeOrigin::signed(ACCOUNT_0)).is_ok()); + ::register_operator(RuntimeOrigin::root(), ACCOUNT_0).unwrap(); + ::activate_operator(RuntimeOrigin::signed(ACCOUNT_0)).unwrap(); let error = ::initiate_request( RuntimeOrigin::signed(ACCOUNT_1), - MockCallback(true), + MockCallback::test(), vec![], minimum_fee() - 1, ) @@ -251,10 +469,11 @@ fn initiate_requests_invalid_insufficient_fee() { #[test] fn initiate_requests_invalid_insufficient_balance_for_fee() { new_test_ext().execute_with(|| { - assert!(::register_operator(RuntimeOrigin::signed(ACCOUNT_0)).is_ok()); + ::register_operator(RuntimeOrigin::root(), ACCOUNT_0).unwrap(); + ::activate_operator(RuntimeOrigin::signed(ACCOUNT_0)).unwrap(); let error = ::initiate_request( RuntimeOrigin::signed(ACCOUNT_1), - MockCallback(true), + MockCallback::test(), vec![], GENESIS_BALANCE + 1, ) @@ -266,39 +485,32 @@ fn initiate_requests_invalid_insufficient_balance_for_fee() { #[test] fn initiate_requests_invalid_wrong_operator() { new_test_ext().execute_with(|| { - assert!(::register_operator(RuntimeOrigin::signed(ACCOUNT_0)).is_ok()); - assert!(::initiate_request( + ::register_operator(RuntimeOrigin::root(), ACCOUNT_0).unwrap(); + ::activate_operator(RuntimeOrigin::signed(ACCOUNT_0)).unwrap(); + ::initiate_request( RuntimeOrigin::signed(ACCOUNT_1), - MockCallback(true), + MockCallback::test(), vec![], minimum_fee(), ) - .is_ok()); + .unwrap(); let error = ::callback(RuntimeOrigin::signed(99), 0, vec![1]).unwrap_err(); assert_eq!(error_msg(error), "WrongOperator"); }); } -#[test] -fn unknown_request() { - new_test_ext().execute_with(|| { - let error = - ::callback(RuntimeOrigin::signed(ACCOUNT_0), 0, 10.encode()).unwrap_err(); - assert_eq!(error_msg(error), "UnknownRequest"); - }); -} - #[test] fn unknown_callback() { new_test_ext().execute_with(|| { - assert!(::register_operator(RuntimeOrigin::signed(ACCOUNT_0)).is_ok()); - assert!(::initiate_request( + ::register_operator(RuntimeOrigin::root(), ACCOUNT_0).unwrap(); + ::activate_operator(RuntimeOrigin::signed(ACCOUNT_0)).unwrap(); + ::initiate_request( RuntimeOrigin::signed(ACCOUNT_1), - MockCallback(true), + MockCallback::test(), vec![], minimum_fee(), ) - .is_ok()); + .unwrap(); // Sending an empty result in this test runtime environment causes // MockCallback to return None for the `with_result` call. The // resulting None will trigger the UnknownCallback error. Note, that @@ -314,14 +526,15 @@ fn kill_request() { new_test_ext().execute_with(|| { let request_id = 0; - assert!(::register_operator(RuntimeOrigin::signed(ACCOUNT_0)).is_ok()); - assert!(::initiate_request( + ::register_operator(RuntimeOrigin::root(), ACCOUNT_0).unwrap(); + ::activate_operator(RuntimeOrigin::signed(ACCOUNT_0)).unwrap(); + ::initiate_request( RuntimeOrigin::signed(ACCOUNT_1), - MockCallback(false), + MockCallback::test(), vec![], minimum_fee(), ) - .is_ok()); + .unwrap(); >::on_finalize( ::ValidityPeriod::get() - 1, diff --git a/gn-pallets/pallet-oracle/src/weights.rs b/gn-pallets/pallet-oracle/src/weights.rs index 120c12ab..dd6ce225 100644 --- a/gn-pallets/pallet-oracle/src/weights.rs +++ b/gn-pallets/pallet-oracle/src/weights.rs @@ -1,29 +1,14 @@ -// This file is part of Substrate. -// Copyright (C) 2022 Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// 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. - -//! Autogenerated weights for pallet_oracle +//! Autogenerated weights for `pallet_oracle` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-09-23, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! HOSTNAME: `turbineblade`, CPU: `AMD Ryzen 5 3600 6-Core Processor` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 19.0.0 +//! DATE: 2023-02-21, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `razorblade`, CPU: `Intel(R) Core(TM) i5-10210U CPU @ 1.60GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/release/node-template +// ./target/release/gn-node // benchmark // pallet // --chain @@ -38,10 +23,8 @@ // 50 // --repeat // 20 -// --template -// frame-weight-template.hbs // --output -// ./pallets/pallet-oracle/src/weights.rs +// ./gn-pallets/pallet-oracle/src/weights.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,41 +33,190 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use sp_std::marker::PhantomData; -/// Weight functions needed for pallet_oracle. pub trait WeightInfo { - fn register_operator() -> Weight; - fn deregister_operator() -> Weight; + fn register_operator(n: u32, ) -> Weight; + fn deregister_operator(n: u32, ) -> Weight; + fn activate_operator(n: u32, ) -> Weight; + fn deactivate_operator(n: u32, ) -> Weight; + fn initiate_request(n: u32, ) -> Weight; } -/// Weights for pallet_oracle using the Substrate node and recommended hardware. +/// Weight functions for `pallet_oracle`. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - // Storage: Oracle Operators (r:1 w:1) - fn register_operator() -> Weight { - Weight::from_parts(16_972_000, 16_972_000) - .saturating_add(T::DbWeight::get().reads(1)) + /// Storage: Oracle NumRegisteredOperators (r:1 w:1) + /// Proof Skipped: Oracle NumRegisteredOperators (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Oracle RegisteredOperators (r:1 w:1) + /// Proof Skipped: Oracle RegisteredOperators (max_values: None, max_size: None, mode: Measured) + /// The range of component `n` is `[1, 9]`. + fn register_operator(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `77 + n * (25 ±0)` + // Estimated: `3120 + n * (50 ±0)` + // Minimum execution time: 21_815 nanoseconds. + Weight::from_parts(33_363_548, 3120) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(Weight::from_proof_size(50).saturating_mul(n.into())) + } + /// Storage: Oracle RegisteredOperators (r:1 w:1) + /// Proof Skipped: Oracle RegisteredOperators (max_values: None, max_size: None, mode: Measured) + /// Storage: Oracle ActiveOperators (r:1 w:1) + /// Proof Skipped: Oracle ActiveOperators (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Oracle NumRegisteredOperators (r:1 w:1) + /// Proof Skipped: Oracle NumRegisteredOperators (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `n` is `[1, 9]`. + fn deregister_operator(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `72 + n * (34 ±0)` + // Estimated: `3681 + n * (102 ±0)` + // Minimum execution time: 22_749 nanoseconds. + Weight::from_parts(32_567_146, 3681) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(Weight::from_proof_size(102).saturating_mul(n.into())) + } + /// Storage: Oracle RegisteredOperators (r:1 w:0) + /// Proof Skipped: Oracle RegisteredOperators (max_values: None, max_size: None, mode: Measured) + /// Storage: Oracle ActiveOperators (r:1 w:1) + /// Proof Skipped: Oracle ActiveOperators (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `n` is `[1, 10]`. + fn activate_operator(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `95 + n * (66 ±0)` + // Estimated: `3124 + n * (136 ±0)` + // Minimum execution time: 23_000 nanoseconds. + Weight::from_parts(32_471_489, 3124) + // Standard Error: 56_513 + .saturating_add(Weight::from_ref_time(298_375).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) + .saturating_add(Weight::from_proof_size(136).saturating_mul(n.into())) } - // Storage: Oracle Operators (r:1 w:1) - fn deregister_operator() -> Weight { - Weight::from_parts(16_862_000, 16_862_000) - .saturating_add(T::DbWeight::get().reads(1)) + /// Storage: Oracle RegisteredOperators (r:1 w:0) + /// Proof Skipped: Oracle RegisteredOperators (max_values: None, max_size: None, mode: Measured) + /// Storage: Oracle ActiveOperators (r:1 w:1) + /// Proof Skipped: Oracle ActiveOperators (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `n` is `[1, 10]`. + fn deactivate_operator(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `128 + n * (65 ±0)` + // Estimated: `3240 + n * (128 ±0)` + // Minimum execution time: 21_588 nanoseconds. + Weight::from_parts(30_203_793, 3240) + // Standard Error: 73_025 + .saturating_add(Weight::from_ref_time(321_732).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) + .saturating_add(Weight::from_proof_size(128).saturating_mul(n.into())) + } + /// Storage: Oracle ActiveOperators (r:1 w:0) + /// Proof Skipped: Oracle ActiveOperators (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Oracle NextOperator (r:1 w:1) + /// Proof Skipped: Oracle NextOperator (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Oracle NextRequestIdentifier (r:1 w:1) + /// Proof Skipped: Oracle NextRequestIdentifier (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Oracle Requests (r:0 w:1) + /// Proof Skipped: Oracle Requests (max_values: None, max_size: None, mode: Measured) + /// The range of component `n` is `[50, 1000]`. + fn initiate_request(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `153` + // Estimated: `2097` + // Minimum execution time: 27_835 nanoseconds. + Weight::from_parts(36_093_449, 2097) + // Standard Error: 931 + .saturating_add(Weight::from_ref_time(3_363).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } } -// For backwards compatibility and tests impl WeightInfo for () { - // Storage: Oracle Operators (r:1 w:1) - fn register_operator() -> Weight { - Weight::from_parts(16_972_000, 16_972_000) - .saturating_add(RocksDbWeight::get().reads(1)) + /// Storage: Oracle NumRegisteredOperators (r:1 w:1) + /// Proof Skipped: Oracle NumRegisteredOperators (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Oracle RegisteredOperators (r:1 w:1) + /// Proof Skipped: Oracle RegisteredOperators (max_values: None, max_size: None, mode: Measured) + /// The range of component `n` is `[1, 9]`. + fn register_operator(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `77 + n * (25 ±0)` + // Estimated: `3120 + n * (50 ±0)` + // Minimum execution time: 21_815 nanoseconds. + Weight::from_parts(33_363_548, 3120) + .saturating_add(RocksDbWeight::get().reads(2)) + .saturating_add(RocksDbWeight::get().writes(2)) + .saturating_add(Weight::from_proof_size(50).saturating_mul(n.into())) + } + /// Storage: Oracle RegisteredOperators (r:1 w:1) + /// Proof Skipped: Oracle RegisteredOperators (max_values: None, max_size: None, mode: Measured) + /// Storage: Oracle ActiveOperators (r:1 w:1) + /// Proof Skipped: Oracle ActiveOperators (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Oracle NumRegisteredOperators (r:1 w:1) + /// Proof Skipped: Oracle NumRegisteredOperators (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `n` is `[1, 9]`. + fn deregister_operator(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `72 + n * (34 ±0)` + // Estimated: `3681 + n * (102 ±0)` + // Minimum execution time: 22_749 nanoseconds. + Weight::from_parts(32_567_146, 3681) + .saturating_add(RocksDbWeight::get().reads(3)) + .saturating_add(RocksDbWeight::get().writes(3)) + .saturating_add(Weight::from_proof_size(102).saturating_mul(n.into())) + } + /// Storage: Oracle RegisteredOperators (r:1 w:0) + /// Proof Skipped: Oracle RegisteredOperators (max_values: None, max_size: None, mode: Measured) + /// Storage: Oracle ActiveOperators (r:1 w:1) + /// Proof Skipped: Oracle ActiveOperators (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `n` is `[1, 10]`. + fn activate_operator(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `95 + n * (66 ±0)` + // Estimated: `3124 + n * (136 ±0)` + // Minimum execution time: 23_000 nanoseconds. + Weight::from_parts(32_471_489, 3124) + // Standard Error: 56_513 + .saturating_add(Weight::from_ref_time(298_375).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(2)) .saturating_add(RocksDbWeight::get().writes(1)) + .saturating_add(Weight::from_proof_size(136).saturating_mul(n.into())) } - // Storage: Oracle Operators (r:1 w:1) - fn deregister_operator() -> Weight { - Weight::from_parts(16_862_000, 16_862_000) - .saturating_add(RocksDbWeight::get().reads(1)) + /// Storage: Oracle RegisteredOperators (r:1 w:0) + /// Proof Skipped: Oracle RegisteredOperators (max_values: None, max_size: None, mode: Measured) + /// Storage: Oracle ActiveOperators (r:1 w:1) + /// Proof Skipped: Oracle ActiveOperators (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `n` is `[1, 10]`. + fn deactivate_operator(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `128 + n * (65 ±0)` + // Estimated: `3240 + n * (128 ±0)` + // Minimum execution time: 21_588 nanoseconds. + Weight::from_parts(30_203_793, 3240) + // Standard Error: 73_025 + .saturating_add(Weight::from_ref_time(321_732).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(2)) .saturating_add(RocksDbWeight::get().writes(1)) + .saturating_add(Weight::from_proof_size(128).saturating_mul(n.into())) + } + /// Storage: Oracle ActiveOperators (r:1 w:0) + /// Proof Skipped: Oracle ActiveOperators (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Oracle NextOperator (r:1 w:1) + /// Proof Skipped: Oracle NextOperator (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Oracle NextRequestIdentifier (r:1 w:1) + /// Proof Skipped: Oracle NextRequestIdentifier (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Oracle Requests (r:0 w:1) + /// Proof Skipped: Oracle Requests (max_values: None, max_size: None, mode: Measured) + /// The range of component `n` is `[50, 1000]`. + fn initiate_request(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `153` + // Estimated: `2097` + // Minimum execution time: 27_835 nanoseconds. + Weight::from_parts(36_093_449, 2097) + // Standard Error: 931 + .saturating_add(Weight::from_ref_time(3_363).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(3)) + .saturating_add(RocksDbWeight::get().writes(3)) } } diff --git a/gn-runtime/Cargo.toml b/gn-runtime/Cargo.toml index 019bb7a6..da22ccb2 100644 --- a/gn-runtime/Cargo.toml +++ b/gn-runtime/Cargo.toml @@ -25,6 +25,7 @@ runtime-benchmarks = [ std = [ "parity-scale-codec/std", "scale-info/std", + "frame-benchmarking?/std", "frame-executive/std", "frame-support/std", "frame-system/std", diff --git a/gn-runtime/src/lib.rs b/gn-runtime/src/lib.rs index 0bc3a12e..ac06dd5f 100644 --- a/gn-runtime/src/lib.rs +++ b/gn-runtime/src/lib.rs @@ -108,7 +108,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { /// up by `pallet_aura` to implement `fn slot_duration()`. /// /// Change this to adjust the block time. -pub const MILLISECS_PER_BLOCK: u64 = 2000; +pub const MILLISECS_PER_BLOCK: u64 = 3000; // NOTE: Currently it is not possible to change the slot duration after the chain has started. // Attempting to do so will brick block production. @@ -141,7 +141,7 @@ parameter_types! { pub const SS58Prefix: u8 = 42; pub const ValidityPeriod: u32 = 50; pub const MinimumFee: u32 = 0; - pub const ExistentialDeposit: Balance = 500; + pub const ExistentialDeposit: Balance = 0; pub const MinAuthorities: u32 = 2; pub const Period: u32 = 2 * MINUTES; pub const Offset: u32 = 0; @@ -275,9 +275,10 @@ impl pallet_oracle::Config for Runtime { type Currency = Balances; type Callback = pallet_guild::Call; type RuntimeEvent = RuntimeEvent; + type MaxOperators = ConstU32<10>; type MinimumFee = MinimumFee; type ValidityPeriod = ValidityPeriod; - type WeightInfo = (); + type WeightInfo = pallet_oracle::weights::SubstrateWeight; } impl pallet_session::Config for Runtime { @@ -355,22 +356,21 @@ pub type Executive = frame_executive::Executive< AllPalletsWithSystem, >; -// TODO benchmarking issue -//#[cfg(feature = "runtime-benchmarks")] -//#[macro_use] -//extern crate frame_benchmarking; -// -//#[cfg(feature = "runtime-benchmarks")] -//mod benches { -// define_benchmarks!( -// [frame_benchmarking, BaselineBench::] -// [frame_system, SystemBench::] -// [pallet_balances, Balances] -// [pallet_timestamp, Timestamp] -// [pallet_guild, Guild] -// [pallet_oracle, Oracle] -// ); -//} +#[cfg(feature = "runtime-benchmarks")] +#[macro_use] +extern crate frame_benchmarking; + +#[cfg(feature = "runtime-benchmarks")] +mod benches { + define_benchmarks!( + [frame_benchmarking, BaselineBench::] + [frame_system, SystemBench::] + [pallet_balances, Balances] + [pallet_timestamp, Timestamp] + [pallet_guild, Guild] + [pallet_oracle, Oracle] + ); +} impl_runtime_apis! { impl sp_api::Core for Runtime { @@ -509,7 +509,6 @@ impl_runtime_apis! { } } - /* TODO benchmarking #[cfg(feature = "runtime-benchmarks")] impl frame_benchmarking::Benchmark for Runtime { fn benchmark_metadata(extra: bool) -> ( @@ -557,7 +556,6 @@ impl_runtime_apis! { Ok(batches) } } - */ #[cfg(all(feature = "try-runtime", feature = "std"))] impl frame_try_runtime::TryRuntime for Runtime { diff --git a/integr_test.py b/integr_test.py index abf5e183..2151e7e7 100644 --- a/integr_test.py +++ b/integr_test.py @@ -23,7 +23,7 @@ def start_node(): def start_oracle(): - oracle = Popen(['./target/release/gn-oracle', '--log', 'info', '--register'], + oracle = Popen(['./target/release/gn-oracle', '--log', 'info', '--activate'], stderr=PIPE, stdout=DEVNULL) start = time.time() @@ -74,6 +74,8 @@ def run_tests(*commands, timeout=300): def main(): try: node = start_node() + command = "cargo run --release --example guild -- --example register" + run_tests(command, timeout=90) oracle = start_oracle() oracle_monitor = Thread(target=monitor_oracle, args=(oracle, node,)) diff --git a/start.sh b/start.sh index 3a1eee2d..cd8a6676 100755 --- a/start.sh +++ b/start.sh @@ -51,7 +51,6 @@ elif [ $1 = "benchmark" ]; then --wasm-execution=compiled \ --steps 50 \ --repeat 20 \ - --template frame-weight-template.hbs \ --output ./gn-pallets/pallet-$pallet/src/weights.rs else echo "Invalid command"