feat(tiers): EmbeddedAI on-chain — base_multiplier + subsidy piso EmbeddedArm (#16)

Espejea HardwareTier::EmbeddedAI (Jetson Orin Nano) en el mirror de la cadena,
en lockstep con arkhe-core bbac1b2 (Ergon Fase 1 EmbeddedAI, ADR-0072 / DC 2ba235e1).

Trampa de la fuente preservada byte-fiel: EmbeddedAI APPEND discriminante 4
(SCALE wire-safe, attestations runtime_tier:u8 viejas válidas) PERO rank de
capacidad 1 (entre EmbeddedArm=0 y Portable=2). Por eso Ord es MANUAL por rank()
(no derive — un derive pondría EmbeddedAI > Ultra, falso) y el gating Hero es por
rank, no por discriminante.

- tiers.rs: variant EmbeddedAI (last) + Ord/PartialOrd manual por rank() +
  rank()/ordinal()/from_ordinal() SSOT (el reverse-map que evita perder el
  tier-floor al deserializar, #16) + base_multiplier_x100=10 (piso, el estudiante
  en Jetson no paga más que en Pi 5) + surcharge Hero gated=0 + supports_hero=false.
- fee_schedule.rs: 6 arms EmbeddedAI = piso EmbeddedArm en subsidy_basis_points +
  educational override incluye EmbeddedAI (device de estudiante).
- fees.rs / unified.rs: cobertura — compute_fee(EmbeddedAI)==EmbeddedArm + grid de
  paridad OCAFB-5 extendido a EmbeddedAI.

Tests: 21 suites / 261 workspace verde, 0 regresión. SCALE index == ordinal sellado.
FIX-4 (verificador attestation) ortogonal — no mapea el enum, intacto.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
davidherranandClaude Opus 4.8 committed 2026-06-16 19:24:17 -05:00
1 parent fcf768b046
commit ca50938495
4 files changed
+236 -13

No files matched your search

+36 -4
View File
@@ -87,6 +87,11 @@ pub const fn subsidy_basis_points(hw: HardwareTier, action: ChainAction) -> u32
(EmbeddedArm, Write) => 9000,
(EmbeddedArm, Compute) => 10000, // educational compute free
(EmbeddedArm, Transfer) => 9000,
// EmbeddedAI (Jetson Orin Nano): MISMO piso EmbeddedArm — Inmutable #16,
// el estudiante en Jetson no paga más que en Pi 5. Ergon bbac1b2.
(EmbeddedAI, Write) => 9000,
(EmbeddedAI, Compute) => 10000, // educational compute free
(EmbeddedAI, Transfer) => 9000,
// Portable: subsidy media
(Portable, Write) => 7500,
(Portable, Compute) => 5000,
@@ -108,6 +113,10 @@ pub const fn subsidy_basis_points(hw: HardwareTier, action: ChainAction) -> u32
(EmbeddedArm, DeployContract) => 9000, // Pi 5 dev contracts canonical
(EmbeddedArm, CallContract) => 10000, // educational call free
(EmbeddedArm, UploadContractCode) => 9000, // Pi 5 storage subsidy
// EmbeddedAI (Jetson): mismo piso EmbeddedArm en contract actions (#16).
(EmbeddedAI, DeployContract) => 9000, // Jetson dev contracts = piso Pi 5
(EmbeddedAI, CallContract) => 10000, // educational call free
(EmbeddedAI, UploadContractCode) => 9000, // Jetson storage subsidy = piso
(Portable, DeployContract) => 7500,
(Portable, CallContract) => 5000,
(Portable, UploadContractCode) => 7500,
@@ -247,11 +256,12 @@ impl OitFeeSchedule for OitFeeScheduleMock {
}
fn subsidy_eligible(&self, _user_id: &str, action: ChainAction) -> bool {
// OCAFB-3 override: educational_world → 100% subsidy EmbeddedArm + Portable
// OCAFB-3 override: educational_world → 100% subsidy en los tiers floor
// EmbeddedArm + EmbeddedAI + Portable (Jetson = device de estudiante, #16).
if self.educational_world
&& matches!(
self.default_hardware,
HardwareTier::EmbeddedArm | HardwareTier::Portable
HardwareTier::EmbeddedArm | HardwareTier::EmbeddedAI | HardwareTier::Portable
)
{
return true;
@@ -260,11 +270,11 @@ impl OitFeeSchedule for OitFeeScheduleMock {
}
fn tier_multiplier(&self, _user_id: &str, action: ChainAction) -> u64 {
// Educational override → multiplier 0 (free)
// Educational override → multiplier 0 (free) en los tiers floor.
if self.educational_world
&& matches!(
self.default_hardware,
HardwareTier::EmbeddedArm | HardwareTier::Portable
HardwareTier::EmbeddedArm | HardwareTier::EmbeddedAI | HardwareTier::Portable
)
{
return 0;
@@ -295,6 +305,7 @@ mod tests {
// Inmutable #37 baseline: Read NEVER charged per HardwareTier
for hw in [
HardwareTier::EmbeddedArm,
HardwareTier::EmbeddedAI,
HardwareTier::Portable,
HardwareTier::Desktop,
HardwareTier::Ultra,
@@ -303,6 +314,27 @@ mod tests {
}
}
#[test]
fn embedded_ai_subsidy_mirrors_embedded_arm_floor_inmutable_16() {
// El estudiante en Jetson (EmbeddedAI) no paga MÁS que en Pi 5
// (EmbeddedArm): piso idéntico en TODA acción. Ergon bbac1b2, #16.
for action in [
ChainAction::Read,
ChainAction::Write,
ChainAction::Compute,
ChainAction::Transfer,
ChainAction::DeployContract,
ChainAction::CallContract,
ChainAction::UploadContractCode,
] {
assert_eq!(
subsidy_basis_points(HardwareTier::EmbeddedAI, action),
subsidy_basis_points(HardwareTier::EmbeddedArm, action),
"EmbeddedAI debe espejar el piso EmbeddedArm en {action:?}"
);
}
}
#[test]
fn ocafb_3_ultra_pays_full_fee_canonical() {
// Ultra: no subsidy except Read
+2 -1
View File
@@ -396,8 +396,9 @@ mod tests {
use super::*;
use crate::fee_schedule::compute_fee as vendor_compute_fee;
const ALL_HW: [HardwareTier; 4] = [
const ALL_HW: [HardwareTier; 5] = [
HardwareTier::EmbeddedArm,
HardwareTier::EmbeddedAI,
HardwareTier::Portable,
HardwareTier::Desktop,
HardwareTier::Ultra,