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#[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 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 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 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) }
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}