Visión general de la arquitectura
El Energy Attestation Service (EnergyAS) está construido como un sistema de dos contratos sobre el Ethereum Attestation Service (EAS). Esta separación de responsabilidades permite actualizar la lógica de validación sin migrar el estado.
Capas del sistema
El protocolo consta de cuatro capas, cada una con una responsabilidad distinta:
┌─────────────────────────────────────────────┐
│ EnergyAS Protocol (your application) │
│ Watchers → Projects → Attestations │
├─────────────────────────────────────────────┤
│ EnergyAttestationResolver (replaceable) │
│ Validates attestation data + permissions │
├─────────────────────────────────────────────┤
│ EnergyRegistry (permanent) │
│ Stores all state, events, and accumulators │
├─────────────────────────────────────────────┤
│ Ethereum Attestation Service (EAS) │
│ Permissionless attestation protocol │
└─────────────────────────────────────────────┘Flujo de datos
Cuando un atestador envía lecturas de energía, los datos fluyen a través de la pila:
Attester calls eas.attest(schemaUID, data)
→ EAS stores the attestation
→ EAS calls resolver.onAttest(attestation)
→ Resolver decodes and validates the data
→ Resolver checks attester authorization
→ Resolver computes energyWh and toTimestamp
→ Resolver calls registry.recordAttestation(...)
→ Registry checks for duplicate periods
→ Registry updates energy accumulators
→ Registry emits EnergyAttested eventCiclo de vida de un registro
Entender qué ocurre con un registro desde su envío hasta su corrección te ayuda a construir sobre EnergyAS.
┌─────────────────────────┐
│ Device / Script │
│ calls sdk.attest() │
└──────────┬──────────────┘
│
┌──────────▼──────────────┐
│ EAS contract │
│ stores raw attestation │
│ calls onAttest() │
└──────────┬──────────────┘
│
┌──────────▼──────────────┐
│ Resolver │
│ validates permissions │
│ decodes data │
│ computes energyWh │
└──────────┬──────────────┘
│
┌──────────▼──────────────┐
│ Registry │
│ checks period lock │
│ updates accumulators │
│ emits EnergyAttested │
└──────────┬──────────────┘
│
┌────────────────┼────────────────┐
│ │ │
┌──────────▼─────┐ ┌───────▼──────┐ ┌─────▼──────────┐
│ On-chain │ │ Subgraph │ │ Accumulators │
│ EAS store │ │ indexes │ │ updated │
│ UID is final │ │ within ~1min│ │ immediately │
└────────────────┘ └──────────────┘ └────────────────┘Ciclo de vida de una corrección
Cuando un registro necesita corregirse, el reemplazo fluye por la misma pila, pero lleva el UID original como refUID:
overwriteAttestation({ refUID: originalUID, ... })
→ Resolver validates same project + period
→ Registry marks original as replaced
→ Registry applies delta to accumulators (newWh - oldWh)
→ Emits EnergyReplaced(oldUID, newUID, delta)
→ Subgraph sets original.replaced = true, links replacedBy / replacesEl registro original nunca se elimina: permanece de forma permanente on-chain y visible en el subgraph con replaced: true. Esto ofrece a los auditores un historial completo de correcciones.
Actualización de acumuladores
Cada envío actualiza de inmediato cuatro contadores en el Registry:
totalGeneratedWhpor proyecto (solo generadores)totalConsumedWhpor proyecto (solo consumidores)totalGeneratedWhByWatcherpor organizacióntotalConsumedWhByWatcherpor organización
Las correcciones actualizan los acumuladores por diferencia (delta): si el registro original reportaba 500 kWh y la corrección reporta 490 kWh, los acumuladores disminuyen 10 kWh. Esto ocurre de forma atómica en la misma transacción.
Indexación en el subgraph
El subgraph escucha EnergyAttested, EnergyReplaced y todos los eventos de gestión del registro. La indexación normalmente tarda menos de un minuto tras la confirmación de la transacción. El subgraph también mantiene entidades DailyEnergySnapshot, totales diarios preagregados por proyecto, que se actualizan automáticamente con cada nuevo registro.
Principios de diseño
La arquitectura sigue tres principios fundamentales:
Estado permanente, lógica reemplazable. El EnergyRegistry contiene todos los datos y nunca se reemplaza. El EnergyAttestationResolver contiene la lógica de validación y puede cambiarse sin ninguna migración de datos.
Verificación on-chain, evidencia off-chain. Los datos centrales (lecturas, marcas de tiempo, totales de energía) viven on-chain. La evidencia de respaldo (PDF de auditoría, exportaciones de IoT) se ancla mediante URIs de metadatos opcionales en IPFS.
Sin permisos, con aislamiento entre inquilinos. Cualquiera puede registrarse y participar, pero los datos de cada watcher están completamente aislados de los demás a nivel de la EVM.
El contrato del registro usa Ownable2Step de OpenZeppelin para transferir la propiedad de forma segura, y el resolver usa Pausable para detenciones de emergencia; ambos son patrones probados en producción.