substrate_constructor/
fill_prepare.rs

1use bitvec::prelude::{BitVec, Lsb0, Msb0};
2use external_memory_tools::ExternalMemory;
3use num_bigint::{BigInt, BigUint};
4use parity_scale_codec::Encode;
5use primitive_types::H256;
6use scale_info::{
7    form::PortableForm, interner::UntrackedSymbol, Field, Type, TypeDef, TypeDefBitSequence,
8    TypeDefPrimitive, Variant,
9};
10use sp_arithmetic::{PerU16, Perbill, Percent, Permill, Perquintill};
11use substrate_crypto_light::{
12    common::AccountId32,
13    ecdsa::{Public as PublicEcdsa, Signature as SignatureEcdsa},
14    ed25519::{Public as PublicEd25519, Signature as SignatureEd25519},
15    sr25519::{Public as PublicSr25519, Signature as SignatureSr25519},
16};
17use substrate_parser::{
18    cards::{Documented, Info},
19    decoding_sci::{find_bit_order_ty, husk_type, FoundBitOrder, ResolvedTy, Ty},
20    error::{ExtensionsError, RegistryError, RegistryInternalError},
21    propagated::{Checker, Propagated, SpecialtySet},
22    special_indicators::{
23        SignatureIndicator, SpecialtyH256, SpecialtyTypeHinted, SpecialtyUnsignedInteger,
24    },
25    traits::ResolveType,
26};
27
28use std::any::TypeId;
29
30use crate::{
31    error::ErrorFixMe,
32    finalize::{Finalize, TypeContent},
33    traits::{AsFillMetadata, AsPalletMetadata, Unsigned},
34    try_fill::TryFill,
35};
36
37#[derive(Clone, Debug)]
38pub struct VariantSelected {
39    pub selector_index: usize,
40    pub docs: String,
41    pub fields_to_fill: Vec<FieldToFill>,
42    pub index: u8,
43    pub name: String,
44}
45
46#[derive(Clone, Debug)]
47pub struct FieldToFill {
48    pub type_to_fill: TypeToFill,
49    pub field_docs: String,
50    pub field_name: Option<String>,
51    pub type_name: Option<String>,
52}
53
54#[derive(Clone, Debug)]
55pub struct TypeToFill {
56    pub content: TypeContentToFill,
57    pub info: Vec<Info>,
58}
59
60#[derive(Clone, Debug)]
61pub enum TypeContentToFill {
62    ArrayU8(ArrayU8ToFill),
63    ArrayRegular(ArrayRegularToFill),
64    BitSequence(BitSequenceContent),
65    Composite(Vec<FieldToFill>),
66    Primitive(PrimitiveToFill),
67    SequenceRegular(SequenceRegularToFill),
68    SequenceU8(SequenceU8ToFill),
69    SpecialType(SpecialTypeToFill),
70    Tuple(Vec<TypeToFill>),
71    Variant(VariantSelector),
72    VariantEmpty,
73}
74
75#[derive(Clone, Debug)]
76pub struct VariantSelector {
77    pub available_variants: Vec<Variant<PortableForm>>,
78    pub selected: VariantSelected,
79}
80
81impl VariantSelector {
82    pub fn init<E: ExternalMemory, M: AsFillMetadata<E>>(
83        variants: &[Variant<PortableForm>],
84        ext_memory: &mut E,
85        registry: &M::TypeRegistry,
86    ) -> Result<Self, RegistryError<E>> {
87        Self::new_at::<E, M>(variants, ext_memory, registry, 0)
88    }
89    pub fn new_at<E: ExternalMemory, M: AsFillMetadata<E>>(
90        variants: &[Variant<PortableForm>],
91        ext_memory: &mut E,
92        registry: &M::TypeRegistry,
93        selector_index: usize,
94    ) -> Result<Self, RegistryError<E>> {
95        // this panics if selector is out of bounds; fix this later;
96        let variant = &variants[selector_index];
97        let name = variant.name.to_owned();
98        let docs = variant.collect_docs();
99        let fields_to_fill =
100            prepare_fields::<E, M>(&variant.fields, ext_memory, registry, Checker::new())?;
101        let selected = VariantSelected {
102            selector_index,
103            docs,
104            fields_to_fill,
105            index: variant.index,
106            name,
107        };
108        Ok(Self {
109            available_variants: variants.to_owned(),
110            selected,
111        })
112    }
113    pub fn selector_up<E: ExternalMemory, M: AsFillMetadata<E>>(
114        &mut self,
115        ext_memory: &mut E,
116        registry: &M::TypeRegistry,
117    ) -> Result<(), RegistryError<E>> {
118        let new_selector_index = {
119            if self.selected.selector_index + 1 == self.available_variants.len() {
120                0
121            } else {
122                self.selected.selector_index + 1
123            }
124        };
125        *self = VariantSelector::new_at::<E, M>(
126            &self.available_variants,
127            ext_memory,
128            registry,
129            new_selector_index,
130        )?;
131        Ok(())
132    }
133    pub fn selector_down<E: ExternalMemory, M: AsFillMetadata<E>>(
134        &mut self,
135        ext_memory: &mut E,
136        registry: &M::TypeRegistry,
137    ) -> Result<(), RegistryError<E>> {
138        let new_selector_index = {
139            if self.selected.selector_index == 0 {
140                self.available_variants.len() - 1
141            } else {
142                self.selected.selector_index - 1
143            }
144        };
145        *self = VariantSelector::new_at::<E, M>(
146            &self.available_variants,
147            ext_memory,
148            registry,
149            new_selector_index,
150        )?;
151        Ok(())
152    }
153}
154
155#[derive(Clone, Debug)]
156pub enum BitSequenceContent {
157    BitVecU8Lsb0(BitVec<u8, Lsb0>),
158    BitVecU16Lsb0(BitVec<u16, Lsb0>),
159    BitVecU32Lsb0(BitVec<u32, Lsb0>),
160    #[cfg(target_pointer_width = "64")]
161    BitVecU64Lsb0(BitVec<u64, Lsb0>),
162    BitVecU8Msb0(BitVec<u8, Msb0>),
163    BitVecU16Msb0(BitVec<u16, Msb0>),
164    BitVecU32Msb0(BitVec<u32, Msb0>),
165    #[cfg(target_pointer_width = "64")]
166    BitVecU64Msb0(BitVec<u64, Msb0>),
167}
168
169#[derive(Clone, Debug)]
170pub enum PrimitiveToFill {
171    CompactUnsigned(SpecialtyUnsignedToFill),
172    Regular(RegularPrimitiveToFill),
173    Unsigned(SpecialtyUnsignedToFill),
174}
175
176#[derive(Clone, Debug)]
177pub enum RegularPrimitiveToFill {
178    Bool(Option<bool>),
179    Char(Option<char>),
180    I8(Option<i8>),
181    I16(Option<i16>),
182    I32(Option<i32>),
183    I64(Option<i64>),
184    I128(Option<i128>),
185    I256(Option<BigInt>),
186    Str(String),
187    U256(Option<BigUint>),
188}
189
190#[derive(Clone, Debug)]
191pub enum UnsignedToFill {
192    U8(Option<u8>),
193    U16(Option<u16>),
194    U32(Option<u32>),
195    U64(Option<u64>),
196    U128(Option<u128>),
197}
198
199impl UnsignedToFill {
200    pub fn into_unsigned(&self) -> Option<Unsigned> {
201        match &self {
202            UnsignedToFill::U8(a) => a.map(Unsigned::U8),
203            UnsignedToFill::U16(a) => a.map(Unsigned::U16),
204            UnsignedToFill::U32(a) => a.map(Unsigned::U32),
205            UnsignedToFill::U64(a) => a.map(Unsigned::U64),
206            UnsignedToFill::U128(a) => a.map(Unsigned::U128),
207        }
208    }
209}
210
211#[derive(Clone, Debug)]
212pub struct SpecialtyUnsignedToFill {
213    pub content: UnsignedToFill,
214    pub specialty: SpecialtyUnsignedInteger,
215}
216
217#[derive(Debug)]
218pub enum SequenceDraft {
219    U8(SequenceDraftContent),
220    Regular(SequenceDraftContent),
221}
222
223#[derive(Debug)]
224pub struct SequenceDraftContent {
225    pub info_element: Vec<Info>,
226    pub resolved_ty: ResolvedTy,
227    pub checker: Checker,
228}
229
230#[derive(Clone, Debug)]
231pub struct SequenceU8ToFill {
232    pub content: Vec<u8>,
233    pub info_element: Vec<Info>,
234}
235
236#[derive(Clone, Debug)]
237pub struct SequenceRegularToFill {
238    pub content: Vec<TypeContentToFill>,
239    pub info_element: Vec<Info>,
240    pub ty: Type<PortableForm>,
241    pub id: u32,
242}
243
244impl SequenceRegularToFill {
245    pub fn remove_last_element(&mut self) {
246        self.content.pop();
247    }
248    pub fn add_new_element<E: ExternalMemory, M: AsFillMetadata<E>>(
249        &mut self,
250        ext_memory: &mut E,
251        registry: &M::TypeRegistry,
252    ) -> Result<(), RegistryError<E>> {
253        let element = prepare_type::<E, M>(
254            &Ty::Resolved(ResolvedTy {
255                ty: self.ty.to_owned(),
256                id: self.id,
257            }),
258            ext_memory,
259            registry,
260            Propagated::new(),
261        )?;
262        self.content.push(element.content);
263        Ok(())
264    }
265    pub fn set_number_of_elements<E: ExternalMemory, M: AsFillMetadata<E>>(
266        &mut self,
267        ext_memory: &mut E,
268        registry: &M::TypeRegistry,
269        number_of_elements: usize,
270    ) -> Result<(), RegistryError<E>> {
271        if self.content.len() <= number_of_elements {
272            for _i in 0..number_of_elements - self.content.len() {
273                self.add_new_element::<E, M>(ext_memory, registry)?;
274            }
275        } else {
276            self.content.truncate(number_of_elements);
277        }
278        Ok(())
279    }
280}
281
282#[derive(Clone, Debug)]
283pub struct ArrayU8ToFill {
284    pub content: Vec<u8>,
285    pub info_element: Vec<Info>,
286    pub len: u32,
287}
288
289#[derive(Clone, Debug)]
290pub struct ArrayRegularToFill {
291    pub content: Vec<TypeContentToFill>,
292    pub info_element: Vec<Info>,
293    pub len: u32,
294}
295
296#[derive(Clone, Debug)]
297pub enum SpecialTypeToFill {
298    AccountId32(Option<AccountId32>),
299    Era(EraToFill),
300    H256 {
301        hash: Option<H256>,
302        specialty: SpecialtyH256,
303    },
304    PerU16 {
305        value: Option<PerU16>,
306        is_compact: bool,
307    },
308    Perbill {
309        value: Option<Perbill>,
310        is_compact: bool,
311    },
312    Percent {
313        value: Option<Percent>,
314        is_compact: bool,
315    },
316    Permill {
317        value: Option<Permill>,
318        is_compact: bool,
319    },
320    Perquintill {
321        value: Option<Perquintill>,
322        is_compact: bool,
323    },
324    PublicEd25519(Option<PublicEd25519>),
325    PublicSr25519(Option<PublicSr25519>),
326    PublicEcdsa(Option<PublicEcdsa>),
327    SignatureEd25519(Option<SignatureEd25519>),
328    SignatureSr25519(Option<SignatureSr25519>),
329    SignatureEcdsa(Option<SignatureEcdsa>),
330}
331
332#[derive(Clone, Debug)]
333pub enum EraToFill {
334    Immortal,
335    Mortal {
336        period_entry: u64,
337        block_number_entry: Option<u64>,
338    },
339}
340
341pub const DEFAULT_PERIOD: u64 = 64;
342
343pub trait FillPrimitive {
344    fn primitive_to_fill(
345        specialty_set: &SpecialtySet,
346    ) -> Result<PrimitiveToFill, RegistryInternalError>;
347}
348
349macro_rules! impl_regular_fill_primitive {
350    ($($ty:ty, $variant:ident), *) => {
351        $(
352            impl FillPrimitive for $ty {
353                fn primitive_to_fill(specialty_set: &SpecialtySet) -> Result<PrimitiveToFill, RegistryInternalError> {
354                    if let Some(id) = specialty_set.compact_at {Err(RegistryInternalError::UnexpectedCompactInsides{id})}
355                    else {Ok(PrimitiveToFill::Regular(RegularPrimitiveToFill::$variant(None)))}
356                }
357            }
358        )*
359    }
360}
361
362impl_regular_fill_primitive!(bool, Bool);
363impl_regular_fill_primitive!(char, Char);
364impl_regular_fill_primitive!(i8, I8);
365impl_regular_fill_primitive!(i16, I16);
366impl_regular_fill_primitive!(i32, I32);
367impl_regular_fill_primitive!(i64, I64);
368impl_regular_fill_primitive!(i128, I128);
369impl_regular_fill_primitive!(BigInt, I256);
370impl_regular_fill_primitive!(BigUint, U256);
371
372impl FillPrimitive for String {
373    fn primitive_to_fill(
374        specialty_set: &SpecialtySet,
375    ) -> Result<PrimitiveToFill, RegistryInternalError> {
376        specialty_set.reject_compact()?;
377        Ok(PrimitiveToFill::Regular(RegularPrimitiveToFill::Str(
378            String::new(),
379        )))
380    }
381}
382
383macro_rules! impl_unsigned_fill_primitive {
384    ($($ty:ty, $variant:ident), *) => {
385        $(
386            impl FillPrimitive for $ty {
387                fn primitive_to_fill(specialty_set: &SpecialtySet) -> Result<PrimitiveToFill, RegistryInternalError> {
388                    let specialty = specialty_set.unsigned_integer();
389                    let specialty_unsigned_to_fill = SpecialtyUnsignedToFill {
390                        content: UnsignedToFill::$variant(None),
391                        specialty,
392                    };
393                    if specialty_set.compact_at.is_some() {
394                        Ok(PrimitiveToFill::CompactUnsigned(specialty_unsigned_to_fill))
395                    }
396                    else {
397                        Ok(PrimitiveToFill::Unsigned(specialty_unsigned_to_fill))
398                    }
399                }
400            }
401        )*
402    }
403}
404
405impl_unsigned_fill_primitive!(u8, U8);
406impl_unsigned_fill_primitive!(u16, U16);
407impl_unsigned_fill_primitive!(u32, U32);
408impl_unsigned_fill_primitive!(u64, U64);
409impl_unsigned_fill_primitive!(u128, U128);
410
411pub trait FillSpecial {
412    fn special_to_fill(
413        specialty_set: &SpecialtySet,
414    ) -> Result<SpecialTypeToFill, RegistryInternalError>;
415}
416
417macro_rules! impl_fill_special {
418    ($($ty:tt), *) => {
419        $(
420            impl FillSpecial for $ty {
421                fn special_to_fill(specialty_set: &SpecialtySet) -> Result<SpecialTypeToFill, RegistryInternalError> {
422                    specialty_set.reject_compact()?;
423                    Ok(SpecialTypeToFill::$ty(None))
424                }
425            }
426        )*
427    }
428}
429
430impl_fill_special!(
431    AccountId32,
432    PublicEd25519,
433    PublicSr25519,
434    PublicEcdsa,
435    SignatureEd25519,
436    SignatureSr25519,
437    SignatureEcdsa
438);
439
440impl FillSpecial for EraToFill {
441    fn special_to_fill(
442        specialty_set: &SpecialtySet,
443    ) -> Result<SpecialTypeToFill, RegistryInternalError> {
444        specialty_set.reject_compact()?;
445        Ok(SpecialTypeToFill::Era(EraToFill::Immortal))
446    }
447}
448
449impl EraToFill {
450    pub fn selector(&mut self) {
451        match &self {
452            EraToFill::Immortal => {
453                *self = EraToFill::Mortal {
454                    period_entry: DEFAULT_PERIOD,
455                    block_number_entry: None,
456                }
457            }
458            EraToFill::Mortal { .. } => *self = EraToFill::Immortal,
459        }
460    }
461}
462
463impl FillSpecial for H256 {
464    fn special_to_fill(
465        specialty_set: &SpecialtySet,
466    ) -> Result<SpecialTypeToFill, RegistryInternalError> {
467        specialty_set.reject_compact()?;
468        let specialty = specialty_set.hint.hash256();
469        Ok(SpecialTypeToFill::H256 {
470            hash: None,
471            specialty,
472        })
473    }
474}
475
476macro_rules! impl_fill_special_with_compact {
477    ($($ty:tt), *) => {
478        $(
479            impl FillSpecial for $ty {
480                fn special_to_fill(specialty_set: &SpecialtySet) -> Result<SpecialTypeToFill, RegistryInternalError> {
481                    Ok(SpecialTypeToFill::$ty{value: None, is_compact: specialty_set.compact_at.is_some()})
482                }
483            }
484        )*
485    }
486}
487
488impl_fill_special_with_compact!(PerU16, Perbill, Percent, Permill, Perquintill);
489
490pub fn prepare_primitive(
491    found_ty: &TypeDefPrimitive,
492    specialty_set: &SpecialtySet,
493) -> Result<PrimitiveToFill, RegistryInternalError> {
494    match found_ty {
495        TypeDefPrimitive::Bool => bool::primitive_to_fill(specialty_set),
496        TypeDefPrimitive::Char => char::primitive_to_fill(specialty_set),
497        TypeDefPrimitive::Str => String::primitive_to_fill(specialty_set),
498        TypeDefPrimitive::I8 => i8::primitive_to_fill(specialty_set),
499        TypeDefPrimitive::I16 => i16::primitive_to_fill(specialty_set),
500        TypeDefPrimitive::I32 => i32::primitive_to_fill(specialty_set),
501        TypeDefPrimitive::I64 => i64::primitive_to_fill(specialty_set),
502        TypeDefPrimitive::I128 => i128::primitive_to_fill(specialty_set),
503        TypeDefPrimitive::I256 => BigInt::primitive_to_fill(specialty_set),
504        TypeDefPrimitive::U8 => u8::primitive_to_fill(specialty_set),
505        TypeDefPrimitive::U16 => u16::primitive_to_fill(specialty_set),
506        TypeDefPrimitive::U32 => u32::primitive_to_fill(specialty_set),
507        TypeDefPrimitive::U64 => u64::primitive_to_fill(specialty_set),
508        TypeDefPrimitive::U128 => u128::primitive_to_fill(specialty_set),
509        TypeDefPrimitive::U256 => BigUint::primitive_to_fill(specialty_set),
510    }
511}
512
513#[derive(Clone, Debug)]
514pub struct TransactionToFill {
515    pub author: TypeToFill,
516    pub call: TypeToFill,
517    pub extensions: Vec<TypeToFill>,
518    pub signature: TypeToFill,
519    pub extra: Vec<usize>,
520    pub genesis_hash: H256,
521}
522
523impl TransactionToFill {
524    pub fn init<E, M>(
525        ext_memory: &mut E,
526        metadata: &M,
527        genesis_hash: H256,
528    ) -> Result<Self, ErrorFixMe<E, M>>
529    where
530        E: ExternalMemory,
531        M: AsFillMetadata<E>,
532    {
533        let registry = metadata.types();
534        let extrinsic_type_params = metadata
535            .extrinsic_type_params()
536            .map_err(ErrorFixMe::MetaStructure)?;
537        let signed_extensions = metadata
538            .signed_extensions()
539            .map_err(ErrorFixMe::MetaStructure)?;
540
541        let author = prepare_type::<E, M>(
542            &Ty::Symbol(&extrinsic_type_params.address_ty),
543            ext_memory,
544            &registry,
545            Propagated::new(),
546        )?;
547
548        let call = prepare_type::<E, M>(
549            &Ty::Symbol(&extrinsic_type_params.call_ty),
550            ext_memory,
551            &registry,
552            Propagated::new(),
553        )?;
554
555        let signature = prepare_type::<E, M>(
556            &Ty::Symbol(&extrinsic_type_params.signature_ty),
557            ext_memory,
558            &registry,
559            Propagated::new(),
560        )?;
561
562        let mut extensions = Vec::new();
563        let mut extensions_ty_ids = Vec::new();
564
565        for signed_extensions_metadata in signed_extensions.iter() {
566            extensions_ty_ids.push(signed_extensions_metadata.ty.id);
567            extensions.push(prepare_type::<E, M>(
568                &Ty::Symbol(&signed_extensions_metadata.ty),
569                ext_memory,
570                &registry,
571                Propagated::from_ext_meta(signed_extensions_metadata),
572            )?)
573        }
574        for signed_extensions_metadata in signed_extensions.iter() {
575            extensions_ty_ids.push(signed_extensions_metadata.additional_signed.id);
576            extensions.push(prepare_type::<E, M>(
577                &Ty::Symbol(&signed_extensions_metadata.additional_signed),
578                ext_memory,
579                &registry,
580                Propagated::from_ext_meta(signed_extensions_metadata),
581            )?)
582        }
583
584        check_extensions(&extensions).map_err(ErrorFixMe::ExtensionsList)?;
585
586        let extra = extra_indices_in_extensions::<E, M>(
587            ext_memory,
588            &registry,
589            &extrinsic_type_params.extra_ty,
590            &extensions_ty_ids,
591        )?;
592
593        let mut out = TransactionToFill {
594            author,
595            call,
596            extensions,
597            signature,
598            extra,
599            genesis_hash,
600        };
601        out.populate_genesis_hash(genesis_hash);
602        out.populate_spec_version(&metadata.spec_version().map_err(ErrorFixMe::MetaStructure)?);
603        if let Some(tx_version) = &metadata.defined_tx_version() {
604            out.populate_tx_version(tx_version)
605        }
606        out.try_default_tip();
607        out.try_default_signature_to_sr25519(ext_memory, metadata)
608            .map_err(ErrorFixMe::Registry)?;
609        Ok(out)
610    }
611
612    pub fn populate_block_info(
613        &mut self,
614        optional_block_hash: Option<H256>,
615        optional_block_number: Option<u64>,
616    ) {
617        if era_is_immortal(&self.extensions) {
618            self.populate_block_hash_helper(self.genesis_hash)
619        } else if let Some(block_hash) = optional_block_hash {
620            if let Some(block_number) = optional_block_number {
621                self.populate_block_hash_helper(block_hash);
622                fill_mortal_block_number(&mut self.extensions, block_number)
623            }
624        }
625    }
626
627    pub fn try_default_tip(&mut self) {
628        for extension in self.extensions.iter_mut() {
629            try_default_tip(&mut extension.content);
630            if let TypeContentToFill::Composite(ref mut fields_to_fill) = extension.content {
631                for field in fields_to_fill.iter_mut() {
632                    try_default_tip(&mut field.type_to_fill.content);
633                }
634            }
635        }
636    }
637
638    pub fn try_default_tip_assets_in_given_asset<E: ExternalMemory, M: AsFillMetadata<E>>(
639        &mut self,
640        ext_memory: &mut E,
641        metadata: &M,
642        known_asset_id: u32,
643    ) {
644        let mut pallet_assets_id = None;
645        for pallet in metadata.pallets() {
646            if pallet.name() == "Assets" {
647                pallet_assets_id = Some(pallet.index());
648                break;
649            }
650        }
651
652        if let Some(pallet_assets_id) = pallet_assets_id {
653            let registry = metadata.types();
654
655            for extension in self.extensions.iter_mut() {
656                // extension is a primitive here, can only set tip to zero
657                try_default_tip(&mut extension.content);
658                if let TypeContentToFill::Composite(ref mut fields_to_fill) = extension.content {
659                    // extension is a composite and could contain a tip with primitive part and a descriptor for asset gas setup
660                    // ..or may not be a tip extension at all
661                    let mut has_tip_related_field = false;
662                    for field in fields_to_fill.iter() {
663                        match &field.type_to_fill.content {
664                            TypeContentToFill::Primitive(PrimitiveToFill::CompactUnsigned(
665                                specialty_unsigned_to_fill,
666                            )) => {
667                                has_tip_related_field = specialty_unsigned_to_fill.specialty
668                                    == SpecialtyUnsignedInteger::TipAsset;
669                            }
670                            TypeContentToFill::Primitive(PrimitiveToFill::Unsigned(
671                                specialty_unsigned_to_fill,
672                            )) => {
673                                has_tip_related_field = specialty_unsigned_to_fill.specialty
674                                    == SpecialtyUnsignedInteger::TipAsset;
675                            }
676                            _ => {}
677                        }
678                        if has_tip_related_field {
679                            break;
680                        }
681                    }
682                    // setup happens only for composites with a tip-related primitive field
683                    if has_tip_related_field {
684                        for field in fields_to_fill.iter_mut() {
685                            try_default_tip_assets_in_given_asset::<E, M>(
686                                &mut field.type_to_fill.content,
687                                ext_memory,
688                                &registry,
689                                known_asset_id,
690                                pallet_assets_id,
691                            );
692                        }
693                    }
694                }
695            }
696        }
697    }
698
699    /// There could be different types of signature available for the chain.
700    ///
701    /// In case there is a set of variants to select from, check if sr25519
702    /// variant is available and select it.
703    pub fn try_default_signature_to_sr25519<E, M>(
704        &mut self,
705        ext_memory: &mut E,
706        metadata: &M,
707    ) -> Result<(), RegistryError<E>>
708    where
709        E: ExternalMemory,
710        M: AsFillMetadata<E>,
711    {
712        if let TypeContentToFill::Variant(ref mut variant_selector) = self.signature.content {
713            let mut found_index = None;
714            let registry = metadata.types();
715            for (i, variant) in variant_selector.available_variants.iter().enumerate() {
716                if variant.fields.len() == 1 {
717                    if let SignatureIndicator::Sr25519 = SignatureIndicator::from_field::<E, M>(
718                        &variant.fields[0],
719                        ext_memory,
720                        &registry,
721                    ) {
722                        found_index = Some(i);
723                        break;
724                    } else {
725                        let ty = registry.resolve_ty(variant.fields[0].ty.id, ext_memory)?;
726                        if let SpecialtyTypeHinted::SignatureSr25519 =
727                            SpecialtyTypeHinted::from_type(&ty)
728                        {
729                            found_index = Some(i);
730                            break;
731                        }
732                    }
733                }
734            }
735            if let Some(new_selector_index) = found_index {
736                *variant_selector = VariantSelector::new_at::<E, M>(
737                    &variant_selector.available_variants,
738                    ext_memory,
739                    &registry,
740                    new_selector_index,
741                )?;
742            }
743        }
744        Ok(())
745    }
746
747    /// Either the type itself is sr25519 signature, the type is single field
748    /// struct with sr25519 signature, or the variant selector with sr25519
749    /// signature selected
750    pub fn signature_is_sr25519(&self) -> bool {
751        match self.signature.content {
752            TypeContentToFill::Composite(ref fields_to_fill) => {
753                if fields_to_fill.len() == 1 {
754                    matches!(
755                        fields_to_fill[0].type_to_fill.content,
756                        TypeContentToFill::SpecialType(SpecialTypeToFill::SignatureSr25519(_))
757                    )
758                } else {
759                    false
760                }
761            }
762            TypeContentToFill::SpecialType(SpecialTypeToFill::SignatureSr25519(_)) => true,
763            TypeContentToFill::Variant(ref variant_selector) => {
764                if variant_selector.selected.fields_to_fill.len() == 1 {
765                    matches!(
766                        variant_selector.selected.fields_to_fill[0]
767                            .type_to_fill
768                            .content,
769                        TypeContentToFill::SpecialType(SpecialTypeToFill::SignatureSr25519(_))
770                    )
771                } else {
772                    false
773                }
774            }
775            _ => false,
776        }
777    }
778
779    /// Either the type itself is sr25519 compatible (AccountId32 or sr25519
780    /// public key), the type is single field struct with one of those types,
781    /// or the variant selector with one of those types selected
782    pub fn author_as_sr25519_compatible(&self) -> Option<[u8; 32]> {
783        match &self.author.content {
784            TypeContentToFill::Composite(ref fields_to_fill) => {
785                if fields_to_fill.len() == 1 {
786                    match &fields_to_fill[0].type_to_fill.content {
787                        TypeContentToFill::SpecialType(SpecialTypeToFill::AccountId32(a)) => {
788                            (*a).map(|b| b.0)
789                        }
790                        TypeContentToFill::SpecialType(SpecialTypeToFill::PublicSr25519(a)) => {
791                            (*a).map(|b| b.0)
792                        }
793                        _ => None,
794                    }
795                } else {
796                    None
797                }
798            }
799            TypeContentToFill::SpecialType(SpecialTypeToFill::AccountId32(a)) => (*a).map(|b| b.0),
800            TypeContentToFill::SpecialType(SpecialTypeToFill::PublicSr25519(a)) => {
801                (*a).map(|b| b.0)
802            }
803            TypeContentToFill::Variant(ref variant_selector) => {
804                if variant_selector.selected.fields_to_fill.len() == 1 {
805                    match &variant_selector.selected.fields_to_fill[0]
806                        .type_to_fill
807                        .content
808                    {
809                        TypeContentToFill::SpecialType(SpecialTypeToFill::AccountId32(a)) => {
810                            (*a).map(|b| b.0)
811                        }
812                        TypeContentToFill::SpecialType(SpecialTypeToFill::PublicSr25519(a)) => {
813                            (*a).map(|b| b.0)
814                        }
815                        _ => None,
816                    }
817                } else {
818                    None
819                }
820            }
821            _ => None,
822        }
823    }
824
825    pub fn extrinsic_to_sign(&self) -> Option<ExtrinsicToSign> {
826        if let Some(call) = self.call.finalize() {
827            let mut extensions = Vec::new();
828            for ext in self.extensions.iter() {
829                if let Some(a) = ext.finalize() {
830                    extensions.push(a);
831                } else {
832                    return None;
833                }
834            }
835            Some(ExtrinsicToSign {
836                call: call.to_owned(),
837                extensions,
838            })
839        } else {
840            None
841        }
842    }
843
844    pub fn sign_this(&self) -> Option<Vec<u8>> {
845        if let Some(extrinsic_to_sign) = self.extrinsic_to_sign() {
846            let mut out = extrinsic_to_sign.call.encode();
847            for ext in extrinsic_to_sign.extensions.iter() {
848                out.extend_from_slice(&ext.encode())
849            }
850            Some(out)
851        } else {
852            None
853        }
854    }
855
856    pub fn into_signer_transaction_format(&self) -> Option<Vec<u8>> {
857        if let Some(extrinsic_to_sign) = self.extrinsic_to_sign() {
858            let mut out = extrinsic_to_sign.call.encode().encode(); // call prefixed by call length
859            for ext in extrinsic_to_sign.extensions.iter() {
860                out.extend_from_slice(&ext.encode())
861            }
862            Some(out)
863        } else {
864            None
865        }
866    }
867
868    pub fn output_qr_data_signer_style(&self) -> Option<Vec<u8>> {
869        if let Some(author) = self.author_as_sr25519_compatible() {
870            if let Some(signable) = self.into_signer_transaction_format() {
871                let mut out = vec![0x53, 0x01, 0x00];
872                out.extend_from_slice(&author);
873                out.extend_from_slice(&signable);
874                out.extend_from_slice(&self.genesis_hash.0);
875                Some(out)
876            } else {
877                None
878            }
879        } else {
880            None
881        }
882    }
883
884    pub fn signed_unchecked_extrinsic<E, M>(
885        &self,
886        metadata: &M,
887    ) -> Result<Option<SignedUncheckedExtrinsic>, ErrorFixMe<E, M>>
888    where
889        E: ExternalMemory,
890        M: AsFillMetadata<E>,
891    {
892        if let Some(author) = self.author.finalize() {
893            if let Some(signature) = self.signature.finalize() {
894                if let Some(call) = self.call.finalize() {
895                    let mut extra = Vec::new();
896                    for extra_index in self.extra.iter() {
897                        let addition = self.extensions[*extra_index]
898                            .finalize()
899                            .ok_or(ErrorFixMe::UnfinalizedExtension)?;
900                        extra.push(addition);
901                    }
902                    let extrinsic_version = metadata
903                        .extrinsic_version()
904                        .map_err(ErrorFixMe::MetaStructure)?;
905                    return Ok(Some(SignedUncheckedExtrinsic {
906                        version_byte: extrinsic_version | 0b1000_0000,
907                        author: author.to_owned(),
908                        signature: signature.to_owned(),
909                        extra,
910                        call: call.to_owned(),
911                    }));
912                }
913            }
914        }
915        Ok(None)
916    }
917
918    pub fn send_this_signed<E, M>(&self, metadata: &M) -> Result<Option<Vec<u8>>, ErrorFixMe<E, M>>
919    where
920        E: ExternalMemory,
921        M: AsFillMetadata<E>,
922    {
923        if let Some(signed_unchecked_extrinsic) = self.signed_unchecked_extrinsic(metadata)? {
924            let mut out = vec![signed_unchecked_extrinsic.version_byte];
925            out.extend_from_slice(&signed_unchecked_extrinsic.author.encode());
926            out.extend_from_slice(&signed_unchecked_extrinsic.signature.encode());
927            for extra_element in signed_unchecked_extrinsic.extra.iter() {
928                out.extend_from_slice(&extra_element.encode());
929            }
930            out.extend_from_slice(&signed_unchecked_extrinsic.call.encode());
931            Ok(Some(out.encode()))
932        } else {
933            Ok(None)
934        }
935    }
936
937    pub fn unsigned_unchecked_extrinsic<E, M>(
938        &self,
939        metadata: &M,
940    ) -> Result<Option<UnsignedUncheckedExtrinsic>, ErrorFixMe<E, M>>
941    where
942        E: ExternalMemory,
943        M: AsFillMetadata<E>,
944    {
945        if let Some(call) = self.call.finalize() {
946            let extrinsic_version = metadata
947                .extrinsic_version()
948                .map_err(ErrorFixMe::MetaStructure)?;
949            Ok(Some(UnsignedUncheckedExtrinsic {
950                version_byte: extrinsic_version,
951                call: call.to_owned(),
952            }))
953        } else {
954            Ok(None)
955        }
956    }
957
958    pub fn send_this_unsigned<E, M>(
959        &self,
960        metadata: &M,
961    ) -> Result<Option<Vec<u8>>, ErrorFixMe<E, M>>
962    where
963        E: ExternalMemory,
964        M: AsFillMetadata<E>,
965    {
966        if let Some(unsigned_unchecked_extrinsic) = self.unsigned_unchecked_extrinsic(metadata)? {
967            let mut out = vec![unsigned_unchecked_extrinsic.version_byte];
968            out.extend_from_slice(&unsigned_unchecked_extrinsic.call.encode());
969            Ok(Some(out.encode()))
970        } else {
971            Ok(None)
972        }
973    }
974}
975
976pub fn extra_indices_in_extensions<E: ExternalMemory, M: AsFillMetadata<E>>(
977    ext_memory: &mut E,
978    registry: &M::TypeRegistry,
979    extra_symbol: &UntrackedSymbol<TypeId>,
980    extensions_ty_ids: &[u32],
981) -> Result<Vec<usize>, ErrorFixMe<E, M>> {
982    let extra_ty = registry
983        .resolve_ty(extra_symbol.id, ext_memory)
984        .map_err(ErrorFixMe::Registry)?;
985    let extra_ty_ids: Vec<u32> = match &extra_ty.type_def {
986        TypeDef::Composite(composite) => composite.fields.iter().map(|field| field.ty.id).collect(),
987        TypeDef::Tuple(tuple) => tuple.fields.iter().map(|ty| ty.id).collect(),
988        _ => return Err(ErrorFixMe::WrongExtraStructure),
989    };
990    let mut out = Vec::new();
991    for extra_ty_id in extra_ty_ids.iter() {
992        let new = extensions_ty_ids
993            .iter()
994            .position(|extension_ty_id| extension_ty_id == extra_ty_id)
995            .ok_or(ErrorFixMe::ExtraNotInExtensions)?;
996        out.push(new);
997    }
998    Ok(out)
999}
1000
1001#[derive(Clone, Debug)]
1002pub struct ExtrinsicToSign {
1003    pub call: TypeContent,
1004    pub extensions: Vec<TypeContent>,
1005}
1006
1007#[derive(Clone, Debug)]
1008pub struct SignedUncheckedExtrinsic {
1009    pub version_byte: u8,
1010    pub author: TypeContent,
1011    pub signature: TypeContent,
1012    pub extra: Vec<TypeContent>,
1013    pub call: TypeContent,
1014}
1015
1016#[derive(Clone, Debug)]
1017pub struct UnsignedUncheckedExtrinsic {
1018    pub version_byte: u8,
1019    pub call: TypeContent,
1020}
1021
1022macro_rules! populate {
1023    ($($func:ident, $filler:ty, $helper_func:ident), *) => {
1024        $(
1025            impl TransactionToFill {
1026                pub fn $func(&mut self, filler: $filler) {
1027                    for extension in self.extensions.iter_mut() {
1028                        if $helper_func(&mut extension.content, filler) {
1029                            break;
1030                        } else if let TypeContentToFill::Composite(ref mut fields_to_fill) = extension.content {
1031                            if fields_to_fill.len() == 1
1032                                && $helper_func(
1033                                    &mut fields_to_fill[0].type_to_fill.content,
1034                                    filler,
1035                                )
1036                            {
1037                                break;
1038                            }
1039                        }
1040                    }
1041                }
1042            }
1043        )*
1044    }
1045}
1046
1047populate!(populate_genesis_hash, H256, genesis_hash_got_filled);
1048populate!(populate_block_hash_helper, H256, block_hash_got_filled);
1049populate!(populate_spec_version, &Unsigned, spec_version_got_filled);
1050populate!(populate_tx_version, &Unsigned, tx_version_got_filled);
1051populate!(populate_nonce, u32, nonce_got_filled);
1052
1053macro_rules! got_filled_unsigned {
1054    ($($func:ident, $unsigned:ident), *) => {
1055        $(
1056            fn $func(content: &mut TypeContentToFill, unsigned: &Unsigned) -> bool {
1057                match content {
1058                    TypeContentToFill::Primitive(PrimitiveToFill::CompactUnsigned(
1059                        ref mut specialty_unsigned_to_fill,
1060                    )) => {
1061                        if let SpecialtyUnsignedInteger::$unsigned = specialty_unsigned_to_fill.specialty {
1062                            specialty_unsigned_to_fill
1063                                .content
1064                                .upd_from_unsigned(unsigned);
1065                            true
1066                        } else {
1067                            false
1068                        }
1069                    }
1070                    TypeContentToFill::Primitive(PrimitiveToFill::Unsigned(
1071                        ref mut specialty_unsigned_to_fill,
1072                    )) => {
1073                        if let SpecialtyUnsignedInteger::$unsigned = specialty_unsigned_to_fill.specialty {
1074                            specialty_unsigned_to_fill
1075                                .content
1076                                .upd_from_unsigned(unsigned);
1077                            true
1078                        } else {
1079                            false
1080                        }
1081                    }
1082                    _ => false,
1083                }
1084            }
1085        )*
1086    }
1087}
1088
1089got_filled_unsigned!(spec_version_got_filled, SpecVersion);
1090got_filled_unsigned!(tx_version_got_filled, TxVersion);
1091
1092fn nonce_got_filled(content: &mut TypeContentToFill, rpc_u32: u32) -> bool {
1093    match content {
1094        TypeContentToFill::Primitive(PrimitiveToFill::CompactUnsigned(
1095            ref mut specialty_unsigned_to_fill,
1096        )) => {
1097            if let SpecialtyUnsignedInteger::Nonce = specialty_unsigned_to_fill.specialty {
1098                specialty_unsigned_to_fill.content.upd_from_u32(rpc_u32);
1099                true
1100            } else {
1101                false
1102            }
1103        }
1104        TypeContentToFill::Primitive(PrimitiveToFill::Unsigned(
1105            ref mut specialty_unsigned_to_fill,
1106        )) => {
1107            if let SpecialtyUnsignedInteger::Nonce = specialty_unsigned_to_fill.specialty {
1108                specialty_unsigned_to_fill.content.upd_from_u32(rpc_u32);
1109                true
1110            } else {
1111                false
1112            }
1113        }
1114        _ => false,
1115    }
1116}
1117
1118fn try_default_tip(content: &mut TypeContentToFill) {
1119    match content {
1120        TypeContentToFill::Primitive(PrimitiveToFill::CompactUnsigned(
1121            ref mut specialty_unsigned_to_fill,
1122        )) => {
1123            if specialty_unsigned_to_fill.specialty == SpecialtyUnsignedInteger::Tip
1124                || specialty_unsigned_to_fill.specialty == SpecialtyUnsignedInteger::TipAsset
1125            {
1126                specialty_unsigned_to_fill.content.upd_from_str("0");
1127            }
1128        }
1129        TypeContentToFill::Primitive(PrimitiveToFill::Unsigned(
1130            ref mut specialty_unsigned_to_fill,
1131        )) => {
1132            if specialty_unsigned_to_fill.specialty == SpecialtyUnsignedInteger::Tip
1133                || specialty_unsigned_to_fill.specialty == SpecialtyUnsignedInteger::TipAsset
1134            {
1135                specialty_unsigned_to_fill.content.upd_from_str("0");
1136            }
1137        }
1138        _ => {}
1139    }
1140}
1141
1142/// Goal is to set zero tip in desired assets so that commission could be paid
1143/// in assets as opposed to native gas.
1144///
1145/// See <https://wiki.polkadot.network/docs/learn/xcm/fundamentals/multilocation-summary>
1146/// for details on some of the fields meaning.
1147fn try_default_tip_assets_in_given_asset<E: ExternalMemory, M: AsFillMetadata<E>>(
1148    content: &mut TypeContentToFill,
1149    ext_memory: &mut E,
1150    registry: &M::TypeRegistry,
1151    asset_id: u32,
1152    pallet_assets_id: u8,
1153) {
1154    match content {
1155        TypeContentToFill::Primitive(PrimitiveToFill::CompactUnsigned(
1156            ref mut specialty_unsigned_to_fill,
1157        )) => {
1158            if specialty_unsigned_to_fill.specialty == SpecialtyUnsignedInteger::TipAsset {
1159                specialty_unsigned_to_fill.content.upd_from_str("0");
1160            }
1161        }
1162        TypeContentToFill::Primitive(PrimitiveToFill::Unsigned(
1163            ref mut specialty_unsigned_to_fill,
1164        )) => {
1165            if specialty_unsigned_to_fill.specialty == SpecialtyUnsignedInteger::TipAsset {
1166                specialty_unsigned_to_fill.content.upd_from_str("0");
1167            }
1168        }
1169        TypeContentToFill::Variant(ref mut variant_selector) => {
1170            let mut index_of_some = None;
1171
1172            for (index, variant) in variant_selector.available_variants.iter().enumerate() {
1173                if variant.name == "Some" {
1174                    index_of_some = Some(index);
1175                    break;
1176                }
1177            }
1178
1179            if let Some(index) = index_of_some {
1180                if let Ok(new_variant_selector) = VariantSelector::new_at::<E, M>(
1181                    &variant_selector.available_variants,
1182                    ext_memory,
1183                    registry,
1184                    index,
1185                ) {
1186                    *variant_selector = new_variant_selector;
1187                    if variant_selector.selected.fields_to_fill.len() == 1 {
1188                        if let TypeContentToFill::Composite(ref mut fields_to_fill) =
1189                            variant_selector.selected.fields_to_fill[0]
1190                                .type_to_fill
1191                                .content
1192                        {
1193                            for field_to_fill in fields_to_fill.iter_mut() {
1194                                if let Some(field_name) = &field_to_fill.field_name {
1195                                    match field_name.as_str() {
1196                                        "parents" => {
1197                                            if let TypeContentToFill::Primitive(
1198                                                PrimitiveToFill::Unsigned(
1199                                                    ref mut specialty_unsigned_to_fill,
1200                                                ),
1201                                            ) = field_to_fill.type_to_fill.content
1202                                            {
1203                                                specialty_unsigned_to_fill.content.upd_from_u8(0);
1204                                            }
1205                                        }
1206                                        "interior" => {
1207                                            if let TypeContentToFill::Variant(
1208                                                ref mut variant_selector_interior,
1209                                            ) = field_to_fill.type_to_fill.content
1210                                            {
1211                                                default_x2_junctions_assets_tip::<E, M>(
1212                                                    variant_selector_interior,
1213                                                    ext_memory,
1214                                                    registry,
1215                                                    asset_id,
1216                                                    pallet_assets_id,
1217                                                )
1218                                            }
1219                                        }
1220                                        _ => {}
1221                                    }
1222                                }
1223                            }
1224                        }
1225                    }
1226                }
1227            }
1228        }
1229        _ => {}
1230    }
1231}
1232
1233fn autofill_x2_selector_pallet_instance<E: ExternalMemory, M: AsFillMetadata<E>>(
1234    selector0: &mut TypeContentToFill,
1235    ext_memory: &mut E,
1236    registry: &M::TypeRegistry,
1237    pallet_assets_id: u8,
1238) {
1239    if let TypeContentToFill::Variant(ref mut junction_variant_selector_0) = selector0 {
1240        let mut index_pallet_instance = None;
1241        for (index, variant) in junction_variant_selector_0
1242            .available_variants
1243            .iter()
1244            .enumerate()
1245        {
1246            if variant.name == "PalletInstance" {
1247                index_pallet_instance = Some(index);
1248                break;
1249            }
1250        }
1251        if let Some(index_pallet_instance) = index_pallet_instance {
1252            if let Ok(new_junction_variant_selector_0) = VariantSelector::new_at::<E, M>(
1253                &junction_variant_selector_0.available_variants,
1254                ext_memory,
1255                registry,
1256                index_pallet_instance,
1257            ) {
1258                *junction_variant_selector_0 = new_junction_variant_selector_0;
1259                if junction_variant_selector_0.selected.fields_to_fill.len() == 1 {
1260                    if let TypeContentToFill::Primitive(PrimitiveToFill::Unsigned(
1261                        ref mut specialty_unsigned_to_fill,
1262                    )) = junction_variant_selector_0.selected.fields_to_fill[0]
1263                        .type_to_fill
1264                        .content
1265                    {
1266                        specialty_unsigned_to_fill
1267                            .content
1268                            .upd_from_u8(pallet_assets_id)
1269                    }
1270                }
1271            }
1272        }
1273    }
1274}
1275
1276fn autofill_x2_selector_general_index<E: ExternalMemory, M: AsFillMetadata<E>>(
1277    selector1: &mut TypeContentToFill,
1278    ext_memory: &mut E,
1279    registry: &M::TypeRegistry,
1280    asset_id: u32,
1281) {
1282    if let TypeContentToFill::Variant(ref mut junction_variant_selector_1) = selector1 {
1283        let mut index_general_index = None;
1284        for (index, variant) in junction_variant_selector_1
1285            .available_variants
1286            .iter()
1287            .enumerate()
1288        {
1289            if variant.name == "GeneralIndex" {
1290                index_general_index = Some(index);
1291                break;
1292            }
1293        }
1294        if let Some(index_general_index) = index_general_index {
1295            if let Ok(new_junction_variant_selector_1) = VariantSelector::new_at::<E, M>(
1296                &junction_variant_selector_1.available_variants,
1297                ext_memory,
1298                registry,
1299                index_general_index,
1300            ) {
1301                *junction_variant_selector_1 = new_junction_variant_selector_1;
1302                if junction_variant_selector_1.selected.fields_to_fill.len() == 1 {
1303                    match junction_variant_selector_1.selected.fields_to_fill[0]
1304                        .type_to_fill
1305                        .content
1306                    {
1307                        TypeContentToFill::Primitive(PrimitiveToFill::Unsigned(
1308                            ref mut specialty_unsigned_to_fill,
1309                        )) => specialty_unsigned_to_fill.content.upd_from_u32(asset_id),
1310                        TypeContentToFill::Primitive(PrimitiveToFill::CompactUnsigned(
1311                            ref mut specialty_unsigned_to_fill,
1312                        )) => specialty_unsigned_to_fill.content.upd_from_u32(asset_id),
1313                        _ => {}
1314                    }
1315                }
1316            }
1317        }
1318    }
1319}
1320
1321fn default_x2_junctions_assets_tip<E: ExternalMemory, M: AsFillMetadata<E>>(
1322    variant_selector_interior: &mut VariantSelector,
1323    ext_memory: &mut E,
1324    registry: &M::TypeRegistry,
1325    asset_id: u32,
1326    pallet_assets_id: u8,
1327) {
1328    // search for index of `X2` variant here; `X2` means 2 junctions in asset address
1329    let mut index_of_x2 = None;
1330
1331    for (index, variant) in variant_selector_interior
1332        .available_variants
1333        .iter()
1334        .enumerate()
1335    {
1336        if variant.name == "X2" {
1337            index_of_x2 = Some(index);
1338            break;
1339        }
1340    }
1341
1342    if let Some(index_x2) = index_of_x2 {
1343        if let Ok(new_variant_selector_interior) = VariantSelector::new_at::<E, M>(
1344            &variant_selector_interior.available_variants,
1345            ext_memory,
1346            registry,
1347            index_x2,
1348        ) {
1349            *variant_selector_interior = new_variant_selector_interior;
1350            match variant_selector_interior.selected.fields_to_fill.len() {
1351                1 => {
1352                    // must be an array of variants, of length 2
1353                    if let TypeContentToFill::ArrayRegular(ref mut array) =
1354                        variant_selector_interior.selected.fields_to_fill[0]
1355                            .type_to_fill
1356                            .content
1357                    {
1358                        // check that length is indeed 2
1359                        if array.len == 2 {
1360                            autofill_x2_selector_pallet_instance::<E, M>(
1361                                &mut array.content[0],
1362                                ext_memory,
1363                                registry,
1364                                pallet_assets_id,
1365                            );
1366                            autofill_x2_selector_general_index::<E, M>(
1367                                &mut array.content[1],
1368                                ext_memory,
1369                                registry,
1370                                asset_id,
1371                            );
1372                        }
1373                    }
1374                }
1375                2 => {
1376                    // must be two variants fields
1377                    autofill_x2_selector_pallet_instance::<E, M>(
1378                        &mut variant_selector_interior.selected.fields_to_fill[0]
1379                            .type_to_fill
1380                            .content,
1381                        ext_memory,
1382                        registry,
1383                        pallet_assets_id,
1384                    );
1385                    autofill_x2_selector_general_index::<E, M>(
1386                        &mut variant_selector_interior.selected.fields_to_fill[1]
1387                            .type_to_fill
1388                            .content,
1389                        ext_memory,
1390                        registry,
1391                        asset_id,
1392                    );
1393                }
1394                _ => {}
1395            }
1396        }
1397    }
1398}
1399
1400fn era_is_immortal(extensions: &[TypeToFill]) -> bool {
1401    let mut era_is_immortal = true;
1402    for extension in extensions.iter() {
1403        if let TypeContentToFill::SpecialType(SpecialTypeToFill::Era(era_to_fill)) =
1404            &extension.content
1405        {
1406            if let EraToFill::Mortal { .. } = era_to_fill {
1407                era_is_immortal = false;
1408            }
1409            break;
1410        }
1411        if let TypeContentToFill::Composite(fields_to_fill) = &extension.content {
1412            if fields_to_fill.len() == 1 {
1413                if let TypeContentToFill::SpecialType(SpecialTypeToFill::Era(era_to_fill)) =
1414                    &fields_to_fill[0].type_to_fill.content
1415                {
1416                    if let EraToFill::Mortal { .. } = era_to_fill {
1417                        era_is_immortal = false;
1418                    }
1419                    break;
1420                }
1421            }
1422        }
1423    }
1424    era_is_immortal
1425}
1426
1427fn fill_mortal_block_number(extensions: &mut [TypeToFill], block_number: u64) {
1428    for extension in extensions.iter_mut() {
1429        if let TypeContentToFill::SpecialType(SpecialTypeToFill::Era(ref mut era_to_fill)) =
1430            extension.content
1431        {
1432            if let EraToFill::Mortal {
1433                period_entry: _,
1434                ref mut block_number_entry,
1435            } = era_to_fill
1436            {
1437                *block_number_entry = Some(block_number);
1438            }
1439            break;
1440        }
1441        if let TypeContentToFill::Composite(ref mut fields_to_fill) = extension.content {
1442            if fields_to_fill.len() == 1 {
1443                if let TypeContentToFill::SpecialType(SpecialTypeToFill::Era(ref mut era_to_fill)) =
1444                    fields_to_fill[0].type_to_fill.content
1445                {
1446                    if let EraToFill::Mortal {
1447                        period_entry: _,
1448                        ref mut block_number_entry,
1449                    } = era_to_fill
1450                    {
1451                        *block_number_entry = Some(block_number);
1452                    }
1453                    break;
1454                }
1455            }
1456        }
1457    }
1458}
1459
1460macro_rules! got_filled_hash {
1461    ($($func:ident, $hash:ident), *) => {
1462        $(
1463            fn $func(content: &mut TypeContentToFill, hash: H256) -> bool {
1464                if let TypeContentToFill::SpecialType(SpecialTypeToFill::H256{hash: ref mut hash_to_fill, specialty: SpecialtyH256::$hash}) =
1465                        content
1466                    {
1467                        *hash_to_fill = Some(hash);
1468                        true
1469                    }
1470                else {false}
1471            }
1472        )*
1473    }
1474}
1475
1476got_filled_hash!(genesis_hash_got_filled, GenesisHash);
1477got_filled_hash!(block_hash_got_filled, BlockHash);
1478
1479struct CheckExtensions {
1480    found_block_hash: bool,
1481    found_era: bool,
1482    found_genesis_hash: bool,
1483    found_spec_version: bool,
1484}
1485
1486impl CheckExtensions {
1487    fn init() -> Self {
1488        Self {
1489            found_block_hash: false,
1490            found_era: false,
1491            found_genesis_hash: false,
1492            found_spec_version: false,
1493        }
1494    }
1495    fn check_iteration(&mut self, content: &TypeContentToFill) -> Result<(), ExtensionsError> {
1496        match content {
1497            TypeContentToFill::SpecialType(SpecialTypeToFill::Era(_)) => {
1498                if self.found_era {
1499                    return Err(ExtensionsError::EraTwice);
1500                } else {
1501                    self.found_era = true;
1502                }
1503            }
1504            TypeContentToFill::SpecialType(SpecialTypeToFill::H256 { hash: _, specialty }) => {
1505                match specialty {
1506                    SpecialtyH256::BlockHash => {
1507                        if self.found_block_hash {
1508                            return Err(ExtensionsError::GenesisHashTwice);
1509                        } else {
1510                            self.found_block_hash = true;
1511                        }
1512                    }
1513                    SpecialtyH256::GenesisHash => {
1514                        if self.found_genesis_hash {
1515                            return Err(ExtensionsError::GenesisHashTwice);
1516                        } else {
1517                            self.found_genesis_hash = true;
1518                        }
1519                    }
1520                    SpecialtyH256::None => {}
1521                }
1522            }
1523            TypeContentToFill::Primitive(PrimitiveToFill::CompactUnsigned(
1524                specialty_unsigned_to_fill,
1525            )) => {
1526                if let SpecialtyUnsignedInteger::SpecVersion = specialty_unsigned_to_fill.specialty
1527                {
1528                    if self.found_spec_version {
1529                        return Err(ExtensionsError::SpecVersionTwice);
1530                    } else {
1531                        self.found_spec_version = true;
1532                    }
1533                }
1534            }
1535            TypeContentToFill::Primitive(PrimitiveToFill::Unsigned(specialty_unsigned_to_fill)) => {
1536                if let SpecialtyUnsignedInteger::SpecVersion = specialty_unsigned_to_fill.specialty
1537                {
1538                    if self.found_spec_version {
1539                        return Err(ExtensionsError::SpecVersionTwice);
1540                    } else {
1541                        self.found_spec_version = true;
1542                    }
1543                }
1544            }
1545            _ => {}
1546        }
1547        Ok(())
1548    }
1549}
1550
1551fn check_extensions(extensions: &[TypeToFill]) -> Result<(), ExtensionsError> {
1552    let mut check_extensions = CheckExtensions::init();
1553    for ext in extensions.iter() {
1554        check_extensions.check_iteration(&ext.content)?;
1555        if let TypeContentToFill::Composite(fields_to_fill) = &ext.content {
1556            if fields_to_fill.len() == 1 {
1557                check_extensions.check_iteration(&fields_to_fill[0].type_to_fill.content)?;
1558            }
1559        }
1560    }
1561    if !check_extensions.found_genesis_hash {
1562        return Err(ExtensionsError::NoGenesisHash);
1563    }
1564    if !check_extensions.found_spec_version {
1565        return Err(ExtensionsError::NoSpecVersion);
1566    }
1567    Ok(())
1568}
1569
1570pub fn prepare_type<E, M>(
1571    ty_input: &Ty,
1572    ext_memory: &mut E,
1573    registry: &M::TypeRegistry,
1574    mut propagated: Propagated,
1575) -> Result<TypeToFill, RegistryError<E>>
1576where
1577    E: ExternalMemory,
1578    M: AsFillMetadata<E>,
1579{
1580    let (ty, id) = match ty_input {
1581        Ty::Resolved(resolved_ty) => (resolved_ty.ty.to_owned(), resolved_ty.id),
1582        Ty::Symbol(ty_symbol) => (registry.resolve_ty(ty_symbol.id, ext_memory)?, ty_symbol.id),
1583    };
1584    let info_ty = Info::from_ty(&ty);
1585    propagated.add_info(&info_ty);
1586
1587    match SpecialtyTypeHinted::from_type(&ty) {
1588        SpecialtyTypeHinted::AccountId32 => Ok(TypeToFill {
1589            content: TypeContentToFill::SpecialType(AccountId32::special_to_fill(
1590                &propagated.checker.specialty_set,
1591            )?),
1592            info: propagated.info,
1593        }),
1594        SpecialtyTypeHinted::Era => Ok(TypeToFill {
1595            content: TypeContentToFill::SpecialType(EraToFill::special_to_fill(
1596                &propagated.checker.specialty_set,
1597            )?),
1598            info: propagated.info,
1599        }),
1600        SpecialtyTypeHinted::H256 => Ok(TypeToFill {
1601            content: TypeContentToFill::SpecialType(H256::special_to_fill(
1602                &propagated.checker.specialty_set,
1603            )?),
1604            info: propagated.info,
1605        }),
1606        SpecialtyTypeHinted::PerU16 => Ok(TypeToFill {
1607            content: TypeContentToFill::SpecialType(PerU16::special_to_fill(
1608                &propagated.checker.specialty_set,
1609            )?),
1610            info: propagated.info,
1611        }),
1612        SpecialtyTypeHinted::Perbill => Ok(TypeToFill {
1613            content: TypeContentToFill::SpecialType(Perbill::special_to_fill(
1614                &propagated.checker.specialty_set,
1615            )?),
1616            info: propagated.info,
1617        }),
1618        SpecialtyTypeHinted::Percent => Ok(TypeToFill {
1619            content: TypeContentToFill::SpecialType(Percent::special_to_fill(
1620                &propagated.checker.specialty_set,
1621            )?),
1622            info: propagated.info,
1623        }),
1624        SpecialtyTypeHinted::Permill => Ok(TypeToFill {
1625            content: TypeContentToFill::SpecialType(Permill::special_to_fill(
1626                &propagated.checker.specialty_set,
1627            )?),
1628            info: propagated.info,
1629        }),
1630        SpecialtyTypeHinted::Perquintill => Ok(TypeToFill {
1631            content: TypeContentToFill::SpecialType(Perquintill::special_to_fill(
1632                &propagated.checker.specialty_set,
1633            )?),
1634            info: propagated.info,
1635        }),
1636        SpecialtyTypeHinted::PublicEd25519 => Ok(TypeToFill {
1637            content: TypeContentToFill::SpecialType(PublicEd25519::special_to_fill(
1638                &propagated.checker.specialty_set,
1639            )?),
1640            info: propagated.info,
1641        }),
1642        SpecialtyTypeHinted::PublicSr25519 => Ok(TypeToFill {
1643            content: TypeContentToFill::SpecialType(PublicSr25519::special_to_fill(
1644                &propagated.checker.specialty_set,
1645            )?),
1646            info: propagated.info,
1647        }),
1648        SpecialtyTypeHinted::PublicEcdsa => Ok(TypeToFill {
1649            content: TypeContentToFill::SpecialType(PublicEcdsa::special_to_fill(
1650                &propagated.checker.specialty_set,
1651            )?),
1652            info: propagated.info,
1653        }),
1654        SpecialtyTypeHinted::SignatureEd25519 => Ok(TypeToFill {
1655            content: TypeContentToFill::SpecialType(SignatureEd25519::special_to_fill(
1656                &propagated.checker.specialty_set,
1657            )?),
1658            info: propagated.info,
1659        }),
1660        SpecialtyTypeHinted::SignatureSr25519 => Ok(TypeToFill {
1661            content: TypeContentToFill::SpecialType(SignatureSr25519::special_to_fill(
1662                &propagated.checker.specialty_set,
1663            )?),
1664            info: propagated.info,
1665        }),
1666        SpecialtyTypeHinted::SignatureEcdsa => Ok(TypeToFill {
1667            content: TypeContentToFill::SpecialType(SignatureEcdsa::special_to_fill(
1668                &propagated.checker.specialty_set,
1669            )?),
1670            info: propagated.info,
1671        }),
1672        _ => match &ty.type_def {
1673            TypeDef::Composite(x) => Ok(TypeToFill {
1674                content: TypeContentToFill::Composite(prepare_fields::<E, M>(
1675                    &x.fields,
1676                    ext_memory,
1677                    registry,
1678                    propagated.checker,
1679                )?),
1680                info: propagated.info,
1681            }),
1682            TypeDef::Variant(x) => {
1683                if x.variants.is_empty() {
1684                    Ok(TypeToFill {
1685                        content: TypeContentToFill::VariantEmpty,
1686                        info: propagated.info,
1687                    })
1688                } else {
1689                    Ok(TypeToFill {
1690                        content: TypeContentToFill::Variant(VariantSelector::init::<E, M>(
1691                            &x.variants,
1692                            ext_memory,
1693                            registry,
1694                        )?),
1695                        info: propagated.info,
1696                    })
1697                }
1698            }
1699            TypeDef::Sequence(x) => {
1700                let mut info = Vec::new();
1701                info.append(&mut propagated.info);
1702                let sequence_draft =
1703                    prepare_elements_set::<E, M>(&x.type_param, ext_memory, registry, propagated)?;
1704                match sequence_draft {
1705                    SequenceDraft::U8(sequence_draft_content) => Ok(TypeToFill {
1706                        content: TypeContentToFill::SequenceU8(SequenceU8ToFill {
1707                            content: Vec::new(),
1708                            info_element: sequence_draft_content.info_element,
1709                        }),
1710                        info,
1711                    }),
1712                    SequenceDraft::Regular(sequence_draft_content) => Ok(TypeToFill {
1713                        content: TypeContentToFill::SequenceRegular(SequenceRegularToFill {
1714                            content: Vec::new(),
1715                            info_element: sequence_draft_content.info_element,
1716                            ty: sequence_draft_content.resolved_ty.ty,
1717                            id: sequence_draft_content.resolved_ty.id,
1718                        }),
1719                        info,
1720                    }),
1721                }
1722            }
1723            TypeDef::Array(x) => {
1724                let mut info = Vec::new();
1725                info.append(&mut propagated.info);
1726                let sequence_draft =
1727                    prepare_elements_set::<E, M>(&x.type_param, ext_memory, registry, propagated)?;
1728                match sequence_draft {
1729                    SequenceDraft::U8(sequence_draft_content) => Ok(TypeToFill {
1730                        content: TypeContentToFill::ArrayU8(ArrayU8ToFill {
1731                            content: Vec::new(),
1732                            info_element: sequence_draft_content.info_element,
1733                            len: x.len,
1734                        }),
1735                        info,
1736                    }),
1737                    SequenceDraft::Regular(sequence_draft_content) => {
1738                        let array_element = prepare_type::<E, M>(
1739                            &Ty::Resolved(sequence_draft_content.resolved_ty),
1740                            ext_memory,
1741                            registry,
1742                            Propagated::new(),
1743                        )?;
1744                        Ok(TypeToFill {
1745                            content: TypeContentToFill::ArrayRegular(ArrayRegularToFill {
1746                                content: vec![array_element.content; x.len as usize],
1747                                info_element: sequence_draft_content.info_element,
1748                                len: x.len,
1749                            }),
1750                            info,
1751                        })
1752                    }
1753                }
1754            }
1755            TypeDef::Tuple(x) => {
1756                if x.fields.len() > 1 {
1757                    propagated.reject_compact()?;
1758                    propagated.forget_hint();
1759                }
1760                let mut tuple_set = Vec::new();
1761                for inner_ty_symbol in x.fields.iter() {
1762                    let id = inner_ty_symbol.id;
1763                    let ty = registry.resolve_ty(id, ext_memory)?;
1764                    let tuple_element = prepare_type::<E, M>(
1765                        &Ty::Resolved(ResolvedTy {
1766                            ty: ty.to_owned(),
1767                            id,
1768                        }),
1769                        ext_memory,
1770                        registry,
1771                        Propagated::for_ty(&propagated.checker, &ty, id)?,
1772                    )?;
1773                    tuple_set.push(tuple_element);
1774                }
1775                Ok(TypeToFill {
1776                    content: TypeContentToFill::Tuple(tuple_set),
1777                    info: propagated.info,
1778                })
1779            }
1780            TypeDef::Primitive(x) => Ok(TypeToFill {
1781                content: TypeContentToFill::Primitive(prepare_primitive(
1782                    x,
1783                    &propagated.checker.specialty_set,
1784                )?),
1785                info: propagated.info,
1786            }),
1787            TypeDef::Compact(x) => {
1788                propagated.reject_compact()?;
1789                propagated.checker.specialty_set.compact_at = Some(id);
1790                propagated.checker.check_id(x.type_param.id)?;
1791                prepare_type::<E, M>(&Ty::Symbol(&x.type_param), ext_memory, registry, propagated)
1792            }
1793            TypeDef::BitSequence(x) => {
1794                propagated.reject_compact()?;
1795                let bit_sequence = prepare_bit_sequence::<E, M>(x, id, ext_memory, registry)?;
1796                Ok(TypeToFill {
1797                    content: TypeContentToFill::BitSequence(bit_sequence),
1798                    info: propagated.info,
1799                })
1800            }
1801        },
1802    }
1803}
1804
1805pub fn prepare_fields<E, M>(
1806    fields: &[Field<PortableForm>],
1807    ext_memory: &mut E,
1808    registry: &M::TypeRegistry,
1809    mut checker: Checker,
1810) -> Result<Vec<FieldToFill>, RegistryError<E>>
1811where
1812    E: ExternalMemory,
1813    M: AsFillMetadata<E>,
1814{
1815    if fields.len() > 1 {
1816        // Only single-field structs can be processed as a compact.
1817        // Note: compact flag was already checked in enum processing at this
1818        // point.
1819        checker.reject_compact()?;
1820
1821        // `Hint` remains relevant only if single-field struct is processed.
1822        // Note: checker gets renewed when fields of enum are processed.
1823        checker.forget_hint();
1824    }
1825    let mut out: Vec<FieldToFill> = Vec::new();
1826    for field in fields.iter() {
1827        let field_name = field.name.to_owned();
1828        let type_name = field.type_name.to_owned();
1829        let type_to_fill = prepare_type::<E, M>(
1830            &Ty::Symbol(&field.ty),
1831            ext_memory,
1832            registry,
1833            Propagated::for_field(&checker, field)?,
1834        )?;
1835        out.push(FieldToFill {
1836            type_to_fill,
1837            field_docs: field.collect_docs(),
1838            field_name,
1839            type_name,
1840        })
1841    }
1842    Ok(out)
1843}
1844
1845pub fn prepare_elements_set<E, M>(
1846    element: &UntrackedSymbol<TypeId>,
1847    ext_memory: &mut E,
1848    registry: &M::TypeRegistry,
1849    propagated: Propagated,
1850) -> Result<SequenceDraft, RegistryError<E>>
1851where
1852    E: ExternalMemory,
1853    M: AsFillMetadata<E>,
1854{
1855    propagated.reject_compact()?;
1856
1857    let husked = husk_type::<E, M>(element, registry, ext_memory, propagated.checker)?;
1858    let resolved_ty = ResolvedTy {
1859        ty: husked.ty.to_owned(),
1860        id: husked.id,
1861    };
1862    let sequence_draft_content = SequenceDraftContent {
1863        info_element: husked.info.to_owned(),
1864        resolved_ty,
1865        checker: husked.checker,
1866    };
1867    if husked.ty.type_def == TypeDef::Primitive(TypeDefPrimitive::U8) {
1868        Ok(SequenceDraft::U8(sequence_draft_content))
1869    } else {
1870        Ok(SequenceDraft::Regular(sequence_draft_content))
1871    }
1872}
1873
1874pub fn prepare_bit_sequence<E, M>(
1875    bit_ty: &TypeDefBitSequence<PortableForm>,
1876    id: u32,
1877    ext_memory: &mut E,
1878    registry: &M::TypeRegistry,
1879) -> Result<BitSequenceContent, RegistryError<E>>
1880where
1881    E: ExternalMemory,
1882    M: AsFillMetadata<E>,
1883{
1884    // BitOrder
1885    let bitorder = find_bit_order_ty::<E, M>(bit_ty, id, ext_memory, registry)?;
1886
1887    // BitStore
1888    let bitstore_type = registry.resolve_ty(bit_ty.bit_store_type.id, ext_memory)?;
1889
1890    match bitstore_type.type_def {
1891        TypeDef::Primitive(TypeDefPrimitive::U8) => match bitorder {
1892            FoundBitOrder::Lsb0 => Ok(BitSequenceContent::BitVecU8Lsb0(BitVec::new())),
1893            FoundBitOrder::Msb0 => Ok(BitSequenceContent::BitVecU8Msb0(BitVec::new())),
1894        },
1895        TypeDef::Primitive(TypeDefPrimitive::U16) => match bitorder {
1896            FoundBitOrder::Lsb0 => Ok(BitSequenceContent::BitVecU16Lsb0(BitVec::new())),
1897            FoundBitOrder::Msb0 => Ok(BitSequenceContent::BitVecU16Msb0(BitVec::new())),
1898        },
1899        TypeDef::Primitive(TypeDefPrimitive::U32) => match bitorder {
1900            FoundBitOrder::Lsb0 => Ok(BitSequenceContent::BitVecU32Lsb0(BitVec::new())),
1901            FoundBitOrder::Msb0 => Ok(BitSequenceContent::BitVecU32Msb0(BitVec::new())),
1902        },
1903        #[cfg(target_pointer_width = "64")]
1904        TypeDef::Primitive(TypeDefPrimitive::U64) => match bitorder {
1905            FoundBitOrder::Lsb0 => Ok(BitSequenceContent::BitVecU64Lsb0(BitVec::new())),
1906            FoundBitOrder::Msb0 => Ok(BitSequenceContent::BitVecU64Msb0(BitVec::new())),
1907        },
1908        _ => Err(RegistryError::Internal(
1909            RegistryInternalError::NotBitStoreType { id },
1910        )),
1911    }
1912}