feat(session): Phase 1.5 — Session rotation 4h epochs canonical v0.0.7
Origin Chain runtime canonical ahora emite SessionEvent::NewSession cada 4 horas exactas per CHN-1 ratified. Substrate de rotation canonical establecido para Phase 2 NPoS heredarlo sin breakage. ## Pallet añadido (per SBS-4) - Index 6 Session (pallet_session 40.0.1) — validator session rotation per CHN-1 4h epochs. Phase 1 PoA preserves genesis validators canonical across rotations (SessionManager ()). Phase 2 NPoS introducira pallet_staking como SessionManager para rotation real per nominator stake + Pi 5 hardware tier weight. ## Configs canonical pallet_session - SessionPeriod = BLOCK_HASH_COUNT (2400 bloques × 6s = 14400s = 4h exactas) - SessionOffset = 0 (sesiones start at block 0) - ValidatorId = ChainAccountId - ValidatorIdOf = AccountIdIsValidatorId (custom identity converter Phase 1 PoA) - ShouldEndSession/NextSessionRotation = PeriodicSessions<SessionPeriod, SessionOffset> - SessionManager = () (preserves genesis Phase 1 PoA) - SessionHandler = <opaque::SessionKeys as OpaqueKeys>::KeyTypeIdProviders - Keys = opaque::SessionKeys (aura sr25519 + grandpa Ed25519) - DisablingStrategy = () (Phase 2 NPoS introduce real slashing-based disable) ## Custom converter canonical AccountIdIsValidatorId struct nueva — identity mapping AccountId → ValidatorId Phase 1 PoA trivial. Phase 2 NPoS reemplazara con pallet_staking::StashOf<Self> para real Stash/Controller separation canonical. ## Filosofía canonical SessionPeriod = 4h es la frontera temporal canonical: cada 4h el chain reflexiona on-chain quienes son los validators activos. Esta cadencia institucional canonical es la minima necesaria para que Phase 2 NPoS pueda evolucionar el set sin re-launching genesis. David canon 2026-05-14 materializado temporalmente. ## Build + tests - cargo check 1.63s warm cache (pallet_session incremental) - cargo build --release 7.70s warm cache clean - ~57 tests passing (count preserved — session tests Phase 1.7 chain_spec) ## Decision empirica pallet_session::Config::DisablingStrategy es nuevo stable2512 canonical (no estaba en versiones anteriores). Phase 1 PoA: () preserva behavior original. Phase 2 NPoS: UpToLimitWithReEnablingDisablingStrategy per CHN-3. ## Phase 1 progress 1.1 ✅ + 1.2 ✅ + 1.3 ✅ + 1.4 ✅ + 1.5 ✅ (esta). Next: 1.6 pallet_identity Ed25519 DID + origin-chain-node real service. 7 pallets composed canonical: - 0 System + 1 Timestamp + 2 Balances + 3 TransactionPayment - 4 Aura + 5 Grandpa + 6 Session ← NEW - Opaque SessionKeys consumed by pallet_session::Config::Keys ← NEW WIRE Refs: CHARON_ROADMAP_V1 Phase 1.5, CHN-1 4h epoch rotation canonical, SBS-4 extended, arkhe-origin-chain commit pending Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
4988693d4b
commit
926650308c
7 files changed
+194
-1
No files matched your search
+104
@@ -6,6 +6,110 @@ by [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Versions follow
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [0.0.7] — 2026-05-20 — Phase 1.5 "Session rotation canonical (4h epochs)"
|
||||||
|
|
||||||
|
Charon sesión 1 continuación. **Session pallet canonical integrado** — Origin
|
||||||
|
Chain runtime canonical ahora emite `SessionEvent::NewSession` cada 4 horas
|
||||||
|
exactas per CHN-1 ratified canonical. Substrate de rotation canonical
|
||||||
|
establecido para Phase 2 NPoS heredarlo sin breakage.
|
||||||
|
|
||||||
|
### Pallet añadido canonical (per SBS-4)
|
||||||
|
|
||||||
|
- **Index 6** `Session` (`pallet_session 40.0.1`) — **validator session
|
||||||
|
rotation canonical** per CHN-1 4h epochs. Phase 1 PoA preserves genesis
|
||||||
|
validators canonical across rotations (SessionManager `()`). Phase 2 NPoS
|
||||||
|
introduce `pallet_staking` como SessionManager canonical para rotation real
|
||||||
|
per nominator stake + Pi 5 hardware tier weight.
|
||||||
|
|
||||||
|
### Configs canonical pallet_session
|
||||||
|
|
||||||
|
```rust
|
||||||
|
parameter_types! {
|
||||||
|
/// 2400 bloques × 6s = 14400s = 4 horas exactas per CHN-1
|
||||||
|
pub const SessionPeriod: BlockNumber = BLOCK_HASH_COUNT;
|
||||||
|
pub const SessionOffset: BlockNumber = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
type RuntimeEvent = RuntimeEvent;
|
||||||
|
type ValidatorId = ChainAccountId;
|
||||||
|
type ValidatorIdOf = AccountIdIsValidatorId; // identity Phase 1 PoA
|
||||||
|
type ShouldEndSession = pallet_session::PeriodicSessions<SessionPeriod, SessionOffset>;
|
||||||
|
type NextSessionRotation = pallet_session::PeriodicSessions<SessionPeriod, SessionOffset>;
|
||||||
|
type SessionManager = (); // Phase 1 PoA preserves genesis
|
||||||
|
type SessionHandler = <opaque::SessionKeys as OpaqueKeys>::KeyTypeIdProviders;
|
||||||
|
type Keys = opaque::SessionKeys; // aura sr25519 + grandpa Ed25519
|
||||||
|
type DisablingStrategy = (); // Phase 2 NPoS introduce real
|
||||||
|
type WeightInfo = pallet_session::weights::SubstrateWeight<Runtime>;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Custom canonical converter
|
||||||
|
|
||||||
|
`AccountIdIsValidatorId` struct nueva canonical (identity mapping AccountId →
|
||||||
|
ValidatorId Phase 1 PoA trivial). Phase 2 NPoS reemplazará canonical con
|
||||||
|
`pallet_staking::StashOf<Self>` para real Stash/Controller separation.
|
||||||
|
|
||||||
|
### Filosofía canonical incorporada
|
||||||
|
|
||||||
|
Doc cita CHN-1: *"Epoch rotation every 4 hours selecting 100-150 active
|
||||||
|
validators from millions of Pi 5 nodes eligible"*. Materializa empíricamente:
|
||||||
|
|
||||||
|
- **Phase 1 PoA** (este v0.0.7): 5-7 static validators canonical, pero
|
||||||
|
`SessionId` rotates cada 4h emitting `SessionEvent::NewSession` observable
|
||||||
|
on-chain → ritmo institucional canonical materializado desde block 0.
|
||||||
|
- **Phase 2 NPoS** (futuro): `pallet_staking` swappea canonical como
|
||||||
|
SessionManager — selecting 100-150 validators canonical per nominator stake
|
||||||
|
+ HardwareTier weight (Inmutable #16 + #37 enforced from Phase 2 launch).
|
||||||
|
|
||||||
|
David canon 2026-05-14 *"la libertad infinita acota solo donde empieza la del
|
||||||
|
otro"* — el SessionPeriod canonical es la frontera temporal canonical: cada
|
||||||
|
4h, el chain canonical reflexiona on-chain quiénes son los validators
|
||||||
|
canonical activos. Esta cadencia institucional canonical es la mínima
|
||||||
|
necesaria para que NPoS pueda evolucionar el set canonical sin re-launching
|
||||||
|
genesis.
|
||||||
|
|
||||||
|
### Tour canonical de Origin Chain runtime composition (7 pallets)
|
||||||
|
|
||||||
|
```
|
||||||
|
┌────────────────────────────────────────────────────────────┐
|
||||||
|
│ Origin Chain Runtime v0.0.7 — frame_support::runtime! │
|
||||||
|
├────────────────────────────────────────────────────────────┤
|
||||||
|
│ Index 0 System (foundational frame) │
|
||||||
|
│ Index 1 Timestamp (block clock → Aura) │
|
||||||
|
│ Index 2 Balances (OGC token CHN-2) │
|
||||||
|
│ Index 3 TransactionPayment (gas baseline CHN-8) │
|
||||||
|
│ Index 4 Aura (PoA block production CHN-1) │
|
||||||
|
│ Index 5 Grandpa (finality gadget CHN-1) │
|
||||||
|
│ Index 6 Session (4h epoch rotation CHN-1) │ ← NEW
|
||||||
|
├────────────────────────────────────────────────────────────┤
|
||||||
|
│ Opaque SessionKeys: aura (sr25519) + grandpa (Ed25519) │
|
||||||
|
│ → consumed canonical by pallet_session::Config::Keys │ ← NEW WIRE
|
||||||
|
└────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### Phase 1 progress canonical
|
||||||
|
|
||||||
|
- ✅ **1.1** Scaffold (v0.0.2)
|
||||||
|
- ✅ **1.2** Substrate foundation (v0.0.4)
|
||||||
|
- ✅ **1.3** Pallets foundation (v0.0.5)
|
||||||
|
- ✅ **1.4** Consensus PoA Aura+GRANDPA (v0.0.6)
|
||||||
|
- ✅ **1.5** **Session rotation 4h epochs** (v0.0.7) ← **ESTA**
|
||||||
|
- ⏳ **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)
|
||||||
|
|
||||||
|
### Build canonical
|
||||||
|
|
||||||
|
- `cargo check --workspace`: **1.63s** (warm cache, pallet_session incremental)
|
||||||
|
- `cargo build --release`: **7.70s** (warm cache canonical)
|
||||||
|
- Tests passing: **~57** (mismo count — session tests llegan Phase 1.7 cuando
|
||||||
|
chain_spec con validators reales se integre)
|
||||||
|
|
||||||
|
### Decision empírica documentada
|
||||||
|
|
||||||
|
`pallet_session::Config::DisablingStrategy` es nuevo en stable2512 canonical
|
||||||
|
(no estaba en versiones anteriores). Phase 1 PoA: `()` canonical preserva
|
||||||
|
behavior original. Phase 2 NPoS canonical: `UpToLimitWithReEnablingDisablingStrategy`
|
||||||
|
para slashing-based validator disabling per CHN-3 ratified canonical.
|
||||||
|
|
||||||
## [0.0.6] — 2026-05-20 — Phase 1.4 "Consensus PoA canonical (Aura+GRANDPA)"
|
## [0.0.6] — 2026-05-20 — Phase 1.4 "Consensus PoA canonical (Aura+GRANDPA)"
|
||||||
|
|
||||||
Charon sesión 1 continuación. **Consensus PoA canonical activado** — Origin
|
Charon sesión 1 continuación. **Consensus PoA canonical activado** — Origin
|
||||||
|
|||||||
Generated
+1
@@ -2088,6 +2088,7 @@ dependencies = [
|
|||||||
"pallet-aura",
|
"pallet-aura",
|
||||||
"pallet-balances",
|
"pallet-balances",
|
||||||
"pallet-grandpa",
|
"pallet-grandpa",
|
||||||
|
"pallet-session",
|
||||||
"pallet-timestamp",
|
"pallet-timestamp",
|
||||||
"pallet-transaction-payment",
|
"pallet-transaction-payment",
|
||||||
"parity-scale-codec",
|
"parity-scale-codec",
|
||||||
|
|||||||
@@ -65,6 +65,9 @@ pallet-transaction-payment = { version = "40.0.0", default-features = false }
|
|||||||
pallet-aura = { version = "39.0.0", default-features = false }
|
pallet-aura = { version = "39.0.0", default-features = false }
|
||||||
pallet-grandpa = { version = "40.0.0", default-features = false }
|
pallet-grandpa = { version = "40.0.0", default-features = false }
|
||||||
|
|
||||||
|
# FRAME pallets canonical Phase 1.5 — Session rotation per CHN-1 4h epochs
|
||||||
|
pallet-session = { version = "40.0.1", default-features = false }
|
||||||
|
|
||||||
# SCALE codec canonical (canonical Substrate serialization)
|
# SCALE codec canonical (canonical Substrate serialization)
|
||||||
parity-scale-codec = { version = "3.7", default-features = false, features = ["derive"] }
|
parity-scale-codec = { version = "3.7", default-features = false, features = ["derive"] }
|
||||||
scale-info = { version = "2.11", default-features = false, features = ["derive"] }
|
scale-info = { version = "2.11", default-features = false, features = ["derive"] }
|
||||||
|
|||||||
@@ -41,6 +41,9 @@ pallet-transaction-payment.workspace = true
|
|||||||
pallet-aura.workspace = true
|
pallet-aura.workspace = true
|
||||||
pallet-grandpa.workspace = true
|
pallet-grandpa.workspace = true
|
||||||
|
|
||||||
|
# FRAME pallets Phase 1.5 — Session rotation per CHN-1 4h epochs
|
||||||
|
pallet-session.workspace = true
|
||||||
|
|
||||||
# SCALE codec canonical
|
# SCALE codec canonical
|
||||||
parity-scale-codec.workspace = true
|
parity-scale-codec.workspace = true
|
||||||
scale-info.workspace = true
|
scale-info.workspace = true
|
||||||
@@ -72,6 +75,7 @@ std = [
|
|||||||
"pallet-transaction-payment/std",
|
"pallet-transaction-payment/std",
|
||||||
"pallet-aura/std",
|
"pallet-aura/std",
|
||||||
"pallet-grandpa/std",
|
"pallet-grandpa/std",
|
||||||
|
"pallet-session/std",
|
||||||
"parity-scale-codec/std",
|
"parity-scale-codec/std",
|
||||||
"scale-info/std",
|
"scale-info/std",
|
||||||
"serde",
|
"serde",
|
||||||
|
|||||||
@@ -229,3 +229,78 @@ impl pallet_grandpa::Config for Runtime {
|
|||||||
/// reports not handled. Phase 2 NPoS introduces real handler canonical.
|
/// reports not handled. Phase 2 NPoS introduces real handler canonical.
|
||||||
type EquivocationReportSystem = ();
|
type EquivocationReportSystem = ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// pallet_session::Config canonical (CHN-1 — 4h epoch rotation)
|
||||||
|
// ============================================================
|
||||||
|
//
|
||||||
|
// Filosofía canonical: PoA Phase 1 preserva el mismo validator set canonical
|
||||||
|
// genesis através de cada session rotation (SessionManager = `()`). El "epoch
|
||||||
|
// rotation" canonical materializa el ritmo institucional canonical (cada 4h se
|
||||||
|
// emite SessionEvent canonical observable on-chain) sin cambiar canonical el
|
||||||
|
// validator set hasta Phase 2 NPoS — cuando pallet_staking introduce dynamic
|
||||||
|
// validator selection basado en stake + nominator delegation.
|
||||||
|
//
|
||||||
|
// CHN-1 ratificado canonical: "Epoch rotation every 4 hours selecting 100-150
|
||||||
|
// active validators from millions of Pi 5 nodes eligible". Phase 1 PoA tiene
|
||||||
|
// 5-7 static validators canonical; el "selecting 100-150" materializa Phase 2
|
||||||
|
// NPoS canonical. Esta integration Phase 1.5 establece el substrate canonical
|
||||||
|
// para que Phase 2 NPoS herede el rotation mechanism sin breakage.
|
||||||
|
|
||||||
|
parameter_types! {
|
||||||
|
/// Canonical session period: 2400 bloques × 6s = 14400s = **4 horas exactas**
|
||||||
|
/// per CHN-1 ratified canonical. Alineado canonical con BLOCK_HASH_COUNT
|
||||||
|
/// (mismo valor) — block hash proof valid durante todo el epoch en curso.
|
||||||
|
pub const SessionPeriod: BlockNumber = BLOCK_HASH_COUNT;
|
||||||
|
/// Canonical session offset: 0 — sesiones canonical start at block 0 (sin
|
||||||
|
/// offset canonical). Phase 2 NPoS puede introducir offset si necesario
|
||||||
|
/// para alinear con extramo institucional (e.g. UTC midnight epoch starts).
|
||||||
|
pub const SessionOffset: BlockNumber = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Canonical converter `ChainAccountId → Option<ChainAccountId>`.
|
||||||
|
///
|
||||||
|
/// Phase 1 PoA simple: cada AccountId IS a ValidatorId canonical (identidad
|
||||||
|
/// trivial). Phase 2 NPoS introduces real Stash/Controller separation canonical
|
||||||
|
/// where ValidatorId derives from Stash account via pallet_staking::StashOf.
|
||||||
|
pub struct AccountIdIsValidatorId;
|
||||||
|
|
||||||
|
impl sp_runtime::traits::Convert<ChainAccountId, Option<ChainAccountId>>
|
||||||
|
for AccountIdIsValidatorId
|
||||||
|
{
|
||||||
|
fn convert(account: ChainAccountId) -> Option<ChainAccountId> {
|
||||||
|
Some(account)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl pallet_session::Config for Runtime {
|
||||||
|
type RuntimeEvent = RuntimeEvent;
|
||||||
|
/// ValidatorId canonical = ChainAccountId (Phase 1 PoA identidad trivial).
|
||||||
|
type ValidatorId = ChainAccountId;
|
||||||
|
/// ValidatorIdOf canonical: identity mapping AccountId → ValidatorId.
|
||||||
|
type ValidatorIdOf = AccountIdIsValidatorId;
|
||||||
|
/// ShouldEndSession canonical: PeriodicSessions every 2400 blocks (4h epoch
|
||||||
|
/// per CHN-1 canonical). Cada 2400 bloques emite SessionEvent::NewSession.
|
||||||
|
type ShouldEndSession = pallet_session::PeriodicSessions<SessionPeriod, SessionOffset>;
|
||||||
|
/// NextSessionRotation canonical: same PeriodicSessions — predecible
|
||||||
|
/// canonical para validators saber cuándo será el next rotation slot.
|
||||||
|
type NextSessionRotation = pallet_session::PeriodicSessions<SessionPeriod, SessionOffset>;
|
||||||
|
/// SessionManager canonical = `()`: Phase 1 PoA preserves genesis validators
|
||||||
|
/// canonical across all sessions (no rotation of validator SET, only
|
||||||
|
/// SessionId increment canonical). Phase 2 NPoS introduces pallet_staking
|
||||||
|
/// como SessionManager canonical para real rotation per nominator stake.
|
||||||
|
type SessionManager = ();
|
||||||
|
/// SessionHandler canonical: deriva desde opaque::SessionKeys (aura sr25519
|
||||||
|
/// + grandpa Ed25519). Cuando una nueva session begins canonical, los
|
||||||
|
/// session keys de cada validator se distribute al consensus pallets canonical
|
||||||
|
/// (Aura recibe nuevo AuraId set + Grandpa recibe nuevo GrandpaId set).
|
||||||
|
type SessionHandler =
|
||||||
|
<crate::opaque::SessionKeys as sp_runtime::traits::OpaqueKeys>::KeyTypeIdProviders;
|
||||||
|
/// Keys canonical = opaque::SessionKeys struct (defined en opaque.rs).
|
||||||
|
type Keys = crate::opaque::SessionKeys;
|
||||||
|
/// DisablingStrategy canonical = `()`: Phase 1 PoA simple — no validator
|
||||||
|
/// disable mechanism. Phase 2 NPoS introduces `UpToLimitWithReEnablingDisablingStrategy`
|
||||||
|
/// canonical para slashing-based validator disabling per CHN-3.
|
||||||
|
type DisablingStrategy = ();
|
||||||
|
type WeightInfo = pallet_session::weights::SubstrateWeight<Runtime>;
|
||||||
|
}
|
||||||
@@ -217,6 +217,13 @@ mod runtime {
|
|||||||
/// (Aura ~6s) de finality cadence (canonical ~6-12s combined).
|
/// (Aura ~6s) de finality cadence (canonical ~6-12s combined).
|
||||||
#[runtime::pallet_index(5)]
|
#[runtime::pallet_index(5)]
|
||||||
pub type Grandpa = pallet_grandpa::Pallet<Runtime>;
|
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>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
//! (puede correr cualquier runtime WASM compatible) + runtime sovereignty (puede
|
//! (puede correr cualquier runtime WASM compatible) + runtime sovereignty (puede
|
||||||
//! evolucionar pallets sin breakar node binaries).
|
//! evolucionar pallets sin breakar node binaries).
|
||||||
|
|
||||||
use crate::{AuraId, GrandpaId};
|
|
||||||
use sp_runtime::impl_opaque_keys;
|
use sp_runtime::impl_opaque_keys;
|
||||||
|
|
||||||
impl_opaque_keys! {
|
impl_opaque_keys! {
|
||||||
|
|||||||
Reference in new issue
Block a user