1#![warn(missing_docs)]
77#![cfg_attr(not(feature = "std"), no_std)]
78#![cfg_attr(enable_alloc_error_handler, feature(alloc_error_handler))]
79
80extern crate alloc;
81
82use alloc::vec::Vec;
83
84#[cfg(not(substrate_runtime))]
85use tracing;
86
87#[cfg(not(substrate_runtime))]
88use sp_core::{
89 crypto::Pair,
90 hexdisplay::HexDisplay,
91 offchain::{OffchainDbExt, OffchainWorkerExt, TransactionPoolExt},
92 storage::ChildInfo,
93};
94#[cfg(not(substrate_runtime))]
95use sp_keystore::KeystoreExt;
96
97#[cfg(feature = "bandersnatch-experimental")]
98use sp_core::bandersnatch;
99use sp_core::{
100 crypto::KeyTypeId,
101 ecdsa, ed25519,
102 offchain::{
103 HttpError, HttpRequestId, HttpRequestStatus, OpaqueNetworkState, StorageKind, Timestamp,
104 },
105 sr25519,
106 storage::StateVersion,
107 LogLevelFilter, OpaquePeerId, RuntimeInterfaceLogLevel, H256,
108};
109
110#[cfg(feature = "bls-experimental")]
111use sp_core::{bls381, ecdsa_bls381};
112
113#[cfg(not(substrate_runtime))]
114use sp_trie::{LayoutV0, LayoutV1, TrieConfiguration};
115
116use sp_runtime_interface::{
117 pass_by::{
118 AllocateAndReturnByCodec, AllocateAndReturnFatPointer, AllocateAndReturnPointer, PassAs,
119 PassFatPointerAndDecode, PassFatPointerAndDecodeSlice, PassFatPointerAndRead,
120 PassFatPointerAndReadWrite, PassPointerAndRead, PassPointerAndReadCopy, ReturnAs,
121 },
122 runtime_interface, Pointer,
123};
124
125use codec::{Decode, Encode};
126
127#[cfg(not(substrate_runtime))]
128use secp256k1::{
129 ecdsa::{RecoverableSignature, RecoveryId},
130 Message,
131};
132
133#[cfg(not(substrate_runtime))]
134use sp_externalities::{Externalities, ExternalitiesExt};
135
136pub use sp_externalities::MultiRemovalResults;
137
138#[cfg(all(not(feature = "disable_allocator"), substrate_runtime))]
139mod global_alloc;
140
141#[cfg(not(substrate_runtime))]
142const LOG_TARGET: &str = "runtime::io";
143
144#[derive(Encode, Decode)]
146pub enum EcdsaVerifyError {
147 BadRS,
149 BadV,
151 BadSignature,
153}
154
155#[derive(Encode, Decode)]
158pub enum KillStorageResult {
159 AllRemoved(u32),
162 SomeRemaining(u32),
165}
166
167impl From<MultiRemovalResults> for KillStorageResult {
168 fn from(r: MultiRemovalResults) -> Self {
169 match r.maybe_cursor {
173 None => Self::AllRemoved(r.loops),
174 Some(..) => Self::SomeRemaining(r.loops),
175 }
176 }
177}
178
179#[runtime_interface]
181pub trait Storage {
182 fn get(
184 &mut self,
185 key: PassFatPointerAndRead<&[u8]>,
186 ) -> AllocateAndReturnByCodec<Option<bytes::Bytes>> {
187 self.storage(key).map(|s| bytes::Bytes::from(s.to_vec()))
188 }
189
190 fn read(
196 &mut self,
197 key: PassFatPointerAndRead<&[u8]>,
198 value_out: PassFatPointerAndReadWrite<&mut [u8]>,
199 value_offset: u32,
200 ) -> AllocateAndReturnByCodec<Option<u32>> {
201 self.storage(key).map(|value| {
202 let value_offset = value_offset as usize;
203 let data = &value[value_offset.min(value.len())..];
204 let written = core::cmp::min(data.len(), value_out.len());
205 value_out[..written].copy_from_slice(&data[..written]);
206 data.len() as u32
207 })
208 }
209
210 fn set(&mut self, key: PassFatPointerAndRead<&[u8]>, value: PassFatPointerAndRead<&[u8]>) {
212 self.set_storage(key.to_vec(), value.to_vec());
213 }
214
215 fn clear(&mut self, key: PassFatPointerAndRead<&[u8]>) {
217 self.clear_storage(key)
218 }
219
220 fn exists(&mut self, key: PassFatPointerAndRead<&[u8]>) -> bool {
222 self.exists_storage(key)
223 }
224
225 fn clear_prefix(&mut self, prefix: PassFatPointerAndRead<&[u8]>) {
227 let _ = Externalities::clear_prefix(*self, prefix, None, None);
228 }
229
230 #[version(2)]
256 fn clear_prefix(
257 &mut self,
258 prefix: PassFatPointerAndRead<&[u8]>,
259 limit: PassFatPointerAndDecode<Option<u32>>,
260 ) -> AllocateAndReturnByCodec<KillStorageResult> {
261 Externalities::clear_prefix(*self, prefix, limit, None).into()
262 }
263
264 #[version(3, register_only)]
296 fn clear_prefix(
297 &mut self,
298 maybe_prefix: PassFatPointerAndRead<&[u8]>,
299 maybe_limit: PassFatPointerAndDecode<Option<u32>>,
300 maybe_cursor: PassFatPointerAndDecode<Option<Vec<u8>>>, ) -> AllocateAndReturnByCodec<MultiRemovalResults> {
303 Externalities::clear_prefix(
304 *self,
305 maybe_prefix,
306 maybe_limit,
307 maybe_cursor.as_ref().map(|x| &x[..]),
308 )
309 .into()
310 }
311
312 fn append(&mut self, key: PassFatPointerAndRead<&[u8]>, value: PassFatPointerAndRead<Vec<u8>>) {
321 self.storage_append(key.to_vec(), value);
322 }
323
324 fn root(&mut self) -> AllocateAndReturnFatPointer<Vec<u8>> {
330 self.storage_root(StateVersion::V0)
331 }
332
333 #[version(2)]
339 fn root(&mut self, version: PassAs<StateVersion, u8>) -> AllocateAndReturnFatPointer<Vec<u8>> {
340 self.storage_root(version)
341 }
342
343 fn changes_root(
345 &mut self,
346 _parent_hash: PassFatPointerAndRead<&[u8]>,
347 ) -> AllocateAndReturnByCodec<Option<Vec<u8>>> {
348 None
349 }
350
351 fn next_key(
353 &mut self,
354 key: PassFatPointerAndRead<&[u8]>,
355 ) -> AllocateAndReturnByCodec<Option<Vec<u8>>> {
356 self.next_storage_key(key)
357 }
358
359 fn start_transaction(&mut self) {
372 self.storage_start_transaction();
373 }
374
375 fn rollback_transaction(&mut self) {
383 self.storage_rollback_transaction()
384 .expect("No open transaction that can be rolled back.");
385 }
386
387 fn commit_transaction(&mut self) {
395 self.storage_commit_transaction()
396 .expect("No open transaction that can be committed.");
397 }
398}
399
400#[runtime_interface]
403pub trait DefaultChildStorage {
404 fn get(
409 &mut self,
410 storage_key: PassFatPointerAndRead<&[u8]>,
411 key: PassFatPointerAndRead<&[u8]>,
412 ) -> AllocateAndReturnByCodec<Option<Vec<u8>>> {
413 let child_info = ChildInfo::new_default(storage_key);
414 self.child_storage(&child_info, key).map(|s| s.to_vec())
415 }
416
417 fn read(
425 &mut self,
426 storage_key: PassFatPointerAndRead<&[u8]>,
427 key: PassFatPointerAndRead<&[u8]>,
428 value_out: PassFatPointerAndReadWrite<&mut [u8]>,
429 value_offset: u32,
430 ) -> AllocateAndReturnByCodec<Option<u32>> {
431 let child_info = ChildInfo::new_default(storage_key);
432 self.child_storage(&child_info, key).map(|value| {
433 let value_offset = value_offset as usize;
434 let data = &value[value_offset.min(value.len())..];
435 let written = core::cmp::min(data.len(), value_out.len());
436 value_out[..written].copy_from_slice(&data[..written]);
437 data.len() as u32
438 })
439 }
440
441 fn set(
445 &mut self,
446 storage_key: PassFatPointerAndRead<&[u8]>,
447 key: PassFatPointerAndRead<&[u8]>,
448 value: PassFatPointerAndRead<&[u8]>,
449 ) {
450 let child_info = ChildInfo::new_default(storage_key);
451 self.set_child_storage(&child_info, key.to_vec(), value.to_vec());
452 }
453
454 fn clear(
458 &mut self,
459 storage_key: PassFatPointerAndRead<&[u8]>,
460 key: PassFatPointerAndRead<&[u8]>,
461 ) {
462 let child_info = ChildInfo::new_default(storage_key);
463 self.clear_child_storage(&child_info, key);
464 }
465
466 fn storage_kill(&mut self, storage_key: PassFatPointerAndRead<&[u8]>) {
471 let child_info = ChildInfo::new_default(storage_key);
472 let _ = self.kill_child_storage(&child_info, None, None);
473 }
474
475 #[version(2)]
479 fn storage_kill(
480 &mut self,
481 storage_key: PassFatPointerAndRead<&[u8]>,
482 limit: PassFatPointerAndDecode<Option<u32>>,
483 ) -> bool {
484 let child_info = ChildInfo::new_default(storage_key);
485 let r = self.kill_child_storage(&child_info, limit, None);
486 r.maybe_cursor.is_none()
487 }
488
489 #[version(3)]
493 fn storage_kill(
494 &mut self,
495 storage_key: PassFatPointerAndRead<&[u8]>,
496 limit: PassFatPointerAndDecode<Option<u32>>,
497 ) -> AllocateAndReturnByCodec<KillStorageResult> {
498 let child_info = ChildInfo::new_default(storage_key);
499 self.kill_child_storage(&child_info, limit, None).into()
500 }
501
502 #[version(4, register_only)]
506 fn storage_kill(
507 &mut self,
508 storage_key: PassFatPointerAndRead<&[u8]>,
509 maybe_limit: PassFatPointerAndDecode<Option<u32>>,
510 maybe_cursor: PassFatPointerAndDecode<Option<Vec<u8>>>,
511 ) -> AllocateAndReturnByCodec<MultiRemovalResults> {
512 let child_info = ChildInfo::new_default(storage_key);
513 self.kill_child_storage(&child_info, maybe_limit, maybe_cursor.as_ref().map(|x| &x[..]))
514 .into()
515 }
516
517 fn exists(
521 &mut self,
522 storage_key: PassFatPointerAndRead<&[u8]>,
523 key: PassFatPointerAndRead<&[u8]>,
524 ) -> bool {
525 let child_info = ChildInfo::new_default(storage_key);
526 self.exists_child_storage(&child_info, key)
527 }
528
529 fn clear_prefix(
533 &mut self,
534 storage_key: PassFatPointerAndRead<&[u8]>,
535 prefix: PassFatPointerAndRead<&[u8]>,
536 ) {
537 let child_info = ChildInfo::new_default(storage_key);
538 let _ = self.clear_child_prefix(&child_info, prefix, None, None);
539 }
540
541 #[version(2)]
545 fn clear_prefix(
546 &mut self,
547 storage_key: PassFatPointerAndRead<&[u8]>,
548 prefix: PassFatPointerAndRead<&[u8]>,
549 limit: PassFatPointerAndDecode<Option<u32>>,
550 ) -> AllocateAndReturnByCodec<KillStorageResult> {
551 let child_info = ChildInfo::new_default(storage_key);
552 self.clear_child_prefix(&child_info, prefix, limit, None).into()
553 }
554
555 #[version(3, register_only)]
559 fn clear_prefix(
560 &mut self,
561 storage_key: PassFatPointerAndRead<&[u8]>,
562 prefix: PassFatPointerAndRead<&[u8]>,
563 maybe_limit: PassFatPointerAndDecode<Option<u32>>,
564 maybe_cursor: PassFatPointerAndDecode<Option<Vec<u8>>>,
565 ) -> AllocateAndReturnByCodec<MultiRemovalResults> {
566 let child_info = ChildInfo::new_default(storage_key);
567 self.clear_child_prefix(
568 &child_info,
569 prefix,
570 maybe_limit,
571 maybe_cursor.as_ref().map(|x| &x[..]),
572 )
573 .into()
574 }
575
576 fn root(
583 &mut self,
584 storage_key: PassFatPointerAndRead<&[u8]>,
585 ) -> AllocateAndReturnFatPointer<Vec<u8>> {
586 let child_info = ChildInfo::new_default(storage_key);
587 self.child_storage_root(&child_info, StateVersion::V0)
588 }
589
590 #[version(2)]
597 fn root(
598 &mut self,
599 storage_key: PassFatPointerAndRead<&[u8]>,
600 version: PassAs<StateVersion, u8>,
601 ) -> AllocateAndReturnFatPointer<Vec<u8>> {
602 let child_info = ChildInfo::new_default(storage_key);
603 self.child_storage_root(&child_info, version)
604 }
605
606 fn next_key(
610 &mut self,
611 storage_key: PassFatPointerAndRead<&[u8]>,
612 key: PassFatPointerAndRead<&[u8]>,
613 ) -> AllocateAndReturnByCodec<Option<Vec<u8>>> {
614 let child_info = ChildInfo::new_default(storage_key);
615 self.next_child_storage_key(&child_info, key)
616 }
617}
618
619#[runtime_interface]
621pub trait Trie {
622 fn blake2_256_root(
624 input: PassFatPointerAndDecode<Vec<(Vec<u8>, Vec<u8>)>>,
625 ) -> AllocateAndReturnPointer<H256, 32> {
626 LayoutV0::<sp_core::Blake2Hasher>::trie_root(input)
627 }
628
629 #[version(2)]
631 fn blake2_256_root(
632 input: PassFatPointerAndDecode<Vec<(Vec<u8>, Vec<u8>)>>,
633 version: PassAs<StateVersion, u8>,
634 ) -> AllocateAndReturnPointer<H256, 32> {
635 match version {
636 StateVersion::V0 => LayoutV0::<sp_core::Blake2Hasher>::trie_root(input),
637 StateVersion::V1 => LayoutV1::<sp_core::Blake2Hasher>::trie_root(input),
638 }
639 }
640
641 fn blake2_256_ordered_root(
643 input: PassFatPointerAndDecode<Vec<Vec<u8>>>,
644 ) -> AllocateAndReturnPointer<H256, 32> {
645 LayoutV0::<sp_core::Blake2Hasher>::ordered_trie_root(input)
646 }
647
648 #[version(2)]
650 fn blake2_256_ordered_root(
651 input: PassFatPointerAndDecode<Vec<Vec<u8>>>,
652 version: PassAs<StateVersion, u8>,
653 ) -> AllocateAndReturnPointer<H256, 32> {
654 match version {
655 StateVersion::V0 => LayoutV0::<sp_core::Blake2Hasher>::ordered_trie_root(input),
656 StateVersion::V1 => LayoutV1::<sp_core::Blake2Hasher>::ordered_trie_root(input),
657 }
658 }
659
660 fn keccak_256_root(
662 input: PassFatPointerAndDecode<Vec<(Vec<u8>, Vec<u8>)>>,
663 ) -> AllocateAndReturnPointer<H256, 32> {
664 LayoutV0::<sp_core::KeccakHasher>::trie_root(input)
665 }
666
667 #[version(2)]
669 fn keccak_256_root(
670 input: PassFatPointerAndDecode<Vec<(Vec<u8>, Vec<u8>)>>,
671 version: PassAs<StateVersion, u8>,
672 ) -> AllocateAndReturnPointer<H256, 32> {
673 match version {
674 StateVersion::V0 => LayoutV0::<sp_core::KeccakHasher>::trie_root(input),
675 StateVersion::V1 => LayoutV1::<sp_core::KeccakHasher>::trie_root(input),
676 }
677 }
678
679 fn keccak_256_ordered_root(
681 input: PassFatPointerAndDecode<Vec<Vec<u8>>>,
682 ) -> AllocateAndReturnPointer<H256, 32> {
683 LayoutV0::<sp_core::KeccakHasher>::ordered_trie_root(input)
684 }
685
686 #[version(2)]
688 fn keccak_256_ordered_root(
689 input: PassFatPointerAndDecode<Vec<Vec<u8>>>,
690 version: PassAs<StateVersion, u8>,
691 ) -> AllocateAndReturnPointer<H256, 32> {
692 match version {
693 StateVersion::V0 => LayoutV0::<sp_core::KeccakHasher>::ordered_trie_root(input),
694 StateVersion::V1 => LayoutV1::<sp_core::KeccakHasher>::ordered_trie_root(input),
695 }
696 }
697
698 fn blake2_256_verify_proof(
700 root: PassPointerAndReadCopy<H256, 32>,
701 proof: PassFatPointerAndDecodeSlice<&[Vec<u8>]>,
702 key: PassFatPointerAndRead<&[u8]>,
703 value: PassFatPointerAndRead<&[u8]>,
704 ) -> bool {
705 sp_trie::verify_trie_proof::<LayoutV0<sp_core::Blake2Hasher>, _, _, _>(
706 &root,
707 proof,
708 &[(key, Some(value))],
709 )
710 .is_ok()
711 }
712
713 #[version(2)]
715 fn blake2_256_verify_proof(
716 root: PassPointerAndReadCopy<H256, 32>,
717 proof: PassFatPointerAndDecodeSlice<&[Vec<u8>]>,
718 key: PassFatPointerAndRead<&[u8]>,
719 value: PassFatPointerAndRead<&[u8]>,
720 version: PassAs<StateVersion, u8>,
721 ) -> bool {
722 match version {
723 StateVersion::V0 => sp_trie::verify_trie_proof::<
724 LayoutV0<sp_core::Blake2Hasher>,
725 _,
726 _,
727 _,
728 >(&root, proof, &[(key, Some(value))])
729 .is_ok(),
730 StateVersion::V1 => sp_trie::verify_trie_proof::<
731 LayoutV1<sp_core::Blake2Hasher>,
732 _,
733 _,
734 _,
735 >(&root, proof, &[(key, Some(value))])
736 .is_ok(),
737 }
738 }
739
740 fn keccak_256_verify_proof(
742 root: PassPointerAndReadCopy<H256, 32>,
743 proof: PassFatPointerAndDecodeSlice<&[Vec<u8>]>,
744 key: PassFatPointerAndRead<&[u8]>,
745 value: PassFatPointerAndRead<&[u8]>,
746 ) -> bool {
747 sp_trie::verify_trie_proof::<LayoutV0<sp_core::KeccakHasher>, _, _, _>(
748 &root,
749 proof,
750 &[(key, Some(value))],
751 )
752 .is_ok()
753 }
754
755 #[version(2)]
757 fn keccak_256_verify_proof(
758 root: PassPointerAndReadCopy<H256, 32>,
759 proof: PassFatPointerAndDecodeSlice<&[Vec<u8>]>,
760 key: PassFatPointerAndRead<&[u8]>,
761 value: PassFatPointerAndRead<&[u8]>,
762 version: PassAs<StateVersion, u8>,
763 ) -> bool {
764 match version {
765 StateVersion::V0 => sp_trie::verify_trie_proof::<
766 LayoutV0<sp_core::KeccakHasher>,
767 _,
768 _,
769 _,
770 >(&root, proof, &[(key, Some(value))])
771 .is_ok(),
772 StateVersion::V1 => sp_trie::verify_trie_proof::<
773 LayoutV1<sp_core::KeccakHasher>,
774 _,
775 _,
776 _,
777 >(&root, proof, &[(key, Some(value))])
778 .is_ok(),
779 }
780 }
781}
782
783#[runtime_interface]
786pub trait Misc {
787 fn print_num(val: u64) {
792 log::debug!(target: "runtime", "{}", val);
793 }
794
795 fn print_utf8(utf8: PassFatPointerAndRead<&[u8]>) {
797 if let Ok(data) = core::str::from_utf8(utf8) {
798 log::debug!(target: "runtime", "{}", data)
799 }
800 }
801
802 fn print_hex(data: PassFatPointerAndRead<&[u8]>) {
804 log::debug!(target: "runtime", "{}", HexDisplay::from(&data));
805 }
806
807 fn runtime_version(
823 &mut self,
824 wasm: PassFatPointerAndRead<&[u8]>,
825 ) -> AllocateAndReturnByCodec<Option<Vec<u8>>> {
826 use sp_core::traits::ReadRuntimeVersionExt;
827
828 let mut ext = sp_state_machine::BasicExternalities::default();
829
830 match self
831 .extension::<ReadRuntimeVersionExt>()
832 .expect("No `ReadRuntimeVersionExt` associated for the current context!")
833 .read_runtime_version(wasm, &mut ext)
834 {
835 Ok(v) => Some(v),
836 Err(err) => {
837 log::debug!(
838 target: LOG_TARGET,
839 "cannot read version from the given runtime: {}",
840 err,
841 );
842 None
843 },
844 }
845 }
846}
847
848#[cfg(not(substrate_runtime))]
849sp_externalities::decl_extension! {
850 pub struct UseDalekExt;
867}
868
869#[cfg(not(substrate_runtime))]
870impl Default for UseDalekExt {
871 fn default() -> Self {
872 Self
873 }
874}
875
876#[runtime_interface]
878pub trait Crypto {
879 fn ed25519_public_keys(
881 &mut self,
882 id: PassPointerAndReadCopy<KeyTypeId, 4>,
883 ) -> AllocateAndReturnByCodec<Vec<ed25519::Public>> {
884 self.extension::<KeystoreExt>()
885 .expect("No `keystore` associated for the current context!")
886 .ed25519_public_keys(id)
887 }
888
889 fn ed25519_generate(
896 &mut self,
897 id: PassPointerAndReadCopy<KeyTypeId, 4>,
898 seed: PassFatPointerAndDecode<Option<Vec<u8>>>,
899 ) -> AllocateAndReturnPointer<ed25519::Public, 32> {
900 let seed = seed.as_ref().map(|s| core::str::from_utf8(s).expect("Seed is valid utf8!"));
901 self.extension::<KeystoreExt>()
902 .expect("No `keystore` associated for the current context!")
903 .ed25519_generate_new(id, seed)
904 .expect("`ed25519_generate` failed")
905 }
906
907 fn ed25519_sign(
912 &mut self,
913 id: PassPointerAndReadCopy<KeyTypeId, 4>,
914 pub_key: PassPointerAndRead<&ed25519::Public, 32>,
915 msg: PassFatPointerAndRead<&[u8]>,
916 ) -> AllocateAndReturnByCodec<Option<ed25519::Signature>> {
917 self.extension::<KeystoreExt>()
918 .expect("No `keystore` associated for the current context!")
919 .ed25519_sign(id, pub_key, msg)
920 .ok()
921 .flatten()
922 }
923
924 fn ed25519_verify(
928 sig: PassPointerAndRead<&ed25519::Signature, 64>,
929 msg: PassFatPointerAndRead<&[u8]>,
930 pub_key: PassPointerAndRead<&ed25519::Public, 32>,
931 ) -> bool {
932 if sp_externalities::with_externalities(|mut e| e.extension::<UseDalekExt>().is_some())
936 .unwrap_or_default()
937 {
938 use ed25519_dalek::Verifier;
939
940 let Ok(public_key) = ed25519_dalek::VerifyingKey::from_bytes(&pub_key.0) else {
941 return false;
942 };
943
944 let sig = ed25519_dalek::Signature::from_bytes(&sig.0);
945
946 public_key.verify(msg, &sig).is_ok()
947 } else {
948 ed25519::Pair::verify(sig, msg, pub_key)
949 }
950 }
951
952 #[version(1, register_only)]
966 fn ed25519_batch_verify(
967 &mut self,
968 sig: PassPointerAndRead<&ed25519::Signature, 64>,
969 msg: PassFatPointerAndRead<&[u8]>,
970 pub_key: PassPointerAndRead<&ed25519::Public, 32>,
971 ) -> bool {
972 let res = ed25519_verify(sig, msg, pub_key);
973
974 if let Some(ext) = self.extension::<VerificationExtDeprecated>() {
975 ext.0 &= res;
976 }
977
978 res
979 }
980
981 #[version(2)]
985 fn sr25519_verify(
986 sig: PassPointerAndRead<&sr25519::Signature, 64>,
987 msg: PassFatPointerAndRead<&[u8]>,
988 pub_key: PassPointerAndRead<&sr25519::Public, 32>,
989 ) -> bool {
990 sr25519::Pair::verify(sig, msg, pub_key)
991 }
992
993 #[version(1, register_only)]
1007 fn sr25519_batch_verify(
1008 &mut self,
1009 sig: PassPointerAndRead<&sr25519::Signature, 64>,
1010 msg: PassFatPointerAndRead<&[u8]>,
1011 pub_key: PassPointerAndRead<&sr25519::Public, 32>,
1012 ) -> bool {
1013 let res = sr25519_verify(sig, msg, pub_key);
1014
1015 if let Some(ext) = self.extension::<VerificationExtDeprecated>() {
1016 ext.0 &= res;
1017 }
1018
1019 res
1020 }
1021
1022 #[version(1, register_only)]
1029 fn start_batch_verify(&mut self) {
1030 self.register_extension(VerificationExtDeprecated(true))
1031 .expect("Failed to register required extension: `VerificationExt`");
1032 }
1033
1034 #[version(1, register_only)]
1046 fn finish_batch_verify(&mut self) -> bool {
1047 let result = self
1048 .extension::<VerificationExtDeprecated>()
1049 .expect("`finish_batch_verify` should only be called after `start_batch_verify`")
1050 .0;
1051
1052 self.deregister_extension::<VerificationExtDeprecated>()
1053 .expect("No verification extension in current context!");
1054
1055 result
1056 }
1057
1058 fn sr25519_public_keys(
1060 &mut self,
1061 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1062 ) -> AllocateAndReturnByCodec<Vec<sr25519::Public>> {
1063 self.extension::<KeystoreExt>()
1064 .expect("No `keystore` associated for the current context!")
1065 .sr25519_public_keys(id)
1066 }
1067
1068 fn sr25519_generate(
1075 &mut self,
1076 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1077 seed: PassFatPointerAndDecode<Option<Vec<u8>>>,
1078 ) -> AllocateAndReturnPointer<sr25519::Public, 32> {
1079 let seed = seed.as_ref().map(|s| core::str::from_utf8(s).expect("Seed is valid utf8!"));
1080 self.extension::<KeystoreExt>()
1081 .expect("No `keystore` associated for the current context!")
1082 .sr25519_generate_new(id, seed)
1083 .expect("`sr25519_generate` failed")
1084 }
1085
1086 fn sr25519_sign(
1091 &mut self,
1092 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1093 pub_key: PassPointerAndRead<&sr25519::Public, 32>,
1094 msg: PassFatPointerAndRead<&[u8]>,
1095 ) -> AllocateAndReturnByCodec<Option<sr25519::Signature>> {
1096 self.extension::<KeystoreExt>()
1097 .expect("No `keystore` associated for the current context!")
1098 .sr25519_sign(id, pub_key, msg)
1099 .ok()
1100 .flatten()
1101 }
1102
1103 fn sr25519_verify(
1108 sig: PassPointerAndRead<&sr25519::Signature, 64>,
1109 msg: PassFatPointerAndRead<&[u8]>,
1110 pubkey: PassPointerAndRead<&sr25519::Public, 32>,
1111 ) -> bool {
1112 sr25519::Pair::verify_deprecated(sig, msg, pubkey)
1113 }
1114
1115 fn ecdsa_public_keys(
1117 &mut self,
1118 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1119 ) -> AllocateAndReturnByCodec<Vec<ecdsa::Public>> {
1120 self.extension::<KeystoreExt>()
1121 .expect("No `keystore` associated for the current context!")
1122 .ecdsa_public_keys(id)
1123 }
1124
1125 fn ecdsa_generate(
1132 &mut self,
1133 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1134 seed: PassFatPointerAndDecode<Option<Vec<u8>>>,
1135 ) -> AllocateAndReturnPointer<ecdsa::Public, 33> {
1136 let seed = seed.as_ref().map(|s| core::str::from_utf8(s).expect("Seed is valid utf8!"));
1137 self.extension::<KeystoreExt>()
1138 .expect("No `keystore` associated for the current context!")
1139 .ecdsa_generate_new(id, seed)
1140 .expect("`ecdsa_generate` failed")
1141 }
1142
1143 fn ecdsa_sign(
1148 &mut self,
1149 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1150 pub_key: PassPointerAndRead<&ecdsa::Public, 33>,
1151 msg: PassFatPointerAndRead<&[u8]>,
1152 ) -> AllocateAndReturnByCodec<Option<ecdsa::Signature>> {
1153 self.extension::<KeystoreExt>()
1154 .expect("No `keystore` associated for the current context!")
1155 .ecdsa_sign(id, pub_key, msg)
1156 .ok()
1157 .flatten()
1158 }
1159
1160 fn ecdsa_sign_prehashed(
1165 &mut self,
1166 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1167 pub_key: PassPointerAndRead<&ecdsa::Public, 33>,
1168 msg: PassPointerAndRead<&[u8; 32], 32>,
1169 ) -> AllocateAndReturnByCodec<Option<ecdsa::Signature>> {
1170 self.extension::<KeystoreExt>()
1171 .expect("No `keystore` associated for the current context!")
1172 .ecdsa_sign_prehashed(id, pub_key, msg)
1173 .ok()
1174 .flatten()
1175 }
1176
1177 fn ecdsa_verify(
1182 sig: PassPointerAndRead<&ecdsa::Signature, 65>,
1183 msg: PassFatPointerAndRead<&[u8]>,
1184 pub_key: PassPointerAndRead<&ecdsa::Public, 33>,
1185 ) -> bool {
1186 #[allow(deprecated)]
1187 ecdsa::Pair::verify_deprecated(sig, msg, pub_key)
1188 }
1189
1190 #[version(2)]
1194 fn ecdsa_verify(
1195 sig: PassPointerAndRead<&ecdsa::Signature, 65>,
1196 msg: PassFatPointerAndRead<&[u8]>,
1197 pub_key: PassPointerAndRead<&ecdsa::Public, 33>,
1198 ) -> bool {
1199 ecdsa::Pair::verify(sig, msg, pub_key)
1200 }
1201
1202 fn ecdsa_verify_prehashed(
1206 sig: PassPointerAndRead<&ecdsa::Signature, 65>,
1207 msg: PassPointerAndRead<&[u8; 32], 32>,
1208 pub_key: PassPointerAndRead<&ecdsa::Public, 33>,
1209 ) -> bool {
1210 ecdsa::Pair::verify_prehashed(sig, msg, pub_key)
1211 }
1212
1213 #[version(1, register_only)]
1227 fn ecdsa_batch_verify(
1228 &mut self,
1229 sig: PassPointerAndRead<&ecdsa::Signature, 65>,
1230 msg: PassFatPointerAndRead<&[u8]>,
1231 pub_key: PassPointerAndRead<&ecdsa::Public, 33>,
1232 ) -> bool {
1233 let res = ecdsa_verify(sig, msg, pub_key);
1234
1235 if let Some(ext) = self.extension::<VerificationExtDeprecated>() {
1236 ext.0 &= res;
1237 }
1238
1239 res
1240 }
1241
1242 fn secp256k1_ecdsa_recover(
1251 sig: PassPointerAndRead<&[u8; 65], 65>,
1252 msg: PassPointerAndRead<&[u8; 32], 32>,
1253 ) -> AllocateAndReturnByCodec<Result<[u8; 64], EcdsaVerifyError>> {
1254 let rid = libsecp256k1::RecoveryId::parse(
1255 if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8,
1256 )
1257 .map_err(|_| EcdsaVerifyError::BadV)?;
1258 let sig = libsecp256k1::Signature::parse_overflowing_slice(&sig[..64])
1259 .map_err(|_| EcdsaVerifyError::BadRS)?;
1260 let msg = libsecp256k1::Message::parse(msg);
1261 let pubkey =
1262 libsecp256k1::recover(&msg, &sig, &rid).map_err(|_| EcdsaVerifyError::BadSignature)?;
1263 let mut res = [0u8; 64];
1264 res.copy_from_slice(&pubkey.serialize()[1..65]);
1265 Ok(res)
1266 }
1267
1268 #[version(2)]
1276 fn secp256k1_ecdsa_recover(
1277 sig: PassPointerAndRead<&[u8; 65], 65>,
1278 msg: PassPointerAndRead<&[u8; 32], 32>,
1279 ) -> AllocateAndReturnByCodec<Result<[u8; 64], EcdsaVerifyError>> {
1280 let rid = RecoveryId::from_i32(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as i32)
1281 .map_err(|_| EcdsaVerifyError::BadV)?;
1282 let sig = RecoverableSignature::from_compact(&sig[..64], rid)
1283 .map_err(|_| EcdsaVerifyError::BadRS)?;
1284 let msg = Message::from_digest_slice(msg).expect("Message is 32 bytes; qed");
1285 #[cfg(feature = "std")]
1286 let ctx = secp256k1::SECP256K1;
1287 #[cfg(not(feature = "std"))]
1288 let ctx = secp256k1::Secp256k1::<secp256k1::VerifyOnly>::gen_new();
1289 let pubkey = ctx.recover_ecdsa(&msg, &sig).map_err(|_| EcdsaVerifyError::BadSignature)?;
1290 let mut res = [0u8; 64];
1291 res.copy_from_slice(&pubkey.serialize_uncompressed()[1..]);
1292 Ok(res)
1293 }
1294
1295 fn secp256k1_ecdsa_recover_compressed(
1302 sig: PassPointerAndRead<&[u8; 65], 65>,
1303 msg: PassPointerAndRead<&[u8; 32], 32>,
1304 ) -> AllocateAndReturnByCodec<Result<[u8; 33], EcdsaVerifyError>> {
1305 let rid = libsecp256k1::RecoveryId::parse(
1306 if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8,
1307 )
1308 .map_err(|_| EcdsaVerifyError::BadV)?;
1309 let sig = libsecp256k1::Signature::parse_overflowing_slice(&sig[0..64])
1310 .map_err(|_| EcdsaVerifyError::BadRS)?;
1311 let msg = libsecp256k1::Message::parse(msg);
1312 let pubkey =
1313 libsecp256k1::recover(&msg, &sig, &rid).map_err(|_| EcdsaVerifyError::BadSignature)?;
1314 Ok(pubkey.serialize_compressed())
1315 }
1316
1317 #[version(2)]
1324 fn secp256k1_ecdsa_recover_compressed(
1325 sig: PassPointerAndRead<&[u8; 65], 65>,
1326 msg: PassPointerAndRead<&[u8; 32], 32>,
1327 ) -> AllocateAndReturnByCodec<Result<[u8; 33], EcdsaVerifyError>> {
1328 let rid = RecoveryId::from_i32(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as i32)
1329 .map_err(|_| EcdsaVerifyError::BadV)?;
1330 let sig = RecoverableSignature::from_compact(&sig[..64], rid)
1331 .map_err(|_| EcdsaVerifyError::BadRS)?;
1332 let msg = Message::from_digest_slice(msg).expect("Message is 32 bytes; qed");
1333 #[cfg(feature = "std")]
1334 let ctx = secp256k1::SECP256K1;
1335 #[cfg(not(feature = "std"))]
1336 let ctx = secp256k1::Secp256k1::<secp256k1::VerifyOnly>::gen_new();
1337 let pubkey = ctx.recover_ecdsa(&msg, &sig).map_err(|_| EcdsaVerifyError::BadSignature)?;
1338 Ok(pubkey.serialize())
1339 }
1340
1341 #[cfg(feature = "bls-experimental")]
1348 fn bls381_generate(
1349 &mut self,
1350 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1351 seed: PassFatPointerAndDecode<Option<Vec<u8>>>,
1352 ) -> AllocateAndReturnPointer<bls381::Public, 144> {
1353 let seed = seed.as_ref().map(|s| core::str::from_utf8(s).expect("Seed is valid utf8!"));
1354 self.extension::<KeystoreExt>()
1355 .expect("No `keystore` associated for the current context!")
1356 .bls381_generate_new(id, seed)
1357 .expect("`bls381_generate` failed")
1358 }
1359
1360 #[cfg(feature = "bls-experimental")]
1365 fn bls381_generate_proof_of_possession(
1366 &mut self,
1367 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1368 pub_key: PassPointerAndRead<&bls381::Public, 144>,
1369 owner: PassFatPointerAndRead<&[u8]>,
1370 ) -> AllocateAndReturnByCodec<Option<bls381::ProofOfPossession>> {
1371 self.extension::<KeystoreExt>()
1372 .expect("No `keystore` associated for the current context!")
1373 .bls381_generate_proof_of_possession(id, pub_key, owner)
1374 .ok()
1375 .flatten()
1376 }
1377
1378 #[cfg(feature = "bls-experimental")]
1385 fn ecdsa_bls381_generate(
1386 &mut self,
1387 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1388 seed: PassFatPointerAndDecode<Option<Vec<u8>>>,
1389 ) -> AllocateAndReturnPointer<ecdsa_bls381::Public, { 144 + 33 }> {
1390 let seed = seed.as_ref().map(|s| core::str::from_utf8(s).expect("Seed is valid utf8!"));
1391 self.extension::<KeystoreExt>()
1392 .expect("No `keystore` associated for the current context!")
1393 .ecdsa_bls381_generate_new(id, seed)
1394 .expect("`ecdsa_bls381_generate` failed")
1395 }
1396
1397 #[cfg(feature = "bandersnatch-experimental")]
1404 fn bandersnatch_generate(
1405 &mut self,
1406 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1407 seed: PassFatPointerAndDecode<Option<Vec<u8>>>,
1408 ) -> AllocateAndReturnPointer<bandersnatch::Public, 32> {
1409 let seed = seed.as_ref().map(|s| core::str::from_utf8(s).expect("Seed is valid utf8!"));
1410 self.extension::<KeystoreExt>()
1411 .expect("No `keystore` associated for the current context!")
1412 .bandersnatch_generate_new(id, seed)
1413 .expect("`bandernatch_generate` failed")
1414 }
1415
1416 #[cfg(feature = "bandersnatch-experimental")]
1421 fn bandersnatch_sign(
1422 &mut self,
1423 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1424 pub_key: PassPointerAndRead<&bandersnatch::Public, 32>,
1425 msg: PassFatPointerAndRead<&[u8]>,
1426 ) -> AllocateAndReturnByCodec<Option<bandersnatch::Signature>> {
1427 self.extension::<KeystoreExt>()
1428 .expect("No `keystore` associated for the current context!")
1429 .bandersnatch_sign(id, pub_key, msg)
1430 .ok()
1431 .flatten()
1432 }
1433}
1434
1435#[runtime_interface]
1437pub trait Hashing {
1438 fn keccak_256(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnPointer<[u8; 32], 32> {
1440 sp_crypto_hashing::keccak_256(data)
1441 }
1442
1443 fn keccak_512(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnPointer<[u8; 64], 64> {
1445 sp_crypto_hashing::keccak_512(data)
1446 }
1447
1448 fn sha2_256(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnPointer<[u8; 32], 32> {
1450 sp_crypto_hashing::sha2_256(data)
1451 }
1452
1453 fn blake2_128(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnPointer<[u8; 16], 16> {
1455 sp_crypto_hashing::blake2_128(data)
1456 }
1457
1458 fn blake2_256(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnPointer<[u8; 32], 32> {
1460 sp_crypto_hashing::blake2_256(data)
1461 }
1462
1463 fn twox_256(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnPointer<[u8; 32], 32> {
1465 sp_crypto_hashing::twox_256(data)
1466 }
1467
1468 fn twox_128(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnPointer<[u8; 16], 16> {
1470 sp_crypto_hashing::twox_128(data)
1471 }
1472
1473 fn twox_64(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnPointer<[u8; 8], 8> {
1475 sp_crypto_hashing::twox_64(data)
1476 }
1477}
1478
1479#[runtime_interface]
1481pub trait TransactionIndex {
1482 fn index(
1484 &mut self,
1485 extrinsic: u32,
1486 size: u32,
1487 context_hash: PassPointerAndReadCopy<[u8; 32], 32>,
1488 ) {
1489 self.storage_index_transaction(extrinsic, &context_hash, size);
1490 }
1491
1492 fn renew(&mut self, extrinsic: u32, context_hash: PassPointerAndReadCopy<[u8; 32], 32>) {
1495 self.storage_renew_transaction_index(extrinsic, &context_hash);
1496 }
1497}
1498
1499#[runtime_interface]
1501pub trait OffchainIndex {
1502 fn set(&mut self, key: PassFatPointerAndRead<&[u8]>, value: PassFatPointerAndRead<&[u8]>) {
1504 self.set_offchain_storage(key, Some(value));
1505 }
1506
1507 fn clear(&mut self, key: PassFatPointerAndRead<&[u8]>) {
1509 self.set_offchain_storage(key, None);
1510 }
1511}
1512
1513#[cfg(not(substrate_runtime))]
1514sp_externalities::decl_extension! {
1515 struct VerificationExtDeprecated(bool);
1519}
1520
1521#[runtime_interface]
1525pub trait Offchain {
1526 fn is_validator(&mut self) -> bool {
1531 self.extension::<OffchainWorkerExt>()
1532 .expect("is_validator can be called only in the offchain worker context")
1533 .is_validator()
1534 }
1535
1536 fn submit_transaction(
1540 &mut self,
1541 data: PassFatPointerAndRead<Vec<u8>>,
1542 ) -> AllocateAndReturnByCodec<Result<(), ()>> {
1543 self.extension::<TransactionPoolExt>()
1544 .expect(
1545 "submit_transaction can be called only in the offchain call context with
1546 TransactionPool capabilities enabled",
1547 )
1548 .submit_transaction(data)
1549 }
1550
1551 fn network_state(&mut self) -> AllocateAndReturnByCodec<Result<OpaqueNetworkState, ()>> {
1553 self.extension::<OffchainWorkerExt>()
1554 .expect("network_state can be called only in the offchain worker context")
1555 .network_state()
1556 }
1557
1558 fn timestamp(&mut self) -> ReturnAs<Timestamp, u64> {
1560 self.extension::<OffchainWorkerExt>()
1561 .expect("timestamp can be called only in the offchain worker context")
1562 .timestamp()
1563 }
1564
1565 fn sleep_until(&mut self, deadline: PassAs<Timestamp, u64>) {
1567 self.extension::<OffchainWorkerExt>()
1568 .expect("sleep_until can be called only in the offchain worker context")
1569 .sleep_until(deadline)
1570 }
1571
1572 fn random_seed(&mut self) -> AllocateAndReturnPointer<[u8; 32], 32> {
1577 self.extension::<OffchainWorkerExt>()
1578 .expect("random_seed can be called only in the offchain worker context")
1579 .random_seed()
1580 }
1581
1582 fn local_storage_set(
1587 &mut self,
1588 kind: PassAs<StorageKind, u32>,
1589 key: PassFatPointerAndRead<&[u8]>,
1590 value: PassFatPointerAndRead<&[u8]>,
1591 ) {
1592 self.extension::<OffchainDbExt>()
1593 .expect(
1594 "local_storage_set can be called only in the offchain call context with
1595 OffchainDb extension",
1596 )
1597 .local_storage_set(kind, key, value)
1598 }
1599
1600 fn local_storage_clear(
1605 &mut self,
1606 kind: PassAs<StorageKind, u32>,
1607 key: PassFatPointerAndRead<&[u8]>,
1608 ) {
1609 self.extension::<OffchainDbExt>()
1610 .expect(
1611 "local_storage_clear can be called only in the offchain call context with
1612 OffchainDb extension",
1613 )
1614 .local_storage_clear(kind, key)
1615 }
1616
1617 fn local_storage_compare_and_set(
1627 &mut self,
1628 kind: PassAs<StorageKind, u32>,
1629 key: PassFatPointerAndRead<&[u8]>,
1630 old_value: PassFatPointerAndDecode<Option<Vec<u8>>>,
1631 new_value: PassFatPointerAndRead<&[u8]>,
1632 ) -> bool {
1633 self.extension::<OffchainDbExt>()
1634 .expect(
1635 "local_storage_compare_and_set can be called only in the offchain call context
1636 with OffchainDb extension",
1637 )
1638 .local_storage_compare_and_set(kind, key, old_value.as_deref(), new_value)
1639 }
1640
1641 fn local_storage_get(
1647 &mut self,
1648 kind: PassAs<StorageKind, u32>,
1649 key: PassFatPointerAndRead<&[u8]>,
1650 ) -> AllocateAndReturnByCodec<Option<Vec<u8>>> {
1651 self.extension::<OffchainDbExt>()
1652 .expect(
1653 "local_storage_get can be called only in the offchain call context with
1654 OffchainDb extension",
1655 )
1656 .local_storage_get(kind, key)
1657 }
1658
1659 fn http_request_start(
1664 &mut self,
1665 method: PassFatPointerAndRead<&str>,
1666 uri: PassFatPointerAndRead<&str>,
1667 meta: PassFatPointerAndRead<&[u8]>,
1668 ) -> AllocateAndReturnByCodec<Result<HttpRequestId, ()>> {
1669 self.extension::<OffchainWorkerExt>()
1670 .expect("http_request_start can be called only in the offchain worker context")
1671 .http_request_start(method, uri, meta)
1672 }
1673
1674 fn http_request_add_header(
1676 &mut self,
1677 request_id: PassAs<HttpRequestId, u16>,
1678 name: PassFatPointerAndRead<&str>,
1679 value: PassFatPointerAndRead<&str>,
1680 ) -> AllocateAndReturnByCodec<Result<(), ()>> {
1681 self.extension::<OffchainWorkerExt>()
1682 .expect("http_request_add_header can be called only in the offchain worker context")
1683 .http_request_add_header(request_id, name, value)
1684 }
1685
1686 fn http_request_write_body(
1693 &mut self,
1694 request_id: PassAs<HttpRequestId, u16>,
1695 chunk: PassFatPointerAndRead<&[u8]>,
1696 deadline: PassFatPointerAndDecode<Option<Timestamp>>,
1697 ) -> AllocateAndReturnByCodec<Result<(), HttpError>> {
1698 self.extension::<OffchainWorkerExt>()
1699 .expect("http_request_write_body can be called only in the offchain worker context")
1700 .http_request_write_body(request_id, chunk, deadline)
1701 }
1702
1703 fn http_response_wait(
1711 &mut self,
1712 ids: PassFatPointerAndDecodeSlice<&[HttpRequestId]>,
1713 deadline: PassFatPointerAndDecode<Option<Timestamp>>,
1714 ) -> AllocateAndReturnByCodec<Vec<HttpRequestStatus>> {
1715 self.extension::<OffchainWorkerExt>()
1716 .expect("http_response_wait can be called only in the offchain worker context")
1717 .http_response_wait(ids, deadline)
1718 }
1719
1720 fn http_response_headers(
1725 &mut self,
1726 request_id: PassAs<HttpRequestId, u16>,
1727 ) -> AllocateAndReturnByCodec<Vec<(Vec<u8>, Vec<u8>)>> {
1728 self.extension::<OffchainWorkerExt>()
1729 .expect("http_response_headers can be called only in the offchain worker context")
1730 .http_response_headers(request_id)
1731 }
1732
1733 fn http_response_read_body(
1742 &mut self,
1743 request_id: PassAs<HttpRequestId, u16>,
1744 buffer: PassFatPointerAndReadWrite<&mut [u8]>,
1745 deadline: PassFatPointerAndDecode<Option<Timestamp>>,
1746 ) -> AllocateAndReturnByCodec<Result<u32, HttpError>> {
1747 self.extension::<OffchainWorkerExt>()
1748 .expect("http_response_read_body can be called only in the offchain worker context")
1749 .http_response_read_body(request_id, buffer, deadline)
1750 .map(|r| r as u32)
1751 }
1752
1753 fn set_authorized_nodes(
1755 &mut self,
1756 nodes: PassFatPointerAndDecode<Vec<OpaquePeerId>>,
1757 authorized_only: bool,
1758 ) {
1759 self.extension::<OffchainWorkerExt>()
1760 .expect("set_authorized_nodes can be called only in the offchain worker context")
1761 .set_authorized_nodes(nodes, authorized_only)
1762 }
1763}
1764
1765#[runtime_interface(wasm_only)]
1767pub trait Allocator {
1768 fn malloc(&mut self, size: u32) -> Pointer<u8> {
1770 self.allocate_memory(size).expect("Failed to allocate memory")
1771 }
1772
1773 fn free(&mut self, ptr: Pointer<u8>) {
1775 self.deallocate_memory(ptr).expect("Failed to deallocate memory")
1776 }
1777}
1778
1779#[runtime_interface(wasm_only)]
1782pub trait PanicHandler {
1783 #[trap_on_return]
1785 fn abort_on_panic(&mut self, message: PassFatPointerAndRead<&str>) {
1786 self.register_panic_error_message(message);
1787 }
1788}
1789
1790#[runtime_interface]
1792pub trait Logging {
1793 fn log(
1800 level: PassAs<RuntimeInterfaceLogLevel, u8>,
1801 target: PassFatPointerAndRead<&str>,
1802 message: PassFatPointerAndRead<&[u8]>,
1803 ) {
1804 if let Ok(message) = core::str::from_utf8(message) {
1805 log::log!(target: target, log::Level::from(level), "{}", message)
1806 }
1807 }
1808
1809 fn max_level() -> ReturnAs<LogLevelFilter, u8> {
1811 log::max_level().into()
1812 }
1813}
1814
1815#[runtime_interface(wasm_only, no_tracing)]
1818pub trait WasmTracing {
1819 fn enabled(&mut self, metadata: PassFatPointerAndDecode<sp_tracing::WasmMetadata>) -> bool {
1829 let metadata: &tracing_core::metadata::Metadata<'static> = (&metadata).into();
1830 tracing::dispatcher::get_default(|d| d.enabled(metadata))
1831 }
1832
1833 fn enter_span(
1840 &mut self,
1841 span: PassFatPointerAndDecode<sp_tracing::WasmEntryAttributes>,
1842 ) -> u64 {
1843 let span: tracing::Span = span.into();
1844 match span.id() {
1845 Some(id) => tracing::dispatcher::get_default(|d| {
1846 let final_id = d.clone_span(&id);
1849 d.enter(&final_id);
1850 final_id.into_u64()
1851 }),
1852 _ => 0,
1853 }
1854 }
1855
1856 fn event(&mut self, event: PassFatPointerAndDecode<sp_tracing::WasmEntryAttributes>) {
1858 event.emit();
1859 }
1860
1861 fn exit(&mut self, span: u64) {
1864 tracing::dispatcher::get_default(|d| {
1865 let id = tracing_core::span::Id::from_u64(span);
1866 d.exit(&id);
1867 });
1868 }
1869}
1870
1871#[cfg(all(substrate_runtime, feature = "with-tracing"))]
1872mod tracing_setup {
1873 use super::wasm_tracing;
1874 use core::sync::atomic::{AtomicBool, Ordering};
1875 use tracing_core::{
1876 dispatcher::{set_global_default, Dispatch},
1877 span::{Attributes, Id, Record},
1878 Event, Metadata,
1879 };
1880
1881 static TRACING_SET: AtomicBool = AtomicBool::new(false);
1882
1883 struct PassingTracingSubscriber;
1886
1887 impl tracing_core::Subscriber for PassingTracingSubscriber {
1888 fn enabled(&self, metadata: &Metadata<'_>) -> bool {
1889 wasm_tracing::enabled(metadata.into())
1890 }
1891 fn new_span(&self, attrs: &Attributes<'_>) -> Id {
1892 Id::from_u64(wasm_tracing::enter_span(attrs.into()))
1893 }
1894 fn enter(&self, _: &Id) {
1895 }
1897 fn record(&self, _: &Id, _: &Record<'_>) {
1900 unimplemented! {} }
1902 fn record_follows_from(&self, _: &Id, _: &Id) {
1905 unimplemented! {} }
1907 fn event(&self, event: &Event<'_>) {
1908 wasm_tracing::event(event.into())
1909 }
1910 fn exit(&self, span: &Id) {
1911 wasm_tracing::exit(span.into_u64())
1912 }
1913 }
1914
1915 pub fn init_tracing() {
1919 if TRACING_SET.load(Ordering::Relaxed) == false {
1920 set_global_default(Dispatch::new(PassingTracingSubscriber {}))
1921 .expect("We only ever call this once");
1922 TRACING_SET.store(true, Ordering::Relaxed);
1923 }
1924 }
1925}
1926
1927#[cfg(not(all(substrate_runtime, feature = "with-tracing")))]
1928mod tracing_setup {
1929 pub fn init_tracing() {}
1932}
1933
1934pub use tracing_setup::init_tracing;
1935
1936pub fn unreachable() -> ! {
1941 #[cfg(target_family = "wasm")]
1942 {
1943 core::arch::wasm32::unreachable();
1944 }
1945
1946 #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
1947 unsafe {
1948 core::arch::asm!("unimp", options(noreturn));
1949 }
1950
1951 #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64", target_family = "wasm")))]
1952 unreachable!();
1953}
1954
1955#[cfg(all(not(feature = "disable_panic_handler"), substrate_runtime))]
1957#[panic_handler]
1958pub fn panic(info: &core::panic::PanicInfo) -> ! {
1959 let message = alloc::format!("{}", info);
1960 #[cfg(feature = "improved_panic_error_reporting")]
1961 {
1962 panic_handler::abort_on_panic(&message);
1963 }
1964 #[cfg(not(feature = "improved_panic_error_reporting"))]
1965 {
1966 logging::log(RuntimeInterfaceLogLevel::Error, "runtime", message.as_bytes());
1967 unreachable();
1968 }
1969}
1970
1971#[cfg(all(not(feature = "disable_oom"), enable_alloc_error_handler))]
1973#[alloc_error_handler]
1974pub fn oom(_: core::alloc::Layout) -> ! {
1975 #[cfg(feature = "improved_panic_error_reporting")]
1976 {
1977 panic_handler::abort_on_panic("Runtime memory exhausted.");
1978 }
1979 #[cfg(not(feature = "improved_panic_error_reporting"))]
1980 {
1981 logging::log(
1982 RuntimeInterfaceLogLevel::Error,
1983 "runtime",
1984 b"Runtime memory exhausted. Aborting",
1985 );
1986 unreachable();
1987 }
1988}
1989
1990#[cfg(feature = "std")] pub type TestExternalities = sp_state_machine::TestExternalities<sp_core::Blake2Hasher>;
1993
1994#[docify::export]
1998#[cfg(not(substrate_runtime))]
1999pub type SubstrateHostFunctions = (
2000 storage::HostFunctions,
2001 default_child_storage::HostFunctions,
2002 misc::HostFunctions,
2003 wasm_tracing::HostFunctions,
2004 offchain::HostFunctions,
2005 crypto::HostFunctions,
2006 hashing::HostFunctions,
2007 allocator::HostFunctions,
2008 panic_handler::HostFunctions,
2009 logging::HostFunctions,
2010 crate::trie::HostFunctions,
2011 offchain_index::HostFunctions,
2012 transaction_index::HostFunctions,
2013);
2014
2015#[cfg(test)]
2016mod tests {
2017 use super::*;
2018 use sp_core::{crypto::UncheckedInto, map, storage::Storage};
2019 use sp_state_machine::BasicExternalities;
2020
2021 #[test]
2022 fn storage_works() {
2023 let mut t = BasicExternalities::default();
2024 t.execute_with(|| {
2025 assert_eq!(storage::get(b"hello"), None);
2026 storage::set(b"hello", b"world");
2027 assert_eq!(storage::get(b"hello"), Some(b"world".to_vec().into()));
2028 assert_eq!(storage::get(b"foo"), None);
2029 storage::set(b"foo", &[1, 2, 3][..]);
2030 });
2031
2032 t = BasicExternalities::new(Storage {
2033 top: map![b"foo".to_vec() => b"bar".to_vec()],
2034 children_default: map![],
2035 });
2036
2037 t.execute_with(|| {
2038 assert_eq!(storage::get(b"hello"), None);
2039 assert_eq!(storage::get(b"foo"), Some(b"bar".to_vec().into()));
2040 });
2041
2042 let value = vec![7u8; 35];
2043 let storage =
2044 Storage { top: map![b"foo00".to_vec() => value.clone()], children_default: map![] };
2045 t = BasicExternalities::new(storage);
2046
2047 t.execute_with(|| {
2048 assert_eq!(storage::get(b"hello"), None);
2049 assert_eq!(storage::get(b"foo00"), Some(value.clone().into()));
2050 });
2051 }
2052
2053 #[test]
2054 fn read_storage_works() {
2055 let value = b"\x0b\0\0\0Hello world".to_vec();
2056 let mut t = BasicExternalities::new(Storage {
2057 top: map![b":test".to_vec() => value.clone()],
2058 children_default: map![],
2059 });
2060
2061 t.execute_with(|| {
2062 let mut v = [0u8; 4];
2063 assert_eq!(storage::read(b":test", &mut v[..], 0).unwrap(), value.len() as u32);
2064 assert_eq!(v, [11u8, 0, 0, 0]);
2065 let mut w = [0u8; 11];
2066 assert_eq!(storage::read(b":test", &mut w[..], 4).unwrap(), value.len() as u32 - 4);
2067 assert_eq!(&w, b"Hello world");
2068 });
2069 }
2070
2071 #[test]
2072 fn clear_prefix_works() {
2073 let mut t = BasicExternalities::new(Storage {
2074 top: map![
2075 b":a".to_vec() => b"\x0b\0\0\0Hello world".to_vec(),
2076 b":abcd".to_vec() => b"\x0b\0\0\0Hello world".to_vec(),
2077 b":abc".to_vec() => b"\x0b\0\0\0Hello world".to_vec(),
2078 b":abdd".to_vec() => b"\x0b\0\0\0Hello world".to_vec()
2079 ],
2080 children_default: map![],
2081 });
2082
2083 t.execute_with(|| {
2084 assert!(matches!(
2090 storage::clear_prefix(b":abc", None),
2091 KillStorageResult::AllRemoved(2),
2092 ));
2093
2094 assert!(storage::get(b":a").is_some());
2095 assert!(storage::get(b":abdd").is_some());
2096 assert!(storage::get(b":abcd").is_none());
2097 assert!(storage::get(b":abc").is_none());
2098
2099 assert!(matches!(
2105 storage::clear_prefix(b":abc", None),
2106 KillStorageResult::AllRemoved(0),
2107 ));
2108 });
2109 }
2110
2111 fn zero_ed_pub() -> ed25519::Public {
2112 [0u8; 32].unchecked_into()
2113 }
2114
2115 fn zero_ed_sig() -> ed25519::Signature {
2116 ed25519::Signature::from_raw([0u8; 64])
2117 }
2118
2119 #[test]
2120 fn use_dalek_ext_works() {
2121 let mut ext = BasicExternalities::default();
2122 ext.register_extension(UseDalekExt);
2123
2124 ext.execute_with(|| {
2126 assert!(!crypto::ed25519_verify(&zero_ed_sig(), &Vec::new(), &zero_ed_pub()));
2127 });
2128
2129 BasicExternalities::default().execute_with(|| {
2131 assert!(crypto::ed25519_verify(&zero_ed_sig(), &Vec::new(), &zero_ed_pub()));
2132 })
2133 }
2134
2135 #[test]
2136 fn dalek_should_not_panic_on_invalid_signature() {
2137 let mut ext = BasicExternalities::default();
2138 ext.register_extension(UseDalekExt);
2139
2140 ext.execute_with(|| {
2141 let mut bytes = [0u8; 64];
2142 bytes[63] = 0b1110_0000;
2144
2145 assert!(!crypto::ed25519_verify(
2146 &ed25519::Signature::from_raw(bytes),
2147 &Vec::new(),
2148 &zero_ed_pub()
2149 ));
2150 });
2151 }
2152}