diff --git a/Cargo.lock b/Cargo.lock index d6c46ad9975e7..307a6a52329ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9423,6 +9423,7 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", + "sp-api", "sp-arithmetic", "sp-core", "sp-io", diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs index 1c67740ee5400..9f01d397598cb 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs @@ -64,7 +64,7 @@ use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::Block as BlockT, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, MultiAddress, Perbill, + ApplyExtrinsicResult, DispatchError, MultiAddress, Perbill, }; use sp_std::prelude::*; #[cfg(feature = "std")] @@ -593,6 +593,12 @@ impl_runtime_apis! { } } + impl pallet_broker::runtime_api::BrokerApi for Runtime { + fn sale_price() -> Result { + Broker::current_price() + } + } + impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi for Runtime { fn query_info( uxt: ::Extrinsic, diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs index 696618c37a28b..29d348c1cd90e 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs @@ -64,7 +64,7 @@ use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::Block as BlockT, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, MultiAddress, Perbill, + ApplyExtrinsicResult, DispatchError, MultiAddress, Perbill, }; use sp_std::prelude::*; #[cfg(feature = "std")] @@ -584,6 +584,12 @@ impl_runtime_apis! { } } + impl pallet_broker::runtime_api::BrokerApi for Runtime { + fn sale_price() -> Result { + Broker::current_price() + } + } + impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi for Runtime { fn query_info( uxt: ::Extrinsic, diff --git a/prdoc/pr_3485.prdoc b/prdoc/pr_3485.prdoc new file mode 100644 index 0000000000000..2add8867c4cdb --- /dev/null +++ b/prdoc/pr_3485.prdoc @@ -0,0 +1,20 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: "Broker: sale price runtime api" + +doc: + - audience: Runtime Dev + description: | + Defines a runtime api for `pallet-broker` for getting the current price + of a core in the ongoing sale. + + - audience: Runtime User + description: | + Defines a runtime api for `pallet-broker` for getting the current price + of a core in the ongoing sale. + +crates: + - name: pallet-broker + - name: coretime-rococo-runtime + - name: coretime-westend-runtime diff --git a/substrate/frame/broker/Cargo.toml b/substrate/frame/broker/Cargo.toml index 3b6bd2019cc17..969f13e269de4 100644 --- a/substrate/frame/broker/Cargo.toml +++ b/substrate/frame/broker/Cargo.toml @@ -18,6 +18,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } bitvec = { version = "1.0.0", default-features = false } +sp-api = { path = "../../primitives/api", default-features = false } sp-std = { path = "../../primitives/std", default-features = false } sp-arithmetic = { path = "../../primitives/arithmetic", default-features = false } sp-core = { path = "../../primitives/core", default-features = false } @@ -39,6 +40,7 @@ std = [ "frame-support/std", "frame-system/std", "scale-info/std", + "sp-api/std", "sp-arithmetic/std", "sp-core/std", "sp-io/std", diff --git a/substrate/frame/broker/src/dispatchable_impls.rs b/substrate/frame/broker/src/dispatchable_impls.rs index a87618147fea2..ef20bc8fb80b1 100644 --- a/substrate/frame/broker/src/dispatchable_impls.rs +++ b/substrate/frame/broker/src/dispatchable_impls.rs @@ -105,8 +105,8 @@ impl Pallet { ) -> Result { let status = Status::::get().ok_or(Error::::Uninitialized)?; let mut sale = SaleInfo::::get().ok_or(Error::::NoSales)?; - ensure!(sale.first_core < status.core_count, Error::::Unavailable); - ensure!(sale.cores_sold < sale.cores_offered, Error::::SoldOut); + Self::ensure_cores_for_sale(&status, &sale)?; + let now = frame_system::Pallet::::block_number(); ensure!(now > sale.sale_start, Error::::TooEarly); let price = Self::sale_price(&sale, now); @@ -131,8 +131,7 @@ impl Pallet { let config = Configuration::::get().ok_or(Error::::Uninitialized)?; let status = Status::::get().ok_or(Error::::Uninitialized)?; let mut sale = SaleInfo::::get().ok_or(Error::::NoSales)?; - ensure!(sale.first_core < status.core_count, Error::::Unavailable); - ensure!(sale.cores_sold < sale.cores_offered, Error::::SoldOut); + 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)?; @@ -456,4 +455,25 @@ impl Pallet { Ok(()) } + + pub(crate) fn ensure_cores_for_sale( + status: &StatusRecord, + sale: &SaleInfoRecordOf, + ) -> Result<(), DispatchError> { + ensure!(sale.first_core < status.core_count, Error::::Unavailable); + ensure!(sale.cores_sold < sale.cores_offered, Error::::SoldOut); + + Ok(()) + } + + /// If there is an ongoing sale returns the current price of a core. + pub fn current_price() -> Result, DispatchError> { + let status = Status::::get().ok_or(Error::::Uninitialized)?; + let sale = SaleInfo::::get().ok_or(Error::::NoSales)?; + + Self::ensure_cores_for_sale(&status, &sale)?; + + let now = frame_system::Pallet::::block_number(); + Ok(Self::sale_price(&sale, now)) + } } diff --git a/substrate/frame/broker/src/lib.rs b/substrate/frame/broker/src/lib.rs index d059965a392ac..a39576b09013f 100644 --- a/substrate/frame/broker/src/lib.rs +++ b/substrate/frame/broker/src/lib.rs @@ -36,6 +36,8 @@ mod tick_impls; mod types; mod utility_impls; +pub mod runtime_api; + pub mod weights; pub use weights::WeightInfo; @@ -132,7 +134,7 @@ pub mod pallet { pub type AllowedRenewals = StorageMap<_, Twox64Concat, AllowedRenewalId, AllowedRenewalRecordOf, OptionQuery>; - /// The current (unassigned) Regions. + /// The current (unassigned or provisionally assigend) Regions. #[pallet::storage] pub type Regions = StorageMap<_, Blake2_128Concat, RegionId, RegionRecordOf, OptionQuery>; diff --git a/substrate/frame/broker/src/runtime_api.rs b/substrate/frame/broker/src/runtime_api.rs new file mode 100644 index 0000000000000..6faab61565038 --- /dev/null +++ b/substrate/frame/broker/src/runtime_api.rs @@ -0,0 +1,31 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Runtime API definition for the FRAME Broker pallet. + +use codec::Codec; +use sp_runtime::DispatchError; + +sp_api::decl_runtime_apis! { + pub trait BrokerApi + where + Balance: Codec + { + /// If there is an ongoing sale returns the current price of a core. + fn sale_price() -> Result; + } +}