fuel_tx/transaction/types/
input.rs

1use crate::{
2    TxPointer,
3    UtxoId,
4};
5use alloc::{
6    string::ToString,
7    vec::Vec,
8};
9use coin::*;
10use consts::*;
11use contract::*;
12use core::fmt::{
13    self,
14    Formatter,
15};
16use fuel_crypto::{
17    Hasher,
18    PublicKey,
19};
20use fuel_types::{
21    bytes,
22    canonical,
23    canonical::{
24        Deserialize,
25        Error,
26        Output,
27        Serialize,
28    },
29    fmt_truncated_hex,
30    Address,
31    AssetId,
32    Bytes32,
33    ContractId,
34    MessageId,
35    Nonce,
36    Word,
37};
38use message::*;
39
40pub mod coin;
41mod consts;
42pub mod contract;
43pub mod message;
44mod predicate;
45mod repr;
46
47pub use predicate::PredicateCode;
48pub use repr::InputRepr;
49
50#[cfg(all(test, feature = "std"))]
51mod ser_de_tests;
52
53pub trait AsField<Type>: AsFieldFmt {
54    fn as_field(&self) -> Option<&Type>;
55
56    fn as_mut_field(&mut self) -> Option<&mut Type>;
57}
58
59pub trait AsFieldFmt {
60    fn fmt_as_field(&self, f: &mut Formatter) -> fmt::Result;
61}
62
63pub fn fmt_as_field<T>(field: &T, f: &mut Formatter) -> fmt::Result
64where
65    T: AsFieldFmt,
66{
67    field.fmt_as_field(f)
68}
69
70/// The empty field used by sub-types of the specification.
71#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
72#[cfg_attr(
73    feature = "da-compression",
74    derive(fuel_compression::Compress, fuel_compression::Decompress)
75)]
76#[cfg_attr(feature = "da-compression", compress(discard(Type)))]
77pub struct Empty<Type>(
78    #[cfg_attr(feature = "da-compression", compress(skip))]
79    ::core::marker::PhantomData<Type>,
80);
81
82impl<Type> Empty<Type> {
83    /// Creates `Self`.
84    pub const fn new() -> Self {
85        Self(::core::marker::PhantomData {})
86    }
87}
88
89impl<Type> Default for Empty<Type> {
90    fn default() -> Self {
91        Self::new()
92    }
93}
94
95impl<Type: Serialize + Default> Serialize for Empty<Type> {
96    #[inline(always)]
97    fn size_static(&self) -> usize {
98        Type::default().size_static()
99    }
100
101    #[inline(always)]
102    fn size_dynamic(&self) -> usize {
103        0
104    }
105
106    #[inline(always)]
107    fn encode_static<O: Output + ?Sized>(&self, buffer: &mut O) -> Result<(), Error> {
108        Type::default().encode_static(buffer)
109    }
110}
111
112impl<Type: Deserialize> Deserialize for Empty<Type> {
113    #[inline(always)]
114    fn decode_static<I: canonical::Input + ?Sized>(
115        buffer: &mut I,
116    ) -> Result<Self, Error> {
117        Type::decode_static(buffer)?;
118        Ok(Default::default())
119    }
120}
121
122impl<Type> AsFieldFmt for Empty<Type> {
123    fn fmt_as_field(&self, f: &mut Formatter) -> fmt::Result {
124        f.write_str("Empty")
125    }
126}
127
128impl<Type> AsField<Type> for Empty<Type> {
129    #[inline(always)]
130    fn as_field(&self) -> Option<&Type> {
131        None
132    }
133
134    fn as_mut_field(&mut self) -> Option<&mut Type> {
135        None
136    }
137}
138
139impl AsField<u8> for u8 {
140    #[inline(always)]
141    fn as_field(&self) -> Option<&u8> {
142        Some(self)
143    }
144
145    fn as_mut_field(&mut self) -> Option<&mut u8> {
146        Some(self)
147    }
148}
149
150impl AsFieldFmt for u8 {
151    fn fmt_as_field(&self, f: &mut Formatter) -> fmt::Result {
152        f.write_str(self.to_string().as_str())
153    }
154}
155
156impl AsField<u16> for u16 {
157    #[inline(always)]
158    fn as_field(&self) -> Option<&u16> {
159        Some(self)
160    }
161
162    fn as_mut_field(&mut self) -> Option<&mut u16> {
163        Some(self)
164    }
165}
166
167impl AsFieldFmt for u16 {
168    fn fmt_as_field(&self, f: &mut Formatter) -> fmt::Result {
169        f.write_str(self.to_string().as_str())
170    }
171}
172
173impl AsField<u64> for u64 {
174    #[inline(always)]
175    fn as_field(&self) -> Option<&u64> {
176        Some(self)
177    }
178
179    fn as_mut_field(&mut self) -> Option<&mut u64> {
180        Some(self)
181    }
182}
183
184impl AsFieldFmt for u64 {
185    fn fmt_as_field(&self, f: &mut Formatter) -> fmt::Result {
186        f.write_str(self.to_string().as_str())
187    }
188}
189
190impl AsField<Vec<u8>> for Vec<u8> {
191    #[inline(always)]
192    fn as_field(&self) -> Option<&Vec<u8>> {
193        Some(self)
194    }
195
196    fn as_mut_field(&mut self) -> Option<&mut Vec<u8>> {
197        Some(self)
198    }
199}
200
201impl AsFieldFmt for Vec<u8> {
202    fn fmt_as_field(&self, f: &mut Formatter) -> fmt::Result {
203        fmt_truncated_hex::<16>(self, f)
204    }
205}
206
207impl AsField<PredicateCode> for PredicateCode {
208    #[inline(always)]
209    fn as_field(&self) -> Option<&PredicateCode> {
210        Some(self)
211    }
212
213    fn as_mut_field(&mut self) -> Option<&mut PredicateCode> {
214        Some(self)
215    }
216}
217
218impl AsFieldFmt for PredicateCode {
219    fn fmt_as_field(&self, f: &mut Formatter) -> fmt::Result {
220        fmt_truncated_hex::<16>(self, f)
221    }
222}
223
224#[derive(
225    Debug,
226    Clone,
227    PartialEq,
228    Eq,
229    Hash,
230    strum_macros::EnumCount,
231    serde::Serialize,
232    serde::Deserialize,
233)]
234#[cfg_attr(
235    feature = "da-compression",
236    derive(fuel_compression::Compress, fuel_compression::Decompress)
237)]
238pub enum Input {
239    CoinSigned(CoinSigned),
240    CoinPredicate(CoinPredicate),
241    Contract(Contract),
242    MessageCoinSigned(MessageCoinSigned),
243    MessageCoinPredicate(MessageCoinPredicate),
244    MessageDataSigned(MessageDataSigned),
245    MessageDataPredicate(MessageDataPredicate),
246}
247
248impl Default for Input {
249    fn default() -> Self {
250        Self::contract(
251            Default::default(),
252            Default::default(),
253            Default::default(),
254            Default::default(),
255            Default::default(),
256        )
257    }
258}
259
260impl Input {
261    pub const fn repr(&self) -> InputRepr {
262        InputRepr::from_input(self)
263    }
264
265    pub fn owner(pk: &PublicKey) -> Address {
266        let owner: [u8; Address::LEN] = pk.hash().into();
267
268        owner.into()
269    }
270
271    pub const fn coin_predicate(
272        utxo_id: UtxoId,
273        owner: Address,
274        amount: Word,
275        asset_id: AssetId,
276        tx_pointer: TxPointer,
277        predicate_gas_used: Word,
278        predicate: Vec<u8>,
279        predicate_data: Vec<u8>,
280    ) -> Self {
281        Self::CoinPredicate(CoinPredicate {
282            utxo_id,
283            owner,
284            amount,
285            asset_id,
286            tx_pointer,
287            witness_index: Empty::new(),
288            predicate_gas_used,
289            predicate: PredicateCode { bytes: predicate },
290            predicate_data,
291        })
292    }
293
294    pub const fn coin_signed(
295        utxo_id: UtxoId,
296        owner: Address,
297        amount: Word,
298        asset_id: AssetId,
299        tx_pointer: TxPointer,
300        witness_index: u16,
301    ) -> Self {
302        Self::CoinSigned(CoinSigned {
303            utxo_id,
304            owner,
305            amount,
306            asset_id,
307            tx_pointer,
308            witness_index,
309            predicate_gas_used: Empty::new(),
310            predicate: Empty::new(),
311            predicate_data: Empty::new(),
312        })
313    }
314
315    pub const fn contract(
316        utxo_id: UtxoId,
317        balance_root: Bytes32,
318        state_root: Bytes32,
319        tx_pointer: TxPointer,
320        contract_id: ContractId,
321    ) -> Self {
322        Self::Contract(Contract {
323            utxo_id,
324            balance_root,
325            state_root,
326            tx_pointer,
327            contract_id,
328        })
329    }
330
331    pub const fn message_coin_signed(
332        sender: Address,
333        recipient: Address,
334        amount: Word,
335        nonce: Nonce,
336        witness_index: u16,
337    ) -> Self {
338        Self::MessageCoinSigned(MessageCoinSigned {
339            sender,
340            recipient,
341            amount,
342            nonce,
343            witness_index,
344            predicate_gas_used: Empty::new(),
345            data: Empty::new(),
346            predicate: Empty::new(),
347            predicate_data: Empty::new(),
348        })
349    }
350
351    pub const fn message_coin_predicate(
352        sender: Address,
353        recipient: Address,
354        amount: Word,
355        nonce: Nonce,
356        predicate_gas_used: Word,
357        predicate: Vec<u8>,
358        predicate_data: Vec<u8>,
359    ) -> Self {
360        Self::MessageCoinPredicate(MessageCoinPredicate {
361            sender,
362            recipient,
363            amount,
364            nonce,
365            witness_index: Empty::new(),
366            predicate_gas_used,
367            data: Empty::new(),
368            predicate: PredicateCode { bytes: predicate },
369            predicate_data,
370        })
371    }
372
373    pub const fn message_data_signed(
374        sender: Address,
375        recipient: Address,
376        amount: Word,
377        nonce: Nonce,
378        witness_index: u16,
379        data: Vec<u8>,
380    ) -> Self {
381        Self::MessageDataSigned(MessageDataSigned {
382            sender,
383            recipient,
384            amount,
385            nonce,
386            witness_index,
387            data,
388            predicate: Empty::new(),
389            predicate_data: Empty::new(),
390            predicate_gas_used: Empty::new(),
391        })
392    }
393
394    pub const fn message_data_predicate(
395        sender: Address,
396        recipient: Address,
397        amount: Word,
398        nonce: Nonce,
399        predicate_gas_used: Word,
400        data: Vec<u8>,
401        predicate: Vec<u8>,
402        predicate_data: Vec<u8>,
403    ) -> Self {
404        Self::MessageDataPredicate(MessageDataPredicate {
405            sender,
406            recipient,
407            amount,
408            nonce,
409            witness_index: Empty::new(),
410            predicate_gas_used,
411            data,
412            predicate: PredicateCode { bytes: predicate },
413            predicate_data,
414        })
415    }
416
417    pub const fn utxo_id(&self) -> Option<&UtxoId> {
418        match self {
419            Self::CoinSigned(CoinSigned { utxo_id, .. })
420            | Self::CoinPredicate(CoinPredicate { utxo_id, .. })
421            | Self::Contract(Contract { utxo_id, .. }) => Some(utxo_id),
422            Self::MessageCoinSigned(_) => None,
423            Self::MessageCoinPredicate(_) => None,
424            Self::MessageDataSigned(_) => None,
425            Self::MessageDataPredicate(_) => None,
426        }
427    }
428
429    pub const fn input_owner(&self) -> Option<&Address> {
430        match self {
431            Self::CoinSigned(CoinSigned { owner, .. })
432            | Self::CoinPredicate(CoinPredicate { owner, .. }) => Some(owner),
433            Self::MessageCoinSigned(MessageCoinSigned { recipient, .. })
434            | Self::MessageCoinPredicate(MessageCoinPredicate { recipient, .. })
435            | Self::MessageDataSigned(MessageDataSigned { recipient, .. })
436            | Self::MessageDataPredicate(MessageDataPredicate { recipient, .. }) => {
437                Some(recipient)
438            }
439            Self::Contract(_) => None,
440        }
441    }
442
443    pub const fn asset_id<'a>(
444        &'a self,
445        base_asset_id: &'a AssetId,
446    ) -> Option<&'a AssetId> {
447        match self {
448            Input::CoinSigned(CoinSigned { asset_id, .. })
449            | Input::CoinPredicate(CoinPredicate { asset_id, .. }) => Some(asset_id),
450            Input::MessageCoinSigned(_)
451            | Input::MessageCoinPredicate(_)
452            | Input::MessageDataSigned(_)
453            | Input::MessageDataPredicate(_) => Some(base_asset_id),
454            Input::Contract(_) => None,
455        }
456    }
457
458    pub const fn contract_id(&self) -> Option<&ContractId> {
459        match self {
460            Self::Contract(Contract { contract_id, .. }) => Some(contract_id),
461            _ => None,
462        }
463    }
464
465    pub const fn amount(&self) -> Option<Word> {
466        match self {
467            Input::CoinSigned(CoinSigned { amount, .. })
468            | Input::CoinPredicate(CoinPredicate { amount, .. })
469            | Input::MessageCoinSigned(MessageCoinSigned { amount, .. })
470            | Input::MessageCoinPredicate(MessageCoinPredicate { amount, .. })
471            | Input::MessageDataSigned(MessageDataSigned { amount, .. })
472            | Input::MessageDataPredicate(MessageDataPredicate { amount, .. }) => {
473                Some(*amount)
474            }
475            Input::Contract(_) => None,
476        }
477    }
478
479    pub const fn witness_index(&self) -> Option<u16> {
480        match self {
481            Input::CoinSigned(CoinSigned { witness_index, .. })
482            | Input::MessageCoinSigned(MessageCoinSigned { witness_index, .. })
483            | Input::MessageDataSigned(MessageDataSigned { witness_index, .. }) => {
484                Some(*witness_index)
485            }
486            Input::CoinPredicate(_)
487            | Input::Contract(_)
488            | Input::MessageCoinPredicate(_)
489            | Input::MessageDataPredicate(_) => None,
490        }
491    }
492
493    pub fn predicate_offset(&self) -> Option<usize> {
494        match self {
495            Input::CoinPredicate(_) => InputRepr::Coin.coin_predicate_offset(),
496            Input::MessageCoinPredicate(_) => InputRepr::Message.data_offset(),
497            Input::MessageDataPredicate(MessageDataPredicate { data, .. }) => {
498                InputRepr::Message.data_offset().map(|o| {
499                    o.saturating_add(bytes::padded_len(data).unwrap_or(usize::MAX))
500                })
501            }
502            Input::CoinSigned(_)
503            | Input::Contract(_)
504            | Input::MessageCoinSigned(_)
505            | Input::MessageDataSigned(_) => None,
506        }
507    }
508
509    pub fn predicate_data_offset(&self) -> Option<usize> {
510        match self {
511            Input::CoinPredicate(CoinPredicate { predicate, .. })
512            | Input::MessageCoinPredicate(MessageCoinPredicate { predicate, .. })
513            | Input::MessageDataPredicate(MessageDataPredicate { predicate, .. }) => {
514                self.predicate_offset().map(|o| {
515                    o.saturating_add(bytes::padded_len(predicate).unwrap_or(usize::MAX))
516                })
517            }
518            Input::CoinSigned(_)
519            | Input::Contract(_)
520            | Input::MessageCoinSigned(_)
521            | Input::MessageDataSigned(_) => None,
522        }
523    }
524
525    pub fn predicate_len(&self) -> Option<usize> {
526        match self {
527            Input::CoinPredicate(CoinPredicate { predicate, .. })
528            | Input::MessageCoinPredicate(MessageCoinPredicate { predicate, .. })
529            | Input::MessageDataPredicate(MessageDataPredicate { predicate, .. }) => {
530                Some(predicate.len())
531            }
532            Input::CoinSigned(_)
533            | Input::MessageCoinSigned(_)
534            | Input::MessageDataSigned(_) => Some(0),
535            Input::Contract(_) => None,
536        }
537    }
538
539    pub fn predicate_data_len(&self) -> Option<usize> {
540        match self {
541            Input::CoinPredicate(CoinPredicate { predicate_data, .. })
542            | Input::MessageCoinPredicate(MessageCoinPredicate {
543                predicate_data, ..
544            })
545            | Input::MessageDataPredicate(MessageDataPredicate {
546                predicate_data, ..
547            }) => Some(predicate_data.len()),
548            Input::CoinSigned(_)
549            | Input::MessageCoinSigned(_)
550            | Input::MessageDataSigned(_) => Some(0),
551            Input::Contract(_) => None,
552        }
553    }
554
555    pub fn predicate_gas_used(&self) -> Option<Word> {
556        match self {
557            Input::CoinPredicate(CoinPredicate {
558                predicate_gas_used, ..
559            })
560            | Input::MessageCoinPredicate(MessageCoinPredicate {
561                predicate_gas_used,
562                ..
563            })
564            | Input::MessageDataPredicate(MessageDataPredicate {
565                predicate_gas_used,
566                ..
567            }) => Some(*predicate_gas_used),
568            Input::CoinSigned(_)
569            | Input::MessageCoinSigned(_)
570            | Input::MessageDataSigned(_)
571            | Input::Contract(_) => None,
572        }
573    }
574
575    pub fn set_predicate_gas_used(&mut self, gas: Word) {
576        match self {
577            Input::CoinPredicate(CoinPredicate {
578                predicate_gas_used, ..
579            })
580            | Input::MessageCoinPredicate(MessageCoinPredicate {
581                predicate_gas_used,
582                ..
583            })
584            | Input::MessageDataPredicate(MessageDataPredicate {
585                predicate_gas_used,
586                ..
587            }) => *predicate_gas_used = gas,
588            Input::CoinSigned(_)
589            | Input::MessageCoinSigned(_)
590            | Input::MessageDataSigned(_)
591            | Input::Contract(_) => {}
592        }
593    }
594
595    pub fn message_id(&self) -> Option<MessageId> {
596        match self {
597            Self::MessageCoinSigned(message) => Some(message.message_id()),
598            Self::MessageCoinPredicate(message) => Some(message.message_id()),
599            Self::MessageDataPredicate(message) => Some(message.message_id()),
600            Self::MessageDataSigned(message) => Some(message.message_id()),
601            _ => None,
602        }
603    }
604
605    pub const fn tx_pointer(&self) -> Option<&TxPointer> {
606        match self {
607            Input::CoinSigned(CoinSigned { tx_pointer, .. })
608            | Input::CoinPredicate(CoinPredicate { tx_pointer, .. })
609            | Input::Contract(Contract { tx_pointer, .. }) => Some(tx_pointer),
610            _ => None,
611        }
612    }
613
614    pub fn input_data(&self) -> Option<&[u8]> {
615        match self {
616            Input::MessageDataSigned(MessageDataSigned { data, .. })
617            | Input::MessageDataPredicate(MessageDataPredicate { data, .. }) => {
618                Some(data)
619            }
620            _ => None,
621        }
622    }
623
624    pub fn input_data_len(&self) -> Option<usize> {
625        match self {
626            Input::MessageDataSigned(MessageDataSigned { data, .. })
627            | Input::MessageDataPredicate(MessageDataPredicate { data, .. }) => {
628                Some(data.len())
629            }
630            Input::MessageCoinSigned(_) | Input::MessageCoinPredicate(_) => Some(0),
631            _ => None,
632        }
633    }
634
635    pub fn input_predicate(&self) -> Option<&[u8]> {
636        match self {
637            Input::CoinPredicate(CoinPredicate { predicate, .. })
638            | Input::MessageCoinPredicate(MessageCoinPredicate { predicate, .. })
639            | Input::MessageDataPredicate(MessageDataPredicate { predicate, .. }) => {
640                Some(predicate)
641            }
642
643            _ => None,
644        }
645    }
646
647    pub fn input_predicate_data(&self) -> Option<&[u8]> {
648        match self {
649            Input::CoinPredicate(CoinPredicate { predicate_data, .. })
650            | Input::MessageCoinPredicate(MessageCoinPredicate {
651                predicate_data, ..
652            })
653            | Input::MessageDataPredicate(MessageDataPredicate {
654                predicate_data, ..
655            }) => Some(predicate_data),
656
657            _ => None,
658        }
659    }
660
661    /// Return a tuple containing the predicate, its data and used gas if the input is of
662    /// type `CoinPredicate` or `MessageCoinPredicate` or `MessageDataPredicate`
663    pub fn predicate(&self) -> Option<(&[u8], &[u8], &Word)> {
664        match self {
665            Input::CoinPredicate(CoinPredicate {
666                predicate,
667                predicate_data,
668                predicate_gas_used,
669                ..
670            })
671            | Input::MessageCoinPredicate(MessageCoinPredicate {
672                predicate,
673                predicate_data,
674                predicate_gas_used,
675                ..
676            })
677            | Input::MessageDataPredicate(MessageDataPredicate {
678                predicate,
679                predicate_data,
680                predicate_gas_used,
681                ..
682            }) => Some((
683                predicate.as_slice(),
684                predicate_data.as_slice(),
685                predicate_gas_used,
686            )),
687
688            _ => None,
689        }
690    }
691
692    pub const fn is_coin(&self) -> bool {
693        self.is_coin_signed() | self.is_coin_predicate()
694    }
695
696    pub const fn is_coin_signed(&self) -> bool {
697        matches!(self, Input::CoinSigned(_))
698    }
699
700    pub const fn is_coin_predicate(&self) -> bool {
701        matches!(self, Input::CoinPredicate(_))
702    }
703
704    pub const fn is_message(&self) -> bool {
705        self.is_message_coin_signed()
706            | self.is_message_coin_predicate()
707            | self.is_message_data_signed()
708            | self.is_message_data_predicate()
709    }
710
711    pub const fn is_message_coin_signed(&self) -> bool {
712        matches!(self, Input::MessageCoinSigned(_))
713    }
714
715    pub const fn is_message_coin_predicate(&self) -> bool {
716        matches!(self, Input::MessageCoinPredicate(_))
717    }
718
719    pub const fn is_message_data_signed(&self) -> bool {
720        matches!(self, Input::MessageDataSigned(_))
721    }
722
723    pub const fn is_message_data_predicate(&self) -> bool {
724        matches!(self, Input::MessageDataPredicate(_))
725    }
726
727    pub const fn is_contract(&self) -> bool {
728        matches!(self, Input::Contract(_))
729    }
730
731    pub const fn coin_predicate_offset() -> usize {
732        INPUT_COIN_FIXED_SIZE
733    }
734
735    pub const fn message_data_offset() -> usize {
736        INPUT_MESSAGE_FIXED_SIZE
737    }
738
739    pub const fn balance_root(&self) -> Option<&Bytes32> {
740        match self {
741            Input::Contract(Contract { balance_root, .. }) => Some(balance_root),
742            _ => None,
743        }
744    }
745
746    pub const fn state_root(&self) -> Option<&Bytes32> {
747        match self {
748            Input::Contract(Contract { state_root, .. }) => Some(state_root),
749            _ => None,
750        }
751    }
752
753    pub const fn sender(&self) -> Option<&Address> {
754        match self {
755            Input::MessageCoinSigned(MessageCoinSigned { sender, .. })
756            | Input::MessageCoinPredicate(MessageCoinPredicate { sender, .. })
757            | Input::MessageDataSigned(MessageDataSigned { sender, .. })
758            | Input::MessageDataPredicate(MessageDataPredicate { sender, .. }) => {
759                Some(sender)
760            }
761            _ => None,
762        }
763    }
764
765    pub const fn recipient(&self) -> Option<&Address> {
766        match self {
767            Input::MessageCoinSigned(MessageCoinSigned { recipient, .. })
768            | Input::MessageCoinPredicate(MessageCoinPredicate { recipient, .. })
769            | Input::MessageDataSigned(MessageDataSigned { recipient, .. })
770            | Input::MessageDataPredicate(MessageDataPredicate { recipient, .. }) => {
771                Some(recipient)
772            }
773            _ => None,
774        }
775    }
776
777    pub const fn nonce(&self) -> Option<&Nonce> {
778        match self {
779            Input::MessageCoinSigned(MessageCoinSigned { nonce, .. })
780            | Input::MessageCoinPredicate(MessageCoinPredicate { nonce, .. })
781            | Input::MessageDataSigned(MessageDataSigned { nonce, .. })
782            | Input::MessageDataPredicate(MessageDataPredicate { nonce, .. }) => {
783                Some(nonce)
784            }
785            _ => None,
786        }
787    }
788
789    /// Empties fields that should be zero during the signing.
790    pub fn prepare_sign(&mut self) {
791        match self {
792            Input::CoinSigned(coin) => coin.prepare_sign(),
793            Input::CoinPredicate(coin) => coin.prepare_sign(),
794            Input::Contract(contract) => contract.prepare_sign(),
795            Input::MessageCoinSigned(message) => message.prepare_sign(),
796            Input::MessageCoinPredicate(message) => message.prepare_sign(),
797            Input::MessageDataSigned(message) => message.prepare_sign(),
798            Input::MessageDataPredicate(message) => message.prepare_sign(),
799        }
800    }
801
802    pub fn compute_message_id(
803        sender: &Address,
804        recipient: &Address,
805        nonce: &Nonce,
806        amount: Word,
807        data: &[u8],
808    ) -> MessageId {
809        compute_message_id(sender, recipient, nonce, amount, data)
810    }
811
812    pub fn predicate_owner<P>(predicate: P) -> Address
813    where
814        P: AsRef<[u8]>,
815    {
816        use crate::Contract;
817
818        let root = Contract::root_from_code(predicate);
819
820        let mut hasher = Hasher::default();
821
822        hasher.input(ContractId::SEED);
823        hasher.input(root);
824
825        (*hasher.digest()).into()
826    }
827
828    pub fn is_predicate_owner_valid<P>(owner: &Address, predicate: P) -> bool
829    where
830        P: AsRef<[u8]>,
831    {
832        owner == &Self::predicate_owner(predicate)
833    }
834}
835
836impl Serialize for Input {
837    fn size_static(&self) -> usize {
838        (match self {
839            Input::CoinSigned(coin) => coin.size_static(),
840            Input::CoinPredicate(coin) => coin.size_static(),
841            Input::Contract(contract) => contract.size_static(),
842            Input::MessageCoinSigned(message) => message.size_static(),
843            Input::MessageCoinPredicate(message) => message.size_static(),
844            Input::MessageDataSigned(message) => message.size_static(),
845            Input::MessageDataPredicate(message) => message.size_static(),
846        })
847        .saturating_add(8) // Discriminant
848    }
849
850    fn size_dynamic(&self) -> usize {
851        match self {
852            Input::CoinSigned(coin) => coin.size_dynamic(),
853            Input::CoinPredicate(coin) => coin.size_dynamic(),
854            Input::Contract(contract) => contract.size_dynamic(),
855            Input::MessageCoinSigned(message) => message.size_dynamic(),
856            Input::MessageCoinPredicate(message) => message.size_dynamic(),
857            Input::MessageDataSigned(message) => message.size_dynamic(),
858            Input::MessageDataPredicate(message) => message.size_dynamic(),
859        }
860    }
861
862    fn encode_static<O: Output + ?Sized>(&self, buffer: &mut O) -> Result<(), Error> {
863        let discr = InputRepr::from(self);
864        discr.encode_static(buffer)?;
865        match self {
866            Input::CoinSigned(coin) => coin.encode_static(buffer),
867            Input::CoinPredicate(coin) => coin.encode_static(buffer),
868            Input::Contract(contract) => contract.encode_static(buffer),
869            Input::MessageCoinSigned(message) => message.encode_static(buffer),
870            Input::MessageCoinPredicate(message) => message.encode_static(buffer),
871            Input::MessageDataSigned(message) => message.encode_static(buffer),
872            Input::MessageDataPredicate(message) => message.encode_static(buffer),
873        }
874    }
875
876    fn encode_dynamic<O: Output + ?Sized>(&self, buffer: &mut O) -> Result<(), Error> {
877        let discr = InputRepr::from(self);
878        discr.encode_dynamic(buffer)?;
879        match self {
880            Input::CoinSigned(coin) => coin.encode_dynamic(buffer),
881            Input::CoinPredicate(coin) => coin.encode_dynamic(buffer),
882            Input::Contract(contract) => contract.encode_dynamic(buffer),
883            Input::MessageCoinSigned(message) => message.encode_dynamic(buffer),
884            Input::MessageCoinPredicate(message) => message.encode_dynamic(buffer),
885            Input::MessageDataSigned(message) => message.encode_dynamic(buffer),
886            Input::MessageDataPredicate(message) => message.encode_dynamic(buffer),
887        }
888    }
889}
890
891impl Deserialize for Input {
892    fn decode_static<I: canonical::Input + ?Sized>(
893        buffer: &mut I,
894    ) -> Result<Self, Error> {
895        Ok(
896            match <InputRepr as Deserialize>::decode(buffer)
897                .map_err(|_| Error::UnknownDiscriminant)?
898            {
899                InputRepr::Coin => {
900                    let coin = CoinFull::decode_static(buffer)?;
901                    if coin.predicate.capacity() == 0 {
902                        Input::CoinSigned(coin.into_signed())
903                    } else {
904                        Input::CoinPredicate(coin.into_predicate())
905                    }
906                }
907                InputRepr::Contract => {
908                    let contract = Contract::decode_static(buffer)?;
909                    Input::Contract(contract)
910                }
911                InputRepr::Message => {
912                    let message = FullMessage::decode_static(buffer)?;
913                    match (
914                        message.data.capacity() == 0,
915                        message.predicate.capacity() == 0,
916                    ) {
917                        (true, true) => {
918                            Input::MessageCoinSigned(message.into_coin_signed())
919                        }
920                        (true, false) => {
921                            Input::MessageCoinPredicate(message.into_coin_predicate())
922                        }
923                        (false, true) => {
924                            Input::MessageDataSigned(message.into_message_data_signed())
925                        }
926                        (false, false) => Input::MessageDataPredicate(
927                            message.into_message_data_predicate(),
928                        ),
929                    }
930                }
931            },
932        )
933    }
934
935    fn decode_dynamic<I: canonical::Input + ?Sized>(
936        &mut self,
937        buffer: &mut I,
938    ) -> Result<(), Error> {
939        match self {
940            Input::CoinSigned(coin) => coin.decode_dynamic(buffer),
941            Input::CoinPredicate(coin) => coin.decode_dynamic(buffer),
942            Input::Contract(contract) => contract.decode_dynamic(buffer),
943            Input::MessageCoinSigned(message) => message.decode_dynamic(buffer),
944            Input::MessageCoinPredicate(message) => message.decode_dynamic(buffer),
945            Input::MessageDataSigned(message) => message.decode_dynamic(buffer),
946            Input::MessageDataPredicate(message) => message.decode_dynamic(buffer),
947        }
948    }
949}
950
951#[cfg(all(test, feature = "std"))]
952mod snapshot_tests;
953
954#[cfg(feature = "typescript")]
955pub mod typescript {
956    use wasm_bindgen::prelude::*;
957
958    use super::*;
959
960    use crate::{
961        TxPointer,
962        UtxoId,
963    };
964    use fuel_types::{
965        Address,
966        AssetId,
967        Bytes32,
968        Word,
969    };
970
971    use alloc::{
972        boxed::Box,
973        format,
974        string::String,
975        vec::Vec,
976    };
977
978    #[derive(Clone, Eq, Hash, PartialEq, serde::Serialize, serde::Deserialize)]
979    #[wasm_bindgen]
980    pub struct Input(#[wasm_bindgen(skip)] pub Box<crate::Input>);
981
982    #[wasm_bindgen]
983    impl Input {
984        #[wasm_bindgen(js_name = toJSON)]
985        pub fn to_json(&self) -> String {
986            serde_json::to_string(&self.0).expect("unable to json format")
987        }
988
989        #[wasm_bindgen(js_name = toString)]
990        pub fn typescript_to_string(&self) -> String {
991            format!("{:?}", self.0)
992        }
993
994        #[wasm_bindgen(js_name = to_bytes)]
995        pub fn typescript_to_bytes(&self) -> Vec<u8> {
996            use fuel_types::canonical::Serialize;
997            self.0.to_bytes()
998        }
999
1000        #[wasm_bindgen(js_name = from_bytes)]
1001        pub fn typescript_from_bytes(value: &[u8]) -> Result<Input, js_sys::Error> {
1002            use fuel_types::canonical::Deserialize;
1003            crate::Input::from_bytes(value)
1004                .map(|v| Input(Box::new(v)))
1005                .map_err(|e| js_sys::Error::new(&format!("{:?}", e)))
1006        }
1007
1008        #[wasm_bindgen]
1009        pub fn coin_predicate(
1010            utxo_id: UtxoId,
1011            owner: Address,
1012            amount: Word,
1013            asset_id: AssetId,
1014            tx_pointer: TxPointer,
1015            predicate_gas_used: Word,
1016            predicate: Vec<u8>,
1017            predicate_data: Vec<u8>,
1018        ) -> Input {
1019            Input(Box::new(crate::Input::CoinPredicate(CoinPredicate {
1020                utxo_id,
1021                owner,
1022                amount,
1023                asset_id,
1024                tx_pointer,
1025                witness_index: Empty::new(),
1026                predicate_gas_used,
1027                predicate: PredicateCode { bytes: predicate },
1028                predicate_data,
1029            })))
1030        }
1031
1032        #[wasm_bindgen]
1033        pub fn coin_signed(
1034            utxo_id: UtxoId,
1035            owner: Address,
1036            amount: Word,
1037            asset_id: AssetId,
1038            tx_pointer: TxPointer,
1039            witness_index: u16,
1040        ) -> Input {
1041            Input(Box::new(crate::Input::CoinSigned(CoinSigned {
1042                utxo_id,
1043                owner,
1044                amount,
1045                asset_id,
1046                tx_pointer,
1047                witness_index,
1048                predicate_gas_used: Empty::new(),
1049                predicate: Empty::new(),
1050                predicate_data: Empty::new(),
1051            })))
1052        }
1053
1054        #[wasm_bindgen]
1055        pub fn contract(
1056            utxo_id: UtxoId,
1057            balance_root: Bytes32,
1058            state_root: Bytes32,
1059            tx_pointer: TxPointer,
1060            contract_id: ContractId,
1061        ) -> Input {
1062            Input(Box::new(crate::Input::Contract(Contract {
1063                utxo_id,
1064                balance_root,
1065                state_root,
1066                tx_pointer,
1067                contract_id,
1068            })))
1069        }
1070
1071        #[wasm_bindgen]
1072        pub fn message_coin_signed(
1073            sender: Address,
1074            recipient: Address,
1075            amount: Word,
1076            nonce: Nonce,
1077            witness_index: u16,
1078        ) -> Input {
1079            Input(Box::new(crate::Input::MessageCoinSigned(
1080                MessageCoinSigned {
1081                    sender,
1082                    recipient,
1083                    amount,
1084                    nonce,
1085                    witness_index,
1086                    predicate_gas_used: Empty::new(),
1087                    data: Empty::new(),
1088                    predicate: Empty::new(),
1089                    predicate_data: Empty::new(),
1090                },
1091            )))
1092        }
1093
1094        #[wasm_bindgen]
1095        pub fn message_coin_predicate(
1096            sender: Address,
1097            recipient: Address,
1098            amount: Word,
1099            nonce: Nonce,
1100            predicate_gas_used: Word,
1101            predicate: Vec<u8>,
1102            predicate_data: Vec<u8>,
1103        ) -> Input {
1104            Input(Box::new(crate::Input::MessageCoinPredicate(
1105                MessageCoinPredicate {
1106                    sender,
1107                    recipient,
1108                    amount,
1109                    nonce,
1110                    witness_index: Empty::new(),
1111                    predicate_gas_used,
1112                    data: Empty::new(),
1113                    predicate: PredicateCode { bytes: predicate },
1114                    predicate_data,
1115                },
1116            )))
1117        }
1118
1119        #[wasm_bindgen]
1120        pub fn message_data_signed(
1121            sender: Address,
1122            recipient: Address,
1123            amount: Word,
1124            nonce: Nonce,
1125            witness_index: u16,
1126            data: Vec<u8>,
1127        ) -> Input {
1128            Input(Box::new(crate::Input::MessageDataSigned(
1129                MessageDataSigned {
1130                    sender,
1131                    recipient,
1132                    amount,
1133                    nonce,
1134                    witness_index,
1135                    data,
1136                    predicate: Empty::new(),
1137                    predicate_data: Empty::new(),
1138                    predicate_gas_used: Empty::new(),
1139                },
1140            )))
1141        }
1142
1143        #[wasm_bindgen]
1144        pub fn message_data_predicate(
1145            sender: Address,
1146            recipient: Address,
1147            amount: Word,
1148            nonce: Nonce,
1149            predicate_gas_used: Word,
1150            data: Vec<u8>,
1151            predicate: Vec<u8>,
1152            predicate_data: Vec<u8>,
1153        ) -> Input {
1154            Input(Box::new(crate::Input::MessageDataPredicate(
1155                MessageDataPredicate {
1156                    sender,
1157                    recipient,
1158                    amount,
1159                    nonce,
1160                    witness_index: Empty::new(),
1161                    predicate_gas_used,
1162                    data,
1163                    predicate: PredicateCode { bytes: predicate },
1164                    predicate_data,
1165                },
1166            )))
1167        }
1168    }
1169}