common_primitives/
offchain.rs1use crate::msa::MessageSourceId;
2use numtoa::NumToA;
3use parity_scale_codec::Decode;
4#[cfg(feature = "std")]
5use sp_externalities::ExternalitiesExt;
6use sp_runtime::offchain::storage::{StorageRetrievalError, StorageValueRef};
7use sp_runtime_interface::runtime_interface;
8extern crate alloc;
9use alloc::vec::Vec;
10use core::fmt::Debug;
11
12#[cfg(feature = "std")]
13sp_externalities::decl_extension! {
14 pub struct OcwCustomExt (
16 Vec<u8>
18 );
19}
20
21#[runtime_interface]
23pub trait Custom: ExternalitiesExt {
24 fn get_val(&mut self) -> Option<Vec<u8>> {
26 self.extension::<OcwCustomExt>().map(|ext| ext.0.clone())
27 }
28}
29pub const MSA_ACCOUNT_LOCK_TIMEOUT_EXPIRATION_MS: u64 = 50;
31pub const MSA_ACCOUNT_LOCK_NAME_PREFIX: &[u8; 16] = b"Msa::ofw::lock::";
33pub const MSA_ACCOUNT_STORAGE_NAME_PREFIX: &[u8; 16] = b"Msa::ofw::keys::";
35pub fn get_msa_account_lock_name(msa_id: MessageSourceId) -> Vec<u8> {
37 let mut buff = [0u8; 30];
38 [MSA_ACCOUNT_LOCK_NAME_PREFIX, msa_id.numtoa(10, &mut buff)].concat()
39}
40pub fn get_msa_account_storage_key_name(msa_id: MessageSourceId) -> Vec<u8> {
42 let mut buff = [0u8; 30];
43 [MSA_ACCOUNT_STORAGE_NAME_PREFIX, msa_id.numtoa(10, &mut buff)].concat()
44}
45
46#[derive(Debug)]
48pub enum LockStatus {
49 Locked,
51 Released,
53}
54
55pub fn get_index_value<V: Decode + Debug>(key: &[u8]) -> Result<Option<V>, StorageRetrievalError> {
57 get_impl::<V>(key)
58}
59
60fn get_impl<V: Decode + Debug>(key: &[u8]) -> Result<Option<V>, StorageRetrievalError> {
62 let oci_mem = StorageValueRef::persistent(key);
63 match oci_mem.get::<V>() {
64 Ok(Some(data)) => Ok(Some(data)),
65 Ok(None) => Ok(None),
66 Err(_) => Err(StorageRetrievalError::Undecodable),
67 }
68}
69
70#[cfg(test)]
71mod tests {
72 use super::*;
73 use sp_core::offchain::{testing, OffchainDbExt, OffchainWorkerExt};
74 use sp_io::TestExternalities;
75
76 #[test]
77 fn get_msa_account_lock_name_should_return_expected_value() {
78 let msa_id: MessageSourceId = 2_000_000;
79 let result = get_msa_account_lock_name(msa_id);
80 assert_eq!(result, b"Msa::ofw::lock::2000000".to_vec());
81 }
82
83 #[test]
84 fn get_msa_account_storage_name_should_return_expected_value() {
85 let msa_id: MessageSourceId = 2_000_000;
86 let result = get_msa_account_storage_key_name(msa_id);
87 assert_eq!(result, b"Msa::ofw::keys::2000000".to_vec());
88 }
89
90 #[test]
91 fn get_index_for_not_set_should_return_none() {
92 let (offchain, _state) = testing::TestOffchainExt::new();
93 let mut t = TestExternalities::default();
94 t.register_extension(OffchainDbExt::new(offchain.clone()));
95 t.register_extension(OffchainWorkerExt::new(offchain));
96
97 t.execute_with(|| {
98 let key = b"my_key";
99 let result = get_index_value::<MessageSourceId>(key);
100 assert_eq!(result, Ok(None));
101 });
102 }
103
104 #[test]
105 fn get_index_for_set_should_return_expected() {
106 let (offchain, _state) = testing::TestOffchainExt::new();
108 let mut t = TestExternalities::default();
109 t.register_extension(OffchainDbExt::new(offchain.clone()));
110 t.register_extension(OffchainWorkerExt::new(offchain));
111
112 t.execute_with(|| {
113 let key = b"my_key1";
114 let msa_id: MessageSourceId = 1000000;
115 let oci_mem = StorageValueRef::persistent(key);
116 oci_mem.set(&msa_id);
117
118 let result = get_index_value::<MessageSourceId>(key);
120
121 assert_eq!(result, Ok(Some(msa_id)));
123 });
124 }
125
126 #[test]
127 fn get_index_for_not_decodable_should_return_error() {
128 let (offchain, _state) = testing::TestOffchainExt::new();
129 let mut t = TestExternalities::default();
130 t.register_extension(OffchainDbExt::new(offchain.clone()));
131 t.register_extension(OffchainWorkerExt::new(offchain));
132
133 #[derive(Debug, Decode, PartialEq)]
134 struct Testing {
135 pub a: u64,
136 pub b: u32,
137 pub c: u16,
138 }
139
140 t.execute_with(|| {
141 let key = b"my_key2";
143 let msa_id: MessageSourceId = 1000000;
144 let oci_mem = StorageValueRef::persistent(key);
145 oci_mem.set(&msa_id);
146
147 let result = get_index_value::<Testing>(key);
149
150 assert_eq!(result, Err(StorageRetrievalError::Undecodable));
152 });
153 }
154}