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