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(
1186 sig: PassPointerAndRead<&ecdsa::Signature, 65>,
1187 msg: PassFatPointerAndRead<&[u8]>,
1188 pub_key: PassPointerAndRead<&ecdsa::Public, 33>,
1189 ) -> bool {
1190 #[allow(deprecated)]
1191 ecdsa::Pair::verify_deprecated(sig, msg, pub_key)
1192 }
1193
1194 #[version(2)]
1202 fn ecdsa_verify(
1203 sig: PassPointerAndRead<&ecdsa::Signature, 65>,
1204 msg: PassFatPointerAndRead<&[u8]>,
1205 pub_key: PassPointerAndRead<&ecdsa::Public, 33>,
1206 ) -> bool {
1207 ecdsa::Pair::verify(sig, msg, pub_key)
1208 }
1209
1210 fn ecdsa_verify_prehashed(
1218 sig: PassPointerAndRead<&ecdsa::Signature, 65>,
1219 msg: PassPointerAndRead<&[u8; 32], 32>,
1220 pub_key: PassPointerAndRead<&ecdsa::Public, 33>,
1221 ) -> bool {
1222 ecdsa::Pair::verify_prehashed(sig, msg, pub_key)
1223 }
1224
1225 #[version(1, register_only)]
1239 fn ecdsa_batch_verify(
1240 &mut self,
1241 sig: PassPointerAndRead<&ecdsa::Signature, 65>,
1242 msg: PassFatPointerAndRead<&[u8]>,
1243 pub_key: PassPointerAndRead<&ecdsa::Public, 33>,
1244 ) -> bool {
1245 let res = ecdsa_verify(sig, msg, pub_key);
1246
1247 if let Some(ext) = self.extension::<VerificationExtDeprecated>() {
1248 ext.0 &= res;
1249 }
1250
1251 res
1252 }
1253
1254 fn secp256k1_ecdsa_recover(
1267 sig: PassPointerAndRead<&[u8; 65], 65>,
1268 msg: PassPointerAndRead<&[u8; 32], 32>,
1269 ) -> AllocateAndReturnByCodec<Result<[u8; 64], EcdsaVerifyError>> {
1270 let rid = libsecp256k1::RecoveryId::parse(
1271 if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8,
1272 )
1273 .map_err(|_| EcdsaVerifyError::BadV)?;
1274 let sig = libsecp256k1::Signature::parse_overflowing_slice(&sig[..64])
1275 .map_err(|_| EcdsaVerifyError::BadRS)?;
1276 let msg = libsecp256k1::Message::parse(msg);
1277 let pubkey =
1278 libsecp256k1::recover(&msg, &sig, &rid).map_err(|_| EcdsaVerifyError::BadSignature)?;
1279 let mut res = [0u8; 64];
1280 res.copy_from_slice(&pubkey.serialize()[1..65]);
1281 Ok(res)
1282 }
1283
1284 #[version(2)]
1296 fn secp256k1_ecdsa_recover(
1297 sig: PassPointerAndRead<&[u8; 65], 65>,
1298 msg: PassPointerAndRead<&[u8; 32], 32>,
1299 ) -> AllocateAndReturnByCodec<Result<[u8; 64], EcdsaVerifyError>> {
1300 let rid = RecoveryId::from_i32(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as i32)
1301 .map_err(|_| EcdsaVerifyError::BadV)?;
1302 let sig = RecoverableSignature::from_compact(&sig[..64], rid)
1303 .map_err(|_| EcdsaVerifyError::BadRS)?;
1304 let msg = Message::from_digest_slice(msg).expect("Message is 32 bytes; qed");
1305 #[cfg(feature = "std")]
1306 let ctx = secp256k1::SECP256K1;
1307 #[cfg(not(feature = "std"))]
1308 let ctx = secp256k1::Secp256k1::<secp256k1::VerifyOnly>::gen_new();
1309 let pubkey = ctx.recover_ecdsa(&msg, &sig).map_err(|_| EcdsaVerifyError::BadSignature)?;
1310 let mut res = [0u8; 64];
1311 res.copy_from_slice(&pubkey.serialize_uncompressed()[1..]);
1312 Ok(res)
1313 }
1314
1315 fn secp256k1_ecdsa_recover_compressed(
1326 sig: PassPointerAndRead<&[u8; 65], 65>,
1327 msg: PassPointerAndRead<&[u8; 32], 32>,
1328 ) -> AllocateAndReturnByCodec<Result<[u8; 33], EcdsaVerifyError>> {
1329 let rid = libsecp256k1::RecoveryId::parse(
1330 if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8,
1331 )
1332 .map_err(|_| EcdsaVerifyError::BadV)?;
1333 let sig = libsecp256k1::Signature::parse_overflowing_slice(&sig[0..64])
1334 .map_err(|_| EcdsaVerifyError::BadRS)?;
1335 let msg = libsecp256k1::Message::parse(msg);
1336 let pubkey =
1337 libsecp256k1::recover(&msg, &sig, &rid).map_err(|_| EcdsaVerifyError::BadSignature)?;
1338 Ok(pubkey.serialize_compressed())
1339 }
1340
1341 #[version(2)]
1352 fn secp256k1_ecdsa_recover_compressed(
1353 sig: PassPointerAndRead<&[u8; 65], 65>,
1354 msg: PassPointerAndRead<&[u8; 32], 32>,
1355 ) -> AllocateAndReturnByCodec<Result<[u8; 33], EcdsaVerifyError>> {
1356 let rid = RecoveryId::from_i32(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as i32)
1357 .map_err(|_| EcdsaVerifyError::BadV)?;
1358 let sig = RecoverableSignature::from_compact(&sig[..64], rid)
1359 .map_err(|_| EcdsaVerifyError::BadRS)?;
1360 let msg = Message::from_digest_slice(msg).expect("Message is 32 bytes; qed");
1361 #[cfg(feature = "std")]
1362 let ctx = secp256k1::SECP256K1;
1363 #[cfg(not(feature = "std"))]
1364 let ctx = secp256k1::Secp256k1::<secp256k1::VerifyOnly>::gen_new();
1365 let pubkey = ctx.recover_ecdsa(&msg, &sig).map_err(|_| EcdsaVerifyError::BadSignature)?;
1366 Ok(pubkey.serialize())
1367 }
1368
1369 #[cfg(feature = "bls-experimental")]
1376 fn bls381_generate(
1377 &mut self,
1378 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1379 seed: PassFatPointerAndDecode<Option<Vec<u8>>>,
1380 ) -> AllocateAndReturnPointer<bls381::Public, 144> {
1381 let seed = seed.as_ref().map(|s| core::str::from_utf8(s).expect("Seed is valid utf8!"));
1382 self.extension::<KeystoreExt>()
1383 .expect("No `keystore` associated for the current context!")
1384 .bls381_generate_new(id, seed)
1385 .expect("`bls381_generate` failed")
1386 }
1387
1388 #[cfg(feature = "bls-experimental")]
1393 fn bls381_generate_proof_of_possession(
1394 &mut self,
1395 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1396 pub_key: PassPointerAndRead<&bls381::Public, 144>,
1397 owner: PassFatPointerAndRead<&[u8]>,
1398 ) -> AllocateAndReturnByCodec<Option<bls381::ProofOfPossession>> {
1399 self.extension::<KeystoreExt>()
1400 .expect("No `keystore` associated for the current context!")
1401 .bls381_generate_proof_of_possession(id, pub_key, owner)
1402 .ok()
1403 .flatten()
1404 }
1405
1406 #[cfg(feature = "bls-experimental")]
1413 fn ecdsa_bls381_generate(
1414 &mut self,
1415 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1416 seed: PassFatPointerAndDecode<Option<Vec<u8>>>,
1417 ) -> AllocateAndReturnPointer<ecdsa_bls381::Public, { 144 + 33 }> {
1418 let seed = seed.as_ref().map(|s| core::str::from_utf8(s).expect("Seed is valid utf8!"));
1419 self.extension::<KeystoreExt>()
1420 .expect("No `keystore` associated for the current context!")
1421 .ecdsa_bls381_generate_new(id, seed)
1422 .expect("`ecdsa_bls381_generate` failed")
1423 }
1424
1425 #[cfg(feature = "bandersnatch-experimental")]
1432 fn bandersnatch_generate(
1433 &mut self,
1434 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1435 seed: PassFatPointerAndDecode<Option<Vec<u8>>>,
1436 ) -> AllocateAndReturnPointer<bandersnatch::Public, 32> {
1437 let seed = seed.as_ref().map(|s| core::str::from_utf8(s).expect("Seed is valid utf8!"));
1438 self.extension::<KeystoreExt>()
1439 .expect("No `keystore` associated for the current context!")
1440 .bandersnatch_generate_new(id, seed)
1441 .expect("`bandernatch_generate` failed")
1442 }
1443
1444 #[cfg(feature = "bandersnatch-experimental")]
1449 fn bandersnatch_sign(
1450 &mut self,
1451 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1452 pub_key: PassPointerAndRead<&bandersnatch::Public, 32>,
1453 msg: PassFatPointerAndRead<&[u8]>,
1454 ) -> AllocateAndReturnByCodec<Option<bandersnatch::Signature>> {
1455 self.extension::<KeystoreExt>()
1456 .expect("No `keystore` associated for the current context!")
1457 .bandersnatch_sign(id, pub_key, msg)
1458 .ok()
1459 .flatten()
1460 }
1461}
1462
1463#[runtime_interface]
1465pub trait Hashing {
1466 fn keccak_256(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnPointer<[u8; 32], 32> {
1468 sp_crypto_hashing::keccak_256(data)
1469 }
1470
1471 fn keccak_512(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnPointer<[u8; 64], 64> {
1473 sp_crypto_hashing::keccak_512(data)
1474 }
1475
1476 fn sha2_256(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnPointer<[u8; 32], 32> {
1478 sp_crypto_hashing::sha2_256(data)
1479 }
1480
1481 fn blake2_128(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnPointer<[u8; 16], 16> {
1483 sp_crypto_hashing::blake2_128(data)
1484 }
1485
1486 fn blake2_256(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnPointer<[u8; 32], 32> {
1488 sp_crypto_hashing::blake2_256(data)
1489 }
1490
1491 fn twox_256(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnPointer<[u8; 32], 32> {
1493 sp_crypto_hashing::twox_256(data)
1494 }
1495
1496 fn twox_128(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnPointer<[u8; 16], 16> {
1498 sp_crypto_hashing::twox_128(data)
1499 }
1500
1501 fn twox_64(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnPointer<[u8; 8], 8> {
1503 sp_crypto_hashing::twox_64(data)
1504 }
1505}
1506
1507#[runtime_interface]
1509pub trait TransactionIndex {
1510 fn index(
1512 &mut self,
1513 extrinsic: u32,
1514 size: u32,
1515 context_hash: PassPointerAndReadCopy<[u8; 32], 32>,
1516 ) {
1517 self.storage_index_transaction(extrinsic, &context_hash, size);
1518 }
1519
1520 fn renew(&mut self, extrinsic: u32, context_hash: PassPointerAndReadCopy<[u8; 32], 32>) {
1523 self.storage_renew_transaction_index(extrinsic, &context_hash);
1524 }
1525}
1526
1527#[runtime_interface]
1529pub trait OffchainIndex {
1530 fn set(&mut self, key: PassFatPointerAndRead<&[u8]>, value: PassFatPointerAndRead<&[u8]>) {
1532 self.set_offchain_storage(key, Some(value));
1533 }
1534
1535 fn clear(&mut self, key: PassFatPointerAndRead<&[u8]>) {
1537 self.set_offchain_storage(key, None);
1538 }
1539}
1540
1541#[cfg(not(substrate_runtime))]
1542sp_externalities::decl_extension! {
1543 struct VerificationExtDeprecated(bool);
1547}
1548
1549#[runtime_interface]
1553pub trait Offchain {
1554 fn is_validator(&mut self) -> bool {
1559 self.extension::<OffchainWorkerExt>()
1560 .expect("is_validator can be called only in the offchain worker context")
1561 .is_validator()
1562 }
1563
1564 fn submit_transaction(
1568 &mut self,
1569 data: PassFatPointerAndRead<Vec<u8>>,
1570 ) -> AllocateAndReturnByCodec<Result<(), ()>> {
1571 self.extension::<TransactionPoolExt>()
1572 .expect(
1573 "submit_transaction can be called only in the offchain call context with
1574 TransactionPool capabilities enabled",
1575 )
1576 .submit_transaction(data)
1577 }
1578
1579 fn network_state(&mut self) -> AllocateAndReturnByCodec<Result<OpaqueNetworkState, ()>> {
1581 self.extension::<OffchainWorkerExt>()
1582 .expect("network_state can be called only in the offchain worker context")
1583 .network_state()
1584 }
1585
1586 fn timestamp(&mut self) -> ReturnAs<Timestamp, u64> {
1588 self.extension::<OffchainWorkerExt>()
1589 .expect("timestamp can be called only in the offchain worker context")
1590 .timestamp()
1591 }
1592
1593 fn sleep_until(&mut self, deadline: PassAs<Timestamp, u64>) {
1595 self.extension::<OffchainWorkerExt>()
1596 .expect("sleep_until can be called only in the offchain worker context")
1597 .sleep_until(deadline)
1598 }
1599
1600 fn random_seed(&mut self) -> AllocateAndReturnPointer<[u8; 32], 32> {
1605 self.extension::<OffchainWorkerExt>()
1606 .expect("random_seed can be called only in the offchain worker context")
1607 .random_seed()
1608 }
1609
1610 fn local_storage_set(
1615 &mut self,
1616 kind: PassAs<StorageKind, u32>,
1617 key: PassFatPointerAndRead<&[u8]>,
1618 value: PassFatPointerAndRead<&[u8]>,
1619 ) {
1620 self.extension::<OffchainDbExt>()
1621 .expect(
1622 "local_storage_set can be called only in the offchain call context with
1623 OffchainDb extension",
1624 )
1625 .local_storage_set(kind, key, value)
1626 }
1627
1628 fn local_storage_clear(
1633 &mut self,
1634 kind: PassAs<StorageKind, u32>,
1635 key: PassFatPointerAndRead<&[u8]>,
1636 ) {
1637 self.extension::<OffchainDbExt>()
1638 .expect(
1639 "local_storage_clear can be called only in the offchain call context with
1640 OffchainDb extension",
1641 )
1642 .local_storage_clear(kind, key)
1643 }
1644
1645 fn local_storage_compare_and_set(
1655 &mut self,
1656 kind: PassAs<StorageKind, u32>,
1657 key: PassFatPointerAndRead<&[u8]>,
1658 old_value: PassFatPointerAndDecode<Option<Vec<u8>>>,
1659 new_value: PassFatPointerAndRead<&[u8]>,
1660 ) -> bool {
1661 self.extension::<OffchainDbExt>()
1662 .expect(
1663 "local_storage_compare_and_set can be called only in the offchain call context
1664 with OffchainDb extension",
1665 )
1666 .local_storage_compare_and_set(kind, key, old_value.as_deref(), new_value)
1667 }
1668
1669 fn local_storage_get(
1675 &mut self,
1676 kind: PassAs<StorageKind, u32>,
1677 key: PassFatPointerAndRead<&[u8]>,
1678 ) -> AllocateAndReturnByCodec<Option<Vec<u8>>> {
1679 self.extension::<OffchainDbExt>()
1680 .expect(
1681 "local_storage_get can be called only in the offchain call context with
1682 OffchainDb extension",
1683 )
1684 .local_storage_get(kind, key)
1685 }
1686
1687 fn http_request_start(
1692 &mut self,
1693 method: PassFatPointerAndRead<&str>,
1694 uri: PassFatPointerAndRead<&str>,
1695 meta: PassFatPointerAndRead<&[u8]>,
1696 ) -> AllocateAndReturnByCodec<Result<HttpRequestId, ()>> {
1697 self.extension::<OffchainWorkerExt>()
1698 .expect("http_request_start can be called only in the offchain worker context")
1699 .http_request_start(method, uri, meta)
1700 }
1701
1702 fn http_request_add_header(
1704 &mut self,
1705 request_id: PassAs<HttpRequestId, u16>,
1706 name: PassFatPointerAndRead<&str>,
1707 value: PassFatPointerAndRead<&str>,
1708 ) -> AllocateAndReturnByCodec<Result<(), ()>> {
1709 self.extension::<OffchainWorkerExt>()
1710 .expect("http_request_add_header can be called only in the offchain worker context")
1711 .http_request_add_header(request_id, name, value)
1712 }
1713
1714 fn http_request_write_body(
1721 &mut self,
1722 request_id: PassAs<HttpRequestId, u16>,
1723 chunk: PassFatPointerAndRead<&[u8]>,
1724 deadline: PassFatPointerAndDecode<Option<Timestamp>>,
1725 ) -> AllocateAndReturnByCodec<Result<(), HttpError>> {
1726 self.extension::<OffchainWorkerExt>()
1727 .expect("http_request_write_body can be called only in the offchain worker context")
1728 .http_request_write_body(request_id, chunk, deadline)
1729 }
1730
1731 fn http_response_wait(
1739 &mut self,
1740 ids: PassFatPointerAndDecodeSlice<&[HttpRequestId]>,
1741 deadline: PassFatPointerAndDecode<Option<Timestamp>>,
1742 ) -> AllocateAndReturnByCodec<Vec<HttpRequestStatus>> {
1743 self.extension::<OffchainWorkerExt>()
1744 .expect("http_response_wait can be called only in the offchain worker context")
1745 .http_response_wait(ids, deadline)
1746 }
1747
1748 fn http_response_headers(
1753 &mut self,
1754 request_id: PassAs<HttpRequestId, u16>,
1755 ) -> AllocateAndReturnByCodec<Vec<(Vec<u8>, Vec<u8>)>> {
1756 self.extension::<OffchainWorkerExt>()
1757 .expect("http_response_headers can be called only in the offchain worker context")
1758 .http_response_headers(request_id)
1759 }
1760
1761 fn http_response_read_body(
1770 &mut self,
1771 request_id: PassAs<HttpRequestId, u16>,
1772 buffer: PassFatPointerAndReadWrite<&mut [u8]>,
1773 deadline: PassFatPointerAndDecode<Option<Timestamp>>,
1774 ) -> AllocateAndReturnByCodec<Result<u32, HttpError>> {
1775 self.extension::<OffchainWorkerExt>()
1776 .expect("http_response_read_body can be called only in the offchain worker context")
1777 .http_response_read_body(request_id, buffer, deadline)
1778 .map(|r| r as u32)
1779 }
1780
1781 fn set_authorized_nodes(
1783 &mut self,
1784 nodes: PassFatPointerAndDecode<Vec<OpaquePeerId>>,
1785 authorized_only: bool,
1786 ) {
1787 self.extension::<OffchainWorkerExt>()
1788 .expect("set_authorized_nodes can be called only in the offchain worker context")
1789 .set_authorized_nodes(nodes, authorized_only)
1790 }
1791}
1792
1793#[runtime_interface(wasm_only)]
1795pub trait Allocator {
1796 fn malloc(&mut self, size: u32) -> Pointer<u8> {
1798 self.allocate_memory(size).expect("Failed to allocate memory")
1799 }
1800
1801 fn free(&mut self, ptr: Pointer<u8>) {
1803 self.deallocate_memory(ptr).expect("Failed to deallocate memory")
1804 }
1805}
1806
1807#[runtime_interface(wasm_only)]
1810pub trait PanicHandler {
1811 #[trap_on_return]
1813 fn abort_on_panic(&mut self, message: PassFatPointerAndRead<&str>) {
1814 self.register_panic_error_message(message);
1815 }
1816}
1817
1818#[runtime_interface]
1820pub trait Logging {
1821 fn log(
1828 level: PassAs<RuntimeInterfaceLogLevel, u8>,
1829 target: PassFatPointerAndRead<&str>,
1830 message: PassFatPointerAndRead<&[u8]>,
1831 ) {
1832 if let Ok(message) = core::str::from_utf8(message) {
1833 log::log!(target: target, log::Level::from(level), "{}", message)
1834 }
1835 }
1836
1837 fn max_level() -> ReturnAs<LogLevelFilter, u8> {
1839 log::max_level().into()
1840 }
1841}
1842
1843#[runtime_interface(wasm_only, no_tracing)]
1846pub trait WasmTracing {
1847 fn enabled(&mut self, metadata: PassFatPointerAndDecode<sp_tracing::WasmMetadata>) -> bool {
1857 let metadata: &tracing_core::metadata::Metadata<'static> = (&metadata).into();
1858 tracing::dispatcher::get_default(|d| d.enabled(metadata))
1859 }
1860
1861 fn enter_span(
1868 &mut self,
1869 span: PassFatPointerAndDecode<sp_tracing::WasmEntryAttributes>,
1870 ) -> u64 {
1871 let span: tracing::Span = span.into();
1872 match span.id() {
1873 Some(id) => tracing::dispatcher::get_default(|d| {
1874 let final_id = d.clone_span(&id);
1877 d.enter(&final_id);
1878 final_id.into_u64()
1879 }),
1880 _ => 0,
1881 }
1882 }
1883
1884 fn event(&mut self, event: PassFatPointerAndDecode<sp_tracing::WasmEntryAttributes>) {
1886 event.emit();
1887 }
1888
1889 fn exit(&mut self, span: u64) {
1892 tracing::dispatcher::get_default(|d| {
1893 let id = tracing_core::span::Id::from_u64(span);
1894 d.exit(&id);
1895 });
1896 }
1897}
1898
1899#[cfg(all(substrate_runtime, feature = "with-tracing"))]
1900mod tracing_setup {
1901 use super::wasm_tracing;
1902 use core::sync::atomic::{AtomicBool, Ordering};
1903 use tracing_core::{
1904 dispatcher::{set_global_default, Dispatch},
1905 span::{Attributes, Id, Record},
1906 Event, Metadata,
1907 };
1908
1909 static TRACING_SET: AtomicBool = AtomicBool::new(false);
1910
1911 struct PassingTracingSubscriber;
1914
1915 impl tracing_core::Subscriber for PassingTracingSubscriber {
1916 fn enabled(&self, metadata: &Metadata<'_>) -> bool {
1917 wasm_tracing::enabled(metadata.into())
1918 }
1919 fn new_span(&self, attrs: &Attributes<'_>) -> Id {
1920 Id::from_u64(wasm_tracing::enter_span(attrs.into()))
1921 }
1922 fn enter(&self, _: &Id) {
1923 }
1925 fn record(&self, _: &Id, _: &Record<'_>) {
1928 unimplemented! {} }
1930 fn record_follows_from(&self, _: &Id, _: &Id) {
1933 unimplemented! {} }
1935 fn event(&self, event: &Event<'_>) {
1936 wasm_tracing::event(event.into())
1937 }
1938 fn exit(&self, span: &Id) {
1939 wasm_tracing::exit(span.into_u64())
1940 }
1941 }
1942
1943 pub fn init_tracing() {
1947 if TRACING_SET.load(Ordering::Relaxed) == false {
1948 set_global_default(Dispatch::new(PassingTracingSubscriber {}))
1949 .expect("We only ever call this once");
1950 TRACING_SET.store(true, Ordering::Relaxed);
1951 }
1952 }
1953}
1954
1955#[cfg(not(all(substrate_runtime, feature = "with-tracing")))]
1956mod tracing_setup {
1957 pub fn init_tracing() {}
1960}
1961
1962pub use tracing_setup::init_tracing;
1963
1964pub fn unreachable() -> ! {
1969 #[cfg(target_family = "wasm")]
1970 {
1971 core::arch::wasm32::unreachable();
1972 }
1973
1974 #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
1975 unsafe {
1976 core::arch::asm!("unimp", options(noreturn));
1977 }
1978
1979 #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64", target_family = "wasm")))]
1980 unreachable!();
1981}
1982
1983#[cfg(all(not(feature = "disable_panic_handler"), substrate_runtime))]
1985#[panic_handler]
1986pub fn panic(info: &core::panic::PanicInfo) -> ! {
1987 let message = alloc::format!("{}", info);
1988 #[cfg(feature = "improved_panic_error_reporting")]
1989 {
1990 panic_handler::abort_on_panic(&message);
1991 }
1992 #[cfg(not(feature = "improved_panic_error_reporting"))]
1993 {
1994 logging::log(RuntimeInterfaceLogLevel::Error, "runtime", message.as_bytes());
1995 unreachable();
1996 }
1997}
1998
1999#[cfg(all(not(feature = "disable_oom"), enable_alloc_error_handler))]
2001#[alloc_error_handler]
2002pub fn oom(_: core::alloc::Layout) -> ! {
2003 #[cfg(feature = "improved_panic_error_reporting")]
2004 {
2005 panic_handler::abort_on_panic("Runtime memory exhausted.");
2006 }
2007 #[cfg(not(feature = "improved_panic_error_reporting"))]
2008 {
2009 logging::log(
2010 RuntimeInterfaceLogLevel::Error,
2011 "runtime",
2012 b"Runtime memory exhausted. Aborting",
2013 );
2014 unreachable();
2015 }
2016}
2017
2018#[cfg(feature = "std")] pub type TestExternalities = sp_state_machine::TestExternalities<sp_core::Blake2Hasher>;
2021
2022#[docify::export]
2026#[cfg(not(substrate_runtime))]
2027pub type SubstrateHostFunctions = (
2028 storage::HostFunctions,
2029 default_child_storage::HostFunctions,
2030 misc::HostFunctions,
2031 wasm_tracing::HostFunctions,
2032 offchain::HostFunctions,
2033 crypto::HostFunctions,
2034 hashing::HostFunctions,
2035 allocator::HostFunctions,
2036 panic_handler::HostFunctions,
2037 logging::HostFunctions,
2038 crate::trie::HostFunctions,
2039 offchain_index::HostFunctions,
2040 transaction_index::HostFunctions,
2041);
2042
2043#[cfg(test)]
2044mod tests {
2045 use super::*;
2046 use sp_core::{crypto::UncheckedInto, map, storage::Storage};
2047 use sp_state_machine::BasicExternalities;
2048
2049 #[test]
2050 fn storage_works() {
2051 let mut t = BasicExternalities::default();
2052 t.execute_with(|| {
2053 assert_eq!(storage::get(b"hello"), None);
2054 storage::set(b"hello", b"world");
2055 assert_eq!(storage::get(b"hello"), Some(b"world".to_vec().into()));
2056 assert_eq!(storage::get(b"foo"), None);
2057 storage::set(b"foo", &[1, 2, 3][..]);
2058 });
2059
2060 t = BasicExternalities::new(Storage {
2061 top: map![b"foo".to_vec() => b"bar".to_vec()],
2062 children_default: map![],
2063 });
2064
2065 t.execute_with(|| {
2066 assert_eq!(storage::get(b"hello"), None);
2067 assert_eq!(storage::get(b"foo"), Some(b"bar".to_vec().into()));
2068 });
2069
2070 let value = vec![7u8; 35];
2071 let storage =
2072 Storage { top: map![b"foo00".to_vec() => value.clone()], children_default: map![] };
2073 t = BasicExternalities::new(storage);
2074
2075 t.execute_with(|| {
2076 assert_eq!(storage::get(b"hello"), None);
2077 assert_eq!(storage::get(b"foo00"), Some(value.clone().into()));
2078 });
2079 }
2080
2081 #[test]
2082 fn read_storage_works() {
2083 let value = b"\x0b\0\0\0Hello world".to_vec();
2084 let mut t = BasicExternalities::new(Storage {
2085 top: map![b":test".to_vec() => value.clone()],
2086 children_default: map![],
2087 });
2088
2089 t.execute_with(|| {
2090 let mut v = [0u8; 4];
2091 assert_eq!(storage::read(b":test", &mut v[..], 0).unwrap(), value.len() as u32);
2092 assert_eq!(v, [11u8, 0, 0, 0]);
2093 let mut w = [0u8; 11];
2094 assert_eq!(storage::read(b":test", &mut w[..], 4).unwrap(), value.len() as u32 - 4);
2095 assert_eq!(&w, b"Hello world");
2096 });
2097 }
2098
2099 #[test]
2100 fn clear_prefix_works() {
2101 let mut t = BasicExternalities::new(Storage {
2102 top: map![
2103 b":a".to_vec() => b"\x0b\0\0\0Hello world".to_vec(),
2104 b":abcd".to_vec() => b"\x0b\0\0\0Hello world".to_vec(),
2105 b":abc".to_vec() => b"\x0b\0\0\0Hello world".to_vec(),
2106 b":abdd".to_vec() => b"\x0b\0\0\0Hello world".to_vec()
2107 ],
2108 children_default: map![],
2109 });
2110
2111 t.execute_with(|| {
2112 assert!(matches!(
2118 storage::clear_prefix(b":abc", None),
2119 KillStorageResult::AllRemoved(2),
2120 ));
2121
2122 assert!(storage::get(b":a").is_some());
2123 assert!(storage::get(b":abdd").is_some());
2124 assert!(storage::get(b":abcd").is_none());
2125 assert!(storage::get(b":abc").is_none());
2126
2127 assert!(matches!(
2133 storage::clear_prefix(b":abc", None),
2134 KillStorageResult::AllRemoved(0),
2135 ));
2136 });
2137 }
2138
2139 fn zero_ed_pub() -> ed25519::Public {
2140 [0u8; 32].unchecked_into()
2141 }
2142
2143 fn zero_ed_sig() -> ed25519::Signature {
2144 ed25519::Signature::from_raw([0u8; 64])
2145 }
2146
2147 #[test]
2148 fn use_dalek_ext_works() {
2149 let mut ext = BasicExternalities::default();
2150 ext.register_extension(UseDalekExt);
2151
2152 ext.execute_with(|| {
2154 assert!(!crypto::ed25519_verify(&zero_ed_sig(), &Vec::new(), &zero_ed_pub()));
2155 });
2156
2157 BasicExternalities::default().execute_with(|| {
2159 assert!(crypto::ed25519_verify(&zero_ed_sig(), &Vec::new(), &zero_ed_pub()));
2160 })
2161 }
2162
2163 #[test]
2164 fn dalek_should_not_panic_on_invalid_signature() {
2165 let mut ext = BasicExternalities::default();
2166 ext.register_extension(UseDalekExt);
2167
2168 ext.execute_with(|| {
2169 let mut bytes = [0u8; 64];
2170 bytes[63] = 0b1110_0000;
2172
2173 assert!(!crypto::ed25519_verify(
2174 &ed25519::Signature::from_raw(bytes),
2175 &Vec::new(),
2176 &zero_ed_pub()
2177 ));
2178 });
2179 }
2180
2181 #[test]
2182 fn secp256k1_ecdsa_recover_valid_signature() {
2183 let pair = ecdsa::Pair::from_seed(b"12345678901234567890123456789012");
2184 let msg = sp_crypto_hashing::blake2_256(b"test message");
2185 let sig = pair.sign_prehashed(&msg);
2186
2187 assert!(ecdsa::is_signature_normalized(&sig.0));
2188
2189 let result = crypto::secp256k1_ecdsa_recover(&sig.0, &msg);
2190 assert!(result.is_ok());
2191 let recovered = ecdsa::Public::from_full(&result.ok().unwrap()).unwrap();
2192 assert_eq!(recovered, pair.public());
2193 }
2194
2195 #[test]
2196 fn secp256k1_ecdsa_recover_compressed_valid_signature() {
2197 let pair = ecdsa::Pair::from_seed(b"12345678901234567890123456789012");
2198 let msg = sp_crypto_hashing::blake2_256(b"test message");
2199 let sig = pair.sign_prehashed(&msg);
2200
2201 let result = crypto::secp256k1_ecdsa_recover_compressed(&sig.0, &msg);
2202 assert!(result.is_ok());
2203 assert_eq!(&result.ok().unwrap()[..], &pair.public().0[..]);
2204 }
2205
2206 #[test]
2207 fn ecdsa_verify_valid_signature() {
2208 let pair = ecdsa::Pair::from_seed(b"12345678901234567890123456789012");
2209 let message = b"test message";
2210 let sig = pair.sign(message);
2211
2212 assert!(ecdsa::is_signature_normalized(&sig.0));
2213 assert!(crypto::ecdsa_verify(&sig, message, &pair.public()));
2214 }
2215
2216 #[test]
2217 fn ecdsa_verify_prehashed_valid_signature() {
2218 let pair = ecdsa::Pair::from_seed(b"12345678901234567890123456789012");
2219 let msg = sp_crypto_hashing::blake2_256(b"test message");
2220 let sig = pair.sign_prehashed(&msg);
2221
2222 assert!(crypto::ecdsa_verify_prehashed(&sig, &msg, &pair.public()));
2223 }
2224
2225 #[test]
2226 fn ecdsa_verify_accepts_high_s_signatures() {
2227 fn make_high_s(sig: &ecdsa::Signature) -> ecdsa::Signature {
2228 let order: [u8; 32] = [
2229 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2230 0xff, 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, 0x8c,
2231 0xd0, 0x36, 0x41, 0x41,
2232 ];
2233 let s: [u8; 32] = sig.0[32..64].try_into().expect("slice has fixed length");
2234 let mut high_s = [0u8; 32];
2235 let mut borrow = 0i16;
2236 for i in (0..32).rev() {
2237 let diff = order[i] as i16 - s[i] as i16 - borrow;
2238 if diff < 0 {
2239 high_s[i] = (diff + 256) as u8;
2240 borrow = 1;
2241 } else {
2242 high_s[i] = diff as u8;
2243 borrow = 0;
2244 }
2245 }
2246
2247 let mut result = sig.0;
2248 result[32..64].copy_from_slice(&high_s);
2249 result[64] ^= 1;
2250 ecdsa::Signature::from_raw(result)
2251 }
2252
2253 let pair = ecdsa::Pair::from_seed(b"12345678901234567890123456789012");
2254 let message = b"test message";
2255 let signature = make_high_s(&pair.sign(message));
2256 assert!(!ecdsa::is_signature_normalized(&signature.0));
2257 assert!(crypto::ecdsa_verify(&signature, message, &pair.public()));
2258
2259 let prehash = sp_crypto_hashing::blake2_256(message);
2260 let signature = make_high_s(&pair.sign_prehashed(&prehash));
2261 assert!(!ecdsa::is_signature_normalized(&signature.0));
2262 assert!(crypto::ecdsa_verify_prehashed(&signature, &prehash, &pair.public()));
2263 }
2264}