diff --git a/Cargo.lock b/Cargo.lock index c971ebcba9c6..e8732f64efa0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9827,6 +9827,7 @@ dependencies = [ "sp-io", "sp-runtime", "sp-std 14.0.0", + "sp-tracing 16.0.0", ] [[package]] diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/coretime.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/coretime.rs index 742dd50f6fa1..ec3a4f31202f 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/coretime.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/coretime.rs @@ -232,5 +232,5 @@ impl pallet_broker::Config for Runtime { type WeightInfo = weights::pallet_broker::WeightInfo; type PalletId = BrokerPalletId; type AdminOrigin = EnsureRoot; - type PriceAdapter = pallet_broker::Linear; + type PriceAdapter = pallet_broker::CenterTargetPrice; } diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs index f43bb1c1e41b..b78802790480 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs @@ -112,6 +112,7 @@ pub type Migrations = ( cumulus_pallet_xcmp_queue::migration::v4::MigrationToV4, cumulus_pallet_xcmp_queue::migration::v5::MigrateV4ToV5, pallet_broker::migration::MigrateV0ToV1, + pallet_broker::migration::MigrateV1ToV2, // permanent pallet_xcm::migration::MigrateToLatestXcmVersion, ); diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_broker.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_broker.rs index 89b1c4c86632..5c9175a18d98 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_broker.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_broker.rs @@ -154,8 +154,8 @@ impl pallet_broker::WeightInfo for WeightInfo { /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) /// Storage: `Broker::SaleInfo` (r:1 w:1) /// Proof: `Broker::SaleInfo` (`max_values`: Some(1), `max_size`: Some(57), added: 552, mode: `MaxEncodedLen`) - /// Storage: `Broker::AllowedRenewals` (r:1 w:2) - /// Proof: `Broker::AllowedRenewals` (`max_values`: None, `max_size`: Some(1233), added: 3708, mode: `MaxEncodedLen`) + /// Storage: `Broker::PotentialRenewals` (r:1 w:2) + /// Proof: `Broker::PotentialRenewals` (`max_values`: None, `max_size`: Some(1233), added: 3708, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Broker::Workplan` (r:0 w:1) @@ -337,8 +337,8 @@ impl pallet_broker::WeightInfo for WeightInfo { } /// Storage: `Broker::Status` (r:1 w:0) /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) - /// Storage: `Broker::AllowedRenewals` (r:1 w:1) - /// Proof: `Broker::AllowedRenewals` (`max_values`: None, `max_size`: Some(1233), added: 3708, mode: `MaxEncodedLen`) + /// Storage: `Broker::PotentialRenewals` (r:1 w:1) + /// Proof: `Broker::PotentialRenewals` (`max_values`: None, `max_size`: Some(1233), added: 3708, mode: `MaxEncodedLen`) fn drop_renewal() -> Weight { // Proof Size summary in bytes: // Measured: `957` diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/coretime.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/coretime.rs index 41cbc62fa211..a5e219b9897e 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/coretime.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/coretime.rs @@ -245,5 +245,5 @@ impl pallet_broker::Config for Runtime { type WeightInfo = weights::pallet_broker::WeightInfo; type PalletId = BrokerPalletId; type AdminOrigin = EnsureRoot; - type PriceAdapter = pallet_broker::Linear; + type PriceAdapter = pallet_broker::CenterTargetPrice; } diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs index ff2456dc1772..78b963e3b405 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs @@ -111,6 +111,7 @@ pub type Migrations = ( pallet_collator_selection::migration::v2::MigrationToV2, cumulus_pallet_xcmp_queue::migration::v4::MigrationToV4, pallet_broker::migration::MigrateV0ToV1, + pallet_broker::migration::MigrateV1ToV2, // permanent pallet_xcm::migration::MigrateToLatestXcmVersion, ); diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_broker.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_broker.rs index 13d5fcf3898b..7e1c832a9092 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_broker.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_broker.rs @@ -152,8 +152,8 @@ impl pallet_broker::WeightInfo for WeightInfo { /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) /// Storage: `Broker::SaleInfo` (r:1 w:1) /// Proof: `Broker::SaleInfo` (`max_values`: Some(1), `max_size`: Some(57), added: 552, mode: `MaxEncodedLen`) - /// Storage: `Broker::AllowedRenewals` (r:1 w:2) - /// Proof: `Broker::AllowedRenewals` (`max_values`: None, `max_size`: Some(1233), added: 3708, mode: `MaxEncodedLen`) + /// Storage: `Broker::PotentialRenewals` (r:1 w:2) + /// Proof: `Broker::PotentialRenewals` (`max_values`: None, `max_size`: Some(1233), added: 3708, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Broker::Workplan` (r:0 w:1) @@ -335,8 +335,8 @@ impl pallet_broker::WeightInfo for WeightInfo { } /// Storage: `Broker::Status` (r:1 w:0) /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) - /// Storage: `Broker::AllowedRenewals` (r:1 w:1) - /// Proof: `Broker::AllowedRenewals` (`max_values`: None, `max_size`: Some(1233), added: 3708, mode: `MaxEncodedLen`) + /// Storage: `Broker::PotentialRenewals` (r:1 w:1) + /// Proof: `Broker::PotentialRenewals` (`max_values`: None, `max_size`: Some(1233), added: 3708, mode: `MaxEncodedLen`) fn drop_renewal() -> Weight { // Proof Size summary in bytes: // Measured: `556` diff --git a/prdoc/pr_4521.prdoc b/prdoc/pr_4521.prdoc new file mode 100644 index 000000000000..a8b42a2c7ee3 --- /dev/null +++ b/prdoc/pr_4521.prdoc @@ -0,0 +1,28 @@ +title: AdaptPrice trait is now price controlled + +doc: + - audience: Runtime Dev + description: | + The broker pallet price adaptation interface is changed to be less opinionated and more + information is made available to the `AdaptPrice` trait. A new example impl is included which + adapts the price based not on the number of cores sold, but rather on the price that was + achieved during the sale to mitigate a potential price manipulation vector. More information + here: + + https://github.com/paritytech/polkadot-sdk/issues/4360 + + - audience: Runtime User + description: | + The price controller of the Rococo and Westend Coretime chain will be + adjusted with this release. This will very likely be used in the + fellowship production runtime to have a much larger leadin. This fixes a + price manipulation issue we discovered with the Kusama launch. + +crates: + - name: pallet-broker + bump: minor + - name: coretime-rococo-runtime + bump: minor + - name: coretime-westend-runtime + bump: minor + diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index 7d9128bb940a..801abc28d3dd 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -2145,7 +2145,7 @@ impl pallet_broker::Config for Runtime { type WeightInfo = (); type PalletId = BrokerPalletId; type AdminOrigin = EnsureRoot; - type PriceAdapter = pallet_broker::Linear; + type PriceAdapter = pallet_broker::CenterTargetPrice; } parameter_types! { diff --git a/substrate/frame/broker/Cargo.toml b/substrate/frame/broker/Cargo.toml index 8f3f30ec58eb..8a84fbfdfb70 100644 --- a/substrate/frame/broker/Cargo.toml +++ b/substrate/frame/broker/Cargo.toml @@ -30,6 +30,7 @@ frame-system = { path = "../system", default-features = false } [dev-dependencies] sp-io = { path = "../../primitives/io" } +sp-tracing = { path = "../../primitives/tracing" } pretty_assertions = "1.3.0" [features] diff --git a/substrate/frame/broker/src/adapt_price.rs b/substrate/frame/broker/src/adapt_price.rs index fbcd7afdf0da..9b2e1dd8997b 100644 --- a/substrate/frame/broker/src/adapt_price.rs +++ b/substrate/frame/broker/src/adapt_price.rs @@ -17,59 +17,122 @@ #![deny(missing_docs)] -use crate::CoreIndex; +use crate::{CoreIndex, SaleInfoRecord}; use sp_arithmetic::{traits::One, FixedU64}; -use sp_runtime::Saturating; +use sp_runtime::{FixedPointNumber, FixedPointOperand, Saturating}; + +/// Performance of a past sale. +#[derive(Copy, Clone)] +pub struct SalePerformance { + /// The price at which the last core was sold. + /// + /// Will be `None` if no cores have been offered. + pub sellout_price: Option, + + /// The minimum price that was achieved in this sale. + pub end_price: Balance, + + /// The number of cores we want to sell, ideally. + pub ideal_cores_sold: CoreIndex, + + /// Number of cores which are/have been offered for sale. + pub cores_offered: CoreIndex, + + /// Number of cores which have been sold; never more than cores_offered. + pub cores_sold: CoreIndex, +} + +/// Result of `AdaptPrice::adapt_price`. +#[derive(Copy, Clone)] +pub struct AdaptedPrices { + /// New minimum price to use. + pub end_price: Balance, + + /// Price the controller is optimizing for. + /// + /// This is the price "expected" by the controller based on the previous sale. We assume that + /// sales in this period will be around this price, assuming stable market conditions. + /// + /// Think of it as the expected market price. This can be used for determining what to charge + /// for renewals, that don't yet have any price information for example. E.g. for expired + /// legacy leases. + pub target_price: Balance, +} + +impl SalePerformance { + /// Construct performance via data from a `SaleInfoRecord`. + pub fn from_sale(record: &SaleInfoRecord) -> Self { + Self { + sellout_price: record.sellout_price, + end_price: record.end_price, + ideal_cores_sold: record.ideal_cores_sold, + cores_offered: record.cores_offered, + cores_sold: record.cores_sold, + } + } + + #[cfg(test)] + fn new(sellout_price: Option, end_price: Balance) -> Self { + Self { sellout_price, end_price, ideal_cores_sold: 0, cores_offered: 0, cores_sold: 0 } + } +} /// Type for determining how to set price. -pub trait AdaptPrice { +pub trait AdaptPrice { /// Return the factor by which the regular price must be multiplied during the leadin period. /// /// - `when`: The amount through the leadin period; between zero and one. fn leadin_factor_at(when: FixedU64) -> FixedU64; - /// Return the correction factor by which the regular price must be multiplied based on market - /// performance. + + /// Return adapted prices for next sale. /// - /// - `sold`: The number of cores sold. - /// - `target`: The target number of cores to be sold (must be larger than zero). - /// - `limit`: The maximum number of cores to be sold. - fn adapt_price(sold: CoreIndex, target: CoreIndex, limit: CoreIndex) -> FixedU64; + /// Based on the previous sale's performance. + fn adapt_price(performance: SalePerformance) -> AdaptedPrices; } -impl AdaptPrice for () { +impl AdaptPrice for () { fn leadin_factor_at(_: FixedU64) -> FixedU64 { FixedU64::one() } - fn adapt_price(_: CoreIndex, _: CoreIndex, _: CoreIndex) -> FixedU64 { - FixedU64::one() + fn adapt_price(performance: SalePerformance) -> AdaptedPrices { + let price = performance.sellout_price.unwrap_or(performance.end_price); + AdaptedPrices { end_price: price, target_price: price } } } -/// Simple implementation of `AdaptPrice` giving a monotonic leadin and a linear price change based -/// on cores sold. -pub struct Linear; -impl AdaptPrice for Linear { +/// Simple implementation of `AdaptPrice` with two linear phases. +/// +/// One steep one downwards to the target price, which is 1/10 of the maximum price and a more flat +/// one down to the minimum price, which is 1/100 of the maximum price. +pub struct CenterTargetPrice(core::marker::PhantomData); + +impl AdaptPrice for CenterTargetPrice { fn leadin_factor_at(when: FixedU64) -> FixedU64 { - FixedU64::from(2).saturating_sub(when) - } - fn adapt_price(sold: CoreIndex, target: CoreIndex, limit: CoreIndex) -> FixedU64 { - if sold <= target { - // Range of [0.5, 1.0]. - FixedU64::from_rational(1, 2).saturating_add(FixedU64::from_rational( - sold.into(), - target.saturating_mul(2).into(), - )) + if when <= FixedU64::from_rational(1, 2) { + FixedU64::from(100).saturating_sub(when.saturating_mul(180.into())) } else { - // Range of (1.0, 2]. - - // Unchecked math: In this branch we know that sold > target. The limit must be >= sold - // by construction, and thus target must be < limit. - FixedU64::one().saturating_add(FixedU64::from_rational( - (sold - target).into(), - (limit - target).into(), - )) + FixedU64::from(19).saturating_sub(when.saturating_mul(18.into())) } } + + fn adapt_price(performance: SalePerformance) -> AdaptedPrices { + let Some(sellout_price) = performance.sellout_price else { + return AdaptedPrices { + end_price: performance.end_price, + target_price: FixedU64::from(10).saturating_mul_int(performance.end_price), + } + }; + + let price = FixedU64::from_rational(1, 10).saturating_mul_int(sellout_price); + let price = if price == Balance::zero() { + // We could not recover from a price equal 0 ever. + sellout_price + } else { + price + }; + + AdaptedPrices { end_price: price, target_price: sellout_price } + } } #[cfg(test)] @@ -78,37 +141,103 @@ mod tests { #[test] fn linear_no_panic() { - for limit in 0..10 { - for target in 1..10 { - for sold in 0..=limit { - let price = Linear::adapt_price(sold, target, limit); - - if sold > target { - assert!(price > FixedU64::one()); - } else { - assert!(price <= FixedU64::one()); - } - } + for sellout in 0..11 { + for price in 0..10 { + let sellout_price = if sellout == 11 { None } else { Some(sellout) }; + CenterTargetPrice::adapt_price(SalePerformance::new(sellout_price, price)); } } } #[test] - fn linear_bound_check() { - // Using constraints from pallet implementation i.e. `limit >= sold`. - // Check extremes - let limit = 10; - let target = 5; - - // Maximally sold: `sold == limit` - assert_eq!(Linear::adapt_price(limit, target, limit), FixedU64::from_float(2.0)); - // Ideally sold: `sold == target` - assert_eq!(Linear::adapt_price(target, target, limit), FixedU64::one()); - // Minimally sold: `sold == 0` - assert_eq!(Linear::adapt_price(0, target, limit), FixedU64::from_float(0.5)); - // Optimistic target: `target == limit` - assert_eq!(Linear::adapt_price(limit, limit, limit), FixedU64::one()); - // Pessimistic target: `target == 0` - assert_eq!(Linear::adapt_price(limit, 0, limit), FixedU64::from_float(2.0)); + fn leadin_price_bound_check() { + assert_eq!( + CenterTargetPrice::::leadin_factor_at(FixedU64::from(0)), + FixedU64::from(100) + ); + assert_eq!( + CenterTargetPrice::::leadin_factor_at(FixedU64::from_rational(1, 4)), + FixedU64::from(55) + ); + + assert_eq!( + CenterTargetPrice::::leadin_factor_at(FixedU64::from_float(0.5)), + FixedU64::from(10) + ); + + assert_eq!( + CenterTargetPrice::::leadin_factor_at(FixedU64::from_rational(3, 4)), + FixedU64::from_float(5.5) + ); + assert_eq!(CenterTargetPrice::::leadin_factor_at(FixedU64::one()), FixedU64::one()); + } + + #[test] + fn no_op_sale_is_good() { + let prices = CenterTargetPrice::adapt_price(SalePerformance::new(None, 1)); + assert_eq!(prices.target_price, 10); + assert_eq!(prices.end_price, 1); + } + + #[test] + fn price_stays_stable_on_optimal_sale() { + // Check price stays stable if sold at the optimal price: + let mut performance = SalePerformance::new(Some(1000), 100); + for _ in 0..10 { + let prices = CenterTargetPrice::adapt_price(performance); + performance.sellout_price = Some(1000); + performance.end_price = prices.end_price; + + assert!(prices.end_price <= 101); + assert!(prices.end_price >= 99); + assert!(prices.target_price <= 1001); + assert!(prices.target_price >= 999); + } + } + + #[test] + fn price_adjusts_correctly_upwards() { + let performance = SalePerformance::new(Some(10_000), 100); + let prices = CenterTargetPrice::adapt_price(performance); + assert_eq!(prices.target_price, 10_000); + assert_eq!(prices.end_price, 1000); + } + + #[test] + fn price_adjusts_correctly_downwards() { + let performance = SalePerformance::new(Some(100), 100); + let prices = CenterTargetPrice::adapt_price(performance); + assert_eq!(prices.target_price, 100); + assert_eq!(prices.end_price, 10); + } + + #[test] + fn price_never_goes_to_zero_and_recovers() { + // Check price stays stable if sold at the optimal price: + let sellout_price = 1; + let mut performance = SalePerformance::new(Some(sellout_price), 1); + for _ in 0..11 { + let prices = CenterTargetPrice::adapt_price(performance); + performance.sellout_price = Some(sellout_price); + performance.end_price = prices.end_price; + + assert!(prices.end_price <= sellout_price); + assert!(prices.end_price > 0); + } + } + + #[test] + fn renewal_price_is_correct_on_no_sale() { + let performance = SalePerformance::new(None, 100); + let prices = CenterTargetPrice::adapt_price(performance); + assert_eq!(prices.target_price, 1000); + assert_eq!(prices.end_price, 100); + } + + #[test] + fn renewal_price_is_sell_out() { + let performance = SalePerformance::new(Some(1000), 100); + let prices = CenterTargetPrice::adapt_price(performance); + assert_eq!(prices.target_price, 1000); } } diff --git a/substrate/frame/broker/src/benchmarking.rs b/substrate/frame/broker/src/benchmarking.rs index 7533e3dc68c4..9cb5ad096c83 100644 --- a/substrate/frame/broker/src/benchmarking.rs +++ b/substrate/frame/broker/src/benchmarking.rs @@ -214,8 +214,8 @@ mod benches { Event::SaleInitialized { sale_start: 2u32.into(), leadin_length: 1u32.into(), - start_price: 20u32.into(), - regular_price: 10u32.into(), + start_price: 1000u32.into(), + end_price: 10u32.into(), region_begin: latest_region_begin + config.region_length, region_end: latest_region_begin + config.region_length * 2, ideal_cores_sold: 0, @@ -288,8 +288,8 @@ mod benches { #[extrinsic_call] _(RawOrigin::Signed(caller), region.core); - let id = AllowedRenewalId { core: region.core, when: region.begin + region_len * 2 }; - assert!(AllowedRenewals::::get(id).is_some()); + let id = PotentialRenewalId { core: region.core, when: region.begin + region_len * 2 }; + assert!(PotentialRenewals::::get(id).is_some()); Ok(()) } @@ -670,20 +670,20 @@ mod benches { (T::TimeslicePeriod::get() * (region_len * 3).into()).try_into().ok().unwrap(), ); - let id = AllowedRenewalId { core, when }; - let record = AllowedRenewalRecord { + let id = PotentialRenewalId { core, when }; + let record = PotentialRenewalRecord { price: 1u32.into(), completion: CompletionStatus::Complete(new_schedule()), }; - AllowedRenewals::::insert(id, record); + PotentialRenewals::::insert(id, record); let caller: T::AccountId = whitelisted_caller(); #[extrinsic_call] _(RawOrigin::Signed(caller), core, when); - assert!(AllowedRenewals::::get(id).is_none()); - assert_last_event::(Event::AllowedRenewalDropped { core, when }.into()); + assert!(PotentialRenewals::::get(id).is_none()); + assert_last_event::(Event::PotentialRenewalDropped { core, when }.into()); Ok(()) } @@ -776,12 +776,12 @@ mod benches { let config = new_config_record::(); let now = frame_system::Pallet::::block_number(); - let price = 10u32.into(); + let end_price = 10u32.into(); let commit_timeslice = Broker::::latest_timeslice_ready_to_commit(&config); let sale = SaleInfoRecordOf:: { sale_start: now, leadin_length: Zero::zero(), - price, + end_price, sellout_price: None, region_begin: commit_timeslice, region_end: commit_timeslice.saturating_add(config.region_length), @@ -815,8 +815,8 @@ mod benches { Event::SaleInitialized { sale_start: 2u32.into(), leadin_length: 1u32.into(), - start_price: 20u32.into(), - regular_price: 10u32.into(), + start_price: 1000u32.into(), + end_price: 10u32.into(), region_begin: sale.region_begin + config.region_length, region_end: sale.region_end + config.region_length, ideal_cores_sold: 0, diff --git a/substrate/frame/broker/src/dispatchable_impls.rs b/substrate/frame/broker/src/dispatchable_impls.rs index 45a0a514c307..79c1a1f79796 100644 --- a/substrate/frame/broker/src/dispatchable_impls.rs +++ b/substrate/frame/broker/src/dispatchable_impls.rs @@ -70,7 +70,10 @@ impl Pallet { Ok(()) } - pub(crate) fn do_start_sales(price: BalanceOf, extra_cores: CoreIndex) -> DispatchResult { + pub(crate) fn do_start_sales( + end_price: BalanceOf, + extra_cores: CoreIndex, + ) -> DispatchResult { let config = Configuration::::get().ok_or(Error::::Uninitialized)?; // Determine the core count @@ -93,7 +96,7 @@ impl Pallet { let old_sale = SaleInfoRecord { sale_start: now, leadin_length: Zero::zero(), - price, + end_price, sellout_price: None, region_begin: commit_timeslice, region_end: commit_timeslice.saturating_add(config.region_length), @@ -102,7 +105,7 @@ impl Pallet { cores_offered: 0, cores_sold: 0, }; - Self::deposit_event(Event::::SalesStarted { price, core_count }); + Self::deposit_event(Event::::SalesStarted { price: end_price, core_count }); Self::rotate_sale(old_sale, &config, &status); Status::::put(&status); Ok(()) @@ -121,12 +124,8 @@ impl Pallet { let price = Self::sale_price(&sale, now); ensure!(price_limit >= price, Error::::Overpriced); - Self::charge(&who, price)?; - let core = sale.first_core.saturating_add(sale.cores_sold); - sale.cores_sold.saturating_inc(); - if sale.cores_sold <= sale.ideal_cores_sold || sale.sellout_price.is_none() { - sale.sellout_price = Some(price); - } + let core = Self::purchase_core(&who, price, &mut sale)?; + SaleInfo::::put(&sale); let id = Self::issue(core, sale.region_begin, sale.region_end, Some(who.clone()), Some(price)); @@ -135,7 +134,7 @@ impl Pallet { Ok(id) } - /// Must be called on a core in `AllowedRenewals` whose value is a timeslice equal to the + /// Must be called on a core in `PotentialRenewals` whose value is a timeslice equal to the /// current sale status's `region_end`. pub(crate) fn do_renew(who: T::AccountId, core: CoreIndex) -> Result { let config = Configuration::::get().ok_or(Error::::Uninitialized)?; @@ -143,14 +142,15 @@ impl Pallet { let mut sale = SaleInfo::::get().ok_or(Error::::NoSales)?; Self::ensure_cores_for_sale(&status, &sale)?; - let renewal_id = AllowedRenewalId { core, when: sale.region_begin }; - let record = AllowedRenewals::::get(renewal_id).ok_or(Error::::NotAllowed)?; + let renewal_id = PotentialRenewalId { core, when: sale.region_begin }; + let record = PotentialRenewals::::get(renewal_id).ok_or(Error::::NotAllowed)?; let workload = record.completion.drain_complete().ok_or(Error::::IncompleteAssignment)?; let old_core = core; - let core = sale.first_core.saturating_add(sale.cores_sold); - Self::charge(&who, record.price)?; + + let core = Self::purchase_core(&who, record.price, &mut sale)?; + Self::deposit_event(Event::Renewed { who, old_core, @@ -161,19 +161,24 @@ impl Pallet { workload: workload.clone(), }); - sale.cores_sold.saturating_inc(); - Workplan::::insert((sale.region_begin, core), &workload); let begin = sale.region_end; let price_cap = record.price + config.renewal_bump * record.price; let now = frame_system::Pallet::::block_number(); let price = Self::sale_price(&sale, now).min(price_cap); - let new_record = AllowedRenewalRecord { price, completion: Complete(workload) }; - AllowedRenewals::::remove(renewal_id); - AllowedRenewals::::insert(AllowedRenewalId { core, when: begin }, &new_record); + log::debug!( + "Renew with: sale price: {:?}, price cap: {:?}, old price: {:?}", + price, + price_cap, + record.price + ); + let new_record = PotentialRenewalRecord { price, completion: Complete(workload) }; + PotentialRenewals::::remove(renewal_id); + PotentialRenewals::::insert(PotentialRenewalId { core, when: begin }, &new_record); SaleInfo::::put(&sale); if let Some(workload) = new_record.completion.drain_complete() { + log::debug!("Recording renewable price for next run: {:?}", price); Self::deposit_event(Event::Renewable { core, price, begin, workload }); } Ok(core) @@ -281,17 +286,19 @@ impl Pallet { let duration = region.end.saturating_sub(region_id.begin); if duration == config.region_length && finality == Finality::Final { if let Some(price) = region.paid { - let renewal_id = AllowedRenewalId { core: region_id.core, when: region.end }; - let assigned = match AllowedRenewals::::get(renewal_id) { - Some(AllowedRenewalRecord { completion: Partial(w), price: p }) + let renewal_id = PotentialRenewalId { core: region_id.core, when: region.end }; + let assigned = match PotentialRenewals::::get(renewal_id) { + Some(PotentialRenewalRecord { completion: Partial(w), price: p }) if price == p => w, _ => CoreMask::void(), } | region_id.mask; let workload = if assigned.is_complete() { Complete(workplan) } else { Partial(assigned) }; - let record = AllowedRenewalRecord { price, completion: workload }; - AllowedRenewals::::insert(&renewal_id, &record); + let record = PotentialRenewalRecord { price, completion: workload }; + // Note: This entry alone does not yet actually allow renewals (the completion + // status has to be complete for `do_renew` to accept it). + PotentialRenewals::::insert(&renewal_id, &record); if let Some(workload) = record.completion.drain_complete() { Self::deposit_event(Event::Renewable { core: region_id.core, @@ -444,10 +451,10 @@ impl Pallet { pub(crate) fn do_drop_renewal(core: CoreIndex, when: Timeslice) -> DispatchResult { let status = Status::::get().ok_or(Error::::Uninitialized)?; ensure!(status.last_committed_timeslice >= when, Error::::StillValid); - let id = AllowedRenewalId { core, when }; - ensure!(AllowedRenewals::::contains_key(id), Error::::UnknownRenewal); - AllowedRenewals::::remove(id); - Self::deposit_event(Event::AllowedRenewalDropped { core, when }); + let id = PotentialRenewalId { core, when }; + ensure!(PotentialRenewals::::contains_key(id), Error::::UnknownRenewal); + PotentialRenewals::::remove(id); + Self::deposit_event(Event::PotentialRenewalDropped { core, when }); Ok(()) } diff --git a/substrate/frame/broker/src/lib.rs b/substrate/frame/broker/src/lib.rs index d59c4c9c6b24..0774c02e1cf1 100644 --- a/substrate/frame/broker/src/lib.rs +++ b/substrate/frame/broker/src/lib.rs @@ -65,7 +65,7 @@ pub mod pallet { use sp_runtime::traits::{Convert, ConvertBack}; use sp_std::vec::Vec; - const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); + const STORAGE_VERSION: StorageVersion = StorageVersion::new(2); #[pallet::pallet] #[pallet::storage_version(STORAGE_VERSION)] @@ -92,7 +92,7 @@ pub mod pallet { type Coretime: CoretimeInterface; /// The algorithm to determine the next price on the basis of market performance. - type PriceAdapter: AdaptPrice; + type PriceAdapter: AdaptPrice>; /// Reversible conversion from local balance to Relay-chain balance. This will typically be /// the `Identity`, but provided just in case the chains use different representations. @@ -136,10 +136,12 @@ pub mod pallet { #[pallet::storage] pub type SaleInfo = StorageValue<_, SaleInfoRecordOf, OptionQuery>; - /// Records of allowed renewals. + /// Records of potential renewals. + /// + /// Renewals will only actually be allowed if `CompletionStatus` is actually `Complete`. #[pallet::storage] - pub type AllowedRenewals = - StorageMap<_, Twox64Concat, AllowedRenewalId, AllowedRenewalRecordOf, OptionQuery>; + pub type PotentialRenewals = + StorageMap<_, Twox64Concat, PotentialRenewalId, PotentialRenewalRecordOf, OptionQuery>; /// The current (unassigned or provisionally assigend) Regions. #[pallet::storage] @@ -290,14 +292,13 @@ pub mod pallet { /// The price of Bulk Coretime at the beginning of the Leadin Period. start_price: BalanceOf, /// The price of Bulk Coretime after the Leadin Period. - regular_price: BalanceOf, + end_price: BalanceOf, /// The first timeslice of the Regions which are being sold in this sale. region_begin: Timeslice, /// The timeslice on which the Regions which are being sold in the sale terminate. /// (i.e. One after the last timeslice which the Regions control.) region_end: Timeslice, - /// The number of cores we want to sell, ideally. Selling this amount would result in - /// no change to the price for the next sale. + /// The number of cores we want to sell, ideally. ideal_cores_sold: CoreIndex, /// Number of cores which are/have been offered for sale. cores_offered: CoreIndex, @@ -413,7 +414,7 @@ pub mod pallet { assignment: Vec<(CoreAssignment, PartsOf57600)>, }, /// Some historical Instantaneous Core Pool payment record has been dropped. - AllowedRenewalDropped { + PotentialRenewalDropped { /// The timeslice whose renewal is no longer available. when: Timeslice, /// The core whose workload is no longer available to be renewed for `when`. @@ -558,7 +559,7 @@ pub mod pallet { /// Begin the Bulk Coretime sales rotation. /// /// - `origin`: Must be Root or pass `AdminOrigin`. - /// - `initial_price`: The price of Bulk Coretime in the first sale. + /// - `end_price`: The price after the leadin period of Bulk Coretime in the first sale. /// - `extra_cores`: Number of extra cores that should be requested on top of the cores /// required for `Reservations` and `Leases`. /// @@ -570,11 +571,11 @@ pub mod pallet { ))] pub fn start_sales( origin: OriginFor, - initial_price: BalanceOf, + end_price: BalanceOf, extra_cores: CoreIndex, ) -> DispatchResultWithPostInfo { T::AdminOrigin::ensure_origin_or_root(origin)?; - Self::do_start_sales(initial_price, extra_cores)?; + Self::do_start_sales(end_price, extra_cores)?; Ok(Pays::No.into()) } diff --git a/substrate/frame/broker/src/migration.rs b/substrate/frame/broker/src/migration.rs index 95aa28250a62..f354e447fe84 100644 --- a/substrate/frame/broker/src/migration.rs +++ b/substrate/frame/broker/src/migration.rs @@ -77,6 +77,57 @@ mod v1 { } } +mod v2 { + use super::*; + use frame_support::{ + pallet_prelude::{OptionQuery, Twox64Concat}, + storage_alias, + }; + + #[storage_alias] + pub type AllowedRenewals = StorageMap< + Pallet, + Twox64Concat, + PotentialRenewalId, + PotentialRenewalRecordOf, + OptionQuery, + >; + + pub struct MigrateToV2Impl(PhantomData); + + impl UncheckedOnRuntimeUpgrade for MigrateToV2Impl { + fn on_runtime_upgrade() -> frame_support::weights::Weight { + let mut count = 0; + for (renewal_id, renewal) in AllowedRenewals::::drain() { + PotentialRenewals::::insert(renewal_id, renewal); + count += 1; + } + + log::info!( + target: LOG_TARGET, + "Storage migration v2 for pallet-broker finished.", + ); + + // calculate and return migration weights + T::DbWeight::get().reads_writes(count as u64 + 1, count as u64 + 1) + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, sp_runtime::TryRuntimeError> { + Ok((AllowedRenewals::::iter_keys().count() as u32).encode()) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(state: Vec) -> Result<(), sp_runtime::TryRuntimeError> { + let old_count = u32::decode(&mut &state[..]).expect("Known good"); + let new_count = PotentialRenewals::::iter_values().count() as u32; + + ensure!(old_count == new_count, "Renewal count should not change"); + Ok(()) + } + } +} + /// Migrate the pallet storage from `0` to `1`. pub type MigrateV0ToV1 = frame_support::migrations::VersionedMigration< 0, @@ -85,3 +136,11 @@ pub type MigrateV0ToV1 = frame_support::migrations::VersionedMigration< Pallet, ::DbWeight, >; + +pub type MigrateV1ToV2 = frame_support::migrations::VersionedMigration< + 1, + 2, + v2::MigrateToV2Impl, + Pallet, + ::DbWeight, +>; diff --git a/substrate/frame/broker/src/mock.rs b/substrate/frame/broker/src/mock.rs index 6219b4eff1b4..6fff6aa10080 100644 --- a/substrate/frame/broker/src/mock.rs +++ b/substrate/frame/broker/src/mock.rs @@ -199,7 +199,7 @@ impl crate::Config for Test { type WeightInfo = (); type PalletId = TestBrokerId; type AdminOrigin = EnsureOneOrRoot; - type PriceAdapter = Linear; + type PriceAdapter = CenterTargetPrice>; } pub fn advance_to(b: u64) { @@ -255,6 +255,10 @@ impl TestExt { Self(new_config()) } + pub fn new_with_config(config: ConfigRecordOf) -> Self { + Self(config) + } + pub fn advance_notice(mut self, advance_notice: Timeslice) -> Self { self.0.advance_notice = advance_notice as u64; self diff --git a/substrate/frame/broker/src/tests.rs b/substrate/frame/broker/src/tests.rs index f929f0d50dcf..e953afd6dc3c 100644 --- a/substrate/frame/broker/src/tests.rs +++ b/substrate/frame/broker/src/tests.rs @@ -25,7 +25,7 @@ use frame_support::{ }; use frame_system::RawOrigin::Root; use pretty_assertions::assert_eq; -use sp_runtime::{traits::Get, TokenError}; +use sp_runtime::{traits::Get, Perbill, TokenError}; use CoreAssignment::*; use CoretimeTraceItem::*; use Finality::*; @@ -78,9 +78,9 @@ fn drop_renewal_works() { let e = Error::::StillValid; assert_noop!(Broker::do_drop_renewal(region.core, region.begin + 3), e); advance_to(12); - assert_eq!(AllowedRenewals::::iter().count(), 1); + assert_eq!(PotentialRenewals::::iter().count(), 1); assert_ok!(Broker::do_drop_renewal(region.core, region.begin + 3)); - assert_eq!(AllowedRenewals::::iter().count(), 0); + assert_eq!(PotentialRenewals::::iter().count(), 0); let e = Error::::UnknownRenewal; assert_noop!(Broker::do_drop_renewal(region.core, region.begin + 3), e); }); @@ -361,22 +361,91 @@ fn migration_works() { #[test] fn renewal_works() { - TestExt::new().endow(1, 1000).execute_with(|| { + let b = 100_000; + TestExt::new().endow(1, b).execute_with(move || { assert_ok!(Broker::do_start_sales(100, 1)); advance_to(2); let region = Broker::do_purchase(1, u64::max_value()).unwrap(); - assert_eq!(balance(1), 900); + assert_eq!(balance(1), 99_900); assert_ok!(Broker::do_assign(region, None, 1001, Final)); // Should now be renewable. advance_to(6); assert_noop!(Broker::do_purchase(1, u64::max_value()), Error::::TooEarly); let core = Broker::do_renew(1, region.core).unwrap(); - assert_eq!(balance(1), 800); + assert_eq!(balance(1), 99_800); advance_to(8); assert_noop!(Broker::do_purchase(1, u64::max_value()), Error::::SoldOut); advance_to(12); assert_ok!(Broker::do_renew(1, core)); - assert_eq!(balance(1), 690); + assert_eq!(balance(1), 99_690); + }); +} + +#[test] +/// Renewals have to affect price as well. Otherwise a market where everything is a renewal would +/// not work. Renewals happening in the leadin or after are effectively competing with the open +/// market and it makes sense to adjust the price to what was paid here. Assuming all renewals were +/// done in the interlude and only normal sales happen in the leadin, renewals will have no effect +/// on price. If there are no cores left for sale on the open markent, renewals will affect price +/// even in the interlude, making sure renewal prices stay in the range of the open market. +fn renewals_affect_price() { + sp_tracing::try_init_simple(); + let b = 100_000; + let config = ConfigRecord { + advance_notice: 2, + interlude_length: 10, + leadin_length: 20, + ideal_bulk_proportion: Perbill::from_percent(100), + limit_cores_offered: None, + // Region length is in time slices (2 blocks): + region_length: 20, + renewal_bump: Perbill::from_percent(10), + contribution_timeout: 5, + }; + TestExt::new_with_config(config).endow(1, b).execute_with(|| { + let price = 910; + assert_ok!(Broker::do_start_sales(10, 1)); + advance_to(11); + let region = Broker::do_purchase(1, u64::max_value()).unwrap(); + // Price is lower, because already one block in: + let b = b - price; + assert_eq!(balance(1), b); + assert_ok!(Broker::do_assign(region, None, 1001, Final)); + advance_to(40); + assert_noop!(Broker::do_purchase(1, u64::max_value()), Error::::TooEarly); + let core = Broker::do_renew(1, region.core).unwrap(); + // First renewal has same price as initial purchase. + let b = b - price; + assert_eq!(balance(1), b); + advance_to(51); + assert_noop!(Broker::do_purchase(1, u64::max_value()), Error::::SoldOut); + advance_to(81); + assert_ok!(Broker::do_renew(1, core)); + // Renewal bump in effect + let price = price + Perbill::from_percent(10) * price; + let b = b - price; + assert_eq!(balance(1), b); + + // Move after interlude and leadin - should reduce price. + advance_to(159); + Broker::do_renew(1, region.core).unwrap(); + let price = price + Perbill::from_percent(10) * price; + let b = b - price; + assert_eq!(balance(1), b); + + advance_to(161); + // Should have the reduced price now: + Broker::do_renew(1, region.core).unwrap(); + let price = 100; + let b = b - price; + assert_eq!(balance(1), b); + + // Price should be bumped normally again: + advance_to(201); + Broker::do_renew(1, region.core).unwrap(); + let price = 110; + let b = b - price; + assert_eq!(balance(1), b); }); } @@ -916,7 +985,8 @@ fn short_leases_are_cleaned() { #[test] fn leases_can_be_renewed() { - TestExt::new().endow(1, 1000).execute_with(|| { + let initial_balance = 100_000; + TestExt::new().endow(1, initial_balance).execute_with(|| { // Timeslice period is 2. // // Sale 1 starts at block 7, Sale 2 starts at 13. @@ -927,13 +997,13 @@ fn leases_can_be_renewed() { // Start the sales with only one core for this lease. assert_ok!(Broker::do_start_sales(100, 0)); - // Advance to sale period 1, we should get an AllowedRenewal for task 2001 for the next + // Advance to sale period 1, we should get an PotentialRenewal for task 2001 for the next // sale. advance_sale_period(); assert_eq!( - AllowedRenewals::::get(AllowedRenewalId { core: 0, when: 10 }), - Some(AllowedRenewalRecord { - price: 100, + PotentialRenewals::::get(PotentialRenewalId { core: 0, when: 10 }), + Some(PotentialRenewalRecord { + price: 1000, completion: CompletionStatus::Complete( vec![ScheduleItem { mask: CoreMask::complete(), assignment: Task(2001) }] .try_into() @@ -947,8 +1017,8 @@ fn leases_can_be_renewed() { // Advance to sale period 2, where we can renew. advance_sale_period(); assert_ok!(Broker::do_renew(1, 0)); - // We renew for the base price of the previous sale period. - assert_eq!(balance(1), 900); + // We renew for the price of the previous sale period. + assert_eq!(balance(1), initial_balance - 1000); // We just renewed for this period. advance_sale_period(); @@ -1023,14 +1093,14 @@ fn short_leases_cannot_be_renewed() { // The lease is removed. assert_eq!(Leases::::get().len(), 0); - // We should have got an entry in AllowedRenewals, but we don't because rotate_sale + // We should have got an entry in PotentialRenewals, but we don't because rotate_sale // schedules leases a period in advance. This renewal should be in the period after next // because while bootstrapping our way into the sale periods, we give everything a lease for // period 1, so they can renew for period 2. So we have a core until the end of period 1, // but we are not marked as able to renew because we expired before sale period 1 starts. // // This should be fixed. - assert_eq!(AllowedRenewals::::get(AllowedRenewalId { core: 0, when: 10 }), None); + assert_eq!(PotentialRenewals::::get(PotentialRenewalId { core: 0, when: 10 }), None); // And the lease has been removed from storage. assert_eq!(Leases::::get().len(), 0); @@ -1102,7 +1172,7 @@ fn purchase_requires_valid_status_and_sale_info() { let mut dummy_sale = SaleInfoRecord { sale_start: 0, leadin_length: 0, - price: 200, + end_price: 200, sellout_price: None, region_begin: 0, region_end: 3, @@ -1144,7 +1214,7 @@ fn renewal_requires_valid_status_and_sale_info() { let mut dummy_sale = SaleInfoRecord { sale_start: 0, leadin_length: 0, - price: 200, + end_price: 200, sellout_price: None, region_begin: 0, region_end: 3, @@ -1163,11 +1233,11 @@ fn renewal_requires_valid_status_and_sale_info() { assert_ok!(Broker::do_start_sales(200, 1)); assert_noop!(Broker::do_renew(1, 1), Error::::NotAllowed); - let record = AllowedRenewalRecord { + let record = PotentialRenewalRecord { price: 100, completion: CompletionStatus::Partial(CoreMask::from_chunk(0, 20)), }; - AllowedRenewals::::insert(AllowedRenewalId { core: 1, when: 4 }, &record); + PotentialRenewals::::insert(PotentialRenewalId { core: 1, when: 4 }, &record); assert_noop!(Broker::do_renew(1, 1), Error::::IncompleteAssignment); }); } @@ -1274,7 +1344,7 @@ fn config_works() { /// Ensure that a lease that ended before `start_sales` was called can be renewed. #[test] fn renewal_works_leases_ended_before_start_sales() { - TestExt::new().endow(1, 1000).execute_with(|| { + TestExt::new().endow(1, 100_000).execute_with(|| { let config = Configuration::::get().unwrap(); // This lease is ended before `start_stales` was called. @@ -1304,7 +1374,7 @@ fn renewal_works_leases_ended_before_start_sales() { let new_core = Broker::do_renew(1, 0).unwrap(); // Renewing the active lease doesn't work. assert_noop!(Broker::do_renew(1, 1), Error::::SoldOut); - assert_eq!(balance(1), 900); + assert_eq!(balance(1), 99000); // This intializes the third sale and the period 2. advance_sale_period(); @@ -1312,7 +1382,7 @@ fn renewal_works_leases_ended_before_start_sales() { // Renewing the active lease doesn't work. assert_noop!(Broker::do_renew(1, 0), Error::::SoldOut); - assert_eq!(balance(1), 800); + assert_eq!(balance(1), 98900); // All leases should have ended assert!(Leases::::get().is_empty()); @@ -1324,7 +1394,7 @@ fn renewal_works_leases_ended_before_start_sales() { assert_eq!(0, Broker::do_renew(1, new_core).unwrap()); // Renew the task 2. assert_eq!(1, Broker::do_renew(1, 0).unwrap()); - assert_eq!(balance(1), 600); + assert_eq!(balance(1), 98790); // This intializes the fifth sale and the period 4. advance_sale_period(); diff --git a/substrate/frame/broker/src/tick_impls.rs b/substrate/frame/broker/src/tick_impls.rs index 04e9a65bf8f6..20637cf7b903 100644 --- a/substrate/frame/broker/src/tick_impls.rs +++ b/substrate/frame/broker/src/tick_impls.rs @@ -17,10 +17,7 @@ use super::*; use frame_support::{pallet_prelude::*, weights::WeightMeter}; -use sp_arithmetic::{ - traits::{One, SaturatedConversion, Saturating, Zero}, - FixedPointNumber, -}; +use sp_arithmetic::traits::{One, SaturatedConversion, Saturating, Zero}; use sp_runtime::traits::ConvertBack; use sp_std::{vec, vec::Vec}; use CompletionStatus::Complete; @@ -163,31 +160,13 @@ impl Pallet { InstaPoolIo::::mutate(old_sale.region_end, |r| r.system.saturating_reduce(old_pooled)); // Calculate the start price for the upcoming sale. - let price = { - let offered = old_sale.cores_offered; - let ideal = old_sale.ideal_cores_sold; - let sold = old_sale.cores_sold; - - let maybe_purchase_price = if offered == 0 { - // No cores offered for sale - no purchase price. - None - } else if sold >= ideal { - // Sold more than the ideal amount. We should look for the last purchase price - // before the sell-out. If there was no purchase at all, then we avoid having a - // price here so that we make no alterations to it (since otherwise we would - // increase it). - old_sale.sellout_price - } else { - // Sold less than the ideal - we fall back to the regular price. - Some(old_sale.price) - }; - if let Some(purchase_price) = maybe_purchase_price { - T::PriceAdapter::adapt_price(sold.min(offered), ideal, offered) - .saturating_mul_int(purchase_price) - } else { - old_sale.price - } - }; + let new_prices = T::PriceAdapter::adapt_price(SalePerformance::from_sale(&old_sale)); + + log::debug!( + "Rotated sale, new prices: {:?}, {:?}", + new_prices.end_price, + new_prices.target_price + ); // Set workload for the reserved (system, probably) workloads. let region_begin = old_sale.region_end; @@ -220,12 +199,15 @@ impl Pallet { let expire = until < region_end; if expire { // last time for this one - make it renewable in the next sale. - let renewal_id = AllowedRenewalId { core: first_core, when: region_end }; - let record = AllowedRenewalRecord { price, completion: Complete(schedule) }; - AllowedRenewals::::insert(renewal_id, &record); + let renewal_id = PotentialRenewalId { core: first_core, when: region_end }; + let record = PotentialRenewalRecord { + price: new_prices.target_price, + completion: Complete(schedule), + }; + PotentialRenewals::::insert(renewal_id, &record); Self::deposit_event(Event::Renewable { core: first_core, - price, + price: new_prices.target_price, begin: region_end, workload: record.completion.drain_complete().unwrap_or_default(), }); @@ -244,12 +226,19 @@ impl Pallet { let sale_start = now.saturating_add(config.interlude_length); let leadin_length = config.leadin_length; let ideal_cores_sold = (config.ideal_bulk_proportion * cores_offered as u32) as u16; + let sellout_price = if cores_offered > 0 { + // No core sold -> price was too high -> we have to adjust downwards. + Some(new_prices.end_price) + } else { + None + }; + // Update SaleInfo let new_sale = SaleInfoRecord { sale_start, leadin_length, - price, - sellout_price: None, + end_price: new_prices.end_price, + sellout_price, region_begin, region_end, first_core, @@ -257,12 +246,13 @@ impl Pallet { cores_offered, cores_sold: 0, }; + SaleInfo::::put(&new_sale); Self::deposit_event(Event::SaleInitialized { sale_start, leadin_length, start_price: Self::sale_price(&new_sale, now), - regular_price: price, + end_price: new_prices.end_price, region_begin, region_end, ideal_cores_sold, diff --git a/substrate/frame/broker/src/types.rs b/substrate/frame/broker/src/types.rs index f2cae9a41ad4..885cac9a5c23 100644 --- a/substrate/frame/broker/src/types.rs +++ b/substrate/frame/broker/src/types.rs @@ -152,25 +152,28 @@ impl CompletionStatus { } } -/// The identity of a possible Core workload renewal. +/// The identity of a possibly renewable Core workload. #[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] -pub struct AllowedRenewalId { +pub struct PotentialRenewalId { /// The core whose workload at the sale ending with `when` may be renewed to begin at `when`. pub core: CoreIndex, /// The point in time that the renewable workload on `core` ends and a fresh renewal may begin. pub when: Timeslice, } -/// A record of an allowed renewal. +/// A record of a potential renewal. +/// +/// The renewal will only actually be allowed if `CompletionStatus` is `Complete` at the time of +/// renewal. #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] -pub struct AllowedRenewalRecord { +pub struct PotentialRenewalRecord { /// The price for which the next renewal can be made. pub price: Balance, /// The workload which will be scheduled on the Core in the case a renewal is made, or if /// incomplete, then the parts of the core which have been scheduled. pub completion: CompletionStatus, } -pub type AllowedRenewalRecordOf = AllowedRenewalRecord>; +pub type PotentialRenewalRecordOf = PotentialRenewalRecord>; /// General status of the system. #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] @@ -211,7 +214,7 @@ pub struct SaleInfoRecord { /// The length in blocks of the Leadin Period (where the price is decreasing). pub leadin_length: BlockNumber, /// The price of Bulk Coretime after the Leadin Period. - pub price: Balance, + pub end_price: Balance, /// The first timeslice of the Regions which are being sold in this sale. pub region_begin: Timeslice, /// The timeslice on which the Regions which are being sold in the sale terminate. (i.e. One @@ -225,8 +228,9 @@ pub struct SaleInfoRecord { /// The index of the first core which is for sale. Core of Regions which are sold have /// incrementing indices from this. pub first_core: CoreIndex, - /// The latest price at which Bulk Coretime was purchased until surpassing the ideal number of - /// cores were sold. + /// The price at which cores have been sold out. + /// + /// Will only be `None` if no core was offered for sale. pub sellout_price: Option, /// Number of cores which have been sold; never more than cores_offered. pub cores_sold: CoreIndex, @@ -263,8 +267,11 @@ pub struct ConfigRecord { pub leadin_length: BlockNumber, /// The length in timeslices of Regions which are up for sale in forthcoming sales. pub region_length: Timeslice, - /// The proportion of cores available for sale which should be sold in order for the price - /// to remain the same in the next sale. + /// The proportion of cores available for sale which should be sold. + /// + /// If more cores are sold than this, then further sales will no longer be considered in + /// determining the sellout price. In other words the sellout price will be the last price + /// paid, without going over this limit. pub ideal_bulk_proportion: Perbill, /// An artificial limit to the number of cores which are allowed to be sold. If `Some` then /// no more cores will be sold than this. diff --git a/substrate/frame/broker/src/utility_impls.rs b/substrate/frame/broker/src/utility_impls.rs index 4163817a8b58..9cceb7f970a9 100644 --- a/substrate/frame/broker/src/utility_impls.rs +++ b/substrate/frame/broker/src/utility_impls.rs @@ -63,7 +63,7 @@ impl Pallet { pub fn sale_price(sale: &SaleInfoRecordOf, now: BlockNumberFor) -> BalanceOf { let num = now.saturating_sub(sale.sale_start).min(sale.leadin_length).saturated_into(); let through = FixedU64::from_rational(num, sale.leadin_length.saturated_into()); - T::PriceAdapter::leadin_factor_at(through).saturating_mul_int(sale.price) + T::PriceAdapter::leadin_factor_at(through).saturating_mul_int(sale.end_price) } pub(crate) fn charge(who: &T::AccountId, amount: BalanceOf) -> DispatchResult { @@ -72,6 +72,25 @@ impl Pallet { Ok(()) } + /// Buy a core at the specified price (price is to be determined by the caller). + /// + /// Note: It is the responsibility of the caller to write back the changed `SaleInfoRecordOf` to + /// storage. + pub(crate) fn purchase_core( + who: &T::AccountId, + price: BalanceOf, + sale: &mut SaleInfoRecordOf, + ) -> Result { + Self::charge(who, price)?; + log::debug!("Purchased core at: {:?}", price); + let core = sale.first_core.saturating_add(sale.cores_sold); + sale.cores_sold.saturating_inc(); + if sale.cores_sold <= sale.ideal_cores_sold || sale.sellout_price.is_none() { + sale.sellout_price = Some(price); + } + Ok(core) + } + pub fn issue( core: CoreIndex, begin: Timeslice, diff --git a/substrate/frame/broker/src/weights.rs b/substrate/frame/broker/src/weights.rs index 2aa1c282a41d..d9d9d348e47e 100644 --- a/substrate/frame/broker/src/weights.rs +++ b/substrate/frame/broker/src/weights.rs @@ -18,27 +18,25 @@ //! Autogenerated weights for `pallet_broker` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-04-08, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-05-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-anb7yjbi-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-vicqj8em-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate-node +// target/production/substrate-node // benchmark // pallet -// --chain=dev // --steps=50 // --repeat=20 -// --pallet=pallet_broker -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/broker/src/weights.rs +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_broker +// --chain=dev // --header=./substrate/HEADER-APACHE2 +// --output=./substrate/frame/broker/src/weights.rs // --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -90,8 +88,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_624_000 picoseconds. - Weight::from_parts(2_804_000, 0) + // Minimum execution time: 1_945_000 picoseconds. + Weight::from_parts(2_142_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Broker::Reservations` (r:1 w:1) @@ -100,8 +98,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `5016` // Estimated: `7496` - // Minimum execution time: 18_451_000 picoseconds. - Weight::from_parts(18_853_000, 7496) + // Minimum execution time: 16_274_000 picoseconds. + Weight::from_parts(16_828_000, 7496) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -111,8 +109,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `6218` // Estimated: `7496` - // Minimum execution time: 16_899_000 picoseconds. - Weight::from_parts(17_645_000, 7496) + // Minimum execution time: 15_080_000 picoseconds. + Weight::from_parts(15_874_000, 7496) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -122,19 +120,19 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `239` // Estimated: `1526` - // Minimum execution time: 10_239_000 picoseconds. - Weight::from_parts(10_754_000, 1526) + // Minimum execution time: 8_761_000 picoseconds. + Weight::from_parts(9_203_000, 1526) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Broker::Configuration` (r:1 w:0) /// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`) - /// Storage: `Broker::InstaPoolIo` (r:3 w:3) - /// Proof: `Broker::InstaPoolIo` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) - /// Storage: `Broker::Reservations` (r:1 w:0) - /// Proof: `Broker::Reservations` (`max_values`: Some(1), `max_size`: Some(6011), added: 6506, mode: `MaxEncodedLen`) /// Storage: `Broker::Leases` (r:1 w:1) /// Proof: `Broker::Leases` (`max_values`: Some(1), `max_size`: Some(41), added: 536, mode: `MaxEncodedLen`) + /// Storage: `Broker::Reservations` (r:1 w:0) + /// Proof: `Broker::Reservations` (`max_values`: Some(1), `max_size`: Some(6011), added: 6506, mode: `MaxEncodedLen`) + /// Storage: `Broker::InstaPoolIo` (r:3 w:3) + /// Proof: `Broker::InstaPoolIo` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) /// Storage: `Broker::SaleInfo` (r:0 w:1) /// Proof: `Broker::SaleInfo` (`max_values`: Some(1), `max_size`: Some(57), added: 552, mode: `MaxEncodedLen`) /// Storage: `Broker::Status` (r:0 w:1) @@ -146,12 +144,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `6330` // Estimated: `8499` - // Minimum execution time: 51_250_000 picoseconds. - Weight::from_parts(54_643_012, 8499) - // Standard Error: 147 - .saturating_add(Weight::from_parts(18, 0).saturating_mul(n.into())) + // Minimum execution time: 26_057_000 picoseconds. + Weight::from_parts(46_673_357, 8499) + // Standard Error: 456 + .saturating_add(Weight::from_parts(2_677, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(6_u64)) - .saturating_add(T::DbWeight::get().writes(16_u64)) + .saturating_add(T::DbWeight::get().writes(15_u64)) } /// Storage: `Broker::Status` (r:1 w:0) /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) @@ -162,13 +160,13 @@ impl WeightInfo for SubstrateWeight { /// Storage: `System::Digest` (r:1 w:0) /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `Broker::Regions` (r:0 w:1) - /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`) fn purchase() -> Weight { // Proof Size summary in bytes: - // Measured: `635` - // Estimated: `2120` - // Minimum execution time: 43_660_000 picoseconds. - Weight::from_parts(45_543_000, 2120) + // Measured: `651` + // Estimated: `2136` + // Minimum execution time: 40_907_000 picoseconds. + Weight::from_parts(42_566_000, 2136) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -178,8 +176,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) /// Storage: `Broker::SaleInfo` (r:1 w:1) /// Proof: `Broker::SaleInfo` (`max_values`: Some(1), `max_size`: Some(57), added: 552, mode: `MaxEncodedLen`) - /// Storage: `Broker::AllowedRenewals` (r:1 w:2) - /// Proof: `Broker::AllowedRenewals` (`max_values`: None, `max_size`: Some(1233), added: 3708, mode: `MaxEncodedLen`) + /// Storage: `Broker::PotentialRenewals` (r:1 w:2) + /// Proof: `Broker::PotentialRenewals` (`max_values`: None, `max_size`: Some(1233), added: 3708, mode: `MaxEncodedLen`) /// Storage: `Authorship::Author` (r:1 w:0) /// Proof: `Authorship::Author` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) /// Storage: `System::Digest` (r:1 w:0) @@ -188,43 +186,43 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) fn renew() -> Weight { // Proof Size summary in bytes: - // Measured: `753` + // Measured: `769` // Estimated: `4698` - // Minimum execution time: 63_122_000 picoseconds. - Weight::from_parts(64_366_000, 4698) + // Minimum execution time: 65_209_000 picoseconds. + Weight::from_parts(68_604_000, 4698) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } /// Storage: `Broker::Regions` (r:1 w:1) - /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`) fn transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `495` - // Estimated: `3550` - // Minimum execution time: 17_552_000 picoseconds. - Weight::from_parts(18_251_000, 3550) + // Measured: `496` + // Estimated: `3551` + // Minimum execution time: 15_860_000 picoseconds. + Weight::from_parts(16_393_000, 3551) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Broker::Regions` (r:1 w:2) - /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`) fn partition() -> Weight { // Proof Size summary in bytes: - // Measured: `495` - // Estimated: `3550` - // Minimum execution time: 18_551_000 picoseconds. - Weight::from_parts(19_727_000, 3550) + // Measured: `496` + // Estimated: `3551` + // Minimum execution time: 17_651_000 picoseconds. + Weight::from_parts(18_088_000, 3551) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Broker::Regions` (r:1 w:3) - /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`) fn interlace() -> Weight { // Proof Size summary in bytes: - // Measured: `495` - // Estimated: `3550` - // Minimum execution time: 20_636_000 picoseconds. - Weight::from_parts(21_060_000, 3550) + // Measured: `496` + // Estimated: `3551` + // Minimum execution time: 18_576_000 picoseconds. + Weight::from_parts(19_810_000, 3551) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -233,22 +231,22 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Broker::Status` (r:1 w:0) /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) /// Storage: `Broker::Regions` (r:1 w:1) - /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`) /// Storage: `Broker::Workplan` (r:1 w:1) /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) fn assign() -> Weight { // Proof Size summary in bytes: - // Measured: `740` + // Measured: `741` // Estimated: `4681` - // Minimum execution time: 32_394_000 picoseconds. - Weight::from_parts(33_324_000, 4681) + // Minimum execution time: 31_015_000 picoseconds. + Weight::from_parts(31_932_000, 4681) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Broker::Status` (r:1 w:0) /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) /// Storage: `Broker::Regions` (r:1 w:1) - /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`) /// Storage: `Broker::Workplan` (r:1 w:1) /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) /// Storage: `Broker::InstaPoolIo` (r:2 w:2) @@ -257,10 +255,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Broker::InstaPoolContribution` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn pool() -> Weight { // Proof Size summary in bytes: - // Measured: `775` + // Measured: `776` // Estimated: `5996` - // Minimum execution time: 38_128_000 picoseconds. - Weight::from_parts(39_274_000, 5996) + // Minimum execution time: 36_473_000 picoseconds. + Weight::from_parts(37_382_000, 5996) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -275,10 +273,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `859` // Estimated: `6196 + m * (2520 ±0)` - // Minimum execution time: 70_453_000 picoseconds. - Weight::from_parts(70_652_822, 6196) - // Standard Error: 75_524 - .saturating_add(Weight::from_parts(2_335_289, 0).saturating_mul(m.into())) + // Minimum execution time: 64_957_000 picoseconds. + Weight::from_parts(66_024_232, 6196) + // Standard Error: 50_170 + .saturating_add(Weight::from_parts(1_290_632, 0).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(m.into()))) .saturating_add(T::DbWeight::get().writes(5_u64)) @@ -290,21 +288,21 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `103` // Estimated: `3593` - // Minimum execution time: 43_945_000 picoseconds. - Weight::from_parts(45_249_000, 3593) + // Minimum execution time: 39_939_000 picoseconds. + Weight::from_parts(40_788_000, 3593) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Broker::Status` (r:1 w:0) /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) /// Storage: `Broker::Regions` (r:1 w:1) - /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`) fn drop_region() -> Weight { // Proof Size summary in bytes: - // Measured: `603` - // Estimated: `3550` - // Minimum execution time: 30_680_000 picoseconds. - Weight::from_parts(32_995_000, 3550) + // Measured: `604` + // Estimated: `3551` + // Minimum execution time: 31_709_000 picoseconds. + Weight::from_parts(37_559_000, 3551) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -318,8 +316,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `601` // Estimated: `3533` - // Minimum execution time: 48_053_000 picoseconds. - Weight::from_parts(51_364_000, 3533) + // Minimum execution time: 42_895_000 picoseconds. + Weight::from_parts(53_945_000, 3533) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -335,21 +333,21 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `995` // Estimated: `3593` - // Minimum execution time: 57_372_000 picoseconds. - Weight::from_parts(59_466_000, 3593) + // Minimum execution time: 50_770_000 picoseconds. + Weight::from_parts(63_117_000, 3593) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Broker::Status` (r:1 w:0) /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) - /// Storage: `Broker::AllowedRenewals` (r:1 w:1) - /// Proof: `Broker::AllowedRenewals` (`max_values`: None, `max_size`: Some(1233), added: 3708, mode: `MaxEncodedLen`) + /// Storage: `Broker::PotentialRenewals` (r:1 w:1) + /// Proof: `Broker::PotentialRenewals` (`max_values`: None, `max_size`: Some(1233), added: 3708, mode: `MaxEncodedLen`) fn drop_renewal() -> Weight { // Proof Size summary in bytes: // Measured: `661` // Estimated: `4698` - // Minimum execution time: 27_768_000 picoseconds. - Weight::from_parts(29_000_000, 4698) + // Minimum execution time: 33_396_000 picoseconds. + Weight::from_parts(36_247_000, 4698) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -358,20 +356,18 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_588_000 picoseconds. - Weight::from_parts(5_201_705, 0) + // Minimum execution time: 3_625_000 picoseconds. + Weight::from_parts(4_011_396, 0) } /// Storage: `Broker::CoreCountInbox` (r:1 w:1) /// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 1000]`. - fn process_core_count(n: u32, ) -> Weight { + fn process_core_count(_n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `404` // Estimated: `1487` - // Minimum execution time: 6_889_000 picoseconds. - Weight::from_parts(7_380_363, 1487) - // Standard Error: 21 - .saturating_add(Weight::from_parts(63, 0).saturating_mul(n.into())) + // Minimum execution time: 6_217_000 picoseconds. + Weight::from_parts(6_608_394, 1487) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -389,8 +385,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `972` // Estimated: `4437` - // Minimum execution time: 50_156_000 picoseconds. - Weight::from_parts(51_610_000, 4437) + // Minimum execution time: 46_853_000 picoseconds. + Weight::from_parts(47_740_000, 4437) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -405,14 +401,12 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Broker::Workplan` (r:0 w:10) /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 1000]`. - fn rotate_sale(n: u32, ) -> Weight { + fn rotate_sale(_n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `6281` // Estimated: `8499` - // Minimum execution time: 38_246_000 picoseconds. - Weight::from_parts(40_008_850, 8499) - // Standard Error: 94 - .saturating_add(Weight::from_parts(964, 0).saturating_mul(n.into())) + // Minimum execution time: 34_240_000 picoseconds. + Weight::from_parts(35_910_175, 8499) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(15_u64)) } @@ -424,8 +418,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `180` // Estimated: `3493` - // Minimum execution time: 7_962_000 picoseconds. - Weight::from_parts(8_313_000, 3493) + // Minimum execution time: 7_083_000 picoseconds. + Weight::from_parts(7_336_000, 3493) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -437,8 +431,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1423` // Estimated: `4681` - // Minimum execution time: 17_457_000 picoseconds. - Weight::from_parts(18_387_000, 4681) + // Minimum execution time: 15_029_000 picoseconds. + Weight::from_parts(15_567_000, 4681) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -446,8 +440,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 133_000 picoseconds. - Weight::from_parts(149_000, 0) + // Minimum execution time: 123_000 picoseconds. + Weight::from_parts(136_000, 0) } /// Storage: `Broker::CoreCountInbox` (r:0 w:1) /// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) @@ -455,8 +449,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_407_000 picoseconds. - Weight::from_parts(2_634_000, 0) + // Minimum execution time: 1_775_000 picoseconds. + Weight::from_parts(1_911_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Broker::Status` (r:1 w:1) @@ -471,8 +465,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `603` // Estimated: `4068` - // Minimum execution time: 13_043_000 picoseconds. - Weight::from_parts(13_541_000, 4068) + // Minimum execution time: 11_859_000 picoseconds. + Weight::from_parts(12_214_000, 4068) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -482,8 +476,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `239` // Estimated: `1526` - // Minimum execution time: 6_606_000 picoseconds. - Weight::from_parts(6_964_000, 1526) + // Minimum execution time: 5_864_000 picoseconds. + Weight::from_parts(6_231_000, 1526) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -497,8 +491,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_624_000 picoseconds. - Weight::from_parts(2_804_000, 0) + // Minimum execution time: 1_945_000 picoseconds. + Weight::from_parts(2_142_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Broker::Reservations` (r:1 w:1) @@ -507,8 +501,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `5016` // Estimated: `7496` - // Minimum execution time: 18_451_000 picoseconds. - Weight::from_parts(18_853_000, 7496) + // Minimum execution time: 16_274_000 picoseconds. + Weight::from_parts(16_828_000, 7496) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -518,8 +512,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `6218` // Estimated: `7496` - // Minimum execution time: 16_899_000 picoseconds. - Weight::from_parts(17_645_000, 7496) + // Minimum execution time: 15_080_000 picoseconds. + Weight::from_parts(15_874_000, 7496) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -529,19 +523,19 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `239` // Estimated: `1526` - // Minimum execution time: 10_239_000 picoseconds. - Weight::from_parts(10_754_000, 1526) + // Minimum execution time: 8_761_000 picoseconds. + Weight::from_parts(9_203_000, 1526) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Broker::Configuration` (r:1 w:0) /// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`) - /// Storage: `Broker::InstaPoolIo` (r:3 w:3) - /// Proof: `Broker::InstaPoolIo` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) - /// Storage: `Broker::Reservations` (r:1 w:0) - /// Proof: `Broker::Reservations` (`max_values`: Some(1), `max_size`: Some(6011), added: 6506, mode: `MaxEncodedLen`) /// Storage: `Broker::Leases` (r:1 w:1) /// Proof: `Broker::Leases` (`max_values`: Some(1), `max_size`: Some(41), added: 536, mode: `MaxEncodedLen`) + /// Storage: `Broker::Reservations` (r:1 w:0) + /// Proof: `Broker::Reservations` (`max_values`: Some(1), `max_size`: Some(6011), added: 6506, mode: `MaxEncodedLen`) + /// Storage: `Broker::InstaPoolIo` (r:3 w:3) + /// Proof: `Broker::InstaPoolIo` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) /// Storage: `Broker::SaleInfo` (r:0 w:1) /// Proof: `Broker::SaleInfo` (`max_values`: Some(1), `max_size`: Some(57), added: 552, mode: `MaxEncodedLen`) /// Storage: `Broker::Status` (r:0 w:1) @@ -553,12 +547,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `6330` // Estimated: `8499` - // Minimum execution time: 51_250_000 picoseconds. - Weight::from_parts(54_643_012, 8499) - // Standard Error: 147 - .saturating_add(Weight::from_parts(18, 0).saturating_mul(n.into())) + // Minimum execution time: 26_057_000 picoseconds. + Weight::from_parts(46_673_357, 8499) + // Standard Error: 456 + .saturating_add(Weight::from_parts(2_677, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(6_u64)) - .saturating_add(RocksDbWeight::get().writes(16_u64)) + .saturating_add(RocksDbWeight::get().writes(15_u64)) } /// Storage: `Broker::Status` (r:1 w:0) /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) @@ -569,13 +563,13 @@ impl WeightInfo for () { /// Storage: `System::Digest` (r:1 w:0) /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `Broker::Regions` (r:0 w:1) - /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`) fn purchase() -> Weight { // Proof Size summary in bytes: - // Measured: `635` - // Estimated: `2120` - // Minimum execution time: 43_660_000 picoseconds. - Weight::from_parts(45_543_000, 2120) + // Measured: `651` + // Estimated: `2136` + // Minimum execution time: 40_907_000 picoseconds. + Weight::from_parts(42_566_000, 2136) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -585,8 +579,8 @@ impl WeightInfo for () { /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) /// Storage: `Broker::SaleInfo` (r:1 w:1) /// Proof: `Broker::SaleInfo` (`max_values`: Some(1), `max_size`: Some(57), added: 552, mode: `MaxEncodedLen`) - /// Storage: `Broker::AllowedRenewals` (r:1 w:2) - /// Proof: `Broker::AllowedRenewals` (`max_values`: None, `max_size`: Some(1233), added: 3708, mode: `MaxEncodedLen`) + /// Storage: `Broker::PotentialRenewals` (r:1 w:2) + /// Proof: `Broker::PotentialRenewals` (`max_values`: None, `max_size`: Some(1233), added: 3708, mode: `MaxEncodedLen`) /// Storage: `Authorship::Author` (r:1 w:0) /// Proof: `Authorship::Author` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) /// Storage: `System::Digest` (r:1 w:0) @@ -595,43 +589,43 @@ impl WeightInfo for () { /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) fn renew() -> Weight { // Proof Size summary in bytes: - // Measured: `753` + // Measured: `769` // Estimated: `4698` - // Minimum execution time: 63_122_000 picoseconds. - Weight::from_parts(64_366_000, 4698) + // Minimum execution time: 65_209_000 picoseconds. + Weight::from_parts(68_604_000, 4698) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } /// Storage: `Broker::Regions` (r:1 w:1) - /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`) fn transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `495` - // Estimated: `3550` - // Minimum execution time: 17_552_000 picoseconds. - Weight::from_parts(18_251_000, 3550) + // Measured: `496` + // Estimated: `3551` + // Minimum execution time: 15_860_000 picoseconds. + Weight::from_parts(16_393_000, 3551) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Broker::Regions` (r:1 w:2) - /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`) fn partition() -> Weight { // Proof Size summary in bytes: - // Measured: `495` - // Estimated: `3550` - // Minimum execution time: 18_551_000 picoseconds. - Weight::from_parts(19_727_000, 3550) + // Measured: `496` + // Estimated: `3551` + // Minimum execution time: 17_651_000 picoseconds. + Weight::from_parts(18_088_000, 3551) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Broker::Regions` (r:1 w:3) - /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`) fn interlace() -> Weight { // Proof Size summary in bytes: - // Measured: `495` - // Estimated: `3550` - // Minimum execution time: 20_636_000 picoseconds. - Weight::from_parts(21_060_000, 3550) + // Measured: `496` + // Estimated: `3551` + // Minimum execution time: 18_576_000 picoseconds. + Weight::from_parts(19_810_000, 3551) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -640,22 +634,22 @@ impl WeightInfo for () { /// Storage: `Broker::Status` (r:1 w:0) /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) /// Storage: `Broker::Regions` (r:1 w:1) - /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`) /// Storage: `Broker::Workplan` (r:1 w:1) /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) fn assign() -> Weight { // Proof Size summary in bytes: - // Measured: `740` + // Measured: `741` // Estimated: `4681` - // Minimum execution time: 32_394_000 picoseconds. - Weight::from_parts(33_324_000, 4681) + // Minimum execution time: 31_015_000 picoseconds. + Weight::from_parts(31_932_000, 4681) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Broker::Status` (r:1 w:0) /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) /// Storage: `Broker::Regions` (r:1 w:1) - /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`) /// Storage: `Broker::Workplan` (r:1 w:1) /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) /// Storage: `Broker::InstaPoolIo` (r:2 w:2) @@ -664,10 +658,10 @@ impl WeightInfo for () { /// Proof: `Broker::InstaPoolContribution` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn pool() -> Weight { // Proof Size summary in bytes: - // Measured: `775` + // Measured: `776` // Estimated: `5996` - // Minimum execution time: 38_128_000 picoseconds. - Weight::from_parts(39_274_000, 5996) + // Minimum execution time: 36_473_000 picoseconds. + Weight::from_parts(37_382_000, 5996) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -682,10 +676,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `859` // Estimated: `6196 + m * (2520 ±0)` - // Minimum execution time: 70_453_000 picoseconds. - Weight::from_parts(70_652_822, 6196) - // Standard Error: 75_524 - .saturating_add(Weight::from_parts(2_335_289, 0).saturating_mul(m.into())) + // Minimum execution time: 64_957_000 picoseconds. + Weight::from_parts(66_024_232, 6196) + // Standard Error: 50_170 + .saturating_add(Weight::from_parts(1_290_632, 0).saturating_mul(m.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(m.into()))) .saturating_add(RocksDbWeight::get().writes(5_u64)) @@ -697,21 +691,21 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `103` // Estimated: `3593` - // Minimum execution time: 43_945_000 picoseconds. - Weight::from_parts(45_249_000, 3593) + // Minimum execution time: 39_939_000 picoseconds. + Weight::from_parts(40_788_000, 3593) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Broker::Status` (r:1 w:0) /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) /// Storage: `Broker::Regions` (r:1 w:1) - /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(86), added: 2561, mode: `MaxEncodedLen`) fn drop_region() -> Weight { // Proof Size summary in bytes: - // Measured: `603` - // Estimated: `3550` - // Minimum execution time: 30_680_000 picoseconds. - Weight::from_parts(32_995_000, 3550) + // Measured: `604` + // Estimated: `3551` + // Minimum execution time: 31_709_000 picoseconds. + Weight::from_parts(37_559_000, 3551) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -725,8 +719,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `601` // Estimated: `3533` - // Minimum execution time: 48_053_000 picoseconds. - Weight::from_parts(51_364_000, 3533) + // Minimum execution time: 42_895_000 picoseconds. + Weight::from_parts(53_945_000, 3533) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -742,21 +736,21 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `995` // Estimated: `3593` - // Minimum execution time: 57_372_000 picoseconds. - Weight::from_parts(59_466_000, 3593) + // Minimum execution time: 50_770_000 picoseconds. + Weight::from_parts(63_117_000, 3593) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Broker::Status` (r:1 w:0) /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) - /// Storage: `Broker::AllowedRenewals` (r:1 w:1) - /// Proof: `Broker::AllowedRenewals` (`max_values`: None, `max_size`: Some(1233), added: 3708, mode: `MaxEncodedLen`) + /// Storage: `Broker::PotentialRenewals` (r:1 w:1) + /// Proof: `Broker::PotentialRenewals` (`max_values`: None, `max_size`: Some(1233), added: 3708, mode: `MaxEncodedLen`) fn drop_renewal() -> Weight { // Proof Size summary in bytes: // Measured: `661` // Estimated: `4698` - // Minimum execution time: 27_768_000 picoseconds. - Weight::from_parts(29_000_000, 4698) + // Minimum execution time: 33_396_000 picoseconds. + Weight::from_parts(36_247_000, 4698) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -765,20 +759,18 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_588_000 picoseconds. - Weight::from_parts(5_201_705, 0) + // Minimum execution time: 3_625_000 picoseconds. + Weight::from_parts(4_011_396, 0) } /// Storage: `Broker::CoreCountInbox` (r:1 w:1) /// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 1000]`. - fn process_core_count(n: u32, ) -> Weight { + fn process_core_count(_n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `404` // Estimated: `1487` - // Minimum execution time: 6_889_000 picoseconds. - Weight::from_parts(7_380_363, 1487) - // Standard Error: 21 - .saturating_add(Weight::from_parts(63, 0).saturating_mul(n.into())) + // Minimum execution time: 6_217_000 picoseconds. + Weight::from_parts(6_608_394, 1487) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -796,8 +788,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `972` // Estimated: `4437` - // Minimum execution time: 50_156_000 picoseconds. - Weight::from_parts(51_610_000, 4437) + // Minimum execution time: 46_853_000 picoseconds. + Weight::from_parts(47_740_000, 4437) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -812,14 +804,12 @@ impl WeightInfo for () { /// Storage: `Broker::Workplan` (r:0 w:10) /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 1000]`. - fn rotate_sale(n: u32, ) -> Weight { + fn rotate_sale(_n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `6281` // Estimated: `8499` - // Minimum execution time: 38_246_000 picoseconds. - Weight::from_parts(40_008_850, 8499) - // Standard Error: 94 - .saturating_add(Weight::from_parts(964, 0).saturating_mul(n.into())) + // Minimum execution time: 34_240_000 picoseconds. + Weight::from_parts(35_910_175, 8499) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(15_u64)) } @@ -831,8 +821,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `180` // Estimated: `3493` - // Minimum execution time: 7_962_000 picoseconds. - Weight::from_parts(8_313_000, 3493) + // Minimum execution time: 7_083_000 picoseconds. + Weight::from_parts(7_336_000, 3493) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -844,8 +834,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1423` // Estimated: `4681` - // Minimum execution time: 17_457_000 picoseconds. - Weight::from_parts(18_387_000, 4681) + // Minimum execution time: 15_029_000 picoseconds. + Weight::from_parts(15_567_000, 4681) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -853,8 +843,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 133_000 picoseconds. - Weight::from_parts(149_000, 0) + // Minimum execution time: 123_000 picoseconds. + Weight::from_parts(136_000, 0) } /// Storage: `Broker::CoreCountInbox` (r:0 w:1) /// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) @@ -862,8 +852,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_407_000 picoseconds. - Weight::from_parts(2_634_000, 0) + // Minimum execution time: 1_775_000 picoseconds. + Weight::from_parts(1_911_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Broker::Status` (r:1 w:1) @@ -878,8 +868,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `603` // Estimated: `4068` - // Minimum execution time: 13_043_000 picoseconds. - Weight::from_parts(13_541_000, 4068) + // Minimum execution time: 11_859_000 picoseconds. + Weight::from_parts(12_214_000, 4068) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -889,8 +879,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `239` // Estimated: `1526` - // Minimum execution time: 6_606_000 picoseconds. - Weight::from_parts(6_964_000, 1526) + // Minimum execution time: 5_864_000 picoseconds. + Weight::from_parts(6_231_000, 1526) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) }