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