substrate_test_runtime/
substrate_test_pallet.rs1use alloc::{vec, vec::Vec};
25use frame_support::{pallet_prelude::*, storage};
26use sp_core::sr25519::Public;
27use sp_runtime::{
28 traits::Hash,
29 transaction_validity::{
30 InvalidTransaction, TransactionSource, TransactionValidity, ValidTransaction,
31 },
32};
33
34pub use self::pallet::*;
35
36const LOG_TARGET: &str = "substrate_test_pallet";
37
38#[frame_support::pallet(dev_mode)]
39pub mod pallet {
40 use super::*;
41 use crate::TransferData;
42 use frame_system::pallet_prelude::*;
43 use sp_core::storage::well_known_keys;
44 use sp_runtime::{traits::BlakeTwo256, transaction_validity::TransactionPriority, Perbill};
45
46 #[pallet::pallet]
47 #[pallet::without_storage_info]
48 pub struct Pallet<T>(_);
49
50 #[pallet::config]
51 pub trait Config: frame_system::Config {}
52
53 #[pallet::storage]
54 #[pallet::getter(fn authorities)]
55 pub type Authorities<T> = StorageValue<_, Vec<Public>, ValueQuery>;
56
57 #[pallet::genesis_config]
58 #[derive(frame_support::DefaultNoBound)]
59 pub struct GenesisConfig<T: Config> {
60 pub authorities: Vec<Public>,
61 #[serde(skip)]
62 pub _config: core::marker::PhantomData<T>,
63 }
64
65 #[pallet::genesis_build]
66 impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
67 fn build(&self) {
68 <Authorities<T>>::put(self.authorities.clone());
69 }
70 }
71
72 #[pallet::call]
73 impl<T: Config> Pallet<T> {
74 #[pallet::call_index(0)]
76 #[pallet::weight(100)]
77 pub fn bench_call(_origin: OriginFor<T>, _transfer: TransferData) -> DispatchResult {
78 Ok(())
79 }
80
81 #[pallet::call_index(1)]
83 #[pallet::weight(100)]
84 pub fn include_data(origin: OriginFor<T>, _data: Vec<u8>) -> DispatchResult {
85 frame_system::ensure_signed(origin)?;
86 Ok(())
87 }
88
89 #[pallet::call_index(2)]
91 #[pallet::weight(100)]
92 pub fn storage_change(
93 _origin: OriginFor<T>,
94 key: Vec<u8>,
95 value: Option<Vec<u8>>,
96 ) -> DispatchResult {
97 match value {
98 Some(value) => storage::unhashed::put_raw(&key, &value),
99 None => storage::unhashed::kill(&key),
100 }
101 Ok(())
102 }
103
104 #[pallet::call_index(3)]
106 #[pallet::weight(100)]
107 pub fn offchain_index_set(
108 origin: OriginFor<T>,
109 key: Vec<u8>,
110 value: Vec<u8>,
111 ) -> DispatchResult {
112 frame_system::ensure_signed(origin)?;
113 sp_io::offchain_index::set(&key, &value);
114 Ok(())
115 }
116
117 #[pallet::call_index(4)]
119 #[pallet::weight(100)]
120 pub fn offchain_index_clear(origin: OriginFor<T>, key: Vec<u8>) -> DispatchResult {
121 frame_system::ensure_signed(origin)?;
122 sp_io::offchain_index::clear(&key);
123 Ok(())
124 }
125
126 #[pallet::call_index(5)]
128 #[pallet::weight(100)]
129 pub fn indexed_call(origin: OriginFor<T>, data: Vec<u8>) -> DispatchResult {
130 frame_system::ensure_signed(origin)?;
131 let content_hash = sp_io::hashing::blake2_256(&data);
132 let extrinsic_index: u32 =
133 storage::unhashed::get(well_known_keys::EXTRINSIC_INDEX).unwrap();
134 sp_io::transaction_index::index(extrinsic_index, data.len() as u32, content_hash);
135 Ok(())
136 }
137
138 #[pallet::call_index(6)]
141 #[pallet::weight(100)]
142 pub fn deposit_log_digest_item(
143 _origin: OriginFor<T>,
144 log: sp_runtime::generic::DigestItem,
145 ) -> DispatchResult {
146 <frame_system::Pallet<T>>::deposit_log(log);
147 Ok(())
148 }
149
150 #[pallet::call_index(7)]
152 #[pallet::weight(100)]
153 pub fn call_with_priority(
154 _origin: OriginFor<T>,
155 _priority: TransactionPriority,
156 ) -> DispatchResult {
157 Ok(())
158 }
159
160 #[pallet::call_index(8)]
162 #[pallet::weight(100)]
163 pub fn call_do_not_propagate(_origin: OriginFor<T>) -> DispatchResult {
164 Ok(())
165 }
166
167 #[pallet::call_index(9)]
169 #[pallet::weight(*_ratio * T::BlockWeights::get().max_block)]
170 pub fn fill_block(origin: OriginFor<T>, _ratio: Perbill) -> DispatchResult {
171 ensure_signed(origin)?;
172 Ok(())
173 }
174
175 #[pallet::call_index(10)]
179 #[pallet::weight(100)]
180 pub fn read(_origin: OriginFor<T>, count: u32) -> DispatchResult {
181 Self::execute_read(count, false)
182 }
183
184 #[pallet::call_index(11)]
188 #[pallet::weight(100)]
189 pub fn read_and_panic(_origin: OriginFor<T>, count: u32) -> DispatchResult {
190 Self::execute_read(count, true)
191 }
192 }
193
194 impl<T: Config> Pallet<T> {
195 fn execute_read(read: u32, panic_at_end: bool) -> DispatchResult {
196 let mut next_key = vec![];
197 for _ in 0..(read as usize) {
198 if let Some(next) = sp_io::storage::next_key(&next_key) {
199 sp_io::storage::get(&next);
201
202 next_key = next;
203 } else {
204 if panic_at_end {
205 return Ok(())
206 } else {
207 panic!("Could not read {read} times from the state");
208 }
209 }
210 }
211
212 if panic_at_end {
213 panic!("BYE")
214 } else {
215 Ok(())
216 }
217 }
218 }
219
220 #[pallet::validate_unsigned]
221 impl<T: Config> ValidateUnsigned for Pallet<T> {
222 type Call = Call<T>;
223
224 fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity {
225 log::trace!(target: LOG_TARGET, "validate_unsigned {call:?}");
226 match call {
227 Call::deposit_log_digest_item { .. } |
231 Call::storage_change { .. } |
232 Call::read { .. } |
233 Call::read_and_panic { .. } => Ok(ValidTransaction {
234 provides: vec![BlakeTwo256::hash_of(&call).encode()],
235 ..Default::default()
236 }),
237 _ => Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
238 }
239 }
240 }
241}
242
243pub fn validate_runtime_call<T: pallet::Config>(call: &pallet::Call<T>) -> TransactionValidity {
244 log::trace!(target: LOG_TARGET, "validate_runtime_call {call:?}");
245 match call {
246 Call::call_do_not_propagate {} =>
247 Ok(ValidTransaction { propagate: false, ..Default::default() }),
248 Call::call_with_priority { priority } =>
249 Ok(ValidTransaction { priority: *priority, ..Default::default() }),
250 _ => Ok(Default::default()),
251 }
252}