From bbdf4eaec52ec92a39cb7aafa0626f3d91a3960b Mon Sep 17 00:00:00 2001 From: ndkazu Date: Wed, 25 Oct 2023 17:38:33 +0900 Subject: [PATCH] Select random investor --- Cargo.lock | 50 +++++++++++++++++++++++++++++--- pallets/bidding/src/functions.rs | 44 +++++++++++++++++++++++++++- pallets/bidding/src/lib.rs | 7 ++++- runtime/Cargo.toml | 9 ++++-- runtime/src/lib.rs | 9 ++++++ 5 files changed, 110 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2c706d49..ee1e014d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -343,7 +343,7 @@ dependencies = [ "num-bigint", "num-traits", "paste", - "rustc_version", + "rustc_version 0.4.0", "zeroize", ] @@ -1635,7 +1635,7 @@ dependencies = [ "digest 0.10.7", "fiat-crypto", "platforms", - "rustc_version", + "rustc_version 0.4.0", "subtle", "zeroize", ] @@ -2342,7 +2342,7 @@ dependencies = [ [[package]] name = "fflonk" version = "0.1.0" -source = "git+https://github.com/w3f/fflonk#26a5045b24e169cffc1f9328ca83d71061145c40" +source = "git+https://github.com/w3f/fflonk#e141d4b6f42fb481aefe1b479788694945b6940d" dependencies = [ "ark-ec", "ark-ff", @@ -2798,6 +2798,7 @@ dependencies = [ "pallet-grandpa", "pallet-housing_fund", "pallet-identity", + "pallet-insecure-randomness-collective-flip", "pallet-nft", "pallet-nfts", "pallet-nfts-runtime-api", @@ -5356,6 +5357,20 @@ dependencies = [ "sp-std 8.0.0", ] +[[package]] +name = "pallet-insecure-randomness-collective-flip" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.1.0#f60318f68687e601c47de5ad5ca88e2c3f8139a7" +dependencies = [ + "frame-support", + "frame-system", + "parity-scale-codec", + "safe-mix", + "scale-info", + "sp-runtime", + "sp-std 8.0.0", +] + [[package]] name = "pallet-nft" version = "4.0.0" @@ -6717,6 +6732,15 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + [[package]] name = "rustc_version" version = "0.4.0" @@ -6867,6 +6891,15 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +[[package]] +name = "safe-mix" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d3d055a2582e6b00ed7a31c1524040aa391092bf636328350813f3a0605215c" +dependencies = [ + "rustc_version 0.2.3", +] + [[package]] name = "safe_arch" version = "0.7.1" @@ -7983,6 +8016,15 @@ dependencies = [ "semver-parser", ] +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + [[package]] name = "semver" version = "1.0.18" @@ -8210,7 +8252,7 @@ dependencies = [ "curve25519-dalek 4.1.1", "rand_core 0.6.4", "ring 0.16.20", - "rustc_version", + "rustc_version 0.4.0", "sha2 0.10.7", "subtle", ] diff --git a/pallets/bidding/src/functions.rs b/pallets/bidding/src/functions.rs index 730cb15e..a11dd315 100644 --- a/pallets/bidding/src/functions.rs +++ b/pallets/bidding/src/functions.rs @@ -1,6 +1,12 @@ pub use super::*; pub use sp_runtime::{BoundedVec,Percent}; -pub use frame_support::pallet_prelude::ConstU32; +pub use frame_support::{ + dispatch::{DispatchResult, GetDispatchInfo}, + ensure, + pallet_prelude::MaxEncodedLen, + traits::{Currency, ExistenceRequirement::KeepAlive, Get, Randomness, ReservableCurrency}, + PalletId, +}; pub use Onboarding::Zero; pub use pallet_roles::vec; @@ -36,6 +42,42 @@ impl Pallet { } + /// Randomly choose an investor from among an investors list. + /// Returns `None` if there are no investors in the list. + fn choose_ticket(mut investors: Vec>) -> (Option>,usize) { + let total = investors.len() as u32; + if total == 0 { + return (None,0) + } + let mut random_number = Self::generate_random_number(0); + + // Best effort attempt to remove bias from modulus operator. + for i in 1..T::MaxGenerateRandom::get() { + if random_number < u32::MAX - u32::MAX % total && ( 0..total-1).contains(&(random_number%total)) { + break + } + + random_number = Self::generate_random_number(i); + } + let num = random_number % total; + let inv = investors[num as usize].clone(); + (Some(inv),num as usize) + } + + + /// Generate a random number from a given seed. + /// Note that there is potential bias introduced by using modulus operator. + /// You should call this function with different seed values until the random + /// number lies within `u32::MAX - u32::MAX % n`. + /// TODO: deal with randomness freshness + /// https://github.com/paritytech/substrate/issues/8311 + fn generate_random_number(seed: u32) -> u32 { + let (random_seed, _) = T::Randomness::random(&(T::PalletId::get(), seed).encode()); + let random_number = ::decode(&mut random_seed.as_ref()) + .expect("secure hashes should always be bigger than u32; qed"); + random_number + } + } diff --git a/pallets/bidding/src/lib.rs b/pallets/bidding/src/lib.rs index 1acfa0ea..3f36654f 100644 --- a/pallets/bidding/src/lib.rs +++ b/pallets/bidding/src/lib.rs @@ -15,6 +15,8 @@ pub use pallet::*; //pub use weights::*; mod functions; mod types; +pub use functions::*; +pub use types::*; pub use pallet_onboarding as Onboarding; pub use pallet_roles as Roles; pub use pallet_housing_fund as Houses; @@ -50,7 +52,10 @@ pub mod pallet { + Share::Config { /// The overarching runtime event type. type RuntimeEvent: From> + IsType<::RuntimeEvent>; - + /// Something that provides randomness in the runtime. + type Randomness: Randomness>; + #[pallet::constant] + type MaxGenerateRandom: Get; } /// A storage item for this pallet. diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 211b8bed..f8f3b5b0 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -51,6 +51,7 @@ pallet-assets = { git = "https://github.com/paritytech/polkadot-sdk", tag = "po pallet-identity = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.1.0", default-features = false } pallet-nfts = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.1.0", default-features = false } pallet-nfts-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.1.0", default-features = false } +pallet-insecure-randomness-collective-flip = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.1.0", default-features = false } sp-storage = { version = "13.0.0", default-features = false, git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.1.0" } @@ -124,7 +125,8 @@ std = [ "pallet-nfts/std", "pallet-nfts-runtime-api/std", "pallet-share_distributor/std", - "pallet-bidding/std" + "pallet-bidding/std", + "pallet-insecure-randomness-collective-flip/std", ### add new std ] runtime-benchmarks = [ @@ -152,7 +154,7 @@ runtime-benchmarks = [ "pallet-democracy/runtime-benchmarks", "pallet-nfts/runtime-benchmarks", "pallet-share_distributor/runtime-benchmarks", - "pallet-bidding/runtime-benchmarks" + "pallet-bidding/runtime-benchmarks", ### add new runtime-benchmarks ] try-runtime = [ @@ -179,7 +181,8 @@ try-runtime = [ "pallet-democracy/try-runtime", "pallet-nfts/try-runtime", "pallet-share_distributor/try-runtime", - "pallet-bidding/try-runtime" + "pallet-bidding/try-runtime", + "pallet-insecure-randomness-collective-flip/try-runtime", ### add new try-runtime ] diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 63b607cb..26a696df 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -289,8 +289,14 @@ impl pallet_roles::Config for Runtime { //type WeightInfo = pallet_roles::weights::SubstrateWeight; } +parameter_types!{ + pub const MaxGenerateRandom:u32 =60; +} impl pallet_bidding::Config for Runtime{ type RuntimeEvent = RuntimeEvent; + type MaxGenerateRandom = MaxGenerateRandom; + type Randomness = RandomnessCollectiveFlip; + } impl pallet_finalizer::Config for Runtime{ @@ -298,6 +304,8 @@ impl pallet_finalizer::Config for Runtime{ //type WeightInfo = } +impl pallet_insecure_randomness_collective_flip::Config for Runtime {} + impl pallet_council::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; @@ -696,6 +704,7 @@ construct_runtime!( FinalizerModule: pallet_finalizer, ShareDistributorModule: pallet_share_distributor, BiddingModule: pallet_bidding, + RandomnessCollectiveFlip: pallet_insecure_randomness_collective_flip, // flag add pallet runtime } );