1#[cfg(feature = "p7")]
2use crate::vec;
3use crate::{
4 cell::UnsafeCell,
5 convert::{self, TryInto},
6 fmt,
7 marker::PhantomData,
8 mem::{self, MaybeUninit},
9 num,
10 num::NonZeroU32,
11 prims, state_btree,
12 traits::*,
13 types::*,
14 vec::Vec,
15 String,
16};
17pub(crate) use concordium_contracts_common::*;
18
19impl convert::From<()> for Reject {
21 #[inline(always)]
22 fn from(_: ()) -> Self { unsafe { num::NonZeroI32::new_unchecked(i32::MIN + 1) }.into() }
23}
24
25impl convert::From<ParseError> for Reject {
27 #[inline(always)]
28 fn from(_: ParseError) -> Self {
29 unsafe { num::NonZeroI32::new_unchecked(i32::MIN + 2) }.into()
30 }
31}
32
33impl From<LogError> for Reject {
36 #[inline(always)]
37 fn from(le: LogError) -> Self {
38 match le {
39 LogError::Full => unsafe { crate::num::NonZeroI32::new_unchecked(i32::MIN + 3) }.into(),
40 LogError::Malformed => {
41 unsafe { crate::num::NonZeroI32::new_unchecked(i32::MIN + 4) }.into()
42 }
43 }
44 }
45}
46
47impl From<NewContractNameError> for Reject {
52 fn from(nre: NewContractNameError) -> Self {
53 match nre {
54 NewContractNameError::MissingInitPrefix => unsafe {
55 crate::num::NonZeroI32::new_unchecked(i32::MIN + 5).into()
56 },
57 NewContractNameError::TooLong => unsafe {
58 crate::num::NonZeroI32::new_unchecked(i32::MIN + 6).into()
59 },
60 NewContractNameError::ContainsDot => unsafe {
61 crate::num::NonZeroI32::new_unchecked(i32::MIN + 9).into()
62 },
63 NewContractNameError::InvalidCharacters => unsafe {
64 crate::num::NonZeroI32::new_unchecked(i32::MIN + 10).into()
65 },
66 }
67 }
68}
69
70impl From<NewReceiveNameError> for Reject {
74 fn from(nre: NewReceiveNameError) -> Self {
75 match nre {
76 NewReceiveNameError::MissingDotSeparator => unsafe {
77 crate::num::NonZeroI32::new_unchecked(i32::MIN + 7).into()
78 },
79 NewReceiveNameError::TooLong => unsafe {
80 crate::num::NonZeroI32::new_unchecked(i32::MIN + 8).into()
81 },
82 NewReceiveNameError::InvalidCharacters => unsafe {
83 crate::num::NonZeroI32::new_unchecked(i32::MIN + 11).into()
84 },
85 }
86 }
87}
88
89impl From<NotPayableError> for Reject {
91 #[inline(always)]
92 fn from(_: NotPayableError) -> Self {
93 unsafe { crate::num::NonZeroI32::new_unchecked(i32::MIN + 12) }.into()
94 }
95}
96
97impl From<TransferError> for Reject {
100 #[inline(always)]
101 fn from(te: TransferError) -> Self {
102 match te {
103 TransferError::AmountTooLarge => unsafe {
104 crate::num::NonZeroI32::new_unchecked(i32::MIN + 13).into()
105 },
106 TransferError::MissingAccount => unsafe {
107 crate::num::NonZeroI32::new_unchecked(i32::MIN + 14).into()
108 },
109 }
110 }
111}
112
113impl<T> From<CallContractError<T>> for Reject {
121 #[inline(always)]
122 fn from(cce: CallContractError<T>) -> Self {
123 match cce {
124 CallContractError::AmountTooLarge => unsafe {
125 crate::num::NonZeroI32::new_unchecked(i32::MIN + 15).into()
126 },
127 CallContractError::MissingAccount => unsafe {
128 crate::num::NonZeroI32::new_unchecked(i32::MIN + 16).into()
129 },
130 CallContractError::MissingContract => unsafe {
131 crate::num::NonZeroI32::new_unchecked(i32::MIN + 17).into()
132 },
133 CallContractError::MissingEntrypoint => unsafe {
134 crate::num::NonZeroI32::new_unchecked(i32::MIN + 18).into()
135 },
136 CallContractError::MessageFailed => unsafe {
137 crate::num::NonZeroI32::new_unchecked(i32::MIN + 19).into()
138 },
139 CallContractError::LogicReject {
140 ..
141 } => unsafe { crate::num::NonZeroI32::new_unchecked(i32::MIN + 20).into() },
142 CallContractError::Trap => unsafe {
143 crate::num::NonZeroI32::new_unchecked(i32::MIN + 21).into()
144 },
145 }
146 }
147}
148
149impl From<UpgradeError> for Reject {
153 #[inline(always)]
154 fn from(te: UpgradeError) -> Self {
155 match te {
156 UpgradeError::MissingModule => unsafe {
157 crate::num::NonZeroI32::new_unchecked(i32::MIN + 22).into()
158 },
159 UpgradeError::MissingContract => unsafe {
160 crate::num::NonZeroI32::new_unchecked(i32::MIN + 23).into()
161 },
162 UpgradeError::UnsupportedModuleVersion => unsafe {
163 crate::num::NonZeroI32::new_unchecked(i32::MIN + 24).into()
164 },
165 }
166 }
167}
168
169impl From<QueryAccountBalanceError> for Reject {
171 #[inline(always)]
172 fn from(_: QueryAccountBalanceError) -> Self {
173 unsafe { crate::num::NonZeroI32::new_unchecked(i32::MIN + 25).into() }
174 }
175}
176
177impl From<QueryContractBalanceError> for Reject {
179 #[inline(always)]
180 fn from(_: QueryContractBalanceError) -> Self {
181 unsafe { crate::num::NonZeroI32::new_unchecked(i32::MIN + 26).into() }
182 }
183}
184
185impl Write for ExternReturnValue {
190 type Err = ();
191
192 fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Err> {
193 let len: u32 = {
194 match buf.len().try_into() {
195 Ok(v) => v,
196 _ => return Err(()),
197 }
198 };
199 if self.current_position.checked_add(len).is_none() {
200 return Err(());
201 }
202 let num_bytes = unsafe { prims::write_output(buf.as_ptr(), len, self.current_position) };
203 self.current_position += num_bytes; Ok(num_bytes as usize)
205 }
206}
207
208impl ExternReturnValue {
209 #[inline(always)]
210 pub fn open() -> Self {
216 Self {
217 current_position: 0,
218 }
219 }
220}
221
222impl StateEntry {
223 pub(crate) fn open(state_entry_id: StateEntryId, key: Vec<u8>) -> Self {
225 Self {
226 state_entry_id,
227 key,
228 current_position: 0,
229 }
230 }
231}
232
233impl HasStateEntry for StateEntry {
234 type Error = ();
235 type StateEntryData = ();
236 type StateEntryKey = ();
237
238 #[inline(always)]
239 fn move_to_start(&mut self) { self.current_position = 0; }
240
241 #[inline(always)]
242 fn size(&self) -> Result<u32, Self::Error> {
243 let res = unsafe { prims::state_entry_size(self.state_entry_id) };
244 match res {
245 u32::MAX => Err(()),
246 _ => Ok(res),
247 }
248 }
249
250 fn truncate(&mut self, new_size: u32) -> Result<(), Self::Error> {
251 let cur_size = self.size()?;
252 if cur_size > new_size {
253 self.resize(new_size)?;
254 }
255 Ok(())
256 }
257
258 fn get_key(&self) -> &[u8] { &self.key }
259
260 fn resize(&mut self, new_size: u32) -> Result<(), Self::Error> {
261 let res = unsafe { prims::state_entry_resize(self.state_entry_id, new_size) };
262 match res {
263 1 => {
264 if self.current_position > new_size {
265 self.current_position = new_size;
266 }
267 Ok(())
268 }
269 _ => Err(()),
270 }
271 }
272}
273
274impl Seek for StateEntry {
275 type Err = ();
276
277 #[inline]
278 fn seek(&mut self, pos: SeekFrom) -> Result<u32, Self::Err> {
281 use SeekFrom::*;
282 let end = self.size()?;
283 match pos {
284 Start(offset) => {
285 if offset <= end {
286 self.current_position = offset;
287 Ok(offset)
288 } else {
289 Err(())
290 }
291 }
292 End(delta) => {
293 if delta > 0 {
294 Err(()) } else {
296 let new_offset = end.wrapping_add(delta as u32);
301 if new_offset <= end {
302 self.current_position = new_offset;
303 Ok(new_offset)
304 } else {
305 Err(())
306 }
307 }
308 }
309 Current(delta) => {
310 let new_offset = self.current_position + delta as u32;
313 if new_offset <= end {
314 self.current_position = new_offset;
315 Ok(new_offset)
316 } else {
317 Err(())
318 }
319 }
320 }
321 }
322
323 #[inline(always)]
324 fn cursor_position(&self) -> u32 { self.current_position }
325}
326
327impl Read for StateEntry {
328 fn read(&mut self, buf: &mut [u8]) -> ParseResult<usize> {
329 let len: u32 = buf.len().try_into().map_err(|_| ParseError::default())?;
330 let num_read = unsafe {
331 prims::state_entry_read(
332 self.state_entry_id,
333 buf.as_mut_ptr(),
334 len,
335 self.current_position,
336 )
337 };
338 if num_read == u32::MAX {
339 return Err(ParseError::default()); }
341 self.current_position += num_read;
342 Ok(num_read as usize)
343 }
344
345 fn read_u64(&mut self) -> ParseResult<u64> {
348 let mut bytes: MaybeUninit<[u8; 8]> = MaybeUninit::uninit();
349 let num_read = unsafe {
350 prims::state_entry_read(
351 self.state_entry_id,
352 bytes.as_mut_ptr() as *mut u8,
353 8,
354 self.current_position,
355 )
356 };
357 if num_read == u32::MAX {
358 return Err(ParseError::default()); }
360 self.current_position += num_read;
361 if num_read == 8 {
362 unsafe { Ok(u64::from_le_bytes(bytes.assume_init())) }
363 } else {
364 Err(ParseError::default())
365 }
366 }
367
368 fn read_u32(&mut self) -> ParseResult<u32> {
371 let mut bytes: MaybeUninit<[u8; 4]> = MaybeUninit::uninit();
372 let num_read = unsafe {
373 prims::state_entry_read(
374 self.state_entry_id,
375 bytes.as_mut_ptr() as *mut u8,
376 4,
377 self.current_position,
378 )
379 };
380 if num_read == u32::MAX {
381 return Err(ParseError::default()); }
383 self.current_position += num_read;
384 if num_read == 4 {
385 unsafe { Ok(u32::from_le_bytes(bytes.assume_init())) }
386 } else {
387 Err(ParseError::default())
388 }
389 }
390
391 fn read_u8(&mut self) -> ParseResult<u8> {
394 let mut bytes: MaybeUninit<[u8; 1]> = MaybeUninit::uninit();
395 let num_read = unsafe {
396 prims::state_entry_read(
397 self.state_entry_id,
398 bytes.as_mut_ptr() as *mut u8,
399 1,
400 self.current_position,
401 )
402 };
403 if num_read == u32::MAX {
404 return Err(ParseError::default()); }
406 self.current_position += num_read;
407 if num_read == 1 {
408 unsafe { Ok(bytes.assume_init()[0]) }
409 } else {
410 Err(ParseError::default())
411 }
412 }
413}
414
415impl Write for StateEntry {
416 type Err = ();
417
418 fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Err> {
419 let len: u32 = {
420 match buf.len().try_into() {
421 Ok(v) => v,
422 _ => return Err(()),
423 }
424 };
425 if self.current_position.checked_add(len).is_none() {
426 return Err(());
427 }
428 let num_bytes = unsafe {
429 prims::state_entry_write(self.state_entry_id, buf.as_ptr(), len, self.current_position)
430 };
431 if num_bytes == u32::MAX {
432 return Err(()); }
434 self.current_position += num_bytes; Ok(num_bytes as usize)
436 }
437}
438
439impl<StateApi: HasStateApi> VacantEntryRaw<StateApi> {
440 pub(crate) fn new(key: Key, state_api: StateApi) -> Self {
442 Self {
443 key,
444 state_api,
445 }
446 }
447
448 #[inline(always)]
451 pub fn key(&self) -> &[u8] { &self.key }
452
453 pub fn insert_raw(mut self, value: &[u8]) -> Result<StateApi::EntryType, StateError> {
455 let mut entry = self.state_api.create_entry(&self.key)?;
456 entry.write_all(value).unwrap_abort(); entry.move_to_start(); Ok(entry)
459 }
460
461 pub fn insert<V: Serial>(mut self, value: &V) -> Result<StateApi::EntryType, StateError> {
468 let mut entry = self.state_api.create_entry(&self.key)?;
469 value.serial(&mut entry).unwrap_abort();
472 entry.move_to_start(); Ok(entry)
474 }
475}
476
477impl<StateApi: HasStateApi> OccupiedEntryRaw<StateApi> {
478 pub(crate) fn new(state_entry: StateApi::EntryType) -> Self {
480 Self {
481 state_entry,
482 }
483 }
484
485 #[inline(always)]
488 pub fn key(&self) -> &[u8] { self.state_entry.get_key() }
489
490 #[inline(always)]
492 pub fn get_ref(&self) -> &StateApi::EntryType { &self.state_entry }
493
494 #[inline(always)]
499 pub fn get(self) -> StateApi::EntryType { self.state_entry }
500
501 #[inline(always)]
506 pub fn get_mut(&mut self) -> &mut StateApi::EntryType { &mut self.state_entry }
507
508 pub fn insert_raw(&mut self, value: &[u8]) {
510 self.state_entry.move_to_start();
511 self.state_entry.write_all(value).unwrap_abort();
512
513 self.state_entry.truncate(value.len() as u32).unwrap_abort();
515 }
516
517 pub fn insert<V: Serial>(&mut self, value: &V) {
522 self.state_entry.truncate(0).unwrap_abort();
524 self.state_entry.move_to_start();
525 value.serial(&mut self.state_entry).unwrap_abort()
526 }
527}
528
529impl<StateApi: HasStateApi> EntryRaw<StateApi> {
530 pub fn or_insert_raw(self, default: &[u8]) -> Result<StateApi::EntryType, StateError> {
533 match self {
534 EntryRaw::Vacant(vac) => vac.insert_raw(default),
535 EntryRaw::Occupied(occ) => Ok(occ.get()),
536 }
537 }
538
539 pub fn or_insert<V: Serial>(self, default: &V) -> StateApi::EntryType {
546 match self {
547 EntryRaw::Vacant(vac) => vac.insert(default).unwrap_abort(),
548 EntryRaw::Occupied(occ) => occ.get(),
549 }
550 }
551
552 pub fn key(&self) -> &[u8] {
554 match self {
555 EntryRaw::Vacant(vac) => vac.key(),
556 EntryRaw::Occupied(occ) => occ.key(),
557 }
558 }
559}
560
561impl<'a, K, V, StateApi> VacantEntry<'a, K, V, StateApi>
562where
563 K: Serial,
564 V: Serial,
565 StateApi: HasStateApi,
566{
567 pub(crate) fn new(key: K, key_bytes: Vec<u8>, state_api: StateApi) -> Self {
569 Self {
570 key,
571 key_bytes,
572 state_api,
573 _lifetime_marker: PhantomData,
574 }
575 }
576
577 #[inline(always)]
579 pub fn key(&self) -> &K { &self.key }
580
581 #[inline(always)]
583 pub fn into_key(self) -> K { self.key }
584
585 pub fn insert(mut self, value: V) -> OccupiedEntry<'a, K, V, StateApi> {
587 let mut state_entry = self.state_api.create_entry(&self.key_bytes).unwrap_abort();
589 value.serial(&mut state_entry).unwrap_abort();
590 state_entry.move_to_start(); OccupiedEntry {
592 key: self.key,
593 value,
594 modified: false,
595 state_entry,
596 _lifetime_marker: self._lifetime_marker,
597 }
598 }
599}
600
601impl<'a, K, V, StateApi> OccupiedEntry<'a, K, V, StateApi>
602where
603 K: Serial,
604 V: Serial,
605 StateApi: HasStateApi,
606{
607 pub(crate) fn new(key: K, value: V, state_entry: StateApi::EntryType) -> Self {
609 Self {
610 key,
611 value,
612 modified: false,
613 state_entry,
614 _lifetime_marker: PhantomData,
615 }
616 }
617
618 #[inline(always)]
620 pub fn key(&self) -> &K { &self.key }
621
622 #[inline(always)]
624 pub fn get_ref(&self) -> &V { &self.value }
625
626 #[inline]
629 pub fn modify<F, A>(&mut self, f: F) -> A
630 where
631 F: FnOnce(&mut V) -> A, {
636 let res = f(&mut self.value);
637 self.store_value();
638 res
639 }
640
641 pub fn try_modify<F, A, E>(&mut self, f: F) -> Result<A, E>
644 where
645 F: FnOnce(&mut V) -> Result<A, E>, {
646 let res = f(&mut self.value)?;
647 self.store_value();
648 Ok(res)
649 }
650}
651
652impl<'a, K, V, StateApi> OccupiedEntry<'a, K, V, StateApi>
653where
654 V: Serial,
655 StateApi: HasStateApi,
656{
657 pub(crate) fn store_value(&mut self) {
658 self.state_entry.truncate(0).unwrap_abort();
664 self.value.serial(&mut self.state_entry).unwrap_abort();
670 }
671}
672
673impl<'a, K, V, StateApi> Entry<'a, K, V, StateApi>
674where
675 K: Serial,
676 V: Serial,
677 StateApi: HasStateApi,
678{
679 #[inline(always)]
681 pub fn is_vacant(&self) -> bool { matches!(self, Entry::Vacant(_)) }
682
683 #[inline(always)]
685 pub fn is_occupied(&self) -> bool { matches!(self, Entry::Occupied(_)) }
686
687 #[inline]
690 pub fn occupied_or<E>(self, e: E) -> Result<OccupiedEntry<'a, K, V, StateApi>, E> {
691 match self {
692 Entry::Vacant(_) => Err(e),
693 Entry::Occupied(oe) => Ok(oe),
694 }
695 }
696
697 #[inline]
700 pub fn vacant_or<E>(self, e: E) -> Result<VacantEntry<'a, K, V, StateApi>, E> {
701 match self {
702 Entry::Vacant(vac) => Ok(vac),
703 Entry::Occupied(_) => Err(e),
704 }
705 }
706
707 pub fn or_insert(self, value: V) -> OccupiedEntry<'a, K, V, StateApi> {
710 match self {
711 Entry::Vacant(vac) => vac.insert(value),
712 Entry::Occupied(oe) => oe,
713 }
714 }
715
716 pub fn or_insert_with<F>(self, default: F) -> OccupiedEntry<'a, K, V, StateApi>
719 where
720 F: FnOnce() -> V, {
721 match self {
722 Entry::Vacant(vac) => vac.insert(default()),
723 Entry::Occupied(oe) => oe,
724 }
725 }
726
727 pub fn and_try_modify<F, E>(mut self, f: F) -> Result<Entry<'a, K, V, StateApi>, E>
733 where
734 F: FnOnce(&mut V) -> Result<(), E>, {
735 if let Entry::Occupied(ref mut occ) = self {
736 occ.try_modify(f)?;
737 }
738 Ok(self)
739 }
740
741 pub fn and_modify<F>(mut self, f: F) -> Entry<'a, K, V, StateApi>
744 where
745 F: FnOnce(&mut V), {
746 if let Entry::Occupied(ref mut occ) = self {
747 occ.modify(f);
748 }
749 self
750 }
751
752 pub fn key(&self) -> &K {
754 match self {
755 Entry::Vacant(vac) => vac.key(),
756 Entry::Occupied(occ) => occ.key(),
757 }
758 }
759}
760
761impl<'a, K, V, StateApi> Entry<'a, K, V, StateApi>
762where
763 K: Serial,
764 V: Serial + Default,
765 StateApi: HasStateApi,
766{
767 #[allow(clippy::unwrap_or_default)]
769 pub fn or_default(self) -> OccupiedEntry<'a, K, V, StateApi> {
770 self.or_insert_with(Default::default)
771 }
772}
773
774const NEXT_ITEM_PREFIX_KEY: [u8; 8] = 0u64.to_le_bytes();
778pub(crate) const INITIAL_NEXT_ITEM_PREFIX: [u8; 8] = 2u64.to_le_bytes();
781
782impl HasStateApi for ExternStateApi {
783 type EntryType = StateEntry;
784 type IterType = ExternStateIter;
785
786 fn create_entry(&mut self, key: &[u8]) -> Result<Self::EntryType, StateError> {
787 let key_start = key.as_ptr();
788 let key_len = key.len() as u32; let entry_id = unsafe { prims::state_create_entry(key_start, key_len) };
790 if entry_id == u64::MAX {
791 return Err(StateError::SubtreeLocked);
792 }
793 Ok(StateEntry::open(entry_id, key.to_vec()))
794 }
795
796 fn lookup_entry(&self, key: &[u8]) -> Option<Self::EntryType> {
797 let key_start = key.as_ptr();
798 let key_len = key.len() as u32; let entry_id = unsafe { prims::state_lookup_entry(key_start, key_len) };
800 if entry_id == u64::MAX {
801 None
802 } else {
803 Some(StateEntry::open(entry_id, key.to_vec()))
804 }
805 }
806
807 fn delete_entry(&mut self, entry: Self::EntryType) -> Result<(), StateError> {
808 let key = entry.get_key();
809 let res = unsafe { prims::state_delete_entry(key.as_ptr(), key.len() as u32) };
810 match res {
811 0 => Err(StateError::SubtreeLocked),
812 1 => Err(StateError::EntryNotFound),
813 2 => Ok(()),
814 _ => crate::trap(), }
816 }
817
818 fn delete_prefix(&mut self, prefix: &[u8]) -> Result<bool, StateError> {
819 let res = unsafe { prims::state_delete_prefix(prefix.as_ptr(), prefix.len() as u32) };
820 match res {
821 0 => Err(StateError::SubtreeLocked),
822 1 => Ok(false),
823 2 => Ok(true),
824 _ => crate::trap(), }
826 }
827
828 fn iterator(&self, prefix: &[u8]) -> Result<Self::IterType, StateError> {
829 let prefix_start = prefix.as_ptr();
830 let prefix_len = prefix.len() as u32; let iterator_id = unsafe { prims::state_iterate_prefix(prefix_start, prefix_len) };
832 match iterator_id {
833 OK_NONE => Err(StateError::SubtreeWithPrefixNotFound),
834 ERR => Err(StateError::IteratorLimitForPrefixExceeded),
835 iterator_id => Ok(ExternStateIter {
836 iterator_id,
837 }),
838 }
839 }
840
841 fn delete_iterator(&mut self, iter: Self::IterType) {
842 unsafe { prims::state_iterator_delete(iter.iterator_id) };
852 }
853}
854
855const OK_NONE: u64 = u64::MAX;
857const ERR: u64 = u64::MAX & !(1u64 << 62);
859
860impl Iterator for ExternStateIter {
861 type Item = StateEntry;
862
863 fn next(&mut self) -> Option<Self::Item> {
864 let res = unsafe { prims::state_iterator_next(self.iterator_id) };
865 match res {
866 OK_NONE => None,
867 ERR => None,
873 _ => {
874 let key_size = unsafe { prims::state_iterator_key_size(self.iterator_id) };
877 let mut key = Vec::with_capacity(key_size as usize);
878 unsafe {
880 let num_read = prims::state_iterator_key_read(
881 self.iterator_id,
882 key.as_mut_ptr(),
883 key_size,
884 0,
885 );
886 key.set_len(num_read as usize);
887 };
888 Some(StateEntry::open(res, key))
889 }
890 }
891 }
892}
893
894impl<K, V, S> StateMap<K, V, S>
895where
896 S: HasStateApi,
897 K: Serialize,
898 V: Serial + DeserialWithState<S>,
899{
900 pub fn get(&self, key: &K) -> Option<StateRef<V>> {
903 let k = self.key_with_map_prefix(key);
904 self.state_api.lookup_entry(&k).map(|mut entry| {
905 StateRef::new(V::deserial_with_state(&self.state_api, &mut entry).unwrap_abort())
907 })
908 }
909
910 pub fn get_mut(&mut self, key: &K) -> Option<StateRefMut<V, S>> {
914 let k = self.key_with_map_prefix(key);
915 let entry = self.state_api.lookup_entry(&k)?;
916 Some(StateRefMut::new(entry, self.state_api.clone()))
917 }
918
919 pub(crate) fn insert_borrowed(&mut self, key: &K, value: V) -> Option<V> {
924 let key_bytes = self.key_with_map_prefix(key);
925 match self.state_api.entry(key_bytes) {
927 EntryRaw::Vacant(vac) => {
928 let _ = vac.insert(&value).unwrap_abort();
929 None
930 }
931 EntryRaw::Occupied(mut occ) => {
932 let old_value =
934 V::deserial_with_state(&self.state_api, occ.get_mut()).unwrap_abort();
935 occ.insert(&value);
936 Some(old_value)
937 }
938 }
939 }
940
941 #[must_use]
951 pub fn insert(&mut self, key: K, value: V) -> Option<V> { self.insert_borrowed(&key, value) }
952
953 pub fn entry(&mut self, key: K) -> Entry<'_, K, V, S> {
955 let key_bytes = self.key_with_map_prefix(&key);
956 match self.state_api.lookup_entry(&key_bytes) {
958 None => Entry::Vacant(VacantEntry::new(key, key_bytes, self.state_api.clone())),
959 Some(mut state_entry) => {
960 let value =
962 V::deserial_with_state(&self.state_api, &mut state_entry).unwrap_abort();
963 Entry::Occupied(OccupiedEntry::new(key, value, state_entry))
964 }
965 }
966 }
967
968 pub fn is_empty(&self) -> bool { self.state_api.lookup_entry(&self.prefix).is_none() }
970
971 pub fn clear(&mut self)
976 where
977 V: Deletable, {
978 for (_, value) in self.iter() {
981 value.value.delete()
982 }
983
984 self.state_api.delete_prefix(&self.prefix).unwrap_abort();
987 }
988
989 pub fn clear_flat(&mut self)
998 where
999 V: Deserial, {
1000 self.state_api.delete_prefix(&self.prefix).unwrap_abort();
1004 }
1005
1006 #[must_use]
1014 pub fn remove_and_get(&mut self, key: &K) -> Option<V> {
1015 let key_bytes = self.key_with_map_prefix(key);
1016 let entry_raw = self.state_api.entry(key_bytes);
1018 match entry_raw {
1019 EntryRaw::Vacant(_) => None,
1020 EntryRaw::Occupied(mut occ) => {
1021 let old_value =
1023 V::deserial_with_state(&self.state_api, occ.get_mut()).unwrap_abort();
1024 let _existed = self.state_api.delete_entry(occ.state_entry);
1025 Some(old_value)
1026 }
1027 }
1028 }
1029
1030 pub fn remove(&mut self, key: &K)
1033 where
1034 V: Deletable, {
1035 if let Some(v) = self.remove_and_get(key) {
1036 v.delete()
1037 }
1038 }
1039
1040 fn key_with_map_prefix(&self, key: &K) -> Vec<u8> {
1042 let mut key_with_prefix = self.prefix.to_vec();
1043 key.serial(&mut key_with_prefix).unwrap_abort();
1044 key_with_prefix
1045 }
1046}
1047
1048impl<'a, K, V, S: HasStateApi> Drop for StateMapIter<'a, K, V, S> {
1049 fn drop(&mut self) {
1050 if let Some(valid) = self.state_iter.take() {
1052 self.state_api.delete_iterator(valid);
1053 }
1054 }
1055}
1056
1057impl<K, V, S> StateMap<K, V, S>
1058where
1059 S: HasStateApi,
1060{
1061 pub(crate) fn open(state_api: S, prefix: [u8; 8]) -> Self {
1062 Self {
1063 _marker_key: PhantomData,
1064 _marker_value: PhantomData,
1065 prefix,
1066 state_api,
1067 }
1068 }
1069
1070 pub fn iter(&self) -> StateMapIter<'_, K, V, S> {
1074 match self.state_api.iterator(&self.prefix) {
1075 Ok(state_iter) => StateMapIter {
1076 state_iter: Some(state_iter),
1077 state_api: self.state_api.clone(),
1078 _lifetime_marker: PhantomData,
1079 },
1080 Err(StateError::SubtreeWithPrefixNotFound) => StateMapIter {
1081 state_iter: None,
1082 state_api: self.state_api.clone(),
1083 _lifetime_marker: PhantomData,
1084 },
1085 _ => crate::trap(),
1086 }
1087 }
1088
1089 pub fn iter_mut(&mut self) -> StateMapIterMut<'_, K, V, S> {
1092 match self.state_api.iterator(&self.prefix) {
1093 Ok(state_iter) => StateMapIterMut {
1094 state_iter: Some(state_iter),
1095 state_api: self.state_api.clone(),
1096 _lifetime_marker: PhantomData,
1097 },
1098 Err(StateError::SubtreeWithPrefixNotFound) => StateMapIterMut {
1099 state_iter: None,
1100 state_api: self.state_api.clone(),
1101 _lifetime_marker: PhantomData,
1102 },
1103 _ => crate::trap(),
1104 }
1105 }
1106}
1107
1108impl<'a, K, V, S: HasStateApi> Iterator for StateMapIter<'a, K, V, S>
1109where
1110 K: Deserial + 'a,
1111 V: DeserialWithState<S> + 'a,
1112{
1113 type Item = (StateRef<'a, K>, StateRef<'a, V>);
1114
1115 fn next(&mut self) -> Option<Self::Item> {
1116 let mut entry = self.state_iter.as_mut()?.next()?;
1117 let key = entry.get_key();
1118 let mut key_cursor = Cursor {
1119 data: key,
1120 offset: 8, };
1122 let k = K::deserial(&mut key_cursor).unwrap_abort();
1124 let v = V::deserial_with_state(&self.state_api, &mut entry).unwrap_abort();
1125 Some((StateRef::new(k), StateRef::new(v)))
1126 }
1127}
1128
1129impl<'a, K, V: Serial, S: HasStateApi> Iterator for StateMapIterMut<'a, K, V, S>
1130where
1131 K: Deserial + 'a,
1132 V: DeserialWithState<S> + 'a,
1133 S::EntryType: 'a,
1134{
1135 type Item = (StateRef<'a, K>, StateRefMut<'a, V, S>);
1136
1137 fn next(&mut self) -> Option<Self::Item> {
1138 let entry = self.state_iter.as_mut()?.next()?;
1139
1140 let key_bytes = entry.get_key();
1141 let mut key_cursor = Cursor {
1142 data: key_bytes,
1143 offset: 8, };
1145 let k = K::deserial(&mut key_cursor).unwrap_abort();
1147 Some((StateRef::new(k), StateRefMut::new(entry, self.state_api.clone())))
1150 }
1151}
1152
1153impl<'a, S: HasStateApi, V: Serial + DeserialWithState<S>> crate::ops::Deref
1154 for StateRefMut<'a, V, S>
1155{
1156 type Target = V;
1157
1158 #[inline(always)]
1159 fn deref(&self) -> &Self::Target { self.get() }
1160}
1161
1162impl<'a, S: HasStateApi, V: Serial + DeserialWithState<S>> crate::ops::DerefMut
1163 for StateRefMut<'a, V, S>
1164{
1165 #[inline(always)]
1166 fn deref_mut(&mut self) -> &mut Self::Target { self.get_mut() }
1167}
1168
1169impl<'a, V: Serial, S: HasStateApi> Drop for StateRefMut<'a, V, S> {
1171 fn drop(&mut self) { self.store_mutations() }
1172}
1173
1174impl<'a, V, S> StateRefMut<'a, V, S>
1175where
1176 V: Serial,
1177 S: HasStateApi,
1178{
1179 pub fn get(&self) -> &V
1183 where
1184 V: DeserialWithState<S>, {
1185 let lv = unsafe { &mut *self.lazy_value.get() };
1186 if let Some(v) = lv {
1187 v
1188 } else {
1189 lv.insert(self.load_value())
1190 }
1191 }
1192
1193 pub fn get_mut(&mut self) -> &mut V
1197 where
1198 V: DeserialWithState<S>, {
1199 let lv = unsafe { &mut *self.lazy_value.get() };
1200 if let Some(v) = lv {
1201 v
1202 } else {
1203 lv.insert(self.load_value())
1204 }
1205 }
1206
1207 fn load_value(&self) -> V
1209 where
1210 V: DeserialWithState<S>, {
1211 let entry = unsafe { &mut *self.entry.get() };
1214 entry.move_to_start();
1215 V::deserial_with_state(&self.state_api, entry).unwrap_abort()
1216 }
1217
1218 pub fn set(&mut self, new_val: V) {
1220 let entry = self.entry.get_mut();
1223 entry.move_to_start();
1224 new_val.serial(entry).unwrap_abort();
1225 let _ = self.lazy_value.get_mut().insert(new_val);
1226 }
1227
1228 pub fn update<F>(&mut self, f: F)
1230 where
1231 V: DeserialWithState<S>,
1232 F: FnOnce(&mut V), {
1233 let lv = self.lazy_value.get_mut();
1234 let entry = self.entry.get_mut();
1237 let value = if let Some(v) = lv {
1238 v
1239 } else {
1240 entry.move_to_start();
1241 let value = V::deserial_with_state(&self.state_api, entry).unwrap_abort();
1242 lv.insert(value)
1243 };
1244
1245 f(value);
1247 entry.move_to_start();
1248 value.serial(entry).unwrap_abort()
1249 }
1250
1251 pub(crate) fn store_mutations(&mut self) {
1253 if let Some(value) = self.lazy_value.get_mut() {
1254 let entry = self.entry.get_mut();
1257 entry.move_to_start();
1258 value.serial(entry).unwrap_abort();
1259 }
1260 }
1261
1262 pub(crate) fn drop_without_storing(mut self) { *self.lazy_value.get_mut() = None; }
1264}
1265
1266impl<K, V, S> Serial for StateMap<K, V, S> {
1267 fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> { out.write_all(&self.prefix) }
1268}
1269
1270impl<T, S> StateSet<T, S>
1271where
1272 T: Serialize,
1273 S: HasStateApi,
1274{
1275 pub fn insert(&mut self, value: T) -> bool {
1279 let key_bytes = self.key_with_set_prefix(&value);
1280 match self.state_api.entry(key_bytes) {
1281 EntryRaw::Vacant(vac) => {
1282 let _ = vac.insert_raw(&[]);
1283 true
1284 }
1285 EntryRaw::Occupied(_) => false,
1286 }
1287 }
1288
1289 pub fn is_empty(&self) -> bool { self.state_api.lookup_entry(&self.prefix).is_none() }
1291
1292 pub fn contains(&self, value: &T) -> bool {
1294 let key_bytes = self.key_with_set_prefix(value);
1295 self.state_api.lookup_entry(&key_bytes).is_some()
1296 }
1297
1298 pub fn clear(&mut self) {
1303 self.state_api.delete_prefix(&self.prefix).unwrap_abort();
1308 }
1309
1310 pub fn remove(&mut self, value: &T) -> bool {
1313 let key_bytes = self.key_with_set_prefix(value);
1314
1315 match self.state_api.entry(key_bytes) {
1317 EntryRaw::Vacant(_) => false,
1318 EntryRaw::Occupied(occ) => {
1319 self.state_api.delete_entry(occ.get()).unwrap_abort();
1321 true
1322 }
1323 }
1324 }
1325
1326 fn key_with_set_prefix(&self, key: &T) -> Vec<u8> {
1327 let mut key_with_prefix = self.prefix.to_vec();
1328 key.serial(&mut key_with_prefix).unwrap_abort();
1329 key_with_prefix
1330 }
1331}
1332
1333impl<T, S: HasStateApi> StateSet<T, S> {
1334 pub(crate) fn open(state_api: S, prefix: [u8; 8]) -> Self {
1335 Self {
1336 _marker: PhantomData,
1337 prefix,
1338 state_api,
1339 }
1340 }
1341
1342 pub fn iter(&self) -> StateSetIter<T, S> {
1346 match self.state_api.iterator(&self.prefix) {
1347 Ok(state_iter) => StateSetIter {
1348 state_iter: Some(state_iter),
1349 state_api: self.state_api.clone(),
1350 _marker_lifetime: PhantomData,
1351 },
1352 Err(StateError::SubtreeWithPrefixNotFound) => StateSetIter {
1353 state_iter: None,
1354 state_api: self.state_api.clone(),
1355 _marker_lifetime: PhantomData,
1356 },
1357 _ => crate::trap(),
1358 }
1359 }
1360}
1361
1362impl<T: Serial, S: HasStateApi> StateBox<T, S> {
1363 pub(crate) fn new(value: T, state_api: S, entry: S::EntryType) -> Self {
1365 StateBox {
1366 state_api,
1367 inner: UnsafeCell::new(StateBoxInner::Loaded {
1368 entry,
1369 modified: true,
1370 value,
1371 }),
1372 }
1373 }
1374
1375 pub(crate) fn get_location(&self) -> &[u8] {
1378 match unsafe { &*self.inner.get() } {
1379 StateBoxInner::Loaded {
1380 entry,
1381 ..
1382 } => entry.get_key(),
1383 StateBoxInner::Reference {
1384 prefix,
1385 } => &prefix[..],
1386 }
1387 }
1388}
1389
1390impl<S: HasStateApi, T: Serial + DeserialWithState<S>> crate::ops::Deref for StateBox<T, S> {
1391 type Target = T;
1392
1393 #[inline(always)]
1394 fn deref(&self) -> &Self::Target { self.get() }
1395}
1396
1397impl<S: HasStateApi, T: Serial + DeserialWithState<S>> crate::ops::DerefMut for StateBox<T, S> {
1398 #[inline(always)]
1399 fn deref_mut(&mut self) -> &mut Self::Target { self.get_mut() }
1400}
1401
1402impl<T: Serial, S: HasStateApi> Drop for StateBox<T, S> {
1403 fn drop(&mut self) {
1404 if let StateBoxInner::Loaded {
1405 entry,
1406 modified,
1407 value,
1408 } = self.inner.get_mut()
1409 {
1410 if *modified {
1411 entry.move_to_start();
1412 value.serial(entry).unwrap_abort();
1413 }
1414 }
1415 }
1416}
1417
1418fn get_with_inner<'a, T: Serial + DeserialWithState<S>, S: HasStateApi>(
1422 state_api: &S,
1423 inner: &'a mut StateBoxInner<T, S>,
1424) -> (&'a mut T, &'a mut bool) {
1425 let (entry, value) = match inner {
1426 StateBoxInner::Loaded {
1427 value,
1428 modified,
1429 ..
1430 } => return (value, modified),
1431 StateBoxInner::Reference {
1432 prefix,
1433 } => {
1434 let mut entry = state_api.lookup_entry(prefix).unwrap_abort();
1435 let value = T::deserial_with_state(state_api, &mut entry).unwrap_abort();
1437 (entry, value)
1438 }
1439 };
1440 *inner = StateBoxInner::Loaded {
1441 entry,
1442 modified: false,
1443 value,
1444 };
1445 match inner {
1446 StateBoxInner::Loaded {
1447 value,
1448 modified,
1449 ..
1450 } => (value, modified),
1451 StateBoxInner::Reference {
1452 ..
1453 } => {
1454 unsafe { crate::hint::unreachable_unchecked() }
1456 }
1457 }
1458}
1459
1460impl<T, S> StateBox<T, S>
1461where
1462 T: Serial + DeserialWithState<S>,
1463 S: HasStateApi,
1464{
1465 pub fn get(&self) -> &T {
1467 let inner = unsafe { &mut *self.inner.get() };
1468 get_with_inner(&self.state_api, inner).0
1469 }
1470
1471 pub fn get_mut(&mut self) -> &mut T {
1474 let inner = self.inner.get_mut();
1475 let (value, modified) = get_with_inner(&self.state_api, inner);
1476 *modified = true;
1477 value
1478 }
1479
1480 #[must_use]
1485 pub fn replace(&mut self, new_val: T) -> T {
1486 let (entry, value) = self.ensure_cached();
1487 entry.move_to_start();
1488 new_val.serial(entry).unwrap_abort();
1489 mem::replace(value, new_val)
1490 }
1491
1492 pub fn update<F, A>(&mut self, f: F) -> A
1496 where
1497 F: FnOnce(&mut T) -> A, {
1498 let (entry, value) = self.ensure_cached();
1499 let res = f(value);
1501 entry.move_to_start();
1502 value.serial(entry).unwrap_abort();
1503 res
1504 }
1505
1506 fn ensure_cached(&mut self) -> (&mut S::EntryType, &mut T) {
1510 let inner = self.inner.get_mut();
1511 let (entry, modified, value) = match inner {
1512 StateBoxInner::Loaded {
1513 entry,
1514 value,
1515 ..
1516 } => return (entry, value),
1517 StateBoxInner::Reference {
1518 prefix,
1519 } => {
1520 let mut entry = self.state_api.lookup_entry(prefix).unwrap_abort();
1521 let value = T::deserial_with_state(&self.state_api, &mut entry).unwrap_abort();
1523 (entry, false, value)
1524 }
1525 };
1526 *inner = StateBoxInner::Loaded {
1527 entry,
1528 modified,
1529 value,
1530 };
1531 match inner {
1532 StateBoxInner::Loaded {
1533 entry,
1534 value,
1535 ..
1536 } => (entry, value),
1537 StateBoxInner::Reference {
1538 ..
1539 } => {
1540 unsafe { crate::hint::unreachable_unchecked() }
1542 }
1543 }
1544 }
1545}
1546
1547impl<T: Serial, S: HasStateApi> Serial for StateBox<T, S> {
1548 fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
1549 out.write_all(self.get_location())
1550 }
1551}
1552
1553impl<T, S> Serial for StateSet<T, S> {
1554 fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> { out.write_all(&self.prefix) }
1555}
1556
1557impl<'a, T, S: HasStateApi> Drop for StateSetIter<'a, T, S> {
1559 #[inline]
1560 fn drop(&mut self) {
1561 if let Some(valid) = self.state_iter.take() {
1563 self.state_api.delete_iterator(valid);
1564 }
1565 }
1566}
1567
1568impl<'a, T, S: HasStateApi> Iterator for StateSetIter<'a, T, S>
1569where
1570 T: DeserialWithState<S>,
1571{
1572 type Item = StateRef<'a, T>;
1573
1574 #[inline(always)]
1575 fn next(&mut self) -> Option<Self::Item> {
1576 let entry = self.state_iter.as_mut()?.next()?;
1577 let key = entry.get_key();
1578 let mut key_cursor = Cursor {
1579 data: key,
1580 offset: 8, };
1582 let t = T::deserial_with_state(&self.state_api, &mut key_cursor).unwrap_abort();
1584 Some(StateRef::new(t))
1585 }
1586}
1587
1588impl Default for ExternParameter {
1591 #[inline(always)]
1592 fn default() -> Self {
1593 ExternParameter {
1594 cursor: Cursor::new(ExternParameterDataPlaceholder {}),
1595 }
1596 }
1597}
1598
1599impl Read for ExternParameter {
1600 fn read(&mut self, buf: &mut [u8]) -> ParseResult<usize> {
1601 let len: u32 = {
1602 match buf.len().try_into() {
1603 Ok(v) => v,
1604 _ => return Err(ParseError::default()),
1605 }
1606 };
1607 let num_read = unsafe {
1608 prims::get_parameter_section(0, buf.as_mut_ptr(), len, self.cursor.offset as u32)
1610 };
1611
1612 self.cursor.offset += num_read as usize;
1613 Ok(num_read as usize)
1614 }
1615}
1616
1617impl HasSize for ExternParameterDataPlaceholder {
1618 #[inline(always)]
1619 fn size(&self) -> u32 { unsafe { prims::get_parameter_size(0) as u32 } }
1621}
1622
1623impl HasSize for ExternParameter {
1624 #[inline(always)]
1625 fn size(&self) -> u32 { self.cursor.data.size() }
1626}
1627
1628impl Seek for ExternParameter {
1629 type Err = ();
1630
1631 #[inline(always)]
1632 fn seek(&mut self, pos: SeekFrom) -> Result<u32, Self::Err> { self.cursor.seek(pos) }
1633
1634 #[inline(always)]
1635 fn cursor_position(&self) -> u32 { self.cursor.cursor_position() }
1636}
1637
1638impl HasParameter for ExternParameter {}
1639
1640impl Read for ExternCallResponse {
1643 fn read(&mut self, buf: &mut [u8]) -> ParseResult<usize> {
1644 let len: u32 = {
1645 match buf.len().try_into() {
1646 Ok(v) => v,
1647 _ => return Err(ParseError::default()),
1648 }
1649 };
1650 let num_read = unsafe {
1651 prims::get_parameter_section(
1652 self.i.into(),
1653 buf.as_mut_ptr(),
1654 len,
1655 self.current_position,
1656 )
1657 };
1658 if num_read >= 0 {
1659 self.current_position += num_read as u32;
1660 Ok(num_read as usize)
1661 } else {
1662 Err(ParseError::default())
1663 }
1664 }
1665}
1666
1667impl HasCallResponse for ExternCallResponse {
1668 fn size(&self) -> u32 { unsafe { prims::get_parameter_size(self.i.get()) as u32 } }
1672}
1673
1674impl HasChainMetadata for ExternChainMeta {
1676 #[inline(always)]
1677 fn slot_time(&self) -> SlotTime {
1678 Timestamp::from_timestamp_millis(unsafe { prims::get_slot_time() })
1679 }
1680}
1681
1682impl AttributesCursor {
1683 fn next_item(&mut self, buf: &mut [u8]) -> Option<(AttributeTag, u8)> {
1684 if self.remaining_items == 0 {
1685 return None;
1686 }
1687
1688 let (tag_value_len, num_read) = unsafe {
1689 let mut tag_value_len = MaybeUninit::<[u8; 2]>::uninit();
1690 let num_read = prims::get_policy_section(
1692 tag_value_len.as_mut_ptr() as *mut u8,
1693 2,
1694 self.current_position,
1695 );
1696 (tag_value_len.assume_init(), num_read)
1697 };
1698 self.current_position += num_read;
1699 if tag_value_len[1] > 31 {
1700 return None;
1702 }
1703 let num_read = unsafe {
1704 prims::get_policy_section(
1705 buf.as_mut_ptr(),
1706 u32::from(tag_value_len[1]),
1707 self.current_position,
1708 )
1709 };
1710 self.current_position += num_read;
1711 self.remaining_items -= 1;
1712 Some((AttributeTag(tag_value_len[0]), tag_value_len[1]))
1713 }
1714}
1715
1716impl HasPolicy for Policy<AttributesCursor> {
1717 type Iterator = PolicyAttributesIter;
1718
1719 fn identity_provider(&self) -> IdentityProvider { self.identity_provider }
1720
1721 fn created_at(&self) -> Timestamp { self.created_at }
1722
1723 fn valid_to(&self) -> Timestamp { self.valid_to }
1724
1725 #[inline(always)]
1726 fn next_item(&mut self, buf: &mut [u8; 31]) -> Option<(AttributeTag, u8)> {
1727 self.items.next_item(buf)
1728 }
1729
1730 fn attributes(&self) -> Self::Iterator {
1731 PolicyAttributesIter {
1732 cursor: AttributesCursor {
1733 current_position: 0,
1734 remaining_items: self.items.total_items,
1735 total_items: self.items.total_items,
1736 },
1737 }
1738 }
1739}
1740
1741impl Iterator for PolicyAttributesIter {
1742 type Item = (AttributeTag, AttributeValue);
1743
1744 fn next(&mut self) -> Option<Self::Item> {
1745 let mut inner = [0u8; 32];
1746 let (tag, len) = self.cursor.next_item(&mut inner[1..])?;
1747 inner[0] = len;
1748 Some((tag, unsafe { AttributeValue::new_unchecked(inner) }))
1749 }
1750}
1751
1752impl ExactSizeIterator for PolicyAttributesIter {
1753 fn len(&self) -> usize { self.cursor.remaining_items as usize }
1754}
1755
1756pub struct PoliciesIterator {
1760 pos: u32,
1762 remaining_items: u16,
1764}
1765
1766impl Iterator for PoliciesIterator {
1767 type Item = Policy<AttributesCursor>;
1768
1769 fn next(&mut self) -> Option<Self::Item> {
1770 if self.remaining_items == 0 {
1771 return None;
1772 }
1773 let mut buf: MaybeUninit<[u8; 2 + 4 + 8 + 8 + 2]> = MaybeUninit::uninit();
1777 let buf = unsafe {
1778 prims::get_policy_section(buf.as_mut_ptr() as *mut u8, 2 + 4 + 8 + 8 + 2, self.pos);
1779 buf.assume_init()
1780 };
1781 let skip_part: [u8; 2] = buf[0..2].try_into().unwrap_abort();
1782 let ip_part: [u8; 4] = buf[2..2 + 4].try_into().unwrap_abort();
1783 let created_at_part: [u8; 8] = buf[2 + 4..2 + 4 + 8].try_into().unwrap_abort();
1784 let valid_to_part: [u8; 8] = buf[2 + 4 + 8..2 + 4 + 8 + 8].try_into().unwrap_abort();
1785 let len_part: [u8; 2] = buf[2 + 4 + 8 + 8..2 + 4 + 8 + 8 + 2].try_into().unwrap_abort();
1786 let identity_provider = IdentityProvider::from_le_bytes(ip_part);
1787 let created_at = Timestamp::from_timestamp_millis(u64::from_le_bytes(created_at_part));
1788 let valid_to = Timestamp::from_timestamp_millis(u64::from_le_bytes(valid_to_part));
1789 let remaining_items = u16::from_le_bytes(len_part);
1790 let attributes_start = self.pos + 2 + 4 + 8 + 8 + 2;
1791 self.pos += u32::from(u16::from_le_bytes(skip_part)) + 2;
1792 self.remaining_items -= 1;
1793 Some(Policy {
1794 identity_provider,
1795 created_at,
1796 valid_to,
1797 items: AttributesCursor {
1798 current_position: attributes_start,
1799 remaining_items,
1800 total_items: remaining_items,
1801 },
1802 })
1803 }
1804
1805 fn size_hint(&self) -> (usize, Option<usize>) {
1806 let rem = self.remaining_items as usize;
1807 (rem, Some(rem))
1808 }
1809}
1810
1811impl ExactSizeIterator for PoliciesIterator {
1812 #[inline(always)]
1813 fn len(&self) -> usize { self.remaining_items as usize }
1814}
1815
1816impl<T: sealed::ContextType> HasCommonData for ExternContext<T> {
1817 type MetadataType = ExternChainMeta;
1818 type ParamType = ExternParameter;
1819 type PolicyIteratorType = PoliciesIterator;
1820 type PolicyType = Policy<AttributesCursor>;
1821
1822 #[inline(always)]
1823 fn metadata(&self) -> &Self::MetadataType { &ExternChainMeta {} }
1824
1825 fn policies(&self) -> PoliciesIterator {
1826 let mut buf: MaybeUninit<[u8; 2]> = MaybeUninit::uninit();
1827 let buf = unsafe {
1828 prims::get_policy_section(buf.as_mut_ptr() as *mut u8, 2, 0);
1829 buf.assume_init()
1830 };
1831 PoliciesIterator {
1832 pos: 2, remaining_items: u16::from_le_bytes(buf),
1834 }
1835 }
1836
1837 #[inline(always)]
1838 fn parameter_cursor(&self) -> Self::ParamType { ExternParameter::default() }
1839}
1840
1841const INVOKE_TRANSFER_TAG: u32 = 0;
1843const INVOKE_CALL_TAG: u32 = 1;
1845const INVOKE_QUERY_ACCOUNT_BALANCE_TAG: u32 = 2;
1848const INVOKE_QUERY_CONTRACT_BALANCE_TAG: u32 = 3;
1851const INVOKE_QUERY_EXCHANGE_RATES_TAG: u32 = 4;
1854const INVOKE_CHECK_ACCOUNT_SIGNATURE_TAG: u32 = 5;
1856const INVOKE_QUERY_ACCOUNT_PUBLIC_KEYS_TAG: u32 = 6;
1858#[cfg(feature = "p7")]
1860const INVOKE_QUERY_CONTRACT_MODULE_REFERENCE_TAG: u32 = 7;
1861#[cfg(feature = "p7")]
1863const INVOKE_QUERY_CONTRACT_NAME_TAG: u32 = 8;
1864
1865#[inline(always)]
1869fn get_invoke_failure_code(code: u64) -> Option<u8> {
1870 if code & 0xff_ffff_ffff == 0 {
1871 None
1872 } else {
1873 let error_code = (code & 0xff_0000_0000) >> 32;
1874 Some(error_code as u8)
1875 }
1876}
1877
1878fn parse_transfer_response_code(code: u64) -> TransferResult {
1889 if let Some(error_code) = get_invoke_failure_code(code) {
1890 match error_code {
1891 0x01 => Err(TransferError::AmountTooLarge),
1892 0x02 => Err(TransferError::MissingAccount),
1893 _ => crate::trap(), }
1895 } else {
1896 Ok(())
1897 }
1898}
1899
1900#[inline(always)]
1912fn parse_upgrade_response_code(code: u64) -> UpgradeResult {
1913 if let Some(error_code) = get_invoke_failure_code(code) {
1914 match error_code {
1915 0x07 => Err(UpgradeError::MissingModule),
1916 0x08 => Err(UpgradeError::MissingContract),
1917 0x09 => Err(UpgradeError::UnsupportedModuleVersion),
1918 _ => crate::trap(), }
1920 } else {
1921 Ok(())
1922 }
1923}
1924
1925fn parse_call_response_code(code: u64) -> CallContractResult<ExternCallResponse> {
1943 if let Some(error_code) = get_invoke_failure_code(code) {
1944 match error_code {
1945 0x00 =>
1946 {
1948 let reason = (0x0000_0000_ffff_ffff & code) as u32 as i32;
1949 if reason == 0 {
1950 crate::trap()
1951 } else {
1952 let rv = (code >> 40) as u32;
1953 if rv > 0 {
1954 Err(CallContractError::LogicReject {
1955 reason,
1956 return_value: ExternCallResponse::new(unsafe {
1957 NonZeroU32::new_unchecked(rv)
1958 }),
1959 })
1960 } else {
1961 unsafe { crate::hint::unreachable_unchecked() } }
1963 }
1964 }
1965 0x01 => Err(CallContractError::AmountTooLarge),
1966 0x02 => Err(CallContractError::MissingAccount),
1967 0x03 => Err(CallContractError::MissingContract),
1968 0x04 => Err(CallContractError::MissingEntrypoint),
1969 0x05 => Err(CallContractError::MessageFailed),
1970 0x06 => Err(CallContractError::Trap),
1971 _ => unsafe { crate::hint::unreachable_unchecked() }, }
1973 } else {
1974 let rv = (code >> 40) as u32;
1976
1977 let tag = 0x80_0000u32; if tag & rv != 0 {
1979 Ok((true, NonZeroU32::new(rv & !tag).map(ExternCallResponse::new)))
1981 } else {
1982 Ok((false, NonZeroU32::new(rv).map(ExternCallResponse::new)))
1983 }
1984 }
1985}
1986
1987fn parse_query_account_balance_response_code(
1995 code: u64,
1996) -> Result<ExternCallResponse, QueryAccountBalanceError> {
1997 if let Some(error_code) = get_invoke_failure_code(code) {
1998 if error_code == 0x02 {
1999 Err(QueryAccountBalanceError)
2000 } else {
2001 unsafe { crate::hint::unreachable_unchecked() }
2002 }
2003 } else {
2004 let return_value_index = NonZeroU32::new((code >> 40) as u32).unwrap_abort();
2006 Ok(ExternCallResponse::new(return_value_index))
2007 }
2008}
2009
2010fn parse_query_contract_balance_response_code(
2018 code: u64,
2019) -> Result<ExternCallResponse, QueryContractBalanceError> {
2020 if let Some(error_code) = get_invoke_failure_code(code) {
2021 if error_code == 0x03 {
2022 Err(QueryContractBalanceError)
2023 } else {
2024 unsafe { crate::hint::unreachable_unchecked() }
2025 }
2026 } else {
2027 let return_value_index = NonZeroU32::new((code >> 40) as u32).unwrap_abort();
2029 Ok(ExternCallResponse::new(return_value_index))
2030 }
2031}
2032
2033fn parse_query_account_public_keys_response_code(
2041 code: u64,
2042) -> Result<ExternCallResponse, QueryAccountPublicKeysError> {
2043 if let Some(error_code) = get_invoke_failure_code(code) {
2044 if error_code == 0x02 {
2045 Err(QueryAccountPublicKeysError)
2046 } else {
2047 unsafe { crate::hint::unreachable_unchecked() }
2048 }
2049 } else {
2050 let return_value_index = NonZeroU32::new((code >> 40) as u32).unwrap_abort();
2052 Ok(ExternCallResponse::new(return_value_index))
2053 }
2054}
2055
2056fn parse_check_account_signature_response_code(
2066 code: u64,
2067) -> Result<bool, CheckAccountSignatureError> {
2068 if let Some(error_code) = get_invoke_failure_code(code) {
2069 if error_code == 0x02 {
2070 Err(CheckAccountSignatureError::MissingAccount)
2071 } else if error_code == 0x0a {
2072 Err(CheckAccountSignatureError::MalformedData)
2073 } else if error_code == 0x0b {
2074 Ok(false)
2075 } else {
2076 unsafe { crate::hint::unreachable_unchecked() }
2077 }
2078 } else {
2079 Ok(true)
2080 }
2081}
2082
2083fn parse_query_exchange_rates_response_code(code: u64) -> ExternCallResponse {
2090 if get_invoke_failure_code(code).is_some() {
2091 unsafe { crate::hint::unreachable_unchecked() }
2093 } else {
2094 let return_value_index = NonZeroU32::new((code >> 40) as u32).unwrap_abort();
2096 ExternCallResponse::new(return_value_index)
2097 }
2098}
2099
2100#[cfg(feature = "p7")]
2108fn parse_query_contract_module_reference_response_code(
2109 code: u64,
2110) -> Result<ExternCallResponse, QueryContractModuleReferenceError> {
2111 if let Some(error_code) = get_invoke_failure_code(code) {
2112 if error_code == 0x03 {
2113 Err(QueryContractModuleReferenceError)
2114 } else {
2115 unsafe { crate::hint::unreachable_unchecked() }
2116 }
2117 } else {
2118 let return_value_index = NonZeroU32::new((code >> 40) as u32).unwrap_abort();
2120 Ok(ExternCallResponse::new(return_value_index))
2121 }
2122}
2123
2124#[cfg(feature = "p7")]
2132fn parse_query_contract_name_response_code(
2133 code: u64,
2134) -> Result<OwnedContractName, QueryContractNameError> {
2135 if let Some(error_code) = get_invoke_failure_code(code) {
2136 if error_code == 0x03 {
2137 Err(QueryContractNameError)
2138 } else {
2139 unsafe { crate::hint::unreachable_unchecked() }
2140 }
2141 } else {
2142 let return_value_index = (code >> 40) as u32;
2144 let name = unsafe {
2145 let name_size = prims::get_parameter_size(return_value_index);
2146 if name_size < 0 {
2147 crate::hint::unreachable_unchecked()
2148 }
2149 let mut buf = vec![0; name_size as usize];
2150 prims::get_parameter_section(return_value_index, buf.as_mut_ptr(), name_size as u32, 0);
2151 String::from_utf8_unchecked(buf)
2152 };
2153 Ok(OwnedContractName::new_unchecked(name))
2154 }
2155}
2156
2157fn invoke_transfer_worker(receiver: &AccountAddress, amount: Amount) -> TransferResult {
2160 let mut bytes: MaybeUninit<[u8; ACCOUNT_ADDRESS_SIZE + 8]> = MaybeUninit::uninit();
2161 let data = unsafe {
2162 (bytes.as_mut_ptr() as *mut u8).copy_from_nonoverlapping(
2163 receiver.as_ref() as *const [u8; ACCOUNT_ADDRESS_SIZE] as *const u8,
2164 ACCOUNT_ADDRESS_SIZE,
2165 );
2166 (bytes.as_mut_ptr() as *mut u8).add(ACCOUNT_ADDRESS_SIZE).copy_from_nonoverlapping(
2167 &amount.micro_ccd.to_le_bytes() as *const [u8; 8] as *const u8,
2168 8,
2169 );
2170 bytes.assume_init()
2171 };
2172 let response = unsafe {
2173 prims::invoke(INVOKE_TRANSFER_TAG, data.as_ptr(), (ACCOUNT_ADDRESS_SIZE + 8) as u32)
2174 };
2175 parse_transfer_response_code(response)
2176}
2177
2178fn invoke_contract_construct_parameter(
2180 to: &ContractAddress,
2181 parameter: Parameter,
2182 method: EntrypointName,
2183 amount: Amount,
2184) -> Vec<u8> {
2185 let mut data =
2186 Vec::with_capacity(16 + parameter.as_ref().len() + 2 + method.size() as usize + 2 + 8);
2187 let mut cursor = Cursor::new(&mut data);
2188 to.serial(&mut cursor).unwrap_abort();
2189 parameter.serial(&mut cursor).unwrap_abort();
2190 method.serial(&mut cursor).unwrap_abort();
2191 amount.serial(&mut cursor).unwrap_abort();
2192 data
2193}
2194
2195fn query_account_balance_worker(address: &AccountAddress) -> QueryAccountBalanceResult {
2198 let response = unsafe {
2199 prims::invoke(
2200 INVOKE_QUERY_ACCOUNT_BALANCE_TAG,
2201 AsRef::<[u8]>::as_ref(&address).as_ptr(),
2202 32,
2203 )
2204 };
2205 let mut return_value = parse_query_account_balance_response_code(response)?;
2206 Ok(AccountBalance::deserial(&mut return_value).unwrap_abort())
2207}
2208
2209fn query_contract_balance_worker(address: &ContractAddress) -> QueryContractBalanceResult {
2212 let data = [address.index.to_le_bytes(), address.subindex.to_le_bytes()];
2213 let response =
2214 unsafe { prims::invoke(INVOKE_QUERY_CONTRACT_BALANCE_TAG, data.as_ptr() as *const u8, 16) };
2215 let mut return_value = parse_query_contract_balance_response_code(response)?;
2216 Ok(Amount::deserial(&mut return_value).unwrap_abort())
2217}
2218
2219fn query_exchange_rates_worker() -> ExchangeRates {
2222 let response_code = unsafe { prims::invoke(INVOKE_QUERY_EXCHANGE_RATES_TAG, [].as_ptr(), 0) };
2223
2224 let mut response = parse_query_exchange_rates_response_code(response_code);
2225 ExchangeRates::deserial(&mut response).unwrap_abort()
2226}
2227
2228fn query_account_public_keys_worker(address: AccountAddress) -> QueryAccountPublicKeysResult {
2231 let data: &[u8] = address.as_ref();
2232 let response =
2233 unsafe { prims::invoke(INVOKE_QUERY_ACCOUNT_PUBLIC_KEYS_TAG, data.as_ptr(), 32) };
2234 let mut return_value = parse_query_account_public_keys_response_code(response)?;
2235 Ok(crate::AccountPublicKeys::deserial(&mut return_value).unwrap_abort())
2236}
2237
2238fn check_account_signature_worker(
2239 address: AccountAddress,
2240 signatures: &AccountSignatures,
2241 data: &[u8],
2242) -> CheckAccountSignatureResult {
2243 let mut buffer = address.0.to_vec();
2244 (data.len() as u32).serial(&mut buffer).unwrap_abort();
2245 buffer.extend_from_slice(data);
2246 signatures.serial(&mut buffer).unwrap_abort();
2247
2248 let response = unsafe {
2249 prims::invoke(INVOKE_CHECK_ACCOUNT_SIGNATURE_TAG, buffer.as_ptr(), buffer.len() as u32)
2250 };
2251 drop(buffer);
2253 parse_check_account_signature_response_code(response)
2254}
2255
2256#[cfg(feature = "p7")]
2259fn query_contract_module_reference_worker(
2260 address: &ContractAddress,
2261) -> QueryContractModuleReferenceResult {
2262 let data = [address.index.to_le_bytes(), address.subindex.to_le_bytes()];
2263 let response = unsafe {
2264 prims::invoke(INVOKE_QUERY_CONTRACT_MODULE_REFERENCE_TAG, data.as_ptr() as *const u8, 16)
2265 };
2266 let mut return_value = parse_query_contract_module_reference_response_code(response)?;
2267 Ok(ModuleReference::deserial(&mut return_value).unwrap_abort())
2268}
2269
2270#[cfg(feature = "p7")]
2273fn query_contract_name_worker(address: &ContractAddress) -> QueryContractNameResult {
2274 let data = [address.index.to_le_bytes(), address.subindex.to_le_bytes()];
2275 let response =
2276 unsafe { prims::invoke(INVOKE_QUERY_CONTRACT_NAME_TAG, data.as_ptr() as *const u8, 16) };
2277 parse_query_contract_name_response_code(response)
2278}
2279
2280impl<S> StateBuilder<S>
2281where
2282 S: HasStateApi,
2283{
2284 pub fn open(state: S) -> Self {
2288 Self {
2289 state_api: state,
2290 }
2291 }
2292
2293 #[must_use]
2320 pub fn new_state_container(&mut self) -> (S, [u8; 8]) {
2321 (self.state_api.clone(), self.get_and_update_item_prefix())
2322 }
2323
2324 pub fn new_map<K, V>(&mut self) -> StateMap<K, V, S> {
2326 let (state_api, prefix) = self.new_state_container();
2327 StateMap::open(state_api, prefix)
2328 }
2329
2330 pub fn new_set<T>(&mut self) -> StateSet<T, S> {
2332 let (state_api, prefix) = self.new_state_container();
2333 StateSet::open(state_api, prefix)
2334 }
2335
2336 #[must_use]
2373 pub fn new_box<T: Serial>(&mut self, value: T) -> StateBox<T, S> {
2374 let (state_api, prefix) = self.new_state_container();
2375
2376 let mut state_entry = self.state_api.create_entry(&prefix).unwrap_abort();
2378 value.serial(&mut state_entry).unwrap_abort();
2379 StateBox::new(value, state_api, state_entry)
2380 }
2381
2382 fn get_and_update_item_prefix(&mut self) -> [u8; 8] {
2383 let mut next_collection_prefix_entry = self
2387 .state_api
2388 .entry(NEXT_ITEM_PREFIX_KEY)
2389 .or_insert_raw(&INITIAL_NEXT_ITEM_PREFIX)
2390 .unwrap_abort();
2391
2392 let collection_prefix = next_collection_prefix_entry.read_u64().unwrap_abort(); next_collection_prefix_entry.move_to_start();
2397
2398 next_collection_prefix_entry.write_u64(collection_prefix + 1).unwrap_abort(); collection_prefix.to_le_bytes()
2402 }
2403}
2404
2405impl StateBuilder<StateApi> {
2406 pub fn new_btree_set<K>(&mut self) -> state_btree::StateBTreeSet<K> {
2408 let (state_api, prefix) = self.new_state_container();
2409 state_btree::StateBTreeSet::new(state_api, prefix)
2410 }
2411
2412 pub fn new_btree_map<K, V>(&mut self) -> state_btree::StateBTreeMap<K, V> {
2414 state_btree::StateBTreeMap {
2415 key_value: self.new_map(),
2416 key_order: self.new_btree_set(),
2417 }
2418 }
2419
2420 pub fn new_btree_set_degree<const M: usize, K>(&mut self) -> state_btree::StateBTreeSet<K, M> {
2424 if M >= 2 {
2425 let (state_api, prefix) = self.new_state_container();
2426 state_btree::StateBTreeSet::new(state_api, prefix)
2427 } else {
2428 crate::fail!(
2429 "Invalid minimum degree used for StateBTreeSet, must be >=2 instead got {}",
2430 M
2431 )
2432 }
2433 }
2434
2435 pub fn new_btree_map_degree<const M: usize, K, V>(
2439 &mut self,
2440 ) -> state_btree::StateBTreeMap<K, V, M> {
2441 if M >= 2 {
2442 state_btree::StateBTreeMap {
2443 key_value: self.new_map(),
2444 key_order: self.new_btree_set_degree(),
2445 }
2446 } else {
2447 crate::fail!(
2448 "Invalid minimum degree used for StateBTreeMap, must be >=2 instead got {}",
2449 M
2450 )
2451 }
2452 }
2453}
2454
2455impl<S> HasHost<S> for ExternHost<S>
2456where
2457 S: Serial + DeserialWithState<ExternStateApi>,
2458{
2459 type ReturnValueType = ExternCallResponse;
2460 type StateApiType = ExternStateApi;
2461
2462 fn invoke_transfer(&self, receiver: &AccountAddress, amount: Amount) -> TransferResult {
2463 invoke_transfer_worker(receiver, amount)
2464 }
2465
2466 fn invoke_contract_raw(
2467 &mut self,
2468 to: &ContractAddress,
2469 parameter: Parameter,
2470 method: EntrypointName,
2471 amount: Amount,
2472 ) -> CallContractResult<Self::ReturnValueType> {
2473 let data = invoke_contract_construct_parameter(to, parameter, method, amount);
2474 let len = data.len();
2475 self.commit_state();
2479 let response = unsafe { prims::invoke(INVOKE_CALL_TAG, data.as_ptr(), len as u32) };
2480 let (state_modified, res) = parse_call_response_code(response)?;
2481 if state_modified {
2482 if let Ok(new_state) = S::deserial_with_state(
2485 &self.state_builder.state_api,
2486 &mut self.state_builder.state_api.lookup_entry(&[]).unwrap_abort(),
2487 ) {
2488 self.state = new_state;
2489 } else {
2490 crate::trap()
2491 }
2492 }
2493 Ok((state_modified, res))
2494 }
2495
2496 fn invoke_contract_raw_read_only(
2497 &self,
2498 to: &ContractAddress,
2499 parameter: Parameter,
2500 method: EntrypointName,
2501 amount: Amount,
2502 ) -> ReadOnlyCallContractResult<Self::ReturnValueType> {
2503 let data = invoke_contract_construct_parameter(to, parameter, method, amount);
2504 let len = data.len();
2505 let response = unsafe { prims::invoke(INVOKE_CALL_TAG, data.as_ptr(), len as u32) };
2506 let (state_modified, res) = parse_call_response_code(response)?;
2507 if state_modified {
2508 crate::trap()
2509 } else {
2510 Ok(res)
2511 }
2512 }
2513
2514 #[inline(always)]
2515 fn account_balance(&self, address: AccountAddress) -> QueryAccountBalanceResult {
2516 query_account_balance_worker(&address)
2517 }
2518
2519 #[inline(always)]
2520 fn contract_balance(&self, address: ContractAddress) -> QueryContractBalanceResult {
2521 query_contract_balance_worker(&address)
2522 }
2523
2524 #[inline(always)]
2525 fn exchange_rates(&self) -> ExchangeRates { query_exchange_rates_worker() }
2526
2527 fn upgrade(&mut self, module: ModuleReference) -> UpgradeResult {
2528 let response = unsafe { prims::upgrade(module.as_ref().as_ptr()) };
2529 parse_upgrade_response_code(response)
2530 }
2531
2532 fn account_public_keys(&self, address: AccountAddress) -> QueryAccountPublicKeysResult {
2533 query_account_public_keys_worker(address)
2534 }
2535
2536 fn check_account_signature(
2537 &self,
2538 address: AccountAddress,
2539 signatures: &AccountSignatures,
2540 data: &[u8],
2541 ) -> CheckAccountSignatureResult {
2542 check_account_signature_worker(address, signatures, data)
2543 }
2544
2545 #[cfg(feature = "p7")]
2546 #[inline(always)]
2547 fn contract_module_reference(
2548 &self,
2549 address: ContractAddress,
2550 ) -> QueryContractModuleReferenceResult {
2551 query_contract_module_reference_worker(&address)
2552 }
2553
2554 #[cfg(feature = "p7")]
2555 #[inline(always)]
2556 fn contract_name(&self, address: ContractAddress) -> QueryContractNameResult {
2557 query_contract_name_worker(&address)
2558 }
2559
2560 fn state(&self) -> &S { &self.state }
2561
2562 fn state_mut(&mut self) -> &mut S { &mut self.state }
2563
2564 fn commit_state(&mut self) {
2565 let mut root_entry = self.state_builder.state_api.lookup_entry(&[]).unwrap_abort();
2566 self.state.serial(&mut root_entry).unwrap_abort();
2567 let new_state_size = root_entry.size().unwrap_abort();
2568 root_entry.truncate(new_state_size).unwrap_abort();
2569 }
2570
2571 #[inline(always)]
2572 fn self_balance(&self) -> Amount {
2573 Amount::from_micro_ccd(unsafe { prims::get_receive_self_balance() })
2574 }
2575
2576 #[inline(always)]
2577 fn state_builder(&mut self) -> &mut StateBuilder<Self::StateApiType> { &mut self.state_builder }
2578
2579 #[inline(always)]
2580 fn state_and_builder(&mut self) -> (&mut S, &mut StateBuilder<Self::StateApiType>) {
2581 (&mut self.state, &mut self.state_builder)
2582 }
2583}
2584impl HasHost<ExternStateApi> for ExternLowLevelHost {
2585 type ReturnValueType = ExternCallResponse;
2586 type StateApiType = ExternStateApi;
2587
2588 #[inline(always)]
2589 fn invoke_transfer(&self, receiver: &AccountAddress, amount: Amount) -> TransferResult {
2590 invoke_transfer_worker(receiver, amount)
2591 }
2592
2593 fn invoke_contract_raw(
2594 &mut self,
2595 to: &ContractAddress,
2596 parameter: Parameter,
2597 method: EntrypointName,
2598 amount: Amount,
2599 ) -> CallContractResult<Self::ReturnValueType> {
2600 let data = invoke_contract_construct_parameter(to, parameter, method, amount);
2601 let len = data.len();
2602 let response = unsafe { prims::invoke(INVOKE_CALL_TAG, data.as_ptr(), len as u32) };
2603 parse_call_response_code(response)
2604 }
2605
2606 #[inline(always)]
2607 fn account_balance(&self, address: AccountAddress) -> QueryAccountBalanceResult {
2608 query_account_balance_worker(&address)
2609 }
2610
2611 #[inline(always)]
2612 fn contract_balance(&self, address: ContractAddress) -> QueryContractBalanceResult {
2613 query_contract_balance_worker(&address)
2614 }
2615
2616 #[inline(always)]
2617 fn exchange_rates(&self) -> ExchangeRates { query_exchange_rates_worker() }
2618
2619 fn upgrade(&mut self, module: ModuleReference) -> UpgradeResult {
2620 let response = unsafe { prims::upgrade(module.as_ref().as_ptr()) };
2621 parse_upgrade_response_code(response)
2622 }
2623
2624 fn account_public_keys(&self, address: AccountAddress) -> QueryAccountPublicKeysResult {
2625 query_account_public_keys_worker(address)
2626 }
2627
2628 fn check_account_signature(
2629 &self,
2630 address: AccountAddress,
2631 signatures: &AccountSignatures,
2632 data: &[u8],
2633 ) -> CheckAccountSignatureResult {
2634 check_account_signature_worker(address, signatures, data)
2635 }
2636
2637 #[cfg(feature = "p7")]
2638 #[inline(always)]
2639 fn contract_module_reference(
2640 &self,
2641 address: ContractAddress,
2642 ) -> QueryContractModuleReferenceResult {
2643 query_contract_module_reference_worker(&address)
2644 }
2645
2646 #[cfg(feature = "p7")]
2647 #[inline(always)]
2648 fn contract_name(&self, address: ContractAddress) -> QueryContractNameResult {
2649 query_contract_name_worker(&address)
2650 }
2651
2652 #[inline(always)]
2653 fn state(&self) -> &ExternStateApi { &self.state_api }
2654
2655 #[inline(always)]
2656 fn state_mut(&mut self) -> &mut ExternStateApi { &mut self.state_api }
2657
2658 #[inline(always)]
2659 fn commit_state(&mut self) {
2660 }
2662
2663 #[inline(always)]
2664 fn self_balance(&self) -> Amount {
2665 Amount::from_micro_ccd(unsafe { prims::get_receive_self_balance() })
2666 }
2667
2668 #[inline(always)]
2669 fn state_builder(&mut self) -> &mut StateBuilder<Self::StateApiType> { &mut self.state_builder }
2670
2671 #[inline(always)]
2672 fn state_and_builder(
2673 &mut self,
2674 ) -> (&mut ExternStateApi, &mut StateBuilder<Self::StateApiType>) {
2675 (&mut self.state_api, &mut self.state_builder)
2676 }
2677
2678 fn invoke_contract_raw_read_only(
2679 &self,
2680 to: &ContractAddress,
2681 parameter: Parameter<'_>,
2682 method: EntrypointName<'_>,
2683 amount: Amount,
2684 ) -> ReadOnlyCallContractResult<Self::ReturnValueType> {
2685 let data = invoke_contract_construct_parameter(to, parameter, method, amount);
2686 let len = data.len();
2687 let response = unsafe { prims::invoke(INVOKE_CALL_TAG, data.as_ptr(), len as u32) };
2688 let (state_modified, res) = parse_call_response_code(response)?;
2689 if state_modified {
2690 crate::trap()
2691 } else {
2692 Ok(res)
2693 }
2694 }
2695}
2696
2697impl HasCryptoPrimitives for ExternCryptoPrimitives {
2698 fn verify_ed25519_signature(
2699 &self,
2700 public_key: PublicKeyEd25519,
2701 signature: SignatureEd25519,
2702 message: &[u8],
2703 ) -> bool {
2704 let res = unsafe {
2705 prims::verify_ed25519_signature(
2706 public_key.0.as_ptr(),
2707 signature.0.as_ptr(),
2708 message.as_ptr(),
2709 message.len() as u32,
2710 )
2711 };
2712 res == 1
2713 }
2714
2715 fn verify_ecdsa_secp256k1_signature(
2716 &self,
2717 public_key: PublicKeyEcdsaSecp256k1,
2718 signature: SignatureEcdsaSecp256k1,
2719 message_hash: [u8; 32],
2720 ) -> bool {
2721 let res = unsafe {
2722 prims::verify_ecdsa_secp256k1_signature(
2723 public_key.0.as_ptr(),
2724 signature.0.as_ptr(),
2725 message_hash.as_ptr(),
2726 )
2727 };
2728 res == 1
2729 }
2730
2731 fn hash_sha2_256(&self, data: &[u8]) -> HashSha2256 {
2732 let mut output: MaybeUninit<[u8; 32]> = MaybeUninit::uninit();
2733 unsafe {
2734 prims::hash_sha2_256(data.as_ptr(), data.len() as u32, output.as_mut_ptr() as *mut u8);
2735 HashSha2256(output.assume_init())
2736 }
2737 }
2738
2739 fn hash_sha3_256(&self, data: &[u8]) -> HashSha3256 {
2740 let mut output: MaybeUninit<[u8; 32]> = MaybeUninit::uninit();
2741 unsafe {
2742 prims::hash_sha3_256(data.as_ptr(), data.len() as u32, output.as_mut_ptr() as *mut u8);
2743 HashSha3256(output.assume_init())
2744 }
2745 }
2746
2747 fn hash_keccak_256(&self, data: &[u8]) -> HashKeccak256 {
2748 let mut output: MaybeUninit<[u8; 32]> = MaybeUninit::uninit();
2749 unsafe {
2750 prims::hash_keccak_256(
2751 data.as_ptr(),
2752 data.len() as u32,
2753 output.as_mut_ptr() as *mut u8,
2754 );
2755 HashKeccak256(output.assume_init())
2756 }
2757 }
2758}
2759
2760impl HasInitContext for ExternContext<crate::types::ExternInitContext> {
2762 type InitData = ();
2763
2764 fn open(_: Self::InitData) -> Self { ExternContext::default() }
2766
2767 #[inline(always)]
2768 fn init_origin(&self) -> AccountAddress {
2769 let mut bytes: MaybeUninit<[u8; ACCOUNT_ADDRESS_SIZE]> = MaybeUninit::uninit();
2770 let ptr = bytes.as_mut_ptr();
2771 let address = unsafe {
2772 prims::get_init_origin(ptr as *mut u8);
2773 bytes.assume_init()
2774 };
2775 AccountAddress(address)
2776 }
2777}
2778
2779impl HasReceiveContext for ExternContext<crate::types::ExternReceiveContext> {
2781 type ReceiveData = ();
2782
2783 fn open(_: Self::ReceiveData) -> Self { ExternContext::default() }
2785
2786 #[inline(always)]
2787 fn invoker(&self) -> AccountAddress {
2788 let mut bytes: MaybeUninit<[u8; ACCOUNT_ADDRESS_SIZE]> = MaybeUninit::uninit();
2789 let ptr = bytes.as_mut_ptr();
2790 let address = unsafe {
2791 prims::get_receive_invoker(ptr as *mut u8);
2792 bytes.assume_init()
2793 };
2794 AccountAddress(address)
2795 }
2796
2797 #[inline(always)]
2798 fn self_address(&self) -> ContractAddress {
2799 let mut bytes: MaybeUninit<[u8; 16]> = MaybeUninit::uninit();
2800 let ptr = bytes.as_mut_ptr();
2801 let address = unsafe {
2802 prims::get_receive_self_address(ptr as *mut u8);
2803 bytes.assume_init()
2804 };
2805 match from_bytes(&address) {
2806 Ok(v) => v,
2807 Err(_) => crate::trap(),
2808 }
2809 }
2810
2811 #[inline(always)]
2812 fn sender(&self) -> Address {
2813 let mut bytes: MaybeUninit<[u8; 33]> = MaybeUninit::uninit();
2814 let ptr = bytes.as_mut_ptr() as *mut u8;
2815 unsafe {
2816 prims::get_receive_sender(ptr);
2817 let tag = *ptr;
2818 match tag {
2819 0u8 => {
2820 match from_bytes(core::slice::from_raw_parts(ptr.add(1), ACCOUNT_ADDRESS_SIZE))
2821 {
2822 Ok(v) => Address::Account(v),
2823 Err(_) => crate::trap(),
2824 }
2825 }
2826 1u8 => match from_bytes(core::slice::from_raw_parts(ptr.add(1), 16)) {
2827 Ok(v) => Address::Contract(v),
2828 Err(_) => crate::trap(),
2829 },
2830 _ => crate::trap(), }
2832 }
2833 }
2834
2835 #[inline(always)]
2836 fn owner(&self) -> AccountAddress {
2837 let mut bytes: MaybeUninit<[u8; ACCOUNT_ADDRESS_SIZE]> = MaybeUninit::uninit();
2838 let ptr = bytes.as_mut_ptr();
2839 let address = unsafe {
2840 prims::get_receive_owner(ptr as *mut u8);
2841 bytes.assume_init()
2842 };
2843 AccountAddress(address)
2844 }
2845
2846 fn named_entrypoint(&self) -> OwnedEntrypointName {
2847 let mut data = crate::vec![0u8; unsafe { prims::get_receive_entrypoint_size() as usize }];
2848 unsafe { prims::get_receive_entrypoint(data.as_mut_ptr()) };
2849 OwnedEntrypointName::new_unchecked(unsafe { String::from_utf8_unchecked(data) })
2850 }
2851}
2852
2853impl HasLogger for Logger {
2856 #[inline(always)]
2857 fn init() -> Self {
2858 Self {
2859 _private: (),
2860 }
2861 }
2862
2863 fn log_raw(&mut self, event: &[u8]) -> Result<(), LogError> {
2864 let res = unsafe { prims::log_event(event.as_ptr(), event.len() as u32) };
2865 match res {
2866 1 => Ok(()),
2867 0 => Err(LogError::Full),
2868 _ => Err(LogError::Malformed),
2869 }
2870 }
2871}
2872
2873#[doc(hidden)]
2877pub fn put_in_memory(input: &[u8]) -> *mut u8 {
2878 let bytes_length = input.len() as u32;
2879 let mut bytes = to_bytes(&bytes_length);
2880 bytes.extend_from_slice(input);
2881 let ptr = bytes.as_mut_ptr();
2882 #[cfg(feature = "std")]
2883 ::std::mem::forget(bytes);
2884 #[cfg(not(feature = "std"))]
2885 core::mem::forget(bytes);
2886 ptr
2887}
2888
2889impl<A, E> UnwrapAbort for Result<A, E> {
2890 type Unwrap = A;
2891
2892 #[inline]
2893 fn unwrap_abort(self) -> Self::Unwrap {
2894 match self {
2895 Ok(x) => x,
2896 Err(_) => crate::trap(),
2897 }
2898 }
2899}
2900
2901impl<A, E: fmt::Debug> ExpectReport for Result<A, E> {
2902 type Unwrap = A;
2903
2904 fn expect_report(self, msg: &str) -> Self::Unwrap {
2905 match self {
2906 Ok(x) => x,
2907 Err(e) => crate::fail!("{}: {:?}", msg, e),
2908 }
2909 }
2910}
2911
2912impl<A: fmt::Debug, E> ExpectErrReport for Result<A, E> {
2913 type Unwrap = E;
2914
2915 fn expect_err_report(self, msg: &str) -> Self::Unwrap {
2916 match self {
2917 Ok(a) => crate::fail!("{}: {:?}", msg, a),
2918 Err(e) => e,
2919 }
2920 }
2921}
2922
2923impl<A> UnwrapAbort for Option<A> {
2924 type Unwrap = A;
2925
2926 #[inline(always)]
2927 #[allow(clippy::redundant_closure)]
2928 fn unwrap_abort(self) -> Self::Unwrap { self.unwrap_or_else(|| crate::trap()) }
2931}
2932
2933impl<A> ExpectReport for Option<A> {
2934 type Unwrap = A;
2935
2936 fn expect_report(self, msg: &str) -> Self::Unwrap {
2937 match self {
2938 Some(v) => v,
2939 None => crate::fail!("{}", msg),
2940 }
2941 }
2942}
2943
2944impl<A: fmt::Debug> ExpectNoneReport for Option<A> {
2945 fn expect_none_report(self, msg: &str) {
2946 if let Some(x) = self {
2947 crate::fail!("{}: {:?}", msg, x)
2948 }
2949 }
2950}
2951
2952impl<D: Deserial, S: HasStateApi> DeserialWithState<S> for D {
2955 #[inline(always)]
2956 fn deserial_with_state<R: Read>(_state: &S, source: &mut R) -> ParseResult<Self> {
2957 Self::deserial(source)
2958 }
2959}
2960
2961impl<D: DeserialCtx, S: HasStateApi> DeserialCtxWithState<S> for D {
2964 #[inline(always)]
2965 fn deserial_ctx_with_state<R: Read>(
2966 size_length: schema::SizeLength,
2967 ensure_ordered: bool,
2968 _state: &S,
2969 source: &mut R,
2970 ) -> ParseResult<Self> {
2971 Self::deserial_ctx(size_length, ensure_ordered, source)
2972 }
2973}
2974
2975impl<K, V, S> DeserialWithState<S> for StateMap<K, V, S>
2976where
2977 S: HasStateApi,
2978{
2979 fn deserial_with_state<R: Read>(state: &S, source: &mut R) -> ParseResult<Self> {
2980 source.read_array().map(|map_prefix| StateMap::open(state.clone(), map_prefix))
2981 }
2982}
2983
2984impl<T, S> DeserialWithState<S> for StateSet<T, S>
2985where
2986 S: HasStateApi,
2987 T: Serial + DeserialWithState<S>,
2988{
2989 fn deserial_with_state<R: Read>(state: &S, source: &mut R) -> ParseResult<Self> {
2990 source.read_array().map(|set_prefix| StateSet::open(state.clone(), set_prefix))
2991 }
2992}
2993
2994impl<T, S> DeserialWithState<S> for StateBox<T, S>
2995where
2996 S: HasStateApi,
2997 T: Serial + DeserialWithState<S>,
2998{
2999 fn deserial_with_state<R: Read>(state: &S, source: &mut R) -> ParseResult<Self> {
3000 let prefix = source.read_array()?;
3001 Ok(StateBox {
3002 state_api: state.clone(),
3003 inner: UnsafeCell::new(StateBoxInner::Reference {
3004 prefix,
3005 }),
3006 })
3007 }
3008}
3009
3010impl<T: Serialize> Deletable for T {
3011 #[inline(always)]
3012 fn delete(self) {} }
3014
3015impl<T, S> Deletable for StateBox<T, S>
3016where
3017 T: Serial + DeserialWithState<S> + Deletable,
3018 S: HasStateApi,
3019{
3020 fn delete(mut self) {
3021 let inner = mem::replace(
3023 &mut self.inner,
3024 UnsafeCell::new(StateBoxInner::Reference {
3025 prefix: [0u8; 8],
3026 }),
3027 );
3028 let (entry, value) = match inner.into_inner() {
3029 StateBoxInner::Loaded {
3030 entry,
3031 value,
3032 ..
3033 } => (entry, value),
3034 StateBoxInner::Reference {
3035 prefix,
3036 } => {
3037 let mut entry = self.state_api.lookup_entry(&prefix).unwrap_abort();
3044 let value = T::deserial_with_state(&self.state_api, &mut entry).unwrap_abort();
3045 (entry, value)
3046 }
3047 };
3048 self.state_api.delete_entry(entry).unwrap_abort();
3049 value.delete()
3050 }
3051}
3052
3053impl<T, S> Deletable for StateSet<T, S>
3054where
3055 S: HasStateApi,
3056{
3057 fn delete(mut self) {
3058 self.state_api.delete_prefix(&self.prefix).unwrap_abort();
3063 }
3064}
3065
3066impl<K, V, S> Deletable for StateMap<K, V, S>
3067where
3068 S: HasStateApi,
3069 K: Serialize,
3070 V: Serial + DeserialWithState<S> + Deletable,
3071{
3072 fn delete(mut self) { self.clear(); }
3073}
3074
3075impl Serial for HashSha2256 {
3076 fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> { self.0.serial(out) }
3077}
3078
3079impl Deserial for HashSha2256 {
3080 fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
3081 Ok(HashSha2256(Deserial::deserial(source)?))
3082 }
3083}
3084
3085impl schema::SchemaType for HashSha2256 {
3086 fn get_type() -> concordium_contracts_common::schema::Type { schema::Type::ByteArray(32) }
3087}
3088
3089impl Serial for HashSha3256 {
3090 fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> { self.0.serial(out) }
3091}
3092
3093impl Deserial for HashSha3256 {
3094 fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
3095 Ok(HashSha3256(Deserial::deserial(source)?))
3096 }
3097}
3098
3099impl schema::SchemaType for HashSha3256 {
3100 fn get_type() -> concordium_contracts_common::schema::Type { schema::Type::ByteArray(32) }
3101}
3102
3103impl Serial for HashKeccak256 {
3104 fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> { self.0.serial(out) }
3105}
3106
3107impl Deserial for HashKeccak256 {
3108 fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
3109 Ok(HashKeccak256(Deserial::deserial(source)?))
3110 }
3111}
3112
3113impl schema::SchemaType for HashKeccak256 {
3114 fn get_type() -> concordium_contracts_common::schema::Type { schema::Type::ByteArray(32) }
3115}
3116
3117impl schema::SchemaType for MetadataUrl {
3118 fn get_type() -> schema::Type {
3119 schema::Type::Struct(schema::Fields::Named(crate::vec![
3120 (String::from("url"), schema::Type::String(schema::SizeLength::U16)),
3121 (String::from("hash"), Option::<HashSha2256>::get_type()),
3123 ]))
3124 }
3125}
3126
3127impl Serial for MetadataUrl {
3128 fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
3129 let bytes = self.url.as_bytes();
3131 let len = bytes.len() as u16;
3132 len.serial(out)?;
3133 serial_vector_no_length(bytes, out)?;
3134 self.hash.serial(out)
3135 }
3136}
3137
3138impl Deserial for MetadataUrl {
3139 fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
3140 let len: u16 = source.get()?;
3142 let bytes = deserial_vector_no_length(source, len as usize)?;
3143 Ok(MetadataUrl {
3144 url: String::from_utf8(bytes).map_err(|_| ParseError::default())?,
3145 hash: Deserial::deserial(source)?,
3146 })
3147 }
3148}
3149
3150#[cfg(test)]
3151mod tests {
3152
3153 #[test]
3156 fn statemap_multiple_entries_not_allowed() {
3157 let t = trybuild::TestCases::new();
3158 t.compile_fail("tests/state/map-multiple-entries.rs");
3159 }
3160
3161 #[test]
3162 fn statemap_multiple_state_ref_mut_not_allowed() {
3163 let t = trybuild::TestCases::new();
3164 t.compile_fail("tests/state/map-multiple-state-ref-mut.rs");
3165 }
3166}
3167
3168#[cfg(feature = "internal-wasm-test")]
3171mod wasm_test {
3172 use crate::{
3173 claim, claim_eq, concordium_test, to_bytes, Deletable, Deserial, DeserialWithState,
3174 EntryRaw, HasStateApi, HasStateEntry, ParseResult, Serial, StateApi, StateBuilder,
3175 StateError, StateMap, StateSet, INITIAL_NEXT_ITEM_PREFIX,
3176 };
3177
3178 const GENERIC_MAP_PREFIX: u64 = 1;
3179
3180 impl<S> StateBuilder<S>
3182 where
3183 S: HasStateApi,
3184 {
3185 pub(crate) fn get<K: Serial, V: DeserialWithState<S>>(
3189 &self,
3190 key: K,
3191 ) -> Option<ParseResult<V>> {
3192 let key_with_map_prefix = Self::prepend_generic_map_key(key);
3193
3194 self.state_api
3195 .lookup_entry(&key_with_map_prefix)
3196 .map(|mut entry| V::deserial_with_state(&self.state_api, &mut entry))
3197 }
3198
3199 pub(crate) fn insert<K: Serial, V: Serial>(
3202 &mut self,
3203 key: K,
3204 value: V,
3205 ) -> Result<(), StateError> {
3206 let key_with_map_prefix = Self::prepend_generic_map_key(key);
3207 match self.state_api.entry(key_with_map_prefix) {
3208 EntryRaw::Vacant(vac) => {
3209 let _ = vac.insert(&value);
3210 }
3211 EntryRaw::Occupied(mut occ) => occ.insert(&value),
3212 }
3213 Ok(())
3214 }
3215
3216 fn prepend_generic_map_key<K: Serial>(key: K) -> Vec<u8> {
3221 let mut key_with_map_prefix = to_bytes(&GENERIC_MAP_PREFIX);
3222 key_with_map_prefix.append(&mut to_bytes(&key));
3223 key_with_map_prefix
3224 }
3225 }
3226
3227 #[concordium_test]
3228 fn high_level_insert_get() {
3229 let expected_value: u64 = 123123123;
3230 let mut state_builder = StateBuilder::open(StateApi::open());
3231 state_builder.insert(0, expected_value).expect("Insert failed");
3232 let actual_value: u64 = state_builder.get(0).expect("Not found").expect("Not a valid u64");
3233 claim_eq!(expected_value, actual_value);
3234 }
3235
3236 #[concordium_test]
3237 fn low_level_entry() {
3238 let expected_value: u64 = 123123123;
3239 let key = to_bytes(&42u64);
3240 let mut state = StateApi::open();
3241 state
3242 .entry(&key[..])
3243 .or_insert_raw(&to_bytes(&expected_value))
3244 .expect("No iterators, so insertion should work.");
3245
3246 match state.entry(key) {
3247 EntryRaw::Vacant(_) => panic!("Unexpected vacant entry."),
3248 EntryRaw::Occupied(occ) => {
3249 claim_eq!(u64::deserial(&mut occ.get()), Ok(expected_value))
3250 }
3251 }
3252 }
3253
3254 #[concordium_test]
3255 fn high_level_statemap() {
3256 let my_map_key = "my_map";
3257 let mut state_builder = StateBuilder::open(StateApi::open());
3258
3259 let map_to_insert = state_builder.new_map::<String, String>();
3260 state_builder.insert(my_map_key, map_to_insert).expect("Insert failed");
3261
3262 let mut my_map: StateMap<String, String, _> = state_builder
3263 .get(my_map_key)
3264 .expect("Could not get statemap")
3265 .expect("Deserializing statemap failed");
3266 let _ = my_map.insert("abc".to_string(), "hello, world".to_string());
3267 let _ = my_map.insert("def".to_string(), "hallo, Weld".to_string());
3268 let _ = my_map.insert("ghi".to_string(), "hej, verden".to_string());
3269 claim_eq!(*my_map.get(&"abc".to_string()).unwrap(), "hello, world".to_string());
3270
3271 let mut iter = my_map.iter();
3272 let (k1, v1) = iter.next().unwrap();
3273 claim_eq!(*k1, "abc".to_string());
3274 claim_eq!(*v1, "hello, world".to_string());
3275 let (k2, v2) = iter.next().unwrap();
3276 claim_eq!(*k2, "def".to_string());
3277 claim_eq!(*v2, "hallo, Weld".to_string());
3278 let (k3, v3) = iter.next().unwrap();
3279 claim_eq!(*k3, "ghi".to_string());
3280 claim_eq!(*v3, "hej, verden".to_string());
3281 claim!(iter.next().is_none());
3282 }
3283
3284 #[concordium_test]
3285 fn statemap_insert_remove() {
3286 let mut state_builder = StateBuilder::open(StateApi::open());
3287 let mut map = state_builder.new_map();
3288 let value = String::from("hello");
3289 let _ = map.insert(42, value.clone());
3290 claim_eq!(*map.get(&42).unwrap(), value);
3291 map.remove(&42);
3292 claim!(map.get(&42).is_none());
3293 }
3294
3295 #[concordium_test]
3296 fn statemap_clear() {
3297 let mut state_builder = StateBuilder::open(StateApi::open());
3298 let mut map = state_builder.new_map();
3299 let _ = map.insert(1, 2);
3300 let _ = map.insert(2, 3);
3301 let _ = map.insert(3, 4);
3302 map.clear();
3303 claim!(map.is_empty());
3304 }
3305
3306 #[concordium_test]
3307 fn high_level_nested_statemaps() {
3308 let inner_map_key = 0u8;
3309 let key_to_value = 77u8;
3310 let value = 255u8;
3311 let mut state_builder = StateBuilder::open(StateApi::open());
3312 let mut outer_map = state_builder.new_map::<u8, StateMap<u8, u8, _>>();
3313 let mut inner_map = state_builder.new_map::<u8, u8>();
3314
3315 let _ = inner_map.insert(key_to_value, value);
3316 let _ = outer_map.insert(inner_map_key, inner_map);
3317
3318 claim_eq!(*outer_map.get(&inner_map_key).unwrap().get(&key_to_value).unwrap(), value);
3319 }
3320
3321 #[concordium_test]
3322 fn statemap_iter_mut_works() {
3323 let mut state_builder = StateBuilder::open(StateApi::open());
3324 let mut map = state_builder.new_map();
3325 let _ = map.insert(0u8, 1u8);
3326 let _ = map.insert(1u8, 2u8);
3327 let _ = map.insert(2u8, 3u8);
3328 for (_, mut v) in map.iter_mut() {
3329 v.update(|old_value| *old_value += 10);
3330 }
3331 let mut iter = map.iter();
3332 let (k1, v1) = iter.next().unwrap();
3333 claim_eq!(*k1, 0);
3334 claim_eq!(*v1, 11);
3335 let (k2, v2) = iter.next().unwrap();
3336 claim_eq!(*k2, 1);
3337 claim_eq!(*v2, 12);
3338 let (k3, v3) = iter.next().unwrap();
3339 claim_eq!(*k3, 2);
3340 claim_eq!(*v3, 13);
3341 claim!(iter.next().is_none());
3342 }
3343
3344 #[concordium_test]
3345 fn iter_mut_works_on_nested_statemaps() {
3346 let mut state_builder = StateBuilder::open(StateApi::open());
3347 let mut outer_map = state_builder.new_map();
3348 let mut inner_map = state_builder.new_map();
3349 let _ = inner_map.insert(0u8, 1u8);
3350 let _ = inner_map.insert(1u8, 2u8);
3351 let _ = outer_map.insert(99u8, inner_map);
3352 for (_, mut v_map) in outer_map.iter_mut() {
3353 v_map.update(|v_map| {
3354 for (_, mut inner_v) in v_map.iter_mut() {
3355 inner_v.update(|inner_v| *inner_v += 10);
3356 }
3357 });
3358 }
3359
3360 let mut outer_iter = outer_map.iter();
3362 let (inner_map_key, inner_map) = outer_iter.next().unwrap();
3363 claim_eq!(*inner_map_key, 99);
3364 claim!(outer_iter.next().is_none());
3365
3366 let mut inner_iter = inner_map.iter();
3368 let (k1, v1) = inner_iter.next().unwrap();
3369 claim_eq!(*k1, 0);
3370 claim_eq!(*v1, 11);
3371 let (k2, v2) = inner_iter.next().unwrap();
3372 claim_eq!(*k2, 1);
3373 claim_eq!(*v2, 12);
3374 claim!(inner_iter.next().is_none());
3375 }
3376
3377 #[concordium_test]
3378 fn statemap_iterator_unlocks_tree_once_dropped() {
3379 let mut state_builder = StateBuilder::open(StateApi::open());
3380 let mut map = state_builder.new_map();
3381 let _ = map.insert(0u8, 1u8);
3382 let _ = map.insert(1u8, 2u8);
3383 {
3384 let _iter = map.iter();
3385 } let _ = map.insert(2u8, 3u8);
3392 }
3393
3394 #[concordium_test]
3395 fn high_level_stateset() {
3396 let my_set_key = "my_set";
3397 let mut state_builder = StateBuilder::open(StateApi::open());
3398
3399 let mut set = state_builder.new_set::<u8>();
3400 claim!(set.insert(0));
3401 claim!(set.insert(1));
3402 claim!(!set.insert(1));
3403 claim!(set.insert(2));
3404 claim!(set.remove(&2));
3405 state_builder.insert(my_set_key, set).expect("Insert failed");
3406
3407 claim!(state_builder.get::<_, StateSet<u8, _>>(my_set_key).unwrap().unwrap().contains(&0),);
3408 claim!(!state_builder.get::<_, StateSet<u8, _>>(my_set_key).unwrap().unwrap().contains(&2),);
3409
3410 let set = state_builder.get::<_, StateSet<u8, _>>(my_set_key).unwrap().unwrap();
3411 let mut iter = set.iter();
3412 claim_eq!(*iter.next().unwrap(), 0);
3413 claim_eq!(*iter.next().unwrap(), 1);
3414 claim!(iter.next().is_none());
3415 }
3416
3417 #[concordium_test]
3418 fn high_level_nested_stateset() {
3419 let inner_set_key = 0u8;
3420 let value = 255u8;
3421 let mut state_builder = StateBuilder::open(StateApi::open());
3422 let mut outer_map = state_builder.new_map::<u8, StateSet<u8, _>>();
3423 let mut inner_set = state_builder.new_set::<u8>();
3424
3425 inner_set.insert(value);
3426 let _ = outer_map.insert(inner_set_key, inner_set);
3427
3428 claim!(outer_map.get(&inner_set_key).unwrap().contains(&value));
3429 }
3430
3431 #[concordium_test]
3432 fn stateset_insert_remove() {
3433 let mut state_builder = StateBuilder::open(StateApi::open());
3434 let mut set = state_builder.new_set();
3435 let _ = set.insert(42);
3436 claim!(set.contains(&42));
3437 set.remove(&42);
3438 claim!(!set.contains(&42));
3439 }
3440
3441 #[concordium_test]
3442 fn stateset_clear() {
3443 let mut state_builder = StateBuilder::open(StateApi::open());
3444 let mut set = state_builder.new_set();
3445 let _ = set.insert(1);
3446 let _ = set.insert(2);
3447 let _ = set.insert(3);
3448 set.clear();
3449 claim!(set.is_empty());
3450 }
3451
3452 #[concordium_test]
3453 fn stateset_iterator_unlocks_tree_once_dropped() {
3454 let mut state_builder = StateBuilder::open(StateApi::open());
3455 let mut set = state_builder.new_set();
3456 set.insert(0u8);
3457 set.insert(1);
3458 {
3459 let _iter = set.iter();
3460 } set.insert(2);
3467 }
3468
3469 #[concordium_test]
3470 fn allocate_and_get_statebox() {
3471 let mut state_builder = StateBuilder::open(StateApi::open());
3472 let boxed_value = String::from("I'm boxed");
3473 let statebox = state_builder.new_box(boxed_value.clone());
3474 claim_eq!(*statebox.get(), boxed_value);
3475 }
3476
3477 #[concordium_test]
3478 fn a_new_entry_can_not_be_created_under_a_locked_subtree() {
3479 let expected_value: u64 = 123123123;
3480 let key = to_bytes(b"ab");
3481 let sub_key = to_bytes(b"abc");
3482 let mut state = StateApi::open();
3483 state
3484 .entry(&key[..])
3485 .or_insert_raw(&to_bytes(&expected_value))
3486 .expect("No iterators, so insertion should work.");
3487 claim!(state.iterator(&key).is_ok(), "Iterator should be present");
3488 let entry = state.create_entry(&sub_key);
3489 claim!(entry.is_err(), "Should not be able to create an entry under a locked subtree");
3490 }
3491
3492 #[concordium_test]
3493 fn a_new_entry_can_be_created_under_a_different_subtree_in_same_super_tree() {
3494 let expected_value: u64 = 123123123;
3495 let key = to_bytes(b"abcd");
3496 let key2 = to_bytes(b"abe");
3497 let mut state = StateApi::open();
3498 state
3499 .entry(&key[..])
3500 .or_insert_raw(&to_bytes(&expected_value))
3501 .expect("No iterators, so insertion should work.");
3502 claim!(state.iterator(&key).is_ok(), "Iterator should be present");
3503 let entry = state.create_entry(&key2);
3504 claim!(entry.is_ok(), "Failed to create a new entry under a different subtree");
3505 }
3506
3507 #[concordium_test]
3508 fn an_existing_entry_can_not_be_deleted_under_a_locked_subtree() {
3509 let expected_value: u64 = 123123123;
3510 let key = to_bytes(b"ab");
3511 let sub_key = to_bytes(b"abc");
3512 let mut state = StateApi::open();
3513 state
3514 .entry(&key[..])
3515 .or_insert_raw(&to_bytes(&expected_value))
3516 .expect("no iterators, so insertion should work.");
3517 let sub_entry = state
3518 .entry(sub_key)
3519 .or_insert_raw(&to_bytes(&expected_value))
3520 .expect("Should be possible to create the entry.");
3521 claim!(state.iterator(&key).is_ok(), "Iterator should be present");
3522 claim!(
3523 state.delete_entry(sub_entry).is_err(),
3524 "Should not be able to delete entry under a locked subtree"
3525 );
3526 }
3527
3528 #[concordium_test]
3529 fn an_existing_entry_can_be_deleted_from_a_different_subtree_in_same_super_tree() {
3530 let expected_value: u64 = 123123123;
3531 let key = to_bytes(b"abcd");
3532 let key2 = to_bytes(b"abe");
3533 let mut state = StateApi::open();
3534 state
3535 .entry(&key[..])
3536 .or_insert_raw(&to_bytes(&expected_value))
3537 .expect("No iterators, so insertion should work.");
3538 let entry2 = state
3539 .entry(key2)
3540 .or_insert_raw(&to_bytes(&expected_value))
3541 .expect("Should be possible to create the entry.");
3542 claim!(state.iterator(&key).is_ok(), "Iterator should be present");
3543 claim!(
3544 state.delete_entry(entry2).is_ok(),
3545 "Should be able to delete entry under a different subtree"
3546 );
3547 }
3548
3549 #[concordium_test]
3550 fn deleting_nested_stateboxes_works() {
3551 let mut state_builder = StateBuilder::open(StateApi::open());
3552 let inner_box = state_builder.new_box(99u8);
3553 let middle_box = state_builder.new_box(inner_box);
3554 let outer_box = state_builder.new_box(middle_box);
3555 outer_box.delete();
3556 let mut iter = state_builder.state_api.iterator(&[]).expect("Could not get iterator");
3557 claim!(iter.nth(1).is_none());
3559 }
3560
3561 #[concordium_test]
3562 fn clearing_statemap_with_stateboxes_works() {
3563 let mut state_builder = StateBuilder::open(StateApi::open());
3564 let box1 = state_builder.new_box(1u8);
3565 let box2 = state_builder.new_box(2u8);
3566 let box3 = state_builder.new_box(3u8);
3567 let mut map = state_builder.new_map();
3568 let _ = map.insert(1u8, box1);
3569 let _ = map.insert(2u8, box2);
3570 let _ = map.insert(3u8, box3);
3571 map.clear();
3572 let mut iter = state_builder.state_api.iterator(&[]).expect("Could not get iterator");
3573 claim!(iter.nth(1).is_none());
3575 }
3576
3577 #[concordium_test]
3578 fn clearing_nested_statemaps_works() {
3579 let mut state_builder = StateBuilder::open(StateApi::open());
3580 let mut inner_map_1 = state_builder.new_map();
3581 let _ = inner_map_1.insert(1u8, 2u8);
3582 let _ = inner_map_1.insert(2u8, 3u8);
3583 let _ = inner_map_1.insert(3u8, 4u8);
3584 let mut inner_map_2 = state_builder.new_map();
3585 let _ = inner_map_2.insert(11u8, 12u8);
3586 let _ = inner_map_2.insert(12u8, 13u8);
3587 let _ = inner_map_2.insert(13u8, 14u8);
3588 let mut outer_map = state_builder.new_map();
3589 let _ = outer_map.insert(0u8, inner_map_1);
3590 let _ = outer_map.insert(1u8, inner_map_2);
3591 outer_map.clear();
3592 let mut iter = state_builder.state_api.iterator(&[]).expect("Could not get iterator");
3593 claim!(iter.nth(1).is_none());
3595 }
3596
3597 #[concordium_test]
3598 fn occupied_entry_truncates_leftover_data() {
3599 let mut state_builder = StateBuilder::open(StateApi::open());
3600 let mut map = state_builder.new_map();
3601 let _ = map.insert(99u8, "A longer string that should be truncated".into());
3602 let a_short_string = "A short string".to_string();
3603 let expected_size = a_short_string.len() + 4; map.entry(99u8).and_modify(|v| *v = a_short_string);
3605 let actual_size = state_builder
3606 .state_api
3607 .lookup_entry(&[INITIAL_NEXT_ITEM_PREFIX[0], 0, 0, 0, 0, 0, 0, 0, 99])
3608 .expect("Lookup failed")
3609 .size()
3610 .expect("Getting size failed");
3611 claim_eq!(expected_size as u32, actual_size);
3612 }
3613
3614 #[concordium_test]
3615 fn occupied_entry_raw_truncates_leftover_data() {
3616 let mut state = StateApi::open();
3617 state
3618 .entry([])
3619 .or_insert_raw(&to_bytes(&"A longer string that should be truncated"))
3620 .expect("No iterators, so insertion should work.");
3621
3622 let a_short_string = "A short string";
3623 let expected_size = a_short_string.len() + 4; match state.entry([]) {
3626 EntryRaw::Vacant(_) => panic!("Entry is vacant"),
3627 EntryRaw::Occupied(mut occ) => occ.insert_raw(&to_bytes(&a_short_string)),
3628 }
3629 let actual_size =
3630 state.lookup_entry(&[]).expect("Lookup failed").size().expect("Getting size failed");
3631 claim_eq!(expected_size as u32, actual_size);
3632 }
3633}