1#![warn(missing_docs)]
21
22#![cfg_attr(not(feature = "std"), no_std)]
23#![cfg_attr(not(feature = "std"), feature(alloc_error_handler))]
24
25#![cfg_attr(feature = "std",
26 doc = "Tetcore runtime standard library as compiled when linked with Rust's standard library.")]
27#![cfg_attr(not(feature = "std"),
28 doc = "Tetcore's runtime standard library as compiled without Rust's standard library.")]
29
30use tetcore_std::vec::Vec;
31
32#[cfg(feature = "std")]
33use tetcore_std::ops::Deref;
34
35#[cfg(feature = "std")]
36use tracing;
37
38#[cfg(feature = "std")]
39use tet_core::{
40 crypto::Pair,
41 traits::{CallInWasmExt, TaskExecutorExt, RuntimeSpawnExt},
42 offchain::{OffchainExt, TransactionPoolExt},
43 hexdisplay::HexDisplay,
44 storage::ChildInfo,
45};
46#[cfg(feature = "std")]
47use tp_keystore::{KeystoreExt, SyncCryptoStore};
48
49use tet_core::{
50 OpaquePeerId, crypto::KeyTypeId, ed25519, sr25519, ecdsa, H256, LogLevel,
51 offchain::{
52 Timestamp, HttpRequestId, HttpRequestStatus, HttpError, StorageKind, OpaqueNetworkState,
53 },
54};
55
56#[cfg(feature = "std")]
57use tp_trie::{TrieConfiguration, trie_types::Layout};
58
59use tp_runtime_interface::{runtime_interface, Pointer};
60use tp_runtime_interface::pass_by::PassBy;
61
62use codec::{Encode, Decode};
63
64#[cfg(feature = "std")]
65use externalities::{ExternalitiesExt, Externalities};
66
67#[cfg(feature = "std")]
68mod batch_verifier;
69
70#[cfg(feature = "std")]
71use batch_verifier::BatchVerifier;
72
73#[derive(Encode, Decode)]
75pub enum EcdsaVerifyError {
76 BadRS,
78 BadV,
80 BadSignature,
82}
83
84#[runtime_interface]
86pub trait Storage {
87 fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
89 self.storage(key).map(|s| s.to_vec())
90 }
91
92 fn read(&self, key: &[u8], value_out: &mut [u8], value_offset: u32) -> Option<u32> {
98 self.storage(key).map(|value| {
99 let value_offset = value_offset as usize;
100 let data = &value[value_offset.min(value.len())..];
101 let written = std::cmp::min(data.len(), value_out.len());
102 value_out[..written].copy_from_slice(&data[..written]);
103 data.len() as u32
104 })
105 }
106
107 fn set(&mut self, key: &[u8], value: &[u8]) {
109 self.set_storage(key.to_vec(), value.to_vec());
110 }
111
112 fn clear(&mut self, key: &[u8]) {
114 self.clear_storage(key)
115 }
116
117 fn exists(&self, key: &[u8]) -> bool {
119 self.exists_storage(key)
120 }
121
122 fn clear_prefix(&mut self, prefix: &[u8]) {
124 Externalities::clear_prefix(*self, prefix)
125 }
126
127 fn append(&mut self, key: &[u8], value: Vec<u8>) {
136 self.storage_append(key.to_vec(), value);
137 }
138
139 fn root(&mut self) -> Vec<u8> {
145 self.storage_root()
146 }
147
148 fn changes_root(&mut self, parent_hash: &[u8]) -> Option<Vec<u8>> {
156 self.storage_changes_root(parent_hash)
157 .expect("Invalid `parent_hash` given to `changes_root`.")
158 }
159
160 fn next_key(&mut self, key: &[u8]) -> Option<Vec<u8>> {
162 self.next_storage_key(&key)
163 }
164
165 fn start_transaction(&mut self) {
178 self.storage_start_transaction();
179 }
180
181 fn rollback_transaction(&mut self) {
189 self.storage_rollback_transaction()
190 .expect("No open transaction that can be rolled back.");
191 }
192
193 fn commit_transaction(&mut self) {
201 self.storage_commit_transaction()
202 .expect("No open transaction that can be committed.");
203 }
204}
205
206#[runtime_interface]
209pub trait DefaultChildStorage {
210 fn get(
215 &self,
216 storage_key: &[u8],
217 key: &[u8],
218 ) -> Option<Vec<u8>> {
219 let child_info = ChildInfo::new_default(storage_key);
220 self.child_storage(&child_info, key).map(|s| s.to_vec())
221 }
222
223 fn read(
231 &self,
232 storage_key: &[u8],
233 key: &[u8],
234 value_out: &mut [u8],
235 value_offset: u32,
236 ) -> Option<u32> {
237 let child_info = ChildInfo::new_default(storage_key);
238 self.child_storage(&child_info, key)
239 .map(|value| {
240 let value_offset = value_offset as usize;
241 let data = &value[value_offset.min(value.len())..];
242 let written = std::cmp::min(data.len(), value_out.len());
243 value_out[..written].copy_from_slice(&data[..written]);
244 data.len() as u32
245 })
246 }
247
248 fn set(
252 &mut self,
253 storage_key: &[u8],
254 key: &[u8],
255 value: &[u8],
256 ) {
257 let child_info = ChildInfo::new_default(storage_key);
258 self.set_child_storage(&child_info, key.to_vec(), value.to_vec());
259 }
260
261 fn clear(
265 &mut self,
266 storage_key: &[u8],
267 key: &[u8],
268 ) {
269 let child_info = ChildInfo::new_default(storage_key);
270 self.clear_child_storage(&child_info, key);
271 }
272
273 fn storage_kill(
278 &mut self,
279 storage_key: &[u8],
280 ) {
281 let child_info = ChildInfo::new_default(storage_key);
282 self.kill_child_storage(&child_info, None);
283 }
284
285 #[version(2)]
308 fn storage_kill(&mut self, storage_key: &[u8], limit: Option<u32>) -> bool {
309 let child_info = ChildInfo::new_default(storage_key);
310 self.kill_child_storage(&child_info, limit)
311 }
312
313 fn exists(
317 &self,
318 storage_key: &[u8],
319 key: &[u8],
320 ) -> bool {
321 let child_info = ChildInfo::new_default(storage_key);
322 self.exists_child_storage(&child_info, key)
323 }
324
325 fn clear_prefix(
329 &mut self,
330 storage_key: &[u8],
331 prefix: &[u8],
332 ) {
333 let child_info = ChildInfo::new_default(storage_key);
334 self.clear_child_prefix(&child_info, prefix);
335 }
336
337 fn root(
344 &mut self,
345 storage_key: &[u8],
346 ) -> Vec<u8> {
347 let child_info = ChildInfo::new_default(storage_key);
348 self.child_storage_root(&child_info)
349 }
350
351 fn next_key(
355 &mut self,
356 storage_key: &[u8],
357 key: &[u8],
358 ) -> Option<Vec<u8>> {
359 let child_info = ChildInfo::new_default(storage_key);
360 self.next_child_storage_key(&child_info, key)
361 }
362}
363
364#[runtime_interface]
366pub trait Trie {
367 fn blake2_256_root(input: Vec<(Vec<u8>, Vec<u8>)>) -> H256 {
369 Layout::<tet_core::Blake2Hasher>::tetsy_trie_root(input)
370 }
371
372 fn blake2_256_ordered_root(input: Vec<Vec<u8>>) -> H256 {
374 Layout::<tet_core::Blake2Hasher>::ordered_tetsy_trie_root(input)
375 }
376
377 fn keccak_256_root(input: Vec<(Vec<u8>, Vec<u8>)>) -> H256 {
379 Layout::<tet_core::KeccakHasher>::tetsy_trie_root(input)
380 }
381
382 fn keccak_256_ordered_root(input: Vec<Vec<u8>>) -> H256 {
384 Layout::<tet_core::KeccakHasher>::ordered_tetsy_trie_root(input)
385 }
386}
387
388#[runtime_interface]
390pub trait Misc {
391 fn print_num(val: u64) {
393 log::debug!(target: "runtime", "{}", val);
394 }
395
396 fn print_utf8(utf8: &[u8]) {
398 if let Ok(data) = std::str::from_utf8(utf8) {
399 log::debug!(target: "runtime", "{}", data)
400 }
401 }
402
403 fn print_hex(data: &[u8]) {
405 log::debug!(target: "runtime", "{}", HexDisplay::from(&data));
406 }
407
408 fn runtime_version(&mut self, wasm: &[u8]) -> Option<Vec<u8>> {
419 let mut ext = tp_state_machine::BasicExternalities::default();
421
422 self.extension::<CallInWasmExt>()
423 .expect("No `CallInWasmExt` associated for the current context!")
424 .call_in_wasm(
425 wasm,
426 None,
427 "Core_version",
428 &[],
429 &mut ext,
430 tet_core::traits::MissingHostFunctions::Allow,
435 )
436 .ok()
437 }
438}
439
440#[runtime_interface]
442pub trait Crypto {
443 fn ed25519_public_keys(&mut self, id: KeyTypeId) -> Vec<ed25519::Public> {
445 let keystore = &***self.extension::<KeystoreExt>()
446 .expect("No `keystore` associated for the current context!");
447 SyncCryptoStore::ed25519_public_keys(keystore, id)
448 }
449
450 fn ed25519_generate(&mut self, id: KeyTypeId, seed: Option<Vec<u8>>) -> ed25519::Public {
457 let seed = seed.as_ref().map(|s| std::str::from_utf8(&s).expect("Seed is valid utf8!"));
458 let keystore = &***self.extension::<KeystoreExt>()
459 .expect("No `keystore` associated for the current context!");
460 SyncCryptoStore::ed25519_generate_new(keystore, id, seed)
461 .expect("`ed25519_generate` failed")
462 }
463
464 fn ed25519_sign(
469 &mut self,
470 id: KeyTypeId,
471 pub_key: &ed25519::Public,
472 msg: &[u8],
473 ) -> Option<ed25519::Signature> {
474 let keystore = &***self.extension::<KeystoreExt>()
475 .expect("No `keystore` associated for the current context!");
476 SyncCryptoStore::sign_with(keystore, id, &pub_key.into(), msg)
477 .map(|sig| ed25519::Signature::from_slice(sig.as_slice()))
478 .ok()
479 }
480
481 fn ed25519_verify(
485 sig: &ed25519::Signature,
486 msg: &[u8],
487 pub_key: &ed25519::Public,
488 ) -> bool {
489 ed25519::Pair::verify(sig, msg, pub_key)
490 }
491
492 fn ed25519_batch_verify(
501 &mut self,
502 sig: &ed25519::Signature,
503 msg: &[u8],
504 pub_key: &ed25519::Public,
505 ) -> bool {
506 self.extension::<VerificationExt>().map(
507 |extension| extension.push_ed25519(sig.clone(), pub_key.clone(), msg.to_vec())
508 ).unwrap_or_else(|| ed25519_verify(sig, msg, pub_key))
509 }
510
511 #[version(2)]
515 fn sr25519_verify(
516 sig: &sr25519::Signature,
517 msg: &[u8],
518 pub_key: &sr25519::Public,
519 ) -> bool {
520 sr25519::Pair::verify(sig, msg, pub_key)
521 }
522
523 fn sr25519_batch_verify(
532 &mut self,
533 sig: &sr25519::Signature,
534 msg: &[u8],
535 pub_key: &sr25519::Public,
536 ) -> bool {
537 self.extension::<VerificationExt>().map(
538 |extension| extension.push_sr25519(sig.clone(), pub_key.clone(), msg.to_vec())
539 ).unwrap_or_else(|| sr25519_verify(sig, msg, pub_key))
540 }
541
542 fn start_batch_verify(&mut self) {
544 let scheduler = self.extension::<TaskExecutorExt>()
545 .expect("No task executor associated with the current context!")
546 .clone();
547
548 self.register_extension(VerificationExt(BatchVerifier::new(scheduler)))
549 .expect("Failed to register required extension: `VerificationExt`");
550 }
551
552 fn finish_batch_verify(&mut self) -> bool {
559 let result = self.extension::<VerificationExt>()
560 .expect("`finish_batch_verify` should only be called after `start_batch_verify`")
561 .verify_and_clear();
562
563 self.deregister_extension::<VerificationExt>()
564 .expect("No verification extension in current context!");
565
566 result
567 }
568
569 fn sr25519_public_keys(&mut self, id: KeyTypeId) -> Vec<sr25519::Public> {
571 let keystore = &*** self.extension::<KeystoreExt>()
572 .expect("No `keystore` associated for the current context!");
573 SyncCryptoStore::sr25519_public_keys(keystore, id)
574 }
575
576 fn sr25519_generate(&mut self, id: KeyTypeId, seed: Option<Vec<u8>>) -> sr25519::Public {
583 let seed = seed.as_ref().map(|s| std::str::from_utf8(&s).expect("Seed is valid utf8!"));
584 let keystore = &***self.extension::<KeystoreExt>()
585 .expect("No `keystore` associated for the current context!");
586 SyncCryptoStore::sr25519_generate_new(keystore, id, seed)
587 .expect("`sr25519_generate` failed")
588 }
589
590 fn sr25519_sign(
595 &mut self,
596 id: KeyTypeId,
597 pub_key: &sr25519::Public,
598 msg: &[u8],
599 ) -> Option<sr25519::Signature> {
600 let keystore = &***self.extension::<KeystoreExt>()
601 .expect("No `keystore` associated for the current context!");
602 SyncCryptoStore::sign_with(keystore, id, &pub_key.into(), msg)
603 .map(|sig| sr25519::Signature::from_slice(sig.as_slice()))
604 .ok()
605 }
606
607 fn sr25519_verify(sig: &sr25519::Signature, msg: &[u8], pubkey: &sr25519::Public) -> bool {
612 sr25519::Pair::verify_deprecated(sig, msg, pubkey)
613 }
614
615 fn ecdsa_public_keys(&mut self, id: KeyTypeId) -> Vec<ecdsa::Public> {
617 let keystore = &***self.extension::<KeystoreExt>()
618 .expect("No `keystore` associated for the current context!");
619 SyncCryptoStore::ecdsa_public_keys(keystore, id)
620 }
621
622 fn ecdsa_generate(&mut self, id: KeyTypeId, seed: Option<Vec<u8>>) -> ecdsa::Public {
629 let seed = seed.as_ref().map(|s| std::str::from_utf8(&s).expect("Seed is valid utf8!"));
630 let keystore = &***self.extension::<KeystoreExt>()
631 .expect("No `keystore` associated for the current context!");
632 SyncCryptoStore::ecdsa_generate_new(keystore, id, seed)
633 .expect("`ecdsa_generate` failed")
634 }
635
636 fn ecdsa_sign(
641 &mut self,
642 id: KeyTypeId,
643 pub_key: &ecdsa::Public,
644 msg: &[u8],
645 ) -> Option<ecdsa::Signature> {
646 let keystore = &***self.extension::<KeystoreExt>()
647 .expect("No `keystore` associated for the current context!");
648 SyncCryptoStore::sign_with(keystore, id, &pub_key.into(), msg)
649 .map(|sig| ecdsa::Signature::from_slice(sig.as_slice()))
650 .ok()
651 }
652
653 fn ecdsa_verify(
657 sig: &ecdsa::Signature,
658 msg: &[u8],
659 pub_key: &ecdsa::Public,
660 ) -> bool {
661 ecdsa::Pair::verify(sig, msg, pub_key)
662 }
663
664 fn ecdsa_batch_verify(
673 &mut self,
674 sig: &ecdsa::Signature,
675 msg: &[u8],
676 pub_key: &ecdsa::Public,
677 ) -> bool {
678 self.extension::<VerificationExt>().map(
679 |extension| extension.push_ecdsa(sig.clone(), pub_key.clone(), msg.to_vec())
680 ).unwrap_or_else(|| ecdsa_verify(sig, msg, pub_key))
681 }
682
683 fn secp256k1_ecdsa_recover(
691 sig: &[u8; 65],
692 msg: &[u8; 32],
693 ) -> Result<[u8; 64], EcdsaVerifyError> {
694 let rs = secp256k1::Signature::parse_slice(&sig[0..64])
695 .map_err(|_| EcdsaVerifyError::BadRS)?;
696 let v = secp256k1::RecoveryId::parse(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8)
697 .map_err(|_| EcdsaVerifyError::BadV)?;
698 let pubkey = secp256k1::recover(&secp256k1::Message::parse(msg), &rs, &v)
699 .map_err(|_| EcdsaVerifyError::BadSignature)?;
700 let mut res = [0u8; 64];
701 res.copy_from_slice(&pubkey.serialize()[1..65]);
702 Ok(res)
703 }
704
705 fn secp256k1_ecdsa_recover_compressed(
712 sig: &[u8; 65],
713 msg: &[u8; 32],
714 ) -> Result<[u8; 33], EcdsaVerifyError> {
715 let rs = secp256k1::Signature::parse_slice(&sig[0..64])
716 .map_err(|_| EcdsaVerifyError::BadRS)?;
717 let v = secp256k1::RecoveryId::parse(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8)
718 .map_err(|_| EcdsaVerifyError::BadV)?;
719 let pubkey = secp256k1::recover(&secp256k1::Message::parse(msg), &rs, &v)
720 .map_err(|_| EcdsaVerifyError::BadSignature)?;
721 Ok(pubkey.serialize_compressed())
722 }
723}
724
725#[runtime_interface]
727pub trait Hashing {
728 fn keccak_256(data: &[u8]) -> [u8; 32] {
730 tet_core::hashing::keccak_256(data)
731 }
732
733 fn keccak_512(data: &[u8]) -> [u8; 64] {
735 tet_core::hashing::keccak_512(data)
736 }
737
738 fn sha2_256(data: &[u8]) -> [u8; 32] {
740 tet_core::hashing::sha2_256(data)
741 }
742
743 fn blake2_128(data: &[u8]) -> [u8; 16] {
745 tet_core::hashing::blake2_128(data)
746 }
747
748 fn blake2_256(data: &[u8]) -> [u8; 32] {
750 tet_core::hashing::blake2_256(data)
751 }
752
753 fn twox_256(data: &[u8]) -> [u8; 32] {
755 tet_core::hashing::twox_256(data)
756 }
757
758 fn twox_128(data: &[u8]) -> [u8; 16] {
760 tet_core::hashing::twox_128(data)
761 }
762
763 fn twox_64(data: &[u8]) -> [u8; 8] {
765 tet_core::hashing::twox_64(data)
766 }
767}
768
769#[runtime_interface]
771pub trait OffchainIndex {
772 fn set(&mut self, key: &[u8], value: &[u8]) {
774 self.set_offchain_storage(key, Some(value));
775 }
776
777 fn clear(&mut self, key: &[u8]) {
779 self.set_offchain_storage(key, None);
780 }
781}
782
783#[cfg(feature = "std")]
784externalities::decl_extension! {
785 pub struct VerificationExt(BatchVerifier);
787}
788
789#[runtime_interface]
793pub trait Offchain {
794 fn is_validator(&mut self) -> bool {
799 self.extension::<OffchainExt>()
800 .expect("is_validator can be called only in the offchain worker context")
801 .is_validator()
802 }
803
804 fn submit_transaction(&mut self, data: Vec<u8>) -> Result<(), ()> {
808 self.extension::<TransactionPoolExt>()
809 .expect("submit_transaction can be called only in the offchain call context with
810 TransactionPool capabilities enabled")
811 .submit_transaction(data)
812 }
813
814 fn network_state(&mut self) -> Result<OpaqueNetworkState, ()> {
816 self.extension::<OffchainExt>()
817 .expect("network_state can be called only in the offchain worker context")
818 .network_state()
819 }
820
821 fn timestamp(&mut self) -> Timestamp {
823 self.extension::<OffchainExt>()
824 .expect("timestamp can be called only in the offchain worker context")
825 .timestamp()
826 }
827
828 fn sleep_until(&mut self, deadline: Timestamp) {
830 self.extension::<OffchainExt>()
831 .expect("sleep_until can be called only in the offchain worker context")
832 .sleep_until(deadline)
833 }
834
835 fn random_seed(&mut self) -> [u8; 32] {
840 self.extension::<OffchainExt>()
841 .expect("random_seed can be called only in the offchain worker context")
842 .random_seed()
843 }
844
845 fn local_storage_set(&mut self, kind: StorageKind, key: &[u8], value: &[u8]) {
850 self.extension::<OffchainExt>()
851 .expect("local_storage_set can be called only in the offchain worker context")
852 .local_storage_set(kind, key, value)
853 }
854
855 fn local_storage_clear(&mut self, kind: StorageKind, key: &[u8]) {
860 self.extension::<OffchainExt>()
861 .expect("local_storage_clear can be called only in the offchain worker context")
862 .local_storage_clear(kind, key)
863 }
864
865 fn local_storage_compare_and_set(
875 &mut self,
876 kind: StorageKind,
877 key: &[u8],
878 old_value: Option<Vec<u8>>,
879 new_value: &[u8],
880 ) -> bool {
881 self.extension::<OffchainExt>()
882 .expect("local_storage_compare_and_set can be called only in the offchain worker context")
883 .local_storage_compare_and_set(kind, key, old_value.as_ref().map(|v| v.deref()), new_value)
884 }
885
886 fn local_storage_get(&mut self, kind: StorageKind, key: &[u8]) -> Option<Vec<u8>> {
892 self.extension::<OffchainExt>()
893 .expect("local_storage_get can be called only in the offchain worker context")
894 .local_storage_get(kind, key)
895 }
896
897 fn http_request_start(
902 &mut self,
903 method: &str,
904 uri: &str,
905 meta: &[u8],
906 ) -> Result<HttpRequestId, ()> {
907 self.extension::<OffchainExt>()
908 .expect("http_request_start can be called only in the offchain worker context")
909 .http_request_start(method, uri, meta)
910 }
911
912 fn http_request_add_header(
914 &mut self,
915 request_id: HttpRequestId,
916 name: &str,
917 value: &str,
918 ) -> Result<(), ()> {
919 self.extension::<OffchainExt>()
920 .expect("http_request_add_header can be called only in the offchain worker context")
921 .http_request_add_header(request_id, name, value)
922 }
923
924 fn http_request_write_body(
931 &mut self,
932 request_id: HttpRequestId,
933 chunk: &[u8],
934 deadline: Option<Timestamp>,
935 ) -> Result<(), HttpError> {
936 self.extension::<OffchainExt>()
937 .expect("http_request_write_body can be called only in the offchain worker context")
938 .http_request_write_body(request_id, chunk, deadline)
939 }
940
941 fn http_response_wait(
949 &mut self,
950 ids: &[HttpRequestId],
951 deadline: Option<Timestamp>,
952 ) -> Vec<HttpRequestStatus> {
953 self.extension::<OffchainExt>()
954 .expect("http_response_wait can be called only in the offchain worker context")
955 .http_response_wait(ids, deadline)
956 }
957
958 fn http_response_headers(&mut self, request_id: HttpRequestId) -> Vec<(Vec<u8>, Vec<u8>)> {
963 self.extension::<OffchainExt>()
964 .expect("http_response_headers can be called only in the offchain worker context")
965 .http_response_headers(request_id)
966 }
967
968 fn http_response_read_body(
977 &mut self,
978 request_id: HttpRequestId,
979 buffer: &mut [u8],
980 deadline: Option<Timestamp>,
981 ) -> Result<u32, HttpError> {
982 self.extension::<OffchainExt>()
983 .expect("http_response_read_body can be called only in the offchain worker context")
984 .http_response_read_body(request_id, buffer, deadline)
985 .map(|r| r as u32)
986 }
987
988 fn set_authorized_nodes(&mut self, nodes: Vec<OpaquePeerId>, authorized_only: bool) {
990 self.extension::<OffchainExt>()
991 .expect("set_authorized_nodes can be called only in the offchain worker context")
992 .set_authorized_nodes(nodes, authorized_only)
993 }
994}
995
996#[runtime_interface(wasm_only)]
998trait Allocator {
999 fn malloc(&mut self, size: u32) -> Pointer<u8> {
1001 self.allocate_memory(size).expect("Failed to allocate memory")
1002 }
1003
1004 fn free(&mut self, ptr: Pointer<u8>) {
1006 self.deallocate_memory(ptr).expect("Failed to deallocate memory")
1007 }
1008}
1009
1010#[runtime_interface]
1012pub trait Logging {
1013 fn log(level: LogLevel, target: &str, message: &[u8]) {
1020 if let Ok(message) = std::str::from_utf8(message) {
1021 log::log!(
1022 target: target,
1023 log::Level::from(level),
1024 "{}",
1025 message,
1026 )
1027 }
1028 }
1029}
1030
1031#[derive(Encode, Decode)]
1032pub struct Crossing<T: Encode + Decode>(T);
1035
1036impl<T: Encode + Decode> PassBy for Crossing<T> {
1037 type PassBy = tp_runtime_interface::pass_by::Codec<Self>;
1038}
1039
1040impl<T: Encode + Decode> Crossing<T> {
1041
1042 pub fn into_inner(self) -> T {
1044 self.0
1045 }
1046}
1047
1048impl<T> core::default::Default for Crossing<T>
1050 where T: core::default::Default + Encode + Decode
1051{
1052 fn default() -> Self {
1053 Self(Default::default())
1054 }
1055
1056}
1057
1058#[runtime_interface(wasm_only, no_tracing)]
1061pub trait WasmTracing {
1062 fn enabled(&mut self, metadata: Crossing<tetcore_tracing::WasmMetadata>) -> bool {
1071 let metadata: &tracing_core::metadata::Metadata<'static> = (&metadata.into_inner()).into();
1072 tracing::dispatcher::get_default(|d| {
1073 d.enabled(metadata)
1074 })
1075 }
1076
1077 fn enter_span(&mut self, span: Crossing<tetcore_tracing::WasmEntryAttributes>) -> u64 {
1084 let span: tracing::Span = span.into_inner().into();
1085 match span.id() {
1086 Some(id) => tracing::dispatcher::get_default(|d| {
1087 let final_id = d.clone_span(&id);
1090 d.enter(&final_id);
1091 final_id.into_u64()
1092 }),
1093 _ => {
1094 0
1095 }
1096 }
1097 }
1098
1099 fn event(&mut self, event: Crossing<tetcore_tracing::WasmEntryAttributes>) {
1101 event.into_inner().emit();
1102 }
1103
1104 fn exit(&mut self, span: u64) {
1107 tracing::dispatcher::get_default(|d| {
1108 let id = tracing_core::span::Id::from_u64(span);
1109 d.exit(&id);
1110 });
1111 }
1112}
1113
1114#[cfg(all(not(feature="std"), feature="with-tracing"))]
1115mod tracing_setup {
1116 use core::sync::atomic::{AtomicBool, Ordering};
1117 use tracing_core::{
1118 dispatcher::{Dispatch, set_global_default},
1119 span::{Id, Record, Attributes},
1120 Metadata, Event,
1121 };
1122 use super::{wasm_tracing, Crossing};
1123
1124 static TRACING_SET: AtomicBool = AtomicBool::new(false);
1125
1126
1127 struct PassingTracingSubsciber;
1130
1131 impl tracing_core::Subscriber for PassingTracingSubsciber {
1132 fn enabled(&self, metadata: &Metadata<'_>) -> bool {
1133 wasm_tracing::enabled(Crossing(metadata.into()))
1134 }
1135 fn new_span(&self, attrs: &Attributes<'_>) -> Id {
1136 Id::from_u64(wasm_tracing::enter_span(Crossing(attrs.into())))
1137 }
1138 fn enter(&self, span: &Id) {
1139 }
1141 fn record(&self, span: &Id, values: &Record<'_>) {
1144 unimplemented!{} }
1146 fn record_follows_from(&self, span: &Id, follows: &Id) {
1149 unimplemented!{ } }
1151 fn event(&self, event: &Event<'_>) {
1152 wasm_tracing::event(Crossing(event.into()))
1153 }
1154 fn exit(&self, span: &Id) {
1155 wasm_tracing::exit(span.into_u64())
1156 }
1157 }
1158
1159
1160 pub fn init_tracing() {
1164 if TRACING_SET.load(Ordering::Relaxed) == false {
1165 set_global_default(Dispatch::new(PassingTracingSubsciber {}))
1166 .expect("We only ever call this once");
1167 TRACING_SET.store(true, Ordering::Relaxed);
1168 }
1169 }
1170}
1171
1172#[cfg(not(all(not(feature="std"), feature="with-tracing")))]
1173mod tracing_setup {
1174 pub fn init_tracing() { }
1177}
1178
1179pub use tracing_setup::init_tracing;
1180
1181#[runtime_interface(wasm_only)]
1183pub trait Sandbox {
1184 fn instantiate(
1186 &mut self,
1187 dispatch_thunk: u32,
1188 wasm_code: &[u8],
1189 env_def: &[u8],
1190 state_ptr: Pointer<u8>,
1191 ) -> u32 {
1192 self.sandbox()
1193 .instance_new(dispatch_thunk, wasm_code, env_def, state_ptr.into())
1194 .expect("Failed to instantiate a new sandbox")
1195 }
1196
1197 fn invoke(
1199 &mut self,
1200 instance_idx: u32,
1201 function: &str,
1202 args: &[u8],
1203 return_val_ptr: Pointer<u8>,
1204 return_val_len: u32,
1205 state_ptr: Pointer<u8>,
1206 ) -> u32 {
1207 self.sandbox().invoke(
1208 instance_idx,
1209 &function,
1210 &args,
1211 return_val_ptr,
1212 return_val_len,
1213 state_ptr.into(),
1214 ).expect("Failed to invoke function with sandbox")
1215 }
1216
1217 fn memory_new(&mut self, initial: u32, maximum: u32) -> u32 {
1219 self.sandbox()
1220 .memory_new(initial, maximum)
1221 .expect("Failed to create new memory with sandbox")
1222 }
1223
1224 fn memory_get(
1226 &mut self,
1227 memory_idx: u32,
1228 offset: u32,
1229 buf_ptr: Pointer<u8>,
1230 buf_len: u32,
1231 ) -> u32 {
1232 self.sandbox()
1233 .memory_get(memory_idx, offset, buf_ptr, buf_len)
1234 .expect("Failed to get memory with sandbox")
1235 }
1236
1237 fn memory_set(
1239 &mut self,
1240 memory_idx: u32,
1241 offset: u32,
1242 val_ptr: Pointer<u8>,
1243 val_len: u32,
1244 ) -> u32 {
1245 self.sandbox()
1246 .memory_set(memory_idx, offset, val_ptr, val_len)
1247 .expect("Failed to set memory with sandbox")
1248 }
1249
1250 fn memory_teardown(&mut self, memory_idx: u32) {
1252 self.sandbox().memory_teardown(memory_idx).expect("Failed to teardown memory with sandbox")
1253 }
1254
1255 fn instance_teardown(&mut self, instance_idx: u32) {
1257 self.sandbox().instance_teardown(instance_idx).expect("Failed to teardown sandbox instance")
1258 }
1259
1260 fn get_global_val(&mut self, instance_idx: u32, name: &str) -> Option<tetcore_wasm_interface::Value> {
1265 self.sandbox().get_global_val(instance_idx, name).expect("Failed to get global from sandbox")
1266 }
1267}
1268
1269#[runtime_interface(wasm_only)]
1273pub trait RuntimeTasks {
1274 fn spawn(dispatcher_ref: u32, entry: u32, payload: Vec<u8>) -> u64 {
1278 externalities::with_externalities(|mut ext|{
1279 let runtime_spawn = ext.extension::<RuntimeSpawnExt>()
1280 .expect("Cannot spawn without dynamic runtime dispatcher (RuntimeSpawnExt)");
1281 runtime_spawn.spawn_call(dispatcher_ref, entry, payload)
1282 }).expect("`RuntimeTasks::spawn`: called outside of externalities context")
1283 }
1284
1285 fn join(handle: u64) -> Vec<u8> {
1289 externalities::with_externalities(|mut ext| {
1290 let runtime_spawn = ext.extension::<RuntimeSpawnExt>()
1291 .expect("Cannot join without dynamic runtime dispatcher (RuntimeSpawnExt)");
1292 runtime_spawn.join(handle)
1293 }).expect("`RuntimeTasks::join`: called outside of externalities context")
1294 }
1295 }
1296
1297#[cfg(not(feature = "std"))]
1299struct WasmAllocator;
1300
1301#[cfg(all(not(feature = "disable_allocator"), not(feature = "std")))]
1302#[global_allocator]
1303static ALLOCATOR: WasmAllocator = WasmAllocator;
1304
1305#[cfg(not(feature = "std"))]
1306mod allocator_impl {
1307 use super::*;
1308 use core::alloc::{GlobalAlloc, Layout};
1309
1310 unsafe impl GlobalAlloc for WasmAllocator {
1311 unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
1312 allocator::malloc(layout.size() as u32)
1313 }
1314
1315 unsafe fn dealloc(&self, ptr: *mut u8, _: Layout) {
1316 allocator::free(ptr)
1317 }
1318 }
1319}
1320
1321#[cfg(all(not(feature = "disable_panic_handler"), not(feature = "std")))]
1323#[panic_handler]
1324#[no_mangle]
1325pub fn panic(info: &core::panic::PanicInfo) -> ! {
1326 unsafe {
1327 let message = tetcore_std::alloc::format!("{}", info);
1328 logging::log(LogLevel::Error, "runtime", message.as_bytes());
1329 core::arch::wasm32::unreachable();
1330 }
1331}
1332
1333#[cfg(all(not(feature = "disable_oom"), not(feature = "std")))]
1335#[alloc_error_handler]
1336pub fn oom(_: core::alloc::Layout) -> ! {
1337 unsafe {
1338 logging::log(LogLevel::Error, "runtime", b"Runtime memory exhausted. Aborting");
1339 core::arch::wasm32::unreachable();
1340 }
1341}
1342
1343#[cfg(feature = "std")]
1345pub type TestExternalities = tp_state_machine::TestExternalities<tet_core::Blake2Hasher, u64>;
1346
1347#[cfg(feature = "std")]
1351pub type TetcoreHostFunctions = (
1352 storage::HostFunctions,
1353 default_child_storage::HostFunctions,
1354 misc::HostFunctions,
1355 wasm_tracing::HostFunctions,
1356 offchain::HostFunctions,
1357 crypto::HostFunctions,
1358 hashing::HostFunctions,
1359 allocator::HostFunctions,
1360 logging::HostFunctions,
1361 sandbox::HostFunctions,
1362 crate::trie::HostFunctions,
1363 offchain_index::HostFunctions,
1364 runtime_tasks::HostFunctions,
1365);
1366
1367#[cfg(test)]
1368mod tests {
1369 use super::*;
1370 use tp_state_machine::BasicExternalities;
1371 use tet_core::{
1372 storage::Storage, map, traits::TaskExecutorExt, testing::TaskExecutor,
1373 };
1374 use std::any::TypeId;
1375
1376 #[test]
1377 fn storage_works() {
1378 let mut t = BasicExternalities::default();
1379 t.execute_with(|| {
1380 assert_eq!(storage::get(b"hello"), None);
1381 storage::set(b"hello", b"world");
1382 assert_eq!(storage::get(b"hello"), Some(b"world".to_vec()));
1383 assert_eq!(storage::get(b"foo"), None);
1384 storage::set(b"foo", &[1, 2, 3][..]);
1385 });
1386
1387 t = BasicExternalities::new(Storage {
1388 top: map![b"foo".to_vec() => b"bar".to_vec()],
1389 children_default: map![],
1390 });
1391
1392 t.execute_with(|| {
1393 assert_eq!(storage::get(b"hello"), None);
1394 assert_eq!(storage::get(b"foo"), Some(b"bar".to_vec()));
1395 });
1396 }
1397
1398 #[test]
1399 fn read_storage_works() {
1400 let value = b"\x0b\0\0\0Hello world".to_vec();
1401 let mut t = BasicExternalities::new(Storage {
1402 top: map![b":test".to_vec() => value.clone()],
1403 children_default: map![],
1404 });
1405
1406 t.execute_with(|| {
1407 let mut v = [0u8; 4];
1408 assert_eq!(storage::read(b":test", &mut v[..], 0).unwrap(), value.len() as u32);
1409 assert_eq!(v, [11u8, 0, 0, 0]);
1410 let mut w = [0u8; 11];
1411 assert_eq!(storage::read(b":test", &mut w[..], 4).unwrap(), value.len() as u32 - 4);
1412 assert_eq!(&w, b"Hello world");
1413 });
1414 }
1415
1416 #[test]
1417 fn clear_prefix_works() {
1418 let mut t = BasicExternalities::new(Storage {
1419 top: map![
1420 b":a".to_vec() => b"\x0b\0\0\0Hello world".to_vec(),
1421 b":abcd".to_vec() => b"\x0b\0\0\0Hello world".to_vec(),
1422 b":abc".to_vec() => b"\x0b\0\0\0Hello world".to_vec(),
1423 b":abdd".to_vec() => b"\x0b\0\0\0Hello world".to_vec()
1424 ],
1425 children_default: map![],
1426 });
1427
1428 t.execute_with(|| {
1429 storage::clear_prefix(b":abc");
1430
1431 assert!(storage::get(b":a").is_some());
1432 assert!(storage::get(b":abdd").is_some());
1433 assert!(storage::get(b":abcd").is_none());
1434 assert!(storage::get(b":abc").is_none());
1435 });
1436 }
1437
1438 #[test]
1439 fn batch_verify_start_finish_works() {
1440 let mut ext = BasicExternalities::default();
1441 ext.register_extension(TaskExecutorExt::new(TaskExecutor::new()));
1442
1443 ext.execute_with(|| {
1444 crypto::start_batch_verify();
1445 });
1446
1447 assert!(ext.extensions().get_mut(TypeId::of::<VerificationExt>()).is_some());
1448
1449 ext.execute_with(|| {
1450 assert!(crypto::finish_batch_verify());
1451 });
1452
1453 assert!(ext.extensions().get_mut(TypeId::of::<VerificationExt>()).is_none());
1454 }
1455
1456 #[test]
1457 fn long_sr25519_batching() {
1458 let mut ext = BasicExternalities::default();
1459 ext.register_extension(TaskExecutorExt::new(TaskExecutor::new()));
1460 ext.execute_with(|| {
1461 let pair = sr25519::Pair::generate_with_phrase(None).0;
1462 crypto::start_batch_verify();
1463 for it in 0..70 {
1464 let msg = format!("Schnorrkel {}!", it);
1465 let signature = pair.sign(msg.as_bytes());
1466 crypto::sr25519_batch_verify(&signature, msg.as_bytes(), &pair.public());
1467 }
1468
1469 crypto::sr25519_batch_verify(
1471 &Default::default(),
1472 &Vec::new(),
1473 &Default::default(),
1474 );
1475 assert!(!crypto::finish_batch_verify());
1476
1477 crypto::start_batch_verify();
1478 for it in 0..70 {
1479 let msg = format!("Schnorrkel {}!", it);
1480 let signature = pair.sign(msg.as_bytes());
1481 crypto::sr25519_batch_verify(&signature, msg.as_bytes(), &pair.public());
1482 }
1483 assert!(crypto::finish_batch_verify());
1484 });
1485 }
1486
1487 #[test]
1488 fn batching_works() {
1489 let mut ext = BasicExternalities::default();
1490 ext.register_extension(TaskExecutorExt::new(TaskExecutor::new()));
1491 ext.execute_with(|| {
1492 crypto::start_batch_verify();
1494 crypto::ed25519_batch_verify(
1495 &Default::default(),
1496 &Vec::new(),
1497 &Default::default(),
1498 );
1499 assert!(!crypto::finish_batch_verify());
1500
1501 crypto::start_batch_verify();
1503
1504 let pair = ed25519::Pair::generate_with_phrase(None).0;
1505 let msg = b"Important message";
1506 let signature = pair.sign(msg);
1507 crypto::ed25519_batch_verify(&signature, msg, &pair.public());
1508
1509 let pair = ed25519::Pair::generate_with_phrase(None).0;
1510 let msg = b"Even more important message";
1511 let signature = pair.sign(msg);
1512 crypto::ed25519_batch_verify(&signature, msg, &pair.public());
1513
1514 assert!(crypto::finish_batch_verify());
1515
1516 crypto::start_batch_verify();
1518
1519 let pair = ed25519::Pair::generate_with_phrase(None).0;
1520 let msg = b"Important message";
1521 let signature = pair.sign(msg);
1522 crypto::ed25519_batch_verify(&signature, msg, &pair.public());
1523
1524 crypto::ed25519_batch_verify(
1525 &Default::default(),
1526 &Vec::new(),
1527 &Default::default(),
1528 );
1529
1530 assert!(!crypto::finish_batch_verify());
1531
1532 crypto::start_batch_verify();
1534
1535 let pair = ed25519::Pair::generate_with_phrase(None).0;
1536 let msg = b"Ed25519 batching";
1537 let signature = pair.sign(msg);
1538 crypto::ed25519_batch_verify(&signature, msg, &pair.public());
1539
1540 let pair = sr25519::Pair::generate_with_phrase(None).0;
1541 let msg = b"Schnorrkel rules";
1542 let signature = pair.sign(msg);
1543 crypto::sr25519_batch_verify(&signature, msg, &pair.public());
1544
1545 let pair = sr25519::Pair::generate_with_phrase(None).0;
1546 let msg = b"Schnorrkel batches!";
1547 let signature = pair.sign(msg);
1548 crypto::sr25519_batch_verify(&signature, msg, &pair.public());
1549
1550 assert!(crypto::finish_batch_verify());
1551
1552 crypto::start_batch_verify();
1554
1555 let pair = sr25519::Pair::generate_with_phrase(None).0;
1556 let msg = b"Schnorrkcel!";
1557 let signature = pair.sign(msg);
1558 crypto::sr25519_batch_verify(&signature, msg, &pair.public());
1559
1560 crypto::sr25519_batch_verify(
1561 &Default::default(),
1562 &Vec::new(),
1563 &Default::default(),
1564 );
1565
1566 assert!(!crypto::finish_batch_verify());
1567 });
1568 }
1569}