subcoin_runtime/
lib.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! Subcoin runtime is a minimalistic Substrate runtime consisting of frame-system and
19//! pallet-bitcoin. It does not implement all the typical runtime APIs the normal runtimes
20//! would do as many of them does not make sense in Subcoin.
21
22#![cfg_attr(not(feature = "std"), no_std)]
23
24// Make the WASM binary available.
25#[cfg(feature = "std")]
26include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
27
28extern crate alloc;
29
30use frame_support::dispatch::PerDispatchClass;
31use frame_support::genesis_builder_helper::{build_state, get_preset};
32use frame_support::pallet_prelude::*;
33use frame_support::{derive_impl, parameter_types};
34use frame_system::limits::WeightsPerClass;
35use frame_system::pallet_prelude::*;
36use pallet_executive::Executive;
37use sp_api::impl_runtime_apis;
38use sp_core::{ConstU32, OpaqueMetadata};
39use sp_inherents::{CheckInherentsResult, InherentData};
40use sp_runtime::traits::Get;
41use sp_runtime::transaction_validity::{TransactionSource, TransactionValidity};
42use sp_runtime::{ApplyExtrinsicResult, ExtrinsicInclusionMode};
43use sp_std::vec;
44use sp_std::vec::Vec;
45#[cfg(feature = "std")]
46use sp_version::NativeVersion;
47use sp_version::{RuntimeVersion, runtime_version};
48
49/// header weight (80 * 4) + tx_data_len(4)
50const BITCOIN_BASE_BLOCK_WEIGHT: u64 = 80 * 4 + 4;
51
52/// Maximum block weight.
53/// https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#Block_size
54const BITCOIN_MAX_WEIGHT: u64 = 4_000_000;
55
56#[runtime_version]
57pub const VERSION: RuntimeVersion = RuntimeVersion {
58    spec_name: alloc::borrow::Cow::Borrowed("subcoin"),
59    impl_name: alloc::borrow::Cow::Borrowed("subcoin"),
60    authoring_version: 0,
61    spec_version: 0,
62    impl_version: 0,
63    apis: RUNTIME_API_VERSIONS,
64    transaction_version: 0,
65    system_version: 1,
66};
67
68/// The version information used to identify this runtime when compiled natively.
69#[cfg(feature = "std")]
70pub fn native_version() -> NativeVersion {
71    NativeVersion {
72        runtime_version: VERSION,
73        can_author_with: Default::default(),
74    }
75}
76
77parameter_types! {
78    pub const Version: RuntimeVersion = VERSION;
79}
80
81#[frame_support::runtime]
82mod runtime {
83    // The main runtime
84    #[runtime::runtime]
85    // Runtime Types to be generated
86    #[runtime::derive(RuntimeCall, RuntimeEvent, RuntimeError, RuntimeOrigin, RuntimeTask)]
87    pub struct Runtime;
88
89    #[runtime::pallet_index(0)]
90    pub type System = frame_system::Pallet<Runtime>;
91
92    #[runtime::pallet_index(1)]
93    pub type Bitcoin = pallet_bitcoin::Pallet<Runtime>;
94}
95
96#[derive_impl(frame_system::config_preludes::SolochainDefaultConfig as frame_system::DefaultConfig)]
97impl frame_system::Config for Runtime {
98    type Block = Block;
99    type Version = Version;
100    type BlockHashCount = ConstU32<1024>;
101    type BlockWeights = BlockWeights;
102}
103
104/// Subcoin block weights.
105pub struct BlockWeights;
106
107impl Get<frame_system::limits::BlockWeights> for BlockWeights {
108    fn get() -> frame_system::limits::BlockWeights {
109        frame_system::limits::BlockWeights {
110            base_block: Weight::from_parts(BITCOIN_BASE_BLOCK_WEIGHT, 0u64),
111            max_block: Weight::from_parts(BITCOIN_MAX_WEIGHT, u64::MAX),
112            per_class: PerDispatchClass::new(|class| {
113                let initial = if class == DispatchClass::Mandatory {
114                    None
115                } else {
116                    Some(Weight::zero())
117                };
118                WeightsPerClass {
119                    base_extrinsic: Weight::zero(),
120                    max_extrinsic: None,
121                    max_total: initial,
122                    reserved: initial,
123                }
124            }),
125        }
126    }
127}
128
129impl pallet_bitcoin::Config for Runtime {
130    type WeightInfo = pallet_bitcoin::BitcoinTransactionWeight;
131}
132
133type SignedExtra = (
134    frame_system::CheckNonZeroSender<Runtime>,
135    frame_system::CheckSpecVersion<Runtime>,
136    frame_system::CheckGenesis<Runtime>,
137);
138type Signature = crate::types_common::Signature;
139type Block = crate::types_common::BlockOf<Runtime, SignedExtra>;
140// TODO: Proper address
141pub type Address = sp_runtime::MultiAddress<interface::AccountId, ()>;
142pub type Header = HeaderFor<Runtime>;
143pub type UncheckedExtrinsic =
144    sp_runtime::generic::UncheckedExtrinsic<Address, RuntimeCall, Signature, SignedExtra>;
145
146type RuntimeExecutive =
147    Executive<Runtime, Block, frame_system::ChainContext<Runtime>, Runtime, AllPalletsWithSystem>;
148
149impl_runtime_apis! {
150    impl sp_api::Core<Block> for Runtime {
151        fn version() -> RuntimeVersion {
152            VERSION
153        }
154
155        fn execute_block(block: Block) {
156            RuntimeExecutive::execute_block(block)
157        }
158
159        fn initialize_block(header: &Header) -> ExtrinsicInclusionMode {
160            RuntimeExecutive::initialize_block(header)
161        }
162    }
163
164    impl sp_api::Metadata<Block> for Runtime {
165        fn metadata() -> OpaqueMetadata {
166            OpaqueMetadata::new(Runtime::metadata().into())
167        }
168
169        fn metadata_at_version(version: u32) -> Option<OpaqueMetadata> {
170            Runtime::metadata_at_version(version)
171        }
172
173        fn metadata_versions() -> Vec<u32> {
174            Runtime::metadata_versions()
175        }
176    }
177
178    // Cannot be removed as required by frame-benchmarking-cli.
179    impl sp_block_builder::BlockBuilder<Block> for Runtime {
180        fn apply_extrinsic(extrinsic: ExtrinsicFor<Runtime>) -> ApplyExtrinsicResult {
181            RuntimeExecutive::apply_extrinsic(extrinsic)
182        }
183
184        fn finalize_block() -> HeaderFor<Runtime> {
185            unimplemented!("BlockBuilder::finalize_block() is useless in Subcoin")
186        }
187
188        fn inherent_extrinsics(data: InherentData) -> Vec<ExtrinsicFor<Runtime>> {
189            data.create_extrinsics()
190        }
191
192        fn check_inherents(
193            block: Block,
194            data: InherentData,
195        ) -> CheckInherentsResult {
196            data.check_extrinsics(&block)
197        }
198    }
199
200    impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
201        fn validate_transaction(
202            source: TransactionSource,
203            tx: ExtrinsicFor<Runtime>,
204            block_hash: <Runtime as frame_system::Config>::Hash,
205        ) -> TransactionValidity {
206            RuntimeExecutive::validate_transaction(source, tx, block_hash)
207        }
208    }
209
210    // Cannot be removed as required by SystemApiServer in rpc.
211    impl frame_system_rpc_runtime_api::AccountNonceApi<Block, interface::AccountId, interface::Nonce> for Runtime {
212        fn account_nonce(account: interface::AccountId) -> interface::Nonce {
213            System::account_nonce(account)
214        }
215    }
216
217    impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
218        fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
219            build_state::<RuntimeGenesisConfig>(config)
220        }
221
222        fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
223            get_preset::<RuntimeGenesisConfig>(id, |_| None)
224        }
225
226        fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
227            vec![]
228        }
229    }
230
231    impl subcoin_runtime_primitives::SubcoinApi<Block> for Runtime {
232        fn execute_block_without_state_root_check(block: Block) {
233            RuntimeExecutive::execute_block_without_state_root_check(block)
234        }
235
236        fn finalize_block_without_checks(header: HeaderFor<Runtime>) {
237            RuntimeExecutive::finalize_block_without_checks(header);
238        }
239
240        fn coins_count() -> u64 {
241            Bitcoin::coins_count()
242        }
243    }
244}
245
246/// A set of opinionated types aliases commonly used in runtimes.
247///
248/// This is one set of opinionated types. They are compatible with one another, but are not
249/// guaranteed to work if you start tweaking a portion.
250///
251/// Some note-worthy opinions in this prelude:
252///
253/// - `u32` block number.
254/// - [`sp_runtime::MultiAddress`] and [`sp_runtime::MultiSignature`] are used as the account id
255///   and signature types. This implies that this prelude can possibly used with an
256///   "account-index" system (eg `pallet-indices`). And, in any case, it should be paired with
257///   `AccountIdLookup` in [`frame_system::Config::Lookup`].
258mod types_common {
259    use frame_system::Config as SysConfig;
260    use sp_runtime::{OpaqueExtrinsic, generic, traits};
261
262    /// A signature type compatible capably of handling multiple crypto-schemes.
263    pub type Signature = sp_runtime::MultiSignature;
264
265    /// The corresponding account-id type of [`Signature`].
266    pub type AccountId =
267        <<Signature as traits::Verify>::Signer as traits::IdentifyAccount>::AccountId;
268
269    /// The block-number type, which should be fed into [`frame_system::Config`].
270    pub type BlockNumber = u32;
271
272    /// TODO: Ideally we want the hashing type to be equal to SysConfig::Hashing?
273    type HeaderInner = generic::Header<BlockNumber, traits::BlakeTwo256>;
274
275    // NOTE: `AccountIndex` is provided for future compatibility, if you want to introduce
276    // something like `pallet-indices`.
277    type ExtrinsicInner<T, Extra, AccountIndex = ()> = generic::UncheckedExtrinsic<
278        sp_runtime::MultiAddress<AccountId, AccountIndex>,
279        <T as SysConfig>::RuntimeCall,
280        Signature,
281        Extra,
282    >;
283
284    /// The block type, which should be fed into [`frame_system::Config`].
285    ///
286    /// Should be parameterized with `T: frame_system::Config` and a tuple of `SignedExtension`.
287    /// When in doubt, use [`SystemSignedExtensionsOf`].
288    // Note that this cannot be dependent on `T` for block-number because it would lead to a
289    // circular dependency (self-referential generics).
290    pub type BlockOf<T, Extra = ()> = generic::Block<HeaderInner, ExtrinsicInner<T, Extra>>;
291
292    /// The opaque block type. This is the same `BlockOf`, but it has
293    /// [`sp_runtime::OpaqueExtrinsic`] as its final extrinsic type.
294    ///
295    /// This should be provided to the client side as the extrinsic type.
296    pub type OpaqueBlock = generic::Block<HeaderInner, OpaqueExtrinsic>;
297}
298
299/// Some re-exports that the node side code needs to know. Some are useful in this context as well.
300///
301/// Other types should preferably be private.
302// TODO: this should be standardized in some way, see:
303// https://github.com/paritytech/substrate/issues/10579#issuecomment-1600537558
304pub mod interface {
305    use super::Runtime;
306
307    pub type Block = super::Block;
308    pub use crate::types_common::OpaqueBlock;
309    pub type AccountId = <Runtime as frame_system::Config>::AccountId;
310    pub type Nonce = <Runtime as frame_system::Config>::Nonce;
311    pub type Hash = <Runtime as frame_system::Config>::Hash;
312    pub type Balance = u128;
313}