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