1use std::{
8 borrow::{Borrow, Cow},
9 collections::HashMap,
10 fmt::Display,
11 fs::File,
12 hash::{Hash, Hasher},
13 io::{Cursor, Read},
14 ops::{Deref, DerefMut},
15 path::Path,
16 str::FromStr,
17 sync::Arc,
18};
19
20use blake3::{traits::digest::Digest, Hasher as Blake3};
21use byteorder::{LittleEndian, ReadBytesExt};
22use serde::{Deserialize, Deserializer, Serialize};
23use serde_with::serde_as;
24
25use crate::client_api::TryFromFbs;
26use crate::common_generated::common::{
27 ContractKey as FbsContractKey, UpdateData as FbsUpdateData, UpdateDataType,
28};
29use crate::generated::client_request::RelatedContracts as FbsRelatedContracts;
30use crate::{client_api::WsApiError, code_hash::CodeHash, parameters::Parameters};
31
32pub(crate) const CONTRACT_KEY_SIZE: usize = 32;
33
34#[derive(Debug, thiserror::Error, Serialize, Deserialize)]
36pub enum ContractError {
37 #[error("de/serialization error: {0}")]
38 Deser(String),
39 #[error("invalid contract update")]
40 InvalidUpdate,
41 #[error("invalid contract update, reason: {reason}")]
42 InvalidUpdateWithInfo { reason: String },
43 #[error("trying to read an invalid state")]
44 InvalidState,
45 #[error("trying to read an invalid delta")]
46 InvalidDelta,
47 #[error("{0}")]
48 Other(String),
49}
50
51#[non_exhaustive]
54#[derive(Debug, Serialize, Deserialize)]
55pub struct UpdateModification<'a> {
56 #[serde(borrow)]
57 pub new_state: Option<State<'a>>,
58 pub related: Vec<RelatedContract>,
60}
61
62impl<'a> UpdateModification<'a> {
63 pub fn valid(new_state: State<'a>) -> Self {
65 Self {
66 new_state: Some(new_state),
67 related: vec![],
68 }
69 }
70
71 pub fn unwrap_valid(self) -> State<'a> {
75 match self.new_state {
76 Some(s) => s,
77 _ => panic!("failed unwrapping state in modification"),
78 }
79 }
80}
81
82impl UpdateModification<'_> {
83 pub fn requires(related: Vec<RelatedContract>) -> Result<Self, ContractError> {
86 if related.is_empty() {
87 return Err(ContractError::InvalidUpdateWithInfo {
88 reason: "At least one related contract is required".into(),
89 });
90 }
91 Ok(Self {
92 new_state: None,
93 related,
94 })
95 }
96
97 pub fn get_related(&self) -> &[RelatedContract] {
99 &self.related
100 }
101
102 pub fn into_owned(self) -> UpdateModification<'static> {
104 let Self { new_state, related } = self;
105 UpdateModification {
106 new_state: new_state.map(State::into_owned),
107 related,
108 }
109 }
110
111 pub fn requires_dependencies(&self) -> bool {
112 !self.related.is_empty()
113 }
114}
115
116#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Default)]
120pub struct RelatedContracts<'a> {
121 #[serde(borrow)]
122 map: HashMap<ContractInstanceId, Option<State<'a>>>,
123}
124
125impl RelatedContracts<'_> {
126 pub fn new() -> Self {
127 Self {
128 map: HashMap::new(),
129 }
130 }
131
132 pub fn into_owned(self) -> RelatedContracts<'static> {
134 let mut map = HashMap::with_capacity(self.map.len());
135 for (k, v) in self.map {
136 map.insert(k, v.map(|s| s.into_owned()));
137 }
138 RelatedContracts { map }
139 }
140
141 pub fn deser_related_contracts<'de, D>(deser: D) -> Result<RelatedContracts<'static>, D::Error>
142 where
143 D: serde::Deserializer<'de>,
144 {
145 let value = <RelatedContracts as Deserialize>::deserialize(deser)?;
146 Ok(value.into_owned())
147 }
148}
149
150impl RelatedContracts<'static> {
151 pub fn states(&self) -> impl Iterator<Item = (&ContractInstanceId, &Option<State<'static>>)> {
152 self.map.iter()
153 }
154}
155
156impl<'a> RelatedContracts<'a> {
157 pub fn update(
158 &mut self,
159 ) -> impl Iterator<Item = (&ContractInstanceId, &mut Option<State<'a>>)> + '_ {
160 self.map.iter_mut()
161 }
162
163 pub fn missing(&mut self, contracts: Vec<ContractInstanceId>) {
164 for key in contracts {
165 self.map.entry(key).or_default();
166 }
167 }
168}
169
170impl<'a> TryFromFbs<&FbsRelatedContracts<'a>> for RelatedContracts<'a> {
171 fn try_decode_fbs(related_contracts: &FbsRelatedContracts<'a>) -> Result<Self, WsApiError> {
172 let mut map = HashMap::with_capacity(related_contracts.contracts().len());
173 for related in related_contracts.contracts().iter() {
174 let id = ContractInstanceId::from_bytes(related.instance_id().data().bytes()).unwrap();
175 let state = State::from(related.state().bytes());
176 map.insert(id, Some(state));
177 }
178 Ok(RelatedContracts::from(map))
179 }
180}
181
182impl<'a> From<HashMap<ContractInstanceId, Option<State<'a>>>> for RelatedContracts<'a> {
183 fn from(related_contracts: HashMap<ContractInstanceId, Option<State<'a>>>) -> Self {
184 Self {
185 map: related_contracts,
186 }
187 }
188}
189
190#[derive(Debug, Serialize, Deserialize)]
193pub struct RelatedContract {
194 pub contract_instance_id: ContractInstanceId,
195 pub mode: RelatedMode,
196 }
198
199#[derive(Debug, Serialize, Deserialize)]
201pub enum RelatedMode {
202 StateOnce,
204 StateThenSubscribe,
206}
207
208#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
210pub enum ValidateResult {
211 Valid,
212 Invalid,
213 RequestRelated(Vec<ContractInstanceId>),
216}
217
218#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
220pub enum UpdateData<'a> {
221 State(#[serde(borrow)] State<'a>),
222 Delta(#[serde(borrow)] StateDelta<'a>),
223 StateAndDelta {
224 #[serde(borrow)]
225 state: State<'a>,
226 #[serde(borrow)]
227 delta: StateDelta<'a>,
228 },
229 RelatedState {
230 related_to: ContractInstanceId,
231 #[serde(borrow)]
232 state: State<'a>,
233 },
234 RelatedDelta {
235 related_to: ContractInstanceId,
236 #[serde(borrow)]
237 delta: StateDelta<'a>,
238 },
239 RelatedStateAndDelta {
240 related_to: ContractInstanceId,
241 #[serde(borrow)]
242 state: State<'a>,
243 #[serde(borrow)]
244 delta: StateDelta<'a>,
245 },
246}
247
248impl UpdateData<'_> {
249 pub fn size(&self) -> usize {
250 match self {
251 UpdateData::State(state) => state.size(),
252 UpdateData::Delta(delta) => delta.size(),
253 UpdateData::StateAndDelta { state, delta } => state.size() + delta.size(),
254 UpdateData::RelatedState { state, .. } => state.size() + CONTRACT_KEY_SIZE,
255 UpdateData::RelatedDelta { delta, .. } => delta.size() + CONTRACT_KEY_SIZE,
256 UpdateData::RelatedStateAndDelta { state, delta, .. } => {
257 state.size() + delta.size() + CONTRACT_KEY_SIZE
258 }
259 }
260 }
261
262 pub fn unwrap_delta(&self) -> &StateDelta<'_> {
263 match self {
264 UpdateData::Delta(delta) => delta,
265 _ => panic!(),
266 }
267 }
268
269 pub fn into_owned(self) -> UpdateData<'static> {
271 match self {
272 UpdateData::State(s) => UpdateData::State(State::from(s.into_bytes())),
273 UpdateData::Delta(d) => UpdateData::Delta(StateDelta::from(d.into_bytes())),
274 UpdateData::StateAndDelta { state, delta } => UpdateData::StateAndDelta {
275 delta: StateDelta::from(delta.into_bytes()),
276 state: State::from(state.into_bytes()),
277 },
278 UpdateData::RelatedState { related_to, state } => UpdateData::RelatedState {
279 related_to,
280 state: State::from(state.into_bytes()),
281 },
282 UpdateData::RelatedDelta { related_to, delta } => UpdateData::RelatedDelta {
283 related_to,
284 delta: StateDelta::from(delta.into_bytes()),
285 },
286 UpdateData::RelatedStateAndDelta {
287 related_to,
288 state,
289 delta,
290 } => UpdateData::RelatedStateAndDelta {
291 related_to,
292 state: State::from(state.into_bytes()),
293 delta: StateDelta::from(delta.into_bytes()),
294 },
295 }
296 }
297
298 pub(crate) fn get_self_states<'a>(
299 updates: &[UpdateData<'a>],
300 ) -> Vec<(Option<State<'a>>, Option<StateDelta<'a>>)> {
301 let mut own_states = Vec::with_capacity(updates.len());
302 for update in updates {
303 match update {
304 UpdateData::State(state) => own_states.push((Some(state.clone()), None)),
305 UpdateData::Delta(delta) => own_states.push((None, Some(delta.clone()))),
306 UpdateData::StateAndDelta { state, delta } => {
307 own_states.push((Some(state.clone()), Some(delta.clone())))
308 }
309 _ => {}
310 }
311 }
312 own_states
313 }
314
315 pub(crate) fn deser_update_data<'de, D>(deser: D) -> Result<UpdateData<'static>, D::Error>
316 where
317 D: serde::Deserializer<'de>,
318 {
319 let value = <UpdateData as Deserialize>::deserialize(deser)?;
320 Ok(value.into_owned())
321 }
322}
323
324impl<'a> From<StateDelta<'a>> for UpdateData<'a> {
325 fn from(delta: StateDelta<'a>) -> Self {
326 UpdateData::Delta(delta)
327 }
328}
329
330impl<'a> TryFromFbs<&FbsUpdateData<'a>> for UpdateData<'a> {
331 fn try_decode_fbs(update_data: &FbsUpdateData<'a>) -> Result<Self, WsApiError> {
332 match update_data.update_data_type() {
333 UpdateDataType::StateUpdate => {
334 let update = update_data.update_data_as_state_update().unwrap();
335 let state = State::from(update.state().bytes());
336 Ok(UpdateData::State(state))
337 }
338 UpdateDataType::DeltaUpdate => {
339 let update = update_data.update_data_as_delta_update().unwrap();
340 let delta = StateDelta::from(update.delta().bytes());
341 Ok(UpdateData::Delta(delta))
342 }
343 UpdateDataType::StateAndDeltaUpdate => {
344 let update = update_data.update_data_as_state_and_delta_update().unwrap();
345 let state = State::from(update.state().bytes());
346 let delta = StateDelta::from(update.delta().bytes());
347 Ok(UpdateData::StateAndDelta { state, delta })
348 }
349 UpdateDataType::RelatedStateUpdate => {
350 let update = update_data.update_data_as_related_state_update().unwrap();
351 let state = State::from(update.state().bytes());
352 let related_to =
353 ContractInstanceId::from_bytes(update.related_to().data().bytes()).unwrap();
354 Ok(UpdateData::RelatedState { related_to, state })
355 }
356 UpdateDataType::RelatedDeltaUpdate => {
357 let update = update_data.update_data_as_related_delta_update().unwrap();
358 let delta = StateDelta::from(update.delta().bytes());
359 let related_to =
360 ContractInstanceId::from_bytes(update.related_to().data().bytes()).unwrap();
361 Ok(UpdateData::RelatedDelta { related_to, delta })
362 }
363 UpdateDataType::RelatedStateAndDeltaUpdate => {
364 let update = update_data
365 .update_data_as_related_state_and_delta_update()
366 .unwrap();
367 let state = State::from(update.state().bytes());
368 let delta = StateDelta::from(update.delta().bytes());
369 let related_to =
370 ContractInstanceId::from_bytes(update.related_to().data().bytes()).unwrap();
371 Ok(UpdateData::RelatedStateAndDelta {
372 related_to,
373 state,
374 delta,
375 })
376 }
377 _ => unreachable!(),
378 }
379 }
380}
381
382pub trait ContractInterface {
440 fn validate_state(
442 parameters: Parameters<'static>,
443 state: State<'static>,
444 related: RelatedContracts<'static>,
445 ) -> Result<ValidateResult, ContractError>;
446
447 fn update_state(
449 parameters: Parameters<'static>,
450 state: State<'static>,
451 data: Vec<UpdateData<'static>>,
452 ) -> Result<UpdateModification<'static>, ContractError>;
453
454 fn summarize_state(
457 parameters: Parameters<'static>,
458 state: State<'static>,
459 ) -> Result<StateSummary<'static>, ContractError>;
460
461 fn get_state_delta(
465 parameters: Parameters<'static>,
466 state: State<'static>,
467 summary: StateSummary<'static>,
468 ) -> Result<StateDelta<'static>, ContractError>;
469}
470#[derive(Debug, Serialize, Deserialize, Clone)]
475#[cfg_attr(
476 any(feature = "testing", all(test, any(unix, windows))),
477 derive(arbitrary::Arbitrary)
478)]
479pub struct Contract<'a> {
480 #[serde(borrow)]
481 pub parameters: Parameters<'a>,
482 #[serde(borrow)]
483 pub data: ContractCode<'a>,
484 key: ContractKey,
486}
487
488impl<'a> Contract<'a> {
489 pub fn new(contract: ContractCode<'a>, parameters: Parameters<'a>) -> Contract<'a> {
491 let key = ContractKey::from_params_and_code(¶meters, &contract);
492 Contract {
493 parameters,
494 data: contract,
495 key,
496 }
497 }
498
499 pub fn key(&self) -> &ContractKey {
501 &self.key
502 }
503
504 pub fn into_code(self) -> ContractCode<'a> {
506 self.data
507 }
508}
509
510impl TryFrom<Vec<u8>> for Contract<'static> {
511 type Error = std::io::Error;
512
513 fn try_from(data: Vec<u8>) -> Result<Self, Self::Error> {
514 let mut reader = Cursor::new(data);
515
516 let params_len = reader.read_u64::<LittleEndian>()?;
517 let mut params_buf = vec![0; params_len as usize];
518 reader.read_exact(&mut params_buf)?;
519 let parameters = Parameters::from(params_buf);
520
521 let contract_len = reader.read_u64::<LittleEndian>()?;
522 let mut contract_buf = vec![0; contract_len as usize];
523 reader.read_exact(&mut contract_buf)?;
524 let contract = ContractCode::from(contract_buf);
525
526 let key = ContractKey::from_params_and_code(¶meters, &contract);
527
528 Ok(Contract {
529 parameters,
530 data: contract,
531 key,
532 })
533 }
534}
535
536impl PartialEq for Contract<'_> {
537 fn eq(&self, other: &Self) -> bool {
538 self.key == other.key
539 }
540}
541
542impl Eq for Contract<'_> {}
543
544impl std::fmt::Display for Contract<'_> {
545 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
546 write!(f, "ContractSpec( key: ")?;
547 internal_fmt_key(&self.key.instance.0, f)?;
548 let data: String = if self.data.data.len() > 8 {
549 self.data.data[..4]
550 .iter()
551 .map(|b| char::from(*b))
552 .chain("...".chars())
553 .chain(self.data.data[4..].iter().map(|b| char::from(*b)))
554 .collect()
555 } else {
556 self.data.data.iter().copied().map(char::from).collect()
557 };
558 write!(f, ", data: [{data}])")
559 }
560}
561
562#[serde_as]
566#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
567#[cfg_attr(feature = "testing", derive(arbitrary::Arbitrary))]
568pub struct State<'a>(
569 #[serde_as(as = "serde_with::Bytes")]
571 #[serde(borrow)]
572 Cow<'a, [u8]>,
573);
574
575impl State<'_> {
576 pub fn size(&self) -> usize {
578 self.0.len()
579 }
580
581 pub fn into_owned(self) -> State<'static> {
582 State(self.0.into_owned().into())
583 }
584
585 pub fn into_bytes(self) -> Vec<u8> {
587 self.0.into_owned()
588 }
589
590 pub fn to_mut(&mut self) -> &mut Vec<u8> {
592 self.0.to_mut()
593 }
594}
595
596impl From<Vec<u8>> for State<'_> {
597 fn from(state: Vec<u8>) -> Self {
598 State(Cow::from(state))
599 }
600}
601
602impl<'a> From<&'a [u8]> for State<'a> {
603 fn from(state: &'a [u8]) -> Self {
604 State(Cow::from(state))
605 }
606}
607
608impl AsRef<[u8]> for State<'_> {
609 fn as_ref(&self) -> &[u8] {
610 match &self.0 {
611 Cow::Borrowed(arr) => arr,
612 Cow::Owned(arr) => arr.as_ref(),
613 }
614 }
615}
616
617impl<'a> Deref for State<'a> {
618 type Target = Cow<'a, [u8]>;
619
620 fn deref(&self) -> &Self::Target {
621 &self.0
622 }
623}
624
625impl DerefMut for State<'_> {
626 fn deref_mut(&mut self) -> &mut Self::Target {
627 &mut self.0
628 }
629}
630
631impl std::io::Read for State<'_> {
632 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
633 self.as_ref().read(buf)
634 }
635}
636
637#[serde_as]
644#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
645#[cfg_attr(feature = "testing", derive(arbitrary::Arbitrary))]
646pub struct StateDelta<'a>(
647 #[serde_as(as = "serde_with::Bytes")]
649 #[serde(borrow)]
650 Cow<'a, [u8]>,
651);
652
653impl StateDelta<'_> {
654 pub fn size(&self) -> usize {
656 self.0.len()
657 }
658
659 pub fn into_bytes(self) -> Vec<u8> {
661 self.0.into_owned()
662 }
663
664 pub fn into_owned(self) -> StateDelta<'static> {
665 StateDelta(self.0.into_owned().into())
666 }
667}
668
669impl From<Vec<u8>> for StateDelta<'_> {
670 fn from(delta: Vec<u8>) -> Self {
671 StateDelta(Cow::from(delta))
672 }
673}
674
675impl<'a> From<&'a [u8]> for StateDelta<'a> {
676 fn from(delta: &'a [u8]) -> Self {
677 StateDelta(Cow::from(delta))
678 }
679}
680
681impl AsRef<[u8]> for StateDelta<'_> {
682 fn as_ref(&self) -> &[u8] {
683 match &self.0 {
684 Cow::Borrowed(arr) => arr,
685 Cow::Owned(arr) => arr.as_ref(),
686 }
687 }
688}
689
690impl<'a> Deref for StateDelta<'a> {
691 type Target = Cow<'a, [u8]>;
692
693 fn deref(&self) -> &Self::Target {
694 &self.0
695 }
696}
697
698impl DerefMut for StateDelta<'_> {
699 fn deref_mut(&mut self) -> &mut Self::Target {
700 &mut self.0
701 }
702}
703
704#[serde_as]
710#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
711#[cfg_attr(feature = "testing", derive(arbitrary::Arbitrary))]
712pub struct StateSummary<'a>(
713 #[serde_as(as = "serde_with::Bytes")]
715 #[serde(borrow)]
716 Cow<'a, [u8]>,
717);
718
719impl StateSummary<'_> {
720 pub fn into_bytes(self) -> Vec<u8> {
722 self.0.into_owned()
723 }
724
725 pub fn size(&self) -> usize {
727 self.0.len()
728 }
729
730 pub fn into_owned(self) -> StateSummary<'static> {
731 StateSummary(self.0.into_owned().into())
732 }
733
734 pub fn deser_state_summary<'de, D>(deser: D) -> Result<StateSummary<'static>, D::Error>
735 where
736 D: serde::Deserializer<'de>,
737 {
738 let value = <StateSummary as Deserialize>::deserialize(deser)?;
739 Ok(value.into_owned())
740 }
741}
742
743impl From<Vec<u8>> for StateSummary<'_> {
744 fn from(state: Vec<u8>) -> Self {
745 StateSummary(Cow::from(state))
746 }
747}
748
749impl<'a> From<&'a [u8]> for StateSummary<'a> {
750 fn from(state: &'a [u8]) -> Self {
751 StateSummary(Cow::from(state))
752 }
753}
754
755impl AsRef<[u8]> for StateSummary<'_> {
756 fn as_ref(&self) -> &[u8] {
757 match &self.0 {
758 Cow::Borrowed(arr) => arr,
759 Cow::Owned(arr) => arr.as_ref(),
760 }
761 }
762}
763
764impl<'a> Deref for StateSummary<'a> {
765 type Target = Cow<'a, [u8]>;
766
767 fn deref(&self) -> &Self::Target {
768 &self.0
769 }
770}
771
772impl DerefMut for StateSummary<'_> {
773 fn deref_mut(&mut self) -> &mut Self::Target {
774 &mut self.0
775 }
776}
777
778#[serde_as]
783#[derive(Serialize, Deserialize, Clone)]
784#[cfg_attr(
785 any(feature = "testing", all(test, any(unix, windows))),
786 derive(arbitrary::Arbitrary)
787)]
788pub struct ContractCode<'a> {
789 #[serde_as(as = "serde_with::Bytes")]
791 #[serde(borrow)]
792 pub(crate) data: Cow<'a, [u8]>,
793 pub(crate) code_hash: CodeHash,
795}
796
797impl ContractCode<'static> {
798 pub fn load_raw(path: &Path) -> Result<Self, std::io::Error> {
800 let contract_data = Self::load_bytes(path)?;
801 Ok(ContractCode::from(contract_data))
802 }
803
804 pub(crate) fn load_bytes(path: &Path) -> Result<Vec<u8>, std::io::Error> {
805 let mut contract_file = File::open(path)?;
806 let mut contract_data = if let Ok(md) = contract_file.metadata() {
807 Vec::with_capacity(md.len() as usize)
808 } else {
809 Vec::new()
810 };
811 contract_file.read_to_end(&mut contract_data)?;
812 Ok(contract_data)
813 }
814}
815
816impl ContractCode<'_> {
817 pub fn hash(&self) -> &CodeHash {
819 &self.code_hash
820 }
821
822 pub fn hash_str(&self) -> String {
824 Self::encode_hash(&self.code_hash.0)
825 }
826
827 pub fn data(&self) -> &[u8] {
829 &self.data
830 }
831
832 pub fn into_bytes(self) -> Vec<u8> {
834 self.data.to_vec()
835 }
836
837 pub fn encode_hash(hash: &[u8; CONTRACT_KEY_SIZE]) -> String {
839 bs58::encode(hash)
840 .with_alphabet(bs58::Alphabet::BITCOIN)
841 .into_string()
842 }
843
844 pub fn into_owned(self) -> ContractCode<'static> {
846 ContractCode {
847 data: self.data.into_owned().into(),
848 code_hash: self.code_hash,
849 }
850 }
851
852 fn gen_hash(data: &[u8]) -> CodeHash {
853 let mut hasher = Blake3::new();
854 hasher.update(data);
855 let key_arr = hasher.finalize();
856 debug_assert_eq!(key_arr[..].len(), CONTRACT_KEY_SIZE);
857 let mut key = [0; CONTRACT_KEY_SIZE];
858 key.copy_from_slice(&key_arr);
859 CodeHash(key)
860 }
861}
862
863impl From<Vec<u8>> for ContractCode<'static> {
864 fn from(data: Vec<u8>) -> Self {
865 let key = ContractCode::gen_hash(&data);
866 ContractCode {
867 data: Cow::from(data),
868 code_hash: key,
869 }
870 }
871}
872
873impl<'a> From<&'a [u8]> for ContractCode<'a> {
874 fn from(data: &'a [u8]) -> ContractCode<'a> {
875 let hash = ContractCode::gen_hash(data);
876 ContractCode {
877 data: Cow::from(data),
878 code_hash: hash,
879 }
880 }
881}
882
883impl PartialEq for ContractCode<'_> {
884 fn eq(&self, other: &Self) -> bool {
885 self.code_hash == other.code_hash
886 }
887}
888
889impl Eq for ContractCode<'_> {}
890
891impl std::fmt::Display for ContractCode<'_> {
892 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
893 write!(f, "Contract( key: ")?;
894 internal_fmt_key(&self.code_hash.0, f)?;
895 let data: String = if self.data.len() > 8 {
896 self.data[..4]
897 .iter()
898 .map(|b| char::from(*b))
899 .chain("...".chars())
900 .chain(self.data[4..].iter().map(|b| char::from(*b)))
901 .collect()
902 } else {
903 self.data.iter().copied().map(char::from).collect()
904 };
905 write!(f, ", data: [{data}])")
906 }
907}
908
909impl std::fmt::Debug for ContractCode<'_> {
910 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
911 f.debug_struct("ContractCode")
912 .field("hash", &self.code_hash);
913 Ok(())
914 }
915}
916
917#[serde_as]
919#[derive(PartialEq, Eq, Clone, Copy, Serialize, Deserialize, Hash)]
920#[cfg_attr(
921 any(feature = "testing", all(test, any(unix, windows))),
922 derive(arbitrary::Arbitrary)
923)]
924#[repr(transparent)]
925pub struct ContractInstanceId(#[serde_as(as = "[_; CONTRACT_KEY_SIZE]")] [u8; CONTRACT_KEY_SIZE]);
926
927impl ContractInstanceId {
928 pub fn from_params_and_code<'a>(
929 params: impl Borrow<Parameters<'a>>,
930 code: impl Borrow<ContractCode<'a>>,
931 ) -> Self {
932 generate_id(params.borrow(), code.borrow())
933 }
934
935 pub const fn new(key: [u8; CONTRACT_KEY_SIZE]) -> Self {
936 Self(key)
937 }
938
939 pub fn encode(&self) -> String {
941 bs58::encode(self.0)
942 .with_alphabet(bs58::Alphabet::BITCOIN)
943 .into_string()
944 }
945
946 pub fn as_bytes(&self) -> &[u8] {
947 self.0.as_slice()
948 }
949
950 pub fn from_bytes(bytes: impl AsRef<[u8]>) -> Result<Self, bs58::decode::Error> {
952 let mut spec = [0; CONTRACT_KEY_SIZE];
953 bs58::decode(bytes)
954 .with_alphabet(bs58::Alphabet::BITCOIN)
955 .onto(&mut spec)?;
956 Ok(Self(spec))
957 }
958}
959
960impl Deref for ContractInstanceId {
961 type Target = [u8; CONTRACT_KEY_SIZE];
962
963 fn deref(&self) -> &Self::Target {
964 &self.0
965 }
966}
967
968impl FromStr for ContractInstanceId {
969 type Err = bs58::decode::Error;
970
971 fn from_str(s: &str) -> Result<Self, Self::Err> {
972 ContractInstanceId::from_bytes(s)
973 }
974}
975
976impl TryFrom<String> for ContractInstanceId {
977 type Error = bs58::decode::Error;
978
979 fn try_from(s: String) -> Result<Self, Self::Error> {
980 ContractInstanceId::from_bytes(s)
981 }
982}
983
984impl Display for ContractInstanceId {
985 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
986 write!(f, "{}", self.encode())
987 }
988}
989
990impl std::fmt::Debug for ContractInstanceId {
991 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
992 f.debug_tuple("ContractInstanceId")
993 .field(&self.encode())
994 .finish()
995 }
996}
997
998#[serde_as]
1000#[derive(Debug, Eq, Copy, Clone, Serialize, Deserialize)]
1001#[cfg_attr(
1002 any(feature = "testing", all(test, any(unix, windows))),
1003 derive(arbitrary::Arbitrary)
1004)]
1005pub struct ContractKey {
1006 instance: ContractInstanceId,
1007 code: Option<CodeHash>,
1008}
1009
1010impl ContractKey {
1011 pub fn from_params_and_code<'a>(
1012 params: impl Borrow<Parameters<'a>>,
1013 wasm_code: impl Borrow<ContractCode<'a>>,
1014 ) -> Self {
1015 let code = wasm_code.borrow();
1016 let id = generate_id(params.borrow(), code);
1017 let code_hash = code.hash();
1018 Self {
1019 instance: id,
1020 code: Some(*code_hash),
1021 }
1022 }
1023
1024 pub fn from_id(instance: impl Into<String>) -> Result<Self, bs58::decode::Error> {
1026 let instance = ContractInstanceId::try_from(instance.into())?;
1027 Ok(Self {
1028 instance,
1029 code: None,
1030 })
1031 }
1032
1033 pub fn as_bytes(&self) -> &[u8] {
1035 self.instance.0.as_ref()
1036 }
1037
1038 pub fn code_hash(&self) -> Option<&CodeHash> {
1040 self.code.as_ref()
1041 }
1042
1043 pub fn encoded_code_hash(&self) -> Option<String> {
1045 self.code.as_ref().map(|c| {
1046 bs58::encode(c.0)
1047 .with_alphabet(bs58::Alphabet::BITCOIN)
1048 .into_string()
1049 })
1050 }
1051
1052 pub fn from_params(
1055 code_hash: impl Into<String>,
1056 parameters: Parameters,
1057 ) -> Result<Self, bs58::decode::Error> {
1058 let mut code_key = [0; CONTRACT_KEY_SIZE];
1059 bs58::decode(code_hash.into())
1060 .with_alphabet(bs58::Alphabet::BITCOIN)
1061 .onto(&mut code_key)?;
1062
1063 let mut hasher = Blake3::new();
1064 hasher.update(code_key.as_slice());
1065 hasher.update(parameters.as_ref());
1066 let full_key_arr = hasher.finalize();
1067
1068 let mut spec = [0; CONTRACT_KEY_SIZE];
1069 spec.copy_from_slice(&full_key_arr);
1070 Ok(Self {
1071 instance: ContractInstanceId(spec),
1072 code: Some(CodeHash(code_key)),
1073 })
1074 }
1075
1076 pub fn encoded_contract_id(&self) -> String {
1078 self.instance.encode()
1079 }
1080
1081 pub fn id(&self) -> &ContractInstanceId {
1082 &self.instance
1083 }
1084}
1085
1086impl PartialEq for ContractKey {
1087 fn eq(&self, other: &Self) -> bool {
1088 self.instance == other.instance
1089 }
1090}
1091
1092impl std::hash::Hash for ContractKey {
1093 fn hash<H: Hasher>(&self, state: &mut H) {
1094 self.instance.0.hash(state);
1095 }
1096}
1097
1098impl From<ContractInstanceId> for ContractKey {
1099 fn from(instance: ContractInstanceId) -> Self {
1100 Self {
1101 instance,
1102 code: None,
1103 }
1104 }
1105}
1106
1107impl From<ContractKey> for ContractInstanceId {
1108 fn from(key: ContractKey) -> Self {
1109 key.instance
1110 }
1111}
1112
1113impl Deref for ContractKey {
1114 type Target = [u8; CONTRACT_KEY_SIZE];
1115
1116 fn deref(&self) -> &Self::Target {
1117 &self.instance.0
1118 }
1119}
1120
1121impl std::fmt::Display for ContractKey {
1122 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1123 self.instance.fmt(f)
1124 }
1125}
1126
1127impl<'a> TryFromFbs<&FbsContractKey<'a>> for ContractKey {
1128 fn try_decode_fbs(key: &FbsContractKey<'a>) -> Result<Self, WsApiError> {
1129 let key_bytes: [u8; CONTRACT_KEY_SIZE] = key.instance().data().bytes().try_into().unwrap();
1130 let instance = ContractInstanceId::new(key_bytes);
1131 let code = key
1132 .code()
1133 .map(|code_hash| CodeHash::from_code(code_hash.bytes()));
1134 Ok(ContractKey { instance, code })
1135 }
1136}
1137
1138fn generate_id<'a>(
1139 parameters: &Parameters<'a>,
1140 code_data: &ContractCode<'a>,
1141) -> ContractInstanceId {
1142 let contract_hash = code_data.hash();
1143
1144 let mut hasher = Blake3::new();
1145 hasher.update(contract_hash.0.as_slice());
1146 hasher.update(parameters.as_ref());
1147 let full_key_arr = hasher.finalize();
1148
1149 debug_assert_eq!(full_key_arr[..].len(), CONTRACT_KEY_SIZE);
1150 let mut spec = [0; CONTRACT_KEY_SIZE];
1151 spec.copy_from_slice(&full_key_arr);
1152 ContractInstanceId(spec)
1153}
1154
1155#[inline]
1156fn internal_fmt_key(
1157 key: &[u8; CONTRACT_KEY_SIZE],
1158 f: &mut std::fmt::Formatter<'_>,
1159) -> std::fmt::Result {
1160 let r = bs58::encode(key)
1161 .with_alphabet(bs58::Alphabet::BITCOIN)
1162 .into_string();
1163 write!(f, "{}", &r[..8])
1164}
1165
1166#[derive(PartialEq, Eq, Clone, serde::Serialize, serde::Deserialize)]
1169#[cfg_attr(feature = "testing", derive(arbitrary::Arbitrary))]
1170pub struct WrappedState(
1171 #[serde(
1172 serialize_with = "WrappedState::ser_state",
1173 deserialize_with = "WrappedState::deser_state"
1174 )]
1175 Arc<Vec<u8>>,
1176);
1177
1178impl WrappedState {
1179 pub fn new(bytes: Vec<u8>) -> Self {
1180 WrappedState(Arc::new(bytes))
1181 }
1182
1183 pub fn size(&self) -> usize {
1184 self.0.len()
1185 }
1186
1187 fn ser_state<S>(data: &Arc<Vec<u8>>, ser: S) -> Result<S::Ok, S::Error>
1188 where
1189 S: serde::Serializer,
1190 {
1191 serde_bytes::serialize(&**data, ser)
1192 }
1193
1194 fn deser_state<'de, D>(deser: D) -> Result<Arc<Vec<u8>>, D::Error>
1195 where
1196 D: Deserializer<'de>,
1197 {
1198 let data: Vec<u8> = serde_bytes::deserialize(deser)?;
1199 Ok(Arc::new(data))
1200 }
1201}
1202
1203impl From<Vec<u8>> for WrappedState {
1204 fn from(bytes: Vec<u8>) -> Self {
1205 Self::new(bytes)
1206 }
1207}
1208
1209impl From<&'_ [u8]> for WrappedState {
1210 fn from(bytes: &[u8]) -> Self {
1211 Self::new(bytes.to_owned())
1212 }
1213}
1214
1215impl AsRef<[u8]> for WrappedState {
1216 fn as_ref(&self) -> &[u8] {
1217 self.0.as_ref()
1218 }
1219}
1220
1221impl Deref for WrappedState {
1222 type Target = [u8];
1223
1224 fn deref(&self) -> &Self::Target {
1225 &self.0
1226 }
1227}
1228
1229impl Borrow<[u8]> for WrappedState {
1230 fn borrow(&self) -> &[u8] {
1231 &self.0
1232 }
1233}
1234
1235impl From<WrappedState> for State<'static> {
1236 fn from(value: WrappedState) -> Self {
1237 match Arc::try_unwrap(value.0) {
1238 Ok(v) => State::from(v),
1239 Err(v) => State::from(v.as_ref().to_vec()),
1240 }
1241 }
1242}
1243
1244impl std::fmt::Display for WrappedState {
1245 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1246 write!(f, "ContractState(data: [0x")?;
1247 for b in self.0.iter().take(8) {
1248 write!(f, "{:02x}", b)?;
1249 }
1250 write!(f, "...])")
1251 }
1252}
1253
1254impl std::fmt::Debug for WrappedState {
1255 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1256 <Self as Display>::fmt(self, f)
1257 }
1258}
1259
1260#[non_exhaustive]
1262#[derive(Clone, Debug, Serialize, Deserialize)]
1263pub struct WrappedContract {
1264 #[serde(
1265 serialize_with = "WrappedContract::ser_contract_data",
1266 deserialize_with = "WrappedContract::deser_contract_data"
1267 )]
1268 pub data: Arc<ContractCode<'static>>,
1269 #[serde(deserialize_with = "Parameters::deser_params")]
1270 pub params: Parameters<'static>,
1271 pub key: ContractKey,
1272}
1273
1274impl PartialEq for WrappedContract {
1275 fn eq(&self, other: &Self) -> bool {
1276 self.key == other.key
1277 }
1278}
1279
1280impl Eq for WrappedContract {}
1281
1282impl WrappedContract {
1283 pub fn new(data: Arc<ContractCode<'static>>, params: Parameters<'static>) -> WrappedContract {
1284 let key = ContractKey::from_params_and_code(¶ms, &*data);
1285 WrappedContract { data, params, key }
1286 }
1287
1288 #[inline]
1289 pub fn key(&self) -> &ContractKey {
1290 &self.key
1291 }
1292
1293 #[inline]
1294 pub fn code(&self) -> &Arc<ContractCode<'static>> {
1295 &self.data
1296 }
1297
1298 #[inline]
1299 pub fn params(&self) -> &Parameters<'static> {
1300 &self.params
1301 }
1302
1303 fn ser_contract_data<S>(data: &Arc<ContractCode<'_>>, ser: S) -> Result<S::Ok, S::Error>
1304 where
1305 S: serde::Serializer,
1306 {
1307 data.serialize(ser)
1308 }
1309
1310 fn deser_contract_data<'de, D>(deser: D) -> Result<Arc<ContractCode<'static>>, D::Error>
1311 where
1312 D: Deserializer<'de>,
1313 {
1314 let data: ContractCode<'de> = Deserialize::deserialize(deser)?;
1315 Ok(Arc::new(data.into_owned()))
1316 }
1317}
1318
1319impl TryInto<Vec<u8>> for WrappedContract {
1320 type Error = ();
1321 fn try_into(self) -> Result<Vec<u8>, Self::Error> {
1322 Arc::try_unwrap(self.data)
1323 .map(|r| r.into_bytes())
1324 .map_err(|_| ())
1325 }
1326}
1327
1328impl Display for WrappedContract {
1329 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1330 self.key.fmt(f)
1331 }
1332}
1333
1334#[cfg(feature = "testing")]
1335impl<'a> arbitrary::Arbitrary<'a> for WrappedContract {
1336 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
1337 use arbitrary::Arbitrary;
1338 let data = <ContractCode as Arbitrary>::arbitrary(u)?.into_owned();
1339 let param_bytes: Vec<u8> = Arbitrary::arbitrary(u)?;
1340 let params = Parameters::from(param_bytes);
1341 let key = ContractKey::from_params_and_code(¶ms, &data);
1342 Ok(Self {
1343 data: Arc::new(data),
1344 params,
1345 key,
1346 })
1347 }
1348}
1349
1350#[doc(hidden)]
1351pub(crate) mod wasm_interface {
1352 use super::*;
1355 use crate::memory::WasmLinearMem;
1356
1357 #[repr(i32)]
1358 enum ResultKind {
1359 ValidateState = 0,
1360 ValidateDelta = 1,
1361 UpdateState = 2,
1362 SummarizeState = 3,
1363 StateDelta = 4,
1364 }
1365
1366 impl From<i32> for ResultKind {
1367 fn from(v: i32) -> Self {
1368 match v {
1369 0 => ResultKind::ValidateState,
1370 1 => ResultKind::ValidateDelta,
1371 2 => ResultKind::UpdateState,
1372 3 => ResultKind::SummarizeState,
1373 4 => ResultKind::StateDelta,
1374 _ => panic!(),
1375 }
1376 }
1377 }
1378
1379 #[doc(hidden)]
1380 #[repr(C)]
1381 #[derive(Debug, Clone, Copy)]
1382 pub struct ContractInterfaceResult {
1383 ptr: i64,
1384 kind: i32,
1385 size: u32,
1386 }
1387
1388 impl ContractInterfaceResult {
1389 pub unsafe fn unwrap_validate_state_res(
1390 self,
1391 mem: WasmLinearMem,
1392 ) -> Result<ValidateResult, ContractError> {
1393 #![allow(clippy::let_and_return)]
1394 let kind = ResultKind::from(self.kind);
1395 match kind {
1396 ResultKind::ValidateState => {
1397 let ptr = crate::memory::buf::compute_ptr(self.ptr as *mut u8, &mem);
1398 let serialized = std::slice::from_raw_parts(ptr as *const u8, self.size as _);
1399 let value = bincode::deserialize(serialized)
1400 .map_err(|e| ContractError::Other(format!("{e}")))?;
1401 #[cfg(feature = "trace")]
1402 self.log_input(serialized, &value, ptr);
1403 value
1404 }
1405 _ => unreachable!(),
1406 }
1407 }
1408
1409 pub unsafe fn unwrap_update_state(
1410 self,
1411 mem: WasmLinearMem,
1412 ) -> Result<UpdateModification<'static>, ContractError> {
1413 let kind = ResultKind::from(self.kind);
1414 match kind {
1415 ResultKind::UpdateState => {
1416 let ptr = crate::memory::buf::compute_ptr(self.ptr as *mut u8, &mem);
1417 let serialized = std::slice::from_raw_parts(ptr as *const u8, self.size as _);
1418 let value: Result<UpdateModification<'_>, ContractError> =
1419 bincode::deserialize(serialized)
1420 .map_err(|e| ContractError::Other(format!("{e}")))?;
1421 #[cfg(feature = "trace")]
1422 self.log_input(serialized, &value, ptr);
1423 value.map(|r| r.into_owned())
1426 }
1427 _ => unreachable!(),
1428 }
1429 }
1430
1431 pub unsafe fn unwrap_summarize_state(
1432 self,
1433 mem: WasmLinearMem,
1434 ) -> Result<StateSummary<'static>, ContractError> {
1435 let kind = ResultKind::from(self.kind);
1436 match kind {
1437 ResultKind::SummarizeState => {
1438 let ptr = crate::memory::buf::compute_ptr(self.ptr as *mut u8, &mem);
1439 let serialized = std::slice::from_raw_parts(ptr as *const u8, self.size as _);
1440 let value: Result<StateSummary<'static>, ContractError> =
1441 bincode::deserialize(serialized)
1442 .map_err(|e| ContractError::Other(format!("{e}")))?;
1443 #[cfg(feature = "trace")]
1444 self.log_input(serialized, &value, ptr);
1445 value.map(|s| StateSummary::from(s.into_bytes()))
1448 }
1449 _ => unreachable!(),
1450 }
1451 }
1452
1453 pub unsafe fn unwrap_get_state_delta(
1454 self,
1455 mem: WasmLinearMem,
1456 ) -> Result<StateDelta<'static>, ContractError> {
1457 let kind = ResultKind::from(self.kind);
1458 match kind {
1459 ResultKind::StateDelta => {
1460 let ptr = crate::memory::buf::compute_ptr(self.ptr as *mut u8, &mem);
1461 let serialized = std::slice::from_raw_parts(ptr as *const u8, self.size as _);
1462 let value: Result<StateDelta<'static>, ContractError> =
1463 bincode::deserialize(serialized)
1464 .map_err(|e| ContractError::Other(format!("{e}")))?;
1465 #[cfg(feature = "trace")]
1466 self.log_input(serialized, &value, ptr);
1467 value.map(|d| StateDelta::from(d.into_bytes()))
1470 }
1471 _ => unreachable!(),
1472 }
1473 }
1474
1475 #[cfg(feature = "contract")]
1476 pub fn into_raw(self) -> i64 {
1477 #[cfg(feature = "trace")]
1478 {
1479 tracing::trace!("returning FFI -> {self:?}");
1480 }
1481 let ptr = Box::into_raw(Box::new(self));
1482 #[cfg(feature = "trace")]
1483 {
1484 tracing::trace!("FFI result ptr: {ptr:p} ({}i64)", ptr as i64);
1485 }
1486 ptr as _
1487 }
1488
1489 pub unsafe fn from_raw(ptr: i64, mem: &WasmLinearMem) -> Self {
1490 let result = Box::leak(Box::from_raw(crate::memory::buf::compute_ptr(
1491 ptr as *mut Self,
1492 mem,
1493 )));
1494 #[cfg(feature = "trace")]
1495 {
1496 tracing::trace!(
1497 "got FFI result @ {ptr} ({:p}) -> {result:?}",
1498 ptr as *mut Self
1499 );
1500 }
1501 *result
1502 }
1503
1504 #[cfg(feature = "trace")]
1505 fn log_input<T: std::fmt::Debug>(&self, serialized: &[u8], value: &T, ptr: *mut u8) {
1506 tracing::trace!(
1507 "got result through FFI; addr: {:p} ({}i64, mapped: {ptr:p})
1508 serialized: {serialized:?}
1509 value: {value:?}",
1510 self.ptr as *mut u8,
1511 self.ptr
1512 );
1513 }
1514 }
1515
1516 #[cfg(feature = "contract")]
1517 macro_rules! conversion {
1518 ($value:ty: $kind:expr) => {
1519 impl From<$value> for ContractInterfaceResult {
1520 fn from(value: $value) -> Self {
1521 let kind = $kind as i32;
1522 let serialized = bincode::serialize(&value).unwrap();
1526 let size = serialized.len() as _;
1527 let ptr = serialized.as_ptr();
1528 #[cfg(feature = "trace")] {
1529 tracing::trace!(
1530 "sending result through FFI; addr: {ptr:p} ({}),\n serialized: {serialized:?}\n value: {value:?}",
1531 ptr as i64
1532 );
1533 }
1534 std::mem::forget(serialized);
1535 Self { kind, ptr: ptr as i64, size }
1536 }
1537 }
1538 };
1539 }
1540
1541 #[cfg(feature = "contract")]
1542 conversion!(Result<ValidateResult, ContractError>: ResultKind::ValidateState);
1543 #[cfg(feature = "contract")]
1544 conversion!(Result<bool, ContractError>: ResultKind::ValidateDelta);
1545 #[cfg(feature = "contract")]
1546 conversion!(Result<UpdateModification<'static>, ContractError>: ResultKind::UpdateState);
1547 #[cfg(feature = "contract")]
1548 conversion!(Result<StateSummary<'static>, ContractError>: ResultKind::SummarizeState);
1549 #[cfg(feature = "contract")]
1550 conversion!(Result<StateDelta<'static>, ContractError>: ResultKind::StateDelta);
1551}
1552
1553#[cfg(all(test, any(unix, windows)))]
1554mod test {
1555 use super::*;
1556 use once_cell::sync::Lazy;
1557 use rand::{rngs::SmallRng, Rng, SeedableRng};
1558
1559 static RND_BYTES: Lazy<[u8; 1024]> = Lazy::new(|| {
1560 let mut bytes = [0; 1024];
1561 let mut rng = SmallRng::from_entropy();
1562 rng.fill(&mut bytes);
1563 bytes
1564 });
1565
1566 #[test]
1567 fn key_encoding() -> Result<(), Box<dyn std::error::Error>> {
1568 let code = ContractCode::from(vec![1, 2, 3]);
1569 let expected = ContractKey::from_params_and_code(Parameters::from(vec![]), &code);
1570 let decoded = ContractKey::from_params(code.hash_str(), [].as_ref().into())?;
1576 assert_eq!(expected, decoded);
1577 assert_eq!(expected.code_hash(), decoded.code_hash());
1578 Ok(())
1579 }
1580
1581 #[test]
1582 fn key_ser() -> Result<(), Box<dyn std::error::Error>> {
1583 let mut gen = arbitrary::Unstructured::new(&*RND_BYTES);
1584 let expected: ContractKey = gen.arbitrary()?;
1585 let encoded = bs58::encode(expected.as_bytes()).into_string();
1586 let serialized = bincode::serialize(&expected)?;
1589 let deserialized: ContractKey = bincode::deserialize(&serialized)?;
1590 let decoded = bs58::encode(deserialized.as_bytes()).into_string();
1591 assert_eq!(encoded, decoded);
1592 assert_eq!(deserialized, expected);
1593 Ok(())
1594 }
1595
1596 #[test]
1597 fn contract_ser() -> Result<(), Box<dyn std::error::Error>> {
1598 let mut gen = arbitrary::Unstructured::new(&*RND_BYTES);
1599 let expected: Contract = gen.arbitrary()?;
1600
1601 let serialized = bincode::serialize(&expected)?;
1602 let deserialized: Contract = bincode::deserialize(&serialized)?;
1603 assert_eq!(deserialized, expected);
1604 Ok(())
1605 }
1606}
1607
1608pub mod encoding {
1609 use std::{collections::HashSet, marker::PhantomData};
1611
1612 use serde::de::DeserializeOwned;
1613
1614 use super::*;
1615
1616 pub enum MergeResult {
1617 Success,
1618 RequestRelated(RelatedContractsContainer),
1619 Error(ContractError),
1620 }
1621
1622 #[derive(Default)]
1623 pub struct RelatedContractsContainer {
1624 contracts: HashMap<ContractInstanceId, State<'static>>,
1625 pending: HashSet<ContractInstanceId>,
1626 not_found: HashSet<ContractInstanceId>,
1627 }
1628
1629 impl From<RelatedContracts<'static>> for RelatedContractsContainer {
1630 fn from(found: RelatedContracts<'static>) -> Self {
1631 let mut not_found = HashSet::new();
1632 let mut contracts = HashMap::with_capacity(found.map.len());
1633 for (id, state) in found.map.into_iter() {
1634 match state {
1635 Some(state) => {
1636 contracts.insert(id, state);
1637 }
1638 None => {
1639 not_found.insert(id);
1640 }
1641 }
1642 }
1643 RelatedContractsContainer {
1644 contracts,
1645 pending: HashSet::new(),
1646 not_found,
1647 }
1648 }
1649 }
1650
1651 impl From<RelatedContractsContainer> for Vec<crate::contract_interface::RelatedContract> {
1652 fn from(related: RelatedContractsContainer) -> Self {
1653 related
1654 .pending
1655 .into_iter()
1656 .map(|id| RelatedContract {
1657 contract_instance_id: id,
1658 mode: RelatedMode::StateOnce,
1659 })
1660 .collect()
1661 }
1662 }
1663
1664 impl From<Vec<UpdateData<'static>>> for RelatedContractsContainer {
1665 fn from(updates: Vec<UpdateData<'static>>) -> Self {
1666 let mut this = RelatedContractsContainer::default();
1667 for update in updates {
1668 match update {
1669 UpdateData::RelatedState { related_to, state } => {
1670 this.contracts.insert(related_to, state);
1671 }
1672 UpdateData::RelatedStateAndDelta {
1673 related_to, state, ..
1674 } => {
1675 this.contracts.insert(related_to, state);
1676 }
1677 _ => {}
1678 }
1679 }
1680 this
1681 }
1682 }
1683
1684 impl RelatedContractsContainer {
1685 pub fn get<C: TypedContract>(
1686 &self,
1687 params: &C::Parameters,
1688 ) -> Result<Related<C>, <<C as EncodingAdapter>::SelfEncoder as Encoder<C>>::Error>
1689 {
1690 let id = <C as TypedContract>::instance_id(params);
1691 if let Some(res) = self.contracts.get(&id) {
1692 match <<C as EncodingAdapter>::SelfEncoder>::deserialize(res.as_ref()) {
1693 Ok(state) => return Ok(Related::Found { state }),
1694 Err(err) => return Err(err),
1695 }
1696 }
1697 if self.pending.contains(&id) {
1698 return Ok(Related::RequestPending);
1699 }
1700 if self.not_found.contains(&id) {
1701 return Ok(Related::NotFound);
1702 }
1703 Ok(Related::NotRequested)
1704 }
1705
1706 pub fn request<C: TypedContract>(&mut self, id: ContractInstanceId) {
1707 self.pending.insert(id);
1708 }
1709
1710 pub fn merge(&mut self, other: Self) {
1711 let Self {
1712 contracts,
1713 pending,
1714 not_found,
1715 } = other;
1716 self.pending.extend(pending);
1717 self.not_found.extend(not_found);
1718 self.contracts.extend(contracts);
1719 }
1720 }
1721
1722 pub enum Related<C: TypedContract> {
1723 Found { state: C },
1725 NotFound,
1727 RequestPending,
1729 NotRequested,
1732 }
1733
1734 pub trait EncodingAdapter
1737 where
1738 Self: Sized,
1739 {
1740 type Parameters;
1741 type Delta;
1742 type Summary;
1743
1744 type SelfEncoder: Encoder<Self>;
1745 type ParametersEncoder: Encoder<Self::Parameters>;
1746 type DeltaEncoder: Encoder<Self::Delta>;
1747 type SummaryEncoder: Encoder<Self::Summary>;
1748 }
1749
1750 pub enum TypedUpdateData<T: EncodingAdapter> {
1751 RelatedState { state: T },
1752 RelatedDelta { delta: T::Delta },
1753 RelatedStateAndDelta { state: T, delta: T::Delta },
1754 }
1755
1756 impl<T: EncodingAdapter> TypedUpdateData<T> {
1757 pub fn from_other<Parent>(value: &TypedUpdateData<Parent>) -> Self
1758 where
1759 Parent: EncodingAdapter,
1760 T: for<'x> From<&'x Parent>,
1761 T::Delta: for<'x> From<&'x Parent::Delta>,
1762 {
1763 match value {
1764 TypedUpdateData::RelatedState { state } => {
1765 let state = T::from(state);
1766 TypedUpdateData::RelatedState { state }
1767 }
1768 TypedUpdateData::RelatedDelta { delta } => {
1769 let delta: T::Delta = <T as EncodingAdapter>::Delta::from(delta);
1770 TypedUpdateData::RelatedDelta { delta }
1771 }
1772 TypedUpdateData::RelatedStateAndDelta { state, delta } => {
1773 let state = T::from(state);
1774 let delta: T::Delta = <T as EncodingAdapter>::Delta::from(delta);
1775 TypedUpdateData::RelatedStateAndDelta { state, delta }
1776 }
1777 }
1778 }
1779 }
1780
1781 impl<T: EncodingAdapter> TryFrom<(Option<T>, Option<T::Delta>)> for TypedUpdateData<T> {
1782 type Error = ContractError;
1783 fn try_from((state, delta): (Option<T>, Option<T::Delta>)) -> Result<Self, Self::Error> {
1784 match (state, delta) {
1785 (None, None) => Err(ContractError::InvalidState),
1786 (None, Some(delta)) => Ok(Self::RelatedDelta { delta }),
1787 (Some(state), None) => Ok(Self::RelatedState { state }),
1788 (Some(state), Some(delta)) => Ok(Self::RelatedStateAndDelta { state, delta }),
1789 }
1790 }
1791 }
1792
1793 pub trait TypedContract: EncodingAdapter {
1794 fn instance_id(params: &Self::Parameters) -> ContractInstanceId;
1795
1796 fn verify(
1797 &self,
1798 parameters: Self::Parameters,
1799 related: RelatedContractsContainer,
1800 ) -> Result<ValidateResult, ContractError>;
1801
1802 fn merge(
1803 &mut self,
1804 parameters: &Self::Parameters,
1805 update: TypedUpdateData<Self>,
1806 related: &RelatedContractsContainer,
1807 ) -> MergeResult;
1808
1809 fn summarize(&self, parameters: Self::Parameters) -> Result<Self::Summary, ContractError>;
1810
1811 fn delta(
1812 &self,
1813 parameters: Self::Parameters,
1814 summary: Self::Summary,
1815 ) -> Result<Self::Delta, ContractError>;
1816 }
1817
1818 pub trait Encoder<T> {
1819 type Error: Into<ContractError>;
1820 fn deserialize(bytes: &[u8]) -> Result<T, Self::Error>;
1821 fn serialize(value: &T) -> Result<Vec<u8>, Self::Error>;
1822 }
1823
1824 pub struct JsonEncoder<T>(PhantomData<T>);
1825
1826 impl<T> Encoder<T> for JsonEncoder<T>
1827 where
1828 T: DeserializeOwned + Serialize,
1829 {
1830 type Error = serde_json::Error;
1831
1832 fn deserialize(bytes: &[u8]) -> Result<T, Self::Error> {
1833 serde_json::from_slice(bytes)
1834 }
1835
1836 fn serialize(value: &T) -> Result<Vec<u8>, Self::Error> {
1837 serde_json::to_vec(value)
1838 }
1839 }
1840
1841 impl From<serde_json::Error> for ContractError {
1842 fn from(value: serde_json::Error) -> Self {
1843 ContractError::Deser(format!("{value}"))
1844 }
1845 }
1846
1847 pub struct BincodeEncoder<T>(PhantomData<T>);
1848
1849 impl<T> Encoder<T> for BincodeEncoder<T>
1850 where
1851 T: DeserializeOwned + Serialize,
1852 {
1853 type Error = bincode::Error;
1854
1855 fn deserialize(bytes: &[u8]) -> Result<T, Self::Error> {
1856 bincode::deserialize(bytes)
1857 }
1858
1859 fn serialize(value: &T) -> Result<Vec<u8>, Self::Error> {
1860 bincode::serialize(value)
1861 }
1862 }
1863
1864 impl From<bincode::Error> for ContractError {
1865 fn from(value: bincode::Error) -> Self {
1866 ContractError::Deser(format!("{value}"))
1867 }
1868 }
1869
1870 pub fn inner_validate_state<T>(
1871 parameters: Parameters<'static>,
1872 state: State<'static>,
1873 related: RelatedContracts<'static>,
1874 ) -> Result<ValidateResult, ContractError>
1875 where
1876 T: EncodingAdapter + TypedContract,
1877 ContractError: From<
1878 <<T as EncodingAdapter>::ParametersEncoder as Encoder<
1879 <T as EncodingAdapter>::Parameters,
1880 >>::Error,
1881 >,
1882 ContractError: From<<<T as EncodingAdapter>::SelfEncoder as Encoder<T>>::Error>,
1883 {
1884 let typed_params =
1885 <<T as EncodingAdapter>::ParametersEncoder>::deserialize(parameters.as_ref())?;
1886 let typed_state = <<T as EncodingAdapter>::SelfEncoder>::deserialize(state.as_ref())?;
1887 let related_container = RelatedContractsContainer::from(related);
1888 typed_state.verify(typed_params, related_container)
1889 }
1890
1891 pub fn inner_update_state<T>(
1892 parameters: Parameters<'static>,
1893 state: State<'static>,
1894 data: Vec<UpdateData<'static>>,
1895 ) -> Result<UpdateModification<'static>, ContractError>
1896 where
1897 T: EncodingAdapter + TypedContract,
1898 ContractError: From<<<T as EncodingAdapter>::SelfEncoder as Encoder<T>>::Error>,
1899 ContractError: From<
1900 <<T as EncodingAdapter>::ParametersEncoder as Encoder<
1901 <T as EncodingAdapter>::Parameters,
1902 >>::Error,
1903 >,
1904 ContractError: From<
1905 <<T as EncodingAdapter>::DeltaEncoder as Encoder<<T as EncodingAdapter>::Delta>>::Error,
1906 >,
1907 {
1908 let typed_params =
1909 <<T as EncodingAdapter>::ParametersEncoder>::deserialize(parameters.as_ref())?;
1910 let mut typed_state = <<T as EncodingAdapter>::SelfEncoder>::deserialize(state.as_ref())?;
1911 let self_updates = UpdateData::get_self_states(&data);
1912 let related_container = RelatedContractsContainer::from(data);
1913 for (state, delta) in self_updates {
1914 let state = state
1915 .map(|s| <<T as EncodingAdapter>::SelfEncoder>::deserialize(s.as_ref()))
1916 .transpose()?;
1917 let delta = delta
1918 .map(|d| <<T as EncodingAdapter>::DeltaEncoder>::deserialize(d.as_ref()))
1919 .transpose()?;
1920 let typed_update = TypedUpdateData::try_from((state, delta))?;
1921 match typed_state.merge(&typed_params, typed_update, &related_container) {
1922 MergeResult::Success => {}
1923 MergeResult::RequestRelated(req) => {
1924 return UpdateModification::requires(req.into());
1925 }
1926 MergeResult::Error(err) => return Err(err),
1927 }
1928 }
1929 let encoded = <<T as EncodingAdapter>::SelfEncoder>::serialize(&typed_state)?;
1930 Ok(UpdateModification::valid(encoded.into()))
1931 }
1932
1933 pub fn inner_summarize_state<T>(
1934 parameters: Parameters<'static>,
1935 state: State<'static>,
1936 ) -> Result<StateSummary<'static>, ContractError>
1937 where
1938 T: EncodingAdapter + TypedContract,
1939 ContractError: From<<<T as EncodingAdapter>::SelfEncoder as Encoder<T>>::Error>,
1940 ContractError: From<
1941 <<T as EncodingAdapter>::ParametersEncoder as Encoder<
1942 <T as EncodingAdapter>::Parameters,
1943 >>::Error,
1944 >,
1945 ContractError:
1946 From<
1947 <<T as EncodingAdapter>::SummaryEncoder as Encoder<
1948 <T as EncodingAdapter>::Summary,
1949 >>::Error,
1950 >,
1951 {
1952 let typed_params =
1953 <<T as EncodingAdapter>::ParametersEncoder>::deserialize(parameters.as_ref())?;
1954 let typed_state = <<T as EncodingAdapter>::SelfEncoder>::deserialize(state.as_ref())?;
1955 let summary = typed_state.summarize(typed_params)?;
1956 let encoded = <<T as EncodingAdapter>::SummaryEncoder>::serialize(&summary)?;
1957 Ok(encoded.into())
1958 }
1959
1960 pub fn inner_state_delta<T>(
1961 parameters: Parameters<'static>,
1962 state: State<'static>,
1963 summary: StateSummary<'static>,
1964 ) -> Result<StateDelta<'static>, ContractError>
1965 where
1966 T: EncodingAdapter + TypedContract,
1967 ContractError: From<<<T as EncodingAdapter>::SelfEncoder as Encoder<T>>::Error>,
1968 ContractError: From<
1969 <<T as EncodingAdapter>::ParametersEncoder as Encoder<
1970 <T as EncodingAdapter>::Parameters,
1971 >>::Error,
1972 >,
1973 ContractError:
1974 From<
1975 <<T as EncodingAdapter>::SummaryEncoder as Encoder<
1976 <T as EncodingAdapter>::Summary,
1977 >>::Error,
1978 >,
1979 ContractError: From<
1980 <<T as EncodingAdapter>::DeltaEncoder as Encoder<<T as EncodingAdapter>::Delta>>::Error,
1981 >,
1982 {
1983 let typed_params =
1984 <<T as EncodingAdapter>::ParametersEncoder>::deserialize(parameters.as_ref())?;
1985 let typed_state = <<T as EncodingAdapter>::SelfEncoder>::deserialize(state.as_ref())?;
1986 let typed_summary =
1987 <<T as EncodingAdapter>::SummaryEncoder>::deserialize(summary.as_ref())?;
1988 let summary = typed_state.delta(typed_params, typed_summary)?;
1989 let encoded = <<T as EncodingAdapter>::DeltaEncoder>::serialize(&summary)?;
1990 Ok(encoded.into())
1991 }
1992}