numbat_wasm_debug/api/
storage_api_mock.rs

1use crate::{TxContext, TxPanic};
2use alloc::vec::Vec;
3use numbat_wasm::api::{BigIntApi, Handle, ManagedBufferApi, StorageReadApi, StorageWriteApi};
4use num_bigint::{BigInt, BigUint, Sign};
5use num_traits::ToPrimitive;
6
7impl StorageReadApi for TxContext {
8    fn storage_load_len(&self, key: &[u8]) -> usize {
9        self.storage_load_vec_u8(key).len()
10    }
11
12    fn storage_load_vec_u8(&self, key: &[u8]) -> Vec<u8> {
13        let tx_output = self.tx_output_cell.borrow();
14        match tx_output.contract_storage.get(&key.to_vec()) {
15            None => Vec::with_capacity(0),
16            Some(value) => value.clone(),
17        }
18    }
19
20    fn storage_load_big_uint_raw(&self, key: &[u8]) -> Handle {
21        let bytes = self.storage_load_vec_u8(key);
22        let bi = BigInt::from_bytes_be(Sign::Plus, bytes.as_slice());
23        let mut tx_output = self.tx_output_cell.borrow_mut();
24        tx_output.managed_types.big_int_map.insert_new_handle(bi)
25    }
26
27    fn storage_load_managed_buffer_raw(&self, key_handle: Handle) -> Handle {
28        let key_bytes = self.mb_to_boxed_bytes(key_handle);
29        let bytes = self.storage_load_vec_u8(key_bytes.as_slice());
30        self.mb_new_from_bytes(bytes.as_slice())
31    }
32
33    fn storage_load_managed_buffer_len(&self, key_handle: Handle) -> usize {
34        let key_bytes = self.mb_to_boxed_bytes(key_handle);
35        let bytes = self.storage_load_vec_u8(key_bytes.as_slice());
36        bytes.len()
37    }
38
39    fn storage_load_u64(&self, key: &[u8]) -> u64 {
40        let value = self.storage_load_vec_u8(key);
41        let bu = BigUint::from_bytes_be(value.as_slice());
42        if let Some(v) = bu.to_u64() {
43            v
44        } else {
45            std::panic::panic_any(TxPanic {
46                status: 10,
47                message: b"storage value out of range".to_vec(),
48            })
49        }
50    }
51
52    fn storage_load_i64(&self, key: &[u8]) -> i64 {
53        let value = self.storage_load_vec_u8(key);
54        let bi = BigInt::from_signed_bytes_be(value.as_slice());
55        if let Some(v) = bi.to_i64() {
56            v
57        } else {
58            std::panic::panic_any(TxPanic {
59                status: 10,
60                message: b"storage value out of range".to_vec(),
61            })
62        }
63    }
64}
65
66impl StorageWriteApi for TxContext {
67    fn storage_store_slice_u8(&self, key: &[u8], value: &[u8]) {
68        // TODO: extract magic strings somewhere
69        if key.starts_with(&b"NUMBAT"[..]) {
70            std::panic::panic_any(TxPanic {
71                status: 10,
72                message: b"cannot write to storage under Numbat reserved key".to_vec(),
73            });
74        }
75
76        let mut tx_output = self.tx_output_cell.borrow_mut();
77        tx_output
78            .contract_storage
79            .insert(key.to_vec(), value.to_vec());
80    }
81
82    fn storage_store_big_uint_raw(&self, key: &[u8], handle: i32) {
83        self.storage_store_slice_u8(key, self.bi_get_signed_bytes(handle).as_slice());
84    }
85
86    fn storage_store_managed_buffer_raw(&self, key_handle: Handle, value_handle: Handle) {
87        let key_bytes = self.mb_to_boxed_bytes(key_handle);
88        let value_bytes = self.mb_to_boxed_bytes(value_handle);
89        self.storage_store_slice_u8(key_bytes.as_slice(), value_bytes.as_slice());
90    }
91
92    fn storage_store_managed_buffer_clear(&self, key_handle: Handle) {
93        let key_bytes = self.mb_to_boxed_bytes(key_handle);
94        self.storage_store_slice_u8(key_bytes.as_slice(), &[]);
95    }
96
97    fn storage_store_u64(&self, key: &[u8], value: u64) {
98        if value == 0 {
99            self.storage_store_slice_u8(key, &[]);
100        } else {
101            self.storage_store_slice_u8(key, &BigUint::from(value).to_bytes_be());
102        }
103    }
104
105    fn storage_store_i64(&self, key: &[u8], value: i64) {
106        if value == 0 {
107            self.storage_store_slice_u8(key, &[]);
108        } else {
109            self.storage_store_slice_u8(key, &BigInt::from(value).to_signed_bytes_be());
110        }
111    }
112}