diff --git a/Cargo.lock b/Cargo.lock index b025942c6..4864df16a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13353,11 +13353,13 @@ dependencies = [ "pallet-im-online", "pallet-indices", "pallet-insecure-randomness-collective-flip", + "pallet-jobs", "pallet-multisig", "pallet-nomination-pools", "pallet-offences", "pallet-preimage", "pallet-proxy", + "pallet-roles", "pallet-scheduler", "pallet-session", "pallet-staking", diff --git a/node/src/chainspec/mainnet.rs b/node/src/chainspec/mainnet.rs index 547066202..42d64717c 100644 --- a/node/src/chainspec/mainnet.rs +++ b/node/src/chainspec/mainnet.rs @@ -23,6 +23,7 @@ use crate::{ mainnet_fixtures::{get_bootnodes, get_initial_authorities, get_root_key}, }; use core::marker::PhantomData; +use hex_literal::hex; use pallet_airdrop_claims::MultiAddress; use pallet_im_online::sr25519::AuthorityId as ImOnlineId; use sc_consensus_grandpa::AuthorityId as GrandpaId; @@ -35,10 +36,10 @@ use sp_runtime::{ }; use tangle_primitives::types::{BlockNumber, Signature}; use tangle_runtime::{ - AccountId, BabeConfig, Balance, BalancesConfig, ClaimsConfig, EVMChainIdConfig, - Eth2ClientConfig, ImOnlineConfig, MaxVestingSchedules, Perbill, RuntimeGenesisConfig, - SessionConfig, StakerStatus, StakingConfig, SudoConfig, SystemConfig, TreasuryPalletId, - VestingConfig, UNIT, WASM_BINARY, + AccountId, BabeConfig, Balance, BalancesConfig, ClaimsConfig, CouncilConfig, EVMChainIdConfig, + Eth2ClientConfig, ImOnlineConfig, MaxVestingSchedules, Perbill, RoleKeyId, + RuntimeGenesisConfig, SessionConfig, StakerStatus, StakingConfig, SudoConfig, SystemConfig, + TreasuryPalletId, VestingConfig, UNIT, WASM_BINARY, }; use webb_consensus_types::network_config::{Network, NetworkConfig}; @@ -64,14 +65,14 @@ where /// Generate an babe authority key. pub fn authority_keys_from_seed( - controller: &str, stash: &str, -) -> (AccountId, BabeId, GrandpaId, ImOnlineId) { +) -> (AccountId, BabeId, GrandpaId, ImOnlineId, RoleKeyId) { ( get_account_id_from_seed::(stash), - get_from_seed::(controller), - get_from_seed::(controller), + get_from_seed::(stash), + get_from_seed::(stash), get_from_seed::(stash), + get_from_seed::(stash), ) } @@ -83,8 +84,9 @@ fn generate_session_keys( babe: BabeId, grandpa: GrandpaId, im_online: ImOnlineId, + role: RoleKeyId, ) -> tangle_runtime::opaque::SessionKeys { - tangle_runtime::opaque::SessionKeys { babe, grandpa, im_online } + tangle_runtime::opaque::SessionKeys { babe, grandpa, im_online, role } } pub fn local_mainnet_config(chain_id: u64) -> Result { @@ -94,6 +96,8 @@ pub fn local_mainnet_config(chain_id: u64) -> Result { properties.insert("tokenDecimals".into(), 18u32.into()); properties.insert("ss58Format".into(), tangle_primitives::MAINNET_SS58_PREFIX.into()); + let endowment: Balance = 10_000_000 * UNIT; + Ok(ChainSpec::from_genesis( "Local Tangle Mainnet", "local-tangle-mainnet", @@ -103,18 +107,15 @@ pub fn local_mainnet_config(chain_id: u64) -> Result { // Wasm binary wasm_binary, // Initial validators - vec![ - authority_keys_from_seed("Alice", "Alice//stash"), - authority_keys_from_seed("Bob", "Bob//stash"), - ], + vec![authority_keys_from_seed("Alice"), authority_keys_from_seed("Bob")], // Endowed accounts vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Charlie"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), - get_account_id_from_seed::("Charlie//stash"), + (get_account_id_from_seed::("Alice"), endowment), + (get_account_id_from_seed::("Bob"), endowment), + (get_account_id_from_seed::("Charlie"), endowment), + (get_account_id_from_seed::("Alice//stash"), endowment), + (get_account_id_from_seed::("Bob//stash"), endowment), + (get_account_id_from_seed::("Charlie//stash"), endowment), ], // Sudo account get_account_id_from_seed::("Alice"), @@ -166,7 +167,7 @@ pub fn tangle_mainnet_config(chain_id: u64) -> Result { // Initial validators get_initial_authorities(), // Endowed accounts - vec![], + vec![mainnet::get_treasury_balance()], // Sudo account get_root_key(), // EVM chain ID @@ -181,6 +182,7 @@ pub fn tangle_mainnet_config(chain_id: u64) -> Result { combine_distributions(vec![ mainnet::get_team_balance_distribution(), mainnet::get_investor_balance_distribution(), + mainnet::get_foundation_balance_distribution(), ]), ) }, @@ -203,14 +205,13 @@ pub fn tangle_mainnet_config(chain_id: u64) -> Result { #[allow(clippy::too_many_arguments)] fn mainnet_genesis( wasm_binary: &[u8], - initial_authorities: Vec<(AccountId, BabeId, GrandpaId, ImOnlineId)>, - endowed_accounts: Vec, + initial_authorities: Vec<(AccountId, BabeId, GrandpaId, ImOnlineId, RoleKeyId)>, + endowed_accounts: Vec<(AccountId, Balance)>, root_key: AccountId, chain_id: u64, genesis_airdrop: DistributionResult, genesis_non_airdrop: Vec<(MultiAddress, u128, u64, u64, u128)>, ) -> RuntimeGenesisConfig { - const ENDOWMENT: Balance = 10_000_000 * UNIT; // stakers: all validators and nominators. let stakers = initial_authorities .iter() @@ -242,7 +243,7 @@ fn mainnet_genesis( balances: genesis_non_airdrop .iter() .map(|(x, y, _, _, _)| (x.clone().to_account_id_32(), *y)) - .chain(endowed_accounts.iter().map(|k| (k.clone(), ENDOWMENT))) + .chain(endowed_accounts) .collect(), }, vesting: VestingConfig { @@ -259,7 +260,7 @@ fn mainnet_genesis( ( x.0.clone(), x.0.clone(), - generate_session_keys(x.1.clone(), x.2.clone(), x.3.clone()), + generate_session_keys(x.1.clone(), x.2.clone(), x.3.clone(), x.4.clone()), ) }) .collect::>(), @@ -273,7 +274,16 @@ fn mainnet_genesis( ..Default::default() }, democracy: Default::default(), - council: Default::default(), + council: CouncilConfig { + members: vec![ + hex!["483b466832e094f01b1779a7ed07025df319c492dac5160aca89a3be117a7b6d"].into(), + hex!["86d08e7bbe77bc74e3d88ee22edc53368bc13d619e05b66fe6c4b8e2d5c7015a"].into(), + hex!["e421301e5aa5dddee51f0d8c73e794df16673e53157c5ea657be742e35b1793f"].into(), + hex!["4ce3a4da3a7c1ce65f7edeff864dc3dd42e8f47eecc2726d99a0a80124698217"].into(), + hex!["dcd9b70a0409b7626cba1a4016d8da19f4df5ce9fc5e8d16b789e71bb1161d73"].into(), + ], + ..Default::default() + }, elections: Default::default(), treasury: Default::default(), babe: BabeConfig { diff --git a/node/src/distributions/data/webb_investor_distributions.json b/node/src/distributions/data/webb_investor_distributions.json new file mode 100644 index 000000000..64fe6709b --- /dev/null +++ b/node/src/distributions/data/webb_investor_distributions.json @@ -0,0 +1,17 @@ +{ + "5FCviiKcJzVfdwqv451JRQc93ZTSbbC9YfgKMkN3LpNMBjS3": 100000000000000000000000, + "5HACeo1RgsWydRP3CaFRZfrd56KAYQbAFasLaWZ8fsF1NzxA": 150000000000000000000000, + "5HBKM8XL7sr7S7qx6ukugDJUBhm16Ubnz1KuJCdHmHQvtc7Z": 400000000000000000000000, + "5Dx1xiArcKt7CbB1yzMVM6VJHzuF3Tezj3R9opMzpEHAt1mC": 100000000000000000000000, + "5H3GqqyhvvYfQdbMbRZfkkuBKrGSv9i2NPktxJrYSGWjQSNV": 7000000000000000000000000, + "5H3GqqyhvvYfQdbMbRZfkkuBKrGSv9i2NPktxJrYSGWjQSNV": 5500000000000000000000000, + "5H3GqqyhvvYfQdbMbRZfkkuBKrGSv9i2NPktxJrYSGWjQSNV": 1000000000000000000000000, + "5H3GqqyhvvYfQdbMbRZfkkuBKrGSv9i2NPktxJrYSGWjQSNV": 200000000000000000000000, + "5H3GqqyhvvYfQdbMbRZfkkuBKrGSv9i2NPktxJrYSGWjQSNV": 100000000000000000000000, + "5FerzxKQZoP9wxjRhS1PHA4v27aPQMoZpXmufcQk1JYE5xU8": 100000000000000000000000, + "5H3GqqyhvvYfQdbMbRZfkkuBKrGSv9i2NPktxJrYSGWjQSNV": 150000000000000000000000, + "5H3GqqyhvvYfQdbMbRZfkkuBKrGSv9i2NPktxJrYSGWjQSNV": 1000000000000000000000000, + "5H3GqqyhvvYfQdbMbRZfkkuBKrGSv9i2NPktxJrYSGWjQSNV": 20000000000000000000000, + "5CXgx89yUwPLjEzsABzieLbS8HuRUTTVT13hqhmAbaackjPb": 20000000000000000000000, + "5DDTvr7P2MaUirj3rSvpcF5DLxECiAqpQegdVCzAuwxingVC": 50000000000000000000000 +} \ No newline at end of file diff --git a/node/src/distributions/mainnet.rs b/node/src/distributions/mainnet.rs index 5526e3238..889655e38 100644 --- a/node/src/distributions/mainnet.rs +++ b/node/src/distributions/mainnet.rs @@ -14,16 +14,14 @@ // // You should have received a copy of the GNU General Public License // along with Tangle. If not, see . -use std::str::FromStr; -use tangle_primitives::types::BlockNumber; -use tangle_runtime::UNIT; - use super::testnet::{get_git_root, read_contents, read_contents_to_evm_accounts}; +use hex_literal::hex; use pallet_airdrop_claims::{EthereumAddress, MultiAddress, StatementKind}; use sp_core::H160; -use sp_runtime::AccountId32; -use std::collections::BTreeMap; -use tangle_testnet_runtime::{AccountId, Balance, ExistentialDeposit}; +use sp_runtime::{traits::AccountIdConversion, AccountId32}; +use std::{collections::BTreeMap, str::FromStr}; +use tangle_primitives::types::BlockNumber; +use tangle_runtime::{AccountId, Balance, ExistentialDeposit, Perbill, UNIT}; /// The contents of the file should be a map of accounts to balances. fn read_contents_to_substrate_accounts(path_str: &str) -> BTreeMap { @@ -44,6 +42,18 @@ fn read_contents_to_substrate_accounts(path_str: &str) -> BTreeMap Vec { read_contents_to_evm_accounts("node/src/distributions/data/edgeware_genesis_participants.json") } @@ -68,6 +78,12 @@ fn get_edgeware_snapshot_list() -> BTreeMap { ) } +fn get_investor_balance_distribution_list() -> BTreeMap { + read_contents_to_substrate_accounts( + "node/src/distributions/data/webb_investor_distribution.json", + ) +} + pub fn get_discord_list() -> Vec { read_contents_to_evm_accounts("node/src/distributions/data/discord_evm_addresses.json") } @@ -90,12 +106,12 @@ pub struct DistributionResult { pub vesting_cliff: BlockNumber, } -fn ninety_nine_percent_endowment(endowment: u128) -> u128 { - endowment * 99 / 100 +fn ninety_five_percent_endowment(endowment: u128) -> u128 { + endowment * 95 / 100 } -fn one_percent_endowment(endowment: u128) -> u128 { - endowment - ninety_nine_percent_endowment(endowment) +fn five_percent_endowment(endowment: u128) -> u128 { + endowment - ninety_five_percent_endowment(endowment) } fn vesting_per_block(endowment: u128, blocks: u64) -> u128 { @@ -103,6 +119,26 @@ fn vesting_per_block(endowment: u128, blocks: u64) -> u128 { endowment / blocks as u128 } +fn get_team_distribution_share() -> Perbill { + Perbill::from_rational(30_u32, 100_u32) +} + +fn get_investor_distribution_share() -> Perbill { + Perbill::from_rational(16_u32, 100_u32) +} + +fn get_foundation_distribution_share() -> Perbill { + Perbill::from_rational(15_u32, 100_u32) +} + +fn get_treasury_distribution_share() -> Perbill { + Perbill::from_rational(35_u32, 100_u32) +} + +fn get_initial_liquidity_share() -> Perbill { + Perbill::from_rational(5_u32, 100_u32) +} + pub fn get_edgeware_genesis_balance_distribution() -> DistributionResult { let list = get_edgeware_genesis_list(); let endowment = ONE_PERCENT_TOTAL_SUPPLY / list.len() as u128; @@ -178,15 +214,49 @@ pub fn get_substrate_balance_distribution() -> DistributionResult { } pub fn get_investor_balance_distribution() -> Vec<(MultiAddress, u128, u64, u64, u128)> { - // TODO : Read from actual investor file - let investor_accounts: Vec<(MultiAddress, u128)> = vec![]; - compute_balance_distribution_with_cliff_and_vesting(investor_accounts) + let investor_accounts: Vec<(MultiAddress, u128)> = get_investor_balance_distribution_list() + .into_iter() + .map(|(address, balance)| (MultiAddress::Native(address), balance as u128)) + .collect(); + compute_balance_distribution_with_cliff_and_vesting_no_endowment(investor_accounts) } pub fn get_team_balance_distribution() -> Vec<(MultiAddress, u128, u64, u64, u128)> { - // TODO : Read from actual team file - let team_accounts: Vec<(MultiAddress, u128)> = vec![]; - compute_balance_distribution_with_cliff_and_vesting(team_accounts) + let team_address: AccountId = + hex!["8e1c2bdddab9573d8cb094dbffba24a2b2c21b7e71e3f5b604e8607483872443"].into(); + let balance = + (get_team_distribution_share() - get_initial_liquidity_share()).mul_floor(TOTAL_SUPPLY); + let team_account = (MultiAddress::Native(team_address), balance as u128); + compute_balance_distribution_with_cliff_and_vesting(vec![team_account]) +} + +pub fn get_treasury_balance() -> (AccountId, u128) { + let pallet_id = tangle_primitives::treasury::TREASURY_PALLET_ID; + let acc: AccountId = pallet_id.into_account_truncating(); + + // any leftover from investors are sent to treasury + let investors_actual_spend = get_investor_balance_distribution_list() + .into_values() + .map(|balance| (balance as u128)) + .sum::(); + + let investors_actual_spend_as_percent = + Perbill::from_rational(investors_actual_spend, TOTAL_SUPPLY); + let leftover_from_investors = + get_investor_distribution_share() - investors_actual_spend_as_percent; + let leftover_amount = leftover_from_investors * TOTAL_SUPPLY; + + (acc, get_treasury_distribution_share() * TOTAL_SUPPLY + leftover_amount) +} + +pub fn get_foundation_balance_distribution() -> Vec<(MultiAddress, u128, u64, u64, u128)> { + let foundation_address: AccountId = + hex!["0cdd6ca9c578fabcc65373004944a401866d5c61568ffb22ecd8ef528599f95b"].into(); + let balance = get_foundation_distribution_share().mul_floor(TOTAL_SUPPLY) - + get_initial_liquidity_share() + .mul_floor(get_foundation_distribution_share().mul_floor(TOTAL_SUPPLY)); + let foundation_account = (MultiAddress::Native(foundation_address), balance as u128); + compute_balance_distribution_with_cliff_and_vesting(vec![foundation_account]) } pub fn compute_balance_distribution_with_cliff_and_vesting( @@ -200,7 +270,24 @@ pub fn compute_balance_distribution_with_cliff_and_vesting( value, ONE_YEAR_BLOCKS, TWO_YEARS_BLOCKS - ONE_YEAR_BLOCKS, - one_percent_endowment(value), + five_percent_endowment(value), + ) + }) + .collect() +} + +pub fn compute_balance_distribution_with_cliff_and_vesting_no_endowment( + investor_accounts: Vec<(MultiAddress, u128)>, +) -> Vec<(MultiAddress, u128, u64, u64, u128)> { + investor_accounts + .into_iter() + .map(|(address, value)| { + ( + address, + value, + ONE_YEAR_BLOCKS, + TWO_YEARS_BLOCKS - ONE_YEAR_BLOCKS, + Default::default(), ) }) .collect() @@ -215,7 +302,7 @@ pub fn get_distribution_for( let mut claims = vec![]; let mut vesting = vec![]; arr.into_iter().filter(|(_, value)| *value > 0).for_each(|(address, value)| { - let claimable_amount = one_percent_endowment(value); + let claimable_amount = five_percent_endowment(value); let vested_amount = value - claimable_amount; let cliff_fraction = vesting_cliff as f64 / total_vesting_schedule as f64; let remaining_fraction = 1.0 - cliff_fraction; @@ -253,7 +340,7 @@ fn test_compute_investor_balance_distribution() { // let compute the expected output // the expected output is that - // 1% is immedately release + // 5% is immedately release // 1 year cliff (vesting starts after year 1) // Vesting finishes 1 year after cliff let alice_expected_response: (MultiAddress, u128, u64, u64, u128) = ( @@ -261,14 +348,14 @@ fn test_compute_investor_balance_distribution() { amount_per_investor, tangle_primitives::time::DAYS * 365, // begins at one year after block 0 tangle_primitives::time::DAYS * 365, // num of blocks from beginning till fully vested - 1, // 1% of 100 + 5, // 5% of 100 ); let bob_expected_response: (MultiAddress, u128, u64, u64, u128) = ( bob.clone(), amount_per_investor, tangle_primitives::time::DAYS * 365, // begins at one year after block 0 tangle_primitives::time::DAYS * 365, // num of blocks from beging till fully vested - 1, // 1% of 100 + 5, // 5% of 100 ); assert_eq!( @@ -289,19 +376,19 @@ fn test_get_distribution_for() { // let compute the expected output // the expected output is that - // 1% is immedately claimable + // 5% is immedately claimable // 1 month cliff (vesting starts after 1 month) (use 1 for easier calculation) // at 1 month cliff, release 1/24th rewards // Vesting finishes after 2 years (use 24 for easier calculation) // 1/24th claimable at every month let expected_distibution_result = DistributionResult { claims: vec![ - (alice.clone(), 1, Some(StatementKind::Regular)), - (bob.clone(), 1, Some(StatementKind::Regular)), + (alice.clone(), 5, Some(StatementKind::Regular)), + (bob.clone(), 5, Some(StatementKind::Regular)), ], vesting: vec![ - (alice.clone(), vec![(4, 4, 1), (94, 4, 1)]), - (bob.clone(), vec![(4, 4, 1), (94, 4, 1)]), + (alice.clone(), vec![(3, 3, 1), (91, 3, 1)]), + (bob.clone(), vec![(3, 3, 1), (91, 3, 1)]), ], vesting_length: 24, vesting_cliff: 1, diff --git a/node/src/mainnet_fixtures.rs b/node/src/mainnet_fixtures.rs index 92bc5e0ed..b1654345b 100644 --- a/node/src/mainnet_fixtures.rs +++ b/node/src/mainnet_fixtures.rs @@ -20,12 +20,12 @@ use sc_consensus_grandpa::AuthorityId as GrandpaId; use sc_network::config::MultiaddrWithPeerId; use sp_consensus_babe::AuthorityId as BabeId; use sp_core::crypto::UncheckedInto; -use tangle_testnet_runtime::AccountId; +use tangle_crypto_primitives::crypto::AuthorityId as RoleKeyId; +use tangle_runtime::AccountId; /// Mainnet root key pub fn get_root_key() -> AccountId { - // Standalone sudo key: 5CDZpRSZ14TmXorHTsTeksY7223FzsaLXPbpTPBUV6NaZSr1 - hex!["06c225d97d596c57e620aba15e1a8a69c7b334ffdab175788c6553f7dd181a56"].into() + hex!["dc15b770b3cab4c43ab92173516482891c5f8ef4d42967f364bd2c52e0aebc0f"].into() } /// Mainnet bootnodes @@ -37,7 +37,7 @@ pub fn get_bootnodes() -> Vec { "/ip4/18.119.14.21/tcp/30333/p2p/12D3KooWJP5NbEjEK1YihofJm3MMSJWrbRWjeEkRf3LtKvkj6mr9" .parse() .unwrap(), - "/ip4/18.188.183.185/tcp/30333/p2p/12D3KooWDL3KiR6CpnEbgUgheje1cMGQtwH4euxGMPQBkwU5cZdu" + "/ip4/3.15.186.160/tcp/30333/p2p/12D3KooWDL3KiR6CpnEbgUgheje1cMGQtwH4euxGMPQBkwU5cZdu" .parse() .unwrap(), "/ip4/3.137.213.159/tcp/30333/p2p/12D3KooWS4aniCJTz2RiNfNUka8TTa3gXak63FJgdAgfAWLCnsAi" @@ -49,57 +49,127 @@ pub fn get_bootnodes() -> Vec { ] } -/// Standalone initial authorities -pub fn get_initial_authorities() -> Vec<(AccountId, BabeId, GrandpaId, ImOnlineId)> { +/// Tangle runtime initial authorities +pub fn get_initial_authorities() -> Vec<(AccountId, BabeId, GrandpaId, ImOnlineId, RoleKeyId)> { vec![ - // standalone 1 + // tangle 1 ( - hex!["6c99e8e4ae3fe7e3328d7e9d85eb98e86bdc6410695797349fa536ebb9bb0a4a"].into(), - hex!["d8a00a2454cd7455c040e363e6e76f4abd9e4d3876253964d9f40a66ad79694b"] + hex!["e4ee912e81516a503285ae59c0990ba5ef93941b3c185b456b84e7bc42c91013"].into(), + hex!["fc7094e63e424d4ca53438646b86cd402c3dbe6a958da834d1933715afe05e31"] .unchecked_into(), - hex!["5bcf983a969f8de7628b271a5bf523924856c3935b15eb3e03f20146ced2c57f"] + hex!["e2442a31fed9cc5cda6b70e15959cad5a9fbfb14e8784233374deabb05b6fa11"] .unchecked_into(), - hex!["0297bc051d94b25787482e60fa4eba19f15af30fa244240ae4439d219ee00e78"] + hex!["be408915b6cf6a5843cef444bbf66609125b251f0ff9d06d059bcc43a631737f"] + .unchecked_into(), + hex!["0208cca30a428925678d695ba02d8968e8a9f6798615a7a0093f8a4c2cd1b5a9fc"] + .unchecked_into(), + ), + // tangle 2 + ( + hex!["22e254b686c1f38823d9d4012c75b9afe44a51ed802485f189d8df2f99053472"].into(), + hex!["30fe2a18dbd35278c804267c61e00bebdc07d912b900d3af5b6df3bb6a35ed77"] + .unchecked_into(), + hex!["dcaef0b1c2e2d8fdeac4f07d60b3eb0d93564dba0c2e6bc5d0a63d775a4318da"] + .unchecked_into(), + hex!["cebebb5bf58a2a989bf8827d7360f04057835e42141162bfa17f3d12dde96a59"] + .unchecked_into(), + hex!["02596bcb7dfc93455d1e7bf93aa874d481590b37af0d43598506f9ed8609086ba0"] + .unchecked_into(), + ), + // tangle 3 + ( + hex!["c083df88dca627b873c972875d3570677ddc8ef7582041ca7c8c5bf6f04b1155"].into(), + hex!["ee9da837e817f7d87eab1df000f92257811a21b895d09653b4bcd44f7e08ff7e"] + .unchecked_into(), + hex!["2f9ea304466841d597eb02f2bdd4dc9f1d6c8a862f0e345220c01a1b2670b51c"] + .unchecked_into(), + hex!["401d823b728892f280ca65daefdcadb37cdc6e42c04be780a6bedde80906df6d"] + .unchecked_into(), + hex!["0301760025504e5f9bec992e1ef79c83c126b372658d676c2c9f51be4bca55c859"] .unchecked_into(), ), - // standalone 2 + // tangle 4 ( - hex!["444dbfd0220eb1a993a7a2b9e1530aee1d17388ba3db34a0ee2b8ff971bfd073"].into(), - hex!["f02ee9baa32c490cf06eabe3580a90be704618f04636b321ee599c8912392c7a"] + hex!["ec012c87ebfac36ab4a56fb19d7ef5561785fc5bc9a1fa380185ae6440f0196f"].into(), + hex!["66621351db6c9ddd0836df712e8838ad03c11d1703401f5f4b4d71a5c14d9b1e"] + .unchecked_into(), + hex!["6386c777558cfe531ca9bb86acc3479ebe8e301ec187f9ea2293a3c1ed309394"] .unchecked_into(), - hex!["2d6ac10cde791863771847c035c36e13ad60e6129465e1aefad8f5fee8dff5c7"] + hex!["de11737a302be3afcae7492c381b5aaaa4ca9449cba9042ffe9cada7b7b37e21"] .unchecked_into(), - hex!["de6d5010678fd2175fe70c857d3eba80838e3735b1051f4aed98671800ec483f"] + hex!["03c7f43daff671e51b56c51b0029903f41c7a4b149b43dc5115c7dbfeba5e9ac3c"] .unchecked_into(), ), - // standalone 3 + // tangle 5 ( - hex!["2c4e648b0fbbb88ff6b92b208273eb144383b2b19edc992e91448a4371d4d97d"].into(), - hex!["a41b35f75e5509ce96e62bc27bb9a1b5587cc3d596f8afa867962b0e03230513"] + hex!["dc6d32ff27a13a3be0c6cebe857c31e17ab8a12da6aecea79541b30a909c8539"].into(), + hex!["a085f963e31e1fd9592a8e3b1106cc7ea5571df53e2bbedc303d244274d24b09"] .unchecked_into(), - hex!["340e5969c8dd40ff77184fa73fbdcda77dcc90dd9b68b8b28eef5f01ce42339c"] + hex!["4d416faaa28fd1d32744e00e40aa783dd30779e7e49f9fc7026923103b460895"] .unchecked_into(), - hex!["8472336050c4e4a51ac69865a4a31c6dd0e5c2f79555d8646cafb3bd8f12d75c"] + hex!["48bccc462321ccf5806ad45d35755e9ac3e76813ad64c5f15e3f15a5b25f1437"] + .unchecked_into(), + hex!["02150142402731bc289cd6edd27536f7fb419e312f25e2c8d0f67c5e76f2a2a9fd"] .unchecked_into(), ), - // standalone 4 + // tangle 6 ( - hex!["c884c8eb280327221a3ae6a45fe6c8805f09bcfc11b409c8e2daa621c0d99608"].into(), - hex!["06e0a0d39503a101ca9c36f84b3ccf53015ee625a546bc570e550af963d13164"] + hex!["5effe50292a6a8932efde21623ea0a8c2acaffe85cf30827907dba715c04137f"].into(), + hex!["fe77de52662d43eafc069b81538e57bbecc266b21f783ceba9302df95c2b6453"] + .unchecked_into(), + hex!["5922a3e86519cb61ab1e4eae6d4feee5c9bee4007a002c1cb4d4f99b69eedd63"] .unchecked_into(), - hex!["57eda010788108257f4c148cf0c3112d620b9067546777dc393a65dd34732079"] + hex!["4482f8fa27f9c9ec566554d2cf6ae3f7430da66fdeb486074a80237f6a7ca55c"] .unchecked_into(), - hex!["029cb182ddb9c5560aaa299f7b445e575007b8295bd85a80a7b2eb7baa3e2b7c"] + hex!["028b4b49f4ab47aaf8583b98c800779397234cb23810856eeca151cc39c7e4637a"] .unchecked_into(), ), - // standalone 5 + // tangle 7 ( - hex!["483e0b8d6801c51115fd4b124c91e2d5dcd642b30335f6c5a1738ea18f66c251"].into(), - hex!["ce80df4851003f6ffd4ee88d9be85966f1de8b2e494c009dbf336177485f023f"] + hex!["f65b33a645a71be5a0953c53855ce3f8e882167d85910dc1e2cc1b9d32abe56d"].into(), + hex!["eaea45fd67d4211b3b20706452c58850f7415c7b821c5617b42fb3373b822645"] + .unchecked_into(), + hex!["5b120ba5d2399de8ba3201d1c464973070934c570c539ddcad1318832353f7b0"] + .unchecked_into(), + hex!["1261548c9de1476e4e8e06e9dddd543ebbd7504ae502ac91a0eb8b6037334372"] + .unchecked_into(), + hex!["02320ab70b215ed1d37748d2aadae924ddb1e6042598ae9c2479684f0913cc15ae"] + .unchecked_into(), + ), + // tangle 8 + ( + hex!["72db776eda47a3962a4dc987801e4762cabe38dfc7f639bd76823e09ec37e422"].into(), + hex!["0a006e5c139ac2a46ed260a41db9bca6edbb937befe83cae167c68902d192d26"] + .unchecked_into(), + hex!["63e68e70b16f553476b879b5dba4b9ff587cd2a4a449df9c97698d56ea067b18"] + .unchecked_into(), + hex!["7c04e33631ff7ae0a453827c82c4b69179e72612f982c4d9b45393f25b4f5f48"] + .unchecked_into(), + hex!["026fa903a87d7e0e262e5c70d6dffecca3f5262f05096a1c5bcd477e8ea63813ad"] + .unchecked_into(), + ), + // tangle 9 + ( + hex!["a21d680b5daed8ca06772666e4245340d2fb6d363f7edab5cf78baa1456a5650"].into(), + hex!["c851a63384fa6d5f7708a233e7de8c4bc81c07cacd0a8f329cb294d47aa64b78"] + .unchecked_into(), + hex!["5b120ba5d2399de8ba3201d1c464973070934c570c539ddcad1318832353f7b0"] + .unchecked_into(), + hex!["7842e1623d6a19cd267ad9b926ddb81a27c6aedc4cab58e99cd0ac3e2a53a762"] + .unchecked_into(), + hex!["02c876f99aa4361e7e81eb96ff325833452efb6eed6ae43abfbbed4106ac556829"] + .unchecked_into(), + ), + // tangle 10 + ( + hex!["3079d12fd7978cee5ff87fad722e3ef2156dea0daaaa1c6f73c28b69cf9a9201"].into(), + hex!["000a4209bd78a7c1ff2eb8093b095be0d2776c3d5d6392ef4edb3d05f41d7e2e"] + .unchecked_into(), + hex!["7363e73123e3fd7600d136652ac763751baf65589a4c5cd6e45f49934f32058f"] .unchecked_into(), - hex!["9027284e6cad3f73eee950695c56f87330311331139616640c9168934dba82df"] + hex!["c0fc962bcbc623e343d0dddf9915f9c269dced366283e76e6302612d5172281d"] .unchecked_into(), - hex!["1ea007d87f91f96c31b1062548eb77c40d47a43f1c84c36caa8586fc7c359729"] + hex!["03d1198468f5ba4f67d155a576d5b2b2823265616b7669000eab08bca538d8c34c"] .unchecked_into(), ), ] diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index c97866057..40a91c434 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -103,7 +103,7 @@ pub mod currency { pub const WEIGHT_FEE: Balance = 100 * MEGAWEI; /// Return the cost to add an item to storage based on size pub const fn deposit(items: u32, bytes: u32) -> Balance { - items as Balance * 20 * DOLLAR + (bytes as Balance) * 100 * MILLICENT + items as Balance * 10 * DOLLAR + (bytes as Balance) * 100 * MILLICENT } } @@ -226,13 +226,12 @@ pub mod evm { pub mod democracy { use crate::{currency::UNIT, time::MINUTES, Balance, BlockNumber}; - - pub const LAUNCH_PERIOD: BlockNumber = 28 * 24 * 60 * MINUTES; - pub const VOTING_PERIOD: BlockNumber = 28 * 24 * 60 * MINUTES; - pub const FASTTRACK_VOTING_PERIOD: BlockNumber = 3 * 24 * 60 * MINUTES; - pub const MINIMUM_DEPOSIT: Balance = 100 * UNIT; - pub const ENACTMENT_PERIOD: BlockNumber = 30 * 24 * 60 * MINUTES; - pub const COOLOFF_PERIOD: BlockNumber = 28 * 24 * 60 * MINUTES; + pub const LAUNCH_PERIOD: BlockNumber = 10 * 24 * 60 * MINUTES; // 10 days + pub const VOTING_PERIOD: BlockNumber = 10 * 24 * 60 * MINUTES; // 10 days + pub const FASTTRACK_VOTING_PERIOD: BlockNumber = 3 * 24 * 60 * MINUTES; // 3 days + pub const MINIMUM_DEPOSIT: Balance = 1000 * UNIT; // 1000 TNT + pub const ENACTMENT_PERIOD: BlockNumber = 3 * 24 * 60 * MINUTES; // 3 days + pub const COOLOFF_PERIOD: BlockNumber = 3 * 24 * 60 * MINUTES; // 3 days pub const MAX_PROPOSALS: u32 = 100; } @@ -260,7 +259,7 @@ pub mod treasury { pub const PROPOSAL_BOND: Permill = Permill::from_percent(5); pub const PROPOSAL_BOND_MINIMUM: Balance = UNIT; pub const SPEND_PERIOD: BlockNumber = DAYS; - pub const BURN: Permill = Permill::from_percent(50); + pub const BURN: Permill = Permill::from_percent(0); pub const TIP_COUNTDOWN: BlockNumber = DAYS; pub const TIP_FINDERS_FEE: Percent = Percent::from_percent(20); pub const TIP_REPORT_DEPOSIT_BASE: Balance = UNIT; diff --git a/runtime/mainnet/Cargo.toml b/runtime/mainnet/Cargo.toml index 4d8ecfd8f..fafc9cc7d 100644 --- a/runtime/mainnet/Cargo.toml +++ b/runtime/mainnet/Cargo.toml @@ -90,6 +90,8 @@ pallet-vesting = { workspace = true } # Webb dependencies tangle-crypto-primitives = { workspace = true } tangle-primitives = { workspace = true } +pallet-roles = { workspace = true } +pallet-jobs = { workspace = true } # Frontier dependencies fp-account = { workspace = true } @@ -205,7 +207,9 @@ std = [ "pallet-airdrop-claims/std", "pallet-identity/std", "frame-system-benchmarking?/std", + "pallet-roles/std", "sp-storage/std", + "pallet-jobs/std", # Tangle dependencies "tangle-primitives/std", diff --git a/runtime/mainnet/src/filters.rs b/runtime/mainnet/src/filters.rs index 0e43f65dd..315bc3848 100644 --- a/runtime/mainnet/src/filters.rs +++ b/runtime/mainnet/src/filters.rs @@ -37,6 +37,9 @@ impl Contains for MainnetCallFilter { RuntimeCall::Democracy(_) | // disallow council RuntimeCall::Council(_) | + // Block jobs and roles pallet + RuntimeCall::Roles(_) | + RuntimeCall::Jobs(_) | // Filter light client calls RuntimeCall::Eth2Client(_) => false, diff --git a/runtime/mainnet/src/lib.rs b/runtime/mainnet/src/lib.rs index 3fbbbb633..3b0a90787 100644 --- a/runtime/mainnet/src/lib.rs +++ b/runtime/mainnet/src/lib.rs @@ -63,14 +63,22 @@ use sp_runtime::{ ApplyExtrinsicResult, FixedPointNumber, FixedU128, Perquintill, SaturatedConversion, }; use sp_staking::currency_to_vote::U128CurrencyToVote; +use tangle_primitives::jobs::{traits::JobToFee, JobSubmission}; + +#[cfg(any(feature = "std", test))] +pub use frame_system::Call as SystemCall; +use sp_runtime::DispatchResult; +use sp_staking::{ + offence::{OffenceError, ReportOffence}, + SessionIndex, +}; use sp_std::prelude::*; #[cfg(feature = "std")] use sp_version::NativeVersion; use sp_version::RuntimeVersion; use static_assertions::const_assert; - -#[cfg(any(feature = "std", test))] -pub use frame_system::Call as SystemCall; +pub use tangle_crypto_primitives::crypto::AuthorityId as RoleKeyId; +use tangle_primitives::jobs::{traits::MPCHandler, JobWithResult, ValidatorOffenceType}; pub use frame_support::{ construct_runtime, @@ -188,6 +196,7 @@ pub mod opaque { pub babe: Babe, pub grandpa: Grandpa, pub im_online: ImOnline, + pub role: Roles, } } } @@ -1059,6 +1068,83 @@ impl pallet_airdrop_claims::Config for Runtime { type WeightInfo = (); } +pub struct MockMPCHandler; + +impl MPCHandler for MockMPCHandler { + fn verify(_data: JobWithResult) -> DispatchResult { + Ok(()) + } + + fn verify_validator_report( + _validator: AccountId, + _offence: ValidatorOffenceType, + _signatures: Vec>, + ) -> DispatchResult { + Ok(()) + } + + fn validate_authority_key(_validator: AccountId, _authority_key: Vec) -> DispatchResult { + Ok(()) + } +} + +type IdTuple = pallet_session::historical::IdentificationTuple; +type Offence = pallet_roles::offences::ValidatorOffence; +/// A mock offence report handler. +pub struct OffenceHandler; +impl ReportOffence for OffenceHandler { + fn report_offence(_reporters: Vec, _offence: Offence) -> Result<(), OffenceError> { + Ok(()) + } + + fn is_known_offence(_offenders: &[IdTuple], _time_slot: &SessionIndex) -> bool { + false + } +} + +parameter_types! { + pub InflationRewardPerSession: Balance = 10_000; + pub Reward : tangle_primitives::roles::ValidatorRewardDistribution = tangle_primitives::roles::ValidatorRewardDistribution::try_new(Percent::from_rational(1_u32,2_u32), Percent::from_rational(1_u32,2_u32)).unwrap(); +} + +impl pallet_roles::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type JobsHandler = Jobs; + type RoleKeyId = RoleKeyId; + type MaxRolesPerAccount = ConstU32<2>; + type MPCHandler = MockMPCHandler; + type InflationRewardPerSession = InflationRewardPerSession; + type ValidatorSet = Historical; + type ReportOffences = OffenceHandler; + type ValidatorRewardDistribution = Reward; + type WeightInfo = (); +} + +pub struct MockJobToFeeHandler; + +impl JobToFee for MockJobToFeeHandler { + type Balance = Balance; + + fn job_to_fee(_job: &JobSubmission) -> Balance { + Default::default() + } +} + +parameter_types! { + pub const JobsPalletId: PalletId = PalletId(*b"py/jobss"); +} + +impl pallet_jobs::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type ForceOrigin = EnsureRootOrHalfCouncil; + type Currency = Balances; + type JobToFee = MockJobToFeeHandler; + type RolesHandler = Roles; + type MPCHandler = MockMPCHandler; + type PalletId = JobsPalletId; + type WeightInfo = (); +} + // Create the runtime by composing the FRAME pallets that were previously configured. construct_runtime!( pub enum Runtime { @@ -1110,6 +1196,8 @@ construct_runtime!( Claims: pallet_airdrop_claims, Eth2Client: pallet_eth2_light_client, + Roles: pallet_roles, + Jobs: pallet_jobs } ); diff --git a/runtime/testnet/src/lib.rs b/runtime/testnet/src/lib.rs index 87163345c..cb0d02c1c 100644 --- a/runtime/testnet/src/lib.rs +++ b/runtime/testnet/src/lib.rs @@ -161,7 +161,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("tangle-testnet"), impl_name: create_runtime_str!("tangle-testnet"), authoring_version: 1, - spec_version: 601, // v0.6.1 + spec_version: 602, // v0.6.2 impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, @@ -999,9 +999,9 @@ impl pallet_transaction_pause::Config for Runtime { } parameter_types! { - pub const BasicDeposit: Balance = deposit(1, 258); - pub const FieldDeposit: Balance = deposit(0, 66); - pub const SubAccountDeposit: Balance = deposit(1, 53); + pub const BasicDeposit: Balance = deposit(0, 100); // purposely set low, do not copy for mainnet + pub const FieldDeposit: Balance = deposit(0, 100); // purposely set low, do not copy for mainnet + pub const SubAccountDeposit: Balance = deposit(1, 1); // purposely set low, do not copy for mainnet pub const MaxSubAccounts: u32 = 100; #[derive(Serialize, Deserialize)] pub const MaxAdditionalFields: u32 = 100;