diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4ecb0491a..4259082d0 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -93,8 +93,7 @@ jobs: cargo +nightly-2020-10-06 test -p mining-eligibility-hardware && cargo +nightly-2020-10-06 test -p mining-claims-token && cargo +nightly-2020-10-06 test -p mining-claims-hardware && - cargo +nightly-2020-10-06 test -p mining-execution-token && - cargo +nightly-2020-10-06 test -p exchange-rate + cargo +nightly-2020-10-06 test -p exchange-rate lints: name: Lints diff --git a/Cargo.lock b/Cargo.lock index e6e1633ac..944f795dd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1000,7 +1000,6 @@ dependencies = [ "mining-config-token", "mining-eligibility-hardware", "mining-eligibility-token", - "mining-execution-token", "mining-rates-hardware", "mining-rates-token", "mining-sampling-hardware", @@ -3239,9 +3238,11 @@ version = "0.1.0" dependencies = [ "frame-support", "frame-system", + "mining-rates-token", "pallet-balances", "pallet-randomness-collective-flip", "pallet-transaction-payment", + "pallet-treasury", "parity-scale-codec", "roaming-operators", "safe-mix", @@ -3293,29 +3294,6 @@ dependencies = [ "sp-std", ] -[[package]] -name = "mining-execution-token" -version = "0.1.0" -dependencies = [ - "frame-support", - "frame-system", - "mining-claims-token", - "mining-config-token", - "mining-eligibility-token", - "mining-rates-token", - "mining-sampling-token", - "pallet-balances", - "pallet-randomness-collective-flip", - "pallet-transaction-payment", - "parity-scale-codec", - "roaming-operators", - "safe-mix", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", -] - [[package]] name = "mining-rates-hardware" version = "0.1.0" diff --git a/EXAMPLES.md b/EXAMPLES.md index 204cb2b99..3edf66b8f 100644 --- a/EXAMPLES.md +++ b/EXAMPLES.md @@ -46,7 +46,8 @@ rm -rf /tmp/polkadot-chains/alice /tmp/polkadot-chains/bob /tmp/polkadot-chains/ --base-path /tmp/polkadot-chains/alice \ --name "Data Highway Development Chain" \ --dev \ - --telemetry-url "wss://telemetry.polkadot.io/submit/ 0" + --telemetry-url "wss://telemetry.polkadot.io/submit/ 0" \ + -lruntime=debug ``` ## Example "local" PoS testnet (with multiple nodes) diff --git a/custom_types.json b/custom_types.json index d2c0b22bf..bab0042f3 100644 --- a/custom_types.json +++ b/custom_types.json @@ -124,8 +124,8 @@ "MiningConfigTokenConfig": { "token_type": "Text", "token_lock_amount": "u64", - "token_lock_start_block": "Moment", - "token_lock_interval_blocks": "Moment" + "token_lock_start_block": "u64", + "token_lock_interval_blocks": "u64" }, "MiningConfigTokenRequirementsConfig": { "token_type": "Text", @@ -146,6 +146,12 @@ "hardware_lock_start_block": "Moment", "hardware_lock_interval_blocks": "Moment" }, + "MiningConfigTokenExecutorAccountID": "u64", + "MiningConfigTokenExecutionResult": { + "token_execution_executor_account_id": "u64", + "token_execution_started_block": "u64", + "token_execution_interval_blocks": "u64" + }, "MiningSamplingToken": "[u8; 16]", "MiningSamplingTokenIndex": "u64", "MiningSamplingTokenSampleLockedAmount": "u64", @@ -196,14 +202,6 @@ "hardware_claim_amount": "u64", "hardware_claim_block_redeemed": "u64" }, - "MiningExecutionToken": "[u8; 16]", - "MiningExecutionTokenIndex": "u64", - "MiningExecutionTokenExecutorAccountID": "u64", - "MiningExecutionTokenExecutionResult": { - "token_execution_exector_account_id": "u64", - "token_execution_started_block": "Moment", - "token_execution_ended_block": "Moment" - }, "ExchangeRateIndex": "u64", "ExchangeRateConfig": { "hbtc": "u64", diff --git a/pallets/exchange-rate/src/lib.rs b/pallets/exchange-rate/src/lib.rs old mode 100755 new mode 100644 index cf2631fad..571ac8427 --- a/pallets/exchange-rate/src/lib.rs +++ b/pallets/exchange-rate/src/lib.rs @@ -269,7 +269,7 @@ impl Module { fn random_value(sender: &T::AccountId) -> [u8; 16] { let payload = ( - T::Randomness::random(&[0]), + ::Randomness::random(&[0]), sender, >::extrinsic_index(), >::block_number(), diff --git a/pallets/mining/claims/hardware/src/lib.rs b/pallets/mining/claims/hardware/src/lib.rs index 5cf86d40b..ca72eaf4c 100644 --- a/pallets/mining/claims/hardware/src/lib.rs +++ b/pallets/mining/claims/hardware/src/lib.rs @@ -374,7 +374,7 @@ impl Module { fn random_value(sender: &T::AccountId) -> [u8; 16] { let payload = ( - T::Randomness::random(&[0]), + ::Randomness::random(&[0]), sender, >::extrinsic_index(), >::block_number(), diff --git a/pallets/mining/claims/token/src/lib.rs b/pallets/mining/claims/token/src/lib.rs index 15cc230c8..dae85fcc4 100644 --- a/pallets/mining/claims/token/src/lib.rs +++ b/pallets/mining/claims/token/src/lib.rs @@ -184,7 +184,7 @@ decl_module! { // FIXME // let current_block = >::block_number(); // // Get the config associated with the given configuration_token - // if let Some(configuration_token_config) = >::mining_config_token_token_configs(mining_config_token_id) { + // if let Some(configuration_token_config) = >::mining_config_token_configs(mining_config_token_id) { // if let _token_lock_interval_blocks = configuration_token_config.token_lock_interval_blocks { // ensure!(current_block > _token_lock_interval_blocks, "Claim may not be made until after the end of the lock interval"); // } else { @@ -475,7 +475,7 @@ impl Module { fn random_value(sender: &T::AccountId) -> [u8; 16] { let payload = ( - T::Randomness::random(&[0]), + ::Randomness::random(&[0]), sender, >::extrinsic_index(), >::block_number(), diff --git a/pallets/mining/config/hardware/src/lib.rs b/pallets/mining/config/hardware/src/lib.rs index 7a50b561f..0280552d3 100644 --- a/pallets/mining/config/hardware/src/lib.rs +++ b/pallets/mining/config/hardware/src/lib.rs @@ -315,7 +315,7 @@ impl Module { fn random_value(sender: &T::AccountId) -> [u8; 16] { let payload = ( - T::Randomness::random(&[0]), + ::Randomness::random(&[0]), sender, >::extrinsic_index(), >::block_number(), diff --git a/pallets/mining/config/token/Cargo.toml b/pallets/mining/config/token/Cargo.toml index 14d23431f..89b2f43d6 100644 --- a/pallets/mining/config/token/Cargo.toml +++ b/pallets/mining/config/token/Cargo.toml @@ -14,12 +14,14 @@ std = [ 'pallet-balances/std', 'pallet-randomness-collective-flip/std', 'pallet-transaction-payment/std', + 'pallet-treasury/std', 'sp-core/std', 'sp-io/std', 'sp-runtime/std', 'sp-std/std', 'roaming-operators/std', + 'mining-rates-token/std', ] [dependencies] @@ -30,11 +32,13 @@ frame-system = { version = '2.0.0', default_features = false } pallet-balances = { version = '2.0.0', default_features = false } pallet-randomness-collective-flip = { version = '2.0.0', default_features = false } pallet-transaction-payment = { version = '2.0.0', default_features = false } +pallet-treasury = { version = '2.0.0', default-features = false } sp-core = { version = '2.0.0', default_features = false } sp-io = { version = '2.0.0', default_features = false } sp-runtime = { version = '2.0.0', default_features = false } sp-std = { version = '2.0.0', default_features = false } roaming-operators = { default_features = false, package = 'roaming-operators', path = '../../../roaming/roaming-operators' } +mining-rates-token = { default_features = false, package = 'mining-rates-token', path = '../../../mining/rates/token' } [dev-dependencies] diff --git a/pallets/mining/config/token/src/lib.rs b/pallets/mining/config/token/src/lib.rs index 5b67fc778..2dbdc453a 100644 --- a/pallets/mining/config/token/src/lib.rs +++ b/pallets/mining/config/token/src/lib.rs @@ -1,4 +1,5 @@ #![cfg_attr(not(feature = "std"), no_std)] +#![feature(step_trait)] use codec::{ Decode, @@ -12,8 +13,12 @@ use frame_support::{ ensure, traits::{ Currency, + ExistenceRequirement, Get, + LockIdentifier, + LockableCurrency, Randomness, + WithdrawReasons, }, Parameter, }; @@ -25,10 +30,14 @@ use sp_runtime::{ Bounded, Member, One, + Zero, }, DispatchError, }; -use sp_std::prelude::*; // Imports Vec +use sp_std::{ + convert::TryInto, + prelude::*, +}; // Imports Vec // FIXME - remove roaming_operators here, only use this approach since do not know how to use BalanceOf using only // mining runtime module @@ -40,16 +49,22 @@ mod mock; mod tests; /// The module's configuration trait. -pub trait Trait: frame_system::Trait + roaming_operators::Trait { +pub trait Trait: + frame_system::Trait + + roaming_operators::Trait + + mining_rates_token::Trait + + pallet_treasury::Trait + + pallet_balances::Trait +{ type Event: From> + Into<::Event>; - type MiningConfigTokenIndex: Parameter + Member + AtLeast32Bit + Bounded + Default + Copy; + type Currency: LockableCurrency; + type MiningConfigTokenIndex: Parameter + Member + AtLeast32Bit + Bounded + Default + Copy + sp_std::iter::Step; // Mining Speed Boost Token Mining Config type MiningConfigTokenType: Parameter + Member + Default; type MiningConfigTokenLockAmount: Parameter + Member + AtLeast32Bit + Bounded + Default + Copy; } -type BalanceOf = - <::Currency as Currency<::AccountId>>::Balance; +type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; #[derive(Encode, Decode, Clone, PartialEq, Eq)] #[cfg_attr(feature = "std", derive(Debug))] @@ -73,25 +88,40 @@ pub struct MiningConfigTokenRequirementsConfig { pub token_lock_min_blocks: W, } +#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Encode, Decode, Default, Clone, PartialEq)] +pub struct MiningConfigTokenExecutionResult { + pub token_execution_executor_account_id: U, + pub token_execution_started_block: V, + pub token_execution_interval_blocks: W, +} + decl_event!( pub enum Event where - ::AccountId, + AccountId = ::AccountId, ::MiningConfigTokenIndex, ::MiningConfigTokenType, - ::BlockNumber, - Balance = BalanceOf, + BlockNumber = ::BlockNumber, + BalanceOfCurrency = BalanceOf, + Balance = ::Balance, { /// A mining_config_token is created. (owner, mining_config_token_id) Created(AccountId, MiningConfigTokenIndex), /// A mining_config_token is transferred. (from, to, mining_config_token_id) Transferred(AccountId, AccountId, MiningConfigTokenIndex), MiningConfigTokenConfigSet( - AccountId, MiningConfigTokenIndex, MiningConfigTokenType, Balance, BlockNumber, BlockNumber + AccountId, MiningConfigTokenIndex, MiningConfigTokenType, BalanceOfCurrency, BlockNumber, BlockNumber ), MiningConfigTokenRequirementsConfigSet( - AccountId, MiningConfigTokenIndex, MiningConfigTokenType, Balance, + AccountId, MiningConfigTokenIndex, MiningConfigTokenType, BalanceOfCurrency, BlockNumber ), + MiningConfigTokenExecutionResultSet( + AccountId, MiningConfigTokenIndex, AccountId, BlockNumber, BlockNumber + ), + TreasuryRewardTokenMiningPostCooldown( + Balance, BlockNumber, AccountId + ), } ); @@ -108,12 +138,20 @@ decl_storage! { pub MiningConfigTokenOwners get(fn mining_config_token_owner): map hasher(opaque_blake2_256) T::MiningConfigTokenIndex => Option; /// Stores mining_config_token_token_config - pub MiningConfigTokenConfigs get(fn mining_config_token_token_configs): map hasher(opaque_blake2_256) T::MiningConfigTokenIndex => + pub MiningConfigTokenConfigs get(fn mining_config_token_configs): map hasher(opaque_blake2_256) T::MiningConfigTokenIndex => Option, T::BlockNumber, T::BlockNumber>>; /// Stores mining_config_token_token_cooldown_config - pub MiningConfigTokenRequirementsConfigs get(fn mining_config_token_token_cooldown_configs): map hasher(opaque_blake2_256) T::MiningConfigTokenIndex => + pub MiningConfigTokenRequirementsConfigs get(fn mining_config_token_cooldown_configs): map hasher(opaque_blake2_256) T::MiningConfigTokenIndex => Option, T::BlockNumber>>; + + /// Stores mining_config_token_execution_result + pub MiningConfigTokenExecutionResults get(fn mining_config_token_execution_results): map hasher(opaque_blake2_256) T::MiningConfigTokenIndex => + Option>; } } @@ -123,6 +161,123 @@ decl_module! { pub struct Module for enum Call where origin: T::Origin { fn deposit_event() = default; + // TODO - automatically checks through all the accounts that have + // successfully been locked, whether it is the end of their cooldown period and if so sample the balance, to + // determine their elegibility, and perform the lodgement for reward and unlock their tokens + fn on_finalize(current_block_number: T::BlockNumber) { + debug::info!("execution/token-mining - on_finalize"); + debug::info!("current block number {:#?}", current_block_number); + + let config_token_count = Self::mining_config_token_count(); + + // FIXME - is there an upper bound on the size of these sets and + // the computation of this nested loop? what max size or custom weight function? + // See https://substrate.dev/recipes/map-set.html + // + // Loop through all mining_config_token_id + for idx_c in 0u32.into()..config_token_count { + let fetched_mining_execution_token_result = >::get(idx_c); + + if let Some(_mining_execution_token_result) = fetched_mining_execution_token_result { + debug::info!("token_execution_executor_account_id {:#?}", _mining_execution_token_result.token_execution_executor_account_id); + debug::info!("token_execution_started_block {:#?}", _mining_execution_token_result.token_execution_started_block); + debug::info!("token_execution_interval_blocks {:#?}", _mining_execution_token_result.token_execution_interval_blocks); + + let fetched_mining_config_token_cooldown_config = Self::mining_config_token_cooldown_configs(idx_c); + if let Some(_mining_config_token_cooldown_config) = fetched_mining_config_token_cooldown_config { + // debug::info!("token_type {:#?}", _mining_config_token_cooldown_config.token_type); + debug::info!("token_lock_min_blocks {:#?}", _mining_config_token_cooldown_config.token_lock_min_blocks); + + if let token_lock_min_blocks = _mining_config_token_cooldown_config.token_lock_min_blocks { + if let Some(configuration_token) = Self::mining_config_token_configs((idx_c)) { + if let token_lock_amount = configuration_token.token_lock_amount { + + // FIXME - remove hard-coded and integrate + let MINING_REQUESTED_END_BLOCK: T::BlockNumber = 10.into(); + + // If the end of the mining period has been reached, then stop giving them rewards, + // and unlock their bonded tokens after waiting the cooldown period of _mining_config_token_cooldown_config.token_lock_min_blocks + // after the end of their mining period. + + if >::block_number() >= _mining_execution_token_result.token_execution_interval_blocks { + // if >::block_number() > _mining_execution_token_result.token_execution_interval_blocks + token_lock_min_blocks { + if >::block_number() > MINING_REQUESTED_END_BLOCK as T::BlockNumber + token_lock_min_blocks { + // TODO - Unlock the funds. Store updated status + // We only want to unlock the rewards they have earned. + // The amount of tokens that they originally locked to mine the rewards will remain locked until the end of their mining period + // (FIXME - or until they request to stop mining, which hasn't been implemented yet), + // and then they cannot move those locked tokens for the cooldown period and receive no further rewards. + + if let Some(mining_config_token) = Self::mining_config_token(idx_c) { + const EXAMPLE_ID: LockIdentifier = *b"example "; + + ::Currency::remove_lock( + EXAMPLE_ID, // FIXME - somehow replace with: mining_config_token, // where idx_c is mining_config_token_id + &_mining_execution_token_result.token_execution_executor_account_id, + ); + } + } + } else if >::block_number() < _mining_execution_token_result.token_execution_interval_blocks { + // Check if cooldown period has been reached before start distributing rewards. + // If so then we unlock and transfer the reward tokens to the user from the treasury. + // Reference: https://github.com/hicommonwealth/edgeware-node/blob/master/modules/edge-treasury-reward/src/lib.rs#L42 + if >::block_number() % token_lock_min_blocks == Zero::zero() { + // FIXME - assumes there is only one rates config index so hard-coded 0, but we could have many + let RATE_HARD_CODED: T::MiningRatesTokenIndex = 0u32.into(); + let fetched_mining_rates_token_rates_config = >::mining_rates_token_rates_configs(RATE_HARD_CODED); + if let Some(_mining_rates_token_rates_config) = fetched_mining_rates_token_rates_config { + debug::info!("token_execution_interval_blocks {:#?}", _mining_execution_token_result.token_execution_interval_blocks); + + // TODO - choose the token rate that corresponds to the _mining_config_token_cooldown_config.token_type + // and use this to determine the reward ratio. + // in the meantime until this is fixed, we will just assume the user is mining MXC and choose the rate for that + + // Reward ratio + let reward_ratio: T::MiningRatesTokenTokenMXC = _mining_rates_token_rates_config.token_token_mxc; + // + // Calculate the reward based on the reward ratio (i.e. 1 DHX per 10 DHX that was locked) + // e.g. (1.1 - 1) * 10 DHX, where 1.1 is ratio of mining reward for the MXC token + let total_ratio: T::MiningRatesTokenTokenMXC = reward_ratio - 1u32.into(); + + let total = TryInto::::try_into(total_ratio).ok(); + let lock_amount = TryInto::::try_into(token_lock_amount).ok(); + let reward: Option = match (total, lock_amount) { + (Some(a), Some(b)) => Some(a * b), + _ => None, + }; + + // Distribute the reward to the account that has locked the funds + let treasury_account_id: T::AccountId = >::account_id(); + + if let Some(reward_to_pay_to_try) = reward { + let reward_to_pay_as_balance_to_try = TryInto::>::try_into(reward_to_pay_to_try).ok(); + if let Some(reward_to_pay) = reward_to_pay_as_balance_to_try { + ::Currency::transfer( + &treasury_account_id, + &_mining_execution_token_result.token_execution_executor_account_id, + reward_to_pay, + ExistenceRequirement::KeepAlive + ); + } + } + + // Emit event since treasury unlocked locked tokens and rewarded customer the reward ratio + Self::deposit_event(RawEvent::TreasuryRewardTokenMiningPostCooldown( + >::free_balance(&_mining_execution_token_result.token_execution_executor_account_id), + >::block_number(), + _mining_execution_token_result.token_execution_executor_account_id + )); + } + } + } + } + } + } + } + } + } + } + /// Create a new mining mining_config_token #[weight = 10_000 + T::DbWeight::get().writes(1)] pub fn create(origin) { @@ -153,7 +308,7 @@ decl_module! { /// Set mining_config_token_token_config #[weight = 10_000 + T::DbWeight::get().writes(1)] - pub fn set_mining_config_token_token_config( + pub fn set_mining_config_token_config( origin, mining_config_token_id: T::MiningConfigTokenIndex, _token_type: Option, @@ -259,7 +414,7 @@ decl_module! { /// Set mining_config_token_token_cooldown_config #[weight = 10_000 + T::DbWeight::get().writes(1)] - pub fn set_mining_config_token_token_cooldown_config( + pub fn set_mining_config_token_cooldown_config( origin, mining_config_token_id: T::MiningConfigTokenIndex, _token_type: Option, @@ -341,6 +496,148 @@ decl_module! { token_lock_min_blocks, )); } + + /// Set mining_config_token_execution_result + #[weight = 10_000 + T::DbWeight::get().writes(1)] + pub fn set_mining_config_token_execution_result( + origin, + mining_config_token_id: T::MiningConfigTokenIndex, + ) { + let sender = ensure_signed(origin)?; + + // Ensure that the mining_config_token_id whose config we want to change actually exists + let is_mining_config_token = Self::exists_mining_config_token(mining_config_token_id).is_ok(); + ensure!(is_mining_config_token, "MiningConfigToken does not exist"); + + // Ensure that the caller is owner of the mining_config_token_token_config they are trying to change + ensure!(Self::mining_config_token_owner(mining_config_token_id) == Some(sender.clone()), "Only owner can set mining_config_token_token_config"); + + // Check that only allow the owner of the configuration that the execution belongs to call this extrinsic to set and execute + ensure!( + Self::is_mining_config_token_owner( + mining_config_token_id, sender.clone() + ).is_ok(), + "Only the configuration_token owner can execute their associated execution" + ); + + // Assign config values to the execution values + let token_execution_executor_account_id = sender.clone(); + let token_execution_started_block; + let token_execution_interval_blocks; + + if let Some(configuration_token_config) = + Self::mining_config_token_configs(mining_config_token_id) + { + if let _token_lock_start_block = configuration_token_config.token_lock_start_block { + token_execution_started_block = _token_lock_start_block.clone(); + } else { + return Err(DispatchError::Other("Cannot find token_lock_start_block associated with the config")); + } + + if let _token_lock_interval_blocks = configuration_token_config.token_lock_interval_blocks { + token_execution_interval_blocks = _token_lock_interval_blocks.clone(); + } else { + return Err(DispatchError::Other("Cannot find token_lock_interval_blocks associated with the config")); + } + } else { + return Err(DispatchError::Other("Cannot find token_config associated with the execution")); + } + + // TODO - we could just use the token_execution_started_block that we queried already instead of calling it again within this function + // Ensure that the associated token configuration has a token_execution_started_block > current_block + let is_token_execution_started_block_greater_than_current_block = Self::token_execution_started_block_greater_than_current_block(mining_config_token_id).is_ok(); + ensure!(is_token_execution_started_block_greater_than_current_block, "token execution does not have a token_execution_started_block > current_block"); + + // Ensure that the associated token configuration has a token_lock_interval_blocks > token_lock_min_blocks + let is_token_lock_interval_blocks_greater_than_token_lock_min_blocks = Self::token_lock_interval_blocks_greater_than_token_lock_min_blocks(mining_config_token_id).is_ok(); + ensure!(is_token_lock_interval_blocks_greater_than_token_lock_min_blocks, "token configuration does not have a token_lock_interval_blocks > token_lock_min_blocks"); + + // Ensure that the associated token configuration has a token_lock_amount > token_lock_min_amount + let is_token_lock_amount_greater_than_token_lock_min_amount = Self::token_lock_amount_greater_than_token_lock_min_amount(mining_config_token_id).is_ok(); + ensure!(is_token_lock_amount_greater_than_token_lock_min_amount, "token configuration does not have a token_lock_amount > token_lock_min_amount"); + + Self::execution( + sender.clone(), + mining_config_token_id, + token_execution_executor_account_id.clone(), + token_execution_started_block, + token_execution_interval_blocks, + ); + debug::info!("Executed"); + + ensure!(Self::execution( + sender.clone(), + mining_config_token_id, + token_execution_executor_account_id.clone(), + token_execution_started_block, + token_execution_interval_blocks, + ).is_ok(), "Cannot execute"); + + // Check if a mining_config_token_execution_result already exists with the given mining_config_token_id + // to determine whether to insert new or mutate existing. + if Self::has_value_for_mining_config_token_execution_result_index(mining_config_token_id).is_ok() { + debug::info!("Mutating values"); + >::mutate((mining_config_token_id), |mining_config_token_execution_result| { + if let Some(_mining_config_token_execution_result) = mining_config_token_execution_result { + // Only update the value of a key in a KV pair if the corresponding parameter value has been provided + _mining_config_token_execution_result.token_execution_executor_account_id = token_execution_executor_account_id.clone(); + _mining_config_token_execution_result.token_execution_started_block = token_execution_started_block.clone(); + _mining_config_token_execution_result.token_execution_interval_blocks = token_execution_interval_blocks.clone(); + } + }); + debug::info!("Checking mutated values"); + let fetched_mining_config_token_execution_result = >::get((mining_config_token_id)); + if let Some(_mining_config_token_execution_result) = fetched_mining_config_token_execution_result { + debug::info!("Latest field token_execution_executor_account_id {:#?}", _mining_config_token_execution_result.token_execution_executor_account_id); + debug::info!("Latest field token_execution_started_block {:#?}", _mining_config_token_execution_result.token_execution_started_block); + debug::info!("Latest field token_execution_interval_blocks {:#?}", _mining_config_token_execution_result.token_execution_interval_blocks); + } + } else { + debug::info!("Inserting values"); + + // Create a new mining mining_config_token_execution_result instance with the input params + let mining_config_token_execution_result_instance = MiningConfigTokenExecutionResult { + // Since each parameter passed into the function is optional (i.e. `Option`) + // we will assign a default value if a parameter value is not provided. + token_execution_executor_account_id: token_execution_executor_account_id.clone(), + token_execution_started_block: token_execution_started_block.clone(), + token_execution_interval_blocks: token_execution_interval_blocks.clone(), + }; + + >::insert( + mining_config_token_id, + &mining_config_token_execution_result_instance + ); + + debug::info!("Checking inserted values"); + let fetched_mining_config_token_execution_result = >::get(mining_config_token_id); + if let Some(_mining_config_token_execution_result) = fetched_mining_config_token_execution_result { + debug::info!("Inserted field token_execution_executor_account_id {:#?}", _mining_config_token_execution_result.token_execution_executor_account_id); + debug::info!("Inserted field token_execution_started_block {:#?}", _mining_config_token_execution_result.token_execution_started_block); + debug::info!("Inserted field token_execution_interval_blocks {:#?}", _mining_config_token_execution_result.token_execution_interval_blocks); + } + } + + Self::deposit_event(RawEvent::MiningConfigTokenExecutionResultSet( + sender.clone(), + mining_config_token_id, + token_execution_executor_account_id.clone(), + token_execution_started_block, + token_execution_interval_blocks, + )); + + if Self::execution( + sender.clone(), + mining_config_token_id, + token_execution_executor_account_id.clone(), + token_execution_started_block, + token_execution_interval_blocks, + ).is_ok() { + debug::info!("Executed"); + } else { + debug::info!("Cannot execute"); + } + } } } @@ -368,12 +665,103 @@ impl Module { pub fn exists_mining_config_token_token_config( mining_config_token_id: T::MiningConfigTokenIndex, ) -> Result<(), DispatchError> { - match Self::mining_config_token_token_configs(mining_config_token_id) { + match Self::mining_config_token_configs(mining_config_token_id) { Some(_value) => Ok(()), None => Err(DispatchError::Other("MiningConfigTokenConfig does not exist")), } } + // Check that the token execution has a token_execution_started_block > current_block + pub fn token_execution_started_block_greater_than_current_block( + mining_config_token_id: T::MiningConfigTokenIndex, + ) -> Result<(), DispatchError> { + // Check that the extrinsic call is made after the start date defined in the provided configuration + + let current_block = >::block_number(); + // Get the config associated with the given configuration_token + if let Some(configuration_token_config) = Self::mining_config_token_configs(mining_config_token_id) { + if let _token_lock_start_block = configuration_token_config.token_lock_start_block { + ensure!( + current_block > _token_lock_start_block, + "Execution may not be made until after the start block of the lock period in the configuration" + ); + Ok(()) + } else { + return Err(DispatchError::Other("Cannot find token_config start_date associated with the execution")); + } + } else { + return Err(DispatchError::Other("Cannot find token_config associated with the execution")); + } + } + + // Check that the associated token configuration has a token_lock_interval_blocks > token_lock_min_blocks + pub fn token_lock_interval_blocks_greater_than_token_lock_min_blocks( + mining_config_token_id: T::MiningConfigTokenIndex, + ) -> Result<(), DispatchError> { + if let Some(configuration_token) = Self::mining_config_token_configs((mining_config_token_id)) { + if let Some(cooldown_configuration_token) = + Self::mining_config_token_cooldown_configs((mining_config_token_id)) + { + if let token_lock_interval_blocks = configuration_token.token_lock_interval_blocks { + if let token_lock_min_blocks = cooldown_configuration_token.token_lock_min_blocks { + ensure!( + token_lock_interval_blocks > token_lock_min_blocks, + "Lock period must be longer than the minimum lock period of the cooldown config. Cannot \ + execute." + ); + Ok(()) + } else { + return Err(DispatchError::Other( + "Cannot find token_config with token_lock_min_blocks associated with the execution", + )); + } + } else { + return Err(DispatchError::Other( + "Cannot find token_config with token_lock_interval_blocks associated with the execution", + )); + } + } else { + return Err(DispatchError::Other("Cannot find token_cooldown_config associated with the execution")); + } + } else { + return Err(DispatchError::Other("Cannot find token_config associated with the execution")); + } + } + + // Check that the associated token configuration has a token_lock_amount > token_lock_min_amount + pub fn token_lock_amount_greater_than_token_lock_min_amount( + mining_config_token_id: T::MiningConfigTokenIndex, + ) -> Result<(), DispatchError> { + if let Some(configuration_token) = Self::mining_config_token_configs((mining_config_token_id)) { + if let Some(cooldown_configuration_token) = + Self::mining_config_token_cooldown_configs((mining_config_token_id)) + { + if let lock_amount = configuration_token.token_lock_amount { + if let lock_min_amount = cooldown_configuration_token.token_lock_min_amount { + ensure!( + lock_amount > lock_min_amount, + "Locked amount must be larger than the minimum locked amount of the cooldown config. \ + Cannot execute." + ); + Ok(()) + } else { + return Err(DispatchError::Other( + "Cannot find token_config with token_lock_min_blocks associated with the execution", + )); + } + } else { + return Err(DispatchError::Other( + "Cannot find token_config with token_lock_interval_blocks associated with the execution", + )); + } + } else { + return Err(DispatchError::Other("Cannot find token_cooldown_config associated with the execution")); + } + } else { + return Err(DispatchError::Other("Cannot find token_config associated with the execution")); + } + } + pub fn has_value_for_mining_config_token_token_config_index( mining_config_token_id: T::MiningConfigTokenIndex, ) -> Result<(), DispatchError> { @@ -401,9 +789,77 @@ impl Module { Err(DispatchError::Other("No value for mining_config_token_token_cooldown_config")) } + pub fn has_value_for_mining_config_token_execution_result_index( + mining_config_token_id: T::MiningConfigTokenIndex, + ) -> Result<(), DispatchError> { + debug::info!("Checking if mining_config_token_execution_result has a value that is defined"); + let fetched_mining_config_token_execution_result = + >::get(mining_config_token_id); + if let Some(_value) = fetched_mining_config_token_execution_result { + debug::info!("Found value for mining_config_token_execution_result"); + return Ok(()); + } + debug::info!("No value for mining_config_token_execution_result"); + Err(DispatchError::Other("No value for mining_config_token_execution_result")) + } + + pub fn execution( + sender: T::AccountId, + mining_config_token_id: T::MiningConfigTokenIndex, + _token_execution_executor_account_id: T::AccountId, + _token_execution_started_block: T::BlockNumber, + _token_execution_interval_blocks: T::BlockNumber, + ) -> Result<(), DispatchError> { + // return Ok(()); + // TODO - Lock the token_lock_amount for the token_lock_interval_blocks using the Balances module + + // TODO - Setup a function in on_finalize that automatically checks through all the accounts that have + // successfully been locked, whether it is the end of their cooldown period and if so sample the balance, to + // determine their elegibility, and perform the claim for reward and unlock their tokens + // TODO - Update tests for the above + if let Some(configuration_token) = Self::mining_config_token_configs((mining_config_token_id)) { + if let lock_amount = configuration_token.token_lock_amount { + if let Some(lock_amount_lockable_currency_try) = TryInto::>::try_into(lock_amount).ok() { + if let lock_amount_lockable_currency = lock_amount_lockable_currency_try { + if let Some(execution_results) = + Self::mining_config_token_execution_results(mining_config_token_id) + { + const EXAMPLE_ID: LockIdentifier = *b"example "; + + ::Currency::set_lock( + // execution_token, // EXAMPLE_ID, + EXAMPLE_ID, + &_token_execution_executor_account_id, + lock_amount_lockable_currency, + WithdrawReasons::all(), + ); + return Ok(()); + } else { + return Err(DispatchError::Other( + "Cannot find mining_config_token_id associated with the execution", + )); + } + } else { + return Err(DispatchError::Other( + "Cannot find lock_amount_lockable_currency associated with the execution", + )); + } + } else { + return Err(DispatchError::Other("Cannot find lock_amount associated with the execution")); + } + } else { + return Err(DispatchError::Other( + "Cannot find token_mining_config with token_lock_period associated with the execution", + )); + } + } else { + return Err(DispatchError::Other("Cannot find token_mining_config associated with the execution")); + } + } + fn random_value(sender: &T::AccountId) -> [u8; 16] { let payload = ( - T::Randomness::random(&[0]), + ::Randomness::random(&[0]), sender, >::extrinsic_index(), >::block_number(), diff --git a/pallets/mining/eligibility/hardware/src/lib.rs b/pallets/mining/eligibility/hardware/src/lib.rs index 2ac927e27..0963422e6 100644 --- a/pallets/mining/eligibility/hardware/src/lib.rs +++ b/pallets/mining/eligibility/hardware/src/lib.rs @@ -546,7 +546,7 @@ impl Module { fn random_value(sender: &T::AccountId) -> [u8; 16] { let payload = ( - T::Randomness::random(&[0]), + ::Randomness::random(&[0]), sender, >::extrinsic_index(), >::block_number(), diff --git a/pallets/mining/eligibility/token/src/lib.rs b/pallets/mining/eligibility/token/src/lib.rs index 7a9c1a8aa..523cc2f7e 100644 --- a/pallets/mining/eligibility/token/src/lib.rs +++ b/pallets/mining/eligibility/token/src/lib.rs @@ -192,7 +192,7 @@ decl_module! { // let mut current_token_type; // let mut current_token_lock_amount; // // Get the config associated with the given configuration_token - // if let Some(configuration_token_config) = >::mining_config_token_token_configs(mining_config_token_id) { + // if let Some(configuration_token_config) = >::mining_config_token_configs(mining_config_token_id) { // if let token_type = configuration_token_config.token_type { // if token_type != "".to_string() { // current_token_type = token_type.clone(); @@ -544,7 +544,7 @@ impl Module { fn random_value(sender: &T::AccountId) -> [u8; 16] { let payload = ( - T::Randomness::random(&[0]), + ::Randomness::random(&[0]), sender, >::extrinsic_index(), >::block_number(), diff --git a/pallets/mining/execution/token/Cargo.toml b/pallets/mining/execution/token/Cargo.toml deleted file mode 100644 index dc848a6f1..000000000 --- a/pallets/mining/execution/token/Cargo.toml +++ /dev/null @@ -1,50 +0,0 @@ -[package] -name = "mining-execution-token" -version = "0.1.0" -authors = ["Luke Schoen"] -edition = "2018" - -[features] -default = ['std'] -std = [ - 'codec/std', - 'frame-support/std', - 'frame-system/std', - 'safe-mix/std', - 'pallet-balances/std', - 'pallet-randomness-collective-flip/std', - 'pallet-transaction-payment/std', - 'sp-core/std', - 'sp-io/std', - 'sp-runtime/std', - 'sp-std/std', - - 'roaming-operators/std', - 'mining-config-token/std', - 'mining-eligibility-token/std', - 'mining-rates-token/std', - 'mining-sampling-token/std', - 'mining-claims-token/std', -] - -[dependencies] -codec = { version = '1.2.0', package = 'parity-scale-codec', default-features = false, features = ['derive'] } -safe-mix = { version = '1.0.0', default-features = false } -frame-support = { version = '2.0.0', default_features = false } -frame-system = { version = '2.0.0', default_features = false } -pallet-balances = { version = '2.0.0', default_features = false } -pallet-randomness-collective-flip = { version = '2.0.0', default_features = false } -pallet-transaction-payment = { version = '2.0.0', default_features = false } -sp-core = { version = '2.0.0', default_features = false } -sp-io = { version = '2.0.0', default_features = false } -sp-runtime = { version = '2.0.0', default_features = false } -sp-std = { version = '2.0.0', default_features = false } - -roaming-operators = { default_features = false, package = 'roaming-operators', path = '../../../roaming/roaming-operators' } -mining-config-token = { default_features = false, package = 'mining-config-token', path = '../../../mining/config/token' } -mining-eligibility-token = { default_features = false, package = 'mining-eligibility-token', path = '../../../mining/eligibility/token' } -mining-rates-token = { default_features = false, package = 'mining-rates-token', path = '../../../mining/rates/token' } -mining-sampling-token = { default_features = false, package = 'mining-sampling-token', path = '../../../mining/sampling/token' } -mining-claims-token = { default_features = false, package = 'mining-claims-token', path = '../../../mining/claims/token' } - -[dev-dependencies] diff --git a/pallets/mining/execution/token/src/lib.rs b/pallets/mining/execution/token/src/lib.rs deleted file mode 100644 index 7214ae56c..000000000 --- a/pallets/mining/execution/token/src/lib.rs +++ /dev/null @@ -1,562 +0,0 @@ -#![cfg_attr(not(feature = "std"), no_std)] - -use codec::{ - Decode, - Encode, -}; -use frame_support::{ - debug, - decl_event, - decl_module, - decl_storage, - ensure, - traits::{ - Get, - Randomness, - }, - Parameter, -}; -use frame_system::ensure_signed; -use sp_io::hashing::blake2_128; -use sp_runtime::{ - traits::{ - AtLeast32Bit, - Bounded, - Member, - One, - }, - DispatchError, -}; -use sp_std::prelude::*; // Imports Vec - -// FIXME - remove roaming_operators here, only use this approach since do not know how to use BalanceOf using only -// mining runtime module -use mining_claims_token; -use mining_config_token; -use mining_eligibility_token; -use mining_rates_token; -use mining_sampling_token; - -// #[cfg(test)] -// mod mock; - -// #[cfg(test)] -// mod tests; - -/// The module's configuration trait. -pub trait Trait: - frame_system::Trait - + roaming_operators::Trait - + mining_config_token::Trait - + mining_eligibility_token::Trait - + mining_rates_token::Trait - + mining_sampling_token::Trait - + mining_claims_token::Trait -{ - type Event: From> + Into<::Event>; - type MiningExecutionTokenIndex: Parameter + Member + AtLeast32Bit + Bounded + Default + Copy; - // type MiningExecutionTokenExecutorAccountID: Parameter - // + Member - // + AtLeast32Bit - // + Bounded - // + Default - // + Copy; -} - -// type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; - -#[derive(Encode, Decode, Clone, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Debug))] -pub struct MiningExecutionToken(pub [u8; 16]); - -#[cfg_attr(feature = "std", derive(Debug))] -#[derive(Encode, Decode, Default, Clone, PartialEq)] -pub struct MiningExecutionTokenExecutionResult { - pub token_execution_executor_account_id: U, - pub token_execution_started_block: V, - pub token_execution_ended_block: W, -} - -decl_event!( - pub enum Event where - ::AccountId, - ::MiningExecutionTokenIndex, - // ::MiningExecutionTokenExecutorAccountID, - ::MiningConfigTokenIndex, - ::BlockNumber, - // Balance = BalanceOf, - { - /// A mining_execution_token is created. (owner, mining_execution_token_id) - Created(AccountId, MiningExecutionTokenIndex), - /// A mining_execution_token is transferred. (from, to, mining_execution_token_id) - Transferred(AccountId, AccountId, MiningExecutionTokenIndex), - MiningExecutionTokenExecutionResultSet( - AccountId, MiningConfigTokenIndex, MiningExecutionTokenIndex, - AccountId, BlockNumber, BlockNumber - ), - /// A mining_execution_token is assigned to an mining_token. - /// (owner of mining_token, mining_execution_token_id, mining_config_token_id) - AssignedTokenExecutionToConfiguration(AccountId, MiningExecutionTokenIndex, MiningConfigTokenIndex), - } -); - -// This module's storage items. -decl_storage! { - trait Store for Module as MiningExecutionToken { - /// Stores all the mining_execution_tokens, key is the mining_execution_token id / index - pub MiningExecutionTokens get(fn mining_execution_token): map hasher(opaque_blake2_256) T::MiningExecutionTokenIndex => Option; - - /// Stores the total number of mining_execution_tokens. i.e. the next mining_execution_token index - pub MiningExecutionTokenCount get(fn mining_execution_token_count): T::MiningExecutionTokenIndex; - - /// Stores mining_execution_token owner - pub MiningExecutionTokenOwners get(fn mining_execution_token_owner): map hasher(opaque_blake2_256) T::MiningExecutionTokenIndex => Option; - - /// Stores mining_execution_token_execution_result - pub MiningExecutionTokenExecutionResults get(fn mining_execution_token_execution_results): map hasher(opaque_blake2_256) (T::MiningConfigTokenIndex, T::MiningExecutionTokenIndex) => - Option>; - - /// Get mining_config_token_id belonging to a mining_execution_token_id - pub TokenExecutionConfiguration get(fn token_execution_configuration): map hasher(opaque_blake2_256) T::MiningExecutionTokenIndex => Option; - - /// Get mining_execution_token_id's belonging to a mining_config_token_id - pub TokenConfigExecution get(fn token_config_execution): map hasher(opaque_blake2_256) T::MiningConfigTokenIndex => Option> - } -} - -// The module's dispatchable functions. -decl_module! { - /// The module declaration. - pub struct Module for enum Call where origin: T::Origin { - fn deposit_event() = default; - - /// Create a new mining mining_execution_token - #[weight = 10_000 + T::DbWeight::get().writes(1)] - pub fn create(origin) { - let sender = ensure_signed(origin)?; - let mining_execution_token_id = Self::next_mining_execution_token_id()?; - - // Generate a random 128bit value - let unique_id = Self::random_value(&sender); - - // Create and store mining_execution_token - let mining_execution_token = MiningExecutionToken(unique_id); - Self::insert_mining_execution_token(&sender, mining_execution_token_id, mining_execution_token); - - Self::deposit_event(RawEvent::Created(sender, mining_execution_token_id)); - } - - /// Transfer a mining_execution_token to new owner - #[weight = 10_000 + T::DbWeight::get().writes(1)] - pub fn transfer(origin, to: T::AccountId, mining_execution_token_id: T::MiningExecutionTokenIndex) { - let sender = ensure_signed(origin)?; - - ensure!(Self::mining_execution_token_owner(mining_execution_token_id) == Some(sender.clone()), "Only owner can transfer mining mining_execution_token"); - - Self::update_owner(&to, mining_execution_token_id); - - Self::deposit_event(RawEvent::Transferred(sender, to, mining_execution_token_id)); - } - - /// Set mining_execution_token_execution_result - #[weight = 10_000 + T::DbWeight::get().writes(1)] - pub fn set_mining_execution_token_execution_result( - origin, - mining_config_token_id: T::MiningConfigTokenIndex, - mining_execution_token_id: T::MiningExecutionTokenIndex, - _token_execution_started_block: Option, - _token_execution_ended_block: Option, - ) { - let sender = ensure_signed(origin)?; - - // Ensure that the mining_execution_token_id whose config we want to change actually exists - let is_mining_execution_token = Self::exists_mining_execution_token(mining_execution_token_id).is_ok(); - ensure!(is_mining_execution_token, "MiningExecutionToken does not exist"); - - // Ensure that the caller is owner of the mining_execution_token_execution_result they are trying to change - ensure!(Self::mining_execution_token_owner(mining_execution_token_id) == Some(sender.clone()), "Only owner can set mining_execution_token_execution_result"); - - // Check that only allow the owner of the configuration that the execution belongs to call this extrinsic to set and execute - ensure!( - >::is_mining_config_token_owner( - mining_config_token_id, sender.clone() - ).is_ok(), - "Only the configuration_token owner can execute their associated execution" - ); - - // TODO - adjust defaults - let token_execution_executor_account_id = sender.clone(); - let token_execution_started_block = match _token_execution_started_block.clone() { - Some(value) => value, - None => >::block_number() - }; - let token_execution_ended_block = match _token_execution_ended_block { - Some(value) => value, - None => >::block_number() + 1.into() // Default - }; - - // FIXME - // // Ensure that the associated token configuration has a token_execution_started_block > current_block - // let is_token_execution_started_block_greater_than_current_block = Self::token_execution_started_block_greater_than_current_block(mining_execution_token_id, mining_config_token_id).is_ok(); - // ensure!(is_token_execution_started_block_greater_than_current_block, "token execution does not have a token_execution_started_block > current_block"); - - // FIXME - // // Ensure that the associated token configuration has a token_lock_interval_blocks > token_lock_min_blocks - // let is_token_lock_interval_blocks_greater_than_token_lock_min_blocks = Self::token_lock_interval_blocks_greater_than_token_lock_min_blocks(mining_execution_token_id, mining_config_token_id).is_ok(); - // ensure!(is_token_lock_interval_blocks_greater_than_token_lock_min_blocks, "token configuration does not have a token_lock_interval_blocks > token_lock_min_blocks"); - - // Ensure that the associated token configuration has a token_lock_amount > token_lock_min_amount - let is_token_lock_amount_greater_than_token_lock_min_amount = Self::token_lock_amount_greater_than_token_lock_min_amount(mining_execution_token_id, mining_config_token_id).is_ok(); - ensure!(is_token_lock_amount_greater_than_token_lock_min_amount, "token configuration does not have a token_lock_amount > token_lock_min_amount"); - - // Check if a mining_execution_token_execution_result already exists with the given mining_execution_token_id - // to determine whether to insert new or mutate existing. - if Self::has_value_for_mining_execution_token_execution_result_index(mining_config_token_id, mining_execution_token_id).is_ok() { - debug::info!("Mutating values"); - >::mutate((mining_config_token_id, mining_execution_token_id), |mining_execution_token_execution_result| { - if let Some(_mining_execution_token_execution_result) = mining_execution_token_execution_result { - // Only update the value of a key in a KV pair if the corresponding parameter value has been provided - _mining_execution_token_execution_result.token_execution_executor_account_id = token_execution_executor_account_id.clone(); - _mining_execution_token_execution_result.token_execution_started_block = token_execution_started_block.clone(); - _mining_execution_token_execution_result.token_execution_ended_block = token_execution_ended_block.clone(); - } - }); - debug::info!("Checking mutated values"); - let fetched_mining_execution_token_execution_result = >::get((mining_config_token_id, mining_execution_token_id)); - if let Some(_mining_execution_token_execution_result) = fetched_mining_execution_token_execution_result { - debug::info!("Latest field token_execution_executor_account_id {:#?}", _mining_execution_token_execution_result.token_execution_executor_account_id); - debug::info!("Latest field token_execution_started_block {:#?}", _mining_execution_token_execution_result.token_execution_started_block); - debug::info!("Latest field token_execution_ended_block {:#?}", _mining_execution_token_execution_result.token_execution_ended_block); - } - } else { - debug::info!("Inserting values"); - - // Create a new mining mining_execution_token_execution_result instance with the input params - let mining_execution_token_execution_result_instance = MiningExecutionTokenExecutionResult { - // Since each parameter passed into the function is optional (i.e. `Option`) - // we will assign a default value if a parameter value is not provided. - token_execution_executor_account_id: token_execution_executor_account_id.clone(), - token_execution_started_block: token_execution_started_block.clone(), - token_execution_ended_block: token_execution_ended_block.clone(), - }; - - >::insert( - (mining_config_token_id, mining_execution_token_id), - &mining_execution_token_execution_result_instance - ); - - debug::info!("Checking inserted values"); - let fetched_mining_execution_token_execution_result = >::get((mining_config_token_id, mining_execution_token_id)); - if let Some(_mining_execution_token_execution_result) = fetched_mining_execution_token_execution_result { - debug::info!("Inserted field token_execution_executor_account_id {:#?}", _mining_execution_token_execution_result.token_execution_executor_account_id); - debug::info!("Inserted field token_execution_started_block {:#?}", _mining_execution_token_execution_result.token_execution_started_block); - debug::info!("Inserted field token_execution_ended_block {:#?}", _mining_execution_token_execution_result.token_execution_ended_block); - } - } - - Self::deposit_event(RawEvent::MiningExecutionTokenExecutionResultSet( - sender.clone(), - mining_config_token_id, - mining_execution_token_id, - token_execution_executor_account_id.clone(), - token_execution_started_block, - token_execution_ended_block, - )); - - - - if Self::execution( - sender.clone(), - mining_config_token_id, - mining_execution_token_id, - token_execution_executor_account_id.clone(), - token_execution_started_block, - token_execution_ended_block, - ).is_ok() { - debug::info!("Executed"); - } else { - debug::info!("Cannot execute"); - } - } - - #[weight = 10_000 + T::DbWeight::get().writes(1)] - pub fn assign_execution_to_configuration( - origin, - mining_execution_token_id: T::MiningExecutionTokenIndex, - mining_config_token_id: T::MiningConfigTokenIndex - ) { - let sender = ensure_signed(origin)?; - - // Ensure that the given configuration id already exists - let is_configuration_token = > - ::exists_mining_config_token(mining_config_token_id).is_ok(); - ensure!(is_configuration_token, "configuration_token does not exist"); - - // Ensure that caller of the function is the owner of the configuration id to assign the execution to - ensure!( - >::is_mining_config_token_owner(mining_config_token_id, sender.clone()).is_ok(), - "Only the configuration_token owner can assign itself a execution" - ); - - Self::associate_token_execution_with_configuration(mining_execution_token_id, mining_config_token_id) - .expect("Unable to associate execution with configuration"); - - // Ensure that the given mining_execution_token_id already exists - let token_execution = Self::mining_execution_token(mining_execution_token_id); - ensure!(token_execution.is_some(), "Invalid mining_execution_token_id"); - - // // Ensure that the execution is not already owned by a different configuration - // // Unassign the execution from any existing configuration since it may only be owned by one configuration - // >::remove(mining_execution_token_id); - - // Assign the network owner to the given operator (even if already belongs to them) - >::insert(mining_execution_token_id, mining_config_token_id); - - Self::deposit_event(RawEvent::AssignedTokenExecutionToConfiguration(sender, mining_execution_token_id, mining_config_token_id)); - } - } -} - -impl Module { - pub fn is_mining_execution_token_owner( - mining_execution_token_id: T::MiningExecutionTokenIndex, - sender: T::AccountId, - ) -> Result<(), DispatchError> { - ensure!( - Self::mining_execution_token_owner(&mining_execution_token_id) - .map(|owner| owner == sender) - .unwrap_or(false), - "Sender is not owner of MiningExecutionToken" - ); - Ok(()) - } - - pub fn exists_mining_execution_token( - mining_execution_token_id: T::MiningExecutionTokenIndex, - ) -> Result { - match Self::mining_execution_token(mining_execution_token_id) { - Some(value) => Ok(value), - None => Err(DispatchError::Other("MiningExecutionToken does not exist")), - } - } - - pub fn exists_mining_execution_token_execution_result( - mining_config_token_id: T::MiningConfigTokenIndex, - mining_execution_token_id: T::MiningExecutionTokenIndex, - ) -> Result<(), DispatchError> { - match Self::mining_execution_token_execution_results((mining_config_token_id, mining_execution_token_id)) { - Some(_value) => Ok(()), - None => Err(DispatchError::Other("MiningExecutionTokenExecutionResult does not exist")), - } - } - - // Check that the token execution has a token_execution_started_block > current_block - pub fn token_execution_started_block_greater_than_current_block( - mining_execution_token_id: T::MiningExecutionTokenIndex, - mining_config_token_id: T::MiningConfigTokenIndex, - ) -> Result<(), DispatchError> { - // Check that the extrinsic call is made after the start date defined in the provided configuration - - let current_block = >::block_number(); - // Get the config associated with the given configuration_token - if let Some(configuration_token_config) = - >::mining_config_token_token_configs(mining_config_token_id) - { - if let _token_lock_start_block = configuration_token_config.token_lock_start_block { - ensure!( - current_block > _token_lock_start_block, - "Execution may not be made until after the start block of the lock period in the configuration" - ); - Ok(()) - } else { - return Err(DispatchError::Other("Cannot find token_config start_date associated with the execution")); - } - } else { - return Err(DispatchError::Other("Cannot find token_config associated with the execution")); - } - } - - // Check that the associated token configuration has a token_lock_interval_blocks > token_lock_min_blocks - pub fn token_lock_interval_blocks_greater_than_token_lock_min_blocks( - mining_execution_token_id: T::MiningExecutionTokenIndex, - mining_config_token_id: T::MiningConfigTokenIndex, - ) -> Result<(), DispatchError> { - if let Some(configuration_token) = - >::mining_config_token_token_configs((mining_config_token_id)) - { - if let Some(cooldown_configuration_token) = - >::mining_config_token_token_cooldown_configs((mining_config_token_id)) - { - if let token_lock_interval_blocks = configuration_token.token_lock_interval_blocks { - if let token_lock_min_blocks = cooldown_configuration_token.token_lock_min_blocks { - ensure!( - token_lock_interval_blocks > token_lock_min_blocks, - "Lock period must be longer than the minimum lock period of the cooldown config. Cannot \ - execute." - ); - Ok(()) - } else { - return Err(DispatchError::Other( - "Cannot find token_config with token_lock_min_blocks associated with the execution", - )); - } - } else { - return Err(DispatchError::Other( - "Cannot find token_config with token_lock_interval_blocks associated with the execution", - )); - } - } else { - return Err(DispatchError::Other("Cannot find token_cooldown_config associated with the execution")); - } - } else { - return Err(DispatchError::Other("Cannot find token_config associated with the execution")); - } - } - - // Check that the associated token configuration has a token_lock_amount > token_lock_min_amount - pub fn token_lock_amount_greater_than_token_lock_min_amount( - mining_execution_token_id: T::MiningExecutionTokenIndex, - mining_config_token_id: T::MiningConfigTokenIndex, - ) -> Result<(), DispatchError> { - if let Some(configuration_token) = - >::mining_config_token_token_configs((mining_config_token_id)) - { - if let Some(cooldown_configuration_token) = - >::mining_config_token_token_cooldown_configs((mining_config_token_id)) - { - if let locked_amount = configuration_token.token_lock_amount { - if let lock_min_amount = cooldown_configuration_token.token_lock_min_amount { - ensure!( - locked_amount > lock_min_amount, - "Locked amount must be larger than the minimum locked amount of the cooldown config. \ - Cannot execute." - ); - Ok(()) - } else { - return Err(DispatchError::Other( - "Cannot find token_config with token_lock_min_blocks associated with the execution", - )); - } - } else { - return Err(DispatchError::Other( - "Cannot find token_config with token_lock_interval_blocks associated with the execution", - )); - } - } else { - return Err(DispatchError::Other("Cannot find token_cooldown_config associated with the execution")); - } - } else { - return Err(DispatchError::Other("Cannot find token_config associated with the execution")); - } - } - - pub fn execution( - sender: T::AccountId, - mining_config_token_id: T::MiningConfigTokenIndex, - mining_execution_token_id: T::MiningExecutionTokenIndex, - _token_execution_executor_account_id: T::AccountId, - _token_execution_started_block: T::BlockNumber, - _token_execution_ended_block: T::BlockNumber, - ) -> Result<(), DispatchError> { - return Ok(()); - - // TODO - Lock the token_lock_amount for the token_lock_interval_blocks using the Balances module - - // TODO - Setup a function in on_finalize that automatically checks through all the accounts that have - // successfully been locked, whether it is the end of their cooldown period and if so sample the balance, to - // determine their elegibility, and perform the claim for reward and unlock their tokens - // TODO - Update tests for the above - } - - pub fn has_value_for_mining_execution_token_execution_result_index( - mining_config_token_id: T::MiningConfigTokenIndex, - mining_execution_token_id: T::MiningExecutionTokenIndex, - ) -> Result<(), DispatchError> { - debug::info!("Checking if mining_execution_token_execution_result has a value that is defined"); - let fetched_mining_execution_token_execution_result = - >::get((mining_config_token_id, mining_execution_token_id)); - if let Some(_value) = fetched_mining_execution_token_execution_result { - debug::info!("Found value for mining_execution_token_execution_result"); - return Ok(()); - } - debug::info!("No value for mining_execution_token_execution_result"); - Err(DispatchError::Other("No value for mining_execution_token_execution_result")) - } - - /// Only push the execution id onto the end of the vector if it does not already exist - pub fn associate_token_execution_with_configuration( - mining_execution_token_id: T::MiningExecutionTokenIndex, - mining_config_token_id: T::MiningConfigTokenIndex, - ) -> Result<(), DispatchError> { - // Early exit with error since do not want to append if the given configuration id already exists as a key, - // and where its corresponding value is a vector that already contains the given execution id - if let Some(configuration_execution) = Self::token_config_execution(mining_config_token_id) { - debug::info!( - "Configuration id key {:?} exists with value {:?}", - mining_config_token_id, - configuration_execution - ); - let not_configuration_contains_execution = !configuration_execution.contains(&mining_execution_token_id); - ensure!(not_configuration_contains_execution, "Configuration already contains the given execution id"); - debug::info!("Configuration id key exists but its vector value does not contain the given execution id"); - >::mutate(mining_config_token_id, |v| { - if let Some(value) = v { - value.push(mining_execution_token_id); - } - }); - debug::info!( - "Associated execution {:?} with configuration {:?}", - mining_execution_token_id, - mining_config_token_id - ); - Ok(()) - } else { - debug::info!( - "Configuration id key does not yet exist. Creating the configuration key {:?} and appending the \ - execution id {:?} to its vector value", - mining_config_token_id, - mining_execution_token_id - ); - >::insert(mining_config_token_id, &vec![mining_execution_token_id]); - Ok(()) - } - } - - fn random_value(sender: &T::AccountId) -> [u8; 16] { - let payload = ( - T::Randomness::random(&[0]), - sender, - >::extrinsic_index(), - >::block_number(), - ); - payload.using_encoded(blake2_128) - } - - fn next_mining_execution_token_id() -> Result { - let mining_execution_token_id = Self::mining_execution_token_count(); - if mining_execution_token_id == ::max_value() { - return Err(DispatchError::Other("MiningExecutionToken count overflow")); - } - Ok(mining_execution_token_id) - } - - fn insert_mining_execution_token( - owner: &T::AccountId, - mining_execution_token_id: T::MiningExecutionTokenIndex, - mining_execution_token: MiningExecutionToken, - ) { - // Create and store mining mining_execution_token - >::insert(mining_execution_token_id, mining_execution_token); - >::put(mining_execution_token_id + One::one()); - >::insert(mining_execution_token_id, owner.clone()); - } - - fn update_owner(to: &T::AccountId, mining_execution_token_id: T::MiningExecutionTokenIndex) { - >::insert(mining_execution_token_id, to); - } -} diff --git a/pallets/mining/lodgements/hardware/src/lib.rs b/pallets/mining/lodgements/hardware/src/lib.rs index b82f5f0fb..dca98dd74 100644 --- a/pallets/mining/lodgements/hardware/src/lib.rs +++ b/pallets/mining/lodgements/hardware/src/lib.rs @@ -398,7 +398,7 @@ impl Module { fn random_value(sender: &T::AccountId) -> [u8; 16] { let payload = ( - T::Randomness::random(&[0]), + ::Randomness::random(&[0]), sender, >::extrinsic_index(), >::block_number(), diff --git a/pallets/mining/rates/hardware/src/lib.rs b/pallets/mining/rates/hardware/src/lib.rs index cf2a6003d..66fec584b 100644 --- a/pallets/mining/rates/hardware/src/lib.rs +++ b/pallets/mining/rates/hardware/src/lib.rs @@ -328,7 +328,7 @@ impl Module { fn random_value(sender: &T::AccountId) -> [u8; 16] { let payload = ( - T::Randomness::random(&[0]), + ::Randomness::random(&[0]), sender, >::extrinsic_index(), >::block_number(), diff --git a/pallets/mining/rates/token/src/lib.rs b/pallets/mining/rates/token/src/lib.rs index 0d76c5151..38b5ecf80 100644 --- a/pallets/mining/rates/token/src/lib.rs +++ b/pallets/mining/rates/token/src/lib.rs @@ -41,7 +41,7 @@ mod tests; /// The module's configuration trait. pub trait Trait: frame_system::Trait + roaming_operators::Trait { type Event: From> + Into<::Event>; - type MiningRatesTokenIndex: Parameter + Member + AtLeast32Bit + Bounded + Default + Copy; + type MiningRatesTokenIndex: Parameter + Member + AtLeast32Bit + Bounded + Default + Copy + From + Into; type MiningRatesTokenTokenMXC: Parameter + Member + AtLeast32Bit + Bounded + Default + Copy; type MiningRatesTokenTokenIOTA: Parameter + Member + AtLeast32Bit + Bounded + Default + Copy; type MiningRatesTokenTokenDOT: Parameter + Member + AtLeast32Bit + Bounded + Default + Copy; @@ -303,7 +303,7 @@ impl Module { fn random_value(sender: &T::AccountId) -> [u8; 16] { let payload = ( - T::Randomness::random(&[0]), + ::Randomness::random(&[0]), sender, >::extrinsic_index(), >::block_number(), diff --git a/pallets/mining/sampling/hardware/src/lib.rs b/pallets/mining/sampling/hardware/src/lib.rs index 586bf0827..8bc11da00 100644 --- a/pallets/mining/sampling/hardware/src/lib.rs +++ b/pallets/mining/sampling/hardware/src/lib.rs @@ -352,7 +352,7 @@ impl Module { fn random_value(sender: &T::AccountId) -> [u8; 16] { let payload = ( - T::Randomness::random(&[0]), + ::Randomness::random(&[0]), sender, >::extrinsic_index(), >::block_number(), diff --git a/pallets/mining/sampling/token-mining/src/lib.rs b/pallets/mining/sampling/token-mining/src/lib.rs index 4108857c9..23eb9a68c 100644 --- a/pallets/mining/sampling/token-mining/src/lib.rs +++ b/pallets/mining/sampling/token-mining/src/lib.rs @@ -370,7 +370,7 @@ impl Module { fn random_value(sender: &T::AccountId) -> [u8; 16] { let payload = ( - T::Randomness::random(&[0]), + ::Randomness::random(&[0]), sender, >::extrinsic_index(), >::block_number(), diff --git a/pallets/mining/sampling/token/src/lib.rs b/pallets/mining/sampling/token/src/lib.rs index 59fef00fe..ddc7e44de 100644 --- a/pallets/mining/sampling/token/src/lib.rs +++ b/pallets/mining/sampling/token/src/lib.rs @@ -349,7 +349,7 @@ impl Module { fn random_value(sender: &T::AccountId) -> [u8; 16] { let payload = ( - T::Randomness::random(&[0]), + ::Randomness::random(&[0]), sender, >::extrinsic_index(), >::block_number(), diff --git a/pallets/roaming/roaming-accounting-policies/src/lib.rs b/pallets/roaming/roaming-accounting-policies/src/lib.rs index 516da1750..1a2194069 100644 --- a/pallets/roaming/roaming-accounting-policies/src/lib.rs +++ b/pallets/roaming/roaming-accounting-policies/src/lib.rs @@ -379,7 +379,7 @@ impl Module { fn random_value(sender: &T::AccountId) -> [u8; 16] { let payload = ( - T::Randomness::random(&[0]), + ::Randomness::random(&[0]), sender, >::extrinsic_index(), >::block_number(), diff --git a/pallets/roaming/roaming-agreement-policies/src/lib.rs b/pallets/roaming/roaming-agreement-policies/src/lib.rs index 99603f5b6..000c19d64 100644 --- a/pallets/roaming/roaming-agreement-policies/src/lib.rs +++ b/pallets/roaming/roaming-agreement-policies/src/lib.rs @@ -452,7 +452,7 @@ impl Module { fn random_value(sender: &T::AccountId) -> [u8; 16] { let payload = ( - T::Randomness::random(&[0]), + ::Randomness::random(&[0]), sender, >::extrinsic_index(), >::block_number(), diff --git a/pallets/roaming/roaming-billing-policies/src/lib.rs b/pallets/roaming/roaming-billing-policies/src/lib.rs index 26701da5e..8755eb379 100644 --- a/pallets/roaming/roaming-billing-policies/src/lib.rs +++ b/pallets/roaming/roaming-billing-policies/src/lib.rs @@ -427,7 +427,7 @@ impl Module { fn random_value(sender: &T::AccountId) -> [u8; 16] { let payload = ( - T::Randomness::random(&[0]), + ::Randomness::random(&[0]), sender, >::extrinsic_index(), >::block_number(), diff --git a/pallets/roaming/roaming-charging-policies/src/lib.rs b/pallets/roaming/roaming-charging-policies/src/lib.rs index a1abae433..db4040ecb 100644 --- a/pallets/roaming/roaming-charging-policies/src/lib.rs +++ b/pallets/roaming/roaming-charging-policies/src/lib.rs @@ -440,7 +440,7 @@ impl Module { fn random_value(sender: &T::AccountId) -> [u8; 16] { let payload = ( - T::Randomness::random(&[0]), + ::Randomness::random(&[0]), sender, >::extrinsic_index(), >::block_number(), diff --git a/pallets/roaming/roaming-device-profiles/src/lib.rs b/pallets/roaming/roaming-device-profiles/src/lib.rs index f2e1adf13..aec3dbe93 100644 --- a/pallets/roaming/roaming-device-profiles/src/lib.rs +++ b/pallets/roaming/roaming-device-profiles/src/lib.rs @@ -367,7 +367,7 @@ impl Module { fn random_value(sender: &T::AccountId) -> [u8; 16] { let payload = ( - T::Randomness::random(&[0]), + ::Randomness::random(&[0]), sender, >::extrinsic_index(), >::block_number(), diff --git a/pallets/roaming/roaming-devices/src/lib.rs b/pallets/roaming/roaming-devices/src/lib.rs index 348d12a19..f842f99ab 100644 --- a/pallets/roaming/roaming-devices/src/lib.rs +++ b/pallets/roaming/roaming-devices/src/lib.rs @@ -348,7 +348,7 @@ impl Module { fn random_value(sender: &T::AccountId) -> [u8; 16] { let payload = ( - T::Randomness::random(&[0]), + ::Randomness::random(&[0]), sender, >::extrinsic_index(), >::block_number(), diff --git a/pallets/roaming/roaming-network-profiles/src/lib.rs b/pallets/roaming/roaming-network-profiles/src/lib.rs index 6d09cab90..67f67a3c0 100644 --- a/pallets/roaming/roaming-network-profiles/src/lib.rs +++ b/pallets/roaming/roaming-network-profiles/src/lib.rs @@ -714,7 +714,7 @@ impl Module { fn random_value(sender: &T::AccountId) -> [u8; 16] { let payload = ( - T::Randomness::random(&[0]), + ::Randomness::random(&[0]), sender, >::extrinsic_index(), >::block_number(), diff --git a/pallets/roaming/roaming-network-servers/src/lib.rs b/pallets/roaming/roaming-network-servers/src/lib.rs index b9a7f5bed..360e9765f 100644 --- a/pallets/roaming/roaming-network-servers/src/lib.rs +++ b/pallets/roaming/roaming-network-servers/src/lib.rs @@ -346,7 +346,7 @@ impl Module { fn random_value(sender: &T::AccountId) -> [u8; 16] { let payload = ( - T::Randomness::random(&[0]), + ::Randomness::random(&[0]), sender, >::extrinsic_index(), >::block_number(), diff --git a/pallets/roaming/roaming-networks/src/lib.rs b/pallets/roaming/roaming-networks/src/lib.rs index 13a665d92..3cbbd0a16 100644 --- a/pallets/roaming/roaming-networks/src/lib.rs +++ b/pallets/roaming/roaming-networks/src/lib.rs @@ -261,7 +261,7 @@ impl Module { fn random_value(sender: &T::AccountId) -> [u8; 16] { let payload = ( - T::Randomness::random(&[0]), + ::Randomness::random(&[0]), sender, >::extrinsic_index(), >::block_number(), diff --git a/pallets/roaming/roaming-operators/src/lib.rs b/pallets/roaming/roaming-operators/src/lib.rs index 331afa8d2..e94e5c94e 100644 --- a/pallets/roaming/roaming-operators/src/lib.rs +++ b/pallets/roaming/roaming-operators/src/lib.rs @@ -184,7 +184,7 @@ impl Module { fn random_value(sender: &T::AccountId) -> [u8; 16] { let payload = ( - T::Randomness::random(&[0]), + ::Randomness::random(&[0]), sender, >::extrinsic_index(), >::block_number(), diff --git a/pallets/roaming/roaming-organizations/src/lib.rs b/pallets/roaming/roaming-organizations/src/lib.rs index f8e70f9eb..93fe93b31 100644 --- a/pallets/roaming/roaming-organizations/src/lib.rs +++ b/pallets/roaming/roaming-organizations/src/lib.rs @@ -276,7 +276,7 @@ impl Module { fn random_value(sender: &T::AccountId) -> [u8; 16] { let payload = ( - T::Randomness::random(&[0]), + ::Randomness::random(&[0]), sender, >::extrinsic_index(), >::block_number(), diff --git a/pallets/roaming/roaming-packet-bundles/src/lib.rs b/pallets/roaming/roaming-packet-bundles/src/lib.rs index 1c42c99e4..f3c34247e 100644 --- a/pallets/roaming/roaming-packet-bundles/src/lib.rs +++ b/pallets/roaming/roaming-packet-bundles/src/lib.rs @@ -606,7 +606,7 @@ impl Module { fn random_value(sender: &T::AccountId) -> [u8; 16] { let payload = ( - T::Randomness::random(&[0]), + ::Randomness::random(&[0]), sender, >::extrinsic_index(), >::block_number(), diff --git a/pallets/roaming/roaming-routing-profiles/src/lib.rs b/pallets/roaming/roaming-routing-profiles/src/lib.rs index 54a459017..1995ba4e7 100644 --- a/pallets/roaming/roaming-routing-profiles/src/lib.rs +++ b/pallets/roaming/roaming-routing-profiles/src/lib.rs @@ -249,7 +249,7 @@ impl Module { fn random_value(sender: &T::AccountId) -> [u8; 16] { let payload = ( - T::Randomness::random(&[0]), + ::Randomness::random(&[0]), sender, >::extrinsic_index(), >::block_number(), diff --git a/pallets/roaming/roaming-service-profiles/src/lib.rs b/pallets/roaming/roaming-service-profiles/src/lib.rs index 4331de75e..e073efdd1 100644 --- a/pallets/roaming/roaming-service-profiles/src/lib.rs +++ b/pallets/roaming/roaming-service-profiles/src/lib.rs @@ -287,7 +287,7 @@ impl Module { fn random_value(sender: &T::AccountId) -> [u8; 16] { let payload = ( - T::Randomness::random(&[0]), + ::Randomness::random(&[0]), sender, >::extrinsic_index(), >::block_number(), diff --git a/pallets/roaming/roaming-sessions/src/lib.rs b/pallets/roaming/roaming-sessions/src/lib.rs index a2ec70f3e..8616fefa0 100644 --- a/pallets/roaming/roaming-sessions/src/lib.rs +++ b/pallets/roaming/roaming-sessions/src/lib.rs @@ -456,7 +456,7 @@ impl Module { fn random_value(sender: &T::AccountId) -> [u8; 16] { let payload = ( - T::Randomness::random(&[0]), + ::Randomness::random(&[0]), sender, >::extrinsic_index(), >::block_number(), diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 2ea5b68fd..5e5f77960 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -64,7 +64,6 @@ std = [ 'mining-eligibility-hardware/std', 'mining-claims-token/std', 'mining-claims-hardware/std', - 'mining-execution-token/std', 'exchange-rate/std', ] @@ -130,7 +129,6 @@ mining-eligibility-token = { default_features = false, package = 'mining-eligibi mining-eligibility-hardware = { default_features = false, package = 'mining-eligibility-hardware', path = '../pallets/mining/eligibility/hardware' } mining-claims-token = { default_features = false, package = 'mining-claims-token', path = '../pallets/mining/claims/token' } mining-claims-hardware = { default_features = false, package = 'mining-claims-hardware', path = '../pallets/mining/claims/hardware' } -mining-execution-token = { default_features = false, package = 'mining-execution-token', path = '../pallets/mining/execution/token' } exchange-rate = { default_features = false, package = 'exchange-rate', path = '../pallets/exchange-rate' } module-primitives = { default-features = false, path = '../pallets/primitives' } diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 0aa1748ea..ef5135c0e 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -320,7 +320,7 @@ parameter_types! { pub const CouncilMaxMembers: u32 = 100; } -type GeneralCouncilInstance = pallet_collective::Instance1; +pub type GeneralCouncilInstance = pallet_collective::Instance1; impl pallet_collective::Trait for Runtime { type DefaultVote = pallet_collective::PrimeDefaultVote; type Event = Event; @@ -543,7 +543,6 @@ impl roaming_devices::Trait for Runtime { impl roaming_routing_profiles::Trait for Runtime { type Event = Event; - // https://polkadot.js.org/api/types/#primitive-types type RoamingRoutingProfileAppServer = Vec; type RoamingRoutingProfileIndex = u64; } @@ -566,7 +565,7 @@ impl roaming_accounting_policies::Trait for Runtime { impl roaming_agreement_policies::Trait for Runtime { type Event = Event; type RoamingAgreementPolicyActivationType = Vec; - type RoamingAgreementPolicyIndex = u64; // as Trait>::Moment` timestamp::Module::Moment; + type RoamingAgreementPolicyIndex = u64; } impl roaming_network_profiles::Trait for Runtime { @@ -608,28 +607,18 @@ impl roaming_packet_bundles::Trait for Runtime { } impl mining_config_token::Trait for Runtime { + type Currency = Balances; type Event = Event; - // FIXME - restore when stop temporarily using roaming-operators - // type Currency = Balances; - // type Randomness = RandomnessCollectiveFlip; type MiningConfigTokenIndex = u64; type MiningConfigTokenLockAmount = u64; - // Mining Speed Boost Token Mining Config - // FIXME - how to use this enum from std? (including importing `use std::str::FromStr;`) type MiningConfigTokenType = Vec; } impl mining_config_hardware::Trait for Runtime { type Event = Event; type MiningConfigHardwareDevEUI = u64; - // type MiningConfigHardwareType = - // MiningConfigHardwareTypes; type MiningConfigHardwareID = u64; - // FIXME - restore when stop temporarily using roaming-operators - // type Currency = Balances; - // type Randomness = RandomnessCollectiveFlip; type MiningConfigHardwareIndex = u64; - // Mining Speed Boost Hardware Mining Config type MiningConfigHardwareSecure = bool; // FIXME - how to use this enum from std? (including importing `use std::str::FromStr;`) type MiningConfigHardwareType = Vec; @@ -700,11 +689,6 @@ impl mining_claims_hardware::Trait for Runtime { type MiningClaimsHardwareIndex = u64; } -impl mining_execution_token::Trait for Runtime { - type Event = Event; - type MiningExecutionTokenIndex = u64; -} - impl exchange_rate::Trait for Runtime { type DOTRate = u64; type DecimalsAfterPoint = u32; @@ -761,7 +745,6 @@ construct_runtime!( MiningEligibilityHardware: mining_eligibility_hardware::{Module, Call, Storage, Event}, MiningClaimsToken: mining_claims_token::{Module, Call, Storage, Event}, MiningClaimsHardware: mining_claims_hardware::{Module, Call, Storage, Event}, - MiningExecutionToken: mining_execution_token::{Module, Call, Storage, Event}, ExchangeRate: exchange_rate::{Module, Call, Storage, Event}, } ); diff --git a/runtime/tests/cli_integration_tests_mining_tokens.rs b/runtime/tests/cli_integration_tests_mining_tokens.rs index bfee5786b..41008431f 100644 --- a/runtime/tests/cli_integration_tests_mining_tokens.rs +++ b/runtime/tests/cli_integration_tests_mining_tokens.rs @@ -2,7 +2,6 @@ extern crate mining_claims_token as mining_claims_token; extern crate mining_config_token as mining_config_token; extern crate mining_eligibility_token as mining_eligibility_token; -extern crate mining_execution_token as mining_execution_token; extern crate mining_rates_token as mining_rates_token; extern crate mining_sampling_token as mining_sampling_token; extern crate roaming_operators as roaming_operators; @@ -15,12 +14,23 @@ mod tests { assert_ok, impl_outer_origin, parameter_types, + traits::{ + Contains, + ContainsLengthBound, + }, weights::{ IdentityFee, Weight, }, }; - + use std::cell::RefCell; + use sp_core::{ + u32_trait::{ + _2, + _3, + _4, + }, + }; use sp_core::H256; use sp_runtime::{ testing::Header, @@ -30,7 +40,9 @@ mod tests { Zero, }, DispatchResult, + ModuleId, Perbill, + Percent, Permill, }; // Import Trait for each runtime module being tested @@ -42,6 +54,7 @@ mod tests { use mining_config_token::{ MiningConfigTokenConfig, MiningConfigTokenRequirementsConfig, + MiningConfigTokenExecutionResult, Module as MiningConfigTokenModule, Trait as MiningConfigTokenTrait, }; @@ -50,11 +63,6 @@ mod tests { Module as MiningEligibilityTokenModule, Trait as MiningEligibilityTokenTrait, }; - use mining_execution_token::{ - MiningExecutionTokenExecutionResult, - Module as MiningExecutionTokenModule, - Trait as MiningExecutionTokenTrait, - }; use mining_rates_token::{ MiningRatesTokenConfig, Module as MiningRatesTokenModule, @@ -65,6 +73,10 @@ mod tests { Module as MiningSamplingTokenModule, Trait as MiningSamplingTokenTrait, }; + use datahighway_runtime::{ + AccountId, + Balance, + }; use roaming_operators; // pub fn origin_of(who: &AccountId) -> ::Origin { @@ -130,6 +142,83 @@ mod tests { type TransactionByteFee = (); type WeightToFee = IdentityFee; } + + thread_local! { + static TEN_TO_FOURTEEN: RefCell> = RefCell::new(vec![10,11,12,13,14]); + } + pub struct TenToFourteen; + impl Contains for TenToFourteen { + fn sorted_members() -> Vec { + TEN_TO_FOURTEEN.with(|v| v.borrow().clone()) + } + + #[cfg(feature = "runtime-benchmarks")] + fn add(new: &u64) { + TEN_TO_FOURTEEN.with(|v| { + let mut members = v.borrow_mut(); + members.push(*new); + members.sort(); + }) + } + } + impl ContainsLengthBound for TenToFourteen { + fn max_len() -> usize { + TEN_TO_FOURTEEN.with(|v| v.borrow().len()) + } + + fn min_len() -> usize { + 0 + } + } + + // Copied from ./runtime/src/constants.rs + const MILLISECS_PER_BLOCK: u64 = 4320; + const MINUTES: u64 = 60_000 / (MILLISECS_PER_BLOCK as u64); + const HOURS: u64 = MINUTES * 60; + const DAYS: u64 = HOURS * 24; + parameter_types! { + pub const ProposalBond: Permill = Permill::from_percent(5); + pub const ProposalBondMinimum: u64 = 1; + pub const SpendPeriod: u64 = 1 * DAYS; + pub const Burn: Permill = Permill::from_percent(0); + pub const TipCountdown: u64 = 1 * DAYS; + pub const TipFindersFee: Percent = Percent::from_percent(20); + pub const TipReportDepositBase: u64 = 1; + pub const MaximumReasonLength: u32 = 16384; + pub const BountyValueMinimum: u64 = 1; + pub const BountyCuratorDeposit: Permill = Permill::from_percent(50); + pub const BountyDepositBase: u64 = 80; + pub const BountyDepositPayoutDelay: u32 = 3; + pub const BountyUpdatePeriod: u32 = 20; + pub const DataDepositPerByte: u64 = 1; + pub const TreasuryModuleId: ModuleId = ModuleId(*b"py/trsry"); + } + impl pallet_treasury::Trait for Test { + type ApproveOrigin = frame_system::EnsureRoot; + type BountyCuratorDeposit = BountyCuratorDeposit; + type BountyDepositBase = BountyDepositBase; + type BountyDepositPayoutDelay = BountyDepositPayoutDelay; + type BountyUpdatePeriod = BountyUpdatePeriod; + type BountyValueMinimum = BountyValueMinimum; + type Burn = Burn; + type BurnDestination = (); + type Currency = Balances; + type DataDepositPerByte = DataDepositPerByte; + type Event = (); + type MaximumReasonLength = MaximumReasonLength; + type ModuleId = TreasuryModuleId; + type OnSlash = (); + type ProposalBond = ProposalBond; + type ProposalBondMinimum = ProposalBondMinimum; + type RejectOrigin = frame_system::EnsureRoot; + type SpendPeriod = SpendPeriod; + type TipCountdown = TipCountdown; + type TipFindersFee = TipFindersFee; + type TipReportDepositBase = TipReportDepositBase; + type Tippers = TenToFourteen; + // Just gets burned. + type WeightInfo = (); + } // FIXME - remove this when figure out how to use these types within mining-speed-boost runtime module itself impl roaming_operators::Trait for Test { type Currency = Balances; @@ -138,24 +227,19 @@ mod tests { type RoamingOperatorIndex = u64; } impl MiningConfigTokenTrait for Test { + type Currency = Balances; type Event = (); - // type Currency = Balances; - // type Randomness = Randomness; type MiningConfigTokenIndex = u64; type MiningConfigTokenLockAmount = u64; - // Mining Speed Boost Token Mining Config - // FIXME - how to use this enum from std? (including importing `use std::str::FromStr;`) type MiningConfigTokenType = Vec; } impl MiningRatesTokenTrait for Test { type Event = (); type MiningRatesTokenIndex = u64; type MiningRatesTokenMaxLoyalty = u32; - // Mining Speed Boost Max Rates type MiningRatesTokenMaxToken = u32; type MiningRatesTokenTokenDOT = u32; type MiningRatesTokenTokenIOTA = u32; - // Mining Speed Boost Rate type MiningRatesTokenTokenMXC = u32; } impl MiningSamplingTokenTrait for Test { @@ -175,10 +259,6 @@ mod tests { type MiningClaimsTokenClaimAmount = u64; type MiningClaimsTokenIndex = u64; } - impl MiningExecutionTokenTrait for Test { - type Event = (); - type MiningExecutionTokenIndex = u64; - } type System = frame_system::Module; pub type Balances = pallet_balances::Module; @@ -187,7 +267,6 @@ mod tests { pub type MiningSamplingTokenTestModule = MiningSamplingTokenModule; pub type MiningEligibilityTokenTestModule = MiningEligibilityTokenModule; pub type MiningClaimsTokenTestModule = MiningClaimsTokenModule; - pub type MiningExecutionTokenTestModule = MiningExecutionTokenModule; type Randomness = pallet_randomness_collective_flip::Module; // This function basically just builds a genesis storage key/value store according to @@ -256,14 +335,14 @@ mod tests { // Call Functions assert_ok!(MiningConfigTokenTestModule::create(Origin::signed(0))); - assert_ok!(MiningConfigTokenTestModule::set_mining_config_token_token_cooldown_config( + assert_ok!(MiningConfigTokenTestModule::set_mining_config_token_cooldown_config( Origin::signed(0), 0, // mining_token_id Some(b"DHX".to_vec()), // token_type Some(10), // token_lock_min_amount Some(7), // token_lock_min_blocks )); - assert_ok!(MiningConfigTokenTestModule::set_mining_config_token_token_config( + assert_ok!(MiningConfigTokenTestModule::set_mining_config_token_config( Origin::signed(0), 0, // mining_token_id Some(b"MXC".to_vec()), // token_type @@ -277,7 +356,7 @@ mod tests { assert!(MiningConfigTokenTestModule::mining_config_token(0).is_some()); assert_eq!(MiningConfigTokenTestModule::mining_config_token_owner(0), Some(0)); assert_eq!( - MiningConfigTokenTestModule::mining_config_token_token_cooldown_configs(0), + MiningConfigTokenTestModule::mining_config_token_cooldown_configs(0), Some(MiningConfigTokenRequirementsConfig { token_type: b"DHX".to_vec(), // token_type token_lock_min_amount: 10, // token_lock_min_amount @@ -285,7 +364,7 @@ mod tests { }) ); assert_eq!( - MiningConfigTokenTestModule::mining_config_token_token_configs(0), + MiningConfigTokenTestModule::mining_config_token_configs(0), Some(MiningConfigTokenConfig { token_type: b"MXC".to_vec(), // token_type token_lock_amount: 100, // token_lock_amount @@ -428,37 +507,44 @@ mod tests { }) ); - // Create Mining Speed Boost Execution Token Mining - - // Call Functions - assert_ok!(MiningExecutionTokenTestModule::create(Origin::signed(0))); - assert_ok!(MiningExecutionTokenTestModule::assign_execution_to_configuration(Origin::signed(0), 0, 0)); + // Create Mining Speed Boost Config Token Mining // Override by DAO if necessary // // Execute is called to start the mining if all checks pass - assert_ok!(MiningExecutionTokenTestModule::set_mining_execution_token_execution_result( + assert_ok!(MiningConfigTokenTestModule::set_mining_config_token_execution_result( Origin::signed(0), 0, // mining_config_token_id - 0, // mining_execution_token_id - Some(12345), // token_execution_started_block - Some(34567) // token_execution_ended_block )); // Verify Storage - assert_eq!(MiningExecutionTokenTestModule::mining_execution_token_count(), 1); - assert!(MiningExecutionTokenTestModule::mining_execution_token(0).is_some()); - assert_eq!(MiningExecutionTokenTestModule::mining_execution_token_owner(0), Some(0)); + assert_eq!(MiningConfigTokenTestModule::mining_config_token_count(), 1); + assert!(MiningConfigTokenTestModule::mining_config_token(0).is_some()); + assert_eq!(MiningConfigTokenTestModule::mining_config_token_owner(0), Some(0)); + // Note: Refer to Edgeware's tests that use on_finalize https://github.com/hicommonwealth/edgeware-node/blob/master/modules/edge-treasury-reward/src/tests.rs#L177 + System::set_block_number(0); assert_eq!( - MiningExecutionTokenTestModule::mining_execution_token_execution_results((0, 0)), - Some(MiningExecutionTokenExecutionResult { + MiningConfigTokenTestModule::mining_config_token_execution_results(0u64), + Some(MiningConfigTokenExecutionResult { token_execution_executor_account_id: 0, token_execution_started_block: 12345, - token_execution_ended_block: 34567, + token_execution_interval_blocks: 34567, }) ); + // TODO - check that the locked amount has actually been locked and check that a sampling, eligibility, and // claim were all run automatically afterwards assert!(false); + // + // how to get the lock info for a given lock identifier using frame_support's methods? + // https://substrate.dev/rustdocs/v3.0.0/frame_support/traits/trait.LockableCurrency.html#required-methods + // + // Or is it going to be necessary to implement our own custom lock pallet that adds this? + // https://github.com/kulupu/kulupu/blob/master/frame/lockdrop/src/lib.rs#L238 + // + // See question posted here https://matrix.to/#/!HzySYSaIhtyWrwiwEV:matrix.org/$161495341266906GzpcB:matrix.org?via=matrix.parity.io&via=matrix.org&via=corepaper.org + + // TODO - allow user to request to stop mining, and trigger the cooldown period until they can + // access their tokens that are locked for mining. }); } }