Los 23 weights de spec 16, certificados por Laurha en el santuario de la rp1 (origin-banco):
- Núcleo 3 aislado, governor performance a 2,4 GHz, CI parada, 45-49 °C.
- frame-omni-bencher 0.15.0 sobre el wasm 40cb5a1d de 3cd1068.
- 5 procesos por pallet; se cobra el MÁXIMO con scripts/bench/max-de-n.py, porque procesos
idénticos se separan hasta un 35 %.
- Evidencia: ~/laurha-work/banco/spec16-20261024-1631 en la rp1 (SHA256SUMS d930c5e1).
- Su perfil va en la cabecera de cada weights.rs.
Antes de cobrarlos:
- Mismos accesos a storage: el esqueleto de los 5 ficheros y sus reads/writes son idénticos a
los de main.
- Lo que Laurha pidió mirar (cast_vote, finalize_proposal y veto_proposal, mucho más altos que
en RV12) es esperable. Contra los interinos del Mac todos caen en la banda Pi/Mac de 2,5-3,9×:
es trabajo nuevo de RV15/RV16 en una CPU unas 3 veces más lenta.
- Destacan los tres que verifican Ed25519 en WASM (attest_asset, register_agent_did,
rotate_agent_key), con unas 6 veces: la criptografía pura sufre más en la Cortex-A76.
- Lo cobrado sube menos que la ejecución, entre +4 % (set_tier_profile) y +56 %
(rotate_agent_key), porque las lecturas y escrituras de storage no cambian.
- spec_version 16 → 17, porque cambian las fees. transaction_version no cambia: ninguna llamada
cambia su codificación.
Ensayado en la rp1 (aarch64) sobre un nodo efímero aparte, antes de la testnet de la casa, con
scripts/e2e/upgrade_en_vivo.py (nuevo):
- sudo(set_code) → CodeUpdated + Sudid Ok;
- spec 17 y LastRuntimeUpgrade sube;
- una firma con la spec vieja → «bad signature»; con la nueva, ExtrinsicSuccess;
- la finalidad pasa del bloque del upgrade.
Es la primera vez que el ejecutor ARM compila y corre un runtime nuevo.
Revisión adversarial (nivel 1 de la directiva), antes de tocar la red, con orden de tumbarlo:
no pudo. Los seis puntos aguantan:
- ningún storage ni codificación cambia, y transaction_version no debe subir;
- el más pesado (veto_proposal) cobra 1,9 ms, 344 veces por debajo del máximo por extrinsic;
- los weights.rs tienen la misma estructura y el impl () coincide;
- ninguna fee, subsidio ni test depende del valor de forma que se rompa.
scripts/rp1 (operación del nodo, medido en 23 h con los valores por defecto):
- 430 MB de WAL de RocksDB retenidos para 15 MB de datos, y el RSS subiendo de 200 a 340 MB:
--db-cache 128. Al reiniciar, 449 → 21 MB.
- El log, de 7 líneas por bloque a ~2 (txpool, sc_basic_authorship y aura en warn; ojo: las
líneas de autoría usan el target del módulo, no «basic-authorship»), de 16 MB/día a unos 3.
- Modo append, y medir.sh lo rota al pasar de 32 MB.
Co-Authored-By: Laurha <laurha@origin>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
213 lines
9.8 KiB
Rust
213 lines
9.8 KiB
Rust
// SPDX-License-Identifier: Apache-2.0
|
|
// Origin Chain — Pilar 4 · Charon
|
|
//
|
|
// ATENCION AL LEER ESTOS NUMEROS: un weight es una LATENCIA, y una latencia sin
|
|
// el hardware y el perfil de potencia que la produjeron no se puede reproducir.
|
|
// La cabecera dice HOSTNAME y CPU: creele a eso y a nada mas. Un weight medido
|
|
// en un portatil y cobrado en un Pi 5 es mispricing estructural, solo que
|
|
// invisible. Los numeros CANONICOS de mainnet salen del banco de referencia
|
|
// (Pi 5, governor y aislamiento declarados), no de la maquina de quien compila.
|
|
|
|
// MEDIDO POR LAURHA 🌊 EN EL BANCO DE REFERENCIA, 2026-10-24 17:41-17:46. El perfil es el mismo
|
|
// al empezar y al acabar:
|
|
// CyberDeckRP1 · Raspberry Pi 5 · Cortex-A76 · kernel 6.18.34+rpt-rpi-2712.
|
|
// Núcleo 3 aislado (partición cgroup «isolated» de origin-banco), governor performance a
|
|
// 2,4 GHz, CI parada, throttled 0x0, 45-49 °C.
|
|
// frame-omni-bencher 0.15.0 · wasm sha256 40cb5a1d…a1cf744 (spec 16, main 3cd1068).
|
|
// steps 50 · repeat 20 · taskset -c 3 · 5 PROCESOS por pallet, y se cobra el MÁXIMO de los 5
|
|
// (scripts/bench/max-de-n.py): procesos idénticos se separan hasta un 35 % en el base weight.
|
|
// Evidencia en la rp1: ~/laurha-work/banco/spec16-20261024-1631 (SHA256SUMS d930c5e1…).
|
|
// La Pi es el hardware MÁS LENTO que puede validar la red: sus pesos son el techo honesto. El
|
|
// TIEMPO DE EJECUCIÓN sale de 2,5 a 3,9 veces el del Mac M3 Max (~6 veces en los que verifican
|
|
// Ed25519). Lo COBRADO sube menos, entre +4 % y +56 %, porque lecturas y escrituras de storage
|
|
// (RocksDbWeight) no cambian y pesan más que la ejecución (revisión adversarial, 25-oct).
|
|
|
|
//! Weights AUTOGENERADOS para `origin_chain_provenance` — NO editar a mano.
|
|
//!
|
|
//! Regenerar: `scripts/bench/regen-weights.sh` (ver ese script para el
|
|
//! procedimiento completo y el hardware al que hay que creerle).
|
|
//!
|
|
//! GENERADO POR SUBSTRATE BENCHMARK CLI VERSION 51.0.0
|
|
//! FECHA: 2026-10-24, STEPS: `50`, REPEAT: `20`
|
|
//! HOSTNAME: `CyberDeckRP1`, CPU: `<UNKNOWN>`
|
|
//! WASM-EXECUTION: `Compiled`, DB CACHE: 1024
|
|
|
|
// Comando ejecutado:
|
|
// /home/davidherran/.cargo/bin/frame-omni-bencher
|
|
// v1
|
|
// benchmark
|
|
// pallet
|
|
// --runtime
|
|
// /home/davidherran/charon/bench/origin_chain_runtime_spec16_3cd1068_bench.compact.compressed.wasm
|
|
// --genesis-builder-preset
|
|
// development
|
|
// --pallet
|
|
// origin_chain_provenance
|
|
// --extrinsic
|
|
//
|
|
// --steps
|
|
// 50
|
|
// --repeat
|
|
// 20
|
|
// --template
|
|
// /home/davidherran/charon/bench/origin-weights-template.hbs
|
|
// --header
|
|
// /home/davidherran/charon/bench/HEADER.txt
|
|
// --output
|
|
// /home/davidherran/laurha-work/banco/spec16-20261024-1631/r1/origin_chain_provenance.rs
|
|
|
|
#![cfg_attr(rustfmt, rustfmt_skip)]
|
|
#![allow(unused_parens)]
|
|
#![allow(unused_imports)]
|
|
#![allow(missing_docs)]
|
|
|
|
use core::marker::PhantomData;
|
|
use frame_support::{traits::Get, weights::constants::RocksDbWeight, weights::Weight};
|
|
|
|
/// Trait de weights para los extrinsics de `origin_chain_provenance`.
|
|
// MAXIMO DE N = 5 PROCESOS (scripts/bench/max-de-n.py): cada coeficiente
|
|
// de tiempo y de proof es el maximo de los N; reads/writes iguales en los N.
|
|
// Entradas (sha256[:12]): f9073e1d0c4a 10b95d00a036 5aa8e0aaf057 5c50e916300f 8f55f561f51a
|
|
|
|
pub trait WeightInfo {
|
|
/// Peso de `attest_asset` — MEDIDO sobre el WASM, no estimado a mano.
|
|
fn attest_asset() -> Weight;
|
|
/// Peso de `register_validator` — MEDIDO sobre el WASM, no estimado a mano.
|
|
fn register_validator() -> Weight;
|
|
/// Peso de `revoke_validator` — MEDIDO sobre el WASM, no estimado a mano.
|
|
fn revoke_validator() -> Weight;
|
|
}
|
|
|
|
/// Weights parametrizados por el `DbWeight` real del runtime.
|
|
pub struct SubstrateWeight<T>(PhantomData<T>);
|
|
impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
|
/// Storage: `Provenance::Attestations` (r:1 w:1)
|
|
/// Proof: `Provenance::Attestations` (`max_values`: None, `max_size`: Some(505), added: 2980, mode: `MaxEncodedLen`)
|
|
/// Storage: `Provenance::AuthorizedValidators` (r:1 w:0)
|
|
/// Proof: `Provenance::AuthorizedValidators` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`)
|
|
/// Storage: `System::BlockHash` (r:1 w:0)
|
|
/// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`)
|
|
/// Storage: `System::Number` (r:1 w:0)
|
|
/// Proof: `System::Number` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
|
/// Storage: `System::ExecutionPhase` (r:1 w:0)
|
|
/// Proof: `System::ExecutionPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `MaxEncodedLen`)
|
|
/// Storage: `System::EventCount` (r:1 w:1)
|
|
/// Proof: `System::EventCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
|
/// Storage: `System::Events` (r:1 w:1)
|
|
/// Proof: `System::Events` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
|
fn attest_asset() -> Weight {
|
|
// Proof size en bytes:
|
|
// Medido: `154`
|
|
// Estimado: `3970`
|
|
// Tiempo minimo de ejecucion: 244_594_000 picosegundos.
|
|
Weight::from_parts(246_613_000, 0)
|
|
.saturating_add(Weight::from_parts(0, 3970))
|
|
.saturating_add(T::DbWeight::get().reads(7_u64))
|
|
.saturating_add(T::DbWeight::get().writes(3_u64))
|
|
}
|
|
/// Storage: `System::Number` (r:1 w:0)
|
|
/// Proof: `System::Number` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
|
/// Storage: `System::ExecutionPhase` (r:1 w:0)
|
|
/// Proof: `System::ExecutionPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `MaxEncodedLen`)
|
|
/// Storage: `System::EventCount` (r:1 w:1)
|
|
/// Proof: `System::EventCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
|
/// Storage: `System::Events` (r:1 w:1)
|
|
/// Proof: `System::Events` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
|
/// Storage: `Provenance::AuthorizedValidators` (r:0 w:1)
|
|
/// Proof: `Provenance::AuthorizedValidators` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`)
|
|
fn register_validator() -> Weight {
|
|
// Proof size en bytes:
|
|
// Medido: `20`
|
|
// Estimado: `1505`
|
|
// Tiempo minimo de ejecucion: 21_333_000 picosegundos.
|
|
Weight::from_parts(22_482_000, 0)
|
|
.saturating_add(Weight::from_parts(0, 1505))
|
|
.saturating_add(T::DbWeight::get().reads(4_u64))
|
|
.saturating_add(T::DbWeight::get().writes(3_u64))
|
|
}
|
|
/// Storage: `System::Number` (r:1 w:0)
|
|
/// Proof: `System::Number` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
|
/// Storage: `System::ExecutionPhase` (r:1 w:0)
|
|
/// Proof: `System::ExecutionPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `MaxEncodedLen`)
|
|
/// Storage: `System::EventCount` (r:1 w:1)
|
|
/// Proof: `System::EventCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
|
/// Storage: `System::Events` (r:1 w:1)
|
|
/// Proof: `System::Events` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
|
/// Storage: `Provenance::AuthorizedValidators` (r:0 w:1)
|
|
/// Proof: `Provenance::AuthorizedValidators` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`)
|
|
fn revoke_validator() -> Weight {
|
|
// Proof size en bytes:
|
|
// Medido: `20`
|
|
// Estimado: `1505`
|
|
// Tiempo minimo de ejecucion: 21_000_000 picosegundos.
|
|
Weight::from_parts(22_518_000, 0)
|
|
.saturating_add(Weight::from_parts(0, 1505))
|
|
.saturating_add(T::DbWeight::get().reads(4_u64))
|
|
.saturating_add(T::DbWeight::get().writes(3_u64))
|
|
}
|
|
}
|
|
|
|
/// Impl para mocks y tests — `RocksDbWeight` directo, sin necesitar `T`.
|
|
impl WeightInfo for () {
|
|
fn attest_asset() -> Weight {
|
|
Weight::from_parts(246_613_000, 0)
|
|
.saturating_add(Weight::from_parts(0, 3970))
|
|
.saturating_add(RocksDbWeight::get().reads(7_u64))
|
|
.saturating_add(RocksDbWeight::get().writes(3_u64))
|
|
}
|
|
fn register_validator() -> Weight {
|
|
Weight::from_parts(22_482_000, 0)
|
|
.saturating_add(Weight::from_parts(0, 1505))
|
|
.saturating_add(RocksDbWeight::get().reads(4_u64))
|
|
.saturating_add(RocksDbWeight::get().writes(3_u64))
|
|
}
|
|
fn revoke_validator() -> Weight {
|
|
Weight::from_parts(22_518_000, 0)
|
|
.saturating_add(Weight::from_parts(0, 1505))
|
|
.saturating_add(RocksDbWeight::get().reads(4_u64))
|
|
.saturating_add(RocksDbWeight::get().writes(3_u64))
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod guard {
|
|
use super::*;
|
|
|
|
/// NINGUN EXTRINSIC PUEDE DECLARAR `proof_size = 0`.
|
|
///
|
|
/// El `proof_size` es lo que el block-builder usa para no pasarse del limite
|
|
/// de PoV. Un cero no dice «este extrinsic no toca storage»: dice «miento
|
|
/// sobre lo que va a ocupar la prueba», y con eso entra en un bloque mucho
|
|
/// mas de lo que cabe.
|
|
///
|
|
/// El test nace de un error propio y de la peor clase: la cabecera de los
|
|
/// weights interinos afirmaba que `T::DbWeight` «puebla tanto ref_time como
|
|
/// proof_size … cerrando el hueco». Es falso y se comprueba en la fuente —
|
|
/// `sp_weights::RuntimeDbWeight` solo tiene los campos `read` y `write`, y
|
|
/// `reads(r)` devuelve `Weight::from_parts(read * r, 0)`. Los interinos
|
|
/// arreglaron reads/writes y dejaron el proof_size donde estaba: en 0. La
|
|
/// afirmacion de haberlo cerrado sobrevivio mas de un mes sin que ninguna
|
|
/// lectura la desmintiera; la desmintio una medicion.
|
|
///
|
|
/// Esta lista la GENERA la plantilla a partir de los benchmarks reales, asi
|
|
/// que no puede quedarse corta cuando se anada un extrinsic nuevo.
|
|
#[test]
|
|
fn ningun_weight_declara_proof_size_cero() {
|
|
let casos: &[(&str, Weight)] = &[
|
|
("attest_asset", <() as WeightInfo>::attest_asset()),
|
|
("register_validator", <() as WeightInfo>::register_validator()),
|
|
("revoke_validator", <() as WeightInfo>::revoke_validator()),
|
|
];
|
|
for (nombre, w) in casos {
|
|
assert!(
|
|
w.proof_size() > 0,
|
|
"`{nombre}` declara proof_size = 0: miente al block-builder sobre el peso PoV"
|
|
);
|
|
assert!(
|
|
w.ref_time() > 0,
|
|
"`{nombre}` declara ref_time = 0: el extrinsic saldria gratis"
|
|
);
|
|
}
|
|
}
|
|
}
|