1use alloc::vec::Vec;
19
20#[cfg(not(substrate_runtime))]
21use tracing;
22
23#[cfg(not(substrate_runtime))]
24use sp_core::{
25 crypto::Pair,
26 hexdisplay::HexDisplay,
27 offchain::{OffchainDbExt, OffchainWorkerExt, TransactionPoolExt},
28 storage::ChildInfo,
29};
30#[cfg(not(substrate_runtime))]
31use sp_keystore::KeystoreExt;
32
33#[cfg(feature = "bandersnatch-experimental")]
34use sp_core::bandersnatch;
35use sp_core::{
36 crypto::KeyTypeId,
37 ecdsa, ed25519,
38 offchain::{
39 HttpError, HttpRequestId, HttpRequestStatus, OpaqueNetworkState, StorageKind, Timestamp,
40 },
41 sr25519,
42 storage::StateVersion,
43 LogLevelFilter, OpaquePeerId, RuntimeInterfaceLogLevel, H256,
44};
45
46#[cfg(feature = "bls-experimental")]
47use sp_core::{bls381, ecdsa_bls381};
48
49#[cfg(not(substrate_runtime))]
50use sp_trie::{LayoutV0, LayoutV1, TrieConfiguration};
51
52use sp_runtime_interface::{
53 pass_by::{
54 AllocateAndReturnByCodec, AllocateAndReturnFatPointer, AllocateAndReturnPointer, PassAs,
55 PassFatPointerAndDecode, PassFatPointerAndDecodeSlice, PassFatPointerAndRead,
56 PassFatPointerAndReadWrite, PassPointerAndRead, PassPointerAndReadCopy, ReturnAs,
57 },
58 runtime_interface, Pointer,
59};
60
61use codec::{Decode, Encode};
62
63#[cfg(not(substrate_runtime))]
64use secp256k1::{
65 ecdsa::{RecoverableSignature, RecoveryId},
66 Message,
67};
68
69#[cfg(not(substrate_runtime))]
70use sp_externalities::{Externalities, ExternalitiesExt};
71
72pub use sp_externalities::MultiRemovalResults;
73
74#[cfg(not(substrate_runtime))]
75const LOG_TARGET: &str = "runtime::io";
76
77#[derive(Encode, Decode)]
79pub enum EcdsaVerifyError {
80 BadRS,
82 BadV,
84 BadSignature,
86}
87
88#[derive(Encode, Decode)]
91pub enum KillStorageResult {
92 AllRemoved(u32),
95 SomeRemaining(u32),
98}
99
100impl From<MultiRemovalResults> for KillStorageResult {
101 fn from(r: MultiRemovalResults) -> Self {
102 match r.maybe_cursor {
106 None => Self::AllRemoved(r.loops),
107 Some(..) => Self::SomeRemaining(r.loops),
108 }
109 }
110}
111
112#[runtime_interface]
114pub trait Storage {
115 fn get(
117 &mut self,
118 key: PassFatPointerAndRead<&[u8]>,
119 ) -> AllocateAndReturnByCodec<Option<bytes::Bytes>> {
120 self.storage(key).map(|s| bytes::Bytes::from(s.to_vec()))
121 }
122
123 fn read(
129 &mut self,
130 key: PassFatPointerAndRead<&[u8]>,
131 value_out: PassFatPointerAndReadWrite<&mut [u8]>,
132 value_offset: u32,
133 ) -> AllocateAndReturnByCodec<Option<u32>> {
134 self.storage(key).map(|value| {
135 let value_offset = value_offset as usize;
136 let data = &value[value_offset.min(value.len())..];
137 let written = core::cmp::min(data.len(), value_out.len());
138 value_out[..written].copy_from_slice(&data[..written]);
139 data.len() as u32
140 })
141 }
142
143 fn set(&mut self, key: PassFatPointerAndRead<&[u8]>, value: PassFatPointerAndRead<&[u8]>) {
145 self.set_storage(key.to_vec(), value.to_vec());
146 }
147
148 fn clear(&mut self, key: PassFatPointerAndRead<&[u8]>) {
150 self.clear_storage(key)
151 }
152
153 fn exists(&mut self, key: PassFatPointerAndRead<&[u8]>) -> bool {
155 self.exists_storage(key)
156 }
157
158 fn clear_prefix(&mut self, prefix: PassFatPointerAndRead<&[u8]>) {
160 let _ = Externalities::clear_prefix(*self, prefix, None, None);
161 }
162
163 #[version(2)]
189 fn clear_prefix(
190 &mut self,
191 prefix: PassFatPointerAndRead<&[u8]>,
192 limit: PassFatPointerAndDecode<Option<u32>>,
193 ) -> AllocateAndReturnByCodec<KillStorageResult> {
194 Externalities::clear_prefix(*self, prefix, limit, None).into()
195 }
196
197 #[version(3, register_only)]
229 fn clear_prefix(
230 &mut self,
231 maybe_prefix: PassFatPointerAndRead<&[u8]>,
232 maybe_limit: PassFatPointerAndDecode<Option<u32>>,
233 maybe_cursor: PassFatPointerAndDecode<Option<Vec<u8>>>, ) -> AllocateAndReturnByCodec<MultiRemovalResults> {
236 Externalities::clear_prefix(
237 *self,
238 maybe_prefix,
239 maybe_limit,
240 maybe_cursor.as_ref().map(|x| &x[..]),
241 )
242 .into()
243 }
244
245 fn append(&mut self, key: PassFatPointerAndRead<&[u8]>, value: PassFatPointerAndRead<Vec<u8>>) {
254 self.storage_append(key.to_vec(), value);
255 }
256
257 fn root(&mut self) -> AllocateAndReturnFatPointer<Vec<u8>> {
263 self.storage_root(StateVersion::V0)
264 }
265
266 #[version(2)]
272 fn root(&mut self, version: PassAs<StateVersion, u8>) -> AllocateAndReturnFatPointer<Vec<u8>> {
273 self.storage_root(version)
274 }
275
276 fn changes_root(
278 &mut self,
279 _parent_hash: PassFatPointerAndRead<&[u8]>,
280 ) -> AllocateAndReturnByCodec<Option<Vec<u8>>> {
281 None
282 }
283
284 fn next_key(
286 &mut self,
287 key: PassFatPointerAndRead<&[u8]>,
288 ) -> AllocateAndReturnByCodec<Option<Vec<u8>>> {
289 self.next_storage_key(key)
290 }
291
292 fn start_transaction(&mut self) {
305 self.storage_start_transaction();
306 }
307
308 fn rollback_transaction(&mut self) {
316 self.storage_rollback_transaction()
317 .expect("No open transaction that can be rolled back.");
318 }
319
320 fn commit_transaction(&mut self) {
328 self.storage_commit_transaction()
329 .expect("No open transaction that can be committed.");
330 }
331}
332
333#[runtime_interface]
336pub trait DefaultChildStorage {
337 fn get(
342 &mut self,
343 storage_key: PassFatPointerAndRead<&[u8]>,
344 key: PassFatPointerAndRead<&[u8]>,
345 ) -> AllocateAndReturnByCodec<Option<Vec<u8>>> {
346 let child_info = ChildInfo::new_default(storage_key);
347 self.child_storage(&child_info, key).map(|s| s.to_vec())
348 }
349
350 fn read(
358 &mut self,
359 storage_key: PassFatPointerAndRead<&[u8]>,
360 key: PassFatPointerAndRead<&[u8]>,
361 value_out: PassFatPointerAndReadWrite<&mut [u8]>,
362 value_offset: u32,
363 ) -> AllocateAndReturnByCodec<Option<u32>> {
364 let child_info = ChildInfo::new_default(storage_key);
365 self.child_storage(&child_info, key).map(|value| {
366 let value_offset = value_offset as usize;
367 let data = &value[value_offset.min(value.len())..];
368 let written = core::cmp::min(data.len(), value_out.len());
369 value_out[..written].copy_from_slice(&data[..written]);
370 data.len() as u32
371 })
372 }
373
374 fn set(
378 &mut self,
379 storage_key: PassFatPointerAndRead<&[u8]>,
380 key: PassFatPointerAndRead<&[u8]>,
381 value: PassFatPointerAndRead<&[u8]>,
382 ) {
383 let child_info = ChildInfo::new_default(storage_key);
384 self.set_child_storage(&child_info, key.to_vec(), value.to_vec());
385 }
386
387 fn clear(
391 &mut self,
392 storage_key: PassFatPointerAndRead<&[u8]>,
393 key: PassFatPointerAndRead<&[u8]>,
394 ) {
395 let child_info = ChildInfo::new_default(storage_key);
396 self.clear_child_storage(&child_info, key);
397 }
398
399 fn storage_kill(&mut self, storage_key: PassFatPointerAndRead<&[u8]>) {
404 let child_info = ChildInfo::new_default(storage_key);
405 let _ = self.kill_child_storage(&child_info, None, None);
406 }
407
408 #[version(2)]
412 fn storage_kill(
413 &mut self,
414 storage_key: PassFatPointerAndRead<&[u8]>,
415 limit: PassFatPointerAndDecode<Option<u32>>,
416 ) -> bool {
417 let child_info = ChildInfo::new_default(storage_key);
418 let r = self.kill_child_storage(&child_info, limit, None);
419 r.maybe_cursor.is_none()
420 }
421
422 #[version(3)]
426 fn storage_kill(
427 &mut self,
428 storage_key: PassFatPointerAndRead<&[u8]>,
429 limit: PassFatPointerAndDecode<Option<u32>>,
430 ) -> AllocateAndReturnByCodec<KillStorageResult> {
431 let child_info = ChildInfo::new_default(storage_key);
432 self.kill_child_storage(&child_info, limit, None).into()
433 }
434
435 #[version(4, register_only)]
439 fn storage_kill(
440 &mut self,
441 storage_key: PassFatPointerAndRead<&[u8]>,
442 maybe_limit: PassFatPointerAndDecode<Option<u32>>,
443 maybe_cursor: PassFatPointerAndDecode<Option<Vec<u8>>>,
444 ) -> AllocateAndReturnByCodec<MultiRemovalResults> {
445 let child_info = ChildInfo::new_default(storage_key);
446 self.kill_child_storage(&child_info, maybe_limit, maybe_cursor.as_ref().map(|x| &x[..]))
447 .into()
448 }
449
450 fn exists(
454 &mut self,
455 storage_key: PassFatPointerAndRead<&[u8]>,
456 key: PassFatPointerAndRead<&[u8]>,
457 ) -> bool {
458 let child_info = ChildInfo::new_default(storage_key);
459 self.exists_child_storage(&child_info, key)
460 }
461
462 fn clear_prefix(
466 &mut self,
467 storage_key: PassFatPointerAndRead<&[u8]>,
468 prefix: PassFatPointerAndRead<&[u8]>,
469 ) {
470 let child_info = ChildInfo::new_default(storage_key);
471 let _ = self.clear_child_prefix(&child_info, prefix, None, None);
472 }
473
474 #[version(2)]
478 fn clear_prefix(
479 &mut self,
480 storage_key: PassFatPointerAndRead<&[u8]>,
481 prefix: PassFatPointerAndRead<&[u8]>,
482 limit: PassFatPointerAndDecode<Option<u32>>,
483 ) -> AllocateAndReturnByCodec<KillStorageResult> {
484 let child_info = ChildInfo::new_default(storage_key);
485 self.clear_child_prefix(&child_info, prefix, limit, None).into()
486 }
487
488 #[version(3, register_only)]
492 fn clear_prefix(
493 &mut self,
494 storage_key: PassFatPointerAndRead<&[u8]>,
495 prefix: PassFatPointerAndRead<&[u8]>,
496 maybe_limit: PassFatPointerAndDecode<Option<u32>>,
497 maybe_cursor: PassFatPointerAndDecode<Option<Vec<u8>>>,
498 ) -> AllocateAndReturnByCodec<MultiRemovalResults> {
499 let child_info = ChildInfo::new_default(storage_key);
500 self.clear_child_prefix(
501 &child_info,
502 prefix,
503 maybe_limit,
504 maybe_cursor.as_ref().map(|x| &x[..]),
505 )
506 .into()
507 }
508
509 fn root(
516 &mut self,
517 storage_key: PassFatPointerAndRead<&[u8]>,
518 ) -> AllocateAndReturnFatPointer<Vec<u8>> {
519 let child_info = ChildInfo::new_default(storage_key);
520 self.child_storage_root(&child_info, StateVersion::V0)
521 }
522
523 #[version(2)]
530 fn root(
531 &mut self,
532 storage_key: PassFatPointerAndRead<&[u8]>,
533 version: PassAs<StateVersion, u8>,
534 ) -> AllocateAndReturnFatPointer<Vec<u8>> {
535 let child_info = ChildInfo::new_default(storage_key);
536 self.child_storage_root(&child_info, version)
537 }
538
539 fn next_key(
543 &mut self,
544 storage_key: PassFatPointerAndRead<&[u8]>,
545 key: PassFatPointerAndRead<&[u8]>,
546 ) -> AllocateAndReturnByCodec<Option<Vec<u8>>> {
547 let child_info = ChildInfo::new_default(storage_key);
548 self.next_child_storage_key(&child_info, key)
549 }
550}
551
552#[runtime_interface]
554pub trait Trie {
555 fn blake2_256_root(
557 input: PassFatPointerAndDecode<Vec<(Vec<u8>, Vec<u8>)>>,
558 ) -> AllocateAndReturnPointer<H256, 32> {
559 LayoutV0::<sp_core::Blake2Hasher>::trie_root(input)
560 }
561
562 #[version(2)]
564 fn blake2_256_root(
565 input: PassFatPointerAndDecode<Vec<(Vec<u8>, Vec<u8>)>>,
566 version: PassAs<StateVersion, u8>,
567 ) -> AllocateAndReturnPointer<H256, 32> {
568 match version {
569 StateVersion::V0 => LayoutV0::<sp_core::Blake2Hasher>::trie_root(input),
570 StateVersion::V1 => LayoutV1::<sp_core::Blake2Hasher>::trie_root(input),
571 }
572 }
573
574 fn blake2_256_ordered_root(
576 input: PassFatPointerAndDecode<Vec<Vec<u8>>>,
577 ) -> AllocateAndReturnPointer<H256, 32> {
578 LayoutV0::<sp_core::Blake2Hasher>::ordered_trie_root(input)
579 }
580
581 #[version(2)]
583 fn blake2_256_ordered_root(
584 input: PassFatPointerAndDecode<Vec<Vec<u8>>>,
585 version: PassAs<StateVersion, u8>,
586 ) -> AllocateAndReturnPointer<H256, 32> {
587 match version {
588 StateVersion::V0 => LayoutV0::<sp_core::Blake2Hasher>::ordered_trie_root(input),
589 StateVersion::V1 => LayoutV1::<sp_core::Blake2Hasher>::ordered_trie_root(input),
590 }
591 }
592
593 fn keccak_256_root(
595 input: PassFatPointerAndDecode<Vec<(Vec<u8>, Vec<u8>)>>,
596 ) -> AllocateAndReturnPointer<H256, 32> {
597 LayoutV0::<sp_core::KeccakHasher>::trie_root(input)
598 }
599
600 #[version(2)]
602 fn keccak_256_root(
603 input: PassFatPointerAndDecode<Vec<(Vec<u8>, Vec<u8>)>>,
604 version: PassAs<StateVersion, u8>,
605 ) -> AllocateAndReturnPointer<H256, 32> {
606 match version {
607 StateVersion::V0 => LayoutV0::<sp_core::KeccakHasher>::trie_root(input),
608 StateVersion::V1 => LayoutV1::<sp_core::KeccakHasher>::trie_root(input),
609 }
610 }
611
612 fn keccak_256_ordered_root(
614 input: PassFatPointerAndDecode<Vec<Vec<u8>>>,
615 ) -> AllocateAndReturnPointer<H256, 32> {
616 LayoutV0::<sp_core::KeccakHasher>::ordered_trie_root(input)
617 }
618
619 #[version(2)]
621 fn keccak_256_ordered_root(
622 input: PassFatPointerAndDecode<Vec<Vec<u8>>>,
623 version: PassAs<StateVersion, u8>,
624 ) -> AllocateAndReturnPointer<H256, 32> {
625 match version {
626 StateVersion::V0 => LayoutV0::<sp_core::KeccakHasher>::ordered_trie_root(input),
627 StateVersion::V1 => LayoutV1::<sp_core::KeccakHasher>::ordered_trie_root(input),
628 }
629 }
630
631 fn blake2_256_verify_proof(
633 root: PassPointerAndReadCopy<H256, 32>,
634 proof: PassFatPointerAndDecodeSlice<&[Vec<u8>]>,
635 key: PassFatPointerAndRead<&[u8]>,
636 value: PassFatPointerAndRead<&[u8]>,
637 ) -> bool {
638 sp_trie::verify_trie_proof::<LayoutV0<sp_core::Blake2Hasher>, _, _, _>(
639 &root,
640 proof,
641 &[(key, Some(value))],
642 )
643 .is_ok()
644 }
645
646 #[version(2)]
648 fn blake2_256_verify_proof(
649 root: PassPointerAndReadCopy<H256, 32>,
650 proof: PassFatPointerAndDecodeSlice<&[Vec<u8>]>,
651 key: PassFatPointerAndRead<&[u8]>,
652 value: PassFatPointerAndRead<&[u8]>,
653 version: PassAs<StateVersion, u8>,
654 ) -> bool {
655 match version {
656 StateVersion::V0 => sp_trie::verify_trie_proof::<
657 LayoutV0<sp_core::Blake2Hasher>,
658 _,
659 _,
660 _,
661 >(&root, proof, &[(key, Some(value))])
662 .is_ok(),
663 StateVersion::V1 => sp_trie::verify_trie_proof::<
664 LayoutV1<sp_core::Blake2Hasher>,
665 _,
666 _,
667 _,
668 >(&root, proof, &[(key, Some(value))])
669 .is_ok(),
670 }
671 }
672
673 fn keccak_256_verify_proof(
675 root: PassPointerAndReadCopy<H256, 32>,
676 proof: PassFatPointerAndDecodeSlice<&[Vec<u8>]>,
677 key: PassFatPointerAndRead<&[u8]>,
678 value: PassFatPointerAndRead<&[u8]>,
679 ) -> bool {
680 sp_trie::verify_trie_proof::<LayoutV0<sp_core::KeccakHasher>, _, _, _>(
681 &root,
682 proof,
683 &[(key, Some(value))],
684 )
685 .is_ok()
686 }
687
688 #[version(2)]
690 fn keccak_256_verify_proof(
691 root: PassPointerAndReadCopy<H256, 32>,
692 proof: PassFatPointerAndDecodeSlice<&[Vec<u8>]>,
693 key: PassFatPointerAndRead<&[u8]>,
694 value: PassFatPointerAndRead<&[u8]>,
695 version: PassAs<StateVersion, u8>,
696 ) -> bool {
697 match version {
698 StateVersion::V0 => sp_trie::verify_trie_proof::<
699 LayoutV0<sp_core::KeccakHasher>,
700 _,
701 _,
702 _,
703 >(&root, proof, &[(key, Some(value))])
704 .is_ok(),
705 StateVersion::V1 => sp_trie::verify_trie_proof::<
706 LayoutV1<sp_core::KeccakHasher>,
707 _,
708 _,
709 _,
710 >(&root, proof, &[(key, Some(value))])
711 .is_ok(),
712 }
713 }
714}
715
716#[runtime_interface]
719pub trait Misc {
720 fn print_num(val: u64) {
725 log::debug!(target: "runtime", "{}", val);
726 }
727
728 fn print_utf8(utf8: PassFatPointerAndRead<&[u8]>) {
730 if let Ok(data) = core::str::from_utf8(utf8) {
731 log::debug!(target: "runtime", "{}", data)
732 }
733 }
734
735 fn print_hex(data: PassFatPointerAndRead<&[u8]>) {
737 log::debug!(target: "runtime", "{}", HexDisplay::from(&data));
738 }
739
740 fn runtime_version(
756 &mut self,
757 wasm: PassFatPointerAndRead<&[u8]>,
758 ) -> AllocateAndReturnByCodec<Option<Vec<u8>>> {
759 use sp_core::traits::ReadRuntimeVersionExt;
760
761 let mut ext = sp_state_machine::BasicExternalities::default();
762
763 match self
764 .extension::<ReadRuntimeVersionExt>()
765 .expect("No `ReadRuntimeVersionExt` associated for the current context!")
766 .read_runtime_version(wasm, &mut ext)
767 {
768 Ok(v) => Some(v),
769 Err(err) => {
770 log::debug!(
771 target: LOG_TARGET,
772 "cannot read version from the given runtime: {}",
773 err,
774 );
775 None
776 },
777 }
778 }
779}
780
781#[cfg(not(substrate_runtime))]
782sp_externalities::decl_extension! {
783 pub struct UseDalekExt;
800}
801
802#[cfg(not(substrate_runtime))]
803impl Default for UseDalekExt {
804 fn default() -> Self {
805 Self
806 }
807}
808
809#[runtime_interface]
811pub trait Crypto {
812 fn ed25519_public_keys(
814 &mut self,
815 id: PassPointerAndReadCopy<KeyTypeId, 4>,
816 ) -> AllocateAndReturnByCodec<Vec<ed25519::Public>> {
817 self.extension::<KeystoreExt>()
818 .expect("No `keystore` associated for the current context!")
819 .ed25519_public_keys(id)
820 }
821
822 fn ed25519_generate(
829 &mut self,
830 id: PassPointerAndReadCopy<KeyTypeId, 4>,
831 seed: PassFatPointerAndDecode<Option<Vec<u8>>>,
832 ) -> AllocateAndReturnPointer<ed25519::Public, 32> {
833 let seed = seed.as_ref().map(|s| core::str::from_utf8(s).expect("Seed is valid utf8!"));
834 self.extension::<KeystoreExt>()
835 .expect("No `keystore` associated for the current context!")
836 .ed25519_generate_new(id, seed)
837 .expect("`ed25519_generate` failed")
838 }
839
840 fn ed25519_sign(
845 &mut self,
846 id: PassPointerAndReadCopy<KeyTypeId, 4>,
847 pub_key: PassPointerAndRead<&ed25519::Public, 32>,
848 msg: PassFatPointerAndRead<&[u8]>,
849 ) -> AllocateAndReturnByCodec<Option<ed25519::Signature>> {
850 self.extension::<KeystoreExt>()
851 .expect("No `keystore` associated for the current context!")
852 .ed25519_sign(id, pub_key, msg)
853 .ok()
854 .flatten()
855 }
856
857 fn ed25519_verify(
861 sig: PassPointerAndRead<&ed25519::Signature, 64>,
862 msg: PassFatPointerAndRead<&[u8]>,
863 pub_key: PassPointerAndRead<&ed25519::Public, 32>,
864 ) -> bool {
865 if sp_externalities::with_externalities(|mut e| e.extension::<UseDalekExt>().is_some())
869 .unwrap_or_default()
870 {
871 use ed25519_dalek::Verifier;
872
873 let Ok(public_key) = ed25519_dalek::VerifyingKey::from_bytes(&pub_key.0) else {
874 return false;
875 };
876
877 let sig = ed25519_dalek::Signature::from_bytes(&sig.0);
878
879 public_key.verify(msg, &sig).is_ok()
880 } else {
881 ed25519::Pair::verify(sig, msg, pub_key)
882 }
883 }
884
885 #[version(1, register_only)]
899 fn ed25519_batch_verify(
900 &mut self,
901 sig: PassPointerAndRead<&ed25519::Signature, 64>,
902 msg: PassFatPointerAndRead<&[u8]>,
903 pub_key: PassPointerAndRead<&ed25519::Public, 32>,
904 ) -> bool {
905 let res = ed25519_verify(sig, msg, pub_key);
906
907 if let Some(ext) = self.extension::<VerificationExtDeprecated>() {
908 ext.0 &= res;
909 }
910
911 res
912 }
913
914 #[version(2)]
918 fn sr25519_verify(
919 sig: PassPointerAndRead<&sr25519::Signature, 64>,
920 msg: PassFatPointerAndRead<&[u8]>,
921 pub_key: PassPointerAndRead<&sr25519::Public, 32>,
922 ) -> bool {
923 sr25519::Pair::verify(sig, msg, pub_key)
924 }
925
926 #[version(1, register_only)]
940 fn sr25519_batch_verify(
941 &mut self,
942 sig: PassPointerAndRead<&sr25519::Signature, 64>,
943 msg: PassFatPointerAndRead<&[u8]>,
944 pub_key: PassPointerAndRead<&sr25519::Public, 32>,
945 ) -> bool {
946 let res = sr25519_verify(sig, msg, pub_key);
947
948 if let Some(ext) = self.extension::<VerificationExtDeprecated>() {
949 ext.0 &= res;
950 }
951
952 res
953 }
954
955 #[version(1, register_only)]
962 fn start_batch_verify(&mut self) {
963 self.register_extension(VerificationExtDeprecated(true))
964 .expect("Failed to register required extension: `VerificationExt`");
965 }
966
967 #[version(1, register_only)]
979 fn finish_batch_verify(&mut self) -> bool {
980 let result = self
981 .extension::<VerificationExtDeprecated>()
982 .expect("`finish_batch_verify` should only be called after `start_batch_verify`")
983 .0;
984
985 self.deregister_extension::<VerificationExtDeprecated>()
986 .expect("No verification extension in current context!");
987
988 result
989 }
990
991 fn sr25519_public_keys(
993 &mut self,
994 id: PassPointerAndReadCopy<KeyTypeId, 4>,
995 ) -> AllocateAndReturnByCodec<Vec<sr25519::Public>> {
996 self.extension::<KeystoreExt>()
997 .expect("No `keystore` associated for the current context!")
998 .sr25519_public_keys(id)
999 }
1000
1001 fn sr25519_generate(
1008 &mut self,
1009 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1010 seed: PassFatPointerAndDecode<Option<Vec<u8>>>,
1011 ) -> AllocateAndReturnPointer<sr25519::Public, 32> {
1012 let seed = seed.as_ref().map(|s| core::str::from_utf8(s).expect("Seed is valid utf8!"));
1013 self.extension::<KeystoreExt>()
1014 .expect("No `keystore` associated for the current context!")
1015 .sr25519_generate_new(id, seed)
1016 .expect("`sr25519_generate` failed")
1017 }
1018
1019 fn sr25519_sign(
1024 &mut self,
1025 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1026 pub_key: PassPointerAndRead<&sr25519::Public, 32>,
1027 msg: PassFatPointerAndRead<&[u8]>,
1028 ) -> AllocateAndReturnByCodec<Option<sr25519::Signature>> {
1029 self.extension::<KeystoreExt>()
1030 .expect("No `keystore` associated for the current context!")
1031 .sr25519_sign(id, pub_key, msg)
1032 .ok()
1033 .flatten()
1034 }
1035
1036 fn sr25519_verify(
1041 sig: PassPointerAndRead<&sr25519::Signature, 64>,
1042 msg: PassFatPointerAndRead<&[u8]>,
1043 pubkey: PassPointerAndRead<&sr25519::Public, 32>,
1044 ) -> bool {
1045 sr25519::Pair::verify_deprecated(sig, msg, pubkey)
1046 }
1047
1048 fn ecdsa_public_keys(
1050 &mut self,
1051 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1052 ) -> AllocateAndReturnByCodec<Vec<ecdsa::Public>> {
1053 self.extension::<KeystoreExt>()
1054 .expect("No `keystore` associated for the current context!")
1055 .ecdsa_public_keys(id)
1056 }
1057
1058 fn ecdsa_generate(
1065 &mut self,
1066 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1067 seed: PassFatPointerAndDecode<Option<Vec<u8>>>,
1068 ) -> AllocateAndReturnPointer<ecdsa::Public, 33> {
1069 let seed = seed.as_ref().map(|s| core::str::from_utf8(s).expect("Seed is valid utf8!"));
1070 self.extension::<KeystoreExt>()
1071 .expect("No `keystore` associated for the current context!")
1072 .ecdsa_generate_new(id, seed)
1073 .expect("`ecdsa_generate` failed")
1074 }
1075
1076 fn ecdsa_sign(
1081 &mut self,
1082 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1083 pub_key: PassPointerAndRead<&ecdsa::Public, 33>,
1084 msg: PassFatPointerAndRead<&[u8]>,
1085 ) -> AllocateAndReturnByCodec<Option<ecdsa::Signature>> {
1086 self.extension::<KeystoreExt>()
1087 .expect("No `keystore` associated for the current context!")
1088 .ecdsa_sign(id, pub_key, msg)
1089 .ok()
1090 .flatten()
1091 }
1092
1093 fn ecdsa_sign_prehashed(
1098 &mut self,
1099 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1100 pub_key: PassPointerAndRead<&ecdsa::Public, 33>,
1101 msg: PassPointerAndRead<&[u8; 32], 32>,
1102 ) -> AllocateAndReturnByCodec<Option<ecdsa::Signature>> {
1103 self.extension::<KeystoreExt>()
1104 .expect("No `keystore` associated for the current context!")
1105 .ecdsa_sign_prehashed(id, pub_key, msg)
1106 .ok()
1107 .flatten()
1108 }
1109
1110 fn ecdsa_verify(
1119 sig: PassPointerAndRead<&ecdsa::Signature, 65>,
1120 msg: PassFatPointerAndRead<&[u8]>,
1121 pub_key: PassPointerAndRead<&ecdsa::Public, 33>,
1122 ) -> bool {
1123 #[allow(deprecated)]
1124 ecdsa::Pair::verify_deprecated(sig, msg, pub_key)
1125 }
1126
1127 #[version(2)]
1135 fn ecdsa_verify(
1136 sig: PassPointerAndRead<&ecdsa::Signature, 65>,
1137 msg: PassFatPointerAndRead<&[u8]>,
1138 pub_key: PassPointerAndRead<&ecdsa::Public, 33>,
1139 ) -> bool {
1140 ecdsa::Pair::verify(sig, msg, pub_key)
1141 }
1142
1143 fn ecdsa_verify_prehashed(
1151 sig: PassPointerAndRead<&ecdsa::Signature, 65>,
1152 msg: PassPointerAndRead<&[u8; 32], 32>,
1153 pub_key: PassPointerAndRead<&ecdsa::Public, 33>,
1154 ) -> bool {
1155 ecdsa::Pair::verify_prehashed(sig, msg, pub_key)
1156 }
1157
1158 #[version(1, register_only)]
1172 fn ecdsa_batch_verify(
1173 &mut self,
1174 sig: PassPointerAndRead<&ecdsa::Signature, 65>,
1175 msg: PassFatPointerAndRead<&[u8]>,
1176 pub_key: PassPointerAndRead<&ecdsa::Public, 33>,
1177 ) -> bool {
1178 let res = ecdsa_verify(sig, msg, pub_key);
1179
1180 if let Some(ext) = self.extension::<VerificationExtDeprecated>() {
1181 ext.0 &= res;
1182 }
1183
1184 res
1185 }
1186
1187 fn secp256k1_ecdsa_recover(
1200 sig: PassPointerAndRead<&[u8; 65], 65>,
1201 msg: PassPointerAndRead<&[u8; 32], 32>,
1202 ) -> AllocateAndReturnByCodec<Result<[u8; 64], EcdsaVerifyError>> {
1203 let rid = libsecp256k1::RecoveryId::parse(
1204 if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8,
1205 )
1206 .map_err(|_| EcdsaVerifyError::BadV)?;
1207 let sig = libsecp256k1::Signature::parse_overflowing_slice(&sig[..64])
1208 .map_err(|_| EcdsaVerifyError::BadRS)?;
1209 let msg = libsecp256k1::Message::parse(msg);
1210 let pubkey =
1211 libsecp256k1::recover(&msg, &sig, &rid).map_err(|_| EcdsaVerifyError::BadSignature)?;
1212 let mut res = [0u8; 64];
1213 res.copy_from_slice(&pubkey.serialize()[1..65]);
1214 Ok(res)
1215 }
1216
1217 #[version(2)]
1229 fn secp256k1_ecdsa_recover(
1230 sig: PassPointerAndRead<&[u8; 65], 65>,
1231 msg: PassPointerAndRead<&[u8; 32], 32>,
1232 ) -> AllocateAndReturnByCodec<Result<[u8; 64], EcdsaVerifyError>> {
1233 let rid = RecoveryId::from_i32(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as i32)
1234 .map_err(|_| EcdsaVerifyError::BadV)?;
1235 let sig = RecoverableSignature::from_compact(&sig[..64], rid)
1236 .map_err(|_| EcdsaVerifyError::BadRS)?;
1237 let msg = Message::from_digest_slice(msg).expect("Message is 32 bytes; qed");
1238 #[cfg(feature = "std")]
1239 let ctx = secp256k1::SECP256K1;
1240 #[cfg(not(feature = "std"))]
1241 let ctx = secp256k1::Secp256k1::<secp256k1::VerifyOnly>::gen_new();
1242 let pubkey = ctx.recover_ecdsa(&msg, &sig).map_err(|_| EcdsaVerifyError::BadSignature)?;
1243 let mut res = [0u8; 64];
1244 res.copy_from_slice(&pubkey.serialize_uncompressed()[1..]);
1245 Ok(res)
1246 }
1247
1248 fn secp256k1_ecdsa_recover_compressed(
1259 sig: PassPointerAndRead<&[u8; 65], 65>,
1260 msg: PassPointerAndRead<&[u8; 32], 32>,
1261 ) -> AllocateAndReturnByCodec<Result<[u8; 33], EcdsaVerifyError>> {
1262 let rid = libsecp256k1::RecoveryId::parse(
1263 if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8,
1264 )
1265 .map_err(|_| EcdsaVerifyError::BadV)?;
1266 let sig = libsecp256k1::Signature::parse_overflowing_slice(&sig[0..64])
1267 .map_err(|_| EcdsaVerifyError::BadRS)?;
1268 let msg = libsecp256k1::Message::parse(msg);
1269 let pubkey =
1270 libsecp256k1::recover(&msg, &sig, &rid).map_err(|_| EcdsaVerifyError::BadSignature)?;
1271 Ok(pubkey.serialize_compressed())
1272 }
1273
1274 #[version(2)]
1285 fn secp256k1_ecdsa_recover_compressed(
1286 sig: PassPointerAndRead<&[u8; 65], 65>,
1287 msg: PassPointerAndRead<&[u8; 32], 32>,
1288 ) -> AllocateAndReturnByCodec<Result<[u8; 33], EcdsaVerifyError>> {
1289 let rid = RecoveryId::from_i32(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as i32)
1290 .map_err(|_| EcdsaVerifyError::BadV)?;
1291 let sig = RecoverableSignature::from_compact(&sig[..64], rid)
1292 .map_err(|_| EcdsaVerifyError::BadRS)?;
1293 let msg = Message::from_digest_slice(msg).expect("Message is 32 bytes; qed");
1294 #[cfg(feature = "std")]
1295 let ctx = secp256k1::SECP256K1;
1296 #[cfg(not(feature = "std"))]
1297 let ctx = secp256k1::Secp256k1::<secp256k1::VerifyOnly>::gen_new();
1298 let pubkey = ctx.recover_ecdsa(&msg, &sig).map_err(|_| EcdsaVerifyError::BadSignature)?;
1299 Ok(pubkey.serialize())
1300 }
1301
1302 #[cfg(feature = "bls-experimental")]
1309 fn bls381_generate(
1310 &mut self,
1311 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1312 seed: PassFatPointerAndDecode<Option<Vec<u8>>>,
1313 ) -> AllocateAndReturnPointer<bls381::Public, 144> {
1314 let seed = seed.as_ref().map(|s| core::str::from_utf8(s).expect("Seed is valid utf8!"));
1315 self.extension::<KeystoreExt>()
1316 .expect("No `keystore` associated for the current context!")
1317 .bls381_generate_new(id, seed)
1318 .expect("`bls381_generate` failed")
1319 }
1320
1321 #[cfg(feature = "bls-experimental")]
1326 fn bls381_generate_proof_of_possession(
1327 &mut self,
1328 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1329 pub_key: PassPointerAndRead<&bls381::Public, 144>,
1330 owner: PassFatPointerAndRead<&[u8]>,
1331 ) -> AllocateAndReturnByCodec<Option<bls381::ProofOfPossession>> {
1332 self.extension::<KeystoreExt>()
1333 .expect("No `keystore` associated for the current context!")
1334 .bls381_generate_proof_of_possession(id, pub_key, owner)
1335 .ok()
1336 .flatten()
1337 }
1338
1339 #[cfg(feature = "bls-experimental")]
1346 fn ecdsa_bls381_generate(
1347 &mut self,
1348 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1349 seed: PassFatPointerAndDecode<Option<Vec<u8>>>,
1350 ) -> AllocateAndReturnPointer<ecdsa_bls381::Public, { 144 + 33 }> {
1351 let seed = seed.as_ref().map(|s| core::str::from_utf8(s).expect("Seed is valid utf8!"));
1352 self.extension::<KeystoreExt>()
1353 .expect("No `keystore` associated for the current context!")
1354 .ecdsa_bls381_generate_new(id, seed)
1355 .expect("`ecdsa_bls381_generate` failed")
1356 }
1357
1358 #[cfg(feature = "bandersnatch-experimental")]
1365 fn bandersnatch_generate(
1366 &mut self,
1367 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1368 seed: PassFatPointerAndDecode<Option<Vec<u8>>>,
1369 ) -> AllocateAndReturnPointer<bandersnatch::Public, 32> {
1370 let seed = seed.as_ref().map(|s| core::str::from_utf8(s).expect("Seed is valid utf8!"));
1371 self.extension::<KeystoreExt>()
1372 .expect("No `keystore` associated for the current context!")
1373 .bandersnatch_generate_new(id, seed)
1374 .expect("`bandernatch_generate` failed")
1375 }
1376
1377 #[cfg(feature = "bandersnatch-experimental")]
1382 fn bandersnatch_sign(
1383 &mut self,
1384 id: PassPointerAndReadCopy<KeyTypeId, 4>,
1385 pub_key: PassPointerAndRead<&bandersnatch::Public, 32>,
1386 msg: PassFatPointerAndRead<&[u8]>,
1387 ) -> AllocateAndReturnByCodec<Option<bandersnatch::Signature>> {
1388 self.extension::<KeystoreExt>()
1389 .expect("No `keystore` associated for the current context!")
1390 .bandersnatch_sign(id, pub_key, msg)
1391 .ok()
1392 .flatten()
1393 }
1394}
1395
1396#[runtime_interface]
1398pub trait Hashing {
1399 fn keccak_256(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnPointer<[u8; 32], 32> {
1401 sp_crypto_hashing::keccak_256(data)
1402 }
1403
1404 fn keccak_512(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnPointer<[u8; 64], 64> {
1406 sp_crypto_hashing::keccak_512(data)
1407 }
1408
1409 fn sha2_256(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnPointer<[u8; 32], 32> {
1411 sp_crypto_hashing::sha2_256(data)
1412 }
1413
1414 fn blake2_128(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnPointer<[u8; 16], 16> {
1416 sp_crypto_hashing::blake2_128(data)
1417 }
1418
1419 fn blake2_256(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnPointer<[u8; 32], 32> {
1421 sp_crypto_hashing::blake2_256(data)
1422 }
1423
1424 fn twox_256(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnPointer<[u8; 32], 32> {
1426 sp_crypto_hashing::twox_256(data)
1427 }
1428
1429 fn twox_128(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnPointer<[u8; 16], 16> {
1431 sp_crypto_hashing::twox_128(data)
1432 }
1433
1434 fn twox_64(data: PassFatPointerAndRead<&[u8]>) -> AllocateAndReturnPointer<[u8; 8], 8> {
1436 sp_crypto_hashing::twox_64(data)
1437 }
1438}
1439
1440#[runtime_interface]
1442pub trait TransactionIndex {
1443 fn index(
1445 &mut self,
1446 extrinsic: u32,
1447 size: u32,
1448 context_hash: PassPointerAndReadCopy<[u8; 32], 32>,
1449 ) {
1450 self.storage_index_transaction(extrinsic, &context_hash, size);
1451 }
1452
1453 fn renew(&mut self, extrinsic: u32, context_hash: PassPointerAndReadCopy<[u8; 32], 32>) {
1456 self.storage_renew_transaction_index(extrinsic, &context_hash);
1457 }
1458}
1459
1460#[runtime_interface]
1462pub trait OffchainIndex {
1463 fn set(&mut self, key: PassFatPointerAndRead<&[u8]>, value: PassFatPointerAndRead<&[u8]>) {
1465 self.set_offchain_storage(key, Some(value));
1466 }
1467
1468 fn clear(&mut self, key: PassFatPointerAndRead<&[u8]>) {
1470 self.set_offchain_storage(key, None);
1471 }
1472}
1473
1474#[cfg(not(substrate_runtime))]
1475sp_externalities::decl_extension! {
1476 struct VerificationExtDeprecated(bool);
1480}
1481
1482#[runtime_interface]
1486pub trait Offchain {
1487 fn is_validator(&mut self) -> bool {
1492 self.extension::<OffchainWorkerExt>()
1493 .expect("is_validator can be called only in the offchain worker context")
1494 .is_validator()
1495 }
1496
1497 fn submit_transaction(
1501 &mut self,
1502 data: PassFatPointerAndRead<Vec<u8>>,
1503 ) -> AllocateAndReturnByCodec<Result<(), ()>> {
1504 self.extension::<TransactionPoolExt>()
1505 .expect(
1506 "submit_transaction can be called only in the offchain call context with
1507 TransactionPool capabilities enabled",
1508 )
1509 .submit_transaction(data)
1510 }
1511
1512 fn network_state(&mut self) -> AllocateAndReturnByCodec<Result<OpaqueNetworkState, ()>> {
1514 self.extension::<OffchainWorkerExt>()
1515 .expect("network_state can be called only in the offchain worker context")
1516 .network_state()
1517 }
1518
1519 fn timestamp(&mut self) -> ReturnAs<Timestamp, u64> {
1521 self.extension::<OffchainWorkerExt>()
1522 .expect("timestamp can be called only in the offchain worker context")
1523 .timestamp()
1524 }
1525
1526 fn sleep_until(&mut self, deadline: PassAs<Timestamp, u64>) {
1528 self.extension::<OffchainWorkerExt>()
1529 .expect("sleep_until can be called only in the offchain worker context")
1530 .sleep_until(deadline)
1531 }
1532
1533 fn random_seed(&mut self) -> AllocateAndReturnPointer<[u8; 32], 32> {
1538 self.extension::<OffchainWorkerExt>()
1539 .expect("random_seed can be called only in the offchain worker context")
1540 .random_seed()
1541 }
1542
1543 fn local_storage_set(
1548 &mut self,
1549 kind: PassAs<StorageKind, u32>,
1550 key: PassFatPointerAndRead<&[u8]>,
1551 value: PassFatPointerAndRead<&[u8]>,
1552 ) {
1553 self.extension::<OffchainDbExt>()
1554 .expect(
1555 "local_storage_set can be called only in the offchain call context with
1556 OffchainDb extension",
1557 )
1558 .local_storage_set(kind, key, value)
1559 }
1560
1561 fn local_storage_clear(
1566 &mut self,
1567 kind: PassAs<StorageKind, u32>,
1568 key: PassFatPointerAndRead<&[u8]>,
1569 ) {
1570 self.extension::<OffchainDbExt>()
1571 .expect(
1572 "local_storage_clear can be called only in the offchain call context with
1573 OffchainDb extension",
1574 )
1575 .local_storage_clear(kind, key)
1576 }
1577
1578 fn local_storage_compare_and_set(
1588 &mut self,
1589 kind: PassAs<StorageKind, u32>,
1590 key: PassFatPointerAndRead<&[u8]>,
1591 old_value: PassFatPointerAndDecode<Option<Vec<u8>>>,
1592 new_value: PassFatPointerAndRead<&[u8]>,
1593 ) -> bool {
1594 self.extension::<OffchainDbExt>()
1595 .expect(
1596 "local_storage_compare_and_set can be called only in the offchain call context
1597 with OffchainDb extension",
1598 )
1599 .local_storage_compare_and_set(kind, key, old_value.as_deref(), new_value)
1600 }
1601
1602 fn local_storage_get(
1608 &mut self,
1609 kind: PassAs<StorageKind, u32>,
1610 key: PassFatPointerAndRead<&[u8]>,
1611 ) -> AllocateAndReturnByCodec<Option<Vec<u8>>> {
1612 self.extension::<OffchainDbExt>()
1613 .expect(
1614 "local_storage_get can be called only in the offchain call context with
1615 OffchainDb extension",
1616 )
1617 .local_storage_get(kind, key)
1618 }
1619
1620 fn http_request_start(
1625 &mut self,
1626 method: PassFatPointerAndRead<&str>,
1627 uri: PassFatPointerAndRead<&str>,
1628 meta: PassFatPointerAndRead<&[u8]>,
1629 ) -> AllocateAndReturnByCodec<Result<HttpRequestId, ()>> {
1630 self.extension::<OffchainWorkerExt>()
1631 .expect("http_request_start can be called only in the offchain worker context")
1632 .http_request_start(method, uri, meta)
1633 }
1634
1635 fn http_request_add_header(
1637 &mut self,
1638 request_id: PassAs<HttpRequestId, u16>,
1639 name: PassFatPointerAndRead<&str>,
1640 value: PassFatPointerAndRead<&str>,
1641 ) -> AllocateAndReturnByCodec<Result<(), ()>> {
1642 self.extension::<OffchainWorkerExt>()
1643 .expect("http_request_add_header can be called only in the offchain worker context")
1644 .http_request_add_header(request_id, name, value)
1645 }
1646
1647 fn http_request_write_body(
1654 &mut self,
1655 request_id: PassAs<HttpRequestId, u16>,
1656 chunk: PassFatPointerAndRead<&[u8]>,
1657 deadline: PassFatPointerAndDecode<Option<Timestamp>>,
1658 ) -> AllocateAndReturnByCodec<Result<(), HttpError>> {
1659 self.extension::<OffchainWorkerExt>()
1660 .expect("http_request_write_body can be called only in the offchain worker context")
1661 .http_request_write_body(request_id, chunk, deadline)
1662 }
1663
1664 fn http_response_wait(
1672 &mut self,
1673 ids: PassFatPointerAndDecodeSlice<&[HttpRequestId]>,
1674 deadline: PassFatPointerAndDecode<Option<Timestamp>>,
1675 ) -> AllocateAndReturnByCodec<Vec<HttpRequestStatus>> {
1676 self.extension::<OffchainWorkerExt>()
1677 .expect("http_response_wait can be called only in the offchain worker context")
1678 .http_response_wait(ids, deadline)
1679 }
1680
1681 fn http_response_headers(
1686 &mut self,
1687 request_id: PassAs<HttpRequestId, u16>,
1688 ) -> AllocateAndReturnByCodec<Vec<(Vec<u8>, Vec<u8>)>> {
1689 self.extension::<OffchainWorkerExt>()
1690 .expect("http_response_headers can be called only in the offchain worker context")
1691 .http_response_headers(request_id)
1692 }
1693
1694 fn http_response_read_body(
1703 &mut self,
1704 request_id: PassAs<HttpRequestId, u16>,
1705 buffer: PassFatPointerAndReadWrite<&mut [u8]>,
1706 deadline: PassFatPointerAndDecode<Option<Timestamp>>,
1707 ) -> AllocateAndReturnByCodec<Result<u32, HttpError>> {
1708 self.extension::<OffchainWorkerExt>()
1709 .expect("http_response_read_body can be called only in the offchain worker context")
1710 .http_response_read_body(request_id, buffer, deadline)
1711 .map(|r| r as u32)
1712 }
1713
1714 fn set_authorized_nodes(
1716 &mut self,
1717 nodes: PassFatPointerAndDecode<Vec<OpaquePeerId>>,
1718 authorized_only: bool,
1719 ) {
1720 self.extension::<OffchainWorkerExt>()
1721 .expect("set_authorized_nodes can be called only in the offchain worker context")
1722 .set_authorized_nodes(nodes, authorized_only)
1723 }
1724}
1725
1726#[runtime_interface(wasm_only)]
1728pub trait Allocator {
1729 fn malloc(&mut self, size: u32) -> Pointer<u8> {
1731 self.allocate_memory(size).expect("Failed to allocate memory")
1732 }
1733
1734 fn free(&mut self, ptr: Pointer<u8>) {
1736 self.deallocate_memory(ptr).expect("Failed to deallocate memory")
1737 }
1738}
1739
1740#[runtime_interface(wasm_only)]
1743pub trait PanicHandler {
1744 #[trap_on_return]
1746 fn abort_on_panic(&mut self, message: PassFatPointerAndRead<&str>) {
1747 self.register_panic_error_message(message);
1748 }
1749}
1750
1751#[runtime_interface]
1753pub trait Logging {
1754 fn log(
1761 level: PassAs<RuntimeInterfaceLogLevel, u8>,
1762 target: PassFatPointerAndRead<&str>,
1763 message: PassFatPointerAndRead<&[u8]>,
1764 ) {
1765 if let Ok(message) = core::str::from_utf8(message) {
1766 log::log!(target: target, log::Level::from(level), "{}", message)
1767 }
1768 }
1769
1770 fn max_level() -> ReturnAs<LogLevelFilter, u8> {
1772 log::max_level().into()
1773 }
1774}
1775
1776#[runtime_interface(wasm_only, no_tracing)]
1779pub trait WasmTracing {
1780 fn enabled(&mut self, metadata: PassFatPointerAndDecode<sp_tracing::WasmMetadata>) -> bool {
1790 let metadata: &tracing_core::metadata::Metadata<'static> = (&metadata).into();
1791 tracing::dispatcher::get_default(|d| d.enabled(metadata))
1792 }
1793
1794 fn enter_span(
1801 &mut self,
1802 span: PassFatPointerAndDecode<sp_tracing::WasmEntryAttributes>,
1803 ) -> u64 {
1804 let span: tracing::Span = span.into();
1805 match span.id() {
1806 Some(id) => tracing::dispatcher::get_default(|d| {
1807 let final_id = d.clone_span(&id);
1810 d.enter(&final_id);
1811 final_id.into_u64()
1812 }),
1813 _ => 0,
1814 }
1815 }
1816
1817 fn event(&mut self, event: PassFatPointerAndDecode<sp_tracing::WasmEntryAttributes>) {
1819 event.emit();
1820 }
1821
1822 fn exit(&mut self, span: u64) {
1825 tracing::dispatcher::get_default(|d| {
1826 let id = tracing_core::span::Id::from_u64(span);
1827 d.exit(&id);
1828 });
1829 }
1830}
1831
1832#[cfg(all(substrate_runtime, feature = "with-tracing"))]
1833mod tracing_setup {
1834 use super::wasm_tracing;
1835 use core::sync::atomic::{AtomicBool, Ordering};
1836 use tracing_core::{
1837 dispatcher::{set_global_default, Dispatch},
1838 span::{Attributes, Id, Record},
1839 Event, Metadata,
1840 };
1841
1842 static TRACING_SET: AtomicBool = AtomicBool::new(false);
1843
1844 struct PassingTracingSubscriber;
1847
1848 impl tracing_core::Subscriber for PassingTracingSubscriber {
1849 fn enabled(&self, metadata: &Metadata<'_>) -> bool {
1850 wasm_tracing::enabled(metadata.into())
1851 }
1852 fn new_span(&self, attrs: &Attributes<'_>) -> Id {
1853 Id::from_u64(wasm_tracing::enter_span(attrs.into()))
1854 }
1855 fn enter(&self, _: &Id) {
1856 }
1858 fn record(&self, _: &Id, _: &Record<'_>) {
1861 unimplemented! {} }
1863 fn record_follows_from(&self, _: &Id, _: &Id) {
1866 unimplemented! {} }
1868 fn event(&self, event: &Event<'_>) {
1869 wasm_tracing::event(event.into())
1870 }
1871 fn exit(&self, span: &Id) {
1872 wasm_tracing::exit(span.into_u64())
1873 }
1874 }
1875
1876 pub fn init_tracing() {
1880 if TRACING_SET.load(Ordering::Relaxed) == false {
1881 set_global_default(Dispatch::new(PassingTracingSubscriber {}))
1882 .expect("We only ever call this once");
1883 TRACING_SET.store(true, Ordering::Relaxed);
1884 }
1885 }
1886}
1887
1888#[cfg(not(all(substrate_runtime, feature = "with-tracing")))]
1889mod tracing_setup {
1890 pub fn init_tracing() {}
1893}
1894
1895pub use tracing_setup::init_tracing;
1896
1897pub fn unreachable() -> ! {
1902 #[cfg(target_family = "wasm")]
1903 {
1904 core::arch::wasm32::unreachable();
1905 }
1906
1907 #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
1908 unsafe {
1909 core::arch::asm!("unimp", options(noreturn));
1910 }
1911
1912 #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64", target_family = "wasm")))]
1913 unreachable!();
1914}
1915
1916#[cfg(all(not(feature = "disable_panic_handler"), substrate_runtime))]
1918#[panic_handler]
1919pub fn panic(info: &core::panic::PanicInfo) -> ! {
1920 let message = alloc::format!("{}", info);
1921 #[cfg(feature = "improved_panic_error_reporting")]
1922 {
1923 panic_handler::abort_on_panic(&message);
1924 }
1925 #[cfg(not(feature = "improved_panic_error_reporting"))]
1926 {
1927 logging::log(RuntimeInterfaceLogLevel::Error, "runtime", message.as_bytes());
1928 unreachable();
1929 }
1930}
1931
1932#[cfg(all(not(feature = "disable_oom"), enable_alloc_error_handler))]
1934#[alloc_error_handler]
1935pub fn oom(_: core::alloc::Layout) -> ! {
1936 #[cfg(feature = "improved_panic_error_reporting")]
1937 {
1938 panic_handler::abort_on_panic("Runtime memory exhausted.");
1939 }
1940 #[cfg(not(feature = "improved_panic_error_reporting"))]
1941 {
1942 logging::log(
1943 RuntimeInterfaceLogLevel::Error,
1944 "runtime",
1945 b"Runtime memory exhausted. Aborting",
1946 );
1947 unreachable();
1948 }
1949}
1950
1951#[cfg(feature = "std")] pub type TestExternalities = sp_state_machine::TestExternalities<sp_core::Blake2Hasher>;
1954
1955#[docify::export]
1959#[cfg(not(substrate_runtime))]
1960pub type SubstrateHostFunctions = (
1961 storage::HostFunctions,
1962 default_child_storage::HostFunctions,
1963 misc::HostFunctions,
1964 wasm_tracing::HostFunctions,
1965 offchain::HostFunctions,
1966 crypto::HostFunctions,
1967 hashing::HostFunctions,
1968 allocator::HostFunctions,
1969 panic_handler::HostFunctions,
1970 logging::HostFunctions,
1971 trie::HostFunctions,
1972 offchain_index::HostFunctions,
1973 transaction_index::HostFunctions,
1974);
1975
1976#[cfg(test)]
1977mod tests {
1978 use super::*;
1979 use sp_core::{crypto::UncheckedInto, map, storage::Storage};
1980 use sp_state_machine::BasicExternalities;
1981
1982 #[test]
1983 fn storage_works() {
1984 let mut t = BasicExternalities::default();
1985 t.execute_with(|| {
1986 assert_eq!(storage::get(b"hello"), None);
1987 storage::set(b"hello", b"world");
1988 assert_eq!(storage::get(b"hello"), Some(b"world".to_vec().into()));
1989 assert_eq!(storage::get(b"foo"), None);
1990 storage::set(b"foo", &[1, 2, 3][..]);
1991 });
1992
1993 t = BasicExternalities::new(Storage {
1994 top: map![b"foo".to_vec() => b"bar".to_vec()],
1995 children_default: map![],
1996 });
1997
1998 t.execute_with(|| {
1999 assert_eq!(storage::get(b"hello"), None);
2000 assert_eq!(storage::get(b"foo"), Some(b"bar".to_vec().into()));
2001 });
2002
2003 let value = vec![7u8; 35];
2004 let storage =
2005 Storage { top: map![b"foo00".to_vec() => value.clone()], children_default: map![] };
2006 t = BasicExternalities::new(storage);
2007
2008 t.execute_with(|| {
2009 assert_eq!(storage::get(b"hello"), None);
2010 assert_eq!(storage::get(b"foo00"), Some(value.clone().into()));
2011 });
2012 }
2013
2014 #[test]
2015 fn read_storage_works() {
2016 let value = b"\x0b\0\0\0Hello world".to_vec();
2017 let mut t = BasicExternalities::new(Storage {
2018 top: map![b":test".to_vec() => value.clone()],
2019 children_default: map![],
2020 });
2021
2022 t.execute_with(|| {
2023 let mut v = [0u8; 4];
2024 assert_eq!(storage::read(b":test", &mut v[..], 0).unwrap(), value.len() as u32);
2025 assert_eq!(v, [11u8, 0, 0, 0]);
2026 let mut w = [0u8; 11];
2027 assert_eq!(storage::read(b":test", &mut w[..], 4).unwrap(), value.len() as u32 - 4);
2028 assert_eq!(&w, b"Hello world");
2029 });
2030 }
2031
2032 #[test]
2033 fn clear_prefix_works() {
2034 let mut t = BasicExternalities::new(Storage {
2035 top: map![
2036 b":a".to_vec() => b"\x0b\0\0\0Hello world".to_vec(),
2037 b":abcd".to_vec() => b"\x0b\0\0\0Hello world".to_vec(),
2038 b":abc".to_vec() => b"\x0b\0\0\0Hello world".to_vec(),
2039 b":abdd".to_vec() => b"\x0b\0\0\0Hello world".to_vec()
2040 ],
2041 children_default: map![],
2042 });
2043
2044 t.execute_with(|| {
2045 assert!(matches!(
2051 storage::clear_prefix(b":abc", None),
2052 KillStorageResult::AllRemoved(2),
2053 ));
2054
2055 assert!(storage::get(b":a").is_some());
2056 assert!(storage::get(b":abdd").is_some());
2057 assert!(storage::get(b":abcd").is_none());
2058 assert!(storage::get(b":abc").is_none());
2059
2060 assert!(matches!(
2066 storage::clear_prefix(b":abc", None),
2067 KillStorageResult::AllRemoved(0),
2068 ));
2069 });
2070 }
2071
2072 fn zero_ed_pub() -> ed25519::Public {
2073 [0u8; 32].unchecked_into()
2074 }
2075
2076 fn zero_ed_sig() -> ed25519::Signature {
2077 ed25519::Signature::from_raw([0u8; 64])
2078 }
2079
2080 #[test]
2081 fn use_dalek_ext_works() {
2082 let mut ext = BasicExternalities::default();
2083 ext.register_extension(UseDalekExt);
2084
2085 ext.execute_with(|| {
2087 assert!(!crypto::ed25519_verify(&zero_ed_sig(), &Vec::new(), &zero_ed_pub()));
2088 });
2089
2090 BasicExternalities::default().execute_with(|| {
2092 assert!(crypto::ed25519_verify(&zero_ed_sig(), &Vec::new(), &zero_ed_pub()));
2093 })
2094 }
2095
2096 #[test]
2097 fn dalek_should_not_panic_on_invalid_signature() {
2098 let mut ext = BasicExternalities::default();
2099 ext.register_extension(UseDalekExt);
2100
2101 ext.execute_with(|| {
2102 let mut bytes = [0u8; 64];
2103 bytes[63] = 0b1110_0000;
2105
2106 assert!(!crypto::ed25519_verify(
2107 &ed25519::Signature::from_raw(bytes),
2108 &Vec::new(),
2109 &zero_ed_pub()
2110 ));
2111 });
2112 }
2113
2114 #[test]
2115 fn secp256k1_ecdsa_recover_valid_signature() {
2116 let pair = ecdsa::Pair::from_seed(b"12345678901234567890123456789012");
2117 let msg = sp_crypto_hashing::blake2_256(b"test message");
2118 let sig = pair.sign_prehashed(&msg);
2119
2120 assert!(ecdsa::is_signature_normalized(&sig.0));
2121
2122 let result = crypto::secp256k1_ecdsa_recover(&sig.0, &msg);
2123 assert!(result.is_ok());
2124 let recovered = ecdsa::Public::from_full(&result.ok().unwrap()).unwrap();
2125 assert_eq!(recovered, pair.public());
2126 }
2127
2128 #[test]
2129 fn secp256k1_ecdsa_recover_compressed_valid_signature() {
2130 let pair = ecdsa::Pair::from_seed(b"12345678901234567890123456789012");
2131 let msg = sp_crypto_hashing::blake2_256(b"test message");
2132 let sig = pair.sign_prehashed(&msg);
2133
2134 let result = crypto::secp256k1_ecdsa_recover_compressed(&sig.0, &msg);
2135 assert!(result.is_ok());
2136 assert_eq!(&result.ok().unwrap()[..], &pair.public().0[..]);
2137 }
2138
2139 #[test]
2140 fn ecdsa_verify_valid_signature() {
2141 let pair = ecdsa::Pair::from_seed(b"12345678901234567890123456789012");
2142 let message = b"test message";
2143 let sig = pair.sign(message);
2144
2145 assert!(ecdsa::is_signature_normalized(&sig.0));
2146 assert!(crypto::ecdsa_verify(&sig, message, &pair.public()));
2147 }
2148
2149 #[test]
2150 fn ecdsa_verify_prehashed_valid_signature() {
2151 let pair = ecdsa::Pair::from_seed(b"12345678901234567890123456789012");
2152 let msg = sp_crypto_hashing::blake2_256(b"test message");
2153 let sig = pair.sign_prehashed(&msg);
2154
2155 assert!(crypto::ecdsa_verify_prehashed(&sig, &msg, &pair.public()));
2156 }
2157
2158 #[test]
2159 fn ecdsa_verify_accepts_high_s_signatures() {
2160 fn make_high_s(sig: &ecdsa::Signature) -> ecdsa::Signature {
2161 let order: [u8; 32] = [
2162 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2163 0xff, 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, 0x8c,
2164 0xd0, 0x36, 0x41, 0x41,
2165 ];
2166 let s: [u8; 32] = sig.0[32..64].try_into().expect("slice has fixed length");
2167 let mut high_s = [0u8; 32];
2168 let mut borrow = 0i16;
2169 for i in (0..32).rev() {
2170 let diff = order[i] as i16 - s[i] as i16 - borrow;
2171 if diff < 0 {
2172 high_s[i] = (diff + 256) as u8;
2173 borrow = 1;
2174 } else {
2175 high_s[i] = diff as u8;
2176 borrow = 0;
2177 }
2178 }
2179
2180 let mut result = sig.0;
2181 result[32..64].copy_from_slice(&high_s);
2182 result[64] ^= 1;
2183 ecdsa::Signature::from_raw(result)
2184 }
2185
2186 let pair = ecdsa::Pair::from_seed(b"12345678901234567890123456789012");
2187 let message = b"test message";
2188 let signature = make_high_s(&pair.sign(message));
2189 assert!(!ecdsa::is_signature_normalized(&signature.0));
2190 assert!(crypto::ecdsa_verify(&signature, message, &pair.public()));
2191
2192 let prehash = sp_crypto_hashing::blake2_256(message);
2193 let signature = make_high_s(&pair.sign_prehashed(&prehash));
2194 assert!(!ecdsa::is_signature_normalized(&signature.0));
2195 assert!(crypto::ecdsa_verify_prehashed(&signature, &prehash, &pair.public()));
2196 }
2197}