Skip to main content

pallet_statement/
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//! Supporting pallet for the statement store.
19//!
20//! - [`Pallet`]
21//!
22//! ## Overview
23//!
24//! The Statement pallet provides means to create statements for the statement store.
25//!
26//! This pallet contains an offchain worker that turns on-chain statement events into
27//! statements. These statements are placed in the store and propagated over the network.
28
29#![cfg_attr(not(feature = "std"), no_std)]
30
31use frame_support::{pallet_prelude::*, traits::fungible::Inspect};
32use frame_system::pallet_prelude::*;
33use sp_statement_store::{Proof, Statement};
34
35pub use pallet::*;
36
37const LOG_TARGET: &str = "runtime::statement";
38
39#[frame_support::pallet]
40pub mod pallet {
41	use super::*;
42
43	pub type BalanceOf<T> =
44		<<T as Config>::Currency as Inspect<<T as frame_system::Config>::AccountId>>::Balance;
45
46	pub type AccountIdOf<T> = <T as frame_system::Config>::AccountId;
47
48	#[pallet::config]
49	pub trait Config: frame_system::Config
50	where
51		<Self as frame_system::Config>::AccountId: From<sp_statement_store::AccountId>,
52	{
53		/// The overarching event type.
54		#[allow(deprecated)]
55		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
56		/// The currency which is used to calculate account limits.
57		type Currency: Inspect<Self::AccountId>;
58		/// Min balance for priority statements.
59		#[pallet::constant]
60		type StatementCost: Get<BalanceOf<Self>>;
61		/// Cost of data byte used for priority calculation.
62		#[pallet::constant]
63		type ByteCost: Get<BalanceOf<Self>>;
64		/// Minimum number of statements allowed per account.
65		#[pallet::constant]
66		type MinAllowedStatements: Get<u32>;
67		/// Maximum number of statements allowed per account.
68		#[pallet::constant]
69		type MaxAllowedStatements: Get<u32>;
70		/// Minimum data bytes allowed per account.
71		#[pallet::constant]
72		type MinAllowedBytes: Get<u32>;
73		/// Maximum data bytes allowed per account.
74		#[pallet::constant]
75		type MaxAllowedBytes: Get<u32>;
76	}
77
78	#[pallet::pallet]
79	pub struct Pallet<T>(core::marker::PhantomData<T>);
80
81	#[pallet::event]
82	#[pallet::generate_deposit(pub(super) fn deposit_event)]
83	pub enum Event<T: Config>
84	where
85		<T as frame_system::Config>::AccountId: From<sp_statement_store::AccountId>,
86	{
87		/// A new statement is submitted
88		NewStatement { account: T::AccountId, statement: Statement },
89	}
90
91	#[pallet::hooks]
92	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T>
93	where
94		<T as frame_system::Config>::AccountId: From<sp_statement_store::AccountId>,
95		sp_statement_store::AccountId: From<<T as frame_system::Config>::AccountId>,
96		<T as frame_system::Config>::RuntimeEvent: From<pallet::Event<T>>,
97		<T as frame_system::Config>::RuntimeEvent: TryInto<pallet::Event<T>>,
98		sp_statement_store::BlockHash: From<<T as frame_system::Config>::Hash>,
99	{
100		fn offchain_worker(now: BlockNumberFor<T>) {
101			log::trace!(target: LOG_TARGET, "Collecting statements at #{:?}", now);
102			Pallet::<T>::collect_statements();
103		}
104	}
105}
106
107impl<T: Config> Pallet<T>
108where
109	<T as frame_system::Config>::AccountId: From<sp_statement_store::AccountId>,
110	sp_statement_store::AccountId: From<<T as frame_system::Config>::AccountId>,
111	<T as frame_system::Config>::RuntimeEvent: From<pallet::Event<T>>,
112	<T as frame_system::Config>::RuntimeEvent: TryInto<pallet::Event<T>>,
113	sp_statement_store::BlockHash: From<<T as frame_system::Config>::Hash>,
114{
115	/// Submit a statement event. The statement will be picked up by the offchain worker and
116	/// broadcast to the network.
117	pub fn submit_statement(account: T::AccountId, statement: Statement) {
118		Self::deposit_event(Event::NewStatement { account, statement });
119	}
120
121	fn collect_statements() {
122		// Find `NewStatement` events and submit them to the store
123		for (index, event) in frame_system::Pallet::<T>::read_events_no_consensus().enumerate() {
124			if let Ok(Event::<T>::NewStatement { account, mut statement }) = event.event.try_into()
125			{
126				if statement.proof().is_none() {
127					let proof = Proof::OnChain {
128						who: account.into(),
129						block_hash: frame_system::Pallet::<T>::parent_hash().into(),
130						event_index: index as u64,
131					};
132					statement.set_proof(proof);
133				}
134				sp_statement_store::runtime_api::statement_store::submit_statement(statement);
135			}
136		}
137	}
138}