//! # Benchmarks para `pallet-origin-provenance` (FRAME v2) //! //! Fuente de verdad de la **forma** del weight de cada extrinsic. Los números //! canónicos se generan con `benchmark pallet` sobre HW de referencia (gated por //! el node sc-service / omni-bencher+WASM, ver `weights.rs` §Estado); mientras //! tanto, `SubstrateWeight` lleva números conservadores DB-aware. //! //! **Verificación sin HW**: `impl_benchmark_test_suite!` ejecuta cada benchmark //! una vez dentro del mock runtime (`cargo test -p origin-chain-provenance //! --features runtime-benchmarks`), probando que el harness corre y que el //! `verify` post-estado se cumple — el mismo camino que el CLI recorrerá luego. //! //! ## `attest_asset` sin firmar en no_std //! //! El benchmark no puede firmar Ed25519 (corre en no_std/wasm). Reusa los **golden //! vectors ASP-3** (payload postcard + firma constantes, keypair seed `[7u8;32]`, //! genesis `0xAB×32`) que ya prueban el fee-path en `tests_integration.rs`. El //! setup siembra `block_hash(0) = 0xAB×32` para que el dominio de la firma //! coincida, exactamente como `mock::new_test_ext_with_genesis`. #![cfg(feature = "runtime-benchmarks")] use super::*; use frame_benchmarking::v2::*; use frame_support::pallet_prelude::Decode; use frame_support::BoundedVec; // `sp-runtime` es dev-dep (no dep normal) → se accede vía el re-export de frame_support. use frame_support::sp_runtime::traits::Zero; use frame_system::pallet_prelude::BlockNumberFor; use frame_system::RawOrigin; use alloc::vec::Vec; /// Genesis de los golden vectors ASP-3 (`0xAB×32`). El pallet lee `block_hash(0)` /// para el dominio de la firma; el setup lo siembra con este valor. const GOLDEN_GENESIS: [u8; 32] = [0xABu8; 32]; /// Pubkey del validador golden (seed `[7u8;32]`). const GOLDEN_PUBKEY: [u8; 32] = [ 0xea, 0x4a, 0x6c, 0x63, 0xe2, 0x9c, 0x52, 0x0a, 0xbe, 0xf5, 0x50, 0x7b, 0x13, 0x2e, 0xc5, 0xf9, 0x95, 0x47, 0x76, 0xae, 0xbe, 0xbe, 0x7b, 0x92, 0x42, 0x1e, 0xea, 0x69, 0x14, 0x46, 0xd2, 0x2c, ]; /// PAYLOAD1: asset `[1×32]`, atelier level 3, Passed/Info → ANCLA (golden ASP-3). const PAYLOAD1: &str = "05312e302e300101010101010101010101010101010101010101010101010101010101010101146174656c6965725f63616e6f6e6963616c5f763103ea4a6c63e29c520abef5507b132ec5f9954776aebebe7b92421eea691446d22cd285d8cc0400002a"; /// SIG1: firma Ed25519 de PAYLOAD1 (dominio-separada con genesis `0xAB×32`). const SIG1: &str = "e155043ad90df787d73e8ba4c3ee961427ecb228637ade77e19bd9b57bb727dcdf3c247462aa8e6facf5697887f3e08f96af1c5f2fdcab10fcfbd2daabe73204"; /// Asset id anclado por PAYLOAD1 (para el `verify` post-estado). const PAYLOAD1_ASSET_ID: [u8; 32] = [1u8; 32]; fn hexval(c: u8) -> u8 { match c { b'0'..=b'9' => c - b'0', b'a'..=b'f' => c - b'a' + 10, b'A'..=b'F' => c - b'A' + 10, _ => 0, } } fn unhex(s: &str) -> Vec { let bytes = s.as_bytes(); let mut out = Vec::with_capacity(bytes.len() / 2); let mut i = 0; while i + 1 < bytes.len() { out.push((hexval(bytes[i]) << 4) | hexval(bytes[i + 1])); i += 2; } out } fn to_sig(s: &str) -> [u8; 64] { let v = unhex(s); let mut out = [0u8; 64]; out.copy_from_slice(&v[..64]); out } /// Siembra `block_hash(0) = 0xAB×32` para que la firma golden verifique. /// Asume `T::Hash = H256` (mock + runtime real), que es lo que exigen los vectores. fn seed_golden_genesis() { let genesis: T::Hash = Decode::decode(&mut &GOLDEN_GENESIS[..]).expect("H256 decodes from 32 bytes"); frame_system::BlockHash::::insert(BlockNumberFor::::zero(), genesis); } #[benchmarks] mod benchmarks { use super::*; #[benchmark] fn attest_asset() { let submitter: T::AccountId = whitelisted_caller(); seed_golden_genesis::(); // El validador golden debe estar registrado a nivel >= 3 (FIX-4 gate). Pallet::::register_validator(RawOrigin::Root.into(), GOLDEN_PUBKEY, 3) .expect("Root registra el validador golden"); let payload: BoundedVec = BoundedVec::try_from(unhex(PAYLOAD1)).expect("payload dentro de la cota"); let signature = to_sig(SIG1); #[extrinsic_call] attest_asset(RawOrigin::Signed(submitter), payload, signature); // Post-estado: la attestation quedó anclada bajo su asset_id BLAKE3. assert!(Attestations::::contains_key(AssetHash::new(PAYLOAD1_ASSET_ID))); } #[benchmark] fn register_validator() { let pubkey = GOLDEN_PUBKEY; #[extrinsic_call] register_validator(RawOrigin::Root, pubkey, 3u8); assert_eq!(AuthorizedValidators::::get(pubkey), Some(3u8)); } #[benchmark] fn revoke_validator() { let pubkey = GOLDEN_PUBKEY; AuthorizedValidators::::insert(pubkey, 3u8); #[extrinsic_call] revoke_validator(RawOrigin::Root, pubkey); assert!(AuthorizedValidators::::get(pubkey).is_none()); } impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test); }