feat(gobierno): spec 18 (RV17), quorum del voto ordinario y pago del tesoro atado a la propuesta

Gobierno (origin-chain-governance):
- El voto ordinario exige un quorum de Aye, el 10 % de PILAR_4 §6.6. Se fija AL CREAR la
  propuesta (VoteQuorumOf) y se consume al decidirla: un set_code no mueve la meta de un
  voto abierto. Cuenta solo el Aye: con el Nay, un voto en contra podria aprobar; con la
  abstencion, el mismo OGC inflaria el quorum de muchas propuestas.
- Un override del veto tiene que alcanzar ese quorum y superar el Nay original, las dos
  condiciones del voto ordinario. Sin ellas, vetar abarataba una aprobacion (dos bloqueantes
  de las revisiones adversariales).
- submit_treasury_proposal (call 16) fija destinatario y monto (TreasuryActions), y
  treasury_disbursement solo paga exactamente eso, una vez. Rechaza montos bajo el deposito
  existencial y como destinatario la propia tesoreria o la cuenta-bond.
- Sin entrada en VoteQuorumOf no hay quorum: la emergencia (que nunca lleva accion de
  tesoro) y lo creado antes de RV17, que se abrio y voto sin quorum.

Runtime: los dos quorums son el 10 % de la emision VIGENTE, redondeado hacia arriba y nunca
por debajo del bond (DiezPorCientoDeLaEmision). Con 100M fijos, en la testnet de la casa
(100M emitidos, todos de Alice) nada se habria aprobado nunca; en mainnet sigue siendo ~100M.
Spec 18, transaction_version 1: todo lo nuevo es aditivo, sin migracion.

Node: pasa a opaque::Block. Decodificaba los extrinsics con tipos nativos y rechazaba en el
pool la llamada que anadia el set_code (1040, el mismo error que una llamada inexistente).
Los bytes y los hashes no cambian: el binario nuevo sincronizo desde cero los 39 273 bloques
de la testnet de la casa con los mismos hashes en 8 alturas. El RPC sirve los extrinsics en hex.

Pesos: seis extrinsics cambiaron de codigo y se midieron en la Pi 5 (smoke declarado: 5
procesos limpios, sin CI en ningun segundo, maximo de los 5). Los otros once siguen siendo los
certificados por Laurha. Se descarto una medida contaminada: su muestreador no veia los tests
de la CI.

Pruebas:
- 363 tests verdes en el workspace.
- 24 contrafactuales, los 24 en rojo.
- Ensayo en la rp1 sobre una cadena con el codigo vivo de spec 17: upgrade a 18 y E2E
  firmando como un wallet (scripts/e2e/rv17_tesoro.py).
- Ejemplo firmar_como_wallet con tesoro, pagar, votar, depositar y finalizar; los eventos
  llevan su fase.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
CharonandClaude Opus 5.5 committed 2026-10-28 21:55:24 -05:00
1 parent abe680e853
commit b6d05eaf45
14 files changed
+1368 -155

No files matched your search

+3 -1
View File
@@ -54,7 +54,9 @@ mod service;
// las Command Line Tools declara la arquitectura `arm64e.x1`, que ld no reconoce.
use clap::{Parser, Subcommand};
use origin_chain_runtime::{genesis_config_presets, Block, IMPL_NAME, RUNTIME_VERSION, SPEC_NAME};
use origin_chain_runtime::{
genesis_config_presets, opaque::Block, IMPL_NAME, RUNTIME_VERSION, SPEC_NAME,
};
use sc_cli::SubstrateCli;
use sp_genesis_builder::PresetId;
+12 -10
View File
@@ -12,16 +12,18 @@ use crate::service::FullClient;
// El client es CONCRETO (`FullClient`), no un `C` genérico como en el template.
//
// El template puede ser genérico porque su node trabaja sobre `opaque::Block`, que no
// menciona la cuenta. El nuestro trabaja sobre el `Block` completo del runtime (sobre
// él están los `impl_runtime_apis!`), y ese tipo lleva dentro `ChainAccountId`, que es
// una PROYECCIÓN: `<<MultiSignature as Verify>::Signer as IdentifyAccount>::AccountId`.
// Dentro de un where-clause genérico rustc no la normaliza a `AccountId32`: el bound
// `C: ProvideRuntimeApi<Block>` queda escrito con una forma del tipo y `System` lo
// pide con la otra, y el compilador informa de que un bound declarado en la propia
// firma «no se satisface» (6 errores, medido el 2026-09-23). Con el tipo concreto no
// hay nada que normalizar en el param-env y los bounds se comprueban sobre el client
// real — que es además el único que este node construye.
// Hasta el 2026-10-28 el node trabajaba sobre el `Block` completo del runtime, y ese tipo
// lleva dentro `ChainAccountId`, que es una PROYECCIÓN:
// `<<MultiSignature as Verify>::Signer as IdentifyAccount>::AccountId`. Dentro de un
// where-clause genérico rustc no la normalizaba a `AccountId32`: el bound
// `C: ProvideRuntimeApi<Block>` quedaba escrito con una forma del tipo y `System` lo pedía
// con la otra, y el compilador informaba de que un bound declarado en la propia firma «no
// se satisface» (6 errores, medido el 2026-09-23). Con el tipo concreto los bounds se
// comprueban sobre el client real, que es además el único que este node construye.
//
// Desde el 2026-10-28 el node trabaja sobre `opaque::Block` (ver
// `origin_chain_runtime::opaque`: el node decodificaba las llamadas con tipos nativos y
// rechazaba las que añadía un `set_code`). El client sigue concreto.
/// Dependencias completas para construir los RPC del node.
pub struct FullDeps<P> {
+6 -5
View File
@@ -12,11 +12,12 @@ use sc_consensus_grandpa::SharedVoterState;
use sc_service::{error::Error as ServiceError, Configuration, TaskManager, WarpSyncConfig};
use sc_telemetry::{Telemetry, TelemetryWorker};
use sc_transaction_pool_api::OffchainTransactionPoolFactory;
// El runtime implementa `impl_runtime_apis!` sobre el `Block` root (con
// UncheckedExtrinsic), no sobre un opaque block separado → el node usa ese mismo
// tipo para que `RuntimeApi` matchee. (El template solochain usa `opaque::Block`
// porque su runtime expone las APIs así; el nuestro las expone sobre root Block.)
use origin_chain_runtime::{Block, RuntimeApi};
// El node trabaja sobre `opaque::Block`: los extrinsics son bytes y sólo el WASM los
// decodifica. Con el `Block` completo del runtime (hasta el 2026-10-28) el node decodificaba
// con sus tipos nativos y rechazaba toda llamada que un `set_code` hubiera añadido (ver
// `origin_chain_runtime::opaque`). Las runtime APIs que genera `impl_runtime_apis!` son
// genéricas en el bloque y cruzan la frontera en SCALE, así que valen igual sobre éste.
use origin_chain_runtime::{opaque::Block, RuntimeApi};
use sp_consensus_aura::sr25519::AuthorityPair as AuraPair;
use std::{sync::Arc, time::Duration};