violet_node_runtime/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.
3#![recursion_limit = "256"]
4
5// Make the WASM binary available.
6#[cfg(feature = "std")]
7include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
8
9mod assets_config;
10mod contracts_config;
11mod ordinals_config;
12
13use frame_support::{
14	derive_impl,
15	dispatch::DispatchClass,
16	genesis_builder_helper::{build_config, create_default_config},
17};
18use frame_system::limits::{BlockLength, BlockWeights};
19use polkadot_runtime_common::SlowAdjustingFeeUpdate;
20use sp_api::impl_runtime_apis;
21use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
22use sp_runtime::{
23	create_runtime_str, generic, impl_opaque_keys,
24	traits::{BlakeTwo256, Block as BlockT, IdentifyAccount, Verify},
25	transaction_validity::{TransactionSource, TransactionValidity},
26	ApplyExtrinsicResult, MultiSignature,
27};
28use sp_std::prelude::*;
29#[cfg(feature = "std")]
30use sp_version::NativeVersion;
31use sp_version::RuntimeVersion;
32
33// A few exports that help ease life for downstream crates.
34pub use frame_support::{
35	construct_runtime, parameter_types,
36	traits::{
37		AsEnsureOriginWithArg, ConstBool, ConstU128, ConstU32, ConstU8, KeyOwnerProofSystem,
38		Randomness, StorageInfo,
39	},
40	weights::{
41		constants::{
42			BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND,
43		},
44		IdentityFee, Weight,
45	},
46	StorageValue,
47};
48pub use frame_system::Call as SystemCall;
49pub use pallet_balances::Call as BalancesCall;
50pub use pallet_timestamp::Call as TimestampCall;
51use pallet_transaction_payment::CurrencyAdapter;
52#[cfg(any(feature = "std", test))]
53pub use sp_runtime::BuildStorage;
54pub use sp_runtime::{Perbill, Permill};
55
56/// An index to a block.
57pub type BlockNumber = u32;
58
59/// Alias to 512-bit hash when used in the context of a transaction signature on the chain.
60pub type Signature = MultiSignature;
61
62/// Some way of identifying an account on the chain. We intentionally make it equivalent
63/// to the public key of our transaction signing scheme.
64pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;
65
66/// Balance of an account.
67pub type Balance = u128;
68
69/// Index of a transaction in the chain.
70pub type Nonce = u32;
71
72/// A hash of some data used by the chain.
73pub type Hash = sp_core::H256;
74
75/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
76/// the specifics of the runtime. They can then be made to be agnostic over specific formats
77/// of data like extrinsics, allowing for them to continue syncing the network through upgrades
78/// to even the core data structures.
79pub mod opaque {
80	use super::*;
81
82	pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;
83
84	/// Opaque block header type.
85	pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
86	/// Opaque block type.
87	pub type Block = generic::Block<Header, UncheckedExtrinsic>;
88	/// Opaque block identifier type.
89	pub type BlockId = generic::BlockId<Block>;
90
91	impl_opaque_keys! {
92		pub struct SessionKeys {}
93	}
94}
95// To learn more about runtime versioning, see:
96// https://docs.substrate.io/main-docs/build/upgrade#runtime-versioning
97#[sp_version::runtime_version]
98pub const VERSION: RuntimeVersion = RuntimeVersion {
99	spec_name: create_runtime_str!("violet-node"),
100	impl_name: create_runtime_str!("violet-node"),
101	authoring_version: 1,
102	// The version of the runtime specification. A full node will not attempt to use its native
103	//   runtime in substitute for the on-chain Wasm runtime unless all of `spec_name`,
104	//   `spec_version`, and `authoring_version` are the same between Wasm and native.
105	// This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use
106	//   the compatible custom types.
107	spec_version: 100,
108	impl_version: 1,
109	apis: RUNTIME_API_VERSIONS,
110	transaction_version: 1,
111	state_version: 1,
112};
113
114/// The version information used to identify this runtime when compiled natively.
115#[cfg(feature = "std")]
116pub fn native_version() -> NativeVersion {
117	NativeVersion { runtime_version: VERSION, can_author_with: Default::default() }
118}
119
120const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);
121
122/// We assume that ~10% of the block weight is consumed by `on_initialize` handlers.
123/// This is used to limit the maximal weight of a single extrinsic.
124const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10);
125
126/// We allow for 2 seconds of compute with a 6 second average block time, with maximum proof size.
127const MAXIMUM_BLOCK_WEIGHT: Weight =
128	Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND.saturating_mul(2), u64::MAX);
129
130// Prints debug output of the `contracts` pallet to stdout if the node is
131// started with `-lruntime::contracts=debug`.
132const CONTRACTS_DEBUG_OUTPUT: pallet_contracts::DebugInfo =
133	pallet_contracts::DebugInfo::UnsafeDebug;
134const CONTRACTS_EVENTS: pallet_contracts::CollectEvents =
135	pallet_contracts::CollectEvents::UnsafeCollect;
136
137// Unit = the base number of indivisible units for balances
138const MILLIUNIT: Balance = 1_000_000_000;
139pub const EXISTENTIAL_DEPOSIT: Balance = MILLIUNIT;
140
141impl pallet_insecure_randomness_collective_flip::Config for Runtime {}
142
143parameter_types! {
144	pub const BlockHashCount: BlockNumber = 2400;
145	pub const Version: RuntimeVersion = VERSION;
146
147	// This part is copied from Substrate's `bin/node/runtime/src/lib.rs`.
148	//  The `RuntimeBlockLength` and `RuntimeBlockWeights` exist here because the
149	// `DeletionWeightLimit` and `DeletionQueueDepth` depend on those to parameterize
150	// the lazy contract deletion.
151	pub RuntimeBlockLength: BlockLength =
152		BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);
153	pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()
154		.base_block(BlockExecutionWeight::get())
155		.for_class(DispatchClass::all(), |weights| {
156			weights.base_extrinsic = ExtrinsicBaseWeight::get();
157		})
158		.for_class(DispatchClass::Normal, |weights| {
159			weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);
160		})
161		.for_class(DispatchClass::Operational, |weights| {
162			weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);
163			// Operational transactions have some extra reserved space, so that they
164			// are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.
165			weights.reserved = Some(
166				MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT
167			);
168		})
169		.avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)
170		.build_or_panic();
171
172	pub const SS58Prefix: u8 = 42;
173}
174
175// Configure FRAME pallets to include in runtime.
176
177#[derive_impl(frame_system::config_preludes::SolochainDefaultConfig)]
178impl frame_system::Config for Runtime {
179	/// The block type for the runtime.
180	type Block = Block;
181	/// Block & extrinsics weights: base values and limits.
182	type BlockWeights = RuntimeBlockWeights;
183	/// The maximum length of a block (in bytes).
184	type BlockLength = RuntimeBlockLength;
185	/// The identifier used to distinguish between accounts.
186	type AccountId = AccountId;
187	/// The type for storing how many extrinsics an account has signed.
188	type Nonce = Nonce;
189	/// The type for hashing blocks and tries.
190	type Hash = Hash;
191	/// Maximum number of block number to block hash mappings to keep (oldest pruned first).
192	type BlockHashCount = BlockHashCount;
193	/// The weight of database operations that the runtime can invoke.
194	type DbWeight = RocksDbWeight;
195	/// Version of the runtime.
196	type Version = Version;
197	/// The data to be stored in an account.
198	type AccountData = pallet_balances::AccountData<Balance>;
199	/// This is used as an identifier of the chain. 42 is the generic substrate prefix.
200	type SS58Prefix = SS58Prefix;
201	type MaxConsumers = frame_support::traits::ConstU32<16>;
202}
203
204parameter_types! {
205	pub const UncleGenerations: u32 = 0;
206}
207
208impl pallet_authorship::Config for Runtime {
209	type FindAuthor = ();
210	type EventHandler = ();
211}
212
213parameter_types! {
214	pub const MinimumPeriod: u64 = 5;
215}
216
217impl pallet_timestamp::Config for Runtime {
218	/// A timestamp: milliseconds since the unix epoch.
219	type Moment = u64;
220	type OnTimestampSet = ();
221	type MinimumPeriod = MinimumPeriod;
222	type WeightInfo = ();
223}
224
225parameter_types! {
226	pub const MaxLocks: u32 = 50;
227	pub const MaxReserves: u32 = 50;
228}
229
230impl pallet_balances::Config for Runtime {
231	type MaxLocks = MaxLocks;
232	type MaxReserves = MaxReserves;
233	type ReserveIdentifier = [u8; 8];
234	/// The type for recording an account's balance.
235	type Balance = Balance;
236	/// The ubiquitous event type.
237	type RuntimeEvent = RuntimeEvent;
238	type DustRemoval = ();
239	type ExistentialDeposit = ConstU128<EXISTENTIAL_DEPOSIT>;
240	type AccountStore = System;
241	type WeightInfo = pallet_balances::weights::SubstrateWeight<Runtime>;
242	type FreezeIdentifier = ();
243	type MaxFreezes = ();
244	type RuntimeHoldReason = RuntimeHoldReason;
245	type RuntimeFreezeReason = RuntimeFreezeReason;
246}
247
248impl pallet_transaction_payment::Config for Runtime {
249	type RuntimeEvent = RuntimeEvent;
250	type OnChargeTransaction = CurrencyAdapter<Balances, ()>;
251	type OperationalFeeMultiplier = ConstU8<5>;
252	type WeightToFee = IdentityFee<Balance>;
253	type LengthToFee = IdentityFee<Balance>;
254	type FeeMultiplierUpdate = SlowAdjustingFeeUpdate<Self>;
255}
256
257impl pallet_sudo::Config for Runtime {
258	type RuntimeEvent = RuntimeEvent;
259	type RuntimeCall = RuntimeCall;
260	type WeightInfo = pallet_sudo::weights::SubstrateWeight<Runtime>;
261}
262
263impl pallet_utility::Config for Runtime {
264	type RuntimeEvent = RuntimeEvent;
265	type RuntimeCall = RuntimeCall;
266	type PalletsOrigin = OriginCaller;
267	type WeightInfo = pallet_utility::weights::SubstrateWeight<Runtime>;
268}
269
270// Create the runtime by composing the FRAME pallets that were previously configured.
271construct_runtime!(
272	pub struct Runtime {
273		System: frame_system,
274		RandomnessCollectiveFlip: pallet_insecure_randomness_collective_flip,
275		Utility: pallet_utility,
276		Timestamp: pallet_timestamp,
277		Balances: pallet_balances,
278		Authorship: pallet_authorship,
279		TransactionPayment: pallet_transaction_payment,
280		Sudo: pallet_sudo,
281		Contracts: pallet_contracts,
282		Assets: pallet_assets,
283		OrdinalsModule: pallet_ordinals,
284	}
285);
286
287/// The address format for describing accounts.
288pub type Address = sp_runtime::MultiAddress<AccountId, ()>;
289/// Block header type as expected by this runtime.
290pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
291/// Block type as expected by this runtime.
292pub type Block = generic::Block<Header, UncheckedExtrinsic>;
293/// The SignedExtension to the basic transaction logic.
294pub type SignedExtra = (
295	frame_system::CheckNonZeroSender<Runtime>,
296	frame_system::CheckSpecVersion<Runtime>,
297	frame_system::CheckTxVersion<Runtime>,
298	frame_system::CheckGenesis<Runtime>,
299	frame_system::CheckEra<Runtime>,
300	frame_system::CheckNonce<Runtime>,
301	frame_system::CheckWeight<Runtime>,
302	pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
303);
304/// The payload being signed in transactions.
305pub type SignedPayload = generic::SignedPayload<RuntimeCall, SignedExtra>;
306/// Unchecked extrinsic type as expected by this runtime.
307pub type UncheckedExtrinsic =
308	generic::UncheckedExtrinsic<Address, RuntimeCall, Signature, SignedExtra>;
309/// Executive: handles dispatch to the various modules.
310pub type Executive = frame_executive::Executive<
311	Runtime,
312	Block,
313	frame_system::ChainContext<Runtime>,
314	Runtime,
315	AllPalletsWithSystem,
316	pallet_contracts::Migration<Runtime>,
317>;
318
319type EventRecord = frame_system::EventRecord<
320	<Runtime as frame_system::Config>::RuntimeEvent,
321	<Runtime as frame_system::Config>::Hash,
322>;
323
324impl_runtime_apis! {
325	impl sp_api::Core<Block> for Runtime {
326		fn version() -> RuntimeVersion {
327			VERSION
328		}
329
330		fn execute_block(block: Block) {
331			Executive::execute_block(block);
332		}
333
334		fn initialize_block(header: &<Block as BlockT>::Header) -> sp_runtime::ExtrinsicInclusionMode {
335			Executive::initialize_block(header)
336		}
337	}
338
339	impl sp_api::Metadata<Block> for Runtime {
340		fn metadata() -> OpaqueMetadata {
341			OpaqueMetadata::new(Runtime::metadata().into())
342		}
343		fn metadata_at_version(version: u32) -> Option<OpaqueMetadata> {
344			Runtime::metadata_at_version(version)
345		}
346
347		fn metadata_versions() -> sp_std::vec::Vec<u32> {
348			Runtime::metadata_versions()
349		}
350	}
351
352	impl sp_block_builder::BlockBuilder<Block> for Runtime {
353		fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {
354			Executive::apply_extrinsic(extrinsic)
355		}
356
357		fn finalize_block() -> <Block as BlockT>::Header {
358			Executive::finalize_block()
359		}
360
361		fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
362			data.create_extrinsics()
363		}
364
365		fn check_inherents(
366			block: Block,
367			data: sp_inherents::InherentData,
368		) -> sp_inherents::CheckInherentsResult {
369			data.check_extrinsics(&block)
370		}
371	}
372
373	impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
374		fn validate_transaction(
375			source: TransactionSource,
376			tx: <Block as BlockT>::Extrinsic,
377			block_hash: <Block as BlockT>::Hash,
378		) -> TransactionValidity {
379			Executive::validate_transaction(source, tx, block_hash)
380		}
381	}
382
383	impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
384		fn offchain_worker(header: &<Block as BlockT>::Header) {
385			Executive::offchain_worker(header)
386		}
387	}
388
389	impl sp_session::SessionKeys<Block> for Runtime {
390		fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
391			opaque::SessionKeys::generate(seed)
392		}
393
394		fn decode_session_keys(
395			encoded: Vec<u8>,
396		) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {
397			opaque::SessionKeys::decode_into_raw_public_keys(&encoded)
398		}
399	}
400
401	impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Nonce> for Runtime {
402		fn account_nonce(account: AccountId) -> Nonce {
403			System::account_nonce(account)
404		}
405	}
406
407	impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {
408		fn query_info(
409			uxt: <Block as BlockT>::Extrinsic,
410			len: u32,
411		) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo<Balance> {
412			TransactionPayment::query_info(uxt, len)
413		}
414		fn query_fee_details(
415			uxt: <Block as BlockT>::Extrinsic,
416			len: u32,
417		) -> pallet_transaction_payment::FeeDetails<Balance> {
418			TransactionPayment::query_fee_details(uxt, len)
419		}
420		fn query_weight_to_fee(weight: Weight) -> Balance {
421			TransactionPayment::weight_to_fee(weight)
422		}
423		fn query_length_to_fee(length: u32) -> Balance {
424			TransactionPayment::length_to_fee(length)
425		}
426	}
427
428	impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentCallApi<Block, Balance, RuntimeCall> for Runtime {
429		fn query_call_info(
430			call: RuntimeCall,
431			len: u32,
432		) -> pallet_transaction_payment::RuntimeDispatchInfo<Balance> {
433			TransactionPayment::query_call_info(call, len)
434		}
435		fn query_call_fee_details(
436			call: RuntimeCall,
437			len: u32,
438		) -> pallet_transaction_payment::FeeDetails<Balance> {
439			TransactionPayment::query_call_fee_details(call, len)
440		}
441		fn query_weight_to_fee(weight: Weight) -> Balance {
442			TransactionPayment::weight_to_fee(weight)
443		}
444		fn query_length_to_fee(length: u32) -> Balance {
445			TransactionPayment::length_to_fee(length)
446		}
447	}
448
449	impl pallet_contracts::ContractsApi<Block, AccountId, Balance, BlockNumber, Hash, EventRecord>
450		for Runtime
451	{
452		fn call(
453			origin: AccountId,
454			dest: AccountId,
455			value: Balance,
456			gas_limit: Option<Weight>,
457			storage_deposit_limit: Option<Balance>,
458			input_data: Vec<u8>,
459		) -> pallet_contracts::ContractExecResult<Balance, EventRecord> {
460			let gas_limit = gas_limit.unwrap_or(RuntimeBlockWeights::get().max_block);
461			Contracts::bare_call(
462				origin,
463				dest,
464				value,
465				gas_limit,
466				storage_deposit_limit,
467				input_data,
468				CONTRACTS_DEBUG_OUTPUT,
469				CONTRACTS_EVENTS,
470				pallet_contracts::Determinism::Enforced,
471			)
472		}
473
474		fn instantiate(
475			origin: AccountId,
476			value: Balance,
477			gas_limit: Option<Weight>,
478			storage_deposit_limit: Option<Balance>,
479			code: pallet_contracts::Code<Hash>,
480			data: Vec<u8>,
481			salt: Vec<u8>,
482		) -> pallet_contracts::ContractInstantiateResult<AccountId, Balance, EventRecord>
483		{
484			let gas_limit = gas_limit.unwrap_or(RuntimeBlockWeights::get().max_block);
485			Contracts::bare_instantiate(
486				origin,
487				value,
488				gas_limit,
489				storage_deposit_limit,
490				code,
491				data,
492				salt,
493				CONTRACTS_DEBUG_OUTPUT,
494				CONTRACTS_EVENTS,
495			)
496		}
497
498		fn upload_code(
499			origin: AccountId,
500			code: Vec<u8>,
501			storage_deposit_limit: Option<Balance>,
502			determinism: pallet_contracts::Determinism,
503		) -> pallet_contracts::CodeUploadResult<Hash, Balance>
504		{
505			Contracts::bare_upload_code(origin, code, storage_deposit_limit, determinism)
506		}
507
508		fn get_storage(
509			address: AccountId,
510			key: Vec<u8>,
511		) -> pallet_contracts::GetStorageResult {
512			Contracts::get_storage(address, key)
513		}
514	}
515
516
517	impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
518		fn create_default_config() -> Vec<u8> {
519			create_default_config::<RuntimeGenesisConfig>()
520		}
521
522		fn build_config(config: Vec<u8>) -> sp_genesis_builder::Result {
523			build_config::<RuntimeGenesisConfig>(config)
524		}
525	}
526}