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