1use std::borrow::Cow;
2use std::collections::HashSet;
3use std::str::FromStr;
4use std::sync::Arc;
5
6use ahash::HashMap;
7use anyhow::Result;
8use serde::Deserialize;
9use sha2::Digest;
10
11use super::error::AbiError;
12use super::{AbiHeaderType, AbiType, AbiValue, AbiVersion, NamedAbiType, NamedAbiValue};
13use crate::abi::AbiHeader;
14use crate::abi::value::ser::AbiSerializer;
15use crate::cell::{
16 Cell, CellBuilder, CellDataBuilder, CellFamily, CellSlice, DynCell, HashBytes, Size, Store,
17};
18use crate::dict::RawDict;
19use crate::models::{
20 ExtInMsgInfo, IntAddr, MsgInfo, OwnedMessage, OwnedRelaxedMessage, RelaxedIntMsgInfo,
21 RelaxedMsgInfo, StateInit, StdAddr,
22};
23use crate::num::Tokens;
24use crate::prelude::Dict;
25
26const PUBKEY_FIELD: &str = "_pubkey";
27
28pub struct Contract {
30 pub abi_version: AbiVersion,
32
33 pub headers: Arc<[AbiHeaderType]>,
37
38 pub functions: HashMap<Arc<str>, Function>,
40
41 pub events: HashMap<Arc<str>, Event>,
43
44 pub init_data: ContractInitData,
46
47 pub fields: Arc<[NamedAbiType]>,
49
50 pub getters: HashMap<Arc<str>, Getter>,
52}
53
54pub enum ContractInitData {
55 Dict(HashMap<Arc<str>, (u64, NamedAbiType)>),
56 PlainFields(HashSet<Arc<str>>),
57}
58
59impl Contract {
60 pub fn find_function_by_id(&self, id: u32, input: bool) -> Option<&Function> {
62 self.functions
63 .values()
64 .find(|item| input && item.input_id == id || !input && item.output_id == id)
65 }
66
67 pub fn find_event_by_id(&self, id: u32) -> Option<&Event> {
69 self.events.values().find(|event| event.id == id)
70 }
71
72 pub fn update_init_data(
77 &self,
78 pubkey: Option<&ed25519_dalek::VerifyingKey>,
79 tokens: &[NamedAbiValue],
80 data: &Cell,
81 ) -> Result<Cell> {
82 if self.abi_version < AbiVersion::V2_4 {
83 self.update_init_data_dict(pubkey, tokens, data)
84 } else {
85 self.update_init_data_plain(pubkey, tokens, data)
86 }
87 }
88
89 fn update_init_data_dict(
90 &self,
91 pubkey: Option<&ed25519_dalek::VerifyingKey>,
92 tokens: &[NamedAbiValue],
93 data: &Cell,
94 ) -> Result<Cell> {
95 let mut result = data.parse::<RawDict<64>>()?;
97
98 if pubkey.is_none() && tokens.is_empty() {
99 return Ok(data.clone());
101 }
102
103 let ContractInitData::Dict(init_data) = &self.init_data else {
104 anyhow::bail!("Plain init_data is not supported for ABI version < 2.4")
105 };
106
107 let context = Cell::empty_context();
108 let mut key_builder = CellDataBuilder::new();
109
110 for token in tokens {
111 let Some((key, ty)) = init_data.get(token.name.as_ref()) else {
112 anyhow::bail!(AbiError::UnexpectedInitDataParam(token.name.clone()));
113 };
114 token.check_type(ty)?;
115
116 key_builder.store_u64(*key)?;
117
118 result.set_ext(
119 key_builder.as_data_slice(),
120 &token.make_builder(self.abi_version)?.as_full_slice(),
121 context,
122 )?;
123
124 key_builder.clear_bits();
125 }
126
127 if let Some(pubkey) = pubkey {
129 key_builder.store_u64(0)?;
130 result.set_ext(
131 key_builder.as_data_slice(),
132 &CellBuilder::from_raw_data(pubkey.as_bytes(), 256)?.as_data_slice(),
133 context,
134 )?;
135 }
136
137 CellBuilder::build_from_ext(result, context).map_err(From::from)
139 }
140
141 fn update_init_data_plain(
142 &self,
143 mut pubkey: Option<&ed25519_dalek::VerifyingKey>,
144 tokens: &[NamedAbiValue],
145 data: &Cell,
146 ) -> Result<Cell> {
147 let ContractInitData::PlainFields(init_data) = &self.init_data else {
148 anyhow::bail!("Dict init_data is not supported for ABI version >= 2.4")
149 };
150
151 let mut data_slice = data.as_slice()?;
152
153 let mut init_values = Vec::with_capacity(self.fields.len());
154
155 let mut tokens_map = HashMap::with_capacity_and_hasher(tokens.len(), Default::default());
156 for i in tokens {
157 tokens_map.insert(i.name.as_ref(), i.value.clone());
158 }
159
160 for i in self.fields.as_ref() {
161 let old_value = AbiValue::load_partial(&i.ty, self.abi_version, &mut data_slice)?;
162
163 let mut token = tokens_map.remove(i.name.as_ref());
164
165 if i.name.as_ref() == PUBKEY_FIELD
166 && let Some(pubkey) = pubkey.take()
167 {
168 token = Some(AbiValue::Uint(
170 256,
171 HashBytes::wrap(pubkey.as_bytes()).as_biguint(),
172 ));
173 }
174
175 init_values.push(if let Some(token) = token {
176 anyhow::ensure!(
177 init_data.contains(i.name.as_ref()),
178 AbiError::UnexpectedInitDataParam(i.name.clone())
179 );
180 token
181 } else {
182 old_value
183 });
184 }
185
186 anyhow::ensure!(pubkey.is_none(), AbiError::PubkeyNotUsed);
187
188 let cell = AbiValue::tuple_to_cell(init_values.as_ref(), self.abi_version)?;
189 Ok(cell)
190 }
191
192 pub fn encode_init_data(
197 &self,
198 pubkey: Option<&ed25519_dalek::VerifyingKey>,
199 tokens: &[NamedAbiValue],
200 ) -> Result<Cell> {
201 if self.abi_version < AbiVersion::V2_4 {
202 self.encode_init_data_dict(pubkey, tokens)
203 } else {
204 self.encode_init_data_plain(pubkey, tokens)
205 }
206 }
207
208 fn encode_init_data_dict(
209 &self,
210 pubkey: Option<&ed25519_dalek::VerifyingKey>,
211 tokens: &[NamedAbiValue],
212 ) -> Result<Cell> {
213 let ContractInitData::Dict(init_data) = &self.init_data else {
214 anyhow::bail!("Plain init fields are not supported")
215 };
216
217 let mut result = RawDict::<64>::new();
218
219 let mut init_data = init_data
220 .iter()
221 .map(|(name, value)| (name.as_ref(), value))
222 .collect::<HashMap<_, _>>();
223
224 let context = Cell::empty_context();
225 let mut key_builder = CellDataBuilder::new();
226
227 for token in tokens {
229 let Some((key, ty)) = init_data.remove(token.name.as_ref()) else {
230 anyhow::bail!(AbiError::UnexpectedInitDataParam(token.name.clone()));
231 };
232 token.check_type(ty)?;
233
234 key_builder.store_u64(*key)?;
235
236 result.set_ext(
237 key_builder.as_data_slice(),
238 &token.make_builder(self.abi_version)?.as_full_slice(),
239 context,
240 )?;
241
242 key_builder.clear_bits();
243 }
244
245 for (key, ty) in init_data.into_values() {
247 key_builder.store_u64(*key)?;
248
249 result.set_ext(
250 key_builder.as_data_slice(),
251 &ty.make_default_value()
252 .make_builder(self.abi_version)?
253 .as_full_slice(),
254 context,
255 )?;
256
257 key_builder.clear_bits();
258 }
259
260 key_builder.store_u64(0)?;
262 result.set_ext(
263 key_builder.as_data_slice(),
264 &CellBuilder::from_raw_data(
265 pubkey.map(|value| value.as_bytes()).unwrap_or(&[0; 32]),
266 256,
267 )?
268 .as_data_slice(),
269 context,
270 )?;
271
272 CellBuilder::build_from_ext(result, context).map_err(From::from)
274 }
275
276 fn encode_init_data_plain(
277 &self,
278 mut pubkey: Option<&ed25519_dalek::VerifyingKey>,
279 tokens: &[NamedAbiValue],
280 ) -> Result<Cell> {
281 let ContractInitData::PlainFields(init_data) = &self.init_data else {
282 anyhow::bail!("Dict init_data is not supported for ABI version >= 2.4")
283 };
284
285 let mut init_values = Vec::with_capacity(self.fields.len());
286
287 let mut tokens_map = HashMap::with_capacity_and_hasher(tokens.len(), Default::default());
288 for i in tokens {
289 tokens_map.insert(i.name.as_ref(), i.value.clone());
290 }
291
292 for i in self.fields.as_ref() {
293 let mut token = tokens_map.remove(i.name.as_ref());
294
295 if i.name.as_ref() == PUBKEY_FIELD
296 && let Some(pubkey) = pubkey.take()
297 {
298 token = Some(AbiValue::Uint(
300 256,
301 HashBytes::wrap(pubkey.as_bytes()).as_biguint(),
302 ));
303 }
304
305 init_values.push(if init_data.contains(i.name.as_ref()) {
306 token.ok_or_else(|| AbiError::InitDataFieldNotFound(i.name.clone()))?
307 } else {
308 anyhow::ensure!(
309 token.is_none(),
310 AbiError::UnexpectedInitDataParam(i.name.clone())
311 );
312 i.ty.make_default_value()
313 });
314 }
315
316 anyhow::ensure!(pubkey.is_none(), AbiError::PubkeyNotUsed);
317
318 let cell = AbiValue::tuple_to_cell(init_values.as_ref(), self.abi_version)?;
319 Ok(cell)
320 }
321
322 pub fn decode_init_data(&self, data: &DynCell) -> Result<Vec<NamedAbiValue>> {
324 if self.abi_version < AbiVersion::V2_4 {
325 self.decode_init_data_internal(data)
326 } else {
327 self.decode_init_fields(data)
328 }
329 }
330
331 fn decode_init_data_internal(&self, data: &DynCell) -> Result<Vec<NamedAbiValue>> {
332 let init_data = data.parse::<Dict<u64, CellSlice>>()?;
333
334 let ContractInitData::Dict(init_data_map) = &self.init_data else {
335 anyhow::bail!("Plain init fields are not supported")
336 };
337 let mut result = Vec::with_capacity(init_data_map.len());
338
339 for (key, item) in init_data_map.values() {
340 let Some(mut value) = init_data.get(key)? else {
341 anyhow::bail!(AbiError::InitDataFieldNotFound(item.name.clone()));
342 };
343 result.push(NamedAbiValue::load(item, self.abi_version, &mut value)?);
344 }
345
346 Ok(result)
347 }
348
349 fn decode_init_fields(&self, data: &DynCell) -> Result<Vec<NamedAbiValue>> {
350 let ContractInitData::PlainFields(init_fields) = &self.init_data else {
351 anyhow::bail!("Plain init fields are not supported")
352 };
353
354 let values = self.decode_fields(data.as_slice()?)?;
355
356 let mut init_values = Vec::with_capacity(init_fields.len());
357
358 for i in values {
359 if init_fields.contains(i.name.as_ref()) {
360 init_values.push(i)
361 }
362 }
363
364 Ok(init_values)
365 }
366
367 pub fn encode_fields(&self, tokens: &[NamedAbiValue]) -> Result<CellBuilder> {
369 ok!(NamedAbiValue::check_types(tokens, &self.fields));
370 NamedAbiValue::tuple_to_builder(tokens, self.abi_version).map_err(From::from)
371 }
372
373 pub fn decode_fields(&self, mut slice: CellSlice<'_>) -> Result<Vec<NamedAbiValue>> {
377 self.decode_fields_ext(&mut slice, false)
378 }
379
380 pub fn decode_fields_ext(
382 &self,
383 slice: &mut CellSlice<'_>,
384 allow_partial: bool,
385 ) -> Result<Vec<NamedAbiValue>> {
386 let res = ok!(NamedAbiValue::load_tuple_ext(
387 &self.fields,
388 self.abi_version,
389 true,
390 allow_partial,
391 slice
392 ));
393 ok!(AbiValue::check_remaining(slice, allow_partial));
394 Ok(res)
395 }
396}
397
398impl<'de> Deserialize<'de> for Contract {
399 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
400 where
401 D: serde::Deserializer<'de>,
402 {
403 use serde::de::Error;
404
405 #[repr(transparent)]
406 struct Id(u32);
407
408 impl<'de> Deserialize<'de> for Id {
409 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
410 where
411 D: serde::Deserializer<'de>,
412 {
413 #[derive(Deserialize)]
414 #[serde(transparent)]
415 struct Id<'a>(#[serde(borrow)] Cow<'a, str>);
416
417 match ok!(Id::deserialize(deserializer)).0.strip_prefix("0x") {
418 Some(s) => u32::from_str_radix(s, 16).map(Self).map_err(Error::custom),
419 None => Err(Error::custom("Hex number must be prefixed with 0x")),
420 }
421 }
422 }
423
424 #[derive(Deserialize)]
425 struct SerdeNamedAbiType {
426 #[serde(flatten)]
427 named_abi_type: NamedAbiType,
428 #[serde(default)]
429 init: bool,
430 }
431
432 #[derive(Deserialize)]
433 struct SerdeContract {
434 #[serde(default, rename = "ABI version")]
435 abi_version: Option<u8>,
436 #[serde(default)]
437 version: Option<String>,
438 #[serde(default)]
439 header: Vec<AbiHeaderType>,
440 functions: Vec<SerdeFunction>,
441 #[serde(default)]
442 events: Vec<SerdeEvent>,
443 #[serde(default)]
444 data: Vec<InitData>,
445 #[serde(default)]
446 fields: Vec<SerdeNamedAbiType>,
447 #[serde(default)]
448 getters: Vec<SerdeFunction>,
449 }
450
451 #[derive(Deserialize)]
452 struct SerdeFunction {
453 name: String,
454 #[serde(default)]
455 inputs: Vec<NamedAbiType>,
456 #[serde(default)]
457 outputs: Vec<NamedAbiType>,
458 #[serde(default)]
459 id: Option<Id>,
460 }
461
462 #[derive(Deserialize)]
463 struct SerdeEvent {
464 name: String,
465 #[serde(default)]
466 inputs: Vec<NamedAbiType>,
467 #[serde(default)]
468 id: Option<Id>,
469 }
470
471 #[derive(Deserialize)]
472 struct InitData {
473 key: u64,
474 #[serde(flatten)]
475 ty: NamedAbiType,
476 }
477
478 let contract = ok!(SerdeContract::deserialize(deserializer));
479 let abi_version = if let Some(version) = &contract.version {
480 ok!(AbiVersion::from_str(version).map_err(Error::custom))
481 } else if let Some(major) = contract.abi_version {
482 AbiVersion::new(major, 0)
483 } else {
484 return Err(Error::custom("No ABI version found"));
485 };
486
487 let headers = Arc::<[AbiHeaderType]>::from(contract.header);
488
489 let functions = contract
490 .functions
491 .into_iter()
492 .map(|item| {
493 let (input_id, output_id) = match item.id {
494 Some(Id(id)) => (id, id),
495 None => {
496 let id = Function::compute_function_id(
497 abi_version,
498 &item.name,
499 headers.as_ref(),
500 &item.inputs,
501 &item.outputs,
502 );
503 (id & Function::INPUT_ID_MASK, id | !Function::INPUT_ID_MASK)
504 }
505 };
506 let name = Arc::<str>::from(item.name);
507 (name.clone(), Function {
508 abi_version,
509 name,
510 headers: headers.clone(),
511 inputs: Arc::from(item.inputs),
512 outputs: Arc::from(item.outputs),
513 input_id,
514 output_id,
515 })
516 })
517 .collect();
518
519 let getters = contract
520 .getters
521 .into_iter()
522 .map(|item| {
523 let id = match item.id {
524 Some(Id(id)) => id,
525 None => Getter::compute_getter_id::<&str>(item.name.as_ref()),
526 };
527 let name = Arc::<str>::from(item.name);
528 (name.clone(), Getter {
529 name,
530 outputs: Arc::from(item.outputs),
531 id,
532 })
533 })
534 .collect();
535
536 let events = contract
537 .events
538 .into_iter()
539 .map(|item| {
540 let id = match item.id {
541 Some(Id(id)) => id,
542 None => {
543 let id = Event::compute_event_id(abi_version, &item.name, &item.inputs);
544 id & Function::INPUT_ID_MASK
545 }
546 };
547 let name = Arc::<str>::from(item.name);
548 (name.clone(), Event {
549 abi_version,
550 name,
551 inputs: Arc::from(item.inputs),
552 id,
553 })
554 })
555 .collect();
556
557 let init_data = if abi_version >= AbiVersion::V2_4 {
558 let init_fields = contract
559 .fields
560 .iter()
561 .filter(|x| x.init)
562 .map(|x| x.named_abi_type.name.clone())
563 .collect();
564 ContractInitData::PlainFields(init_fields)
565 } else {
566 let data = contract
567 .data
568 .into_iter()
569 .map(|item| {
570 let name = item.ty.name.clone();
571 (name, (item.key, item.ty))
572 })
573 .collect();
574
575 ContractInitData::Dict(data)
576 };
577
578 Ok(Self {
579 abi_version,
580 headers,
581 functions,
582 events,
583 init_data,
584 fields: Arc::from(
585 contract
586 .fields
587 .into_iter()
588 .map(|x| x.named_abi_type)
589 .collect::<Vec<_>>(),
590 ),
591 getters,
592 })
593 }
594}
595
596pub trait AsGetterMethodId {
598 fn as_getter_method_id(&self) -> u32;
599}
600
601impl<T: AsGetterMethodId + ?Sized> AsGetterMethodId for &T {
602 fn as_getter_method_id(&self) -> u32 {
603 T::as_getter_method_id(*self)
604 }
605}
606
607impl<T: AsGetterMethodId + ?Sized> AsGetterMethodId for &mut T {
608 fn as_getter_method_id(&self) -> u32 {
609 T::as_getter_method_id(*self)
610 }
611}
612
613impl AsGetterMethodId for u32 {
614 fn as_getter_method_id(&self) -> u32 {
615 *self
616 }
617}
618
619impl AsGetterMethodId for str {
620 fn as_getter_method_id(&self) -> u32 {
621 let crc = crate::crc::crc_16(self.as_bytes());
622 crc as u32 | 0x10000
623 }
624}
625
626#[derive(Debug, Clone)]
627pub struct Getter {
628 pub name: Arc<str>,
630 pub outputs: Arc<[NamedAbiType]>,
632 pub id: u32,
634}
635
636impl Getter {
637 pub fn compute_getter_id<T: AsGetterMethodId>(input: T) -> u32 {
638 input.as_getter_method_id()
639 }
640}
641
642#[derive(Debug, Clone)]
644pub struct Function {
645 pub abi_version: AbiVersion,
647 pub headers: Arc<[AbiHeaderType]>,
652 pub name: Arc<str>,
654 pub inputs: Arc<[NamedAbiType]>,
656 pub outputs: Arc<[NamedAbiType]>,
658 pub input_id: u32,
660 pub output_id: u32,
662}
663
664impl Function {
665 pub const INPUT_ID_MASK: u32 = 0x7fffffff;
667
668 pub fn compute_function_id(
670 abi_version: AbiVersion,
671 name: &str,
672 headers: &[AbiHeaderType],
673 inputs: &[NamedAbiType],
674 outputs: &[NamedAbiType],
675 ) -> u32 {
676 let mut hasher = sha2::Sha256::new();
677 FunctionSignatureRaw {
678 abi_version,
679 name,
680 headers,
681 inputs,
682 outputs,
683 }
684 .update_hasher(&mut hasher);
685
686 let hash: [u8; 32] = hasher.finalize().into();
687 u32::from_be_bytes(hash[0..4].try_into().unwrap())
688 }
689
690 pub fn encode_internal_msg_body(
692 version: AbiVersion,
693 id: u32,
694 tokens: &[NamedAbiValue],
695 ) -> Result<CellBuilder> {
696 let mut serializer = AbiSerializer::new(version);
697 let output_id = AbiValue::uint(32, id);
698
699 serializer.reserve_value(&output_id);
700 for token in tokens {
701 serializer.reserve_value(&token.value);
702 }
703
704 let context = Cell::empty_context();
705 serializer.write_value(&output_id, version, context)?;
706 serializer.write_tuple(tokens, version, context)?;
707 serializer.finalize(context).map_err(From::from)
708 }
709
710 #[inline]
712 pub fn builder<T: Into<String>>(abi_version: AbiVersion, name: T) -> FunctionBuilder {
713 FunctionBuilder::new(abi_version, name)
714 }
715
716 pub fn encode_external<'f, 'a: 'f>(
718 &'f self,
719 tokens: &'a [NamedAbiValue],
720 ) -> ExternalInput<'f, 'a> {
721 ExternalInput {
722 function: self,
723 tokens,
724 time: None,
725 expire_at: None,
726 pubkey: None,
727 address: None,
728 }
729 }
730
731 pub fn decode_external_input(&self, mut slice: CellSlice<'_>) -> Result<Vec<NamedAbiValue>> {
735 self.decode_external_input_ext(&mut slice, false)
736 }
737
738 pub fn decode_external_input_ext(
740 &self,
741 slice: &mut CellSlice<'_>,
742 allow_partial: bool,
743 ) -> Result<Vec<NamedAbiValue>> {
744 let id = if self.abi_version.major == 1 {
746 let id = slice.load_u32()?;
748 slice.load_reference()?;
750 ok!(AbiHeader::skip_all(&self.headers, slice));
752
753 id
754 } else {
755 if slice.load_bit()? {
757 slice.skip_first(512, 0)?;
758 }
759 ok!(AbiHeader::skip_all(&self.headers, slice));
761 slice.load_u32()?
763 };
764
765 anyhow::ensure!(id == self.input_id, AbiError::InputIdMismatch {
767 expected: self.input_id,
768 id
769 });
770
771 let res = ok!(NamedAbiValue::load_tuple_ext(
772 &self.inputs,
773 self.abi_version,
774 true,
775 allow_partial,
776 slice
777 ));
778 ok!(AbiValue::check_remaining(slice, allow_partial));
779 Ok(res)
780 }
781
782 pub fn encode_internal_input(&self, tokens: &[NamedAbiValue]) -> Result<CellBuilder> {
784 ok!(NamedAbiValue::check_types(tokens, &self.inputs));
785 Self::encode_internal_msg_body(self.abi_version, self.input_id, tokens)
786 }
787
788 pub fn encode_internal_message(
790 &self,
791 tokens: &[NamedAbiValue],
792 dst: IntAddr,
793 value: Tokens,
794 bounce: bool,
795 state_init: Option<&StateInit>,
796 ) -> Result<Box<OwnedRelaxedMessage>> {
797 let body = self.encode_internal_input(tokens)?;
798 let body = body.build()?;
799
800 Ok(Box::new(OwnedRelaxedMessage {
801 info: RelaxedMsgInfo::Int(RelaxedIntMsgInfo {
802 dst,
803 bounce,
804 value: value.into(),
805 ..Default::default()
806 }),
807 body: body.into(),
808 init: state_init.cloned(),
809 layout: None,
810 }))
811 }
812
813 pub fn decode_internal_input(&self, mut slice: CellSlice<'_>) -> Result<Vec<NamedAbiValue>> {
817 self.decode_internal_input_ext(&mut slice, false)
818 }
819
820 pub fn decode_internal_input_ext(
822 &self,
823 slice: &mut CellSlice<'_>,
824 allow_partial: bool,
825 ) -> Result<Vec<NamedAbiValue>> {
826 let id = slice.load_u32()?;
827 anyhow::ensure!(id == self.input_id, AbiError::InputIdMismatch {
828 expected: self.input_id,
829 id
830 });
831 let res = ok!(NamedAbiValue::load_tuple_ext(
832 &self.inputs,
833 self.abi_version,
834 true,
835 allow_partial,
836 slice
837 ));
838 ok!(AbiValue::check_remaining(slice, allow_partial));
839 Ok(res)
840 }
841
842 pub fn encode_output(&self, tokens: &[NamedAbiValue]) -> Result<CellBuilder> {
844 ok!(NamedAbiValue::check_types(tokens, &self.outputs));
845 Self::encode_internal_msg_body(self.abi_version, self.output_id, tokens)
846 }
847
848 pub fn decode_output(&self, mut slice: CellSlice<'_>) -> Result<Vec<NamedAbiValue>> {
852 self.decode_output_ext(&mut slice, false)
853 }
854
855 pub fn decode_output_ext(
857 &self,
858 slice: &mut CellSlice<'_>,
859 allow_partial: bool,
860 ) -> Result<Vec<NamedAbiValue>> {
861 let id = slice.load_u32()?;
862 anyhow::ensure!(id == self.output_id, AbiError::OutputIdMismatch {
863 expected: self.output_id,
864 id
865 });
866 let res = ok!(NamedAbiValue::load_tuple_ext(
867 &self.outputs,
868 self.abi_version,
869 true,
870 allow_partial,
871 slice
872 ));
873 ok!(AbiValue::check_remaining(slice, allow_partial));
874 Ok(res)
875 }
876
877 pub fn display_signature(&self) -> impl std::fmt::Display + '_ {
879 FunctionSignatureRaw {
880 abi_version: self.abi_version,
881 name: &self.name,
882 headers: &self.headers,
883 inputs: &self.inputs,
884 outputs: &self.outputs,
885 }
886 }
887}
888
889#[derive(Clone)]
891pub struct ExternalInput<'f, 'a> {
892 function: &'f Function,
893 tokens: &'a [NamedAbiValue],
894 time: Option<u64>,
895 expire_at: Option<u32>,
896 pubkey: Option<&'a ed25519_dalek::VerifyingKey>,
897 address: Option<&'a StdAddr>,
898}
899
900impl<'a> ExternalInput<'_, 'a> {
901 pub fn build_message(&self, address: &StdAddr) -> Result<UnsignedExternalMessage> {
903 Ok(ok!(self.build_input_ext(Some(address))).with_dst(address.clone()))
904 }
905
906 pub fn build_message_without_signature(
910 &self,
911 address: &StdAddr,
912 ) -> Result<(u32, OwnedMessage)> {
913 let (expire_at, body) = ok!(self.build_input_without_signature());
914 Ok((expire_at, OwnedMessage {
915 info: MsgInfo::ExtIn(ExtInMsgInfo {
916 dst: IntAddr::Std(address.clone()),
917 ..Default::default()
918 }),
919 body: body.into(),
920 init: None,
921 layout: None,
922 }))
923 }
924
925 pub fn build_input(&self) -> Result<UnsignedBody> {
927 self.build_input_ext(self.address)
928 }
929
930 fn build_input_ext(&self, address: Option<&StdAddr>) -> Result<UnsignedBody> {
931 let (expire_at, payload) = self.build_payload(true)?;
932
933 let context = Cell::empty_context();
934 let hash = if self.function.abi_version >= AbiVersion::V2_3 {
935 let mut to_sign = CellBuilder::new();
936 match address {
937 Some(address) => address.store_into(&mut to_sign, context)?,
938 None => anyhow::bail!(AbiError::AddressNotProvided),
939 };
940 to_sign.store_slice(payload.as_slice()?)?;
941 *to_sign.build_ext(context)?.repr_hash()
942 } else {
943 *payload.repr_hash()
944 };
945
946 Ok(UnsignedBody {
947 abi_version: self.function.abi_version,
948 expire_at,
949 payload,
950 hash,
951 })
952 }
953
954 pub fn build_input_without_signature(&self) -> Result<(u32, Cell)> {
956 self.build_payload(false)
957 }
958
959 fn build_payload(&self, reserve_signature: bool) -> Result<(u32, Cell)> {
960 const DEFAULT_TIMEOUT_SEC: u32 = 60;
961
962 fn now_ms() -> u64 {
963 std::time::SystemTime::now()
964 .duration_since(std::time::SystemTime::UNIX_EPOCH)
965 .unwrap()
966 .as_millis() as u64
967 }
968
969 ok!(NamedAbiValue::check_types(
970 self.tokens,
971 &self.function.inputs
972 ));
973
974 let abi_version = self.function.abi_version;
975
976 let mut serializer = AbiSerializer::new(abi_version);
977
978 serializer.add_offset(if abi_version.major == 1 {
979 Size { bits: 0, refs: 1 }
981 } else {
982 let bits = if abi_version >= AbiVersion::V2_3 {
983 IntAddr::BITS_MAX
985 } else {
986 1 + 512
988 };
989 Size { bits, refs: 0 }
990 });
991
992 let input_id = AbiValue::uint(32, self.function.input_id);
993
994 serializer.reserve_headers(&self.function.headers, self.pubkey.is_some());
995 serializer.reserve_value(&input_id);
996 for token in self.tokens {
997 serializer.reserve_value(&token.value);
998 }
999
1000 let context = Cell::empty_context();
1001
1002 if !reserve_signature {
1003 let value = if abi_version.major == 1 {
1004 AbiValue::Cell(Cell::default())
1005 } else {
1006 AbiValue::Bool(false)
1007 };
1008 serializer.reserve_value(&value);
1009 serializer.write_value(&value, abi_version, context)?;
1010 }
1011
1012 let time = self.time.unwrap_or_else(now_ms);
1013 let expire_at = self
1014 .expire_at
1015 .unwrap_or((time / 1000) as u32 + DEFAULT_TIMEOUT_SEC);
1016
1017 for header in self.function.headers.as_ref() {
1018 serializer.write_header_value(&match header {
1019 AbiHeaderType::Time => AbiHeader::Time(time),
1020 AbiHeaderType::Expire => AbiHeader::Expire(expire_at),
1021 AbiHeaderType::PublicKey => {
1022 AbiHeader::PublicKey(self.pubkey.map(|key| Box::new(*key)))
1023 }
1024 })?;
1025 }
1026
1027 serializer.write_value(&input_id, abi_version, context)?;
1028 serializer.write_tuple(self.tokens, abi_version, context)?;
1029
1030 let payload = serializer.finalize(context)?.build_ext(context)?;
1031 Ok((expire_at, payload))
1032 }
1033
1034 #[inline]
1036 pub fn set_time(&mut self, time: u64) {
1037 self.time = Some(time);
1038 }
1039
1040 #[inline]
1042 pub fn with_time(mut self, time: u64) -> Self {
1043 self.set_time(time);
1044 self
1045 }
1046
1047 #[inline]
1049 pub fn set_expire_at(&mut self, expire_at: u32) {
1050 self.expire_at = Some(expire_at);
1051 }
1052
1053 #[inline]
1055 pub fn with_expire_at(mut self, expire_at: u32) -> Self {
1056 self.set_expire_at(expire_at);
1057 self
1058 }
1059
1060 #[inline]
1062 pub fn set_pubkey(&mut self, pubkey: &'a ed25519_dalek::VerifyingKey) {
1063 self.pubkey = Some(pubkey);
1064 }
1065
1066 #[inline]
1068 pub fn with_pubkey(mut self, pubkey: &'a ed25519_dalek::VerifyingKey) -> Self {
1069 self.set_pubkey(pubkey);
1070 self
1071 }
1072
1073 #[inline]
1075 pub fn set_address(&mut self, address: &'a StdAddr) {
1076 self.address = Some(address);
1077 }
1078
1079 #[inline]
1081 pub fn with_address(mut self, address: &'a StdAddr) -> Self {
1082 self.set_address(address);
1083 self
1084 }
1085}
1086
1087#[derive(Debug, Clone)]
1089pub struct FunctionBuilder {
1090 abi_version: AbiVersion,
1091 name: String,
1092 headers: Vec<AbiHeaderType>,
1093 inputs: Vec<NamedAbiType>,
1094 outputs: Vec<NamedAbiType>,
1095 id: Option<u32>,
1096}
1097
1098impl FunctionBuilder {
1099 pub fn new<T: Into<String>>(abi_version: AbiVersion, name: T) -> Self {
1101 Self {
1102 abi_version,
1103 name: name.into(),
1104 headers: Default::default(),
1105 inputs: Default::default(),
1106 outputs: Default::default(),
1107 id: None,
1108 }
1109 }
1110
1111 pub fn build(self) -> Function {
1113 let (input_id, output_id) = match self.id {
1114 Some(id) => (id, id),
1115 None => {
1116 let id = Function::compute_function_id(
1117 self.abi_version,
1118 &self.name,
1119 &self.headers,
1120 &self.inputs,
1121 &self.outputs,
1122 );
1123 (id & Function::INPUT_ID_MASK, id | !Function::INPUT_ID_MASK)
1124 }
1125 };
1126
1127 Function {
1128 abi_version: self.abi_version,
1129 headers: Arc::from(self.headers),
1130 name: Arc::from(self.name),
1131 inputs: Arc::from(self.inputs),
1132 outputs: Arc::from(self.outputs),
1133 input_id,
1134 output_id,
1135 }
1136 }
1137
1138 pub fn with_headers<I: IntoIterator<Item = AbiHeaderType>>(mut self, headers: I) -> Self {
1140 self.headers = headers.into_iter().collect();
1141 self
1142 }
1143
1144 pub fn with_inputs<I, T>(mut self, inputs: I) -> Self
1146 where
1147 I: IntoIterator<Item = T>,
1148 T: Into<NamedAbiType>,
1149 {
1150 self.inputs = inputs.into_iter().map(Into::into).collect();
1151 self
1152 }
1153
1154 pub fn with_unnamed_inputs<I: IntoIterator<Item = AbiType>>(mut self, inputs: I) -> Self {
1156 self.inputs = inputs
1157 .into_iter()
1158 .enumerate()
1159 .map(NamedAbiType::from)
1160 .collect();
1161 self
1162 }
1163
1164 pub fn with_outputs<I, T>(mut self, outputs: I) -> Self
1166 where
1167 I: IntoIterator<Item = T>,
1168 T: Into<NamedAbiType>,
1169 {
1170 self.outputs = outputs.into_iter().map(Into::into).collect();
1171 self
1172 }
1173
1174 pub fn with_unnamed_outputs<I: IntoIterator<Item = AbiType>>(mut self, outputs: I) -> Self {
1176 self.outputs = outputs
1177 .into_iter()
1178 .enumerate()
1179 .map(NamedAbiType::from)
1180 .collect();
1181 self
1182 }
1183
1184 pub fn with_id(mut self, id: u32) -> Self {
1186 self.id = Some(id);
1187 self
1188 }
1189}
1190
1191#[derive(Debug, Clone)]
1193pub struct Event {
1194 pub abi_version: AbiVersion,
1196 pub name: Arc<str>,
1198 pub inputs: Arc<[NamedAbiType]>,
1200 pub id: u32,
1202}
1203
1204impl Event {
1205 pub fn compute_event_id(abi_version: AbiVersion, name: &str, inputs: &[NamedAbiType]) -> u32 {
1207 let mut hasher = sha2::Sha256::new();
1208 EventSignatureRaw {
1209 abi_version,
1210 name,
1211 inputs,
1212 }
1213 .update_hasher(&mut hasher);
1214
1215 let hash: [u8; 32] = hasher.finalize().into();
1216 u32::from_be_bytes(hash[0..4].try_into().unwrap())
1217 }
1218
1219 #[inline]
1221 pub fn builder<T: Into<String>>(abi_version: AbiVersion, name: T) -> EventBuilder {
1222 EventBuilder::new(abi_version, name)
1223 }
1224
1225 pub fn encode_internal_input(&self, tokens: &[NamedAbiValue]) -> Result<CellBuilder> {
1227 ok!(NamedAbiValue::check_types(tokens, &self.inputs));
1228 Function::encode_internal_msg_body(self.abi_version, self.id, tokens)
1229 }
1230
1231 pub fn decode_internal_input(&self, mut slice: CellSlice<'_>) -> Result<Vec<NamedAbiValue>> {
1235 self.decode_internal_input_ext(&mut slice, false)
1236 }
1237
1238 pub fn decode_internal_input_ext(
1240 &self,
1241 slice: &mut CellSlice<'_>,
1242 allow_partial: bool,
1243 ) -> Result<Vec<NamedAbiValue>> {
1244 let id = slice.load_u32()?;
1245 anyhow::ensure!(id == self.id, AbiError::InputIdMismatch {
1246 expected: self.id,
1247 id
1248 });
1249 let res = ok!(NamedAbiValue::load_tuple_ext(
1250 &self.inputs,
1251 self.abi_version,
1252 true,
1253 allow_partial,
1254 slice
1255 ));
1256 ok!(AbiValue::check_remaining(slice, allow_partial));
1257 Ok(res)
1258 }
1259
1260 pub fn display_signature(&self) -> impl std::fmt::Display + '_ {
1262 EventSignatureRaw {
1263 abi_version: self.abi_version,
1264 name: &self.name,
1265 inputs: &self.inputs,
1266 }
1267 }
1268}
1269
1270#[derive(Debug, Clone)]
1272pub struct EventBuilder {
1273 abi_version: AbiVersion,
1274 name: String,
1275 inputs: Vec<NamedAbiType>,
1276 id: Option<u32>,
1277}
1278
1279impl EventBuilder {
1280 pub fn new<T: Into<String>>(abi_version: AbiVersion, name: T) -> Self {
1282 Self {
1283 abi_version,
1284 name: name.into(),
1285 inputs: Default::default(),
1286 id: None,
1287 }
1288 }
1289
1290 pub fn build(self) -> Event {
1292 let id = match self.id {
1293 Some(id) => id,
1294 None => {
1295 let id = Event::compute_event_id(self.abi_version, &self.name, &self.inputs);
1296 id & Function::INPUT_ID_MASK
1297 }
1298 };
1299
1300 Event {
1301 abi_version: self.abi_version,
1302 name: Arc::from(self.name),
1303 inputs: Arc::from(self.inputs),
1304 id,
1305 }
1306 }
1307
1308 pub fn with_inputs<I, T>(mut self, inputs: I) -> Self
1310 where
1311 I: IntoIterator<Item = T>,
1312 T: Into<NamedAbiType>,
1313 {
1314 self.inputs = inputs.into_iter().map(Into::into).collect();
1315 self
1316 }
1317
1318 pub fn with_unnamed_inputs<I: IntoIterator<Item = AbiType>>(mut self, inputs: I) -> Self {
1320 self.inputs = inputs
1321 .into_iter()
1322 .enumerate()
1323 .map(NamedAbiType::from)
1324 .collect();
1325 self
1326 }
1327
1328 pub fn with_id(mut self, id: u32) -> Self {
1330 self.id = Some(id);
1331 self
1332 }
1333}
1334
1335pub struct UnsignedExternalMessage {
1337 pub dst: StdAddr,
1339 pub body: UnsignedBody,
1341 pub init: Option<StateInit>,
1343}
1344
1345impl UnsignedExternalMessage {
1346 pub fn set_state_init(&mut self, init: Option<StateInit>) {
1348 self.init = init;
1349 }
1350
1351 pub fn with_state_init(mut self, init: StateInit) -> Self {
1353 self.set_state_init(Some(init));
1354 self
1355 }
1356
1357 #[inline]
1359 pub fn expire_at(&self) -> u32 {
1360 self.body.expire_at
1361 }
1362
1363 pub fn sign(
1365 self,
1366 key: &ed25519_dalek::SigningKey,
1367 signature_id: Option<i32>,
1368 ) -> Result<OwnedMessage> {
1369 let signature =
1370 crate::abi::sign_with_signature_id(key, self.body.hash.as_slice(), signature_id);
1371 self.with_signature(&signature)
1372 }
1373
1374 pub fn with_signature(self, signature: &ed25519_dalek::Signature) -> Result<OwnedMessage> {
1376 self.into_signed(Some(&signature.to_bytes()))
1377 }
1378
1379 pub fn with_fake_signature(self) -> Result<OwnedMessage> {
1381 self.into_signed(Some(&[0u8; 64]))
1382 }
1383
1384 pub fn without_signature(self) -> Result<OwnedMessage> {
1386 self.into_signed(None)
1387 }
1388
1389 pub fn fill_signature(&self, signature: Option<&[u8; 64]>) -> Result<OwnedMessage> {
1391 let body = self.body.fill_signature(signature)?;
1392 Ok(OwnedMessage {
1393 info: MsgInfo::ExtIn(ExtInMsgInfo {
1394 dst: IntAddr::Std(self.dst.clone()),
1395 ..Default::default()
1396 }),
1397 body: body.into(),
1398 init: self.init.clone(),
1399 layout: None,
1400 })
1401 }
1402
1403 fn into_signed(self, signature: Option<&[u8; 64]>) -> Result<OwnedMessage> {
1405 let body = self.body.fill_signature(signature)?;
1406 Ok(OwnedMessage {
1407 info: MsgInfo::ExtIn(ExtInMsgInfo {
1408 dst: IntAddr::Std(self.dst),
1409 ..Default::default()
1410 }),
1411 body: body.into(),
1412 init: self.init,
1413 layout: None,
1414 })
1415 }
1416}
1417
1418pub struct UnsignedBody {
1420 pub abi_version: AbiVersion,
1422 pub payload: Cell,
1424 pub hash: HashBytes,
1426 pub expire_at: u32,
1428}
1429
1430impl UnsignedBody {
1431 pub fn with_dst(self, dst: StdAddr) -> UnsignedExternalMessage {
1434 UnsignedExternalMessage {
1435 dst,
1436 body: self,
1437 init: None,
1438 }
1439 }
1440
1441 pub fn sign(self, key: &ed25519_dalek::SigningKey, signature_id: Option<i32>) -> Result<Cell> {
1443 let signature = crate::abi::sign_with_signature_id(key, self.hash.as_slice(), signature_id);
1444 self.with_signature(&signature)
1445 }
1446
1447 pub fn with_signature(self, signature: &ed25519_dalek::Signature) -> Result<Cell> {
1449 self.fill_signature(Some(&signature.to_bytes()))
1450 }
1451
1452 pub fn with_fake_signature(self) -> Result<Cell> {
1454 self.fill_signature(Some(&[0u8; 64]))
1455 }
1456
1457 pub fn without_signature(self) -> Result<Cell> {
1459 self.fill_signature(None)
1460 }
1461
1462 pub fn fill_signature(&self, signature: Option<&[u8; 64]>) -> Result<Cell> {
1464 let mut builder = CellBuilder::new();
1465
1466 if self.abi_version.major == 1 {
1467 builder.store_reference(match signature {
1468 Some(signature) => {
1469 CellBuilder::from_raw_data(signature, 512).and_then(CellBuilder::build)?
1471 }
1472 None => Cell::empty_cell(),
1473 })?;
1474 } else {
1475 match signature {
1476 Some(signature) => {
1477 builder.store_bit_one()?;
1478 builder.store_raw(signature, 512)?;
1479 }
1480 None => builder.store_bit_zero()?,
1481 }
1482 builder.store_slice(self.payload.as_slice()?)?;
1483 }
1484
1485 builder.build().map_err(From::from)
1486 }
1487}
1488
1489struct FunctionSignatureRaw<'a> {
1490 abi_version: AbiVersion,
1491 name: &'a str,
1492 headers: &'a [AbiHeaderType],
1493 inputs: &'a [NamedAbiType],
1494 outputs: &'a [NamedAbiType],
1495}
1496
1497impl FunctionSignatureRaw<'_> {
1498 fn update_hasher<H: Digest>(&self, engine: &mut H) {
1499 std::fmt::write(&mut DisplayHasher(engine), format_args!("{self}")).unwrap();
1500 }
1501}
1502
1503impl std::fmt::Display for FunctionSignatureRaw<'_> {
1504 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1505 ok!(write!(f, "{}(", self.name));
1506
1507 let mut first = true;
1508 if self.abi_version.major == 1 {
1509 for header in self.headers {
1510 if !std::mem::take(&mut first) {
1511 ok!(f.write_str(","));
1512 }
1513 ok!(std::fmt::Display::fmt(header, f));
1514 }
1515 }
1516 for item in self.inputs {
1517 if !std::mem::take(&mut first) {
1518 ok!(f.write_str(","));
1519 }
1520 ok!(std::fmt::Display::fmt(&item.ty, f));
1521 }
1522
1523 ok!(f.write_str(")("));
1524
1525 first = true;
1526 for item in self.outputs {
1527 if !std::mem::take(&mut first) {
1528 ok!(f.write_str(","));
1529 }
1530 ok!(std::fmt::Display::fmt(&item.ty, f));
1531 }
1532
1533 write!(f, ")v{}", self.abi_version.major)
1534 }
1535}
1536
1537struct EventSignatureRaw<'a> {
1538 abi_version: AbiVersion,
1539 name: &'a str,
1540 inputs: &'a [NamedAbiType],
1541}
1542
1543impl EventSignatureRaw<'_> {
1544 fn update_hasher<H: Digest>(&self, engine: &mut H) {
1545 std::fmt::write(&mut DisplayHasher(engine), format_args!("{self}")).unwrap();
1546 }
1547}
1548
1549impl std::fmt::Display for EventSignatureRaw<'_> {
1550 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1551 ok!(write!(f, "{}(", self.name));
1552
1553 let mut first = true;
1554 for item in self.inputs {
1555 if !std::mem::take(&mut first) {
1556 ok!(f.write_str(","));
1557 }
1558 ok!(std::fmt::Display::fmt(&item.ty, f));
1559 }
1560 write!(f, ")v{}", self.abi_version.major)
1561 }
1562}
1563
1564#[repr(transparent)]
1565struct DisplayHasher<'a, H>(&'a mut H);
1566
1567impl<H: Digest> std::fmt::Write for DisplayHasher<'_, H> {
1568 #[inline]
1569 fn write_str(&mut self, s: &str) -> std::fmt::Result {
1570 self.0.update(s.as_bytes());
1571 Ok(())
1572 }
1573}