diff --git a/Cargo.lock b/Cargo.lock
index b3e8010e2c0..45aa8d137b5 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -7028,9 +7028,11 @@ dependencies = [
name = "gear-weight-diff"
version = "1.0.0"
dependencies = [
+ "anyhow",
"clap 4.5.9",
"frame-support",
"gear-utils",
+ "heck 0.5.0",
"indexmap 2.2.6",
"pallet-gear",
"proc-macro2",
diff --git a/core/src/gas_metering/schedule.rs b/core/src/gas_metering/schedule.rs
index 2676a1a892b..2731dc7a1d1 100644
--- a/core/src/gas_metering/schedule.rs
+++ b/core/src/gas_metering/schedule.rs
@@ -16,11 +16,12 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
+#![allow(rustdoc::broken_intra_doc_links, missing_docs)]
#![doc = r" This is auto-generated module that contains cost schedule from"]
#![doc = r" `pallets/gear/src/schedule.rs`."]
#![doc = r""]
#![doc = r" See `./scripts/weight-dump.sh` if you want to update it."]
-#![allow(rustdoc::broken_intra_doc_links, missing_docs)]
+
use crate::costs::*;
#[derive(Debug, Clone)]
@@ -1013,20 +1014,23 @@ impl Default for DbWeights {
}
}
-#[doc = r" TODO: documentation"]
+#[doc = r" Represents the computational time and storage space required for an operation."]
#[derive(Debug, Clone, Copy)]
pub struct Weight {
- #[doc = r" Reference time"]
+ #[doc = r" The weight of computational time used based on some reference hardware."]
pub ref_time: u64,
- #[doc = r" Storage size of the weight"]
+ #[doc = r" The weight of storage space used by proof of validity."]
pub proof_size: u64,
}
impl Weight {
+ #[doc = r" Return the reference time part of the weight."]
#[doc(hidden)]
pub const fn ref_time(&self) -> u64 {
self.ref_time
}
+ #[doc = r" Saturating [`Weight`] addition. Computes `self + rhs`, saturating at the numeric bounds of"]
+ #[doc = r" all fields instead of overflowing."]
#[doc(hidden)]
pub const fn saturating_add(&self, other: Self) -> Self {
Self {
diff --git a/utils/weight-diff/Cargo.toml b/utils/weight-diff/Cargo.toml
index 73dbfc333d4..3b35c1292df 100644
--- a/utils/weight-diff/Cargo.toml
+++ b/utils/weight-diff/Cargo.toml
@@ -6,6 +6,8 @@ edition.workspace = true
license.workspace = true
[dependencies]
+anyhow.workspace = true
+heck.workspace = true
clap = { workspace = true, features = ["derive"] }
indexmap = { workspace = true, features = ["serde"] }
serde = { workspace = true, features = ["derive"] }
diff --git a/utils/weight-diff/src/main.rs b/utils/weight-diff/src/main.rs
index 482d02e03cf..4baa0792e73 100644
--- a/utils/weight-diff/src/main.rs
+++ b/utils/weight-diff/src/main.rs
@@ -18,19 +18,25 @@
//! Helper utility to track changes in weights between different branches.
+use anyhow::Result;
use clap::{Parser, Subcommand, ValueEnum};
use frame_support::{
sp_runtime::{FixedPointNumber, FixedU128 as Fixed},
weights::Weight,
};
use gear_utils::codegen::{format_with_rustfmt, LICENSE};
+use heck::ToSnakeCase;
use indexmap::IndexMap;
use pallet_gear::Schedule;
use proc_macro2::TokenStream;
use quote::{quote, ToTokens};
use serde::{Deserialize, Serialize};
use serde_json::Value;
-use std::{fs, path::PathBuf, str::FromStr};
+use std::{
+ fs::{self, File},
+ path::PathBuf,
+ str::FromStr,
+};
use syn::{
ext::IdentExt,
visit::{self, Visit},
@@ -230,26 +236,34 @@ impl<'ast> Visit<'ast> for StructuresVisitor {
let mut structure = node.clone();
- structure
- .attrs
- .retain(|attr| attr.path().segments.first().unwrap().ident == "doc");
+ structure.attrs.retain(|attr| {
+ attr.path()
+ .segments
+ .first()
+ .filter(|segment| segment.ident == "doc")
+ .is_some()
+ });
+
if structure_name == "Schedule" {
structure.attrs.drain(1..);
}
+
structure.generics = Generics::default();
if let Fields::Named(ref mut fields) = structure.fields {
- let last_ident = fields
+ if fields
.named
.last()
- .and_then(|field| field.ident.as_ref().map(|ident| ident.to_string()));
- if last_ident == Some(String::from("_phantom")) {
+ .and_then(|field| field.ident.as_ref())
+ .filter(|ident| *ident == "_phantom")
+ .is_some()
+ {
fields.named.pop();
}
}
for field in structure.fields.iter_mut() {
- field.vis = syn::parse2(quote! { pub }).unwrap();
+ field.vis = syn::parse2(quote! { pub }).expect("infallible");
if let Type::Path(TypePath { path, .. }) = &mut field.ty {
for segment in path.segments.iter_mut() {
@@ -265,9 +279,14 @@ impl<'ast> Visit<'ast> for StructuresVisitor {
}
}
}
- field
- .attrs
- .retain(|attr| attr.path().segments.first().unwrap().ident == "doc");
+
+ field.attrs.retain(|attr| {
+ attr.path()
+ .segments
+ .first()
+ .filter(|segment| segment.ident == "doc")
+ .is_some()
+ });
}
self.structures.insert(structure_name, structure);
@@ -281,7 +300,7 @@ struct ImplementationVisitor {
impls: Vec,
}
-static TYPE_LIST: &[&str] = &[
+const TYPE_LIST: &[&str] = &[
"InstructionCosts",
"SyscallCosts",
"MemoryCosts",
@@ -291,36 +310,39 @@ static TYPE_LIST: &[&str] = &[
];
impl ImplementationVisitor {
- fn find_from_impls(&mut self, node: &syn::ItemImpl) -> bool {
+ fn find_from_impls(&mut self, node: &ItemImpl) -> bool {
let mut implementation = node.clone();
- implementation
- .attrs
- .retain(|attr| attr.path().segments.first().unwrap().ident == "doc");
+
+ implementation.attrs.retain(|attr| {
+ attr.path()
+ .segments
+ .first()
+ .filter(|segment| segment.ident == "doc")
+ .is_some()
+ });
+
implementation.generics = Generics::default();
// first extract all the `*Costs` impls.
if let Some((_, Path { segments, .. }, _)) = &mut implementation.trait_ {
if let Some(PathSegment { ident, arguments }) = segments.first_mut() {
if *ident == "From" {
- if let Type::Path(tpath) = &mut *implementation.self_ty {
+ if let Type::Path(TypePath { path, .. }) = &mut *implementation.self_ty {
let PathArguments::AngleBracketed(types) = arguments else {
unreachable!("unexpected From impl detected")
};
- let Some(GenericArgument::Type(ref mut typ)) = types.args.first_mut()
- else {
+ let Some(GenericArgument::Type(ref mut ty)) = types.args.first_mut() else {
unreachable!("unexpected From impl detected")
};
- if let Type::Path(path) = typ {
- path.path.segments.first_mut().unwrap().arguments = PathArguments::None;
+ if let Type::Path(TypePath { path, .. }) = ty {
+ if let Some(PathSegment { arguments, .. }) = path.segments.first_mut() {
+ *arguments = PathArguments::None;
+ }
}
- if let Some(PathSegment {
- ident,
- arguments: _,
- }) = tpath.path.segments.first_mut()
- {
+ if let Some(PathSegment { ident, .. }) = path.segments.first_mut() {
if TYPE_LIST.contains(&ident.to_string().as_str()) {
let Some(ImplItem::Fn(from_fn)) = implementation.items.first_mut()
else {
@@ -353,21 +375,26 @@ impl ImplementationVisitor {
}
}
- fn find_process_costs(&mut self, node: &syn::ItemImpl) {
+ fn find_process_costs(&mut self, node: &ItemImpl) {
let mut implementation = node.clone();
- implementation
- .attrs
- .retain(|attr| attr.path().segments.first().unwrap().ident == "doc");
+
+ implementation.attrs.retain(|attr| {
+ attr.path()
+ .segments
+ .first()
+ .filter(|segment| segment.ident == "doc")
+ .is_some()
+ });
+
implementation.generics = Generics::default();
- if let Type::Path(path) = &mut *implementation.self_ty {
- if let Some(PathSegment { arguments, ident }) = path.path.segments.first_mut() {
+ if let Type::Path(TypePath { path, .. }) = &mut *implementation.self_ty {
+ if let Some(PathSegment { arguments, ident }) = path.segments.first_mut() {
*arguments = PathArguments::None;
if *ident == "Schedule" {
// only leave process_costs method
implementation.items.retain_mut(|item| match item {
ImplItem::Fn(func) => func.sig.ident == "process_costs",
-
_ => false,
});
@@ -379,7 +406,7 @@ impl ImplementationVisitor {
}
impl<'ast> Visit<'ast> for ImplementationVisitor {
- fn visit_item_impl(&mut self, node: &'ast syn::ItemImpl) {
+ fn visit_item_impl(&mut self, node: &'ast ItemImpl) {
if !self.find_from_impls(node) {
self.find_process_costs(node);
}
@@ -388,20 +415,19 @@ impl<'ast> Visit<'ast> for ImplementationVisitor {
}
}
-fn main() {
+fn main() -> Result<()> {
let Cli { command } = Cli::parse();
match command {
Commands::Dump { output_path, label } => {
- let writer = fs::File::create(output_path).unwrap();
+ let writer = File::create(output_path)?;
serde_json::to_writer_pretty(
writer,
&SerializableDump {
vara_schedule: Default::default(),
label,
},
- )
- .unwrap();
+ )?;
}
Commands::Diff {
display_units,
@@ -410,11 +436,9 @@ fn main() {
runtime,
kind,
} => {
- let dump1: DeserializableDump =
- serde_json::from_str(&fs::read_to_string(before).unwrap()).unwrap();
+ let dump1: DeserializableDump = serde_json::from_str(&fs::read_to_string(before)?)?;
- let dump2: DeserializableDump =
- serde_json::from_str(&fs::read_to_string(after).unwrap()).unwrap();
+ let dump2: DeserializableDump = serde_json::from_str(&fs::read_to_string(after)?)?;
let (schedule1, schedule2) = match runtime {
Runtime::Vara => (dump1.vara_schedule, dump2.vara_schedule),
@@ -471,15 +495,12 @@ fn main() {
println!();
}
Commands::Codegen { path, runtime } => {
- let dump: DeserializableDump =
- serde_json::from_str(&fs::read_to_string(path).unwrap()).unwrap();
+ let dump: DeserializableDump = serde_json::from_str(&fs::read_to_string(path)?)?;
let raw_schedule = match runtime {
- Runtime::Vara => serde_json::to_value(dump.vara_schedule).unwrap(),
+ Runtime::Vara => serde_json::to_value(dump.vara_schedule)?,
};
- let file =
- syn::parse_file(&fs::read_to_string("pallets/gear/src/schedule.rs").unwrap())
- .unwrap();
+ let file = syn::parse_file(&fs::read_to_string("pallets/gear/src/schedule.rs")?)?;
let mut visitor = StructuresVisitor::default();
visitor.visit_file(&file);
@@ -493,18 +514,20 @@ fn main() {
.map(|item| Item::Impl(item).to_token_stream())
.collect::>();
- let mut declarations = vec![quote! {
- //! This is auto-generated module that contains cost schedule from
- //! `pallets/gear/src/schedule.rs`.
- //!
- //! See `./scripts/weight-dump.sh` if you want to update it.
- }];
-
- declarations.push(quote! {
- #![allow(rustdoc::broken_intra_doc_links, missing_docs)]
-
- use crate::costs::*;
- });
+ let mut declarations = vec![
+ quote! {
+ #![allow(rustdoc::broken_intra_doc_links, missing_docs)]
+ },
+ quote! {
+ //! This is auto-generated module that contains cost schedule from
+ //! `pallets/gear/src/schedule.rs`.
+ //!
+ //! See `./scripts/weight-dump.sh` if you want to update it.
+ },
+ quote! {
+ use crate::costs::*;
+ },
+ ];
for (structure_name, structure) in visitor.structures {
let structure_ident = &structure.ident;
@@ -516,16 +539,17 @@ fn main() {
let field_ident = field.ident.as_ref().unwrap();
let field_name = field_ident.unraw().to_string();
+ let structure_name_snake_case = structure_name.to_snake_case();
let value = match structure_name.as_str() {
"Schedule" => &raw_schedule[field_name],
- "Limits" => &raw_schedule["limits"][field_name],
- "InstructionWeights" => &raw_schedule["instruction_weights"][field_name],
- "SyscallWeights" => &raw_schedule["syscall_weights"][field_name],
- "MemoryWeights" => &raw_schedule["memory_weights"][field_name],
- "RentWeights" => &raw_schedule["rent_weights"][field_name],
- "DbWeights" => &raw_schedule["db_weights"][field_name],
- "InstantiationWeights" => {
- &raw_schedule["instantiation_weights"][field_name]
+ "Limits"
+ | "InstructionWeights"
+ | "SyscallWeights"
+ | "MemoryWeights"
+ | "RentWeights"
+ | "DbWeights"
+ | "InstantiationWeights" => {
+ &raw_schedule[structure_name_snake_case.as_str()][field_name]
}
_ => &raw_schedule,
};
@@ -576,24 +600,26 @@ fn main() {
}
declarations.push(quote! {
-
- /// TODO: documentation
+ /// Represents the computational time and storage space required for an operation.
#[derive(Debug, Clone, Copy)]
pub struct Weight {
- /// Reference time
+ /// The weight of computational time used based on some reference hardware.
pub ref_time: u64,
- /// Storage size of the weight
+ /// The weight of storage space used by proof of validity.
pub proof_size: u64,
}
});
declarations.push(quote! {
impl Weight {
+ /// Return the reference time part of the weight.
#[doc(hidden)]
pub const fn ref_time(&self) -> u64 {
self.ref_time
}
+ /// Saturating [`Weight`] addition. Computes `self + rhs`, saturating at the numeric bounds of
+ /// all fields instead of overflowing.
#[doc(hidden)]
pub const fn saturating_add(&self, other: Self) -> Self {
Self {
@@ -615,4 +641,6 @@ fn main() {
println!("{formatted}");
}
}
+
+ Ok(())
}