1use std::borrow::Cow;
2use std::str::FromStr;
3use std::sync::Arc;
4
5use ahash::HashMap;
6use anyhow::Result;
7use serde::Deserialize;
8use sha2::Digest;
9
10use crate::abi::value::ser::AbiSerializer;
11use crate::abi::AbiHeader;
12use crate::cell::{
13 Cell, CellBuilder, CellFamily, CellSlice, CellSliceRange, DynCell, HashBytes, Size, Store,
14};
15use crate::dict::RawDict;
16use crate::models::{
17 ExtInMsgInfo, IntAddr, MsgInfo, OwnedMessage, OwnedRelaxedMessage, RelaxedIntMsgInfo,
18 RelaxedMsgInfo, StateInit, StdAddr,
19};
20use crate::num::Tokens;
21use crate::prelude::Dict;
22
23use super::error::AbiError;
24use super::{AbiHeaderType, AbiType, AbiValue, AbiVersion, NamedAbiType, NamedAbiValue};
25
26pub struct Contract {
28 pub abi_version: AbiVersion,
30
31 pub headers: Arc<[AbiHeaderType]>,
35
36 pub functions: HashMap<Arc<str>, Function>,
38
39 pub events: HashMap<Arc<str>, Event>,
41
42 pub init_data: HashMap<Arc<str>, (u64, NamedAbiType)>,
44
45 pub fields: Arc<[NamedAbiType]>,
47}
48
49impl Contract {
50 pub fn find_function_by_id(&self, id: u32, input: bool) -> Option<&Function> {
52 self.functions
53 .values()
54 .find(|item| input && item.input_id == id || !input && item.output_id == id)
55 }
56
57 pub fn find_event_by_id(&self, id: u32) -> Option<&Event> {
59 self.events.values().find(|event| event.id == id)
60 }
61
62 pub fn update_init_data(
67 &self,
68 pubkey: Option<&ed25519_dalek::VerifyingKey>,
69 tokens: &[NamedAbiValue],
70 data: &Cell,
71 ) -> Result<Cell> {
72 let mut result = data.parse::<RawDict<64>>()?;
74
75 if pubkey.is_none() && tokens.is_empty() {
76 return Ok(data.clone());
78 }
79
80 let context = &mut Cell::empty_context();
81 let mut key_builder = CellBuilder::new();
82
83 for token in tokens {
84 let Some((key, ty)) = self.init_data.get(token.name.as_ref()) else {
85 anyhow::bail!(AbiError::UnexpectedInitDataParam(token.name.clone()));
86 };
87 token.check_type(ty)?;
88
89 key_builder.store_u64(*key)?;
90
91 result.set_ext(
92 key_builder.as_data_slice(),
93 &token.make_builder(self.abi_version)?.as_full_slice(),
94 context,
95 )?;
96
97 key_builder.rewind(64)?;
98 }
99
100 if let Some(pubkey) = pubkey {
102 key_builder.store_u64(0)?;
103 result.set_ext(
104 key_builder.as_data_slice(),
105 &CellBuilder::from_raw_data(pubkey.as_bytes(), 256)?.as_data_slice(),
106 context,
107 )?;
108 }
109
110 CellBuilder::build_from_ext(result, context).map_err(From::from)
112 }
113
114 pub fn encode_init_data(
119 &self,
120 pubkey: &ed25519_dalek::VerifyingKey,
121 tokens: &[NamedAbiValue],
122 ) -> Result<Cell> {
123 let mut result = RawDict::<64>::new();
124
125 let mut init_data = self
126 .init_data
127 .iter()
128 .map(|(name, value)| (name.as_ref(), value))
129 .collect::<HashMap<_, _>>();
130
131 let context = &mut Cell::empty_context();
132 let mut key_builder = CellBuilder::new();
133
134 for token in tokens {
136 let Some((key, ty)) = init_data.remove(token.name.as_ref()) else {
137 anyhow::bail!(AbiError::UnexpectedInitDataParam(token.name.clone()));
138 };
139 token.check_type(ty)?;
140
141 key_builder.store_u64(*key)?;
142
143 result.set_ext(
144 key_builder.as_data_slice(),
145 &token.make_builder(self.abi_version)?.as_full_slice(),
146 context,
147 )?;
148
149 key_builder.rewind(64)?;
150 }
151
152 for (key, ty) in init_data.into_values() {
154 key_builder.store_u64(*key)?;
155
156 result.set_ext(
157 key_builder.as_data_slice(),
158 &ty.make_default_value()
159 .make_builder(self.abi_version)?
160 .as_full_slice(),
161 context,
162 )?;
163
164 key_builder.rewind(64)?;
165 }
166
167 key_builder.store_u64(0)?;
169 result.set_ext(
170 key_builder.as_data_slice(),
171 &CellBuilder::from_raw_data(pubkey.as_bytes(), 256)?.as_data_slice(),
172 context,
173 )?;
174
175 CellBuilder::build_from_ext(result, context).map_err(From::from)
177 }
178
179 pub fn decode_init_data(&self, data: &DynCell) -> Result<Vec<NamedAbiValue>> {
181 let init_data = data.parse::<Dict<u64, CellSlice>>()?;
182
183 let mut result = Vec::with_capacity(self.init_data.len());
184
185 for (key, item) in self.init_data.values() {
186 let Some(mut value) = init_data.get(key)? else {
187 anyhow::bail!(AbiError::InitDataFieldNotFound(item.name.clone()));
188 };
189 result.push(NamedAbiValue::load(item, self.abi_version, &mut value)?);
190 }
191
192 Ok(result)
193 }
194
195 pub fn encode_fields(&self, tokens: &[NamedAbiValue]) -> Result<CellBuilder> {
197 ok!(NamedAbiValue::check_types(tokens, &self.fields));
198 NamedAbiValue::tuple_to_builder(tokens, self.abi_version).map_err(From::from)
199 }
200
201 pub fn decode_fields(&self, mut slice: CellSlice<'_>) -> Result<Vec<NamedAbiValue>> {
205 self.decode_fields_ext(&mut slice, false)
206 }
207
208 pub fn decode_fields_ext(
210 &self,
211 slice: &mut CellSlice<'_>,
212 allow_partial: bool,
213 ) -> Result<Vec<NamedAbiValue>> {
214 let res = ok!(NamedAbiValue::load_tuple_ext(
215 &self.fields,
216 self.abi_version,
217 true,
218 allow_partial,
219 slice
220 ));
221 ok!(AbiValue::check_remaining(slice, allow_partial));
222 Ok(res)
223 }
224}
225
226impl<'de> Deserialize<'de> for Contract {
227 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
228 where
229 D: serde::Deserializer<'de>,
230 {
231 use serde::de::Error;
232
233 #[repr(transparent)]
234 struct Id(u32);
235
236 impl<'de> Deserialize<'de> for Id {
237 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
238 where
239 D: serde::Deserializer<'de>,
240 {
241 #[derive(Deserialize)]
242 #[serde(transparent)]
243 struct Id<'a>(#[serde(borrow)] Cow<'a, str>);
244
245 match ok!(Id::deserialize(deserializer)).0.strip_prefix("0x") {
246 Some(s) => u32::from_str_radix(s, 16).map(Self).map_err(Error::custom),
247 None => Err(Error::custom("Hex number must be prefixed with 0x")),
248 }
249 }
250 }
251
252 #[derive(Deserialize)]
253 struct SerdeContract {
254 #[serde(default, rename = "ABI version")]
255 abi_version: Option<u8>,
256 #[serde(default)]
257 version: Option<String>,
258 #[serde(default)]
259 header: Vec<AbiHeaderType>,
260 functions: Vec<SerdeFunction>,
261 #[serde(default)]
262 events: Vec<SerdeEvent>,
263 #[serde(default)]
264 data: Vec<InitData>,
265 #[serde(default)]
266 fields: Vec<NamedAbiType>,
267 }
268
269 #[derive(Deserialize)]
270 struct SerdeFunction {
271 name: String,
272 #[serde(default)]
273 inputs: Vec<NamedAbiType>,
274 #[serde(default)]
275 outputs: Vec<NamedAbiType>,
276 #[serde(default)]
277 id: Option<Id>,
278 }
279
280 #[derive(Deserialize)]
281 struct SerdeEvent {
282 name: String,
283 #[serde(default)]
284 inputs: Vec<NamedAbiType>,
285 #[serde(default)]
286 id: Option<Id>,
287 }
288
289 #[derive(Deserialize)]
290 struct InitData {
291 key: u64,
292 #[serde(flatten)]
293 ty: NamedAbiType,
294 }
295
296 let contract = ok!(SerdeContract::deserialize(deserializer));
297 let abi_version = if let Some(version) = &contract.version {
298 ok!(AbiVersion::from_str(version).map_err(Error::custom))
299 } else if let Some(major) = contract.abi_version {
300 AbiVersion::new(major, 0)
301 } else {
302 return Err(Error::custom("No ABI version found"));
303 };
304
305 let headers = Arc::<[AbiHeaderType]>::from(contract.header);
306
307 let functions = contract
308 .functions
309 .into_iter()
310 .map(|item| {
311 let (input_id, output_id) = match item.id {
312 Some(Id(id)) => (id, id),
313 None => {
314 let id = Function::compute_function_id(
315 abi_version,
316 &item.name,
317 headers.as_ref(),
318 &item.inputs,
319 &item.outputs,
320 );
321 (id & Function::INPUT_ID_MASK, id | !Function::INPUT_ID_MASK)
322 }
323 };
324 let name = Arc::<str>::from(item.name);
325 (
326 name.clone(),
327 Function {
328 abi_version,
329 name,
330 headers: headers.clone(),
331 inputs: Arc::from(item.inputs),
332 outputs: Arc::from(item.outputs),
333 input_id,
334 output_id,
335 },
336 )
337 })
338 .collect();
339
340 let events = contract
341 .events
342 .into_iter()
343 .map(|item| {
344 let id = match item.id {
345 Some(Id(id)) => id,
346 None => {
347 let id = Event::compute_event_id(abi_version, &item.name, &item.inputs);
348 id & Function::INPUT_ID_MASK
349 }
350 };
351 let name = Arc::<str>::from(item.name);
352 (
353 name.clone(),
354 Event {
355 abi_version,
356 name,
357 inputs: Arc::from(item.inputs),
358 id,
359 },
360 )
361 })
362 .collect();
363
364 let init_data = contract
365 .data
366 .into_iter()
367 .map(|item| {
368 let name = item.ty.name.clone();
369 (name, (item.key, item.ty))
370 })
371 .collect();
372
373 Ok(Self {
374 abi_version,
375 headers,
376 functions,
377 events,
378 init_data,
379 fields: Arc::from(contract.fields),
380 })
381 }
382}
383
384#[derive(Debug, Clone)]
386pub struct Function {
387 pub abi_version: AbiVersion,
389 pub headers: Arc<[AbiHeaderType]>,
394 pub name: Arc<str>,
396 pub inputs: Arc<[NamedAbiType]>,
398 pub outputs: Arc<[NamedAbiType]>,
400 pub input_id: u32,
402 pub output_id: u32,
404}
405
406impl Function {
407 pub const INPUT_ID_MASK: u32 = 0x7fffffff;
409
410 pub fn compute_function_id(
412 abi_version: AbiVersion,
413 name: &str,
414 headers: &[AbiHeaderType],
415 inputs: &[NamedAbiType],
416 outputs: &[NamedAbiType],
417 ) -> u32 {
418 let mut hasher = sha2::Sha256::new();
419 FunctionSignatureRaw {
420 abi_version,
421 name,
422 headers,
423 inputs,
424 outputs,
425 }
426 .update_hasher(&mut hasher);
427
428 let hash: [u8; 32] = hasher.finalize().into();
429 u32::from_be_bytes(hash[0..4].try_into().unwrap())
430 }
431
432 pub fn encode_internal_msg_body(
434 version: AbiVersion,
435 id: u32,
436 tokens: &[NamedAbiValue],
437 ) -> Result<CellBuilder> {
438 let mut serializer = AbiSerializer::new(version);
439 let output_id = AbiValue::uint(32, id);
440
441 serializer.reserve_value(&output_id);
442 for token in tokens {
443 serializer.reserve_value(&token.value);
444 }
445
446 let context = &mut Cell::empty_context();
447 serializer.write_value(&output_id, context)?;
448 serializer.write_tuple(tokens, context)?;
449 serializer.finalize(context).map_err(From::from)
450 }
451
452 #[inline]
454 pub fn builder<T: Into<String>>(abi_version: AbiVersion, name: T) -> FunctionBuilder {
455 FunctionBuilder::new(abi_version, name)
456 }
457
458 pub fn encode_external<'f, 'a: 'f>(&'f self, tokens: &'a [NamedAbiValue]) -> ExternalInput {
460 ExternalInput {
461 function: self,
462 tokens,
463 time: None,
464 expire_at: None,
465 pubkey: None,
466 address: None,
467 }
468 }
469
470 pub fn decode_external_input(&self, mut slice: CellSlice<'_>) -> Result<Vec<NamedAbiValue>> {
474 self.decode_external_input_ext(&mut slice, false)
475 }
476
477 pub fn decode_external_input_ext(
479 &self,
480 slice: &mut CellSlice<'_>,
481 allow_partial: bool,
482 ) -> Result<Vec<NamedAbiValue>> {
483 let id = if self.abi_version.major == 1 {
485 let id = slice.load_u32()?;
487 slice.load_reference()?;
489 ok!(AbiHeader::skip_all(&self.headers, slice));
491
492 id
493 } else {
494 if slice.load_bit()? {
496 slice.skip_first(512, 0)?;
497 }
498 ok!(AbiHeader::skip_all(&self.headers, slice));
500 slice.load_u32()?
502 };
503
504 anyhow::ensure!(
506 id == self.input_id,
507 AbiError::InputIdMismatch {
508 expected: self.input_id,
509 id
510 }
511 );
512
513 let res = ok!(NamedAbiValue::load_tuple_ext(
514 &self.inputs,
515 self.abi_version,
516 true,
517 allow_partial,
518 slice
519 ));
520 ok!(AbiValue::check_remaining(slice, allow_partial));
521 Ok(res)
522 }
523
524 pub fn encode_internal_input(&self, tokens: &[NamedAbiValue]) -> Result<CellBuilder> {
526 ok!(NamedAbiValue::check_types(tokens, &self.inputs));
527 Self::encode_internal_msg_body(self.abi_version, self.input_id, tokens)
528 }
529
530 pub fn encode_internal_message(
532 &self,
533 tokens: &[NamedAbiValue],
534 dst: IntAddr,
535 value: Tokens,
536 bounce: bool,
537 state_init: Option<&StateInit>,
538 ) -> Result<Box<OwnedRelaxedMessage>> {
539 let body = self.encode_internal_input(tokens)?;
540 let cell = body.build()?;
541 let range = CellSliceRange::full(cell.as_ref());
542
543 Ok(Box::new(OwnedRelaxedMessage {
544 info: RelaxedMsgInfo::Int(RelaxedIntMsgInfo {
545 dst,
546 bounce,
547 value: value.into(),
548 ..Default::default()
549 }),
550 body: (cell, range),
551 init: state_init.cloned(),
552 layout: None,
553 }))
554 }
555
556 pub fn decode_internal_input(&self, mut slice: CellSlice<'_>) -> Result<Vec<NamedAbiValue>> {
560 self.decode_internal_input_ext(&mut slice, false)
561 }
562
563 pub fn decode_internal_input_ext(
565 &self,
566 slice: &mut CellSlice<'_>,
567 allow_partial: bool,
568 ) -> Result<Vec<NamedAbiValue>> {
569 let id = slice.load_u32()?;
570 anyhow::ensure!(
571 id == self.input_id,
572 AbiError::InputIdMismatch {
573 expected: self.input_id,
574 id
575 }
576 );
577 let res = ok!(NamedAbiValue::load_tuple_ext(
578 &self.inputs,
579 self.abi_version,
580 true,
581 allow_partial,
582 slice
583 ));
584 ok!(AbiValue::check_remaining(slice, allow_partial));
585 Ok(res)
586 }
587
588 pub fn encode_output(&self, tokens: &[NamedAbiValue]) -> Result<CellBuilder> {
590 ok!(NamedAbiValue::check_types(tokens, &self.outputs));
591 Self::encode_internal_msg_body(self.abi_version, self.output_id, tokens)
592 }
593
594 pub fn decode_output(&self, mut slice: CellSlice<'_>) -> Result<Vec<NamedAbiValue>> {
598 self.decode_output_ext(&mut slice, false)
599 }
600
601 pub fn decode_output_ext(
603 &self,
604 slice: &mut CellSlice<'_>,
605 allow_partial: bool,
606 ) -> Result<Vec<NamedAbiValue>> {
607 let id = slice.load_u32()?;
608 anyhow::ensure!(
609 id == self.output_id,
610 AbiError::OutputIdMismatch {
611 expected: self.output_id,
612 id
613 }
614 );
615 let res = ok!(NamedAbiValue::load_tuple_ext(
616 &self.outputs,
617 self.abi_version,
618 true,
619 allow_partial,
620 slice
621 ));
622 ok!(AbiValue::check_remaining(slice, allow_partial));
623 Ok(res)
624 }
625
626 pub fn display_signature(&self) -> impl std::fmt::Display + '_ {
628 FunctionSignatureRaw {
629 abi_version: self.abi_version,
630 name: &self.name,
631 headers: &self.headers,
632 inputs: &self.inputs,
633 outputs: &self.outputs,
634 }
635 }
636}
637
638#[derive(Clone)]
640pub struct ExternalInput<'f, 'a> {
641 function: &'f Function,
642 tokens: &'a [NamedAbiValue],
643 time: Option<u64>,
644 expire_at: Option<u32>,
645 pubkey: Option<&'a ed25519_dalek::VerifyingKey>,
646 address: Option<&'a StdAddr>,
647}
648
649impl<'f, 'a> ExternalInput<'f, 'a> {
650 pub fn build_message(&self, address: &StdAddr) -> Result<UnsignedExternalMessage> {
652 Ok(ok!(self.build_input_ext(Some(address))).with_dst(address.clone()))
653 }
654
655 pub fn build_message_without_signature(
659 &self,
660 address: &StdAddr,
661 ) -> Result<(u32, OwnedMessage)> {
662 let (expire_at, body) = ok!(self.build_input_without_signature());
663 let range = CellSliceRange::full(body.as_ref());
664 Ok((
665 expire_at,
666 OwnedMessage {
667 info: MsgInfo::ExtIn(ExtInMsgInfo {
668 dst: IntAddr::Std(address.clone()),
669 ..Default::default()
670 }),
671 body: (body, range),
672 init: None,
673 layout: None,
674 },
675 ))
676 }
677
678 pub fn build_input(&self) -> Result<UnsignedBody> {
680 self.build_input_ext(self.address)
681 }
682
683 fn build_input_ext(&self, address: Option<&StdAddr>) -> Result<UnsignedBody> {
684 let (expire_at, payload) = self.build_payload(true)?;
685
686 let context = &mut Cell::empty_context();
687 let hash = if self.function.abi_version >= AbiVersion::V2_3 {
688 let mut to_sign = CellBuilder::new();
689 match address {
690 Some(address) => address.store_into(&mut to_sign, context)?,
691 None => anyhow::bail!(AbiError::AddressNotProvided),
692 };
693 to_sign.store_slice(payload.as_slice()?)?;
694 *to_sign.build_ext(context)?.repr_hash()
695 } else {
696 *payload.repr_hash()
697 };
698
699 Ok(UnsignedBody {
700 abi_version: self.function.abi_version,
701 expire_at,
702 payload,
703 hash,
704 })
705 }
706
707 pub fn build_input_without_signature(&self) -> Result<(u32, Cell)> {
709 self.build_payload(false)
710 }
711
712 fn build_payload(&self, reserve_signature: bool) -> Result<(u32, Cell)> {
713 const DEFAULT_TIMEOUT_SEC: u32 = 60;
714
715 fn now_ms() -> u64 {
716 std::time::SystemTime::now()
717 .duration_since(std::time::SystemTime::UNIX_EPOCH)
718 .unwrap()
719 .as_millis() as u64
720 }
721
722 ok!(NamedAbiValue::check_types(
723 self.tokens,
724 &self.function.inputs
725 ));
726
727 let abi_version = self.function.abi_version;
728
729 let mut serializer = AbiSerializer::new(abi_version);
730
731 if reserve_signature {
732 serializer.add_offset(if abi_version.major == 1 {
733 Size { bits: 0, refs: 1 }
735 } else {
736 let bits = if abi_version >= AbiVersion::V2_3 {
737 IntAddr::BITS_MAX
739 } else {
740 1 + 512
742 };
743 Size { bits, refs: 0 }
744 });
745 }
746
747 let input_id = AbiValue::uint(32, self.function.input_id);
748
749 serializer.reserve_headers(&self.function.headers, self.pubkey.is_some());
750 serializer.reserve_value(&input_id);
751 for token in self.tokens {
752 serializer.reserve_value(&token.value);
753 }
754
755 let context = &mut Cell::empty_context();
756
757 if !reserve_signature {
758 let value = if abi_version.major == 1 {
759 AbiValue::Cell(Cell::default())
760 } else {
761 AbiValue::Bool(false)
762 };
763 serializer.reserve_value(&value);
764 serializer.write_value(&value, context)?;
765 }
766
767 let time = self.time.unwrap_or_else(now_ms);
768 let expire_at = self
769 .expire_at
770 .unwrap_or((time / 1000) as u32 + DEFAULT_TIMEOUT_SEC);
771
772 for header in self.function.headers.as_ref() {
773 serializer.write_header_value(&match header {
774 AbiHeaderType::Time => AbiHeader::Time(time),
775 AbiHeaderType::Expire => AbiHeader::Expire(expire_at),
776 AbiHeaderType::PublicKey => {
777 AbiHeader::PublicKey(self.pubkey.map(|key| Box::new(*key)))
778 }
779 })?;
780 }
781
782 serializer.write_value(&input_id, context)?;
783 serializer.write_tuple(self.tokens, context)?;
784
785 let payload = serializer.finalize(context)?.build_ext(context)?;
786 Ok((expire_at, payload))
787 }
788
789 #[inline]
791 pub fn set_time(&mut self, time: u64) {
792 self.time = Some(time);
793 }
794
795 #[inline]
797 pub fn with_time(mut self, time: u64) -> Self {
798 self.set_time(time);
799 self
800 }
801
802 #[inline]
804 pub fn set_expire_at(&mut self, expire_at: u32) {
805 self.expire_at = Some(expire_at);
806 }
807
808 #[inline]
810 pub fn with_expire_at(mut self, expire_at: u32) -> Self {
811 self.set_expire_at(expire_at);
812 self
813 }
814
815 #[inline]
817 pub fn set_pubkey(&mut self, pubkey: &'a ed25519_dalek::VerifyingKey) {
818 self.pubkey = Some(pubkey);
819 }
820
821 #[inline]
823 pub fn with_pubkey(mut self, pubkey: &'a ed25519_dalek::VerifyingKey) -> Self {
824 self.set_pubkey(pubkey);
825 self
826 }
827
828 #[inline]
830 pub fn set_address(&mut self, address: &'a StdAddr) {
831 self.address = Some(address);
832 }
833
834 #[inline]
836 pub fn with_address(mut self, address: &'a StdAddr) -> Self {
837 self.set_address(address);
838 self
839 }
840}
841
842#[derive(Debug, Clone)]
844pub struct FunctionBuilder {
845 abi_version: AbiVersion,
846 name: String,
847 headers: Vec<AbiHeaderType>,
848 inputs: Vec<NamedAbiType>,
849 outputs: Vec<NamedAbiType>,
850 id: Option<u32>,
851}
852
853impl FunctionBuilder {
854 pub fn new<T: Into<String>>(abi_version: AbiVersion, name: T) -> Self {
856 Self {
857 abi_version,
858 name: name.into(),
859 headers: Default::default(),
860 inputs: Default::default(),
861 outputs: Default::default(),
862 id: None,
863 }
864 }
865
866 pub fn build(self) -> Function {
868 let (input_id, output_id) = match self.id {
869 Some(id) => (id, id),
870 None => {
871 let id = Function::compute_function_id(
872 self.abi_version,
873 &self.name,
874 &self.headers,
875 &self.inputs,
876 &self.outputs,
877 );
878 (id & Function::INPUT_ID_MASK, id | !Function::INPUT_ID_MASK)
879 }
880 };
881
882 Function {
883 abi_version: self.abi_version,
884 headers: Arc::from(self.headers),
885 name: Arc::from(self.name),
886 inputs: Arc::from(self.inputs),
887 outputs: Arc::from(self.outputs),
888 input_id,
889 output_id,
890 }
891 }
892
893 pub fn with_headers<I: IntoIterator<Item = AbiHeaderType>>(mut self, headers: I) -> Self {
895 self.headers = headers.into_iter().collect();
896 self
897 }
898
899 pub fn with_inputs<I, T>(mut self, inputs: I) -> Self
901 where
902 I: IntoIterator<Item = T>,
903 T: Into<NamedAbiType>,
904 {
905 self.inputs = inputs.into_iter().map(Into::into).collect();
906 self
907 }
908
909 pub fn with_unnamed_inputs<I: IntoIterator<Item = AbiType>>(mut self, inputs: I) -> Self {
911 self.inputs = inputs
912 .into_iter()
913 .enumerate()
914 .map(NamedAbiType::from)
915 .collect();
916 self
917 }
918
919 pub fn with_outputs<I, T>(mut self, outputs: I) -> Self
921 where
922 I: IntoIterator<Item = NamedAbiType>,
923 T: Into<NamedAbiType>,
924 {
925 self.outputs = outputs.into_iter().collect();
926 self
927 }
928
929 pub fn with_unnamed_outputs<I: IntoIterator<Item = AbiType>>(mut self, outputs: I) -> Self {
931 self.outputs = outputs
932 .into_iter()
933 .enumerate()
934 .map(NamedAbiType::from)
935 .collect();
936 self
937 }
938
939 pub fn with_id(mut self, id: u32) -> Self {
941 self.id = Some(id);
942 self
943 }
944}
945
946#[derive(Debug, Clone)]
948pub struct Event {
949 pub abi_version: AbiVersion,
951 pub name: Arc<str>,
953 pub inputs: Arc<[NamedAbiType]>,
955 pub id: u32,
957}
958
959impl Event {
960 pub fn compute_event_id(abi_version: AbiVersion, name: &str, inputs: &[NamedAbiType]) -> u32 {
962 let mut hasher = sha2::Sha256::new();
963 EventSignatureRaw {
964 abi_version,
965 name,
966 inputs,
967 }
968 .update_hasher(&mut hasher);
969
970 let hash: [u8; 32] = hasher.finalize().into();
971 u32::from_be_bytes(hash[0..4].try_into().unwrap())
972 }
973
974 #[inline]
976 pub fn builder<T: Into<String>>(abi_version: AbiVersion, name: T) -> EventBuilder {
977 EventBuilder::new(abi_version, name)
978 }
979
980 pub fn encode_internal_input(&self, tokens: &[NamedAbiValue]) -> Result<CellBuilder> {
982 ok!(NamedAbiValue::check_types(tokens, &self.inputs));
983 Function::encode_internal_msg_body(self.abi_version, self.id, tokens)
984 }
985
986 pub fn decode_internal_input(&self, mut slice: CellSlice<'_>) -> Result<Vec<NamedAbiValue>> {
990 self.decode_internal_input_ext(&mut slice, false)
991 }
992
993 pub fn decode_internal_input_ext(
995 &self,
996 slice: &mut CellSlice<'_>,
997 allow_partial: bool,
998 ) -> Result<Vec<NamedAbiValue>> {
999 let id = slice.load_u32()?;
1000 anyhow::ensure!(
1001 id == self.id,
1002 AbiError::InputIdMismatch {
1003 expected: self.id,
1004 id
1005 }
1006 );
1007 let res = ok!(NamedAbiValue::load_tuple_ext(
1008 &self.inputs,
1009 self.abi_version,
1010 true,
1011 allow_partial,
1012 slice
1013 ));
1014 ok!(AbiValue::check_remaining(slice, allow_partial));
1015 Ok(res)
1016 }
1017
1018 pub fn display_signature(&self) -> impl std::fmt::Display + '_ {
1020 EventSignatureRaw {
1021 abi_version: self.abi_version,
1022 name: &self.name,
1023 inputs: &self.inputs,
1024 }
1025 }
1026}
1027
1028#[derive(Debug, Clone)]
1030pub struct EventBuilder {
1031 abi_version: AbiVersion,
1032 name: String,
1033 inputs: Vec<NamedAbiType>,
1034 id: Option<u32>,
1035}
1036
1037impl EventBuilder {
1038 pub fn new<T: Into<String>>(abi_version: AbiVersion, name: T) -> Self {
1040 Self {
1041 abi_version,
1042 name: name.into(),
1043 inputs: Default::default(),
1044 id: None,
1045 }
1046 }
1047
1048 pub fn build(self) -> Event {
1050 let id = match self.id {
1051 Some(id) => id,
1052 None => {
1053 let id = Event::compute_event_id(self.abi_version, &self.name, &self.inputs);
1054 id & Function::INPUT_ID_MASK
1055 }
1056 };
1057
1058 Event {
1059 abi_version: self.abi_version,
1060 name: Arc::from(self.name),
1061 inputs: Arc::from(self.inputs),
1062 id,
1063 }
1064 }
1065
1066 pub fn with_inputs<I, T>(mut self, inputs: I) -> Self
1068 where
1069 I: IntoIterator<Item = T>,
1070 T: Into<NamedAbiType>,
1071 {
1072 self.inputs = inputs.into_iter().map(Into::into).collect();
1073 self
1074 }
1075
1076 pub fn with_unnamed_inputs<I: IntoIterator<Item = AbiType>>(mut self, inputs: I) -> Self {
1078 self.inputs = inputs
1079 .into_iter()
1080 .enumerate()
1081 .map(NamedAbiType::from)
1082 .collect();
1083 self
1084 }
1085
1086 pub fn with_id(mut self, id: u32) -> Self {
1088 self.id = Some(id);
1089 self
1090 }
1091}
1092
1093pub struct UnsignedExternalMessage {
1095 pub dst: StdAddr,
1097 pub body: UnsignedBody,
1099 pub init: Option<StateInit>,
1101}
1102
1103impl UnsignedExternalMessage {
1104 pub fn set_state_init(&mut self, init: Option<StateInit>) {
1106 self.init = init;
1107 }
1108
1109 pub fn with_state_init(mut self, init: StateInit) -> Self {
1111 self.set_state_init(Some(init));
1112 self
1113 }
1114
1115 #[inline]
1117 pub fn expire_at(&self) -> u32 {
1118 self.body.expire_at
1119 }
1120
1121 pub fn sign(
1123 self,
1124 key: &ed25519_dalek::SigningKey,
1125 signature_id: Option<i32>,
1126 ) -> Result<OwnedMessage> {
1127 let signature =
1128 crate::abi::sign_with_signature_id(key, self.body.hash.as_slice(), signature_id);
1129 self.with_signature(&signature)
1130 }
1131
1132 pub fn with_signature(self, signature: &ed25519_dalek::Signature) -> Result<OwnedMessage> {
1134 self.into_signed(Some(&signature.to_bytes()))
1135 }
1136
1137 pub fn with_fake_signature(self) -> Result<OwnedMessage> {
1139 self.into_signed(Some(&[0u8; 64]))
1140 }
1141
1142 pub fn without_signature(self) -> Result<OwnedMessage> {
1144 self.into_signed(None)
1145 }
1146
1147 pub fn fill_signature(&self, signature: Option<&[u8; 64]>) -> Result<OwnedMessage> {
1149 let body = self.body.fill_signature(signature)?;
1150 let range = CellSliceRange::full(body.as_ref());
1151 Ok(OwnedMessage {
1152 info: MsgInfo::ExtIn(ExtInMsgInfo {
1153 dst: IntAddr::Std(self.dst.clone()),
1154 ..Default::default()
1155 }),
1156 body: (body, range),
1157 init: self.init.clone(),
1158 layout: None,
1159 })
1160 }
1161
1162 fn into_signed(self, signature: Option<&[u8; 64]>) -> Result<OwnedMessage> {
1164 let body = self.body.fill_signature(signature)?;
1165 let range = CellSliceRange::full(body.as_ref());
1166 Ok(OwnedMessage {
1167 info: MsgInfo::ExtIn(ExtInMsgInfo {
1168 dst: IntAddr::Std(self.dst),
1169 ..Default::default()
1170 }),
1171 body: (body, range),
1172 init: self.init,
1173 layout: None,
1174 })
1175 }
1176}
1177
1178pub struct UnsignedBody {
1180 pub abi_version: AbiVersion,
1182 pub payload: Cell,
1184 pub hash: HashBytes,
1186 pub expire_at: u32,
1188}
1189
1190impl UnsignedBody {
1191 pub fn with_dst(self, dst: StdAddr) -> UnsignedExternalMessage {
1194 UnsignedExternalMessage {
1195 dst,
1196 body: self,
1197 init: None,
1198 }
1199 }
1200
1201 pub fn sign(self, key: &ed25519_dalek::SigningKey, signature_id: Option<i32>) -> Result<Cell> {
1203 let signature = crate::abi::sign_with_signature_id(key, self.hash.as_slice(), signature_id);
1204 self.with_signature(&signature)
1205 }
1206
1207 pub fn with_signature(self, signature: &ed25519_dalek::Signature) -> Result<Cell> {
1209 self.fill_signature(Some(&signature.to_bytes()))
1210 }
1211
1212 pub fn with_fake_signature(self) -> Result<Cell> {
1214 self.fill_signature(Some(&[0u8; 64]))
1215 }
1216
1217 pub fn without_signature(self) -> Result<Cell> {
1219 self.fill_signature(None)
1220 }
1221
1222 pub fn fill_signature(&self, signature: Option<&[u8; 64]>) -> Result<Cell> {
1224 let mut builder = CellBuilder::new();
1225
1226 if self.abi_version.major == 1 {
1227 builder.store_reference(match signature {
1228 Some(signature) => {
1229 CellBuilder::from_raw_data(signature, 512).and_then(CellBuilder::build)?
1231 }
1232 None => Cell::empty_cell(),
1233 })?;
1234 } else {
1235 match signature {
1236 Some(signature) => {
1237 builder.store_bit_one()?;
1238 builder.store_raw(signature, 512)?;
1239 }
1240 None => builder.store_bit_zero()?,
1241 }
1242 builder.store_slice(self.payload.as_slice()?)?;
1243 }
1244
1245 builder.build().map_err(From::from)
1246 }
1247}
1248
1249struct FunctionSignatureRaw<'a> {
1250 abi_version: AbiVersion,
1251 name: &'a str,
1252 headers: &'a [AbiHeaderType],
1253 inputs: &'a [NamedAbiType],
1254 outputs: &'a [NamedAbiType],
1255}
1256
1257impl FunctionSignatureRaw<'_> {
1258 fn update_hasher<H: Digest>(&self, engine: &mut H) {
1259 std::fmt::write(&mut DisplayHasher(engine), format_args!("{self}")).unwrap();
1260 }
1261}
1262
1263impl std::fmt::Display for FunctionSignatureRaw<'_> {
1264 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1265 ok!(write!(f, "{}(", self.name));
1266
1267 let mut first = true;
1268 if self.abi_version.major == 1 {
1269 for header in self.headers {
1270 if !std::mem::take(&mut first) {
1271 ok!(f.write_str(","));
1272 }
1273 ok!(std::fmt::Display::fmt(header, f));
1274 }
1275 }
1276 for item in self.inputs {
1277 if !std::mem::take(&mut first) {
1278 ok!(f.write_str(","));
1279 }
1280 ok!(std::fmt::Display::fmt(&item.ty, f));
1281 }
1282
1283 ok!(f.write_str(")("));
1284
1285 first = true;
1286 for item in self.outputs {
1287 if !std::mem::take(&mut first) {
1288 ok!(f.write_str(","));
1289 }
1290 ok!(std::fmt::Display::fmt(&item.ty, f));
1291 }
1292
1293 write!(f, ")v{}", self.abi_version.major)
1294 }
1295}
1296
1297struct EventSignatureRaw<'a> {
1298 abi_version: AbiVersion,
1299 name: &'a str,
1300 inputs: &'a [NamedAbiType],
1301}
1302
1303impl EventSignatureRaw<'_> {
1304 fn update_hasher<H: Digest>(&self, engine: &mut H) {
1305 std::fmt::write(&mut DisplayHasher(engine), format_args!("{self}")).unwrap();
1306 }
1307}
1308
1309impl std::fmt::Display for EventSignatureRaw<'_> {
1310 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1311 ok!(write!(f, "{}(", self.name));
1312
1313 let mut first = true;
1314 for item in self.inputs {
1315 if !std::mem::take(&mut first) {
1316 ok!(f.write_str(","));
1317 }
1318 ok!(std::fmt::Display::fmt(&item.ty, f));
1319 }
1320 write!(f, ")v{}", self.abi_version.major)
1321 }
1322}
1323
1324#[repr(transparent)]
1325struct DisplayHasher<'a, H>(&'a mut H);
1326
1327impl<H: Digest> std::fmt::Write for DisplayHasher<'_, H> {
1328 #[inline]
1329 fn write_str(&mut self, s: &str) -> std::fmt::Result {
1330 self.0.update(s.as_bytes());
1331 Ok(())
1332 }
1333}