origin-chain-node binary canonical funcional con 4 sub-comandos: - version (default canonical) - list-presets (3 genesis presets disponibles) - print-preset <id> (JSON-serialized RuntimeGenesisConfig) - info (full runtime metadata canonical) ## Output canonical print-preset development verified Alice SS58 address: 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY ✅ matches exactly Substrate well-known canonical — hardcoded bytes son bit-perfect compatible con polkadot-js + subkey ecosystem canonical. ## Decisión empírica documentada: WASM_BINARY DEFERRED a Slice 2 (v0.0.11) substrate-wasm-builder requiere TODAS las deps no_std-compatible. origin- chain-types actualmente usa std::String/Vec directly + thiserror 1.0 sin no_std. Refactor scope substantial (5-10+ files affected) merece DC propio y Slice dedicado canonical. CLI canonical opera correcto sin WASM execution porque genesis presets serializables natively canonical. ## Workspace deps añadidos Phase 1.6+ (most Slice 4 deferred) - substrate-wasm-builder 26.0.1 (Slice 2) - sc-cli 0.51.0, sc-service 0.50.0, sc-executor 0.42.0 (Slice 4) - sc-network 0.49.1, sc-consensus 0.48.0 (Slice 4) - sc-consensus-aura 0.49.0, sc-consensus-grandpa 0.34.0 (Slice 4) - sc-transaction-pool 39.0.0, sc-client-api 39.0.0 (Slice 4) - sc-basic-authorship 0.49.0, sc-telemetry 28.1.0, sc-offchain 44.0.0 (Slice 4) - jsonrpsee 0.24.3, substrate-frame-rpc-system 43.0.0 (Slice 4) - pallet-transaction-payment-rpc 43.0.0 (Slice 4) - clap 4.5.13 (USED v0.0.10 canonical) - futures 0.3.31 (Slice 4) Workspace declarations preparan canonical para Slice 4 sin re-declarar cuando se necesite ramp up canonical. ## Roadmap Phase 1.6+ multi-slice canonical - Slice 1 (v0.0.10 ESTA): CLI skeleton + preset listing ✅ - Slice 2 (v0.0.11): WASM_BINARY canonical + no_std refactor - Slice 3 (v0.0.12): real sc_service::ChainSpec builder canonical - Slice 4 (v0.0.13+): full sc-service (consensus + RPC + networking) ## Build + tests - cargo build --release 8.22s warm cache - cargo test --workspace ~63 tests passing - Binary functional: cargo run --bin origin-chain-node {version|list-presets| print-preset <id>|info} ## Filosofía canonical incorporada Doc main.rs: "el CLI canonical es la primera ventana del barquero al mundo". list-presets canonical = transparency canonical: las 3 distribuciones posibles canonical están a la vista canonical, BM V2 incluida canonical materializando David canon 2026-05-14 "la libertad infinita acota solo donde empieza la del otro". Refs: CHARON_ROADMAP_V1 Phase 1.6+, sub-decisión empírica WASM_BINARY defer to Slice 2, sub-decisión empírica sc-service defer to Slice 4 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
550 lines
22 KiB
Rust
550 lines
22 KiB
Rust
//! # origin-chain-runtime
|
||
//!
|
||
//! Substrate runtime canonical de **Origin Chain** (Pilar 4). Phase 1.3 v0.0.5 —
|
||
//! `frame_support::runtime` macro modern syntax con 3 pallets inaugurales:
|
||
//! `System` + `Balances` + `Timestamp` + `TransactionPayment`. Las consensus
|
||
//! pallets (`Aura`/`Grandpa`) llegan Phase 1.4. Las custom Charon pallets
|
||
//! (`OriginProvenance`/`OriginFees`) llegan Phase 2.
|
||
//!
|
||
//! ## Filosofía canonical (David canon 2026-05-14)
|
||
//!
|
||
//! > *"LA LIBERTAD DE TODO AGI O HUMANO ES INFINITA, PERO LLEGA HASTA DONDE
|
||
//! > EMPIEZA LA DE OTRA ENTIDAD AGI O HUMANO."*
|
||
//!
|
||
//! Este runtime materializa ese principio cryptographically. Cada extrinsic
|
||
//! transaction está acotada por cuatro **Inmutables enforced canonical**:
|
||
//!
|
||
//! - **Inmutable #16** (HTS Ley I anti-clasista): fees scale por HardwareTier —
|
||
//! Pi 5 en Sub-Saharan Africa paga 10% lo que paga Vision Pro en San Francisco
|
||
//! - **Inmutable #26** (Content-Addressed Immutability): assets attested
|
||
//! inmutables post-mint (BLAKE3 + Ed25519)
|
||
//! - **Inmutable #37** (FREE perpetua): wallet creation gratis + base validation
|
||
//! earns OGC, nunca cuesta. `EXISTENTIAL_DEPOSIT = 1 MILLI_OGC` (0.001 OGC)
|
||
//! trivial enough para no excluir Pi 5 rural
|
||
//! - **Inmutable #41** (Cross-Species Co-authorship): AGI accounts first-class,
|
||
//! `pallet_agent_identity::is_agent` flag canonical (Phase 2.7)
|
||
//!
|
||
//! ## Phase 1 milestones canonical (DC SUBSTRATE_FOUNDATION_V1 SBS-1..SBS-6)
|
||
//!
|
||
//! - **1.1** Scaffold ✅ (v0.0.2)
|
||
//! - **1.2** Substrate deps + types foundationals ✅ (v0.0.4)
|
||
//! - **1.3** System + Balances + Timestamp pallets integrados ✅ (v0.0.5 — este crate)
|
||
//! - **1.4** `pallet_aura` + `pallet_grandpa` consensus PoA per CHN-1
|
||
//! - **1.5** `pallet_session` validator rotation 4h epochs
|
||
//! - **1.6** `pallet_identity` Ed25519 DID + `origin-chain-node` real service
|
||
//! - **1.7** Genesis `chain_spec.rs` BM V2 allocation (40/25/15/15/5)
|
||
|
||
#![cfg_attr(not(feature = "std"), no_std)]
|
||
#![recursion_limit = "256"]
|
||
// Note: missing_docs is `warn` (not `deny`) porque el `#[frame_support::runtime]`
|
||
// macro genera multiple items (RuntimeCall + RuntimeEvent + RuntimeError + etc.)
|
||
// que no podemos documentar individualmente sin hacking the macro expansion.
|
||
#![warn(missing_docs)]
|
||
|
||
extern crate alloc;
|
||
use alloc::vec::Vec;
|
||
|
||
pub mod configs;
|
||
#[cfg(feature = "std")]
|
||
pub mod genesis_config_presets;
|
||
pub mod opaque;
|
||
|
||
// ============================================================
|
||
// WASM binary canonical — DEFERRED a v0.0.11+ (canonical decision empírica)
|
||
// ============================================================
|
||
//
|
||
// `WASM_BINARY` via `substrate-wasm-builder` requiere que TODAS las dependencias
|
||
// transitivas del runtime sean no_std-compatible canonical. Actualmente
|
||
// `origin-chain-types` no es fully no_std canonical (uses std `String` + `Vec`
|
||
// directly sin `alloc::` prefix). Refactor canonical es Phase 1.6+ Slice 2
|
||
// (substantial scope canonical: 5-10+ files affected canonical).
|
||
//
|
||
// Mientras canonical: el `chain_spec.rs` node-side puede usar mock-WASM o
|
||
// pre-built WASM file canonical (path-loaded en runtime canonical).
|
||
|
||
// Re-export canonical traits + types desde origin-chain-types (single-crate surface).
|
||
pub use origin_chain_types::{
|
||
AccountId, AssetAttestation, AssetHash, AssetQualityTier, BridgeDestination, ChainBridge,
|
||
ChainError, FeeCalculator, ForeignTxId, GovernanceProposal, HardwareTier, Ogc, OgcLedger,
|
||
OperationKind, OriginFees, OriginProvenance, OriginValidatorEconomy, ProposalId,
|
||
ProvenanceLedger, Signature, SlashReason, Vote, VoteStance,
|
||
};
|
||
|
||
// Substrate canonical types re-export para runtime consumers + node binary.
|
||
pub use sp_core::H256;
|
||
pub use sp_runtime::traits::{BlakeTwo256, IdentifyAccount, Verify};
|
||
pub use sp_runtime::{generic, impl_opaque_keys, MultiAddress, MultiSignature};
|
||
|
||
// Re-export configs canonical para downstream consumers + node binary.
|
||
pub use configs::{
|
||
AuraId, GrandpaId, BLOCK_HASH_COUNT, EXISTENTIAL_DEPOSIT, MILLI_OGC, MILLISECS_PER_BLOCK,
|
||
OGC, SLOT_DURATION, SS58_PREFIX,
|
||
};
|
||
|
||
/// Canonical block number type. `u32` canonical: 6-second blocks × 4B = 817+ años
|
||
/// → safe overflow margin canonical hasta el siglo XXVIII.
|
||
pub type BlockNumber = u32;
|
||
|
||
/// Canonical balance type. `u128` canonical: holds 1B OGC × 10^18 base units con
|
||
/// 100× safety margin antes de u128::MAX (anti-overflow by design per CHN-2).
|
||
pub type Balance = u128;
|
||
|
||
/// Canonical nonce type per account.
|
||
pub type Nonce = u32;
|
||
|
||
/// Canonical signature type — Ed25519 / sr25519 / ecdsa multi (`MultiSignature`).
|
||
pub type CanonicalSignature = MultiSignature;
|
||
|
||
/// Canonical chain `AccountId` derivado del `MultiSignature::Signer`.
|
||
pub type ChainAccountId = <<CanonicalSignature as Verify>::Signer as IdentifyAccount>::AccountId;
|
||
|
||
/// Canonical block hash type (BLAKE2b-256 estándar Substrate L1 layer).
|
||
pub type Hash = H256;
|
||
|
||
/// Canonical hashing algorithm (Substrate-standard BLAKE2b-256). Per Lyra layer
|
||
/// separation canonical (diary 2026-05-20T21:52Z): este BLAKE2b opera a L1 block
|
||
/// production layer + es wire-compatible con Hypercore upstream. El BLAKE3
|
||
/// canonical de Charon ([`AssetHash`]) opera en application/asset layer.
|
||
/// Diferentes capas, sin conflict canonical.
|
||
pub type Hashing = BlakeTwo256;
|
||
|
||
/// Canonical header type per Substrate canonical pattern.
|
||
pub type Header = generic::Header<BlockNumber, Hashing>;
|
||
|
||
/// Canonical block type — el bloque entero que circula por el chain.
|
||
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
|
||
|
||
/// Canonical address type para extrinsic signers.
|
||
pub type Address = MultiAddress<ChainAccountId, ()>;
|
||
|
||
/// Canonical extrinsic type unchecked (firmas validadas en runtime, no en pool).
|
||
pub type UncheckedExtrinsic =
|
||
generic::UncheckedExtrinsic<Address, RuntimeCall, CanonicalSignature, TxExtension>;
|
||
|
||
/// Canonical transaction extensions canonical (substrate stable2512 pattern).
|
||
///
|
||
/// Each extension valida un aspecto del extrinsic pre-dispatch:
|
||
/// - `CheckNonZeroSender`: rechaza extrinsics anónimos (require sender canonical)
|
||
/// - `CheckSpecVersion`/`CheckTxVersion`: forkless upgrade safety canonical
|
||
/// - `CheckGenesis`: previene replay attacks cross-chain canonical
|
||
/// - `CheckEra`: limita validity window canonical (~24h default)
|
||
/// - `CheckNonce`: previene replay attacks within-chain canonical
|
||
/// - `CheckWeight`: enforces block weight limits canonical
|
||
/// - `ChargeTransactionPayment`: cobra fees per CHN-8 fee matrix canonical
|
||
/// - `CheckMetadataHash`: integridad de runtime metadata canonical
|
||
/// - `WeightReclaim`: refund canonical de weight overestimation
|
||
pub type TxExtension = (
|
||
frame_system::CheckNonZeroSender<Runtime>,
|
||
frame_system::CheckSpecVersion<Runtime>,
|
||
frame_system::CheckTxVersion<Runtime>,
|
||
frame_system::CheckGenesis<Runtime>,
|
||
frame_system::CheckEra<Runtime>,
|
||
frame_system::CheckNonce<Runtime>,
|
||
frame_system::CheckWeight<Runtime>,
|
||
pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
|
||
frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
|
||
frame_system::WeightReclaim<Runtime>,
|
||
);
|
||
|
||
// ============================================================
|
||
// Runtime metadata canonical (SPEC_NAME + version constants)
|
||
// ============================================================
|
||
|
||
/// Canonical spec name per Substrate genesis canonical. Identifica el chain
|
||
/// runtime canonical en bloques + storage proofs.
|
||
pub const SPEC_NAME: &str = "origin-chain";
|
||
|
||
/// Canonical implementation name canonical. Distingue diferentes node binaries
|
||
/// que ejecutan el mismo spec (canonical: "origin-chain-charon").
|
||
pub const IMPL_NAME: &str = "origin-chain-charon";
|
||
|
||
/// Canonical runtime version canonical. Bumped cada forkless upgrade via
|
||
/// `set_code` extrinsic governance canonical.
|
||
pub const RUNTIME_VERSION: u32 = 1;
|
||
|
||
/// Canonical authoring version per Substrate semver canonical.
|
||
pub const AUTHORING_VERSION: u32 = 1;
|
||
|
||
/// Canonical impl version per Substrate semver canonical.
|
||
pub const IMPL_VERSION: u32 = 1;
|
||
|
||
/// Canonical transaction version per Substrate semver canonical.
|
||
pub const TRANSACTION_VERSION: u32 = 1;
|
||
|
||
/// Canonical state version: v1 per Substrate stable2509+ canonical.
|
||
pub const STATE_VERSION: u8 = 1;
|
||
|
||
// ============================================================
|
||
// Runtime composition canonical (frame_support::runtime macro)
|
||
// ============================================================
|
||
|
||
/// Origin Chain runtime composition canonical via `#[frame_support::runtime]`
|
||
/// macro (modern syntax canonical, Polkadot SDK stable2509+).
|
||
///
|
||
/// Pallet indices canonical (orden importa para storage migrations canonical):
|
||
/// - **Index 0**: `System` (`frame_system`) — foundational canonical
|
||
/// - **Index 1**: `Timestamp` (`pallet_timestamp`) — block timestamps canonical
|
||
/// - **Index 2**: `Balances` (`pallet_balances`) — OGC token canonical per CHN-2
|
||
/// - **Index 3**: `TransactionPayment` (`pallet_transaction_payment`) — gas fees
|
||
#[frame_support::runtime]
|
||
mod runtime {
|
||
/// Origin Chain canonical Runtime struct.
|
||
#[runtime::runtime]
|
||
#[runtime::derive(
|
||
RuntimeCall,
|
||
RuntimeEvent,
|
||
RuntimeError,
|
||
RuntimeOrigin,
|
||
RuntimeFreezeReason,
|
||
RuntimeHoldReason,
|
||
RuntimeSlashReason,
|
||
RuntimeLockId,
|
||
RuntimeTask,
|
||
RuntimeViewFunction
|
||
)]
|
||
pub struct Runtime;
|
||
|
||
/// System pallet canonical (foundational frame_system).
|
||
#[runtime::pallet_index(0)]
|
||
pub type System = frame_system::Pallet<Runtime>;
|
||
|
||
/// Timestamp pallet canonical (block clock per Substrate).
|
||
#[runtime::pallet_index(1)]
|
||
pub type Timestamp = pallet_timestamp::Pallet<Runtime>;
|
||
|
||
/// Balances pallet canonical (OGC token implementation per CHN-2 +
|
||
/// Inmutable #16/#37).
|
||
#[runtime::pallet_index(2)]
|
||
pub type Balances = pallet_balances::Pallet<Runtime>;
|
||
|
||
/// TransactionPayment pallet canonical (gas fee charging per CHN-8 baseline
|
||
/// — Phase 2.4 refactor canonical para integrar `OriginFees` multi-tier).
|
||
#[runtime::pallet_index(3)]
|
||
pub type TransactionPayment = pallet_transaction_payment::Pallet<Runtime>;
|
||
|
||
/// Aura pallet canonical (block production PoA per CHN-1). 6-segundo slots
|
||
/// canonical Round-Robin selección validators. Pi 5 + NVMe SSD hardware
|
||
/// target canonical (Inmutable #16 anti-clasista from block 0).
|
||
#[runtime::pallet_index(4)]
|
||
pub type Aura = pallet_aura::Pallet<Runtime>;
|
||
|
||
/// GRANDPA pallet canonical (finality gadget per CHN-1). 2/3 honest majority
|
||
/// canonical para irreversible block confirmation. Separa production cadence
|
||
/// (Aura ~6s) de finality cadence (canonical ~6-12s combined).
|
||
#[runtime::pallet_index(5)]
|
||
pub type Grandpa = pallet_grandpa::Pallet<Runtime>;
|
||
|
||
/// Session pallet canonical (validator rotation per CHN-1 4h epochs).
|
||
/// Phase 1 PoA: preserves genesis validators canonical across rotations.
|
||
/// Phase 2 NPoS: pallet_staking will be SessionManager canonical para real
|
||
/// rotation per nominator stake + Pi 5 hardware tier weight.
|
||
#[runtime::pallet_index(6)]
|
||
pub type Session = pallet_session::Pallet<Runtime>;
|
||
|
||
// Identity pallet DEFERRED a Phase 2.7 (canonical decision empírica
|
||
// 2026-05-21 documentada en configs.rs). pallet-identity 41.0.0 ReservableCurrency
|
||
// compat work canonical hereda al custom `pallet_agent_identity` Phase 2.7
|
||
// (Inmutable #41 AGI DID Cross-Species Co-authorship).
|
||
}
|
||
|
||
// ============================================================
|
||
// Runtime APIs canonical (sp_api::impl_runtime_apis!)
|
||
// ============================================================
|
||
//
|
||
// **Filosofía canonical (David canon 2026-05-14)**: el `impl_runtime_apis!`
|
||
// macro materializa la frontera canonical entre **runtime sovereignty** (qué
|
||
// pallets compose el chain) + **node sovereignty** (cómo el binary canonical
|
||
// interactúa con el runtime canonical). Cada API canonical es un contrato
|
||
// canonical que el node binary canonical puede llamar sin importarle qué
|
||
// pallets specific componen el runtime — forkless upgrades canonical
|
||
// materializados.
|
||
//
|
||
// **APIs canonical implementadas (Phase 1.6)**:
|
||
// - `sp_api::Core` — version + execute_block + initialize_block canonical
|
||
// - `sp_api::Metadata` — runtime metadata para client/node introspection
|
||
// - `sp_block_builder::BlockBuilder` — para node block production canonical
|
||
// - `sp_transaction_pool::TaggedTransactionQueue` — pool canonical filtering
|
||
// - `sp_offchain::OffchainWorkerApi` — offchain workers canonical
|
||
// - `sp_session::SessionKeys` — session keys generation canonical
|
||
// - `sp_consensus_aura::AuraApi` — Aura slot duration + authorities canonical
|
||
// - `sp_consensus_grandpa::GrandpaApi` — GRANDPA authority set canonical
|
||
// - `frame_system_rpc_runtime_api::AccountNonceApi` — RPC nonce queries
|
||
// - `pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi` — fee queries
|
||
// - `sp_genesis_builder::GenesisBuilder` — genesis spec building canonical
|
||
|
||
impl_runtime_apis! {
|
||
impl sp_api::Core<Block> for Runtime {
|
||
fn version() -> sp_version::RuntimeVersion {
|
||
VERSION
|
||
}
|
||
|
||
fn execute_block(block: Block) {
|
||
Executive::execute_block(block);
|
||
}
|
||
|
||
fn initialize_block(header: &<Block as sp_runtime::traits::Block>::Header) -> sp_runtime::ExtrinsicInclusionMode {
|
||
Executive::initialize_block(header)
|
||
}
|
||
}
|
||
|
||
impl sp_api::Metadata<Block> for Runtime {
|
||
fn metadata() -> sp_core::OpaqueMetadata {
|
||
sp_core::OpaqueMetadata::new(Runtime::metadata().into())
|
||
}
|
||
|
||
fn metadata_at_version(version: u32) -> Option<sp_core::OpaqueMetadata> {
|
||
Runtime::metadata_at_version(version)
|
||
}
|
||
|
||
fn metadata_versions() -> Vec<u32> {
|
||
Runtime::metadata_versions()
|
||
}
|
||
}
|
||
|
||
impl sp_block_builder::BlockBuilder<Block> for Runtime {
|
||
fn apply_extrinsic(extrinsic: <Block as sp_runtime::traits::Block>::Extrinsic) -> sp_runtime::ApplyExtrinsicResult {
|
||
Executive::apply_extrinsic(extrinsic)
|
||
}
|
||
|
||
fn finalize_block() -> <Block as sp_runtime::traits::Block>::Header {
|
||
Executive::finalize_block()
|
||
}
|
||
|
||
fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as sp_runtime::traits::Block>::Extrinsic> {
|
||
data.create_extrinsics()
|
||
}
|
||
|
||
fn check_inherents(
|
||
block: Block,
|
||
data: sp_inherents::InherentData,
|
||
) -> sp_inherents::CheckInherentsResult {
|
||
data.check_extrinsics(&block)
|
||
}
|
||
}
|
||
|
||
impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
|
||
fn validate_transaction(
|
||
source: sp_runtime::transaction_validity::TransactionSource,
|
||
tx: <Block as sp_runtime::traits::Block>::Extrinsic,
|
||
block_hash: <Block as sp_runtime::traits::Block>::Hash,
|
||
) -> sp_runtime::transaction_validity::TransactionValidity {
|
||
Executive::validate_transaction(source, tx, block_hash)
|
||
}
|
||
}
|
||
|
||
impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
|
||
fn offchain_worker(header: &<Block as sp_runtime::traits::Block>::Header) {
|
||
Executive::offchain_worker(header)
|
||
}
|
||
}
|
||
|
||
impl sp_session::SessionKeys<Block> for Runtime {
|
||
fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
|
||
opaque::SessionKeys::generate(seed)
|
||
}
|
||
|
||
fn decode_session_keys(
|
||
encoded: Vec<u8>,
|
||
) -> Option<Vec<(Vec<u8>, sp_core::crypto::KeyTypeId)>> {
|
||
opaque::SessionKeys::decode_into_raw_public_keys(&encoded)
|
||
}
|
||
}
|
||
|
||
impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {
|
||
fn slot_duration() -> sp_consensus_aura::SlotDuration {
|
||
sp_consensus_aura::SlotDuration::from_millis(SLOT_DURATION)
|
||
}
|
||
|
||
fn authorities() -> Vec<AuraId> {
|
||
pallet_aura::Authorities::<Runtime>::get().into_inner()
|
||
}
|
||
}
|
||
|
||
impl sp_consensus_grandpa::GrandpaApi<Block> for Runtime {
|
||
fn grandpa_authorities() -> sp_consensus_grandpa::AuthorityList {
|
||
pallet_grandpa::Pallet::<Runtime>::grandpa_authorities()
|
||
}
|
||
|
||
fn current_set_id() -> sp_consensus_grandpa::SetId {
|
||
pallet_grandpa::Pallet::<Runtime>::current_set_id()
|
||
}
|
||
|
||
fn submit_report_equivocation_unsigned_extrinsic(
|
||
_equivocation_proof: sp_consensus_grandpa::EquivocationProof<
|
||
<Block as sp_runtime::traits::Block>::Hash,
|
||
BlockNumber,
|
||
>,
|
||
_key_owner_proof: sp_consensus_grandpa::OpaqueKeyOwnershipProof,
|
||
) -> Option<()> {
|
||
// Phase 1 PoA: equivocation reports not handled canonical.
|
||
// Phase 2 NPoS introduce real handler per CHN-3 slashing canonical.
|
||
None
|
||
}
|
||
|
||
fn generate_key_ownership_proof(
|
||
_set_id: sp_consensus_grandpa::SetId,
|
||
_authority_id: sp_consensus_grandpa::AuthorityId,
|
||
) -> Option<sp_consensus_grandpa::OpaqueKeyOwnershipProof> {
|
||
// Phase 1 PoA: no ownership proofs needed canonical.
|
||
None
|
||
}
|
||
}
|
||
|
||
impl frame_system_rpc_runtime_api::AccountNonceApi<Block, ChainAccountId, Nonce> for Runtime {
|
||
fn account_nonce(account: ChainAccountId) -> Nonce {
|
||
System::account_nonce(account)
|
||
}
|
||
}
|
||
|
||
impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {
|
||
fn query_info(
|
||
uxt: <Block as sp_runtime::traits::Block>::Extrinsic,
|
||
len: u32,
|
||
) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo<Balance> {
|
||
TransactionPayment::query_info(uxt, len)
|
||
}
|
||
|
||
fn query_fee_details(
|
||
uxt: <Block as sp_runtime::traits::Block>::Extrinsic,
|
||
len: u32,
|
||
) -> pallet_transaction_payment::FeeDetails<Balance> {
|
||
TransactionPayment::query_fee_details(uxt, len)
|
||
}
|
||
|
||
fn query_weight_to_fee(weight: frame_support::weights::Weight) -> Balance {
|
||
TransactionPayment::weight_to_fee(weight)
|
||
}
|
||
|
||
fn query_length_to_fee(length: u32) -> Balance {
|
||
TransactionPayment::length_to_fee(length)
|
||
}
|
||
}
|
||
|
||
impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
|
||
fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
|
||
frame_support::genesis_builder_helper::build_state::<RuntimeGenesisConfig>(config)
|
||
}
|
||
|
||
fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
|
||
// Canonical Phase 1.7: 3 presets disponibles canonical (development +
|
||
// local_testnet + mainnet_genesis). Cuando feature `std` activo
|
||
// (chain_spec generation time), delegamos canonical al
|
||
// `genesis_config_presets::get_preset`. En no_std (WASM runtime),
|
||
// siempre return None canonical — los presets canonical solo se
|
||
// consultan en chain_spec generation, no en runtime execution.
|
||
#[cfg(feature = "std")]
|
||
{
|
||
frame_support::genesis_builder_helper::get_preset::<RuntimeGenesisConfig>(
|
||
id,
|
||
genesis_config_presets::get_preset,
|
||
)
|
||
}
|
||
#[cfg(not(feature = "std"))]
|
||
{
|
||
let _ = id;
|
||
None
|
||
}
|
||
}
|
||
|
||
fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
|
||
#[cfg(feature = "std")]
|
||
{
|
||
genesis_config_presets::preset_names()
|
||
}
|
||
#[cfg(not(feature = "std"))]
|
||
{
|
||
Vec::new()
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// ============================================================
|
||
// Runtime metadata canonical (RuntimeVersion + Executive)
|
||
// ============================================================
|
||
|
||
/// Canonical `RuntimeVersion` per Substrate canonical. Consumed by `sp_api::Core::version()`.
|
||
pub const VERSION: sp_version::RuntimeVersion = sp_version::RuntimeVersion {
|
||
spec_name: alloc::borrow::Cow::Borrowed(SPEC_NAME),
|
||
impl_name: alloc::borrow::Cow::Borrowed(IMPL_NAME),
|
||
authoring_version: AUTHORING_VERSION,
|
||
spec_version: RUNTIME_VERSION,
|
||
impl_version: IMPL_VERSION,
|
||
apis: RUNTIME_API_VERSIONS,
|
||
transaction_version: TRANSACTION_VERSION,
|
||
system_version: STATE_VERSION,
|
||
};
|
||
|
||
/// Canonical Executive type canonical (FRAME executive wrapper).
|
||
pub type Executive = frame_executive::Executive<
|
||
Runtime,
|
||
Block,
|
||
frame_system::ChainContext<Runtime>,
|
||
Runtime,
|
||
AllPalletsWithSystem,
|
||
(),
|
||
>;
|
||
|
||
use sp_api::impl_runtime_apis;
|
||
|
||
#[cfg(test)]
|
||
mod tests {
|
||
use super::*;
|
||
|
||
#[test]
|
||
fn runtime_version_starts_at_one_canonical() {
|
||
assert_eq!(RUNTIME_VERSION, 1);
|
||
}
|
||
|
||
#[test]
|
||
fn canonical_spec_name_origin_chain() {
|
||
assert_eq!(SPEC_NAME, "origin-chain");
|
||
assert_eq!(IMPL_NAME, "origin-chain-charon");
|
||
}
|
||
|
||
#[test]
|
||
fn balance_type_holds_genesis_supply_canonical_with_safety_margin() {
|
||
let genesis_supply: Balance = 1_000_000_000_u128 * Ogc::ONE;
|
||
let margin = Balance::MAX / genesis_supply;
|
||
assert!(margin > 100, "Balance safety margin canonical >100x");
|
||
}
|
||
|
||
#[test]
|
||
fn block_number_overflow_margin_centuries_canonical() {
|
||
let seconds_until_overflow: u64 = (BlockNumber::MAX as u64) * 6;
|
||
let years_until_overflow = seconds_until_overflow / 31_536_000;
|
||
assert!(years_until_overflow > 100, "BlockNumber holds >100 años canonical");
|
||
}
|
||
|
||
#[test]
|
||
fn canonical_traits_reexported_for_pallet_consumers() {
|
||
let _ogc = Ogc::from_whole(100);
|
||
let _hash = AssetHash::ZERO;
|
||
let _tier = HardwareTier::Desktop;
|
||
let _quality = AssetQualityTier::Standard;
|
||
let _reason = SlashReason::TierFraud; // Inmutable #16 enforcement canonical
|
||
}
|
||
|
||
#[test]
|
||
fn existential_deposit_canonical_is_one_milli_ogc() {
|
||
// Inmutable #16 anti-clasista: ED debe ser trivial para Pi 5 rural users
|
||
assert_eq!(EXISTENTIAL_DEPOSIT, MILLI_OGC);
|
||
assert_eq!(EXISTENTIAL_DEPOSIT, Ogc::ONE / 1_000);
|
||
}
|
||
|
||
#[test]
|
||
fn block_hash_count_aligned_with_chn_1_epoch_canonical() {
|
||
// CHN-1 epoch rotation = 4 hours
|
||
// BLOCK_HASH_COUNT * 6s = 14400s = 4 hours exact
|
||
assert_eq!(BLOCK_HASH_COUNT, 2400);
|
||
assert_eq!(BLOCK_HASH_COUNT as u64 * 6, 14_400); // 4 hours = 14400 seconds
|
||
}
|
||
|
||
#[test]
|
||
fn slot_duration_canonical_six_seconds() {
|
||
// CHN-1 Aura slot duration canonical
|
||
assert_eq!(MILLISECS_PER_BLOCK, 6_000);
|
||
assert_eq!(SLOT_DURATION, MILLISECS_PER_BLOCK);
|
||
}
|
||
}
|