1use std::convert::TryInto;
7use std::mem::{size_of, size_of_val};
8use std::panic as std_panic;
9use std::{convert::TryFrom, mem::MaybeUninit};
10
11#[cfg(all(not(target_arch = "wasm32"), feature = "unit-testing"))]
12use crate::mock::MockedBlockchain;
13use crate::promise::Allowance;
14use crate::types::{
15 AccountId, BlockHeight, Gas, PromiseIndex, PromiseResult, PublicKey, StorageUsage, UncToken,
16};
17use crate::{CryptoHash, GasWeight, PromiseError};
18use unc_sys as sys;
19
20const REGISTER_EXPECTED_ERR: &str =
21 "Register was expected to have data because we just wrote it into it.";
22
23const ATOMIC_OP_REGISTER: u64 = std::u64::MAX - 2;
27const EVICTED_REGISTER: u64 = std::u64::MAX - 1;
29
30const STATE_KEY: &[u8] = b"STATE";
32
33const MIN_ACCOUNT_ID_LEN: u64 = 2;
35const MAX_ACCOUNT_ID_LEN: u64 = 64;
37
38fn expect_register<T>(option: Option<T>) -> T {
39 option.unwrap_or_else(|| panic_str(REGISTER_EXPECTED_ERR))
40}
41
42macro_rules! try_method_into_register {
44 ( $method:ident ) => {{
45 unsafe { sys::$method(ATOMIC_OP_REGISTER) };
46 read_register(ATOMIC_OP_REGISTER)
47 }};
48}
49
50macro_rules! method_into_register {
52 ( $method:ident ) => {{
53 expect_register(try_method_into_register!($method))
54 }};
55}
56
57pub(crate) unsafe fn read_register_fixed_20(register_id: u64) -> [u8; 20] {
61 let mut hash = [MaybeUninit::<u8>::uninit(); 20];
62 sys::read_register(register_id, hash.as_mut_ptr() as _);
63 std::mem::transmute(hash)
64}
65
66pub(crate) unsafe fn read_register_fixed_32(register_id: u64) -> [u8; 32] {
67 let mut hash = [MaybeUninit::<u8>::uninit(); 32];
68 sys::read_register(register_id, hash.as_mut_ptr() as _);
69 std::mem::transmute(hash)
70}
71
72pub(crate) unsafe fn read_register_fixed_64(register_id: u64) -> [u8; 64] {
73 let mut hash = [MaybeUninit::<u8>::uninit(); 64];
74 sys::read_register(register_id, hash.as_mut_ptr() as _);
75 std::mem::transmute(hash)
76}
77
78#[cfg(all(not(target_arch = "wasm32"), feature = "unit-testing"))]
100pub fn set_blockchain_interface(blockchain_interface: MockedBlockchain) {
101 crate::mock::with_mocked_blockchain(|b| {
102 *b = blockchain_interface;
103 })
104}
105
106fn panic_hook_impl(info: &std_panic::PanicInfo) {
109 panic_str(info.to_string().as_str());
110}
111
112pub fn setup_panic_hook() {
114 std_panic::set_hook(Box::new(panic_hook_impl));
115}
116
117pub fn read_register(register_id: u64) -> Option<Vec<u8>> {
119 let len: usize = register_len(register_id)?.try_into().unwrap_or_else(|_| abort());
123
124 let mut buffer = Vec::with_capacity(len);
126
127 unsafe {
131 sys::read_register(register_id, buffer.as_mut_ptr() as u64);
132
133 buffer.set_len(len);
135 }
136 Some(buffer)
137}
138
139pub fn register_len(register_id: u64) -> Option<u64> {
141 let len = unsafe { sys::register_len(register_id) };
142 if len == std::u64::MAX {
143 None
144 } else {
145 Some(len)
146 }
147}
148
149pub fn current_account_id() -> AccountId {
154 assert_valid_account_id(method_into_register!(current_account_id))
155}
156
157pub fn signer_account_id() -> AccountId {
160 assert_valid_account_id(method_into_register!(signer_account_id))
161}
162
163pub fn signer_account_pk() -> PublicKey {
165 PublicKey::try_from(method_into_register!(signer_account_pk)).unwrap_or_else(|_| abort())
166}
167
168pub fn predecessor_account_id() -> AccountId {
171 assert_valid_account_id(method_into_register!(predecessor_account_id))
172}
173
174fn assert_valid_account_id(bytes: Vec<u8>) -> AccountId {
176 String::from_utf8(bytes)
177 .ok()
178 .and_then(|s| AccountId::try_from(s).ok())
179 .unwrap_or_else(|| abort())
180}
181
182pub fn input() -> Option<Vec<u8>> {
184 try_method_into_register!(input)
185}
186
187#[deprecated(since = "2.0.0", note = "Use block_height instead")]
189pub fn block_index() -> BlockHeight {
190 block_height()
191}
192
193pub fn block_height() -> BlockHeight {
195 unsafe { sys::block_height() }
196}
197
198pub fn block_timestamp() -> u64 {
200 unsafe { sys::block_timestamp() }
201}
202
203pub fn block_timestamp_ms() -> u64 {
205 block_timestamp() / 1_000_000
206}
207
208pub fn epoch_height() -> u64 {
210 unsafe { sys::epoch_height() }
211}
212
213pub fn storage_usage() -> StorageUsage {
215 unsafe { sys::storage_usage() }
216}
217
218pub fn account_balance() -> UncToken {
224 let data = [0u8; size_of::<UncToken>()];
225 unsafe { sys::account_balance(data.as_ptr() as u64) };
226 UncToken::from_attounc(u128::from_le_bytes(data))
227}
228
229pub fn account_locked_balance() -> UncToken {
231 let data = [0u8; size_of::<UncToken>()];
232 unsafe { sys::account_locked_balance(data.as_ptr() as u64) };
233 UncToken::from_attounc(u128::from_le_bytes(data))
234}
235
236pub fn attached_deposit() -> UncToken {
239 let data = [0u8; size_of::<UncToken>()];
240 unsafe { sys::attached_deposit(data.as_ptr() as u64) };
241 UncToken::from_attounc(u128::from_le_bytes(data))
242}
243
244pub fn prepaid_gas() -> Gas {
246 Gas::from_gas(unsafe { sys::prepaid_gas() })
247}
248
249pub fn used_gas() -> Gas {
251 Gas::from_gas(unsafe { sys::used_gas() })
252}
253
254pub fn random_seed() -> Vec<u8> {
262 random_seed_array().to_vec()
263}
264
265pub fn random_seed_array() -> [u8; 32] {
315 unsafe {
319 sys::random_seed(ATOMIC_OP_REGISTER);
320 read_register_fixed_32(ATOMIC_OP_REGISTER)
321 }
322}
323
324pub fn sha256(value: &[u8]) -> Vec<u8> {
338 sha256_array(value).to_vec()
339}
340
341pub fn keccak256(value: &[u8]) -> Vec<u8> {
343 keccak256_array(value).to_vec()
344}
345
346pub fn keccak512(value: &[u8]) -> Vec<u8> {
348 keccak512_array(value).to_vec()
349}
350
351pub fn sha256_array(value: &[u8]) -> [u8; 32] {
367 unsafe {
371 sys::sha256(value.len() as _, value.as_ptr() as _, ATOMIC_OP_REGISTER);
372 read_register_fixed_32(ATOMIC_OP_REGISTER)
373 }
374}
375
376pub fn keccak256_array(value: &[u8]) -> [u8; 32] {
378 unsafe {
382 sys::keccak256(value.len() as _, value.as_ptr() as _, ATOMIC_OP_REGISTER);
383 read_register_fixed_32(ATOMIC_OP_REGISTER)
384 }
385}
386
387pub fn keccak512_array(value: &[u8]) -> [u8; 64] {
389 unsafe {
393 sys::keccak512(value.len() as _, value.as_ptr() as _, ATOMIC_OP_REGISTER);
394 read_register_fixed_64(ATOMIC_OP_REGISTER)
395 }
396}
397
398pub fn ripemd160_array(value: &[u8]) -> [u8; 20] {
400 unsafe {
404 sys::ripemd160(value.len() as _, value.as_ptr() as _, ATOMIC_OP_REGISTER);
405 read_register_fixed_20(ATOMIC_OP_REGISTER)
406 }
407}
408
409#[cfg(feature = "unstable")]
417pub fn ecrecover(
418 hash: &[u8],
419 signature: &[u8],
420 v: u8,
421 malleability_flag: bool,
422) -> Option<[u8; 64]> {
423 unsafe {
424 let return_code = sys::ecrecover(
425 hash.len() as _,
426 hash.as_ptr() as _,
427 signature.len() as _,
428 signature.as_ptr() as _,
429 v as u64,
430 malleability_flag as u64,
431 ATOMIC_OP_REGISTER,
432 );
433 if return_code == 0 {
434 None
435 } else {
436 Some(read_register_fixed_64(ATOMIC_OP_REGISTER))
437 }
438 }
439}
440
441pub fn ed25519_verify(signature: &[u8; 64], message: &[u8], public_key: &[u8; 32]) -> bool {
443 unsafe {
444 sys::ed25519_verify(
445 signature.len() as _,
446 signature.as_ptr() as _,
447 message.len() as _,
448 message.as_ptr() as _,
449 public_key.len() as _,
450 public_key.as_ptr() as _,
451 ) == 1
452 }
453}
454
455pub fn alt_bn128_g1_multiexp(value: &[u8]) -> Vec<u8> {
462 unsafe {
463 sys::alt_bn128_g1_multiexp(value.len() as _, value.as_ptr() as _, ATOMIC_OP_REGISTER);
464 };
465 read_register(ATOMIC_OP_REGISTER).expect(REGISTER_EXPECTED_ERR)
466}
467
468pub fn alt_bn128_g1_sum(value: &[u8]) -> Vec<u8> {
475 unsafe {
476 sys::alt_bn128_g1_sum(value.len() as _, value.as_ptr() as _, ATOMIC_OP_REGISTER);
477 };
478 read_register(ATOMIC_OP_REGISTER).expect(REGISTER_EXPECTED_ERR)
479}
480
481pub fn alt_bn128_pairing_check(value: &[u8]) -> bool {
488 unsafe { sys::alt_bn128_pairing_check(value.len() as _, value.as_ptr() as _) == 1 }
489}
490
491pub fn promise_create(
497 account_id: AccountId,
498 function_name: &str,
499 arguments: &[u8],
500 amount: UncToken,
501 gas: Gas,
502) -> PromiseIndex {
503 let account_id = account_id.as_bytes();
504 unsafe {
505 PromiseIndex(sys::promise_create(
506 account_id.len() as _,
507 account_id.as_ptr() as _,
508 function_name.len() as _,
509 function_name.as_ptr() as _,
510 arguments.len() as _,
511 arguments.as_ptr() as _,
512 &amount.as_attounc() as *const u128 as _,
513 gas.as_gas(),
514 ))
515 }
516}
517
518pub fn promise_then(
520 promise_idx: PromiseIndex,
521 account_id: AccountId,
522 function_name: &str,
523 arguments: &[u8],
524 amount: UncToken,
525 gas: Gas,
526) -> PromiseIndex {
527 let account_id = account_id.as_bytes();
528 unsafe {
529 PromiseIndex(sys::promise_then(
530 promise_idx.0,
531 account_id.len() as _,
532 account_id.as_ptr() as _,
533 function_name.len() as _,
534 function_name.as_ptr() as _,
535 arguments.len() as _,
536 arguments.as_ptr() as _,
537 &amount.as_attounc() as *const u128 as _,
538 gas.as_gas(),
539 ))
540 }
541}
542
543pub fn promise_and(promise_indices: &[PromiseIndex]) -> PromiseIndex {
545 let mut data = vec![0u8; size_of_val(promise_indices)];
546 for i in 0..promise_indices.len() {
547 data[i * size_of::<PromiseIndex>()..(i + 1) * size_of::<PromiseIndex>()]
548 .copy_from_slice(&promise_indices[i].0.to_le_bytes());
549 }
550 unsafe { PromiseIndex(sys::promise_and(data.as_ptr() as _, promise_indices.len() as _)) }
551}
552
553pub fn promise_batch_create(account_id: &AccountId) -> PromiseIndex {
554 let account_id: &str = account_id.as_ref();
555 unsafe {
556 PromiseIndex(sys::promise_batch_create(account_id.len() as _, account_id.as_ptr() as _))
557 }
558}
559
560pub fn promise_batch_then(promise_index: PromiseIndex, account_id: &AccountId) -> PromiseIndex {
561 let account_id: &str = account_id.as_ref();
562 unsafe {
563 PromiseIndex(sys::promise_batch_then(
564 promise_index.0,
565 account_id.len() as _,
566 account_id.as_ptr() as _,
567 ))
568 }
569}
570
571pub fn promise_batch_action_create_account(promise_index: PromiseIndex) {
572 unsafe { sys::promise_batch_action_create_account(promise_index.0) }
573}
574
575pub fn promise_batch_action_deploy_contract(promise_index: PromiseIndex, code: &[u8]) {
576 unsafe {
577 sys::promise_batch_action_deploy_contract(
578 promise_index.0,
579 code.len() as _,
580 code.as_ptr() as _,
581 )
582 }
583}
584
585pub fn promise_batch_action_function_call(
586 promise_index: PromiseIndex,
587 function_name: &str,
588 arguments: &[u8],
589 amount: UncToken,
590 gas: Gas,
591) {
592 unsafe {
593 sys::promise_batch_action_function_call(
594 promise_index.0,
595 function_name.len() as _,
596 function_name.as_ptr() as _,
597 arguments.len() as _,
598 arguments.as_ptr() as _,
599 &amount.as_attounc() as *const u128 as _,
600 gas.as_gas(),
601 )
602 }
603}
604
605pub fn promise_batch_action_function_call_weight(
606 promise_index: PromiseIndex,
607 function_name: &str,
608 arguments: &[u8],
609 amount: UncToken,
610 gas: Gas,
611 weight: GasWeight,
612) {
613 unsafe {
614 sys::promise_batch_action_function_call_weight(
615 promise_index.0,
616 function_name.len() as _,
617 function_name.as_ptr() as _,
618 arguments.len() as _,
619 arguments.as_ptr() as _,
620 &amount.as_attounc() as *const u128 as _,
621 gas.as_gas(),
622 weight.0,
623 )
624 }
625}
626
627pub fn promise_batch_action_transfer(promise_index: PromiseIndex, amount: UncToken) {
628 unsafe {
629 sys::promise_batch_action_transfer(
630 promise_index.0,
631 &amount.as_attounc() as *const u128 as _,
632 )
633 }
634}
635
636pub fn promise_batch_action_stake(
637 promise_index: PromiseIndex,
638 amount: UncToken,
639 public_key: &PublicKey,
640) {
641 unsafe {
642 sys::promise_batch_action_stake(
643 promise_index.0,
644 &amount.as_attounc() as *const u128 as _,
645 public_key.as_bytes().len() as _,
646 public_key.as_bytes().as_ptr() as _,
647 )
648 }
649}
650pub fn promise_batch_action_add_key_with_full_access(
651 promise_index: PromiseIndex,
652 public_key: &PublicKey,
653 nonce: u64,
654) {
655 unsafe {
656 sys::promise_batch_action_add_key_with_full_access(
657 promise_index.0,
658 public_key.as_bytes().len() as _,
659 public_key.as_bytes().as_ptr() as _,
660 nonce,
661 )
662 }
663}
664
665pub(crate) fn migrate_to_allowance(allowance: UncToken) -> Allowance {
667 Allowance::limited(allowance).unwrap_or(Allowance::Unlimited)
668}
669
670#[deprecated(since = "2.0.0", note = "Use add_access_key_allowance instead")]
671pub fn promise_batch_action_add_key_with_function_call(
672 promise_index: PromiseIndex,
673 public_key: &PublicKey,
674 nonce: u64,
675 allowance: UncToken,
676 receiver_id: &AccountId,
677 function_names: &str,
678) {
679 let allowance = migrate_to_allowance(allowance);
680 promise_batch_action_add_key_allowance_with_function_call(
681 promise_index,
682 public_key,
683 nonce,
684 allowance,
685 receiver_id,
686 function_names,
687 )
688}
689
690pub fn promise_batch_action_add_key_allowance_with_function_call(
691 promise_index: PromiseIndex,
692 public_key: &PublicKey,
693 nonce: u64,
694 allowance: Allowance,
695 receiver_id: &AccountId,
696 function_names: &str,
697) {
698 let receiver_id: &str = receiver_id.as_ref();
699 let allowance = match allowance {
700 Allowance::Limited(x) => x.get(),
701 Allowance::Unlimited => 0,
702 };
703 unsafe {
704 sys::promise_batch_action_add_key_with_function_call(
705 promise_index.0,
706 public_key.as_bytes().len() as _,
707 public_key.as_bytes().as_ptr() as _,
708 nonce,
709 &allowance as *const u128 as _,
710 receiver_id.len() as _,
711 receiver_id.as_ptr() as _,
712 function_names.len() as _,
713 function_names.as_ptr() as _,
714 )
715 }
716}
717pub fn promise_batch_action_delete_key(promise_index: PromiseIndex, public_key: &PublicKey) {
718 unsafe {
719 sys::promise_batch_action_delete_key(
720 promise_index.0,
721 public_key.as_bytes().len() as _,
722 public_key.as_bytes().as_ptr() as _,
723 )
724 }
725}
726
727pub fn promise_batch_action_delete_account(
728 promise_index: PromiseIndex,
729 beneficiary_id: &AccountId,
730) {
731 let beneficiary_id: &str = beneficiary_id.as_ref();
732 unsafe {
733 sys::promise_batch_action_delete_account(
734 promise_index.0,
735 beneficiary_id.len() as _,
736 beneficiary_id.as_ptr() as _,
737 )
738 }
739}
740
741pub fn promise_results_count() -> u64 {
745 unsafe { sys::promise_results_count() }
746}
747pub fn promise_result(result_idx: u64) -> PromiseResult {
750 match promise_result_internal(result_idx) {
751 Ok(()) => {
752 let data = expect_register(read_register(ATOMIC_OP_REGISTER));
753 PromiseResult::Successful(data)
754 }
755 Err(PromiseError::Failed) => PromiseResult::Failed,
756 }
757}
758
759pub(crate) fn promise_result_internal(result_idx: u64) -> Result<(), PromiseError> {
760 match unsafe { sys::promise_result(result_idx, ATOMIC_OP_REGISTER) } {
761 1 => Ok(()),
762 2 => Err(PromiseError::Failed),
763 _ => abort(),
764 }
765}
766pub fn promise_return(promise_idx: PromiseIndex) {
769 unsafe { sys::promise_return(promise_idx.0) }
770}
771
772pub fn promise_yield_create(
783 function_name: &str,
784 arguments: &[u8],
785 gas: Gas,
786 weight: GasWeight,
787 register_id: u64,
788) -> PromiseIndex {
789 unsafe {
790 PromiseIndex(sys::promise_yield_create(
791 function_name.len() as _,
792 function_name.as_ptr() as _,
793 arguments.len() as _,
794 arguments.as_ptr() as _,
795 gas.as_gas(),
796 weight.0,
797 register_id as _,
798 ))
799 }
800}
801
802pub fn promise_yield_resume(data_id: &CryptoHash, data: &[u8]) -> bool {
811 unsafe {
812 sys::promise_yield_resume(
813 data_id.len() as _,
814 data_id.as_ptr() as _,
815 data.len() as _,
816 data.as_ptr() as _,
817 ) != 0
818 }
819}
820
821pub fn validator_stake(account_id: &AccountId) -> UncToken {
827 let account_id: &str = account_id.as_ref();
828 let data = [0u8; size_of::<UncToken>()];
829 unsafe {
830 sys::validator_stake(account_id.len() as _, account_id.as_ptr() as _, data.as_ptr() as u64)
831 };
832 UncToken::from_attounc(u128::from_le_bytes(data))
833}
834
835pub fn validator_total_stake() -> UncToken {
837 let data = [0u8; size_of::<UncToken>()];
838 unsafe { sys::validator_total_stake(data.as_ptr() as u64) };
839 UncToken::from_attounc(u128::from_le_bytes(data))
840}
841
842pub fn value_return(value: &[u8]) {
847 unsafe { sys::value_return(value.len() as _, value.as_ptr() as _) }
848}
849#[deprecated(since = "2.0.0", note = "Use env::panic_str to panic with a message.")]
852pub fn panic(message: &[u8]) -> ! {
853 unsafe { sys::panic_utf8(message.len() as _, message.as_ptr() as _) }
854}
855
856pub fn panic_str(message: &str) -> ! {
858 unsafe { sys::panic_utf8(message.len() as _, message.as_ptr() as _) }
859}
860
861pub fn abort() -> ! {
864 #[cfg(target_arch = "wasm32")]
866 #[allow(unused_unsafe)]
868 unsafe {
869 core::arch::wasm32::unreachable()
870 }
871 #[cfg(not(target_arch = "wasm32"))]
872 unsafe {
873 sys::panic()
874 }
875}
876
877pub fn log_str(message: &str) {
879 #[cfg(all(debug_assertions, not(target_arch = "wasm32")))]
880 eprintln!("{}", message);
881
882 unsafe { sys::log_utf8(message.len() as _, message.as_ptr() as _) }
883}
884
885#[deprecated(since = "2.0.0", note = "Use env::log_str for logging messages.")]
887pub fn log(message: &[u8]) {
888 #[cfg(all(debug_assertions, not(target_arch = "wasm32")))]
889 eprintln!("{}", String::from_utf8_lossy(message));
890
891 unsafe { sys::log_utf8(message.len() as _, message.as_ptr() as _) }
892}
893
894pub fn storage_write(key: &[u8], value: &[u8]) -> bool {
910 match unsafe {
911 sys::storage_write(
912 key.len() as _,
913 key.as_ptr() as _,
914 value.len() as _,
915 value.as_ptr() as _,
916 EVICTED_REGISTER,
917 )
918 } {
919 0 => false,
920 1 => true,
921 _ => abort(),
922 }
923}
924pub fn storage_read(key: &[u8]) -> Option<Vec<u8>> {
936 match unsafe { sys::storage_read(key.len() as _, key.as_ptr() as _, ATOMIC_OP_REGISTER) } {
937 0 => None,
938 1 => Some(expect_register(read_register(ATOMIC_OP_REGISTER))),
939 _ => abort(),
940 }
941}
942pub fn storage_remove(key: &[u8]) -> bool {
945 match unsafe { sys::storage_remove(key.len() as _, key.as_ptr() as _, EVICTED_REGISTER) } {
946 0 => false,
947 1 => true,
948 _ => abort(),
949 }
950}
951pub fn storage_get_evicted() -> Option<Vec<u8>> {
953 read_register(EVICTED_REGISTER)
954}
955pub fn storage_has_key(key: &[u8]) -> bool {
957 match unsafe { sys::storage_has_key(key.len() as _, key.as_ptr() as _) } {
958 0 => false,
959 1 => true,
960 _ => abort(),
961 }
962}
963
964pub fn state_read<T: borsh::BorshDeserialize>() -> Option<T> {
969 storage_read(STATE_KEY)
970 .map(|data| T::try_from_slice(&data).expect("Cannot deserialize the contract state."))
971}
972
973pub fn state_write<T: borsh::BorshSerialize>(state: &T) {
974 let data = borsh::to_vec(state).expect("Cannot serialize the contract state.");
975 storage_write(STATE_KEY, &data);
976}
977
978pub fn state_exists() -> bool {
980 storage_has_key(STATE_KEY)
981}
982
983pub fn storage_byte_cost() -> UncToken {
991 UncToken::from_attounc(10_000_000_000_000_000_000u128)
992}
993
994pub fn is_valid_account_id(account_id: &[u8]) -> bool {
1000 if (account_id.len() as u64) < MIN_ACCOUNT_ID_LEN
1001 || (account_id.len() as u64) > MAX_ACCOUNT_ID_LEN
1002 {
1003 return false;
1004 }
1005
1006 let mut last_char_is_separator = true;
1012
1013 for c in account_id {
1014 let current_char_is_separator = match *c {
1015 b'a'..=b'z' | b'0'..=b'9' => false,
1016 b'-' | b'_' | b'.' => true,
1017 _ => return false,
1018 };
1019 if current_char_is_separator && last_char_is_separator {
1020 return false;
1021 }
1022 last_char_is_separator = current_char_is_separator;
1023 }
1024 !last_char_is_separator
1026}
1027
1028#[cfg(test)]
1029mod tests {
1030 use super::*;
1031
1032 #[test]
1033 fn test_is_valid_account_id_strings() {
1034 for account_id in &[
1036 "aa",
1037 "a-a",
1038 "a-aa",
1039 "100",
1040 "0o",
1041 "com",
1042 "unc",
1043 "bowen",
1044 "b-o_w_e-n",
1045 "b.owen",
1046 "bro.wen",
1047 "a.ha",
1048 "a.b-a.ra",
1049 "system",
1050 "over.9000",
1051 "google.com",
1052 "wick.cheapaccounts.unc",
1053 "0o0ooo00oo00o",
1054 "alex-skidanov",
1055 "10-4.8-2",
1056 "b-o_w_e-n",
1057 "no_lols",
1058 "0123456789012345678901234567890123456789012345678901234567890123",
1059 "unc.a",
1061 "a.a",
1062 ] {
1063 assert!(
1064 is_valid_account_id(account_id.as_ref()),
1065 "Valid account id {:?} marked invalid",
1066 account_id
1067 );
1068 }
1069
1070 for account_id in &[
1072 "",
1073 "a",
1074 "A",
1075 "Abc",
1076 "-unc",
1077 "unc-",
1078 "-unc-",
1079 "unc.",
1080 ".unc",
1081 "unc@",
1082 "@unc",
1083 "неар",
1084 "@@@@@",
1085 "0__0",
1086 "0_-_0",
1087 "0_-_0",
1088 "..",
1089 "a..unc",
1090 "nEar",
1091 "_bowen",
1092 "hello world",
1093 "abcdefghijklmnopqrstuvwxyz.abcdefghijklmnopqrstuvwxyz.abcdefghijklmnopqrstuvwxyz",
1094 "01234567890123456789012345678901234567890123456789012345678901234",
1095 "some-complex-address@gmail.com",
1097 "sub.buy_d1gitz@atata@b0-rg.c_0_m",
1098 ] {
1099 assert!(
1100 !is_valid_account_id(account_id.as_ref()),
1101 "Invalid account id {:?} marked valid",
1102 account_id
1103 );
1104 }
1105 }
1106
1107 #[test]
1108 fn test_is_valid_account_id_binary() {
1109 assert!(!is_valid_account_id(&[]));
1110 assert!(!is_valid_account_id(&[0]));
1111 assert!(!is_valid_account_id(&[0, 1]));
1112 assert!(!is_valid_account_id(&[0, 1, 2]));
1113 assert!(is_valid_account_id(b"unc"));
1114 }
1115
1116 #[cfg(not(target_arch = "wasm32"))]
1117 #[test]
1118 fn hash_smoke_tests() {
1119 assert_eq!(
1120 &super::sha256_array(b"some value"),
1121 hex::decode("ab3d07f3169ccbd0ed6c4b45de21519f9f938c72d24124998aab949ce83bb51b")
1122 .unwrap()
1123 .as_slice()
1124 );
1125
1126 assert_eq!(
1127 &super::keccak256_array(b"some value"),
1128 hex::decode("f928dfb5fc72b3bbfb9a5ccb0ee9843b27b4ac1ebc25a6f6f783e23ebd47ef1f")
1129 .unwrap()
1130 .as_slice()
1131 );
1132
1133 assert_eq!(
1134 &super::keccak512_array(b"some value"),
1135 hex::decode("3e38d140a85123374ee63ec208973aa39b87349d17ccac948a2493e18b18b5913220cd174b4f511aa97977009e16be485fc94f5e2743cb9bb0579d35ab410583")
1136 .unwrap()
1137 .as_slice()
1138 );
1139
1140 assert_eq!(
1141 &super::ripemd160_array(b"some value"),
1142 hex::decode("09f025fed704e1ecac8f88b2bda3e56876da03ac").unwrap().as_slice()
1143 );
1144 }
1145
1146 #[cfg(not(target_arch = "wasm32"))]
1147 #[test]
1148 fn random_seed_smoke_test() {
1149 crate::testing_env!(crate::test_utils::VMContextBuilder::new()
1150 .random_seed([8; 32])
1151 .build());
1152
1153 assert_eq!(super::random_seed(), [8; 32]);
1154 }
1155
1156 #[cfg(not(target_arch = "wasm32"))]
1157 #[cfg(feature = "unstable")]
1158 #[test]
1159 fn test_ecrecover() {
1160 use crate::test_utils::test_env;
1161 use hex::FromHex;
1162 use serde::de::Error;
1163 use serde::{Deserialize, Deserializer};
1164 use serde_json::from_slice;
1165 use std::fmt::Display;
1166
1167 #[derive(Deserialize)]
1168 struct EcrecoverTest {
1169 #[serde(with = "hex::serde")]
1170 m: [u8; 32],
1171 v: u8,
1172 #[serde(with = "hex::serde")]
1173 sig: [u8; 64],
1174 mc: bool,
1175 #[serde(deserialize_with = "deserialize_option_hex")]
1176 res: Option<[u8; 64]>,
1177 }
1178
1179 fn deserialize_option_hex<'de, D, T>(deserializer: D) -> Result<Option<T>, D::Error>
1180 where
1181 D: Deserializer<'de>,
1182 T: FromHex,
1183 <T as FromHex>::Error: Display,
1184 {
1185 Deserialize::deserialize(deserializer)
1186 .map(|v: Option<&str>| v.map(FromHex::from_hex).transpose().map_err(Error::custom))
1187 .and_then(|v| v)
1188 }
1189
1190 test_env::setup_free();
1191 for EcrecoverTest { m, v, sig, mc, res } in
1192 from_slice::<'_, Vec<_>>(include_bytes!("../../tests/ecrecover-tests.json")).unwrap()
1193 {
1194 assert_eq!(super::ecrecover(&m, &sig, v, mc), res);
1195 }
1196 }
1197
1198 #[cfg(not(target_arch = "wasm32"))]
1199 #[test]
1200 fn signer_public_key() {
1201 let key: PublicKey =
1202 "ed25519:6E8sCci9badyRkXb3JoRpBj5p8C6Tw41ELDZoiihKEtp".parse().unwrap();
1203
1204 crate::testing_env!(crate::test_utils::VMContextBuilder::new()
1205 .signer_account_pk(key.clone())
1206 .build());
1207 assert_eq!(super::signer_account_pk(), key);
1208 }
1209
1210 #[test]
1211 fn ed25519_verify() {
1212 const SIGNATURE: [u8; 64] = [
1213 145, 193, 203, 18, 114, 227, 14, 117, 33, 213, 121, 66, 130, 14, 25, 4, 36, 120, 46,
1214 142, 226, 215, 7, 66, 122, 112, 97, 30, 249, 135, 61, 165, 221, 249, 252, 23, 105, 40,
1215 56, 70, 31, 152, 236, 141, 154, 122, 207, 20, 75, 118, 79, 90, 168, 6, 221, 122, 213,
1216 29, 126, 196, 216, 104, 191, 6,
1217 ];
1218
1219 const BAD_SIGNATURE: [u8; 64] = [1; 64];
1220
1221 const FORGED_SIGNATURE: [u8; 64] = {
1224 let mut sig = SIGNATURE;
1225 sig[63] = 0b1110_0001;
1226 sig
1227 };
1228
1229 const PUBLIC_KEY: [u8; 32] = [
1230 32, 122, 6, 120, 146, 130, 30, 37, 215, 112, 241, 251, 160, 196, 124, 17, 255, 75, 129,
1231 62, 84, 22, 46, 206, 158, 184, 57, 224, 118, 35, 26, 182,
1232 ];
1233
1234 const FORGED_PUBLIC_KEY: [u8; 32] = {
1237 let mut key = PUBLIC_KEY;
1238 key[31] = 0b1110_0001;
1239 key
1240 };
1241
1242 const MESSAGE: [u8; 32] = [
1244 107, 97, 106, 100, 108, 102, 107, 106, 97, 108, 107, 102, 106, 97, 107, 108, 102, 106,
1245 100, 107, 108, 97, 100, 106, 102, 107, 108, 106, 97, 100, 115, 107,
1246 ];
1247
1248 assert!(super::ed25519_verify(&SIGNATURE, &MESSAGE, &PUBLIC_KEY));
1249 assert!(!super::ed25519_verify(&BAD_SIGNATURE, &MESSAGE, &FORGED_PUBLIC_KEY));
1250 assert!(!super::ed25519_verify(&SIGNATURE, &MESSAGE, &FORGED_PUBLIC_KEY));
1251 assert!(!super::ed25519_verify(&FORGED_SIGNATURE, &MESSAGE, &PUBLIC_KEY));
1252 }
1253
1254 #[test]
1255 pub fn alt_bn128_g1_multiexp() {
1256 let buffer = [
1258 16, 238, 91, 161, 241, 22, 172, 158, 138, 252, 202, 212, 136, 37, 110, 231, 118, 220,
1259 8, 45, 14, 153, 125, 217, 227, 87, 238, 238, 31, 138, 226, 8, 238, 185, 12, 155, 93,
1260 126, 144, 248, 200, 177, 46, 245, 40, 162, 169, 80, 150, 211, 157, 13, 10, 36, 44, 232,
1261 173, 32, 32, 115, 123, 2, 9, 47, 190, 148, 181, 91, 69, 6, 83, 40, 65, 222, 251, 70,
1262 81, 73, 60, 142, 130, 217, 176, 20, 69, 75, 40, 167, 41, 180, 244, 5, 142, 215, 135,
1263 35,
1264 ];
1265
1266 assert_eq!(
1267 super::alt_bn128_g1_multiexp(&buffer),
1268 vec![
1269 150, 94, 159, 52, 239, 226, 181, 150, 77, 86, 90, 186, 102, 219, 243, 204, 36, 128,
1270 164, 209, 106, 6, 62, 124, 235, 104, 223, 195, 30, 204, 42, 20, 13, 158, 14, 197,
1271 133, 73, 43, 171, 28, 68, 82, 116, 244, 164, 36, 251, 244, 8, 234, 40, 118, 55,
1272 216, 187, 242, 39, 213, 160, 192, 184, 28, 23
1273 ]
1274 );
1275 }
1276
1277 #[test]
1278 pub fn alt_bn128_g1_sum() {
1279 let buffer = [
1281 0, 11, 49, 94, 29, 152, 111, 116, 138, 248, 2, 184, 8, 159, 80, 169, 45, 149, 48, 32,
1282 49, 37, 6, 133, 105, 171, 194, 120, 44, 195, 17, 180, 35, 137, 154, 4, 192, 211, 244,
1283 93, 200, 2, 44, 0, 64, 26, 108, 139, 147, 88, 235, 242, 23, 253, 52, 110, 236, 67, 99,
1284 176, 2, 186, 198, 228, 25,
1285 ];
1286
1287 assert_eq!(
1288 super::alt_bn128_g1_sum(&buffer),
1289 vec![
1290 11, 49, 94, 29, 152, 111, 116, 138, 248, 2, 184, 8, 159, 80, 169, 45, 149, 48, 32,
1291 49, 37, 6, 133, 105, 171, 194, 120, 44, 195, 17, 180, 35, 137, 154, 4, 192, 211,
1292 244, 93, 200, 2, 44, 0, 64, 26, 108, 139, 147, 88, 235, 242, 23, 253, 52, 110, 236,
1293 67, 99, 176, 2, 186, 198, 228, 25
1294 ]
1295 );
1296 }
1297
1298 #[test]
1299 pub fn alt_bn128_pairing_check() {
1300 let valid_pair = [
1302 117, 10, 217, 99, 113, 78, 234, 67, 183, 90, 26, 58, 200, 86, 195, 123, 42, 184, 213,
1303 88, 224, 248, 18, 200, 108, 6, 181, 6, 28, 17, 99, 7, 36, 134, 53, 115, 192, 180, 3,
1304 113, 76, 227, 174, 147, 50, 174, 79, 74, 151, 195, 172, 10, 211, 210, 26, 92, 117, 246,
1305 65, 237, 168, 104, 16, 4, 1, 26, 3, 219, 6, 13, 193, 115, 77, 230, 27, 13, 242, 214,
1306 195, 9, 213, 99, 135, 12, 160, 202, 114, 135, 175, 42, 116, 172, 79, 234, 26, 41, 212,
1307 111, 192, 129, 124, 112, 57, 107, 38, 244, 230, 222, 240, 36, 65, 238, 133, 188, 19,
1308 43, 148, 59, 205, 40, 161, 179, 173, 228, 88, 169, 231, 29, 17, 67, 163, 51, 165, 187,
1309 101, 44, 250, 24, 68, 101, 92, 128, 203, 190, 51, 85, 9, 43, 58, 136, 68, 180, 92, 110,
1310 185, 168, 107, 129, 45, 30, 187, 22, 100, 17, 75, 93, 216, 125, 23, 212, 11, 186, 199,
1311 204, 1, 140, 133, 11, 82, 44, 65, 222, 20, 26, 48, 26, 132, 220, 25, 213, 93, 25, 79,
1312 176, 4, 149, 151, 243, 11, 131, 253, 233, 121, 38, 222, 15, 118, 117, 200, 214, 175,
1313 233, 130, 181, 193, 167, 255, 153, 169, 240, 207, 235, 28, 31, 83, 74, 69, 179, 6, 150,
1314 72, 67, 74, 166, 130, 83, 82, 115, 123, 111, 208, 221, 64, 43, 237, 213, 186, 235, 7,
1315 56, 251, 179, 95, 233, 159, 23, 109, 173, 85, 103, 8, 165, 235, 226, 218, 79, 72, 120,
1316 172, 251, 20, 83, 121, 201, 140, 98, 170, 246, 121, 218, 19, 115, 42, 135, 60, 239, 30,
1317 32, 49, 170, 171, 204, 196, 197, 160, 158, 168, 47, 23, 110, 139, 123, 222, 222, 245,
1318 98, 125, 208, 70, 39, 110, 186, 146, 254, 66, 185, 118, 3, 78, 32, 47, 179, 197, 93,
1319 79, 240, 204, 78, 236, 133, 213, 173, 117, 94, 63, 154, 68, 89, 236, 138, 0, 247, 242,
1320 212, 245, 33, 249, 0, 35, 246, 233, 0, 124, 86, 198, 162, 201, 54, 19, 26, 196, 75,
1321 254, 71, 70, 238, 51, 2, 23, 185, 152, 139, 134, 65, 107, 129, 114, 244, 47, 251, 240,
1322 80, 193, 23,
1323 ];
1324 assert!(super::alt_bn128_pairing_check(&valid_pair));
1325
1326 let invalid_pair = [
1328 117, 10, 217, 99, 113, 78, 234, 67, 183, 90, 26, 58, 200, 86, 195, 123, 42, 184, 213,
1329 88, 224, 248, 18, 200, 108, 6, 181, 6, 28, 17, 99, 7, 36, 134, 53, 115, 192, 180, 3,
1330 113, 76, 227, 174, 147, 50, 174, 79, 74, 151, 195, 172, 10, 211, 210, 26, 92, 117, 246,
1331 65, 237, 168, 104, 16, 4, 1, 26, 3, 219, 6, 13, 193, 115, 77, 230, 27, 13, 242, 214,
1332 195, 9, 213, 99, 135, 12, 160, 202, 114, 135, 175, 42, 116, 172, 79, 234, 26, 41, 212,
1333 111, 192, 129, 124, 112, 57, 107, 38, 244, 230, 222, 240, 36, 65, 238, 133, 188, 19,
1334 43, 148, 59, 205, 40, 161, 179, 173, 228, 88, 169, 231, 29, 17, 67, 163, 51, 165, 187,
1335 101, 44, 250, 24, 68, 101, 92, 128, 203, 190, 51, 85, 9, 43, 58, 136, 68, 180, 92, 110,
1336 185, 168, 107, 129, 45, 30, 187, 22, 100, 17, 75, 93, 216, 125, 23, 212, 11, 186, 199,
1337 204, 1, 140, 133, 11, 82, 44, 65, 222, 20, 26, 48, 26, 132, 220, 25, 213, 93, 25, 117,
1338 10, 217, 99, 113, 78, 234, 67, 183, 90, 26, 58, 200, 86, 195, 123, 42, 184, 213, 88,
1339 224, 248, 18, 200, 108, 6, 181, 6, 28, 17, 99, 7, 36, 134, 53, 115, 192, 180, 3, 113,
1340 76, 227, 174, 147, 50, 174, 79, 74, 151, 195, 172, 10, 211, 210, 26, 92, 117, 246, 65,
1341 237, 168, 104, 16, 4, 109, 173, 85, 103, 8, 165, 235, 226, 218, 79, 72, 120, 172, 251,
1342 20, 83, 121, 201, 140, 98, 170, 246, 121, 218, 19, 115, 42, 135, 60, 239, 30, 32, 49,
1343 170, 171, 204, 196, 197, 160, 158, 168, 47, 23, 110, 139, 123, 222, 222, 245, 98, 125,
1344 208, 70, 39, 110, 186, 146, 254, 66, 185, 118, 3, 78, 32, 47, 179, 197, 93, 79, 240,
1345 204, 78, 236, 133, 213, 173, 117, 94, 63, 154, 68, 89, 236, 138, 0, 247, 242, 212, 245,
1346 33, 249, 0, 35, 246, 233, 0, 124, 86, 198, 162, 201, 54, 19, 26, 196, 75, 254, 71, 70,
1347 238, 51, 2, 23, 185, 152, 139, 134, 65, 107, 129, 114, 244, 47, 251, 240, 80, 193, 23,
1348 ];
1349
1350 assert!(!super::alt_bn128_pairing_check(&invalid_pair));
1351 }
1352}