Skip to content
Snippets Groups Projects
Select Git revision
  • fe571d884ebaab8b12a1bf299de45c7efc633c98
  • master default protected
  • 311_gtest_fixes
  • set_UniversalDividendApi_in_RuntimeApiCollection
  • tuxmain/fix-change-owner-key
  • network/gtest-1000 protected
  • upgradable-multisig
  • runtime/gtest-1000
  • network/gdev-800 protected
  • cgeek/issue-297-cpu
  • gdev-800-tests
  • update-docker-compose-rpc-squid-names
  • fix-252
  • 1000i100-test
  • hugo/tmp-0.9.1
  • network/gdev-803 protected
  • hugo/endpoint-gossip
  • network/gdev-802 protected
  • hugo/distance-precompute
  • network/gdev-900 protected
  • tuxmain/anonymous-tx
  • gtest-1000-0.11.1 protected
  • gtest-1000-0.11.0 protected
  • gtest-1000 protected
  • gdev-900-0.10.1 protected
  • gdev-900-0.10.0 protected
  • gdev-900-0.9.2 protected
  • gdev-800-0.8.0 protected
  • gdev-900-0.9.1 protected
  • gdev-900-0.9.0 protected
  • gdev-803 protected
  • gdev-802 protected
  • runtime-801 protected
  • gdev-800 protected
  • runtime-800-bis protected
  • runtime-800 protected
  • runtime-800-backup protected
  • runtime-701 protected
  • runtime-700 protected
  • runtime-600 protected
  • runtime-500 protected
41 results

gen_calls_doc.rs

Blame
    • Benjamin Gallois's avatar
      31a25023
      Upgrade to Polkadot v0.9.42 (!172) · 31a25023
      Benjamin Gallois authored and Hugo Trentesaux's avatar Hugo Trentesaux committed
      * allow clippy needless_pass_by_ref_mut
      
      * fix clippy
      
      °_°
      
      * fix provider behavior
      
      * fix build errors
      
      * change behavior of going below ED
      
      * fix provider initialization
      
      * add mock epoch change
      
      * add session number test
      
      * add session number test
      
      * WIP fix tests
      
      * fix time-based ud test
      
      * update metadata
      
      * FIX apply all fix from flash branch
      
      * partial fix clippy
      
      other suggestions are not legit
      
      * fix metadata and end2end test
      
      * fix build tests
      
      * fix build and clippy
      
      * remove benchmark of upgrade_accounts
      
      this happens in substrate dependency
      I also updated other packages because why not :D
      and I removed a useless implementation in mock
      but the test do not compile with feature runtime benchmarks anyway
      
      * test_total_issuance_vs_monetary_mass
      
      * proofreading comment
      
      * fix total issuance differently
      
      this actually fixes total issuance at genesis
      instead of creating duplicate account data
      
      * fix test scenario
      
      the thing tested here was not the ability to call the function,
      but the impossibility of deleting the account
      
      * add comment to explain test
      
      * fix providers and sufficients counts
      
      * fix initial balance
      
      * fix initial TotalIssuance
      
      * fix clippy warnings and optimization
      
      * fix xtask
      
      * update docs
      
      * add DustHandle
      
      * fix pallets config
      
      * fix tests
      
      * fix pallet_balance genesis config
      
      * wip: fix end2end-test
      
      * fix manual and instant sealing
      
      * fix live-tests
      
      * fix offences after rebase
      
      * generate all weights
      
      * add rust toolchain file
      
      * fix benchmarks
      
      Pallet balances benchmarks need https://github.com/duniter/substrate/commit/c36ab4f32454318a47777b24b6533c44121fc10b because pallet duniter-account add another provider.
      
      * fix babe-worker
      
      * fix subxt dependency
      
      * fix ImplicitCallIndex and Weight::from_ref_time deprecation
      
      * fix consensus_babe dependency
      
      * regenerate weights
      
      Regenerate all weights except for pallet-balance failing on one extrinsic
      
      * workaround pallet_duniter_account
      
      Workaround to be able to pass https://github.com/paritytech/substrate/blob/6ef184e33f6ce0f56999ae84b212ea6148c0624d/frame/balances/src/benchmarking.rs#L271 in the benchmark.
      ExtraFlags is private and Default is always new_logic not suitable for the benchmark.
      
      * wip fix node errors
      
      * wip fix runtime errors
      
      * fix pallet-duniter-account errors
      
      * fix pallet-balance errors
      
      * fix pallet-identity errors
      
      * fix pallet-duniter-account errors
      
      * upgrade Cargo files
      
      * update docs
      31a25023
      History
      Upgrade to Polkadot v0.9.42 (!172)
      Benjamin Gallois authored and Hugo Trentesaux's avatar Hugo Trentesaux committed
      * allow clippy needless_pass_by_ref_mut
      
      * fix clippy
      
      °_°
      
      * fix provider behavior
      
      * fix build errors
      
      * change behavior of going below ED
      
      * fix provider initialization
      
      * add mock epoch change
      
      * add session number test
      
      * add session number test
      
      * WIP fix tests
      
      * fix time-based ud test
      
      * update metadata
      
      * FIX apply all fix from flash branch
      
      * partial fix clippy
      
      other suggestions are not legit
      
      * fix metadata and end2end test
      
      * fix build tests
      
      * fix build and clippy
      
      * remove benchmark of upgrade_accounts
      
      this happens in substrate dependency
      I also updated other packages because why not :D
      and I removed a useless implementation in mock
      but the test do not compile with feature runtime benchmarks anyway
      
      * test_total_issuance_vs_monetary_mass
      
      * proofreading comment
      
      * fix total issuance differently
      
      this actually fixes total issuance at genesis
      instead of creating duplicate account data
      
      * fix test scenario
      
      the thing tested here was not the ability to call the function,
      but the impossibility of deleting the account
      
      * add comment to explain test
      
      * fix providers and sufficients counts
      
      * fix initial balance
      
      * fix initial TotalIssuance
      
      * fix clippy warnings and optimization
      
      * fix xtask
      
      * update docs
      
      * add DustHandle
      
      * fix pallets config
      
      * fix tests
      
      * fix pallet_balance genesis config
      
      * wip: fix end2end-test
      
      * fix manual and instant sealing
      
      * fix live-tests
      
      * fix offences after rebase
      
      * generate all weights
      
      * add rust toolchain file
      
      * fix benchmarks
      
      Pallet balances benchmarks need https://github.com/duniter/substrate/commit/c36ab4f32454318a47777b24b6533c44121fc10b because pallet duniter-account add another provider.
      
      * fix babe-worker
      
      * fix subxt dependency
      
      * fix ImplicitCallIndex and Weight::from_ref_time deprecation
      
      * fix consensus_babe dependency
      
      * regenerate weights
      
      Regenerate all weights except for pallet-balance failing on one extrinsic
      
      * workaround pallet_duniter_account
      
      Workaround to be able to pass https://github.com/paritytech/substrate/blob/6ef184e33f6ce0f56999ae84b212ea6148c0624d/frame/balances/src/benchmarking.rs#L271 in the benchmark.
      ExtraFlags is private and Default is always new_logic not suitable for the benchmark.
      
      * wip fix node errors
      
      * wip fix runtime errors
      
      * fix pallet-duniter-account errors
      
      * fix pallet-balance errors
      
      * fix pallet-identity errors
      
      * fix pallet-duniter-account errors
      
      * upgrade Cargo files
      
      * update docs
    gen_calls_doc.rs 9.18 KiB
    // Copyright 2021 Axiom-Team
    //
    // This file is part of Duniter-v2S.
    //
    // Duniter-v2S is free software: you can redistribute it and/or modify
    // it under the terms of the GNU Affero General Public License as published by
    // the Free Software Foundation, version 3 of the License.
    //
    // Duniter-v2S is distributed in the hope that it will be useful,
    // but WITHOUT ANY WARRANTY; without even the implied warranty of
    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    // GNU Affero General Public License for more details.
    //
    // You should have received a copy of the GNU Affero General Public License
    // along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>.
    
    use anyhow::{bail, Context, Result};
    use codec::Decode;
    use scale_info::form::PortableForm;
    use serde::Serialize;
    use std::{
        fs::File,
        io::{Read, Write},
    };
    use tera::Tera;
    
    // consts
    
    const CALLS_DOC_FILEPATH: &str = "docs/api/runtime-calls.md";
    const TEMPLATES_GLOB: &str = "xtask/res/templates/*.md";
    
    // define structs and implementations
    
    type RuntimeCalls = Vec<Pallet>;
    
    #[derive(Clone, Serialize)]
    struct Pallet {
        index: u8,
        name: String,
        calls: Vec<Call>,
    }
    
    impl Pallet {
        fn new(
            index: u8,
            name: String,
            scale_type_def: &scale_info::TypeDef<PortableForm>,
        ) -> Result<Self> {
            if let scale_info::TypeDef::Variant(calls_enum) = scale_type_def {
                Ok(Self {
                    index,
                    name,
                    calls: calls_enum.variants.iter().map(Into::into).collect(),
                })
            } else {
                bail!("Invalid metadata")
            }
        }
    }
    
    #[derive(Clone, Serialize)]
    struct Call {
        documentation: String,
        index: u8,
        name: String,
        params: Vec<CallParam>,
    }
    
    impl From<&scale_info::Variant<PortableForm>> for Call {
        fn from(variant: &scale_info::Variant<PortableForm>) -> Self {
            Self {
                documentation: variant
                    .docs
                    .iter()
                    .take_while(|line| !line.starts_with("# <weight>"))
                    .cloned()
                    .collect::<Vec<_>>()
                    .join("\n"),
                index: variant.index,
                name: variant.name.to_owned(),
                params: variant.fields.iter().map(Into::into).collect(),
            }
        }
    }
    
    #[derive(Clone, Serialize)]
    struct CallParam {
        name: String,
        type_name: String,
    }
    
    impl From<&scale_info::Field<PortableForm>> for CallParam {
        fn from(field: &scale_info::Field<PortableForm>) -> Self {
            Self {
                name: field.clone().name.unwrap_or_default(),
                type_name: field.clone().type_name.unwrap_or_default(),
            }
        }
    }
    
    enum CallCategory {
        Disabled,
        Inherent,
        OtherOrigin,
        Root,
        Sudo,
        User,
    }
    
    impl CallCategory {
        fn is(pallet_name: &str, call_name: &str) -> Self {
            match (pallet_name, call_name) {
                ("System", "remark" | "remark_with_event") => Self::Disabled,
                ("System", _) => Self::Root,
                ("Babe", "report_equivocation_unsigned") => Self::Inherent,
                ("Babe", "plan_config_change") => Self::Root,
                ("Timestamp", _) => Self::Inherent,
                ("Balances", "set_balance" | "force_transfer" | "force_unreserve") => Self::Root,
                ("AuthorityMembers", "prune_account_id_of" | "remove_member") => Self::Root,
                ("Authorship", _) => Self::Inherent,
                ("Session", _) => Self::Disabled,
                ("Grandpa", "report_equivocation_unsigned") => Self::Inherent,
                ("Grandpa", "note_stalled") => Self::Root,
                ("UpgradeOrigin", "dispatch_as_root") => Self::OtherOrigin,
                ("ImOnline", _) => Self::Inherent,
                ("Sudo", _) => Self::Sudo,
                (
                    "Identity",
                    "remove_identity" | "prune_item_identities_names" | "prune_item_identity_index_of",
                ) => Self::Root,
                ("Membership", "request_membership" | "revoke_membership") => Self::Disabled,
                ("Cert", "del_cert" | "remove_all_certs_received_by") => Self::Root,
                ("SmithCert", "del_cert" | "remove_all_certs_received_by") => Self::Root,
                ("TechnicalCommittee", "set_members" | "disapprove_proposal") => Self::Root,
                ("Utility", "dispatch_as") => Self::Root,
                ("Treasury", "approve_proposal" | "reject_proposal") => Self::OtherOrigin,
                _ => Self::User,
            }
        }
        fn is_root(pallet_name: &str, call_name: &str) -> bool {
            matches!(Self::is(pallet_name, call_name), Self::Root)
        }
        fn is_user(pallet_name: &str, call_name: &str) -> bool {
            matches!(Self::is(pallet_name, call_name), Self::User)
        }
        fn is_disabled(pallet_name: &str, call_name: &str) -> bool {
            matches!(Self::is(pallet_name, call_name), Self::Disabled)
        }
    }
    
    /// generate runtime calls documentation
    pub(super) fn gen_calls_doc() -> Result<()> {
        // Read metadata
        let mut file = std::fs::File::open("resources/metadata.scale")
            .with_context(|| "Failed to open metadata file")?;
    
        let mut bytes = Vec::new();
        file.read_to_end(&mut bytes)
            .with_context(|| "Failed to read metadata file")?;
    
        let metadata = frame_metadata::RuntimeMetadataPrefixed::decode(&mut &bytes[..])
            .with_context(|| "Failed to decode metadata")?;
    
        println!("Metadata successfully loaded!");
    
        let runtime_calls = if let frame_metadata::RuntimeMetadata::V14(metadata_v14) = metadata.1 {
            get_calls_from_metadata_v14(metadata_v14)?
        } else {
            bail!("unsuported metadata version")
        };
    
        let output = print_runtime_calls(runtime_calls);
    
        let mut file = File::create(CALLS_DOC_FILEPATH)
            .with_context(|| format!("Failed to create file '{}'", CALLS_DOC_FILEPATH))?;
        file.write_all(output.as_bytes())
            .with_context(|| format!("Failed to write to file '{}'", CALLS_DOC_FILEPATH))?;
    
        Ok(())
    }
    
    fn get_calls_from_metadata_v14(
        metadata_v14: frame_metadata::v14::RuntimeMetadataV14,
    ) -> Result<RuntimeCalls> {
        println!("Number of pallets: {}", metadata_v14.pallets.len());
        let mut pallets = Vec::new();
        for pallet in metadata_v14.pallets {
            if let Some(calls) = pallet.calls {
                if let Some(calls_type) = metadata_v14.types.resolve(calls.ty.id) {
                    let pallet = Pallet::new(pallet.index, pallet.name.clone(), &calls_type.type_def)?;
                    let calls_len = pallet.calls.len();
                    println!("{}: {} ({} calls)", pallet.index, pallet.name, calls_len);
                    pallets.push(pallet);
                } else {
                    bail!("Invalid metadata")
                }
            } else {
                println!("{}: {} (0 calls)", pallet.index, pallet.name);
            }
        }
        Ok(pallets)
    }
    
    /// use template to render markdown file with runtime calls documentation
    fn print_runtime_calls(pallets: RuntimeCalls) -> String {
        // init variables
        let mut user_calls_counter = 0;
        let user_calls_pallets: RuntimeCalls = pallets
            .iter()
            .cloned()
            .filter_map(|mut pallet| {
                let pallet_name = pallet.name.clone();
                pallet
                    .calls
                    .retain(|call| CallCategory::is_user(&pallet_name, &call.name));
                if pallet.calls.is_empty() {
                    None
                } else {
                    user_calls_counter += pallet.calls.len();
                    Some(pallet)
                }
            })
            .collect();
        let mut root_calls_counter = 0;
        let root_calls_pallets: RuntimeCalls = pallets
            .iter()
            .cloned()
            .filter_map(|mut pallet| {
                let pallet_name = pallet.name.clone();
                pallet
                    .calls
                    .retain(|call| CallCategory::is_root(&pallet_name, &call.name));
                if pallet.calls.is_empty() {
                    None
                } else {
                    root_calls_counter += pallet.calls.len();
                    Some(pallet)
                }
            })
            .collect();
        let mut disabled_calls_counter = 0;
        let disabled_calls_pallets: RuntimeCalls = pallets
            .iter()
            .cloned()
            .filter_map(|mut pallet| {
                let pallet_name = pallet.name.clone();
                pallet
                    .calls
                    .retain(|call| CallCategory::is_disabled(&pallet_name, &call.name));
                if pallet.calls.is_empty() {
                    None
                } else {
                    disabled_calls_counter += pallet.calls.len();
                    Some(pallet)
                }
            })
            .collect();
    
        // compile template
        let tera = match Tera::new(TEMPLATES_GLOB) {
            Ok(t) => t,
            Err(e) => {
                println!("Parsing error(s): {}", e);
                ::std::process::exit(1);
            }
        };
    
        // fills tera context for rendering
        let mut context = tera::Context::new();
        context.insert("user_calls_counter", &user_calls_counter);
        context.insert("user_calls_pallets", &user_calls_pallets);
        context.insert("root_calls_counter", &root_calls_counter);
        context.insert("root_calls_pallets", &root_calls_pallets);
        context.insert("disabled_calls_counter", &disabled_calls_counter);
        context.insert("disabled_calls_pallets", &disabled_calls_pallets);
    
        tera.render("runtime-calls.md", &context)
            .expect("template error")
    }