Skip to main content

tycho_types/abi/
contract.rs

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
28/// Contract ABI definition.
29pub struct Contract {
30    /// ABI version.
31    pub abi_version: AbiVersion,
32
33    /// List of headers for external messages.
34    ///
35    /// NOTE: header order matters.
36    pub headers: Arc<[AbiHeaderType]>,
37
38    /// A mapping with all contract methods by name.
39    pub functions: HashMap<Arc<str>, Function>,
40
41    /// A mapping with all contract events by name.
42    pub events: HashMap<Arc<str>, Event>,
43
44    /// Contract init data.
45    pub init_data: ContractInitData,
46
47    /// Contract storage fields.
48    pub fields: Arc<[NamedAbiType]>,
49
50    /// A mapping with all contract getters by name. Supported for ABI 2.7 and later
51    pub getters: HashMap<Arc<str>, Getter>,
52}
53
54/// Contract initialization data representation.
55pub enum ContractInitData {
56    /// Dictionary-based init data for ABI versions < 2.4.
57    ///
58    /// Maps field names to tuples of (key, named type), where the key is used
59    /// for dictionary lookups in the contract storage.
60    Dict(HashMap<Arc<str>, (u64, NamedAbiType)>),
61
62    /// Plain fields init data for ABI versions >= 2.4.
63    ///
64    /// Contains a set of field names that represent the initialization data.
65    /// These fields are stored sequentially in the contract data cell.
66    PlainFields(HashSet<Arc<str>>),
67}
68
69impl Contract {
70    /// Finds a method declaration with the specified id.
71    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    /// Finds an event with the specified id.
78    pub fn find_event_by_id(&self, id: u32) -> Option<&Event> {
79        self.events.values().find(|event| event.id == id)
80    }
81
82    /// Returns a new init data with replaced items.
83    ///
84    /// NOTE: `tokens` can be a subset of init data fields, all other
85    /// will not be touched.
86    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        // Always check if data is valid
106        let mut result = data.parse::<RawDict<64>>()?;
107
108        if pubkey.is_none() && tokens.is_empty() {
109            // Do nothing if no items are updated
110            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        // Set public key if specified
138        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        // Encode init data as mapping
148        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                // Overwrite pubkey if specified.
179                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    /// Encodes an account data with the specified initial parameters.
203    ///
204    /// NOTE: `tokens` can be a subset of init data fields, all other
205    /// will be set to default.
206    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        // Write explicitly provided values
238        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        // Write remaining values with default values
256        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        // Set public key
271        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        // Encode init data as mapping
283        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                // Overwrite pubkey if specified.
309                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    /// Tries to parse init data fields of this contract from an account data.
333    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    /// Encodes an account data with the specified storage fields of this contract.
378    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    /// Tries to parse storage fields of this contract from an account data.
384    ///
385    /// NOTE: The slice is required to contain nothing other than these fields.
386    pub fn decode_fields(&self, mut slice: CellSlice<'_>) -> Result<Vec<NamedAbiValue>> {
387        self.decode_fields_ext(&mut slice, false)
388    }
389
390    /// Tries to parse storage fields of this contract from an account data.
391    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
609/// Helper trait to convert various types to u32 getter id
610pub 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    /// Getter name.
642    pub name: Arc<str>,
643    /// Getter output types
644    pub outputs: Arc<[NamedAbiType]>,
645    /// Getter id
646    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/// Contract method ABI definition.
656#[derive(Debug, Clone)]
657pub struct Function {
658    /// ABI version (same as contract ABI version).
659    pub abi_version: AbiVersion,
660    /// List of headers for external messages.
661    /// Must be the same as in contract.
662    ///
663    /// NOTE: header order matters.
664    pub headers: Arc<[AbiHeaderType]>,
665    /// Method name.
666    pub name: Arc<str>,
667    /// Method input argument types.
668    pub inputs: Arc<[NamedAbiType]>,
669    /// Method output types.
670    pub outputs: Arc<[NamedAbiType]>,
671    /// Function id in incoming messages (with input).
672    pub input_id: u32,
673    /// Function id in outgoing messages (with output).
674    pub output_id: u32,
675    /// Whether the function can be executed as external message.
676    /// Parsed as `None` for ABI versions before v2.7.
677    pub external_msg: Option<bool>,
678}
679
680impl Function {
681    /// Mask with a bit difference of input id and output id.
682    pub const INPUT_ID_MASK: u32 = 0x7fffffff;
683
684    /// Computes function id from the full function signature.
685    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    /// Encodes message body without headers.
707    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    /// Returns a method builder with the specified ABI version and name.
727    #[inline]
728    pub fn builder<T: Into<String>>(abi_version: AbiVersion, name: T) -> FunctionBuilder {
729        FunctionBuilder::new(abi_version, name)
730    }
731
732    /// Encodes an unsigned body with invocation of this method as an external message.
733    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    /// Tries to parse input arguments for this method from an external message body.
747    ///
748    /// NOTE: The slice is required to contain nothing other than these arguments.
749    pub fn decode_external_input(&self, mut slice: CellSlice<'_>) -> Result<Vec<NamedAbiValue>> {
750        self.decode_external_input_ext(&mut slice, false)
751    }
752
753    /// Tries to parse input arguments for this method from an external message body.
754    pub fn decode_external_input_ext(
755        &self,
756        slice: &mut CellSlice<'_>,
757        allow_partial: bool,
758    ) -> Result<Vec<NamedAbiValue>> {
759        // Read prefix
760        let id = if self.abi_version.major == 1 {
761            // Load input id
762            let id = slice.load_u32()?;
763            // Skip signature
764            slice.load_reference()?;
765            // Skip headers
766            ok!(AbiHeader::skip_all(&self.headers, slice));
767
768            id
769        } else {
770            // Skip signature
771            if slice.load_bit()? {
772                slice.skip_first(512, 0)?;
773            }
774            // Skip headers
775            ok!(AbiHeader::skip_all(&self.headers, slice));
776            // Load input id
777            slice.load_u32()?
778        };
779
780        // Check input id
781        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    /// Encodes a message body with invocation of this method as an internal message.
798    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    /// Encodes an internal message with invocation of this method.
804    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    /// Tries to parse input arguments for this method from an internal message body.
829    ///
830    /// NOTE: The slice is required to contain nothing other than these arguments.
831    pub fn decode_internal_input(&self, mut slice: CellSlice<'_>) -> Result<Vec<NamedAbiValue>> {
832        self.decode_internal_input_ext(&mut slice, false)
833    }
834
835    /// Tries to parse input arguments for this method from an internal message body.
836    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    /// Encodes a message body with result of invocation of this method.
858    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    /// Tries to parse output arguments of this method from a message body.
864    ///
865    /// NOTE: The slice is required to contain nothing other than these arguments.
866    pub fn decode_output(&self, mut slice: CellSlice<'_>) -> Result<Vec<NamedAbiValue>> {
867        self.decode_output_ext(&mut slice, false)
868    }
869
870    /// Tries to parse output arguments of this method from a message body.
871    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    /// Returns an object which can be used to display the normalized signature of this method.
893    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/// External input builder.
905#[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    /// Builds an external message to the specified address.
916    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    /// Builds an external message to the specified address without signature.
921    ///
922    /// Returns an expiration timestamp along with message.
923    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    /// Builds an external message body.
940    ///
941    /// For contracts with ABI >= 2.3, the address must be provided.
942    /// Otherwise the method will fail with [`AbiError::AddressNotProvided`] error.
943    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    /// Builds an external message body without signature.
972    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            // Reserve reference for signature
997            Size { bits: 0, refs: 1 }
998        } else {
999            let bits = if abi_version >= AbiVersion::V2_3 {
1000                // Reserve only for address as it also ensures the signature will fit
1001                IntAddr::BITS_MAX
1002            } else {
1003                // Reserve for `Some` non-empty signature
1004                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    /// Use the specified time for the `time` header.
1052    #[inline]
1053    pub fn set_time(&mut self, time: u64) {
1054        self.time = Some(time);
1055    }
1056
1057    /// Use the specified time for the `time` header.
1058    #[inline]
1059    pub fn with_time(mut self, time: u64) -> Self {
1060        self.set_time(time);
1061        self
1062    }
1063
1064    /// Use the specified expiration timestamp for the `expire` header.
1065    #[inline]
1066    pub fn set_expire_at(&mut self, expire_at: u32) {
1067        self.expire_at = Some(expire_at);
1068    }
1069
1070    /// Use the specified expiration timestamp for the `expire` header.
1071    #[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    /// Use the specified public key for the `pubkey` header.
1078    #[inline]
1079    pub fn set_pubkey(&mut self, pubkey: &'a ed25519_dalek::VerifyingKey) {
1080        self.pubkey = Some(pubkey);
1081    }
1082
1083    /// Use the specified public key for the `pubkey` header.
1084    #[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/// Method ABI declaration builder.
1092#[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    /// Creates an empty ABI declaration for a method with the specified ABI version and name.
1105    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    /// Finalizes an ABI declaration.
1118    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    /// Sets method headers to the specified list.
1146    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    /// Sets method input types to the specified list of named arguments.
1152    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    /// Sets method input types to the specified list of unnamed arguments.
1162    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    /// Sets method output types to the specified list of named arguments.
1172    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    /// Sets method output types to the specified list of unnamed arguments.
1182    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    /// Sets an explicit function id.
1192    pub fn with_id(mut self, id: u32) -> Self {
1193        self.id = Some(id);
1194        self
1195    }
1196
1197    /// Sets `externalMsg` function flag.
1198    pub fn external_msg(mut self, external_msg: Option<bool>) -> Self {
1199        self.external_msg = external_msg;
1200        self
1201    }
1202}
1203
1204/// Contract event ABI definition.
1205#[derive(Debug, Clone)]
1206pub struct Event {
1207    /// ABI version (same as contract ABI version).
1208    pub abi_version: AbiVersion,
1209    /// Event name.
1210    pub name: Arc<str>,
1211    /// Event arguments.
1212    pub inputs: Arc<[NamedAbiType]>,
1213    /// Event id derived from signature.
1214    pub id: u32,
1215}
1216
1217impl Event {
1218    /// Computes event id from the full event signature.
1219    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    /// Returns an event builder with the specified ABI version and name.
1233    #[inline]
1234    pub fn builder<T: Into<String>>(abi_version: AbiVersion, name: T) -> EventBuilder {
1235        EventBuilder::new(abi_version, name)
1236    }
1237
1238    /// Encodes a message body with this event as an internal message.
1239    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    /// Tries to parse input arguments for this event from an internal message body.
1245    ///
1246    /// NOTE: The slice is required to contain nothing other than these arguments.
1247    pub fn decode_internal_input(&self, mut slice: CellSlice<'_>) -> Result<Vec<NamedAbiValue>> {
1248        self.decode_internal_input_ext(&mut slice, false)
1249    }
1250
1251    /// Tries to parse input arguments for this event from an internal message body.
1252    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    /// Returns an object which can be used to display the normalized signature of this event.
1274    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/// Event ABI declaration builder.
1284#[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    /// Creates an empty ABI declaration for an event with the specified ABI version and name.
1294    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    /// Finalizes an ABI declaration.
1304    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    /// Sets event input types to the specified list of named arguments.
1322    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    /// Sets event input types to the specified list of unnamed arguments.
1332    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    /// Sets an explicit event id.
1342    pub fn with_id(mut self, id: u32) -> Self {
1343        self.id = Some(id);
1344        self
1345    }
1346}
1347
1348/// Unsigned external message.
1349#[derive(Debug, Clone)]
1350pub struct UnsignedExternalMessage {
1351    /// Destination contract address.
1352    pub dst: StdAddr,
1353    /// Unsigned payload.
1354    pub body: UnsignedBody,
1355    /// Optional initial contract state.
1356    pub init: Option<StateInit>,
1357}
1358
1359impl UnsignedExternalMessage {
1360    /// Updates the state init of the external message to the specified one.
1361    pub fn set_state_init(&mut self, init: Option<StateInit>) {
1362        self.init = init;
1363    }
1364
1365    /// Returns an external message with the specified state init.
1366    pub fn with_state_init(mut self, init: StateInit) -> Self {
1367        self.init = Some(init);
1368        self
1369    }
1370
1371    /// Returns an external message with the specified state init.
1372    pub fn with_state_init_opt(mut self, init: Option<StateInit>) -> Self {
1373        self.init = init;
1374        self
1375    }
1376
1377    /// Returns the expiration timestamp of this message.
1378    #[inline]
1379    pub fn expire_at(&self) -> u32 {
1380        self.body.expire_at
1381    }
1382
1383    /// Signs the payload and returns an external message with filled signature.
1384    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    /// Signs the payload with the specified closure
1394    /// and returns an external message with filled signature.
1395    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    /// Returns an external message with filled signature.
1404    pub fn with_signature(self, signature: &ed25519_dalek::Signature) -> Result<OwnedMessage> {
1405        self.into_signed(Some(&signature.to_bytes()))
1406    }
1407
1408    /// Returns an external message with signature filled with zero bytes.
1409    pub fn with_fake_signature(self) -> Result<OwnedMessage> {
1410        self.into_signed(Some(&[0u8; 64]))
1411    }
1412
1413    /// Returns an external message with empty signature.
1414    pub fn without_signature(self) -> Result<OwnedMessage> {
1415        self.into_signed(None)
1416    }
1417
1418    /// Returns an external message with filled signature.
1419    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    /// Converts an unsigned message into an external message with filled signature.
1433    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/// Unsigned external message payload.
1448#[derive(Debug, Clone)]
1449pub struct UnsignedBody {
1450    /// ABI version used during encoding.
1451    pub abi_version: AbiVersion,
1452    /// Unsigned payload.
1453    pub payload: Cell,
1454    /// A hash to sign.
1455    pub hash: HashBytes,
1456    /// Message expiration timestamp (in seconds).
1457    pub expire_at: u32,
1458}
1459
1460impl UnsignedBody {
1461    /// Extends message with the specified destination address and returns an
1462    /// unsigned external message.
1463    pub fn with_dst(self, dst: StdAddr) -> UnsignedExternalMessage {
1464        UnsignedExternalMessage {
1465            dst,
1466            body: self,
1467            init: None,
1468        }
1469    }
1470
1471    /// Signs the payload and returns a body cell with filled signature.
1472    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    /// Signs the payload with the specified closure
1478    /// and returns a body cell with filled signature.
1479    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    /// Returns a body cell with filled signature.
1488    pub fn with_signature(self, signature: &ed25519_dalek::Signature) -> Result<Cell> {
1489        self.fill_signature(Some(&signature.to_bytes()))
1490    }
1491
1492    /// Returns a body cell with signature filled with zero bytes.
1493    pub fn with_fake_signature(self) -> Result<Cell> {
1494        self.fill_signature(Some(&[0u8; 64]))
1495    }
1496
1497    /// Returns a body cell with empty signature.
1498    pub fn without_signature(self) -> Result<Cell> {
1499        self.fill_signature(None)
1500    }
1501
1502    /// Returns a body cell with filled signature.
1503    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                    // TODO: extend with public key?
1510                    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}