Files
arkhe-origin-chain/crates/origin-chain-provenance/Cargo.toml
T
davidherranandClaude Fable 5 ce18e191d0 feat(provenance): FIX-4 — verificador attestation on-chain (cierra V3-C1 + squat)
El verificador attestation queda VIVO: una firma producida por el código
REAL de Ergon (arkhe-noesis-core, postcard + mensaje domain-separado)
verifica byte-fiel en el pallet Substrate. Cierra el FIX-DEFERRED del
roadmap (helper de Ergon ya en árbol) + el replay cross-chain V3-C1.

origin-chain-types/attestation_verify.rs (nuevo):
- ATTESTATION_DOMAIN_TAG + attestation_signed_message: espejo BYTE-IDÉNTICO
  del oráculo (DC 076d15cc ASP-3). Mensaje = TAG ‖ genesis_hash(32) ‖ payload.
- decode_signing_payload: lector postcard SECUENCIAL total y estricto del
  SigningPayload de Ergon (sin dep nueva en el runtime wasm frágil). Lectores
  varint u64/u32 con los bounds exactos de postcard (cierra el LOW de fidelidad
  flagged: verdict/severity/constraints son u32, máx 5 bytes / 5º ≤ 15).
  Cotas DoS en strings. NUNCA re-serializa (contrato ASP-3).

pallet-origin-provenance:
- attest_asset(signing_payload: BoundedVec<u8,512>, signature: [u8;64]):
  recibe los bytes postcard OPACOS + la firma; decodifica, verifica Ed25519
  vía sp_io::crypto::ed25519_verify (host function, no bloatea wasm, precedente
  FIX-3) sobre el mensaje domain-separado con el genesis_hash de ESTA cadena.
  La pubkey se decodifica del payload (no param aparte). creator = el validador,
  anchored_at_block real (cerró los placeholders del scaffold).
- Dedup-by-BLAKE3 con rechazo EXPLÍCITO (asset_id = BLAKE3 content hash, dentro
  del payload firmado → replay del mismo blob reusa el asset_id → AlreadyAttested).

Hallazgos de la verificación adversarial (workflow ultracode, 3 lentes)
cerrados de RAÍZ:
- HIGH asset-id squat / provenance poisoning + MEDIUM tier-forgery: el gate
  era self-attested (level del payload) → cualquiera con una clave Ed25519
  anclaba basura institucional bajo el hash PÚBLICO de un asset legítimo y lo
  envenenaba de forma inmutable. FIX: registro on-chain AuthorizedValidators
  (pubkey → nivel OIT) gobernado por Root (register_validator/revoke_validator);
  la membresía es la VERDAD, no el payload. Mismo patrón que TierProfiles de
  FIX-6 Stage 2a (legitimidad on-chain, no caller-supplied). Sunset a
  attestation-driven cuando aterrice el registro OIT de Mathi.
- MEDIUM método muerto: removido el ValidationAttestation::signing_payload()
  SCALE divergente (producía bytes que jamás verificarían — footgun).

Decisiones (autoridad Pilar 4): sp_io ed25519_verify (consistente FIX-3,
estándar Substrate) · dedup-by-asset_id subsume replay exacto · golden vectors
generados desde el oráculo REAL de Ergon (seed [7u8;32], genesis 0xAB) =
prueba cross-runtime.

PENDIENTE (gap legítimo, no bug): OriginChainAttestationSink (impl del trait
ValidationAttestationSink de Ergon) es código cliente off-chain — vive en un
crate bridge del monorepo (subxt), NO en el chain repo (dependency direction
submódulo→monorepo prohibida). Se cablea con la integración Noesis→chain.

Tests: 19 provenance (golden vectors cross-runtime + squat cerrado + revoke +
anti-replay cross/intra-chain + tamper + malformed) + 72 types (decoder fuzz-
equivalente a postcard + fidelidad u32) + 21 suites workspace verde. cargo +1.88.

WASM: build VPS-gated (UnknownOpcode 252 ambiental, ver v0.0.58).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 19:52:57 -05:00

64 lines
2.1 KiB
TOML

[package]
name = "origin-chain-provenance"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
authors.workspace = true
repository.workspace = true
homepage.workspace = true
description = "Asset attestation pallet canonical per CHN-7. Phase 2.1 scaffold v0.0.14 — trait-first foundation pattern. Real impl post Ergon arkhe-noesis-attestation-types Cap 42+ sub-crate."
[dependencies]
# Origin Chain canonical types (vendor ValidationAttestation interim Option B)
origin-chain-types = { workspace = true }
# FRAME canonical pallet macro + storage + dispatch + events + errors
frame-support = { workspace = true }
frame-system = { workspace = true }
# Runtime API canonical (v0.0.17 PROV-8 — verify_provenance read-only RPC query)
sp-api = { workspace = true }
# Crypto canonical. FIX-4: sp-io host function ed25519_verify (no bloatea wasm,
# precedente FIX-3 agent-identity) + blake3 para dedup. ed25519-dalek se mantiene
# solo para los fixtures de test (dev-deps) — el runtime usa sp_io.
blake3 = { workspace = true }
# FIX-4 (V3-C1): verificacion Ed25519 on-chain via host function + genesis read.
sp-core = { workspace = true }
sp-io = { workspace = true }
# SCALE codec canonical
parity-scale-codec = { workspace = true }
scale-info = { workspace = true }
[dev-dependencies]
# Mock runtime canonical para integration tests — PROV-3 E2E flow + golden
# vectors ASP-3. ed25519-dalek solo aqui (fixtures); el runtime usa sp_io.
sp-core = { workspace = true, default-features = true }
sp-io = { workspace = true, default-features = true }
sp-runtime = { workspace = true, default-features = true }
ed25519-dalek = { workspace = true, default-features = true }
[features]
default = ["std"]
std = [
"origin-chain-types/std",
"frame-support/std",
"frame-system/std",
"sp-api/std",
"sp-core/std",
"sp-io/std",
"parity-scale-codec/std",
"scale-info/std",
]
runtime-benchmarks = [
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
]
try-runtime = [
"frame-support/try-runtime",
"frame-system/try-runtime",
]