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, target_family = "wasm"))]
139mod global_alloc_wasm;
140
141#[cfg(all(
142 not(feature = "disable_allocator"),
143 substrate_runtime,
144 any(target_arch = "riscv32", target_arch = "riscv64")
145))]
146mod global_alloc_riscv;
147
148#[cfg(not(substrate_runtime))]
149const LOG_TARGET: &str = "runtime::io";
150
151#[derive(Encode, Decode)]
153pub enum EcdsaVerifyError {
154 BadRS,
156 BadV,
158 BadSignature,
160}
161
162#[derive(Encode, Decode)]
165pub enum KillStorageResult {
166 AllRemoved(u32),
169 SomeRemaining(u32),
172}
173
174impl From<MultiRemovalResults> for KillStorageResult {
175 fn from(r: MultiRemovalResults) -> Self {
176 match r.maybe_cursor {
180 None => Self::AllRemoved(r.loops),
181 Some(..) => Self::SomeRemaining(r.loops),
182 }
183 }
184}
185
186#[runtime_interface]
188pub trait Storage {
189 fn get(
191 &mut self,
192 key: PassFatPointerAndRead<&[u8]>,
193 ) -> AllocateAndReturnByCodec<Option<bytes::Bytes>> {
194 self.storage(key).map(|s| bytes::Bytes::from(s.to_vec()))
195 }
196
197 fn read(
203 &mut self,
204 key: PassFatPointerAndRead<&[u8]>,
205 value_out: PassFatPointerAndReadWrite<&mut [u8]>,
206 value_offset: u32,
207 ) -> AllocateAndReturnByCodec<Option<u32>> {
208 self.storage(key).map(|value| {
209 let value_offset = value_offset as usize;
210 let data = &value[value_offset.min(value.len())..];
211 let written = core::cmp::min(data.len(), value_out.len());
212 value_out[..written].copy_from_slice(&data[..written]);
213 data.len() as u32
214 })
215 }
216
217 fn set(&mut self, key: PassFatPointerAndRead<&[u8]>, value: PassFatPointerAndRead<&[u8]>) {
219 self.set_storage(key.to_vec(), value.to_vec());
220 }
221
222 fn clear(&mut self, key: PassFatPointerAndRead<&[u8]>) {
224 self.clear_storage(key)
225 }
226
227 fn exists(&mut self, key: PassFatPointerAndRead<&[u8]>) -> bool {
229 self.exists_storage(key)
230 }
231
232 fn clear_prefix(&mut self, prefix: PassFatPointerAndRead<&[u8]>) {
234 let _ = Externalities::clear_prefix(*self, prefix, None, None);
235 }
236
237 #[version(2)]
263 fn clear_prefix(
264 &mut self,
265 prefix: PassFatPointerAndRead<&[u8]>,
266 limit: PassFatPointerAndDecode<Option<u32>>,
267 ) -> AllocateAndReturnByCodec<KillStorageResult> {
268 Externalities::clear_prefix(*self, prefix, limit, None).into()
269 }
270
271 #[version(3, register_only)]
303 fn clear_prefix(
304 &mut self,
305 maybe_prefix: PassFatPointerAndRead<&[u8]>,
306 maybe_limit: PassFatPointerAndDecode<Option<u32>>,
307 maybe_cursor: PassFatPointerAndDecode<Option<Vec<u8>>>, ) -> AllocateAndReturnByCodec<MultiRemovalResults> {
310 Externalities::clear_prefix(
311 *self,
312 maybe_prefix,
313 maybe_limit,
314 maybe_cursor.as_ref().map(|x| &x[..]),
315 )
316 .into()
317 }
318
319 fn append(&mut self, key: PassFatPointerAndRead<&[u8]>, value: PassFatPointerAndRead<Vec<u8>>) {
328 self.storage_append(key.to_vec(), value);
329 }
330
331 fn root(&mut self) -> AllocateAndReturnFatPointer<Vec<u8>> {
337 self.storage_root(StateVersion::V0)
338 }
339
340 #[version(2)]
346 fn root(&mut self, version: PassAs<StateVersion, u8>) -> AllocateAndReturnFatPointer<Vec<u8>> {
347 self.storage_root(version)
348 }
349
350 fn changes_root(
352 &mut self,
353 _parent_hash: PassFatPointerAndRead<&[u8]>,
354 ) -> AllocateAndReturnByCodec<Option<Vec<u8>>> {
355 None
356 }
357
358 fn next_key(
360 &mut self,
361 key: PassFatPointerAndRead<&[u8]>,
362 ) -> AllocateAndReturnByCodec<Option<Vec<u8>>> {
363 self.next_storage_key(key)
364 }
365
366 fn start_transaction(&mut self) {
379 self.storage_start_transaction();
380 }
381
382 fn rollback_transaction(&mut self) {
390 self.storage_rollback_transaction()
391 .expect("No open transaction that can be rolled back.");
392 }
393
394 fn commit_transaction(&mut self) {
402 self.storage_commit_transaction()
403 .expect("No open transaction that can be committed.");
404 }
405}
406
407#[runtime_interface]
410pub trait DefaultChildStorage {
411 fn get(
416 &mut self,
417 storage_key: PassFatPointerAndRead<&[u8]>,
418 key: PassFatPointerAndRead<&[u8]>,
419 ) -> AllocateAndReturnByCodec<Option<Vec<u8>>> {
420 let child_info = ChildInfo::new_default(storage_key);
421 self.child_storage(&child_info, key).map(|s| s.to_vec())
422 }
423
424 fn read(
432 &mut self,
433 storage_key: PassFatPointerAndRead<&[u8]>,
434 key: PassFatPointerAndRead<&[u8]>,
435 value_out: PassFatPointerAndReadWrite<&mut [u8]>,
436 value_offset: u32,
437 ) -> AllocateAndReturnByCodec<Option<u32>> {
438 let child_info = ChildInfo::new_default(storage_key);
439 self.child_storage(&child_info, key).map(|value| {
440 let value_offset = value_offset as usize;
441 let data = &value[value_offset.min(value.len())..];
442 let written = core::cmp::min(data.len(), value_out.len());
443 value_out[..written].copy_from_slice(&data[..written]);
444 data.len() as u32
445 })
446 }
447
448 fn set(
452 &mut self,
453 storage_key: PassFatPointerAndRead<&[u8]>,
454 key: PassFatPointerAndRead<&[u8]>,
455 value: PassFatPointerAndRead<&[u8]>,
456 ) {
457 let child_info = ChildInfo::new_default(storage_key);
458 self.set_child_storage(&child_info, key.to_vec(), value.to_vec());
459 }
460
461 fn clear(
465 &mut self,
466 storage_key: PassFatPointerAndRead<&[u8]>,
467 key: PassFatPointerAndRead<&[u8]>,
468 ) {
469 let child_info = ChildInfo::new_default(storage_key);
470 self.clear_child_storage(&child_info, key);
471 }
472
473 fn storage_kill(&mut self, storage_key: PassFatPointerAndRead<&[u8]>) {
478 let child_info = ChildInfo::new_default(storage_key);
479 let _ = self.kill_child_storage(&child_info, None, None);
480 }
481
482 #[version(2)]
486 fn storage_kill(
487 &mut self,
488 storage_key: PassFatPointerAndRead<&[u8]>,
489 limit: PassFatPointerAndDecode<Option<u32>>,
490 ) -> bool {
491 let child_info = ChildInfo::new_default(storage_key);
492 let r = self.kill_child_storage(&child_info, limit, None);
493 r.maybe_cursor.is_none()
494 }
495
496 #[version(3)]
500 fn storage_kill(
501 &mut self,
502 storage_key: PassFatPointerAndRead<&[u8]>,
503 limit: PassFatPointerAndDecode<Option<u32>>,
504 ) -> AllocateAndReturnByCodec<KillStorageResult> {
505 let child_info = ChildInfo::new_default(storage_key);
506 self.kill_child_storage(&child_info, limit, None).into()
507 }
508
509 #[version(4, register_only)]
513 fn storage_kill(
514 &mut self,
515 storage_key: PassFatPointerAndRead<&[u8]>,
516 maybe_limit: PassFatPointerAndDecode<Option<u32>>,
517 maybe_cursor: PassFatPointerAndDecode<Option<Vec<u8>>>,
518 ) -> AllocateAndReturnByCodec<MultiRemovalResults> {
519 let child_info = ChildInfo::new_default(storage_key);
520 self.kill_child_storage(&child_info, maybe_limit, maybe_cursor.as_ref().map(|x| &x[..]))
521 .into()
522 }
523
524 fn exists(
528 &mut self,
529 storage_key: PassFatPointerAndRead<&[u8]>,
530 key: PassFatPointerAndRead<&[u8]>,
531 ) -> bool {
532 let child_info = ChildInfo::new_default(storage_key);
533 self.exists_child_storage(&child_info, key)
534 }
535
536 fn clear_prefix(
540 &mut self,
541 storage_key: PassFatPointerAndRead<&[u8]>,
542 prefix: PassFatPointerAndRead<&[u8]>,
543 ) {
544 let child_info = ChildInfo::new_default(storage_key);
545 let _ = self.clear_child_prefix(&child_info, prefix, None, None);
546 }
547
548 #[version(2)]
552 fn clear_prefix(
553 &mut self,
554 storage_key: PassFatPointerAndRead<&[u8]>,
555 prefix: PassFatPointerAndRead<&[u8]>,
556 limit: PassFatPointerAndDecode<Option<u32>>,
557 ) -> AllocateAndReturnByCodec<KillStorageResult> {
558 let child_info = ChildInfo::new_default(storage_key);
559 self.clear_child_prefix(&child_info, prefix, limit, None).into()
560 }
561
562 #[version(3, register_only)]
566 fn clear_prefix(
567 &mut self,
568 storage_key: PassFatPointerAndRead<&[u8]>,
569 prefix: PassFatPointerAndRead<&[u8]>,
570 maybe_limit: PassFatPointerAndDecode<Option<u32>>,
571 maybe_cursor: PassFatPointerAndDecode<Option<Vec<u8>>>,
572 ) -> AllocateAndReturnByCodec<MultiRemovalResults> {
573 let child_info = ChildInfo::new_default(storage_key);
574 self.clear_child_prefix(
575 &child_info,
576 prefix,
577 maybe_limit,
578 maybe_cursor.as_ref().map(|x| &x[..]),
579 )
580 .into()
581 }
582
583 fn root(
590 &mut self,
591 storage_key: PassFatPointerAndRead<&[u8]>,
592 ) -> AllocateAndReturnFatPointer<Vec<u8>> {
593 let child_info = ChildInfo::new_default(storage_key);
594 self.child_storage_root(&child_info, StateVersion::V0)
595 }
596
597 #[version(2)]
604 fn root(
605 &mut self,
606 storage_key: PassFatPointerAndRead<&[u8]>,
607 version: PassAs<StateVersion, u8>,
608 ) -> AllocateAndReturnFatPointer<Vec<u8>> {
609 let child_info = ChildInfo::new_default(storage_key);
610 self.child_storage_root(&child_info, version)
611 }
612
613 fn next_key(
617 &mut self,
618 storage_key: PassFatPointerAndRead<&[u8]>,
619 key: PassFatPointerAndRead<&[u8]>,
620 ) -> AllocateAndReturnByCodec<Option<Vec<u8>>> {
621 let child_info = ChildInfo::new_default(storage_key);
622 self.next_child_storage_key(&child_info, key)
623 }
624}
625
626#[runtime_interface]
628pub trait Trie {
629 fn blake2_256_root(
631 input: PassFatPointerAndDecode<Vec<(Vec<u8>, Vec<u8>)>>,
632 ) -> AllocateAndReturnPointer<H256, 32> {
633 LayoutV0::<sp_core::Blake2Hasher>::trie_root(input)
634 }
635
636 #[version(2)]
638 fn blake2_256_root(
639 input: PassFatPointerAndDecode<Vec<(Vec<u8>, Vec<u8>)>>,
640 version: PassAs<StateVersion, u8>,
641 ) -> AllocateAndReturnPointer<H256, 32> {
642 match version {
643 StateVersion::V0 => LayoutV0::<sp_core::Blake2Hasher>::trie_root(input),
644 StateVersion::V1 => LayoutV1::<sp_core::Blake2Hasher>::trie_root(input),
645 }
646 }
647
648 fn blake2_256_ordered_root(
650 input: PassFatPointerAndDecode<Vec<Vec<u8>>>,
651 ) -> AllocateAndReturnPointer<H256, 32> {
652 LayoutV0::<sp_core::Blake2Hasher>::ordered_trie_root(input)
653 }
654
655 #[version(2)]
657 fn blake2_256_ordered_root(
658 input: PassFatPointerAndDecode<Vec<Vec<u8>>>,
659 version: PassAs<StateVersion, u8>,
660 ) -> AllocateAndReturnPointer<H256, 32> {
661 match version {
662 StateVersion::V0 => LayoutV0::<sp_core::Blake2Hasher>::ordered_trie_root(input),
663 StateVersion::V1 => LayoutV1::<sp_core::Blake2Hasher>::ordered_trie_root(input),
664 }
665 }
666
667 fn keccak_256_root(
669 input: PassFatPointerAndDecode<Vec<(Vec<u8>, Vec<u8>)>>,
670 ) -> AllocateAndReturnPointer<H256, 32> {
671 LayoutV0::<sp_core::KeccakHasher>::trie_root(input)
672 }
673
674 #[version(2)]
676 fn keccak_256_root(
677 input: PassFatPointerAndDecode<Vec<(Vec<u8>, Vec<u8>)>>,
678 version: PassAs<StateVersion, u8>,
679 ) -> AllocateAndReturnPointer<H256, 32> {
680 match version {
681 StateVersion::V0 => LayoutV0::<sp_core::KeccakHasher>::trie_root(input),
682 StateVersion::V1 => LayoutV1::<sp_core::KeccakHasher>::trie_root(input),
683 }
684 }
685
686 fn keccak_256_ordered_root(
688 input: PassFatPointerAndDecode<Vec<Vec<u8>>>,
689 ) -> AllocateAndReturnPointer<H256, 32> {
690 LayoutV0::<sp_core::KeccakHasher>::ordered_trie_root(input)
691 }
692
693 #[version(2)]
695 fn keccak_256_ordered_root(
696 input: PassFatPointerAndDecode<Vec<Vec<u8>>>,
697 version: PassAs<StateVersion, u8>,
698 ) -> AllocateAndReturnPointer<H256, 32> {
699 match version {
700 StateVersion::V0 => LayoutV0::<sp_core::KeccakHasher>::ordered_trie_root(input),
701 StateVersion::V1 => LayoutV1::<sp_core::KeccakHasher>::ordered_trie_root(input),
702 }
703 }
704
705 fn blake2_256_verify_proof(
707 root: PassPointerAndReadCopy<H256, 32>,
708 proof: PassFatPointerAndDecodeSlice<&[Vec<u8>]>,
709 key: PassFatPointerAndRead<&[u8]>,
710 value: PassFatPointerAndRead<&[u8]>,
711 ) -> bool {
712 sp_trie::verify_trie_proof::<LayoutV0<sp_core::Blake2Hasher>, _, _, _>(
713 &root,
714 proof,
715 &[(key, Some(value))],
716 )
717 .is_ok()
718 }
719
720 #[version(2)]
722 fn blake2_256_verify_proof(
723 root: PassPointerAndReadCopy<H256, 32>,
724 proof: PassFatPointerAndDecodeSlice<&[Vec<u8>]>,
725 key: PassFatPointerAndRead<&[u8]>,
726 value: PassFatPointerAndRead<&[u8]>,
727 version: PassAs<StateVersion, u8>,
728 ) -> bool {
729 match version {
730 StateVersion::V0 => sp_trie::verify_trie_proof::<
731 LayoutV0<sp_core::Blake2Hasher>,
732 _,
733 _,
734 _,
735 >(&root, proof, &[(key, Some(value))])
736 .is_ok(),
737 StateVersion::V1 => sp_trie::verify_trie_proof::<
738 LayoutV1<sp_core::Blake2Hasher>,
739 _,
740 _,
741 _,
742 >(&root, proof, &[(key, Some(value))])
743 .is_ok(),
744 }
745 }
746
747 fn keccak_256_verify_proof(
749 root: PassPointerAndReadCopy<H256, 32>,
750 proof: PassFatPointerAndDecodeSlice<&[Vec<u8>]>,
751 key: PassFatPointerAndRead<&[u8]>,
752 value: PassFatPointerAndRead<&[u8]>,
753 ) -> bool {
754 sp_trie::verify_trie_proof::<LayoutV0<sp_core::KeccakHasher>, _, _, _>(
755 &root,
756 proof,
757 &[(key, Some(value))],
758 )
759 .is_ok()
760 }
761
762 #[version(2)]
764 fn keccak_256_verify_proof(
765 root: PassPointerAndReadCopy<H256, 32>,
766 proof: PassFatPointerAndDecodeSlice<&[Vec<u8>]>,
767 key: PassFatPointerAndRead<&[u8]>,
768 value: PassFatPointerAndRead<&[u8]>,
769 version: PassAs<StateVersion, u8>,
770 ) -> bool {
771 match version {
772 StateVersion::V0 => sp_trie::verify_trie_proof::<
773 LayoutV0<sp_core::KeccakHasher>,
774 _,
775 _,
776 _,
777 >(&root, proof, &[(key, Some(value))])
778 .is_ok(),
779 StateVersion::V1 => sp_trie::verify_trie_proof::<
780 LayoutV1<sp_core::KeccakHasher>,
781 _,
782 _,
783 _,
784 >(&root, proof, &[(key, Some(value))])
785 .is_ok(),
786 }
787 }
788}
789
790#[runtime_interface]
793pub trait Misc {
794 fn print_num(val: u64) {
799 log::debug!(target: "runtime", "{}", val);
800 }
801
802 fn print_utf8(utf8: PassFatPointerAndRead<&[u8]>) {
804 if let Ok(data) = core::str::from_utf8(utf8) {
805 log::debug!(target: "runtime", "{}", data)
806 }
807 }
808
809 fn print_hex(data: PassFatPointerAndRead<&[u8]>) {
811 log::debug!(target: "runtime", "{}", HexDisplay::from(&data));
812 }
813
814 fn runtime_version(
830 &mut self,
831 wasm: PassFatPointerAndRead<&[u8]>,
832 ) -> AllocateAndReturnByCodec<Option<Vec<u8>>> {
833 use sp_core::traits::ReadRuntimeVersionExt;
834
835 let mut ext = sp_state_machine::BasicExternalities::default();
836
837 match self
838 .extension::<ReadRuntimeVersionExt>()
839 .expect("No `ReadRuntimeVersionExt` associated for the current context!")
840 .read_runtime_version(wasm, &mut ext)
841 {
842 Ok(v) => Some(v),
843 Err(err) => {
844 log::debug!(
845 target: LOG_TARGET,
846 "cannot read version from the given runtime: {}",
847 err,
848 );
849 None
850 },
851 }
852 }
853}
854
855#[cfg(not(substrate_runtime))]
856sp_externalities::decl_extension! {
857 pub struct UseDalekExt;
874}
875
876#[cfg(not(substrate_runtime))]
877impl Default for UseDalekExt {
878 fn default() -> Self {
879 Self
880 }
881}
882
883#[runtime_interface]
885pub trait Crypto {
886 fn ed25519_public_keys(
888 &mut self,
889 id: PassPointerAndReadCopy<KeyTypeId, 4>,
890 ) -> AllocateAndReturnByCodec<Vec<ed25519::Public>> {
891 self.extension::<KeystoreExt>()
892 .expect("No `keystore` associated for the current context!")
893 .ed25519_public_keys(id)
894 }
895
896 fn ed25519_generate(
903 &mut self,
904 id: PassPointerAndReadCopy<KeyTypeId, 4>,
905 seed: PassFatPointerAndDecode<Option<Vec<u8>>>,
906 ) -> AllocateAndReturnPointer<ed25519::Public, 32> {
907 let seed = seed.as_ref().map(|s| core::str::from_utf8(s).expect("Seed is valid utf8!"));
908 self.extension::<KeystoreExt>()
909 .expect("No `keystore` associated for the current context!")
910 .ed25519_generate_new(id, seed)
911 .expect("`ed25519_generate` failed")
912 }
913
914 fn ed25519_sign(
919 &mut self,
920 id: PassPointerAndReadCopy<KeyTypeId, 4>,
921 pub_key: PassPointerAndRead<&ed25519::Public, 32>,
922 msg: PassFatPointerAndRead<&[u8]>,
923 ) -> AllocateAndReturnByCodec<Option<ed25519::Signature>> {
924 self.extension::<KeystoreExt>()
925 .expect("No `keystore` associated for the current context!")
926 .ed25519_sign(id, pub_key, msg)
927 .ok()
928 .flatten()
929 }
930
931 fn ed25519_verify(
935 sig: PassPointerAndRead<&ed25519::Signature, 64>,
936 msg: PassFatPointerAndRead<&[u8]>,
937 pub_key: PassPointerAndRead<&ed25519::Public, 32>,
938 ) -> bool {
939 if sp_externalities::with_externalities(|mut e| e.extension::<UseDalekExt>().is_some())
943 .unwrap_or_default()
944 {
945 use ed25519_dalek::Verifier;
946
947 let Ok(public_key) = ed25519_dalek::VerifyingKey::from_bytes(&pub_key.0) else {
948 return false
949 };
950
951 let sig = ed25519_dalek::Signature::from_bytes(&sig.0);
952
953 public_key.verify(msg, &sig).is_ok()
954 } else {
955 ed25519::Pair::verify(sig, msg, pub_key)
956 }
957 }
958
959 #[version(1, register_only)]
973 fn ed25519_batch_verify(
974 &mut self,
975 sig: PassPointerAndRead<&ed25519::Signature, 64>,
976 msg: PassFatPointerAndRead<&[u8]>,
977 pub_key: PassPointerAndRead<&ed25519::Public, 32>,
978 ) -> bool {
979 let res = ed25519_verify(sig, msg, pub_key);
980
981 if let Some(ext) = self.extension::<VerificationExtDeprecated>() {
982 ext.0 &= res;
983 }
984
985 res
986 }
987
988 #[version(2)]
992 fn sr25519_verify(
993 sig: PassPointerAndRead<&sr25519::Signature, 64>,
994 msg: PassFatPointerAndRead<&[u8]>,
995 pub_key: PassPointerAndRead<&sr25519::Public, 32>,
996 ) -> bool {
997 sr25519::Pair::verify(sig, msg, pub_key)
998 }
999
1000 #[version(1, register_only)]
1014 fn sr25519_batch_verify(
1015 &mut self,
1016 sig: PassPointerAndRead<&sr25519::Signature, 64>,
1017 msg: PassFatPointerAndRead<&[u8]>,
1018 pub_key: PassPointerAndRead<&sr25519::Public, 32>,
1019 ) -> bool {
1020 let res = sr25519_verify(sig, msg, pub_key);
1021
1022 if let Some(ext) = self.extension::<VerificationExtDeprecated>() {
1023 ext.0 &= res;
1024 }
1025
1026 res
1027 }
1028
1029 #[version(1, register_only)]
1036 fn start_batch_verify(&mut self) {
1037 self.register_extension(VerificationExtDeprecated(true))
1038 .expect("Failed to register required extension: `VerificationExt`");
1039 }
1040
1041 #[version(1, register_only)]
1053 fn finish_batch_verify(&mut self) -> bool {
1054 let result = self
1055 .extension::<VerificationExtDeprecated>()
1056 .expect("`finish_batch_verify` should only be called after `start_batch_verify`")
1057 .0;
1058
1059 self.deregister_extension::<VerificationExtDeprecated>()
1060 .expect("No verification extension in current context!");
1061
1062 result
1063 }
1064
1065 fn sr25519_public_keys(
1067 &mut self,
1068 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1069 ) -> AllocateAndReturnByCodec<Vec<sr25519::Public>> {
1070 self.extension::<KeystoreExt>()
1071 .expect("No `keystore` associated for the current context!")
1072 .sr25519_public_keys(id)
1073 }
1074
1075 fn sr25519_generate(
1082 &mut self,
1083 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1084 seed: PassFatPointerAndDecode<Option<Vec<u8>>>,
1085 ) -> AllocateAndReturnPointer<sr25519::Public, 32> {
1086 let seed = seed.as_ref().map(|s| core::str::from_utf8(s).expect("Seed is valid utf8!"));
1087 self.extension::<KeystoreExt>()
1088 .expect("No `keystore` associated for the current context!")
1089 .sr25519_generate_new(id, seed)
1090 .expect("`sr25519_generate` failed")
1091 }
1092
1093 fn sr25519_sign(
1098 &mut self,
1099 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1100 pub_key: PassPointerAndRead<&sr25519::Public, 32>,
1101 msg: PassFatPointerAndRead<&[u8]>,
1102 ) -> AllocateAndReturnByCodec<Option<sr25519::Signature>> {
1103 self.extension::<KeystoreExt>()
1104 .expect("No `keystore` associated for the current context!")
1105 .sr25519_sign(id, pub_key, msg)
1106 .ok()
1107 .flatten()
1108 }
1109
1110 fn sr25519_verify(
1115 sig: PassPointerAndRead<&sr25519::Signature, 64>,
1116 msg: PassFatPointerAndRead<&[u8]>,
1117 pubkey: PassPointerAndRead<&sr25519::Public, 32>,
1118 ) -> bool {
1119 sr25519::Pair::verify_deprecated(sig, msg, pubkey)
1120 }
1121
1122 fn ecdsa_public_keys(
1124 &mut self,
1125 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1126 ) -> AllocateAndReturnByCodec<Vec<ecdsa::Public>> {
1127 self.extension::<KeystoreExt>()
1128 .expect("No `keystore` associated for the current context!")
1129 .ecdsa_public_keys(id)
1130 }
1131
1132 fn ecdsa_generate(
1139 &mut self,
1140 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1141 seed: PassFatPointerAndDecode<Option<Vec<u8>>>,
1142 ) -> AllocateAndReturnPointer<ecdsa::Public, 33> {
1143 let seed = seed.as_ref().map(|s| core::str::from_utf8(s).expect("Seed is valid utf8!"));
1144 self.extension::<KeystoreExt>()
1145 .expect("No `keystore` associated for the current context!")
1146 .ecdsa_generate_new(id, seed)
1147 .expect("`ecdsa_generate` failed")
1148 }
1149
1150 fn ecdsa_sign(
1155 &mut self,
1156 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1157 pub_key: PassPointerAndRead<&ecdsa::Public, 33>,
1158 msg: PassFatPointerAndRead<&[u8]>,
1159 ) -> AllocateAndReturnByCodec<Option<ecdsa::Signature>> {
1160 self.extension::<KeystoreExt>()
1161 .expect("No `keystore` associated for the current context!")
1162 .ecdsa_sign(id, pub_key, msg)
1163 .ok()
1164 .flatten()
1165 }
1166
1167 fn ecdsa_sign_prehashed(
1172 &mut self,
1173 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1174 pub_key: PassPointerAndRead<&ecdsa::Public, 33>,
1175 msg: PassPointerAndRead<&[u8; 32], 32>,
1176 ) -> AllocateAndReturnByCodec<Option<ecdsa::Signature>> {
1177 self.extension::<KeystoreExt>()
1178 .expect("No `keystore` associated for the current context!")
1179 .ecdsa_sign_prehashed(id, pub_key, msg)
1180 .ok()
1181 .flatten()
1182 }
1183
1184 fn ecdsa_verify(
1189 sig: PassPointerAndRead<&ecdsa::Signature, 65>,
1190 msg: PassFatPointerAndRead<&[u8]>,
1191 pub_key: PassPointerAndRead<&ecdsa::Public, 33>,
1192 ) -> bool {
1193 #[allow(deprecated)]
1194 ecdsa::Pair::verify_deprecated(sig, msg, pub_key)
1195 }
1196
1197 #[version(2)]
1201 fn ecdsa_verify(
1202 sig: PassPointerAndRead<&ecdsa::Signature, 65>,
1203 msg: PassFatPointerAndRead<&[u8]>,
1204 pub_key: PassPointerAndRead<&ecdsa::Public, 33>,
1205 ) -> bool {
1206 ecdsa::Pair::verify(sig, msg, pub_key)
1207 }
1208
1209 fn ecdsa_verify_prehashed(
1213 sig: PassPointerAndRead<&ecdsa::Signature, 65>,
1214 msg: PassPointerAndRead<&[u8; 32], 32>,
1215 pub_key: PassPointerAndRead<&ecdsa::Public, 33>,
1216 ) -> bool {
1217 ecdsa::Pair::verify_prehashed(sig, msg, pub_key)
1218 }
1219
1220 #[version(1, register_only)]
1234 fn ecdsa_batch_verify(
1235 &mut self,
1236 sig: PassPointerAndRead<&ecdsa::Signature, 65>,
1237 msg: PassFatPointerAndRead<&[u8]>,
1238 pub_key: PassPointerAndRead<&ecdsa::Public, 33>,
1239 ) -> bool {
1240 let res = ecdsa_verify(sig, msg, pub_key);
1241
1242 if let Some(ext) = self.extension::<VerificationExtDeprecated>() {
1243 ext.0 &= res;
1244 }
1245
1246 res
1247 }
1248
1249 fn secp256k1_ecdsa_recover(
1258 sig: PassPointerAndRead<&[u8; 65], 65>,
1259 msg: PassPointerAndRead<&[u8; 32], 32>,
1260 ) -> AllocateAndReturnByCodec<Result<[u8; 64], EcdsaVerifyError>> {
1261 let rid = libsecp256k1::RecoveryId::parse(
1262 if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8,
1263 )
1264 .map_err(|_| EcdsaVerifyError::BadV)?;
1265 let sig = libsecp256k1::Signature::parse_overflowing_slice(&sig[..64])
1266 .map_err(|_| EcdsaVerifyError::BadRS)?;
1267 let msg = libsecp256k1::Message::parse(msg);
1268 let pubkey =
1269 libsecp256k1::recover(&msg, &sig, &rid).map_err(|_| EcdsaVerifyError::BadSignature)?;
1270 let mut res = [0u8; 64];
1271 res.copy_from_slice(&pubkey.serialize()[1..65]);
1272 Ok(res)
1273 }
1274
1275 #[version(2)]
1283 fn secp256k1_ecdsa_recover(
1284 sig: PassPointerAndRead<&[u8; 65], 65>,
1285 msg: PassPointerAndRead<&[u8; 32], 32>,
1286 ) -> AllocateAndReturnByCodec<Result<[u8; 64], EcdsaVerifyError>> {
1287 let rid = RecoveryId::from_i32(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as i32)
1288 .map_err(|_| EcdsaVerifyError::BadV)?;
1289 let sig = RecoverableSignature::from_compact(&sig[..64], rid)
1290 .map_err(|_| EcdsaVerifyError::BadRS)?;
1291 let msg = Message::from_digest_slice(msg).expect("Message is 32 bytes; qed");
1292 #[cfg(feature = "std")]
1293 let ctx = secp256k1::SECP256K1;
1294 #[cfg(not(feature = "std"))]
1295 let ctx = secp256k1::Secp256k1::<secp256k1::VerifyOnly>::gen_new();
1296 let pubkey = ctx.recover_ecdsa(&msg, &sig).map_err(|_| EcdsaVerifyError::BadSignature)?;
1297 let mut res = [0u8; 64];
1298 res.copy_from_slice(&pubkey.serialize_uncompressed()[1..]);
1299 Ok(res)
1300 }
1301
1302 fn secp256k1_ecdsa_recover_compressed(
1309 sig: PassPointerAndRead<&[u8; 65], 65>,
1310 msg: PassPointerAndRead<&[u8; 32], 32>,
1311 ) -> AllocateAndReturnByCodec<Result<[u8; 33], EcdsaVerifyError>> {
1312 let rid = libsecp256k1::RecoveryId::parse(
1313 if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8,
1314 )
1315 .map_err(|_| EcdsaVerifyError::BadV)?;
1316 let sig = libsecp256k1::Signature::parse_overflowing_slice(&sig[0..64])
1317 .map_err(|_| EcdsaVerifyError::BadRS)?;
1318 let msg = libsecp256k1::Message::parse(msg);
1319 let pubkey =
1320 libsecp256k1::recover(&msg, &sig, &rid).map_err(|_| EcdsaVerifyError::BadSignature)?;
1321 Ok(pubkey.serialize_compressed())
1322 }
1323
1324 #[version(2)]
1331 fn secp256k1_ecdsa_recover_compressed(
1332 sig: PassPointerAndRead<&[u8; 65], 65>,
1333 msg: PassPointerAndRead<&[u8; 32], 32>,
1334 ) -> AllocateAndReturnByCodec<Result<[u8; 33], EcdsaVerifyError>> {
1335 let rid = RecoveryId::from_i32(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as i32)
1336 .map_err(|_| EcdsaVerifyError::BadV)?;
1337 let sig = RecoverableSignature::from_compact(&sig[..64], rid)
1338 .map_err(|_| EcdsaVerifyError::BadRS)?;
1339 let msg = Message::from_digest_slice(msg).expect("Message is 32 bytes; qed");
1340 #[cfg(feature = "std")]
1341 let ctx = secp256k1::SECP256K1;
1342 #[cfg(not(feature = "std"))]
1343 let ctx = secp256k1::Secp256k1::<secp256k1::VerifyOnly>::gen_new();
1344 let pubkey = ctx.recover_ecdsa(&msg, &sig).map_err(|_| EcdsaVerifyError::BadSignature)?;
1345 Ok(pubkey.serialize())
1346 }
1347
1348 #[cfg(feature = "bls-experimental")]
1355 fn bls381_generate(
1356 &mut self,
1357 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1358 seed: PassFatPointerAndDecode<Option<Vec<u8>>>,
1359 ) -> AllocateAndReturnPointer<bls381::Public, 144> {
1360 let seed = seed.as_ref().map(|s| core::str::from_utf8(s).expect("Seed is valid utf8!"));
1361 self.extension::<KeystoreExt>()
1362 .expect("No `keystore` associated for the current context!")
1363 .bls381_generate_new(id, seed)
1364 .expect("`bls381_generate` failed")
1365 }
1366
1367 #[cfg(feature = "bls-experimental")]
1372 fn bls381_generate_proof_of_possession(
1373 &mut self,
1374 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1375 pub_key: PassPointerAndRead<&bls381::Public, 144>,
1376 owner: PassFatPointerAndRead<&[u8]>,
1377 ) -> AllocateAndReturnByCodec<Option<bls381::ProofOfPossession>> {
1378 self.extension::<KeystoreExt>()
1379 .expect("No `keystore` associated for the current context!")
1380 .bls381_generate_proof_of_possession(id, pub_key, owner)
1381 .ok()
1382 .flatten()
1383 }
1384
1385 #[cfg(feature = "bls-experimental")]
1392 fn ecdsa_bls381_generate(
1393 &mut self,
1394 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1395 seed: PassFatPointerAndDecode<Option<Vec<u8>>>,
1396 ) -> AllocateAndReturnPointer<ecdsa_bls381::Public, { 144 + 33 }> {
1397 let seed = seed.as_ref().map(|s| core::str::from_utf8(s).expect("Seed is valid utf8!"));
1398 self.extension::<KeystoreExt>()
1399 .expect("No `keystore` associated for the current context!")
1400 .ecdsa_bls381_generate_new(id, seed)
1401 .expect("`ecdsa_bls381_generate` failed")
1402 }
1403
1404 #[cfg(feature = "bandersnatch-experimental")]
1411 fn bandersnatch_generate(
1412 &mut self,
1413 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1414 seed: PassFatPointerAndDecode<Option<Vec<u8>>>,
1415 ) -> AllocateAndReturnPointer<bandersnatch::Public, 32> {
1416 let seed = seed.as_ref().map(|s| core::str::from_utf8(s).expect("Seed is valid utf8!"));
1417 self.extension::<KeystoreExt>()
1418 .expect("No `keystore` associated for the current context!")
1419 .bandersnatch_generate_new(id, seed)
1420 .expect("`bandernatch_generate` failed")
1421 }
1422
1423 #[cfg(feature = "bandersnatch-experimental")]
1428 fn bandersnatch_sign(
1429 &mut self,
1430 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1431 pub_key: PassPointerAndRead<&bandersnatch::Public, 32>,
1432 msg: PassFatPointerAndRead<&[u8]>,
1433 ) -> AllocateAndReturnByCodec<Option<bandersnatch::Signature>> {
1434 self.extension::<KeystoreExt>()
1435 .expect("No `keystore` associated for the current context!")
1436 .bandersnatch_sign(id, pub_key, msg)
1437 .ok()
1438 .flatten()
1439 }
1440}
1441
1442#[runtime_interface]
1444pub trait Hashing {
1445 fn keccak_256(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnPointer<[u8; 32], 32> {
1447 sp_crypto_hashing::keccak_256(data)
1448 }
1449
1450 fn keccak_512(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnPointer<[u8; 64], 64> {
1452 sp_crypto_hashing::keccak_512(data)
1453 }
1454
1455 fn sha2_256(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnPointer<[u8; 32], 32> {
1457 sp_crypto_hashing::sha2_256(data)
1458 }
1459
1460 fn blake2_128(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnPointer<[u8; 16], 16> {
1462 sp_crypto_hashing::blake2_128(data)
1463 }
1464
1465 fn blake2_256(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnPointer<[u8; 32], 32> {
1467 sp_crypto_hashing::blake2_256(data)
1468 }
1469
1470 fn twox_256(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnPointer<[u8; 32], 32> {
1472 sp_crypto_hashing::twox_256(data)
1473 }
1474
1475 fn twox_128(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnPointer<[u8; 16], 16> {
1477 sp_crypto_hashing::twox_128(data)
1478 }
1479
1480 fn twox_64(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnPointer<[u8; 8], 8> {
1482 sp_crypto_hashing::twox_64(data)
1483 }
1484}
1485
1486#[runtime_interface]
1488pub trait TransactionIndex {
1489 fn index(
1491 &mut self,
1492 extrinsic: u32,
1493 size: u32,
1494 context_hash: PassPointerAndReadCopy<[u8; 32], 32>,
1495 ) {
1496 self.storage_index_transaction(extrinsic, &context_hash, size);
1497 }
1498
1499 fn renew(&mut self, extrinsic: u32, context_hash: PassPointerAndReadCopy<[u8; 32], 32>) {
1501 self.storage_renew_transaction_index(extrinsic, &context_hash);
1502 }
1503}
1504
1505#[runtime_interface]
1507pub trait OffchainIndex {
1508 fn set(&mut self, key: PassFatPointerAndRead<&[u8]>, value: PassFatPointerAndRead<&[u8]>) {
1510 self.set_offchain_storage(key, Some(value));
1511 }
1512
1513 fn clear(&mut self, key: PassFatPointerAndRead<&[u8]>) {
1515 self.set_offchain_storage(key, None);
1516 }
1517}
1518
1519#[cfg(not(substrate_runtime))]
1520sp_externalities::decl_extension! {
1521 struct VerificationExtDeprecated(bool);
1525}
1526
1527#[runtime_interface]
1531pub trait Offchain {
1532 fn is_validator(&mut self) -> bool {
1537 self.extension::<OffchainWorkerExt>()
1538 .expect("is_validator can be called only in the offchain worker context")
1539 .is_validator()
1540 }
1541
1542 fn submit_transaction(
1546 &mut self,
1547 data: PassFatPointerAndRead<Vec<u8>>,
1548 ) -> AllocateAndReturnByCodec<Result<(), ()>> {
1549 self.extension::<TransactionPoolExt>()
1550 .expect(
1551 "submit_transaction can be called only in the offchain call context with
1552 TransactionPool capabilities enabled",
1553 )
1554 .submit_transaction(data)
1555 }
1556
1557 fn network_state(&mut self) -> AllocateAndReturnByCodec<Result<OpaqueNetworkState, ()>> {
1559 self.extension::<OffchainWorkerExt>()
1560 .expect("network_state can be called only in the offchain worker context")
1561 .network_state()
1562 }
1563
1564 fn timestamp(&mut self) -> ReturnAs<Timestamp, u64> {
1566 self.extension::<OffchainWorkerExt>()
1567 .expect("timestamp can be called only in the offchain worker context")
1568 .timestamp()
1569 }
1570
1571 fn sleep_until(&mut self, deadline: PassAs<Timestamp, u64>) {
1573 self.extension::<OffchainWorkerExt>()
1574 .expect("sleep_until can be called only in the offchain worker context")
1575 .sleep_until(deadline)
1576 }
1577
1578 fn random_seed(&mut self) -> AllocateAndReturnPointer<[u8; 32], 32> {
1583 self.extension::<OffchainWorkerExt>()
1584 .expect("random_seed can be called only in the offchain worker context")
1585 .random_seed()
1586 }
1587
1588 fn local_storage_set(
1593 &mut self,
1594 kind: PassAs<StorageKind, u32>,
1595 key: PassFatPointerAndRead<&[u8]>,
1596 value: PassFatPointerAndRead<&[u8]>,
1597 ) {
1598 self.extension::<OffchainDbExt>()
1599 .expect(
1600 "local_storage_set can be called only in the offchain call context with
1601 OffchainDb extension",
1602 )
1603 .local_storage_set(kind, key, value)
1604 }
1605
1606 fn local_storage_clear(
1611 &mut self,
1612 kind: PassAs<StorageKind, u32>,
1613 key: PassFatPointerAndRead<&[u8]>,
1614 ) {
1615 self.extension::<OffchainDbExt>()
1616 .expect(
1617 "local_storage_clear can be called only in the offchain call context with
1618 OffchainDb extension",
1619 )
1620 .local_storage_clear(kind, key)
1621 }
1622
1623 fn local_storage_compare_and_set(
1633 &mut self,
1634 kind: PassAs<StorageKind, u32>,
1635 key: PassFatPointerAndRead<&[u8]>,
1636 old_value: PassFatPointerAndDecode<Option<Vec<u8>>>,
1637 new_value: PassFatPointerAndRead<&[u8]>,
1638 ) -> bool {
1639 self.extension::<OffchainDbExt>()
1640 .expect(
1641 "local_storage_compare_and_set can be called only in the offchain call context
1642 with OffchainDb extension",
1643 )
1644 .local_storage_compare_and_set(kind, key, old_value.as_deref(), new_value)
1645 }
1646
1647 fn local_storage_get(
1653 &mut self,
1654 kind: PassAs<StorageKind, u32>,
1655 key: PassFatPointerAndRead<&[u8]>,
1656 ) -> AllocateAndReturnByCodec<Option<Vec<u8>>> {
1657 self.extension::<OffchainDbExt>()
1658 .expect(
1659 "local_storage_get can be called only in the offchain call context with
1660 OffchainDb extension",
1661 )
1662 .local_storage_get(kind, key)
1663 }
1664
1665 fn http_request_start(
1670 &mut self,
1671 method: PassFatPointerAndRead<&str>,
1672 uri: PassFatPointerAndRead<&str>,
1673 meta: PassFatPointerAndRead<&[u8]>,
1674 ) -> AllocateAndReturnByCodec<Result<HttpRequestId, ()>> {
1675 self.extension::<OffchainWorkerExt>()
1676 .expect("http_request_start can be called only in the offchain worker context")
1677 .http_request_start(method, uri, meta)
1678 }
1679
1680 fn http_request_add_header(
1682 &mut self,
1683 request_id: PassAs<HttpRequestId, u16>,
1684 name: PassFatPointerAndRead<&str>,
1685 value: PassFatPointerAndRead<&str>,
1686 ) -> AllocateAndReturnByCodec<Result<(), ()>> {
1687 self.extension::<OffchainWorkerExt>()
1688 .expect("http_request_add_header can be called only in the offchain worker context")
1689 .http_request_add_header(request_id, name, value)
1690 }
1691
1692 fn http_request_write_body(
1699 &mut self,
1700 request_id: PassAs<HttpRequestId, u16>,
1701 chunk: PassFatPointerAndRead<&[u8]>,
1702 deadline: PassFatPointerAndDecode<Option<Timestamp>>,
1703 ) -> AllocateAndReturnByCodec<Result<(), HttpError>> {
1704 self.extension::<OffchainWorkerExt>()
1705 .expect("http_request_write_body can be called only in the offchain worker context")
1706 .http_request_write_body(request_id, chunk, deadline)
1707 }
1708
1709 fn http_response_wait(
1717 &mut self,
1718 ids: PassFatPointerAndDecodeSlice<&[HttpRequestId]>,
1719 deadline: PassFatPointerAndDecode<Option<Timestamp>>,
1720 ) -> AllocateAndReturnByCodec<Vec<HttpRequestStatus>> {
1721 self.extension::<OffchainWorkerExt>()
1722 .expect("http_response_wait can be called only in the offchain worker context")
1723 .http_response_wait(ids, deadline)
1724 }
1725
1726 fn http_response_headers(
1731 &mut self,
1732 request_id: PassAs<HttpRequestId, u16>,
1733 ) -> AllocateAndReturnByCodec<Vec<(Vec<u8>, Vec<u8>)>> {
1734 self.extension::<OffchainWorkerExt>()
1735 .expect("http_response_headers can be called only in the offchain worker context")
1736 .http_response_headers(request_id)
1737 }
1738
1739 fn http_response_read_body(
1748 &mut self,
1749 request_id: PassAs<HttpRequestId, u16>,
1750 buffer: PassFatPointerAndReadWrite<&mut [u8]>,
1751 deadline: PassFatPointerAndDecode<Option<Timestamp>>,
1752 ) -> AllocateAndReturnByCodec<Result<u32, HttpError>> {
1753 self.extension::<OffchainWorkerExt>()
1754 .expect("http_response_read_body can be called only in the offchain worker context")
1755 .http_response_read_body(request_id, buffer, deadline)
1756 .map(|r| r as u32)
1757 }
1758
1759 fn set_authorized_nodes(
1761 &mut self,
1762 nodes: PassFatPointerAndDecode<Vec<OpaquePeerId>>,
1763 authorized_only: bool,
1764 ) {
1765 self.extension::<OffchainWorkerExt>()
1766 .expect("set_authorized_nodes can be called only in the offchain worker context")
1767 .set_authorized_nodes(nodes, authorized_only)
1768 }
1769}
1770
1771#[runtime_interface(wasm_only)]
1773pub trait Allocator {
1774 fn malloc(&mut self, size: u32) -> Pointer<u8> {
1776 self.allocate_memory(size).expect("Failed to allocate memory")
1777 }
1778
1779 fn free(&mut self, ptr: Pointer<u8>) {
1781 self.deallocate_memory(ptr).expect("Failed to deallocate memory")
1782 }
1783}
1784
1785#[runtime_interface(wasm_only)]
1788pub trait PanicHandler {
1789 #[trap_on_return]
1791 fn abort_on_panic(&mut self, message: PassFatPointerAndRead<&str>) {
1792 self.register_panic_error_message(message);
1793 }
1794}
1795
1796#[runtime_interface]
1798pub trait Logging {
1799 fn log(
1806 level: PassAs<RuntimeInterfaceLogLevel, u8>,
1807 target: PassFatPointerAndRead<&str>,
1808 message: PassFatPointerAndRead<&[u8]>,
1809 ) {
1810 if let Ok(message) = core::str::from_utf8(message) {
1811 log::log!(target: target, log::Level::from(level), "{}", message)
1812 }
1813 }
1814
1815 fn max_level() -> ReturnAs<LogLevelFilter, u8> {
1817 log::max_level().into()
1818 }
1819}
1820
1821#[runtime_interface(wasm_only, no_tracing)]
1824pub trait WasmTracing {
1825 fn enabled(&mut self, metadata: PassFatPointerAndDecode<sp_tracing::WasmMetadata>) -> bool {
1835 let metadata: &tracing_core::metadata::Metadata<'static> = (&metadata).into();
1836 tracing::dispatcher::get_default(|d| d.enabled(metadata))
1837 }
1838
1839 fn enter_span(
1846 &mut self,
1847 span: PassFatPointerAndDecode<sp_tracing::WasmEntryAttributes>,
1848 ) -> u64 {
1849 let span: tracing::Span = span.into();
1850 match span.id() {
1851 Some(id) => tracing::dispatcher::get_default(|d| {
1852 let final_id = d.clone_span(&id);
1855 d.enter(&final_id);
1856 final_id.into_u64()
1857 }),
1858 _ => 0,
1859 }
1860 }
1861
1862 fn event(&mut self, event: PassFatPointerAndDecode<sp_tracing::WasmEntryAttributes>) {
1864 event.emit();
1865 }
1866
1867 fn exit(&mut self, span: u64) {
1870 tracing::dispatcher::get_default(|d| {
1871 let id = tracing_core::span::Id::from_u64(span);
1872 d.exit(&id);
1873 });
1874 }
1875}
1876
1877#[cfg(all(substrate_runtime, feature = "with-tracing"))]
1878mod tracing_setup {
1879 use super::wasm_tracing;
1880 use core::sync::atomic::{AtomicBool, Ordering};
1881 use tracing_core::{
1882 dispatcher::{set_global_default, Dispatch},
1883 span::{Attributes, Id, Record},
1884 Event, Metadata,
1885 };
1886
1887 static TRACING_SET: AtomicBool = AtomicBool::new(false);
1888
1889 struct PassingTracingSubscriber;
1892
1893 impl tracing_core::Subscriber for PassingTracingSubscriber {
1894 fn enabled(&self, metadata: &Metadata<'_>) -> bool {
1895 wasm_tracing::enabled(metadata.into())
1896 }
1897 fn new_span(&self, attrs: &Attributes<'_>) -> Id {
1898 Id::from_u64(wasm_tracing::enter_span(attrs.into()))
1899 }
1900 fn enter(&self, _: &Id) {
1901 }
1903 fn record(&self, _: &Id, _: &Record<'_>) {
1906 unimplemented! {} }
1908 fn record_follows_from(&self, _: &Id, _: &Id) {
1911 unimplemented! {} }
1913 fn event(&self, event: &Event<'_>) {
1914 wasm_tracing::event(event.into())
1915 }
1916 fn exit(&self, span: &Id) {
1917 wasm_tracing::exit(span.into_u64())
1918 }
1919 }
1920
1921 pub fn init_tracing() {
1925 if TRACING_SET.load(Ordering::Relaxed) == false {
1926 set_global_default(Dispatch::new(PassingTracingSubscriber {}))
1927 .expect("We only ever call this once");
1928 TRACING_SET.store(true, Ordering::Relaxed);
1929 }
1930 }
1931}
1932
1933#[cfg(not(all(substrate_runtime, feature = "with-tracing")))]
1934mod tracing_setup {
1935 pub fn init_tracing() {}
1938}
1939
1940pub use tracing_setup::init_tracing;
1941
1942pub fn unreachable() -> ! {
1947 #[cfg(target_family = "wasm")]
1948 {
1949 core::arch::wasm32::unreachable();
1950 }
1951
1952 #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
1953 unsafe {
1954 core::arch::asm!("unimp", options(noreturn));
1955 }
1956
1957 #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64", target_family = "wasm")))]
1958 unreachable!();
1959}
1960
1961#[cfg(all(not(feature = "disable_panic_handler"), substrate_runtime))]
1963#[panic_handler]
1964pub fn panic(info: &core::panic::PanicInfo) -> ! {
1965 let message = alloc::format!("{}", info);
1966 #[cfg(feature = "improved_panic_error_reporting")]
1967 {
1968 panic_handler::abort_on_panic(&message);
1969 }
1970 #[cfg(not(feature = "improved_panic_error_reporting"))]
1971 {
1972 logging::log(RuntimeInterfaceLogLevel::Error, "runtime", message.as_bytes());
1973 unreachable();
1974 }
1975}
1976
1977#[cfg(all(not(feature = "disable_oom"), enable_alloc_error_handler))]
1979#[alloc_error_handler]
1980pub fn oom(_: core::alloc::Layout) -> ! {
1981 #[cfg(feature = "improved_panic_error_reporting")]
1982 {
1983 panic_handler::abort_on_panic("Runtime memory exhausted.");
1984 }
1985 #[cfg(not(feature = "improved_panic_error_reporting"))]
1986 {
1987 logging::log(
1988 RuntimeInterfaceLogLevel::Error,
1989 "runtime",
1990 b"Runtime memory exhausted. Aborting",
1991 );
1992 unreachable();
1993 }
1994}
1995
1996#[cfg(feature = "std")] pub type TestExternalities = sp_state_machine::TestExternalities<sp_core::Blake2Hasher>;
1999
2000#[docify::export]
2004#[cfg(not(substrate_runtime))]
2005pub type SubstrateHostFunctions = (
2006 storage::HostFunctions,
2007 default_child_storage::HostFunctions,
2008 misc::HostFunctions,
2009 wasm_tracing::HostFunctions,
2010 offchain::HostFunctions,
2011 crypto::HostFunctions,
2012 hashing::HostFunctions,
2013 allocator::HostFunctions,
2014 panic_handler::HostFunctions,
2015 logging::HostFunctions,
2016 crate::trie::HostFunctions,
2017 offchain_index::HostFunctions,
2018 transaction_index::HostFunctions,
2019);
2020
2021#[cfg(test)]
2022mod tests {
2023 use super::*;
2024 use sp_core::{crypto::UncheckedInto, map, storage::Storage};
2025 use sp_state_machine::BasicExternalities;
2026
2027 #[test]
2028 fn storage_works() {
2029 let mut t = BasicExternalities::default();
2030 t.execute_with(|| {
2031 assert_eq!(storage::get(b"hello"), None);
2032 storage::set(b"hello", b"world");
2033 assert_eq!(storage::get(b"hello"), Some(b"world".to_vec().into()));
2034 assert_eq!(storage::get(b"foo"), None);
2035 storage::set(b"foo", &[1, 2, 3][..]);
2036 });
2037
2038 t = BasicExternalities::new(Storage {
2039 top: map![b"foo".to_vec() => b"bar".to_vec()],
2040 children_default: map![],
2041 });
2042
2043 t.execute_with(|| {
2044 assert_eq!(storage::get(b"hello"), None);
2045 assert_eq!(storage::get(b"foo"), Some(b"bar".to_vec().into()));
2046 });
2047
2048 let value = vec![7u8; 35];
2049 let storage =
2050 Storage { top: map![b"foo00".to_vec() => value.clone()], children_default: map![] };
2051 t = BasicExternalities::new(storage);
2052
2053 t.execute_with(|| {
2054 assert_eq!(storage::get(b"hello"), None);
2055 assert_eq!(storage::get(b"foo00"), Some(value.clone().into()));
2056 });
2057 }
2058
2059 #[test]
2060 fn read_storage_works() {
2061 let value = b"\x0b\0\0\0Hello world".to_vec();
2062 let mut t = BasicExternalities::new(Storage {
2063 top: map![b":test".to_vec() => value.clone()],
2064 children_default: map![],
2065 });
2066
2067 t.execute_with(|| {
2068 let mut v = [0u8; 4];
2069 assert_eq!(storage::read(b":test", &mut v[..], 0).unwrap(), value.len() as u32);
2070 assert_eq!(v, [11u8, 0, 0, 0]);
2071 let mut w = [0u8; 11];
2072 assert_eq!(storage::read(b":test", &mut w[..], 4).unwrap(), value.len() as u32 - 4);
2073 assert_eq!(&w, b"Hello world");
2074 });
2075 }
2076
2077 #[test]
2078 fn clear_prefix_works() {
2079 let mut t = BasicExternalities::new(Storage {
2080 top: map![
2081 b":a".to_vec() => b"\x0b\0\0\0Hello world".to_vec(),
2082 b":abcd".to_vec() => b"\x0b\0\0\0Hello world".to_vec(),
2083 b":abc".to_vec() => b"\x0b\0\0\0Hello world".to_vec(),
2084 b":abdd".to_vec() => b"\x0b\0\0\0Hello world".to_vec()
2085 ],
2086 children_default: map![],
2087 });
2088
2089 t.execute_with(|| {
2090 assert!(matches!(
2096 storage::clear_prefix(b":abc", None),
2097 KillStorageResult::AllRemoved(2),
2098 ));
2099
2100 assert!(storage::get(b":a").is_some());
2101 assert!(storage::get(b":abdd").is_some());
2102 assert!(storage::get(b":abcd").is_none());
2103 assert!(storage::get(b":abc").is_none());
2104
2105 assert!(matches!(
2111 storage::clear_prefix(b":abc", None),
2112 KillStorageResult::AllRemoved(0),
2113 ));
2114 });
2115 }
2116
2117 fn zero_ed_pub() -> ed25519::Public {
2118 [0u8; 32].unchecked_into()
2119 }
2120
2121 fn zero_ed_sig() -> ed25519::Signature {
2122 ed25519::Signature::from_raw([0u8; 64])
2123 }
2124
2125 #[test]
2126 fn use_dalek_ext_works() {
2127 let mut ext = BasicExternalities::default();
2128 ext.register_extension(UseDalekExt::default());
2129
2130 ext.execute_with(|| {
2132 assert!(!crypto::ed25519_verify(&zero_ed_sig(), &Vec::new(), &zero_ed_pub()));
2133 });
2134
2135 BasicExternalities::default().execute_with(|| {
2137 assert!(crypto::ed25519_verify(&zero_ed_sig(), &Vec::new(), &zero_ed_pub()));
2138 })
2139 }
2140
2141 #[test]
2142 fn dalek_should_not_panic_on_invalid_signature() {
2143 let mut ext = BasicExternalities::default();
2144 ext.register_extension(UseDalekExt::default());
2145
2146 ext.execute_with(|| {
2147 let mut bytes = [0u8; 64];
2148 bytes[63] = 0b1110_0000;
2150
2151 assert!(!crypto::ed25519_verify(
2152 &ed25519::Signature::from_raw(bytes),
2153 &Vec::new(),
2154 &zero_ed_pub()
2155 ));
2156 });
2157 }
2158}