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(feature = "testing", derive(arbitrary::Arbitrary))]
476pub struct Contract<'a> {
477 #[serde(borrow)]
478 pub parameters: Parameters<'a>,
479 #[serde(borrow)]
480 pub data: ContractCode<'a>,
481 key: ContractKey,
483}
484
485impl<'a> Contract<'a> {
486 pub fn new(contract: ContractCode<'a>, parameters: Parameters<'a>) -> Contract<'a> {
488 let key = ContractKey::from_params_and_code(¶meters, &contract);
489 Contract {
490 parameters,
491 data: contract,
492 key,
493 }
494 }
495
496 pub fn key(&self) -> &ContractKey {
498 &self.key
499 }
500
501 pub fn into_code(self) -> ContractCode<'a> {
503 self.data
504 }
505}
506
507impl TryFrom<Vec<u8>> for Contract<'static> {
508 type Error = std::io::Error;
509
510 fn try_from(data: Vec<u8>) -> Result<Self, Self::Error> {
511 let mut reader = Cursor::new(data);
512
513 let params_len = reader.read_u64::<LittleEndian>()?;
514 let mut params_buf = vec![0; params_len as usize];
515 reader.read_exact(&mut params_buf)?;
516 let parameters = Parameters::from(params_buf);
517
518 let contract_len = reader.read_u64::<LittleEndian>()?;
519 let mut contract_buf = vec![0; contract_len as usize];
520 reader.read_exact(&mut contract_buf)?;
521 let contract = ContractCode::from(contract_buf);
522
523 let key = ContractKey::from_params_and_code(¶meters, &contract);
524
525 Ok(Contract {
526 parameters,
527 data: contract,
528 key,
529 })
530 }
531}
532
533impl PartialEq for Contract<'_> {
534 fn eq(&self, other: &Self) -> bool {
535 self.key == other.key
536 }
537}
538
539impl Eq for Contract<'_> {}
540
541impl std::fmt::Display for Contract<'_> {
542 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
543 write!(f, "ContractSpec( key: ")?;
544 internal_fmt_key(&self.key.instance.0, f)?;
545 let data: String = if self.data.data.len() > 8 {
546 self.data.data[..4]
547 .iter()
548 .map(|b| char::from(*b))
549 .chain("...".chars())
550 .chain(self.data.data[4..].iter().map(|b| char::from(*b)))
551 .collect()
552 } else {
553 self.data.data.iter().copied().map(char::from).collect()
554 };
555 write!(f, ", data: [{data}])")
556 }
557}
558
559#[serde_as]
563#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
564#[cfg_attr(feature = "testing", derive(arbitrary::Arbitrary))]
565pub struct State<'a>(
566 #[serde_as(as = "serde_with::Bytes")]
568 #[serde(borrow)]
569 Cow<'a, [u8]>,
570);
571
572impl State<'_> {
573 pub fn size(&self) -> usize {
575 self.0.len()
576 }
577
578 pub fn into_owned(self) -> State<'static> {
579 State(self.0.into_owned().into())
580 }
581
582 pub fn into_bytes(self) -> Vec<u8> {
584 self.0.into_owned()
585 }
586
587 pub fn to_mut(&mut self) -> &mut Vec<u8> {
589 self.0.to_mut()
590 }
591}
592
593impl From<Vec<u8>> for State<'_> {
594 fn from(state: Vec<u8>) -> Self {
595 State(Cow::from(state))
596 }
597}
598
599impl<'a> From<&'a [u8]> for State<'a> {
600 fn from(state: &'a [u8]) -> Self {
601 State(Cow::from(state))
602 }
603}
604
605impl AsRef<[u8]> for State<'_> {
606 fn as_ref(&self) -> &[u8] {
607 match &self.0 {
608 Cow::Borrowed(arr) => arr,
609 Cow::Owned(arr) => arr.as_ref(),
610 }
611 }
612}
613
614impl<'a> Deref for State<'a> {
615 type Target = Cow<'a, [u8]>;
616
617 fn deref(&self) -> &Self::Target {
618 &self.0
619 }
620}
621
622impl DerefMut for State<'_> {
623 fn deref_mut(&mut self) -> &mut Self::Target {
624 &mut self.0
625 }
626}
627
628impl std::io::Read for State<'_> {
629 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
630 self.as_ref().read(buf)
631 }
632}
633
634#[serde_as]
641#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
642#[cfg_attr(feature = "testing", derive(arbitrary::Arbitrary))]
643pub struct StateDelta<'a>(
644 #[serde_as(as = "serde_with::Bytes")]
646 #[serde(borrow)]
647 Cow<'a, [u8]>,
648);
649
650impl StateDelta<'_> {
651 pub fn size(&self) -> usize {
653 self.0.len()
654 }
655
656 pub fn into_bytes(self) -> Vec<u8> {
658 self.0.into_owned()
659 }
660
661 pub fn into_owned(self) -> StateDelta<'static> {
662 StateDelta(self.0.into_owned().into())
663 }
664}
665
666impl From<Vec<u8>> for StateDelta<'_> {
667 fn from(delta: Vec<u8>) -> Self {
668 StateDelta(Cow::from(delta))
669 }
670}
671
672impl<'a> From<&'a [u8]> for StateDelta<'a> {
673 fn from(delta: &'a [u8]) -> Self {
674 StateDelta(Cow::from(delta))
675 }
676}
677
678impl AsRef<[u8]> for StateDelta<'_> {
679 fn as_ref(&self) -> &[u8] {
680 match &self.0 {
681 Cow::Borrowed(arr) => arr,
682 Cow::Owned(arr) => arr.as_ref(),
683 }
684 }
685}
686
687impl<'a> Deref for StateDelta<'a> {
688 type Target = Cow<'a, [u8]>;
689
690 fn deref(&self) -> &Self::Target {
691 &self.0
692 }
693}
694
695impl DerefMut for StateDelta<'_> {
696 fn deref_mut(&mut self) -> &mut Self::Target {
697 &mut self.0
698 }
699}
700
701#[serde_as]
707#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
708#[cfg_attr(feature = "testing", derive(arbitrary::Arbitrary))]
709pub struct StateSummary<'a>(
710 #[serde_as(as = "serde_with::Bytes")]
712 #[serde(borrow)]
713 Cow<'a, [u8]>,
714);
715
716impl StateSummary<'_> {
717 pub fn into_bytes(self) -> Vec<u8> {
719 self.0.into_owned()
720 }
721
722 pub fn size(&self) -> usize {
724 self.0.len()
725 }
726
727 pub fn into_owned(self) -> StateSummary<'static> {
728 StateSummary(self.0.into_owned().into())
729 }
730
731 pub fn deser_state_summary<'de, D>(deser: D) -> Result<StateSummary<'static>, D::Error>
732 where
733 D: serde::Deserializer<'de>,
734 {
735 let value = <StateSummary as Deserialize>::deserialize(deser)?;
736 Ok(value.into_owned())
737 }
738}
739
740impl From<Vec<u8>> for StateSummary<'_> {
741 fn from(state: Vec<u8>) -> Self {
742 StateSummary(Cow::from(state))
743 }
744}
745
746impl<'a> From<&'a [u8]> for StateSummary<'a> {
747 fn from(state: &'a [u8]) -> Self {
748 StateSummary(Cow::from(state))
749 }
750}
751
752impl AsRef<[u8]> for StateSummary<'_> {
753 fn as_ref(&self) -> &[u8] {
754 match &self.0 {
755 Cow::Borrowed(arr) => arr,
756 Cow::Owned(arr) => arr.as_ref(),
757 }
758 }
759}
760
761impl<'a> Deref for StateSummary<'a> {
762 type Target = Cow<'a, [u8]>;
763
764 fn deref(&self) -> &Self::Target {
765 &self.0
766 }
767}
768
769impl DerefMut for StateSummary<'_> {
770 fn deref_mut(&mut self) -> &mut Self::Target {
771 &mut self.0
772 }
773}
774
775#[serde_as]
780#[derive(Serialize, Deserialize, Clone)]
781#[cfg_attr(feature = "testing", derive(arbitrary::Arbitrary))]
782pub struct ContractCode<'a> {
783 #[serde_as(as = "serde_with::Bytes")]
785 #[serde(borrow)]
786 pub(crate) data: Cow<'a, [u8]>,
787 pub(crate) code_hash: CodeHash,
789}
790
791impl ContractCode<'static> {
792 pub fn load_raw(path: &Path) -> Result<Self, std::io::Error> {
794 let contract_data = Self::load_bytes(path)?;
795 Ok(ContractCode::from(contract_data))
796 }
797
798 pub(crate) fn load_bytes(path: &Path) -> Result<Vec<u8>, std::io::Error> {
799 let mut contract_file = File::open(path)?;
800 let mut contract_data = if let Ok(md) = contract_file.metadata() {
801 Vec::with_capacity(md.len() as usize)
802 } else {
803 Vec::new()
804 };
805 contract_file.read_to_end(&mut contract_data)?;
806 Ok(contract_data)
807 }
808}
809
810impl ContractCode<'_> {
811 pub fn hash(&self) -> &CodeHash {
813 &self.code_hash
814 }
815
816 pub fn hash_str(&self) -> String {
818 Self::encode_hash(&self.code_hash.0)
819 }
820
821 pub fn data(&self) -> &[u8] {
823 &self.data
824 }
825
826 pub fn into_bytes(self) -> Vec<u8> {
828 self.data.to_vec()
829 }
830
831 pub fn encode_hash(hash: &[u8; CONTRACT_KEY_SIZE]) -> String {
833 bs58::encode(hash)
834 .with_alphabet(bs58::Alphabet::BITCOIN)
835 .into_string()
836 }
837
838 pub fn into_owned(self) -> ContractCode<'static> {
840 ContractCode {
841 data: self.data.into_owned().into(),
842 code_hash: self.code_hash,
843 }
844 }
845
846 fn gen_hash(data: &[u8]) -> CodeHash {
847 let mut hasher = Blake3::new();
848 hasher.update(data);
849 let key_arr = hasher.finalize();
850 debug_assert_eq!(key_arr[..].len(), CONTRACT_KEY_SIZE);
851 let mut key = [0; CONTRACT_KEY_SIZE];
852 key.copy_from_slice(&key_arr);
853 CodeHash(key)
854 }
855}
856
857impl From<Vec<u8>> for ContractCode<'static> {
858 fn from(data: Vec<u8>) -> Self {
859 let key = ContractCode::gen_hash(&data);
860 ContractCode {
861 data: Cow::from(data),
862 code_hash: key,
863 }
864 }
865}
866
867impl<'a> From<&'a [u8]> for ContractCode<'a> {
868 fn from(data: &'a [u8]) -> ContractCode<'a> {
869 let hash = ContractCode::gen_hash(data);
870 ContractCode {
871 data: Cow::from(data),
872 code_hash: hash,
873 }
874 }
875}
876
877impl PartialEq for ContractCode<'_> {
878 fn eq(&self, other: &Self) -> bool {
879 self.code_hash == other.code_hash
880 }
881}
882
883impl Eq for ContractCode<'_> {}
884
885impl std::fmt::Display for ContractCode<'_> {
886 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
887 write!(f, "Contract( key: ")?;
888 internal_fmt_key(&self.code_hash.0, f)?;
889 let data: String = if self.data.len() > 8 {
890 self.data[..4]
891 .iter()
892 .map(|b| char::from(*b))
893 .chain("...".chars())
894 .chain(self.data[4..].iter().map(|b| char::from(*b)))
895 .collect()
896 } else {
897 self.data.iter().copied().map(char::from).collect()
898 };
899 write!(f, ", data: [{data}])")
900 }
901}
902
903impl std::fmt::Debug for ContractCode<'_> {
904 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
905 f.debug_struct("ContractCode")
906 .field("hash", &self.code_hash);
907 Ok(())
908 }
909}
910
911#[serde_as]
913#[derive(PartialEq, Eq, Clone, Copy, Serialize, Deserialize, Hash)]
914#[cfg_attr(feature = "testing", derive(arbitrary::Arbitrary))]
915#[repr(transparent)]
916pub struct ContractInstanceId(#[serde_as(as = "[_; CONTRACT_KEY_SIZE]")] [u8; CONTRACT_KEY_SIZE]);
917
918impl ContractInstanceId {
919 pub fn from_params_and_code<'a>(
920 params: impl Borrow<Parameters<'a>>,
921 code: impl Borrow<ContractCode<'a>>,
922 ) -> Self {
923 generate_id(params.borrow(), code.borrow())
924 }
925
926 pub const fn new(key: [u8; CONTRACT_KEY_SIZE]) -> Self {
927 Self(key)
928 }
929
930 pub fn encode(&self) -> String {
932 bs58::encode(self.0)
933 .with_alphabet(bs58::Alphabet::BITCOIN)
934 .into_string()
935 }
936
937 pub fn as_bytes(&self) -> &[u8] {
938 self.0.as_slice()
939 }
940
941 pub fn from_bytes(bytes: impl AsRef<[u8]>) -> Result<Self, bs58::decode::Error> {
943 let mut spec = [0; CONTRACT_KEY_SIZE];
944 bs58::decode(bytes)
945 .with_alphabet(bs58::Alphabet::BITCOIN)
946 .onto(&mut spec)?;
947 Ok(Self(spec))
948 }
949}
950
951impl Deref for ContractInstanceId {
952 type Target = [u8; CONTRACT_KEY_SIZE];
953
954 fn deref(&self) -> &Self::Target {
955 &self.0
956 }
957}
958
959impl FromStr for ContractInstanceId {
960 type Err = bs58::decode::Error;
961
962 fn from_str(s: &str) -> Result<Self, Self::Err> {
963 ContractInstanceId::from_bytes(s)
964 }
965}
966
967impl TryFrom<String> for ContractInstanceId {
968 type Error = bs58::decode::Error;
969
970 fn try_from(s: String) -> Result<Self, Self::Error> {
971 ContractInstanceId::from_bytes(s)
972 }
973}
974
975impl Display for ContractInstanceId {
976 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
977 write!(f, "{}", self.encode())
978 }
979}
980
981impl std::fmt::Debug for ContractInstanceId {
982 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
983 f.debug_tuple("ContractInstanceId")
984 .field(&self.encode())
985 .finish()
986 }
987}
988
989#[serde_as]
991#[derive(Debug, Eq, Copy, Clone, Serialize, Deserialize)]
992#[cfg_attr(feature = "testing", derive(arbitrary::Arbitrary))]
993pub struct ContractKey {
994 instance: ContractInstanceId,
995 code: Option<CodeHash>,
996}
997
998impl ContractKey {
999 pub fn from_params_and_code<'a>(
1000 params: impl Borrow<Parameters<'a>>,
1001 wasm_code: impl Borrow<ContractCode<'a>>,
1002 ) -> Self {
1003 let code = wasm_code.borrow();
1004 let id = generate_id(params.borrow(), code);
1005 let code_hash = code.hash();
1006 Self {
1007 instance: id,
1008 code: Some(*code_hash),
1009 }
1010 }
1011
1012 pub fn from_id(instance: impl Into<String>) -> Result<Self, bs58::decode::Error> {
1014 let instance = ContractInstanceId::try_from(instance.into())?;
1015 Ok(Self {
1016 instance,
1017 code: None,
1018 })
1019 }
1020
1021 pub fn as_bytes(&self) -> &[u8] {
1023 self.instance.0.as_ref()
1024 }
1025
1026 pub fn code_hash(&self) -> Option<&CodeHash> {
1028 self.code.as_ref()
1029 }
1030
1031 pub fn encoded_code_hash(&self) -> Option<String> {
1033 self.code.as_ref().map(|c| {
1034 bs58::encode(c.0)
1035 .with_alphabet(bs58::Alphabet::BITCOIN)
1036 .into_string()
1037 })
1038 }
1039
1040 pub fn from_params(
1043 code_hash: impl Into<String>,
1044 parameters: Parameters,
1045 ) -> Result<Self, bs58::decode::Error> {
1046 let mut code_key = [0; CONTRACT_KEY_SIZE];
1047 bs58::decode(code_hash.into())
1048 .with_alphabet(bs58::Alphabet::BITCOIN)
1049 .onto(&mut code_key)?;
1050
1051 let mut hasher = Blake3::new();
1052 hasher.update(code_key.as_slice());
1053 hasher.update(parameters.as_ref());
1054 let full_key_arr = hasher.finalize();
1055
1056 let mut spec = [0; CONTRACT_KEY_SIZE];
1057 spec.copy_from_slice(&full_key_arr);
1058 Ok(Self {
1059 instance: ContractInstanceId(spec),
1060 code: Some(CodeHash(code_key)),
1061 })
1062 }
1063
1064 pub fn encoded_contract_id(&self) -> String {
1066 self.instance.encode()
1067 }
1068
1069 pub fn id(&self) -> &ContractInstanceId {
1070 &self.instance
1071 }
1072}
1073
1074impl PartialEq for ContractKey {
1075 fn eq(&self, other: &Self) -> bool {
1076 self.instance == other.instance
1077 }
1078}
1079
1080impl std::hash::Hash for ContractKey {
1081 fn hash<H: Hasher>(&self, state: &mut H) {
1082 self.instance.0.hash(state);
1083 }
1084}
1085
1086impl From<ContractInstanceId> for ContractKey {
1087 fn from(instance: ContractInstanceId) -> Self {
1088 Self {
1089 instance,
1090 code: None,
1091 }
1092 }
1093}
1094
1095impl From<ContractKey> for ContractInstanceId {
1096 fn from(key: ContractKey) -> Self {
1097 key.instance
1098 }
1099}
1100
1101impl Deref for ContractKey {
1102 type Target = [u8; CONTRACT_KEY_SIZE];
1103
1104 fn deref(&self) -> &Self::Target {
1105 &self.instance.0
1106 }
1107}
1108
1109impl std::fmt::Display for ContractKey {
1110 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1111 self.instance.fmt(f)
1112 }
1113}
1114
1115impl<'a> TryFromFbs<&FbsContractKey<'a>> for ContractKey {
1116 fn try_decode_fbs(key: &FbsContractKey<'a>) -> Result<Self, WsApiError> {
1117 let key_bytes: [u8; CONTRACT_KEY_SIZE] = key.instance().data().bytes().try_into().unwrap();
1118 let instance = ContractInstanceId::new(key_bytes);
1119 let code = key
1120 .code()
1121 .map(|code_hash| CodeHash::from_code(code_hash.bytes()));
1122 Ok(ContractKey { instance, code })
1123 }
1124}
1125
1126fn generate_id<'a>(
1127 parameters: &Parameters<'a>,
1128 code_data: &ContractCode<'a>,
1129) -> ContractInstanceId {
1130 let contract_hash = code_data.hash();
1131
1132 let mut hasher = Blake3::new();
1133 hasher.update(contract_hash.0.as_slice());
1134 hasher.update(parameters.as_ref());
1135 let full_key_arr = hasher.finalize();
1136
1137 debug_assert_eq!(full_key_arr[..].len(), CONTRACT_KEY_SIZE);
1138 let mut spec = [0; CONTRACT_KEY_SIZE];
1139 spec.copy_from_slice(&full_key_arr);
1140 ContractInstanceId(spec)
1141}
1142
1143#[inline]
1144fn internal_fmt_key(
1145 key: &[u8; CONTRACT_KEY_SIZE],
1146 f: &mut std::fmt::Formatter<'_>,
1147) -> std::fmt::Result {
1148 let r = bs58::encode(key)
1149 .with_alphabet(bs58::Alphabet::BITCOIN)
1150 .into_string();
1151 write!(f, "{}", &r[..8])
1152}
1153
1154#[derive(PartialEq, Eq, Clone, serde::Serialize, serde::Deserialize)]
1157#[cfg_attr(feature = "testing", derive(arbitrary::Arbitrary))]
1158pub struct WrappedState(
1159 #[serde(
1160 serialize_with = "WrappedState::ser_state",
1161 deserialize_with = "WrappedState::deser_state"
1162 )]
1163 Arc<Vec<u8>>,
1164);
1165
1166impl WrappedState {
1167 pub fn new(bytes: Vec<u8>) -> Self {
1168 WrappedState(Arc::new(bytes))
1169 }
1170
1171 pub fn size(&self) -> usize {
1172 self.0.len()
1173 }
1174
1175 fn ser_state<S>(data: &Arc<Vec<u8>>, ser: S) -> Result<S::Ok, S::Error>
1176 where
1177 S: serde::Serializer,
1178 {
1179 serde_bytes::serialize(&**data, ser)
1180 }
1181
1182 fn deser_state<'de, D>(deser: D) -> Result<Arc<Vec<u8>>, D::Error>
1183 where
1184 D: Deserializer<'de>,
1185 {
1186 let data: Vec<u8> = serde_bytes::deserialize(deser)?;
1187 Ok(Arc::new(data))
1188 }
1189}
1190
1191impl From<Vec<u8>> for WrappedState {
1192 fn from(bytes: Vec<u8>) -> Self {
1193 Self::new(bytes)
1194 }
1195}
1196
1197impl From<&'_ [u8]> for WrappedState {
1198 fn from(bytes: &[u8]) -> Self {
1199 Self::new(bytes.to_owned())
1200 }
1201}
1202
1203impl AsRef<[u8]> for WrappedState {
1204 fn as_ref(&self) -> &[u8] {
1205 self.0.as_ref()
1206 }
1207}
1208
1209impl Deref for WrappedState {
1210 type Target = [u8];
1211
1212 fn deref(&self) -> &Self::Target {
1213 &self.0
1214 }
1215}
1216
1217impl Borrow<[u8]> for WrappedState {
1218 fn borrow(&self) -> &[u8] {
1219 &self.0
1220 }
1221}
1222
1223impl From<WrappedState> for State<'static> {
1224 fn from(value: WrappedState) -> Self {
1225 match Arc::try_unwrap(value.0) {
1226 Ok(v) => State::from(v),
1227 Err(v) => State::from(v.as_ref().to_vec()),
1228 }
1229 }
1230}
1231
1232impl std::fmt::Display for WrappedState {
1233 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1234 write!(f, "ContractState(data: [0x")?;
1235 for b in self.0.iter().take(8) {
1236 write!(f, "{:02x}", b)?;
1237 }
1238 write!(f, "...])")
1239 }
1240}
1241
1242impl std::fmt::Debug for WrappedState {
1243 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1244 <Self as Display>::fmt(self, f)
1245 }
1246}
1247
1248#[non_exhaustive]
1250#[derive(Clone, Debug, Serialize, Deserialize)]
1251pub struct WrappedContract {
1252 #[serde(
1253 serialize_with = "WrappedContract::ser_contract_data",
1254 deserialize_with = "WrappedContract::deser_contract_data"
1255 )]
1256 pub data: Arc<ContractCode<'static>>,
1257 #[serde(deserialize_with = "Parameters::deser_params")]
1258 pub params: Parameters<'static>,
1259 pub key: ContractKey,
1260}
1261
1262impl PartialEq for WrappedContract {
1263 fn eq(&self, other: &Self) -> bool {
1264 self.key == other.key
1265 }
1266}
1267
1268impl Eq for WrappedContract {}
1269
1270impl WrappedContract {
1271 pub fn new(data: Arc<ContractCode<'static>>, params: Parameters<'static>) -> WrappedContract {
1272 let key = ContractKey::from_params_and_code(¶ms, &*data);
1273 WrappedContract { data, params, key }
1274 }
1275
1276 #[inline]
1277 pub fn key(&self) -> &ContractKey {
1278 &self.key
1279 }
1280
1281 #[inline]
1282 pub fn code(&self) -> &Arc<ContractCode<'static>> {
1283 &self.data
1284 }
1285
1286 #[inline]
1287 pub fn params(&self) -> &Parameters<'static> {
1288 &self.params
1289 }
1290
1291 fn ser_contract_data<S>(data: &Arc<ContractCode<'_>>, ser: S) -> Result<S::Ok, S::Error>
1292 where
1293 S: serde::Serializer,
1294 {
1295 data.serialize(ser)
1296 }
1297
1298 fn deser_contract_data<'de, D>(deser: D) -> Result<Arc<ContractCode<'static>>, D::Error>
1299 where
1300 D: Deserializer<'de>,
1301 {
1302 let data: ContractCode<'de> = Deserialize::deserialize(deser)?;
1303 Ok(Arc::new(data.into_owned()))
1304 }
1305}
1306
1307impl TryInto<Vec<u8>> for WrappedContract {
1308 type Error = ();
1309 fn try_into(self) -> Result<Vec<u8>, Self::Error> {
1310 Arc::try_unwrap(self.data)
1311 .map(|r| r.into_bytes())
1312 .map_err(|_| ())
1313 }
1314}
1315
1316impl Display for WrappedContract {
1317 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1318 self.key.fmt(f)
1319 }
1320}
1321
1322#[cfg(feature = "testing")]
1323impl<'a> arbitrary::Arbitrary<'a> for WrappedContract {
1324 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
1325 use arbitrary::Arbitrary;
1326 let data = <ContractCode as Arbitrary>::arbitrary(u)?.into_owned();
1327 let param_bytes: Vec<u8> = Arbitrary::arbitrary(u)?;
1328 let params = Parameters::from(param_bytes);
1329 let key = ContractKey::from_params_and_code(¶ms, &data);
1330 Ok(Self {
1331 data: Arc::new(data),
1332 params,
1333 key,
1334 })
1335 }
1336}
1337
1338#[doc(hidden)]
1339pub(crate) mod wasm_interface {
1340 use super::*;
1343 use crate::memory::WasmLinearMem;
1344
1345 #[repr(i32)]
1346 enum ResultKind {
1347 ValidateState = 0,
1348 ValidateDelta = 1,
1349 UpdateState = 2,
1350 SummarizeState = 3,
1351 StateDelta = 4,
1352 }
1353
1354 impl From<i32> for ResultKind {
1355 fn from(v: i32) -> Self {
1356 match v {
1357 0 => ResultKind::ValidateState,
1358 1 => ResultKind::ValidateDelta,
1359 2 => ResultKind::UpdateState,
1360 3 => ResultKind::SummarizeState,
1361 4 => ResultKind::StateDelta,
1362 _ => panic!(),
1363 }
1364 }
1365 }
1366
1367 #[doc(hidden)]
1368 #[repr(C)]
1369 #[derive(Debug, Clone, Copy)]
1370 pub struct ContractInterfaceResult {
1371 ptr: i64,
1372 kind: i32,
1373 size: u32,
1374 }
1375
1376 impl ContractInterfaceResult {
1377 pub unsafe fn unwrap_validate_state_res(
1378 self,
1379 mem: WasmLinearMem,
1380 ) -> Result<ValidateResult, ContractError> {
1381 #![allow(clippy::let_and_return)]
1382 let kind = ResultKind::from(self.kind);
1383 match kind {
1384 ResultKind::ValidateState => {
1385 let ptr = crate::memory::buf::compute_ptr(self.ptr as *mut u8, &mem);
1386 let serialized = std::slice::from_raw_parts(ptr as *const u8, self.size as _);
1387 let value = bincode::deserialize(serialized)
1388 .map_err(|e| ContractError::Other(format!("{e}")))?;
1389 #[cfg(feature = "trace")]
1390 self.log_input(serialized, &value, ptr);
1391 value
1392 }
1393 _ => unreachable!(),
1394 }
1395 }
1396
1397 pub unsafe fn unwrap_update_state(
1398 self,
1399 mem: WasmLinearMem,
1400 ) -> Result<UpdateModification<'static>, ContractError> {
1401 let kind = ResultKind::from(self.kind);
1402 match kind {
1403 ResultKind::UpdateState => {
1404 let ptr = crate::memory::buf::compute_ptr(self.ptr as *mut u8, &mem);
1405 let serialized = std::slice::from_raw_parts(ptr as *const u8, self.size as _);
1406 let value: Result<UpdateModification<'_>, ContractError> =
1407 bincode::deserialize(serialized)
1408 .map_err(|e| ContractError::Other(format!("{e}")))?;
1409 #[cfg(feature = "trace")]
1410 self.log_input(serialized, &value, ptr);
1411 value.map(|r| r.into_owned())
1414 }
1415 _ => unreachable!(),
1416 }
1417 }
1418
1419 pub unsafe fn unwrap_summarize_state(
1420 self,
1421 mem: WasmLinearMem,
1422 ) -> Result<StateSummary<'static>, ContractError> {
1423 let kind = ResultKind::from(self.kind);
1424 match kind {
1425 ResultKind::SummarizeState => {
1426 let ptr = crate::memory::buf::compute_ptr(self.ptr as *mut u8, &mem);
1427 let serialized = std::slice::from_raw_parts(ptr as *const u8, self.size as _);
1428 let value: Result<StateSummary<'static>, ContractError> =
1429 bincode::deserialize(serialized)
1430 .map_err(|e| ContractError::Other(format!("{e}")))?;
1431 #[cfg(feature = "trace")]
1432 self.log_input(serialized, &value, ptr);
1433 value.map(|s| StateSummary::from(s.into_bytes()))
1436 }
1437 _ => unreachable!(),
1438 }
1439 }
1440
1441 pub unsafe fn unwrap_get_state_delta(
1442 self,
1443 mem: WasmLinearMem,
1444 ) -> Result<StateDelta<'static>, ContractError> {
1445 let kind = ResultKind::from(self.kind);
1446 match kind {
1447 ResultKind::StateDelta => {
1448 let ptr = crate::memory::buf::compute_ptr(self.ptr as *mut u8, &mem);
1449 let serialized = std::slice::from_raw_parts(ptr as *const u8, self.size as _);
1450 let value: Result<StateDelta<'static>, ContractError> =
1451 bincode::deserialize(serialized)
1452 .map_err(|e| ContractError::Other(format!("{e}")))?;
1453 #[cfg(feature = "trace")]
1454 self.log_input(serialized, &value, ptr);
1455 value.map(|d| StateDelta::from(d.into_bytes()))
1458 }
1459 _ => unreachable!(),
1460 }
1461 }
1462
1463 #[cfg(feature = "contract")]
1464 pub fn into_raw(self) -> i64 {
1465 #[cfg(feature = "trace")]
1466 {
1467 tracing::trace!("returning FFI -> {self:?}");
1468 }
1469 let ptr = Box::into_raw(Box::new(self));
1470 #[cfg(feature = "trace")]
1471 {
1472 tracing::trace!("FFI result ptr: {ptr:p} ({}i64)", ptr as i64);
1473 }
1474 ptr as _
1475 }
1476
1477 pub unsafe fn from_raw(ptr: i64, mem: &WasmLinearMem) -> Self {
1478 let result = Box::leak(Box::from_raw(crate::memory::buf::compute_ptr(
1479 ptr as *mut Self,
1480 mem,
1481 )));
1482 #[cfg(feature = "trace")]
1483 {
1484 tracing::trace!(
1485 "got FFI result @ {ptr} ({:p}) -> {result:?}",
1486 ptr as *mut Self
1487 );
1488 }
1489 *result
1490 }
1491
1492 #[cfg(feature = "trace")]
1493 fn log_input<T: std::fmt::Debug>(&self, serialized: &[u8], value: &T, ptr: *mut u8) {
1494 tracing::trace!(
1495 "got result through FFI; addr: {:p} ({}i64, mapped: {ptr:p})
1496 serialized: {serialized:?}
1497 value: {value:?}",
1498 self.ptr as *mut u8,
1499 self.ptr
1500 );
1501 }
1502 }
1503
1504 #[cfg(feature = "contract")]
1505 macro_rules! conversion {
1506 ($value:ty: $kind:expr) => {
1507 impl From<$value> for ContractInterfaceResult {
1508 fn from(value: $value) -> Self {
1509 let kind = $kind as i32;
1510 let serialized = bincode::serialize(&value).unwrap();
1514 let size = serialized.len() as _;
1515 let ptr = serialized.as_ptr();
1516 #[cfg(feature = "trace")] {
1517 tracing::trace!(
1518 "sending result through FFI; addr: {ptr:p} ({}),\n serialized: {serialized:?}\n value: {value:?}",
1519 ptr as i64
1520 );
1521 }
1522 std::mem::forget(serialized);
1523 Self { kind, ptr: ptr as i64, size }
1524 }
1525 }
1526 };
1527 }
1528
1529 #[cfg(feature = "contract")]
1530 conversion!(Result<ValidateResult, ContractError>: ResultKind::ValidateState);
1531 #[cfg(feature = "contract")]
1532 conversion!(Result<bool, ContractError>: ResultKind::ValidateDelta);
1533 #[cfg(feature = "contract")]
1534 conversion!(Result<UpdateModification<'static>, ContractError>: ResultKind::UpdateState);
1535 #[cfg(feature = "contract")]
1536 conversion!(Result<StateSummary<'static>, ContractError>: ResultKind::SummarizeState);
1537 #[cfg(feature = "contract")]
1538 conversion!(Result<StateDelta<'static>, ContractError>: ResultKind::StateDelta);
1539}
1540
1541#[cfg(all(test, any(unix, windows)))]
1542mod test {
1543 use super::*;
1544 use once_cell::sync::Lazy;
1545 use rand::{rngs::SmallRng, Rng, SeedableRng};
1546
1547 static RND_BYTES: Lazy<[u8; 1024]> = Lazy::new(|| {
1548 let mut bytes = [0; 1024];
1549 let mut rng = SmallRng::from_entropy();
1550 rng.fill(&mut bytes);
1551 bytes
1552 });
1553
1554 #[test]
1555 fn key_encoding() -> Result<(), Box<dyn std::error::Error>> {
1556 let code = ContractCode::from(vec![1, 2, 3]);
1557 let expected = ContractKey::from_params_and_code(Parameters::from(vec![]), &code);
1558 let decoded = ContractKey::from_params(code.hash_str(), [].as_ref().into())?;
1564 assert_eq!(expected, decoded);
1565 assert_eq!(expected.code_hash(), decoded.code_hash());
1566 Ok(())
1567 }
1568
1569 #[test]
1570 fn key_ser() -> Result<(), Box<dyn std::error::Error>> {
1571 let mut gen = arbitrary::Unstructured::new(&*RND_BYTES);
1572 let expected: ContractKey = gen.arbitrary()?;
1573 let encoded = bs58::encode(expected.as_bytes()).into_string();
1574 let serialized = bincode::serialize(&expected)?;
1577 let deserialized: ContractKey = bincode::deserialize(&serialized)?;
1578 let decoded = bs58::encode(deserialized.as_bytes()).into_string();
1579 assert_eq!(encoded, decoded);
1580 assert_eq!(deserialized, expected);
1581 Ok(())
1582 }
1583
1584 #[test]
1585 fn contract_ser() -> Result<(), Box<dyn std::error::Error>> {
1586 let mut gen = arbitrary::Unstructured::new(&*RND_BYTES);
1587 let expected: Contract = gen.arbitrary()?;
1588
1589 let serialized = bincode::serialize(&expected)?;
1590 let deserialized: Contract = bincode::deserialize(&serialized)?;
1591 assert_eq!(deserialized, expected);
1592 Ok(())
1593 }
1594}
1595
1596pub mod encoding {
1597 use std::{collections::HashSet, marker::PhantomData};
1599
1600 use serde::de::DeserializeOwned;
1601
1602 use super::*;
1603
1604 pub enum MergeResult {
1605 Success,
1606 RequestRelated(RelatedContractsContainer),
1607 Error(ContractError),
1608 }
1609
1610 #[derive(Default)]
1611 pub struct RelatedContractsContainer {
1612 contracts: HashMap<ContractInstanceId, State<'static>>,
1613 pending: HashSet<ContractInstanceId>,
1614 not_found: HashSet<ContractInstanceId>,
1615 }
1616
1617 impl From<RelatedContracts<'static>> for RelatedContractsContainer {
1618 fn from(found: RelatedContracts<'static>) -> Self {
1619 let mut not_found = HashSet::new();
1620 let mut contracts = HashMap::with_capacity(found.map.len());
1621 for (id, state) in found.map.into_iter() {
1622 match state {
1623 Some(state) => {
1624 contracts.insert(id, state);
1625 }
1626 None => {
1627 not_found.insert(id);
1628 }
1629 }
1630 }
1631 RelatedContractsContainer {
1632 contracts,
1633 pending: HashSet::new(),
1634 not_found,
1635 }
1636 }
1637 }
1638
1639 impl From<RelatedContractsContainer> for Vec<crate::contract_interface::RelatedContract> {
1640 fn from(related: RelatedContractsContainer) -> Self {
1641 related
1642 .pending
1643 .into_iter()
1644 .map(|id| RelatedContract {
1645 contract_instance_id: id,
1646 mode: RelatedMode::StateOnce,
1647 })
1648 .collect()
1649 }
1650 }
1651
1652 impl From<Vec<UpdateData<'static>>> for RelatedContractsContainer {
1653 fn from(updates: Vec<UpdateData<'static>>) -> Self {
1654 let mut this = RelatedContractsContainer::default();
1655 for update in updates {
1656 match update {
1657 UpdateData::RelatedState { related_to, state } => {
1658 this.contracts.insert(related_to, state);
1659 }
1660 UpdateData::RelatedStateAndDelta {
1661 related_to, state, ..
1662 } => {
1663 this.contracts.insert(related_to, state);
1664 }
1665 _ => {}
1666 }
1667 }
1668 this
1669 }
1670 }
1671
1672 impl RelatedContractsContainer {
1673 pub fn get<C: TypedContract>(
1674 &self,
1675 params: &C::Parameters,
1676 ) -> Result<Related<C>, <<C as EncodingAdapter>::SelfEncoder as Encoder<C>>::Error>
1677 {
1678 let id = <C as TypedContract>::instance_id(params);
1679 if let Some(res) = self.contracts.get(&id) {
1680 match <<C as EncodingAdapter>::SelfEncoder>::deserialize(res.as_ref()) {
1681 Ok(state) => return Ok(Related::Found { state }),
1682 Err(err) => return Err(err),
1683 }
1684 }
1685 if self.pending.contains(&id) {
1686 return Ok(Related::RequestPending);
1687 }
1688 if self.not_found.contains(&id) {
1689 return Ok(Related::NotFound);
1690 }
1691 Ok(Related::NotRequested)
1692 }
1693
1694 pub fn request<C: TypedContract>(&mut self, id: ContractInstanceId) {
1695 self.pending.insert(id);
1696 }
1697
1698 pub fn merge(&mut self, other: Self) {
1699 let Self {
1700 contracts,
1701 pending,
1702 not_found,
1703 } = other;
1704 self.pending.extend(pending);
1705 self.not_found.extend(not_found);
1706 self.contracts.extend(contracts);
1707 }
1708 }
1709
1710 pub enum Related<C: TypedContract> {
1711 Found { state: C },
1713 NotFound,
1715 RequestPending,
1717 NotRequested,
1720 }
1721
1722 pub trait EncodingAdapter
1725 where
1726 Self: Sized,
1727 {
1728 type Parameters;
1729 type Delta;
1730 type Summary;
1731
1732 type SelfEncoder: Encoder<Self>;
1733 type ParametersEncoder: Encoder<Self::Parameters>;
1734 type DeltaEncoder: Encoder<Self::Delta>;
1735 type SummaryEncoder: Encoder<Self::Summary>;
1736 }
1737
1738 pub enum TypedUpdateData<T: EncodingAdapter> {
1739 RelatedState { state: T },
1740 RelatedDelta { delta: T::Delta },
1741 RelatedStateAndDelta { state: T, delta: T::Delta },
1742 }
1743
1744 impl<T: EncodingAdapter> TypedUpdateData<T> {
1745 pub fn from_other<Parent>(value: &TypedUpdateData<Parent>) -> Self
1746 where
1747 Parent: EncodingAdapter,
1748 T: for<'x> From<&'x Parent>,
1749 T::Delta: for<'x> From<&'x Parent::Delta>,
1750 {
1751 match value {
1752 TypedUpdateData::RelatedState { state } => {
1753 let state = T::from(state);
1754 TypedUpdateData::RelatedState { state }
1755 }
1756 TypedUpdateData::RelatedDelta { delta } => {
1757 let delta: T::Delta = <T as EncodingAdapter>::Delta::from(delta);
1758 TypedUpdateData::RelatedDelta { delta }
1759 }
1760 TypedUpdateData::RelatedStateAndDelta { state, delta } => {
1761 let state = T::from(state);
1762 let delta: T::Delta = <T as EncodingAdapter>::Delta::from(delta);
1763 TypedUpdateData::RelatedStateAndDelta { state, delta }
1764 }
1765 }
1766 }
1767 }
1768
1769 impl<T: EncodingAdapter> TryFrom<(Option<T>, Option<T::Delta>)> for TypedUpdateData<T> {
1770 type Error = ContractError;
1771 fn try_from((state, delta): (Option<T>, Option<T::Delta>)) -> Result<Self, Self::Error> {
1772 match (state, delta) {
1773 (None, None) => Err(ContractError::InvalidState),
1774 (None, Some(delta)) => Ok(Self::RelatedDelta { delta }),
1775 (Some(state), None) => Ok(Self::RelatedState { state }),
1776 (Some(state), Some(delta)) => Ok(Self::RelatedStateAndDelta { state, delta }),
1777 }
1778 }
1779 }
1780
1781 pub trait TypedContract: EncodingAdapter {
1782 fn instance_id(params: &Self::Parameters) -> ContractInstanceId;
1783
1784 fn verify(
1785 &self,
1786 parameters: Self::Parameters,
1787 related: RelatedContractsContainer,
1788 ) -> Result<ValidateResult, ContractError>;
1789
1790 fn merge(
1791 &mut self,
1792 parameters: &Self::Parameters,
1793 update: TypedUpdateData<Self>,
1794 related: &RelatedContractsContainer,
1795 ) -> MergeResult;
1796
1797 fn summarize(&self, parameters: Self::Parameters) -> Result<Self::Summary, ContractError>;
1798
1799 fn delta(
1800 &self,
1801 parameters: Self::Parameters,
1802 summary: Self::Summary,
1803 ) -> Result<Self::Delta, ContractError>;
1804 }
1805
1806 pub trait Encoder<T> {
1807 type Error: Into<ContractError>;
1808 fn deserialize(bytes: &[u8]) -> Result<T, Self::Error>;
1809 fn serialize(value: &T) -> Result<Vec<u8>, Self::Error>;
1810 }
1811
1812 pub struct JsonEncoder<T>(PhantomData<T>);
1813
1814 impl<T> Encoder<T> for JsonEncoder<T>
1815 where
1816 T: DeserializeOwned + Serialize,
1817 {
1818 type Error = serde_json::Error;
1819
1820 fn deserialize(bytes: &[u8]) -> Result<T, Self::Error> {
1821 serde_json::from_slice(bytes)
1822 }
1823
1824 fn serialize(value: &T) -> Result<Vec<u8>, Self::Error> {
1825 serde_json::to_vec(value)
1826 }
1827 }
1828
1829 impl From<serde_json::Error> for ContractError {
1830 fn from(value: serde_json::Error) -> Self {
1831 ContractError::Deser(format!("{value}"))
1832 }
1833 }
1834
1835 pub struct BincodeEncoder<T>(PhantomData<T>);
1836
1837 impl<T> Encoder<T> for BincodeEncoder<T>
1838 where
1839 T: DeserializeOwned + Serialize,
1840 {
1841 type Error = bincode::Error;
1842
1843 fn deserialize(bytes: &[u8]) -> Result<T, Self::Error> {
1844 bincode::deserialize(bytes)
1845 }
1846
1847 fn serialize(value: &T) -> Result<Vec<u8>, Self::Error> {
1848 bincode::serialize(value)
1849 }
1850 }
1851
1852 impl From<bincode::Error> for ContractError {
1853 fn from(value: bincode::Error) -> Self {
1854 ContractError::Deser(format!("{value}"))
1855 }
1856 }
1857
1858 pub fn inner_validate_state<T>(
1859 parameters: Parameters<'static>,
1860 state: State<'static>,
1861 related: RelatedContracts<'static>,
1862 ) -> Result<ValidateResult, ContractError>
1863 where
1864 T: EncodingAdapter + TypedContract,
1865 ContractError: From<
1866 <<T as EncodingAdapter>::ParametersEncoder as Encoder<
1867 <T as EncodingAdapter>::Parameters,
1868 >>::Error,
1869 >,
1870 ContractError: From<<<T as EncodingAdapter>::SelfEncoder as Encoder<T>>::Error>,
1871 {
1872 let typed_params =
1873 <<T as EncodingAdapter>::ParametersEncoder>::deserialize(parameters.as_ref())?;
1874 let typed_state = <<T as EncodingAdapter>::SelfEncoder>::deserialize(state.as_ref())?;
1875 let related_container = RelatedContractsContainer::from(related);
1876 typed_state.verify(typed_params, related_container)
1877 }
1878
1879 pub fn inner_update_state<T>(
1880 parameters: Parameters<'static>,
1881 state: State<'static>,
1882 data: Vec<UpdateData<'static>>,
1883 ) -> Result<UpdateModification<'static>, ContractError>
1884 where
1885 T: EncodingAdapter + TypedContract,
1886 ContractError: From<<<T as EncodingAdapter>::SelfEncoder as Encoder<T>>::Error>,
1887 ContractError: From<
1888 <<T as EncodingAdapter>::ParametersEncoder as Encoder<
1889 <T as EncodingAdapter>::Parameters,
1890 >>::Error,
1891 >,
1892 ContractError: From<
1893 <<T as EncodingAdapter>::DeltaEncoder as Encoder<<T as EncodingAdapter>::Delta>>::Error,
1894 >,
1895 {
1896 let typed_params =
1897 <<T as EncodingAdapter>::ParametersEncoder>::deserialize(parameters.as_ref())?;
1898 let mut typed_state = <<T as EncodingAdapter>::SelfEncoder>::deserialize(state.as_ref())?;
1899 let self_updates = UpdateData::get_self_states(&data);
1900 let related_container = RelatedContractsContainer::from(data);
1901 for (state, delta) in self_updates {
1902 let state = state
1903 .map(|s| <<T as EncodingAdapter>::SelfEncoder>::deserialize(s.as_ref()))
1904 .transpose()?;
1905 let delta = delta
1906 .map(|d| <<T as EncodingAdapter>::DeltaEncoder>::deserialize(d.as_ref()))
1907 .transpose()?;
1908 let typed_update = TypedUpdateData::try_from((state, delta))?;
1909 match typed_state.merge(&typed_params, typed_update, &related_container) {
1910 MergeResult::Success => {}
1911 MergeResult::RequestRelated(req) => {
1912 return UpdateModification::requires(req.into());
1913 }
1914 MergeResult::Error(err) => return Err(err),
1915 }
1916 }
1917 let encoded = <<T as EncodingAdapter>::SelfEncoder>::serialize(&typed_state)?;
1918 Ok(UpdateModification::valid(encoded.into()))
1919 }
1920
1921 pub fn inner_summarize_state<T>(
1922 parameters: Parameters<'static>,
1923 state: State<'static>,
1924 ) -> Result<StateSummary<'static>, ContractError>
1925 where
1926 T: EncodingAdapter + TypedContract,
1927 ContractError: From<<<T as EncodingAdapter>::SelfEncoder as Encoder<T>>::Error>,
1928 ContractError: From<
1929 <<T as EncodingAdapter>::ParametersEncoder as Encoder<
1930 <T as EncodingAdapter>::Parameters,
1931 >>::Error,
1932 >,
1933 ContractError:
1934 From<
1935 <<T as EncodingAdapter>::SummaryEncoder as Encoder<
1936 <T as EncodingAdapter>::Summary,
1937 >>::Error,
1938 >,
1939 {
1940 let typed_params =
1941 <<T as EncodingAdapter>::ParametersEncoder>::deserialize(parameters.as_ref())?;
1942 let typed_state = <<T as EncodingAdapter>::SelfEncoder>::deserialize(state.as_ref())?;
1943 let summary = typed_state.summarize(typed_params)?;
1944 let encoded = <<T as EncodingAdapter>::SummaryEncoder>::serialize(&summary)?;
1945 Ok(encoded.into())
1946 }
1947
1948 pub fn inner_state_delta<T>(
1949 parameters: Parameters<'static>,
1950 state: State<'static>,
1951 summary: StateSummary<'static>,
1952 ) -> Result<StateDelta<'static>, ContractError>
1953 where
1954 T: EncodingAdapter + TypedContract,
1955 ContractError: From<<<T as EncodingAdapter>::SelfEncoder as Encoder<T>>::Error>,
1956 ContractError: From<
1957 <<T as EncodingAdapter>::ParametersEncoder as Encoder<
1958 <T as EncodingAdapter>::Parameters,
1959 >>::Error,
1960 >,
1961 ContractError:
1962 From<
1963 <<T as EncodingAdapter>::SummaryEncoder as Encoder<
1964 <T as EncodingAdapter>::Summary,
1965 >>::Error,
1966 >,
1967 ContractError: From<
1968 <<T as EncodingAdapter>::DeltaEncoder as Encoder<<T as EncodingAdapter>::Delta>>::Error,
1969 >,
1970 {
1971 let typed_params =
1972 <<T as EncodingAdapter>::ParametersEncoder>::deserialize(parameters.as_ref())?;
1973 let typed_state = <<T as EncodingAdapter>::SelfEncoder>::deserialize(state.as_ref())?;
1974 let typed_summary =
1975 <<T as EncodingAdapter>::SummaryEncoder>::deserialize(summary.as_ref())?;
1976 let summary = typed_state.delta(typed_params, typed_summary)?;
1977 let encoded = <<T as EncodingAdapter>::DeltaEncoder>::serialize(&summary)?;
1978 Ok(encoded.into())
1979 }
1980}