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 #[serde(default, rename = "externalMsg")]
471 external_msg: Option<bool>,
472 }
473
474 #[derive(Deserialize)]
475 struct SerdeEvent {
476 name: String,
477 #[serde(default)]
478 inputs: Vec<NamedAbiType>,
479 #[serde(default)]
480 id: Option<Id>,
481 }
482
483 #[derive(Deserialize)]
484 struct InitData {
485 key: u64,
486 #[serde(flatten)]
487 ty: NamedAbiType,
488 }
489
490 let contract = ok!(SerdeContract::deserialize(deserializer));
491 let abi_version = if let Some(version) = &contract.version {
492 ok!(AbiVersion::from_str(version).map_err(Error::custom))
493 } else if let Some(major) = contract.abi_version {
494 AbiVersion::new(major, 0)
495 } else {
496 return Err(Error::custom("No ABI version found"));
497 };
498
499 let headers = Arc::<[AbiHeaderType]>::from(contract.header);
500
501 let functions = contract
502 .functions
503 .into_iter()
504 .map(|item| {
505 let (input_id, output_id) = match item.id {
506 Some(Id(id)) => (id, id),
507 None => {
508 let id = Function::compute_function_id(
509 abi_version,
510 &item.name,
511 headers.as_ref(),
512 &item.inputs,
513 &item.outputs,
514 );
515 (id & Function::INPUT_ID_MASK, id | !Function::INPUT_ID_MASK)
516 }
517 };
518 let name = Arc::<str>::from(item.name);
519 (name.clone(), Function {
520 abi_version,
521 name,
522 headers: headers.clone(),
523 inputs: Arc::from(item.inputs),
524 outputs: Arc::from(item.outputs),
525 input_id,
526 output_id,
527 external_msg: item.external_msg,
528 })
529 })
530 .collect();
531
532 let getters = contract
533 .getters
534 .into_iter()
535 .map(|item| {
536 let id = match item.id {
537 Some(Id(id)) => id,
538 None => Getter::compute_getter_id::<&str>(item.name.as_ref()),
539 };
540 let name = Arc::<str>::from(item.name);
541 (name.clone(), Getter {
542 name,
543 outputs: Arc::from(item.outputs),
544 id,
545 })
546 })
547 .collect();
548
549 let events = contract
550 .events
551 .into_iter()
552 .map(|item| {
553 let id = match item.id {
554 Some(Id(id)) => id,
555 None => {
556 let id = Event::compute_event_id(abi_version, &item.name, &item.inputs);
557 id & Function::INPUT_ID_MASK
558 }
559 };
560 let name = Arc::<str>::from(item.name);
561 (name.clone(), Event {
562 abi_version,
563 name,
564 inputs: Arc::from(item.inputs),
565 id,
566 })
567 })
568 .collect();
569
570 let init_data = if abi_version >= AbiVersion::V2_4 {
571 let init_fields = contract
572 .fields
573 .iter()
574 .filter(|x| x.init)
575 .map(|x| x.named_abi_type.name.clone())
576 .collect();
577 ContractInitData::PlainFields(init_fields)
578 } else {
579 let data = contract
580 .data
581 .into_iter()
582 .map(|item| {
583 let name = item.ty.name.clone();
584 (name, (item.key, item.ty))
585 })
586 .collect();
587
588 ContractInitData::Dict(data)
589 };
590
591 Ok(Self {
592 abi_version,
593 headers,
594 functions,
595 events,
596 init_data,
597 fields: Arc::from(
598 contract
599 .fields
600 .into_iter()
601 .map(|x| x.named_abi_type)
602 .collect::<Vec<_>>(),
603 ),
604 getters,
605 })
606 }
607}
608
609pub trait AsGetterMethodId {
611 fn as_getter_method_id(&self) -> u32;
612}
613
614impl<T: AsGetterMethodId + ?Sized> AsGetterMethodId for &T {
615 fn as_getter_method_id(&self) -> u32 {
616 T::as_getter_method_id(*self)
617 }
618}
619
620impl<T: AsGetterMethodId + ?Sized> AsGetterMethodId for &mut T {
621 fn as_getter_method_id(&self) -> u32 {
622 T::as_getter_method_id(*self)
623 }
624}
625
626impl AsGetterMethodId for u32 {
627 fn as_getter_method_id(&self) -> u32 {
628 *self
629 }
630}
631
632impl AsGetterMethodId for str {
633 fn as_getter_method_id(&self) -> u32 {
634 let crc = crate::crc::crc_16(self.as_bytes());
635 crc as u32 | 0x10000
636 }
637}
638
639#[derive(Debug, Clone)]
640pub struct Getter {
641 pub name: Arc<str>,
643 pub outputs: Arc<[NamedAbiType]>,
645 pub id: u32,
647}
648
649impl Getter {
650 pub fn compute_getter_id<T: AsGetterMethodId>(input: T) -> u32 {
651 input.as_getter_method_id()
652 }
653}
654
655#[derive(Debug, Clone)]
657pub struct Function {
658 pub abi_version: AbiVersion,
660 pub headers: Arc<[AbiHeaderType]>,
665 pub name: Arc<str>,
667 pub inputs: Arc<[NamedAbiType]>,
669 pub outputs: Arc<[NamedAbiType]>,
671 pub input_id: u32,
673 pub output_id: u32,
675 pub external_msg: Option<bool>,
678}
679
680impl Function {
681 pub const INPUT_ID_MASK: u32 = 0x7fffffff;
683
684 pub fn compute_function_id(
686 abi_version: AbiVersion,
687 name: &str,
688 headers: &[AbiHeaderType],
689 inputs: &[NamedAbiType],
690 outputs: &[NamedAbiType],
691 ) -> u32 {
692 let mut hasher = sha2::Sha256::new();
693 FunctionSignatureRaw {
694 abi_version,
695 name,
696 headers,
697 inputs,
698 outputs,
699 }
700 .update_hasher(&mut hasher);
701
702 let hash: [u8; 32] = hasher.finalize().into();
703 u32::from_be_bytes(hash[0..4].try_into().unwrap())
704 }
705
706 pub fn encode_internal_msg_body(
708 version: AbiVersion,
709 id: u32,
710 tokens: &[NamedAbiValue],
711 ) -> Result<CellBuilder> {
712 let mut serializer = AbiSerializer::new(version);
713 let output_id = AbiValue::uint(32, id);
714
715 serializer.reserve_value(&output_id);
716 for token in tokens {
717 serializer.reserve_value(&token.value);
718 }
719
720 let context = Cell::empty_context();
721 serializer.write_value(&output_id, version, context)?;
722 serializer.write_tuple(tokens, version, context)?;
723 serializer.finalize(context).map_err(From::from)
724 }
725
726 #[inline]
728 pub fn builder<T: Into<String>>(abi_version: AbiVersion, name: T) -> FunctionBuilder {
729 FunctionBuilder::new(abi_version, name)
730 }
731
732 pub fn encode_external<'f, 'a: 'f>(
734 &'f self,
735 tokens: &'a [NamedAbiValue],
736 ) -> ExternalInput<'f, 'a> {
737 ExternalInput {
738 function: self,
739 tokens,
740 time: None,
741 expire_at: None,
742 pubkey: None,
743 }
744 }
745
746 pub fn decode_external_input(&self, mut slice: CellSlice<'_>) -> Result<Vec<NamedAbiValue>> {
750 self.decode_external_input_ext(&mut slice, false)
751 }
752
753 pub fn decode_external_input_ext(
755 &self,
756 slice: &mut CellSlice<'_>,
757 allow_partial: bool,
758 ) -> Result<Vec<NamedAbiValue>> {
759 let id = if self.abi_version.major == 1 {
761 let id = slice.load_u32()?;
763 slice.load_reference()?;
765 ok!(AbiHeader::skip_all(&self.headers, slice));
767
768 id
769 } else {
770 if slice.load_bit()? {
772 slice.skip_first(512, 0)?;
773 }
774 ok!(AbiHeader::skip_all(&self.headers, slice));
776 slice.load_u32()?
778 };
779
780 anyhow::ensure!(id == self.input_id, AbiError::InputIdMismatch {
782 expected: self.input_id,
783 id
784 });
785
786 let res = ok!(NamedAbiValue::load_tuple_ext(
787 &self.inputs,
788 self.abi_version,
789 true,
790 allow_partial,
791 slice
792 ));
793 ok!(AbiValue::check_remaining(slice, allow_partial));
794 Ok(res)
795 }
796
797 pub fn encode_internal_input(&self, tokens: &[NamedAbiValue]) -> Result<CellBuilder> {
799 ok!(NamedAbiValue::check_types(tokens, &self.inputs));
800 Self::encode_internal_msg_body(self.abi_version, self.input_id, tokens)
801 }
802
803 pub fn encode_internal_message(
805 &self,
806 tokens: &[NamedAbiValue],
807 dst: IntAddr,
808 value: Tokens,
809 bounce: bool,
810 state_init: Option<&StateInit>,
811 ) -> Result<Box<OwnedRelaxedMessage>> {
812 let body = self.encode_internal_input(tokens)?;
813 let body = body.build()?;
814
815 Ok(Box::new(OwnedRelaxedMessage {
816 info: RelaxedMsgInfo::Int(RelaxedIntMsgInfo {
817 dst,
818 bounce,
819 value: value.into(),
820 ..Default::default()
821 }),
822 body: body.into(),
823 init: state_init.cloned(),
824 layout: None,
825 }))
826 }
827
828 pub fn decode_internal_input(&self, mut slice: CellSlice<'_>) -> Result<Vec<NamedAbiValue>> {
832 self.decode_internal_input_ext(&mut slice, false)
833 }
834
835 pub fn decode_internal_input_ext(
837 &self,
838 slice: &mut CellSlice<'_>,
839 allow_partial: bool,
840 ) -> Result<Vec<NamedAbiValue>> {
841 let id = slice.load_u32()?;
842 anyhow::ensure!(id == self.input_id, AbiError::InputIdMismatch {
843 expected: self.input_id,
844 id
845 });
846 let res = ok!(NamedAbiValue::load_tuple_ext(
847 &self.inputs,
848 self.abi_version,
849 true,
850 allow_partial,
851 slice
852 ));
853 ok!(AbiValue::check_remaining(slice, allow_partial));
854 Ok(res)
855 }
856
857 pub fn encode_output(&self, tokens: &[NamedAbiValue]) -> Result<CellBuilder> {
859 ok!(NamedAbiValue::check_types(tokens, &self.outputs));
860 Self::encode_internal_msg_body(self.abi_version, self.output_id, tokens)
861 }
862
863 pub fn decode_output(&self, mut slice: CellSlice<'_>) -> Result<Vec<NamedAbiValue>> {
867 self.decode_output_ext(&mut slice, false)
868 }
869
870 pub fn decode_output_ext(
872 &self,
873 slice: &mut CellSlice<'_>,
874 allow_partial: bool,
875 ) -> Result<Vec<NamedAbiValue>> {
876 let id = slice.load_u32()?;
877 anyhow::ensure!(id == self.output_id, AbiError::OutputIdMismatch {
878 expected: self.output_id,
879 id
880 });
881 let res = ok!(NamedAbiValue::load_tuple_ext(
882 &self.outputs,
883 self.abi_version,
884 true,
885 allow_partial,
886 slice
887 ));
888 ok!(AbiValue::check_remaining(slice, allow_partial));
889 Ok(res)
890 }
891
892 pub fn display_signature(&self) -> impl std::fmt::Display + '_ {
894 FunctionSignatureRaw {
895 abi_version: self.abi_version,
896 name: &self.name,
897 headers: &self.headers,
898 inputs: &self.inputs,
899 outputs: &self.outputs,
900 }
901 }
902}
903
904#[derive(Clone)]
906pub struct ExternalInput<'f, 'a> {
907 function: &'f Function,
908 tokens: &'a [NamedAbiValue],
909 time: Option<u64>,
910 expire_at: Option<u32>,
911 pubkey: Option<&'a ed25519_dalek::VerifyingKey>,
912}
913
914impl<'a> ExternalInput<'_, 'a> {
915 pub fn build_message(&self, address: &StdAddr) -> Result<UnsignedExternalMessage> {
917 Ok(ok!(self.build_input_ext(Some(address))).with_dst(address.clone()))
918 }
919
920 pub fn build_message_without_signature(
924 &self,
925 address: &StdAddr,
926 ) -> Result<(u32, OwnedMessage)> {
927 let (expire_at, body) = ok!(self.build_input_without_signature());
928 Ok((expire_at, OwnedMessage {
929 info: MsgInfo::ExtIn(ExtInMsgInfo {
930 dst: IntAddr::Std(address.clone()),
931 ..Default::default()
932 }),
933 body: body.into(),
934 init: None,
935 layout: None,
936 }))
937 }
938
939 pub fn build_input(&self, address: Option<&StdAddr>) -> Result<UnsignedBody> {
944 self.build_input_ext(address)
945 }
946
947 fn build_input_ext(&self, address: Option<&StdAddr>) -> Result<UnsignedBody> {
948 let (expire_at, payload) = self.build_payload(true)?;
949
950 let context = Cell::empty_context();
951 let hash = if self.function.abi_version >= AbiVersion::V2_3 {
952 let mut to_sign = CellBuilder::new();
953 match address {
954 Some(address) => address.store_into(&mut to_sign, context)?,
955 None => anyhow::bail!(AbiError::AddressNotProvided),
956 };
957 to_sign.store_slice(payload.as_slice()?)?;
958 *to_sign.build_ext(context)?.repr_hash()
959 } else {
960 *payload.repr_hash()
961 };
962
963 Ok(UnsignedBody {
964 abi_version: self.function.abi_version,
965 expire_at,
966 payload,
967 hash,
968 })
969 }
970
971 pub fn build_input_without_signature(&self) -> Result<(u32, Cell)> {
973 self.build_payload(false)
974 }
975
976 fn build_payload(&self, reserve_signature: bool) -> Result<(u32, Cell)> {
977 const DEFAULT_TIMEOUT_SEC: u32 = 60;
978
979 fn now_ms() -> u64 {
980 std::time::SystemTime::now()
981 .duration_since(std::time::SystemTime::UNIX_EPOCH)
982 .unwrap()
983 .as_millis() as u64
984 }
985
986 ok!(NamedAbiValue::check_types(
987 self.tokens,
988 &self.function.inputs
989 ));
990
991 let abi_version = self.function.abi_version;
992
993 let mut serializer = AbiSerializer::new(abi_version);
994
995 serializer.add_offset(if abi_version.major == 1 {
996 Size { bits: 0, refs: 1 }
998 } else {
999 let bits = if abi_version >= AbiVersion::V2_3 {
1000 IntAddr::BITS_MAX
1002 } else {
1003 1 + 512
1005 };
1006 Size { bits, refs: 0 }
1007 });
1008
1009 let input_id = AbiValue::uint(32, self.function.input_id);
1010
1011 serializer.reserve_headers(&self.function.headers, self.pubkey.is_some());
1012 serializer.reserve_value(&input_id);
1013 for token in self.tokens {
1014 serializer.reserve_value(&token.value);
1015 }
1016
1017 let context = Cell::empty_context();
1018
1019 if !reserve_signature {
1020 let value = if abi_version.major == 1 {
1021 AbiValue::Cell(Cell::default())
1022 } else {
1023 AbiValue::Bool(false)
1024 };
1025 serializer.reserve_value(&value);
1026 serializer.write_value(&value, abi_version, context)?;
1027 }
1028
1029 let time = self.time.unwrap_or_else(now_ms);
1030 let expire_at = self
1031 .expire_at
1032 .unwrap_or((time / 1000) as u32 + DEFAULT_TIMEOUT_SEC);
1033
1034 for header in self.function.headers.as_ref() {
1035 serializer.write_header_value(&match header {
1036 AbiHeaderType::Time => AbiHeader::Time(time),
1037 AbiHeaderType::Expire => AbiHeader::Expire(expire_at),
1038 AbiHeaderType::PublicKey => {
1039 AbiHeader::PublicKey(self.pubkey.map(|key| Box::new(*key)))
1040 }
1041 })?;
1042 }
1043
1044 serializer.write_value(&input_id, abi_version, context)?;
1045 serializer.write_tuple(self.tokens, abi_version, context)?;
1046
1047 let payload = serializer.finalize(context)?.build_ext(context)?;
1048 Ok((expire_at, payload))
1049 }
1050
1051 #[inline]
1053 pub fn set_time(&mut self, time: u64) {
1054 self.time = Some(time);
1055 }
1056
1057 #[inline]
1059 pub fn with_time(mut self, time: u64) -> Self {
1060 self.set_time(time);
1061 self
1062 }
1063
1064 #[inline]
1066 pub fn set_expire_at(&mut self, expire_at: u32) {
1067 self.expire_at = Some(expire_at);
1068 }
1069
1070 #[inline]
1072 pub fn with_expire_at(mut self, expire_at: u32) -> Self {
1073 self.set_expire_at(expire_at);
1074 self
1075 }
1076
1077 #[inline]
1079 pub fn set_pubkey(&mut self, pubkey: &'a ed25519_dalek::VerifyingKey) {
1080 self.pubkey = Some(pubkey);
1081 }
1082
1083 #[inline]
1085 pub fn with_pubkey(mut self, pubkey: &'a ed25519_dalek::VerifyingKey) -> Self {
1086 self.set_pubkey(pubkey);
1087 self
1088 }
1089}
1090
1091#[derive(Debug, Clone)]
1093pub struct FunctionBuilder {
1094 abi_version: AbiVersion,
1095 name: String,
1096 headers: Vec<AbiHeaderType>,
1097 inputs: Vec<NamedAbiType>,
1098 outputs: Vec<NamedAbiType>,
1099 id: Option<u32>,
1100 external_msg: Option<bool>,
1101}
1102
1103impl FunctionBuilder {
1104 pub fn new<T: Into<String>>(abi_version: AbiVersion, name: T) -> Self {
1106 Self {
1107 abi_version,
1108 name: name.into(),
1109 headers: Default::default(),
1110 inputs: Default::default(),
1111 outputs: Default::default(),
1112 id: None,
1113 external_msg: None,
1114 }
1115 }
1116
1117 pub fn build(self) -> Function {
1119 let (input_id, output_id) = match self.id {
1120 Some(id) => (id, id),
1121 None => {
1122 let id = Function::compute_function_id(
1123 self.abi_version,
1124 &self.name,
1125 &self.headers,
1126 &self.inputs,
1127 &self.outputs,
1128 );
1129 (id & Function::INPUT_ID_MASK, id | !Function::INPUT_ID_MASK)
1130 }
1131 };
1132
1133 Function {
1134 abi_version: self.abi_version,
1135 headers: Arc::from(self.headers),
1136 name: Arc::from(self.name),
1137 inputs: Arc::from(self.inputs),
1138 outputs: Arc::from(self.outputs),
1139 input_id,
1140 output_id,
1141 external_msg: self.external_msg,
1142 }
1143 }
1144
1145 pub fn with_headers<I: IntoIterator<Item = AbiHeaderType>>(mut self, headers: I) -> Self {
1147 self.headers = headers.into_iter().collect();
1148 self
1149 }
1150
1151 pub fn with_inputs<I, T>(mut self, inputs: I) -> Self
1153 where
1154 I: IntoIterator<Item = T>,
1155 T: Into<NamedAbiType>,
1156 {
1157 self.inputs = inputs.into_iter().map(Into::into).collect();
1158 self
1159 }
1160
1161 pub fn with_unnamed_inputs<I: IntoIterator<Item = AbiType>>(mut self, inputs: I) -> Self {
1163 self.inputs = inputs
1164 .into_iter()
1165 .enumerate()
1166 .map(NamedAbiType::from)
1167 .collect();
1168 self
1169 }
1170
1171 pub fn with_outputs<I, T>(mut self, outputs: I) -> Self
1173 where
1174 I: IntoIterator<Item = T>,
1175 T: Into<NamedAbiType>,
1176 {
1177 self.outputs = outputs.into_iter().map(Into::into).collect();
1178 self
1179 }
1180
1181 pub fn with_unnamed_outputs<I: IntoIterator<Item = AbiType>>(mut self, outputs: I) -> Self {
1183 self.outputs = outputs
1184 .into_iter()
1185 .enumerate()
1186 .map(NamedAbiType::from)
1187 .collect();
1188 self
1189 }
1190
1191 pub fn with_id(mut self, id: u32) -> Self {
1193 self.id = Some(id);
1194 self
1195 }
1196
1197 pub fn external_msg(mut self, external_msg: Option<bool>) -> Self {
1199 self.external_msg = external_msg;
1200 self
1201 }
1202}
1203
1204#[derive(Debug, Clone)]
1206pub struct Event {
1207 pub abi_version: AbiVersion,
1209 pub name: Arc<str>,
1211 pub inputs: Arc<[NamedAbiType]>,
1213 pub id: u32,
1215}
1216
1217impl Event {
1218 pub fn compute_event_id(abi_version: AbiVersion, name: &str, inputs: &[NamedAbiType]) -> u32 {
1220 let mut hasher = sha2::Sha256::new();
1221 EventSignatureRaw {
1222 abi_version,
1223 name,
1224 inputs,
1225 }
1226 .update_hasher(&mut hasher);
1227
1228 let hash: [u8; 32] = hasher.finalize().into();
1229 u32::from_be_bytes(hash[0..4].try_into().unwrap())
1230 }
1231
1232 #[inline]
1234 pub fn builder<T: Into<String>>(abi_version: AbiVersion, name: T) -> EventBuilder {
1235 EventBuilder::new(abi_version, name)
1236 }
1237
1238 pub fn encode_internal_input(&self, tokens: &[NamedAbiValue]) -> Result<CellBuilder> {
1240 ok!(NamedAbiValue::check_types(tokens, &self.inputs));
1241 Function::encode_internal_msg_body(self.abi_version, self.id, tokens)
1242 }
1243
1244 pub fn decode_internal_input(&self, mut slice: CellSlice<'_>) -> Result<Vec<NamedAbiValue>> {
1248 self.decode_internal_input_ext(&mut slice, false)
1249 }
1250
1251 pub fn decode_internal_input_ext(
1253 &self,
1254 slice: &mut CellSlice<'_>,
1255 allow_partial: bool,
1256 ) -> Result<Vec<NamedAbiValue>> {
1257 let id = slice.load_u32()?;
1258 anyhow::ensure!(id == self.id, AbiError::InputIdMismatch {
1259 expected: self.id,
1260 id
1261 });
1262 let res = ok!(NamedAbiValue::load_tuple_ext(
1263 &self.inputs,
1264 self.abi_version,
1265 true,
1266 allow_partial,
1267 slice
1268 ));
1269 ok!(AbiValue::check_remaining(slice, allow_partial));
1270 Ok(res)
1271 }
1272
1273 pub fn display_signature(&self) -> impl std::fmt::Display + '_ {
1275 EventSignatureRaw {
1276 abi_version: self.abi_version,
1277 name: &self.name,
1278 inputs: &self.inputs,
1279 }
1280 }
1281}
1282
1283#[derive(Debug, Clone)]
1285pub struct EventBuilder {
1286 abi_version: AbiVersion,
1287 name: String,
1288 inputs: Vec<NamedAbiType>,
1289 id: Option<u32>,
1290}
1291
1292impl EventBuilder {
1293 pub fn new<T: Into<String>>(abi_version: AbiVersion, name: T) -> Self {
1295 Self {
1296 abi_version,
1297 name: name.into(),
1298 inputs: Default::default(),
1299 id: None,
1300 }
1301 }
1302
1303 pub fn build(self) -> Event {
1305 let id = match self.id {
1306 Some(id) => id,
1307 None => {
1308 let id = Event::compute_event_id(self.abi_version, &self.name, &self.inputs);
1309 id & Function::INPUT_ID_MASK
1310 }
1311 };
1312
1313 Event {
1314 abi_version: self.abi_version,
1315 name: Arc::from(self.name),
1316 inputs: Arc::from(self.inputs),
1317 id,
1318 }
1319 }
1320
1321 pub fn with_inputs<I, T>(mut self, inputs: I) -> Self
1323 where
1324 I: IntoIterator<Item = T>,
1325 T: Into<NamedAbiType>,
1326 {
1327 self.inputs = inputs.into_iter().map(Into::into).collect();
1328 self
1329 }
1330
1331 pub fn with_unnamed_inputs<I: IntoIterator<Item = AbiType>>(mut self, inputs: I) -> Self {
1333 self.inputs = inputs
1334 .into_iter()
1335 .enumerate()
1336 .map(NamedAbiType::from)
1337 .collect();
1338 self
1339 }
1340
1341 pub fn with_id(mut self, id: u32) -> Self {
1343 self.id = Some(id);
1344 self
1345 }
1346}
1347
1348#[derive(Debug, Clone)]
1350pub struct UnsignedExternalMessage {
1351 pub dst: StdAddr,
1353 pub body: UnsignedBody,
1355 pub init: Option<StateInit>,
1357}
1358
1359impl UnsignedExternalMessage {
1360 pub fn set_state_init(&mut self, init: Option<StateInit>) {
1362 self.init = init;
1363 }
1364
1365 pub fn with_state_init(mut self, init: StateInit) -> Self {
1367 self.init = Some(init);
1368 self
1369 }
1370
1371 pub fn with_state_init_opt(mut self, init: Option<StateInit>) -> Self {
1373 self.init = init;
1374 self
1375 }
1376
1377 #[inline]
1379 pub fn expire_at(&self) -> u32 {
1380 self.body.expire_at
1381 }
1382
1383 pub fn sign(
1385 self,
1386 key: &ed25519_dalek::SigningKey,
1387 context: SignatureContext,
1388 ) -> Result<OwnedMessage> {
1389 let signature = context.sign(key, self.body.hash.as_slice());
1390 self.with_signature(&signature)
1391 }
1392
1393 pub fn sign_with<F>(self, f: F) -> Result<OwnedMessage>
1396 where
1397 for<'a> F: FnOnce(&'a HashBytes) -> ed25519_dalek::Signature,
1398 {
1399 let signature = f(&self.body.hash);
1400 self.with_signature(&signature)
1401 }
1402
1403 pub fn with_signature(self, signature: &ed25519_dalek::Signature) -> Result<OwnedMessage> {
1405 self.into_signed(Some(&signature.to_bytes()))
1406 }
1407
1408 pub fn with_fake_signature(self) -> Result<OwnedMessage> {
1410 self.into_signed(Some(&[0u8; 64]))
1411 }
1412
1413 pub fn without_signature(self) -> Result<OwnedMessage> {
1415 self.into_signed(None)
1416 }
1417
1418 pub fn fill_signature(&self, signature: Option<&[u8; 64]>) -> Result<OwnedMessage> {
1420 let body = self.body.fill_signature(signature)?;
1421 Ok(OwnedMessage {
1422 info: MsgInfo::ExtIn(ExtInMsgInfo {
1423 dst: IntAddr::Std(self.dst.clone()),
1424 ..Default::default()
1425 }),
1426 body: body.into(),
1427 init: self.init.clone(),
1428 layout: None,
1429 })
1430 }
1431
1432 fn into_signed(self, signature: Option<&[u8; 64]>) -> Result<OwnedMessage> {
1434 let body = self.body.fill_signature(signature)?;
1435 Ok(OwnedMessage {
1436 info: MsgInfo::ExtIn(ExtInMsgInfo {
1437 dst: IntAddr::Std(self.dst),
1438 ..Default::default()
1439 }),
1440 body: body.into(),
1441 init: self.init,
1442 layout: None,
1443 })
1444 }
1445}
1446
1447#[derive(Debug, Clone)]
1449pub struct UnsignedBody {
1450 pub abi_version: AbiVersion,
1452 pub payload: Cell,
1454 pub hash: HashBytes,
1456 pub expire_at: u32,
1458}
1459
1460impl UnsignedBody {
1461 pub fn with_dst(self, dst: StdAddr) -> UnsignedExternalMessage {
1464 UnsignedExternalMessage {
1465 dst,
1466 body: self,
1467 init: None,
1468 }
1469 }
1470
1471 pub fn sign(self, key: &ed25519_dalek::SigningKey, context: SignatureContext) -> Result<Cell> {
1473 let signature = context.sign(key, self.hash.as_slice());
1474 self.with_signature(&signature)
1475 }
1476
1477 pub fn sign_with<F>(self, f: F) -> Result<Cell>
1480 where
1481 for<'a> F: FnOnce(&'a HashBytes) -> ed25519_dalek::Signature,
1482 {
1483 let signature = f(&self.hash);
1484 self.with_signature(&signature)
1485 }
1486
1487 pub fn with_signature(self, signature: &ed25519_dalek::Signature) -> Result<Cell> {
1489 self.fill_signature(Some(&signature.to_bytes()))
1490 }
1491
1492 pub fn with_fake_signature(self) -> Result<Cell> {
1494 self.fill_signature(Some(&[0u8; 64]))
1495 }
1496
1497 pub fn without_signature(self) -> Result<Cell> {
1499 self.fill_signature(None)
1500 }
1501
1502 pub fn fill_signature(&self, signature: Option<&[u8; 64]>) -> Result<Cell> {
1504 let mut builder = CellBuilder::new();
1505
1506 if self.abi_version.major == 1 {
1507 builder.store_reference(match signature {
1508 Some(signature) => {
1509 CellBuilder::from_raw_data(signature, 512).and_then(CellBuilder::build)?
1511 }
1512 None => Cell::empty_cell(),
1513 })?;
1514 } else {
1515 match signature {
1516 Some(signature) => {
1517 builder.store_bit_one()?;
1518 builder.store_raw(signature, 512)?;
1519 }
1520 None => builder.store_bit_zero()?,
1521 }
1522 builder.store_slice(self.payload.as_slice()?)?;
1523 }
1524
1525 builder.build().map_err(From::from)
1526 }
1527}
1528
1529struct FunctionSignatureRaw<'a> {
1530 abi_version: AbiVersion,
1531 name: &'a str,
1532 headers: &'a [AbiHeaderType],
1533 inputs: &'a [NamedAbiType],
1534 outputs: &'a [NamedAbiType],
1535}
1536
1537impl FunctionSignatureRaw<'_> {
1538 fn update_hasher<H: Digest>(&self, engine: &mut H) {
1539 std::fmt::write(&mut DisplayHasher(engine), format_args!("{self}")).unwrap();
1540 }
1541}
1542
1543impl std::fmt::Display for FunctionSignatureRaw<'_> {
1544 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1545 ok!(write!(f, "{}(", self.name));
1546
1547 let mut first = true;
1548 if self.abi_version.major == 1 {
1549 for header in self.headers {
1550 if !std::mem::take(&mut first) {
1551 ok!(f.write_str(","));
1552 }
1553 ok!(std::fmt::Display::fmt(header, f));
1554 }
1555 }
1556 for item in self.inputs {
1557 if !std::mem::take(&mut first) {
1558 ok!(f.write_str(","));
1559 }
1560 ok!(std::fmt::Display::fmt(&item.ty, f));
1561 }
1562
1563 ok!(f.write_str(")("));
1564
1565 first = true;
1566 for item in self.outputs {
1567 if !std::mem::take(&mut first) {
1568 ok!(f.write_str(","));
1569 }
1570 ok!(std::fmt::Display::fmt(&item.ty, f));
1571 }
1572
1573 write!(f, ")v{}", self.abi_version.major)
1574 }
1575}
1576
1577struct EventSignatureRaw<'a> {
1578 abi_version: AbiVersion,
1579 name: &'a str,
1580 inputs: &'a [NamedAbiType],
1581}
1582
1583impl EventSignatureRaw<'_> {
1584 fn update_hasher<H: Digest>(&self, engine: &mut H) {
1585 std::fmt::write(&mut DisplayHasher(engine), format_args!("{self}")).unwrap();
1586 }
1587}
1588
1589impl std::fmt::Display for EventSignatureRaw<'_> {
1590 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1591 ok!(write!(f, "{}(", self.name));
1592
1593 let mut first = true;
1594 for item in self.inputs {
1595 if !std::mem::take(&mut first) {
1596 ok!(f.write_str(","));
1597 }
1598 ok!(std::fmt::Display::fmt(&item.ty, f));
1599 }
1600 write!(f, ")v{}", self.abi_version.major)
1601 }
1602}
1603
1604#[repr(transparent)]
1605struct DisplayHasher<'a, H>(&'a mut H);
1606
1607impl<H: Digest> std::fmt::Write for DisplayHasher<'_, H> {
1608 #[inline]
1609 fn write_str(&mut self, s: &str) -> std::fmt::Result {
1610 self.0.update(s.as_bytes());
1611 Ok(())
1612 }
1613}