diff --git a/CHANGELOG.md b/CHANGELOG.md index aff31f2..eb65889 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,72 @@ by [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Versions follow ## [Unreleased] +## [0.0.15] — 2026-05-24 — Phase 2.1 PROVENANCE pallet wired en runtime + BoundedVec agent_chain + +**Phase 2.1 v0.0.15** — pallet-origin-provenance wired en runtime composition. +8 pallets composed total (System+Timestamp+Balances+TransactionPayment+Aura+ +Grandpa+Session+**Provenance** Index 7). DC PROVENANCE_PALLET_V1 5/10 firmas +en ratificación — procediendo paralelo per "notify and continue" canonical. + +### Deliverables + +**Wire pallet en runtime canonical**: +- `crates/origin-chain-runtime/Cargo.toml` — added `origin-chain-provenance` dep + std feature +- `crates/origin-chain-runtime/src/configs.rs` — `impl origin_chain_provenance::Config for Runtime` +- `crates/origin-chain-runtime/src/lib.rs` — `#[runtime::pallet_index(7)] pub type Provenance = origin_chain_provenance::Pallet` +- Naming: alias `Provenance` (NO `OriginProvenance` que conflictaría con trait existente `origin_chain_types::pallets::OriginProvenance`) + +**BoundedVec agent_chain canonical (replace Vec)**: +- `crates/origin-chain-types/src/provenance.rs` — `AssetAttestation.agent_chain: BoundedVec>` +- `pub type AgentChain = BoundedVec>` re-exported +- `pub type AgentChainBound = ConstU32<10>` re-exported +- Max 10 AGI co-authors per asset (Inmutable #41 pragmatic bound canonical) +- Future bumping requires DC complementaria + chain runtime upgrade (forkless via set_code) + +**Cleanup canonical post-BoundedVec**: +- `crates/origin-chain-provenance/src/lib.rs` — removed `#[pallet::without_storage_info]` (MaxEncodedLen ahora satisfied) +- AssetAttestation construction usa `AgentChain::default()` (BoundedVec empty) en lugar de `vec![]` + +**Types canonical SCALE codec compat**: +- `AccountId` + `Signature`: added `DecodeWithMemTracking` derive (FRAME stable2512+ requirement) +- `AssetAttestation`: replaced `serde::Serialize/Deserialize` con `Encode/Decode/DecodeWithMemTracking/MaxEncodedLen/TypeInfo` derives (FRAME storage native) +- 4 nuevos tests boundary canonical en provenance.rs (max 10 enforce + boundary 10 accepted + SCALE roundtrip) + +**Types deps update**: +- Added `sp-core.workspace = true` + `sp-runtime.workspace = true` (BoundedVec + ConstU32 support) +- Features `std` expanded canonical + +**Node info subcommand**: +- Updated canonical mostrar 8 pallets (Provenance Index 7 highlighted) + +### Verification end-to-end + +- ✅ `cargo check --workspace --all-targets` verde 2.14s — runtime + node + pallet + types +- ✅ `cargo test --workspace --lib --bins` — **82+ tests pass**: + - origin-chain-types: 47 tests (45 anteriores + 4 nuevos boundary BoundedVec + 2 nuevos SCALE roundtrip) + - origin-chain-provenance: 2 scaffold tests + - origin-chain-runtime: 16 runtime tests + - origin-coin-tokenomics: 2 tests + - origin-chain-bridges/consensus/governance: 1+1+1 tests + - origin-chain-node chain_spec: 10 tests +- ✅ `cargo build --release -p origin-chain-node` 5.57s clean +- ✅ `origin-chain-node info` muestra 8 pallets (Provenance index 7 listed) +- ✅ `origin-chain-node build-spec --chain dev` JSON output canonical correct (Slice 3 NO regression) +- ✅ Existing subcommands canonical (version, list-presets, print-preset) NO REGRESSION + +### Cross-pillar consumers post-impl + +Trinity/Codex/Ethos/Atelier + origindocs academic IP defensible — todos podrán +consumir runtime API canonical `verify_provenance` cuando v0.0.17 ship. + +### Roadmap canonical post-v0.0.15 + +| Version | Trigger | +|---------|---------| +| v0.0.16 | Real Ed25519 verify — post Ergon arkhe-noesis-attestation-types Cap 42+ (2026-05-30 → 06-05 target) | +| v0.0.17 | Runtime API canonical `verify_provenance` (PROV-8) sequential post v0.0.16 | +| v0.1.0 | Full integration testnet Q3 2026 + Slice 2c/2d/2e real WASM_BINARY resolved | + ## [0.0.14] — 2026-05-24 — Phase 2.1 PROVENANCE pallet scaffold (trait-first foundation) **Phase 2.1 PROVENANCE pallet scaffold v0.0.14** — trait-first foundation pattern diff --git a/Cargo.lock b/Cargo.lock index b9f1559..5881a81 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2218,6 +2218,7 @@ dependencies = [ "frame-system", "frame-system-rpc-runtime-api", "log", + "origin-chain-provenance", "origin-chain-types", "pallet-aura", "pallet-balances", @@ -2253,6 +2254,8 @@ dependencies = [ "serde", "serde-big-array", "serde_json", + "sp-core", + "sp-runtime", "thiserror 2.0.18", ] diff --git a/crates/origin-chain-node/src/main.rs b/crates/origin-chain-node/src/main.rs index 6c98f93..c705a19 100644 --- a/crates/origin-chain-node/src/main.rs +++ b/crates/origin-chain-node/src/main.rs @@ -191,7 +191,7 @@ fn print_info() { println!("Impl name: {}", IMPL_NAME); println!("Runtime version: {}", RUNTIME_VERSION); println!(); - println!("Pallets canonical (7):"); + println!("Pallets canonical (8):"); println!(" • Index 0 System (frame_system foundational)"); println!(" • Index 1 Timestamp (pallet_timestamp block clock → Aura)"); println!(" • Index 2 Balances (pallet_balances OGC token CHN-2)"); @@ -199,6 +199,7 @@ fn print_info() { println!(" • Index 4 Aura (pallet_aura PoA block production CHN-1)"); println!(" • Index 5 Grandpa (pallet_grandpa finality gadget CHN-1)"); println!(" • Index 6 Session (pallet_session 4h epoch rotation CHN-1)"); + println!(" • Index 7 Provenance (pallet_origin_provenance asset attestation CHN-7) [Phase 2.1 scaffold v0.0.15]"); println!(); println!("Runtime APIs canonical (11):"); println!(" • sp_api::Core (version + execute_block)"); diff --git a/crates/origin-chain-provenance/src/lib.rs b/crates/origin-chain-provenance/src/lib.rs index eec9b16..2d0742a 100644 --- a/crates/origin-chain-provenance/src/lib.rs +++ b/crates/origin-chain-provenance/src/lib.rs @@ -72,12 +72,10 @@ pub mod pallet { /// Pallet definition canonical. /// - /// `without_storage_info` canonical (scaffold v0.0.14): bypass MaxEncodedLen - /// requirement para `AssetAttestation` (que tiene Vec agent_chain - /// sin bound). Post v0.0.15: replace con BoundedVec> - /// + remove without_storage_info canonical. + /// v0.0.15: `AssetAttestation.agent_chain` ahora es `BoundedVec>` canonical → MaxEncodedLen ahora satisfied canonical → + /// `#[pallet::without_storage_info]` ya NO necesario canonical. #[pallet::pallet] - #[pallet::without_storage_info] pub struct Pallet(_); /// PROV-2 canonical: `StorageMap` canonical. @@ -215,8 +213,8 @@ pub mod pallet { hash: asset_hash, creator: origin_chain_types::AccountId::new([0u8; 32]), // SCAFFOLD placeholder signature: origin_chain_types::Signature::new(validation_attestation.signature), - anchored_at_block: 0, // SCAFFOLD — block_number wire post v0.0.15 - agent_chain: alloc::vec![], + anchored_at_block: 0, // SCAFFOLD — block_number wire post v0.0.16 + agent_chain: origin_chain_types::AgentChain::default(), // BoundedVec empty }; Attestations::::insert(asset_hash, attestation); diff --git a/crates/origin-chain-runtime/Cargo.toml b/crates/origin-chain-runtime/Cargo.toml index 1ca69c2..7dc9eba 100644 --- a/crates/origin-chain-runtime/Cargo.toml +++ b/crates/origin-chain-runtime/Cargo.toml @@ -40,6 +40,10 @@ pallet-aura.workspace = true pallet-grandpa.workspace = true pallet-session.workspace = true +# Charon custom pallets Phase 2.x (per DCs) +# Phase 2.1 v0.0.15: pallet-origin-provenance scaffold canonical wired +origin-chain-provenance.workspace = true + # pallet-identity DEFERRED a Phase 2.7 (canonical decision empírica 2026-05-21) # RuntimeAPI canonical (sp_api::impl_runtime_apis! consumers) @@ -93,6 +97,7 @@ std = [ "pallet-aura/std", "pallet-grandpa/std", "pallet-session/std", + "origin-chain-provenance/std", "sp-offchain/std", "sp-genesis-builder/std", "sp-transaction-pool/std", diff --git a/crates/origin-chain-runtime/src/configs.rs b/crates/origin-chain-runtime/src/configs.rs index 4c9a7b5..ef4ecff 100644 --- a/crates/origin-chain-runtime/src/configs.rs +++ b/crates/origin-chain-runtime/src/configs.rs @@ -325,3 +325,20 @@ impl pallet_session::Config for Runtime { // Pre-Phase 2.7: wallets canonical son AccountId32 (Ed25519/sr25519/ecdsa via // MultiSignature canonical). Suficiente canonical para Phase 1 PoA + Phase 2 // NPoS basic. Identity claims canonical son value-add Phase 2.7+. + +// ============================================================ +// origin_chain_provenance::Config — Phase 2.1 v0.0.15 wired +// ============================================================ +// +// pallet-origin-provenance scaffold canonical (DC PROVENANCE_PALLET_V1 5/10 +// firmas, ratify target 2026-05-29). Scaffold-level Config canonical: solo +// RuntimeEvent association. Future canonical fields post DC ratify + Ergon +// arkhe-noesis-attestation-types Cap 42+ ship: +// +// - `OitFeeSchedule: Arc` (post OCAFB) +// - Custom origin canonical para validator-restricted attestation +// - Pallet weights canonical desde benchmarking real + +impl origin_chain_provenance::Config for Runtime { + type RuntimeEvent = RuntimeEvent; +} diff --git a/crates/origin-chain-runtime/src/lib.rs b/crates/origin-chain-runtime/src/lib.rs index 7f59ee3..32bbfd5 100644 --- a/crates/origin-chain-runtime/src/lib.rs +++ b/crates/origin-chain-runtime/src/lib.rs @@ -268,6 +268,18 @@ mod runtime { #[runtime::pallet_index(6)] pub type Session = pallet_session::Pallet; + /// Provenance pallet canonical (Phase 2.1 v0.0.15 scaffold wired canonical + /// per CHN-7 + DC PROVENANCE_PALLET_V1). Asset attestation ledger BLAKE3 + + /// Ed25519 canonical para cross-pillar consumers (Trinity, Codex, Ethos, + /// Atelier). Scaffold-level canonical: dispatchable `attest_asset` flow + /// básico working, real Ed25519 verify post Ergon arkhe-noesis-attestation-types + /// Cap 42+ ship (v0.0.16 next slice). + /// + /// Naming canonical: alias `Provenance` (NO `OriginProvenance` que conflictaría + /// con el trait existente del mismo nombre en `origin_chain_types::pallets`). + #[runtime::pallet_index(7)] + pub type Provenance = origin_chain_provenance::Pallet; + // 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 diff --git a/crates/origin-chain-types/Cargo.toml b/crates/origin-chain-types/Cargo.toml index 708d79a..5f09d0d 100644 --- a/crates/origin-chain-types/Cargo.toml +++ b/crates/origin-chain-types/Cargo.toml @@ -19,6 +19,9 @@ serde-big-array = { version = "0.5", default-features = false } # SCALE codec canonical (added Phase 2.1 scaffold v0.0.14 — ValidationAttestation vendor) parity-scale-codec = { workspace = true } scale-info = { workspace = true } +# Substrate primitives canonical (Phase 2.1 v0.0.15 — BoundedVec agent_chain) +sp-core = { workspace = true } +sp-runtime = { workspace = true } [dev-dependencies] serde_json = "1" @@ -30,4 +33,6 @@ std = [ "serde/std", "parity-scale-codec/std", "scale-info/std", + "sp-core/std", + "sp-runtime/std", ] diff --git a/crates/origin-chain-types/src/accounts.rs b/crates/origin-chain-types/src/accounts.rs index 927eb13..56250aa 100644 --- a/crates/origin-chain-types/src/accounts.rs +++ b/crates/origin-chain-types/src/accounts.rs @@ -12,6 +12,7 @@ Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize, )] #[derive(parity_scale_codec::Encode, parity_scale_codec::Decode)] +#[derive(parity_scale_codec::DecodeWithMemTracking)] #[derive(parity_scale_codec::MaxEncodedLen, scale_info::TypeInfo)] pub struct AccountId(pub [u8; 32]); @@ -37,6 +38,7 @@ use serde_big_array::BigArray; /// Canonical signature — Ed25519, 64 bytes. #[derive(Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] #[derive(parity_scale_codec::Encode, parity_scale_codec::Decode)] +#[derive(parity_scale_codec::DecodeWithMemTracking)] #[derive(parity_scale_codec::MaxEncodedLen, scale_info::TypeInfo)] pub struct Signature(#[serde(with = "BigArray")] pub [u8; 64]); diff --git a/crates/origin-chain-types/src/lib.rs b/crates/origin-chain-types/src/lib.rs index 0bf5454..6a490c3 100644 --- a/crates/origin-chain-types/src/lib.rs +++ b/crates/origin-chain-types/src/lib.rs @@ -60,7 +60,7 @@ pub use fees::{FeeCalculator, OperationKind}; pub use governance::{GovernanceProposal, ProposalId, Vote, VoteStance}; pub use ogc::{Ogc, OgcLedger}; pub use pallets::{OriginFees, OriginProvenance, OriginValidatorEconomy, SlashReason}; -pub use provenance::{AssetAttestation, ProvenanceLedger}; +pub use provenance::{AgentChain, AgentChainBound, AssetAttestation, ProvenanceLedger}; pub use tiers::{AssetQualityTier, HardwareTier}; /// Bridge trait for cross-chain asset export. Export-first per CHN-5 — Origin diff --git a/crates/origin-chain-types/src/provenance.rs b/crates/origin-chain-types/src/provenance.rs index 0ecd0ab..6fdb85e 100644 --- a/crates/origin-chain-types/src/provenance.rs +++ b/crates/origin-chain-types/src/provenance.rs @@ -10,12 +10,31 @@ extern crate alloc; +use sp_core::ConstU32; +use sp_runtime::BoundedVec; + use crate::{AccountId, AssetHash, ChainError, Signature}; -/// Canonical attestation record stored on-chain. Compact (~140 bytes) so it fits -/// in a single extrinsic without bloating block size. -#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] -#[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, scale_info::TypeInfo)] +/// Max AGI co-authors per asset per Inmutable #41 canonical pragmatic bound. +/// +/// 10 co-authors es el upper bound canonical razonable para asset attestation: +/// la mayoría de assets tienen 1-3 AGI co-authors (Daedalus + Hephaistos + +/// Phanes en Trinity; Codex + 1 AGI Daimonion en .odoc; Sussi Daimonion en +/// Ethos credential). Bound canonical permite MaxEncodedLen + storage info. +/// +/// Si en futuro emerge use case canonical de >10 co-authors, bumping requires +/// DC complementaria + chain runtime upgrade canonical (forkless via set_code). +pub type AgentChainBound = ConstU32<10>; + +/// AGI co-author chain canonical — `BoundedVec>`. +pub type AgentChain = BoundedVec; + +/// Canonical attestation record stored on-chain. Compact (~140 bytes max) so it +/// fits in a single extrinsic without bloating block size. +#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(parity_scale_codec::Encode, parity_scale_codec::Decode)] +#[derive(parity_scale_codec::DecodeWithMemTracking)] +#[derive(parity_scale_codec::MaxEncodedLen, scale_info::TypeInfo)] pub struct AssetAttestation { /// BLAKE3 32-byte content hash of the asset bytes (off-chain). pub hash: AssetHash, @@ -25,10 +44,13 @@ pub struct AssetAttestation { pub signature: Signature, /// Block number at which the attestation was committed. Set by the runtime. pub anchored_at_block: u64, - /// Optional AGI co-author chain. Empty for purely human-authored assets; - /// populated for Synthesizer / Forge / Skill outputs that include AGI input - /// (per Inmutable #41 cross-species co-authorship). - pub agent_chain: alloc::vec::Vec, + /// Optional AGI co-author chain canonical (bounded canonical max 10). + /// Empty for purely human-authored assets; populated for Synthesizer / Forge + /// / Skill outputs that include AGI input (per Inmutable #41 cross-species + /// co-authorship canonical). Phase 2.1 v0.0.15 canonical: replaced + /// `Vec` con `BoundedVec>` para + /// MaxEncodedLen storage info compatibility canonical. + pub agent_chain: AgentChain, } /// Canonical provenance ledger. Consumed by Trinity (Phanes), Codex, @@ -52,31 +74,55 @@ mod tests { use super::*; #[test] - fn attestation_roundtrip_serde() { + fn attestation_scale_codec_roundtrip() { + use parity_scale_codec::{Decode, Encode}; let att = AssetAttestation { hash: AssetHash::new([1u8; 32]), creator: AccountId::new([2u8; 32]), signature: Signature::new([3u8; 64]), anchored_at_block: 42, - agent_chain: vec![], + agent_chain: AgentChain::default(), }; - let json = serde_json::to_string(&att).unwrap(); - let parsed: AssetAttestation = serde_json::from_str(&json).unwrap(); + let bytes = att.encode(); + let parsed = AssetAttestation::decode(&mut &bytes[..]).unwrap(); assert_eq!(att, parsed); } #[test] fn attestation_supports_agi_co_authorship() { - // Inmutable #41 — agent_chain may carry AGI co-authors. + // Inmutable #41 — agent_chain may carry AGI co-authors (bounded canonical). let agi1 = AccountId::new([10u8; 32]); let agi2 = AccountId::new([11u8; 32]); + let agent_chain = AgentChain::try_from(alloc::vec![agi1, agi2]) + .expect("2 co-authors within bound canonical"); let att = AssetAttestation { hash: AssetHash::new([1u8; 32]), creator: AccountId::new([2u8; 32]), signature: Signature::new([3u8; 64]), anchored_at_block: 0, - agent_chain: vec![agi1, agi2], + agent_chain, }; assert_eq!(att.agent_chain.len(), 2); } + + #[test] + fn agent_chain_bound_canonical_max_10() { + // BoundedVec canonical enforce max 10 AGI co-authors per Inmutable #41. + let too_many: alloc::vec::Vec = (0..11) + .map(|i| AccountId::new([i; 32])) + .collect(); + let result = AgentChain::try_from(too_many); + assert!(result.is_err(), "Bound canonical = ConstU32<10> enforce"); + } + + #[test] + fn agent_chain_max_10_accepted() { + // Exactly 10 co-authors canonical (boundary canonical). + let exactly_10: alloc::vec::Vec = (0..10) + .map(|i| AccountId::new([i; 32])) + .collect(); + let agent_chain = AgentChain::try_from(exactly_10) + .expect("10 co-authors at boundary canonical"); + assert_eq!(agent_chain.len(), 10); + } }