Siguiente
Continúa con Verificación para ver cómo una proof final se comprueba de forma independiente y se exporta como un bundle portable.
Esta página cubre cómo se gobierna el anchoring: en qué modo se ancla un punto, cómo se resuelve esa política, cómo una proof avanza hacia la finality, y qué ocurre cuando la cadena se reorganiza, o el backlog crece.
CORE-M admite tres modos de anchoring. El modo determina cómo el hash de un punto llega a la cadena.
Merkle batch (por defecto). Los hashes de los puntos se acumulan en un batch, se construye un Merkle tree binario SHA-256, y solo el root de 32 bytes se ancla en una transacción. El más eficiente en coste — una transacción compromete hasta un batch completo de puntos. La verificación necesita el Merkle path por punto. La latencia está acotada por la ventana de vaciado (flush window). Consulta Hashing y Merkle trees.
Per-event. Cada punto se ancla en su propia transacción, con el data_hash del
punto llevado directamente en el OP_RETURN y data_point_count = 1. La máxima
garantía y la menor latencia, pero usa una transacción por punto — el modo más caro.
No se necesita Merkle path; el OP_RETURN se comprueba directamente.
Hash chain. Las transacciones de anchoring se enlazan de modo que cada nueva transacción gasta una salida de continuación de la anterior, produciendo una secuencia ordenada on-chain. Útil para demostrar el orden cronológico de los eventos. La primera transacción inicia la cadena; cada una de las siguientes se financia desde la salida de continuación de la transacción previa.
La política de anchoring se aplica en tres niveles. La política efectiva se resuelve de lo más específico primero — gana el primer nivel que defina un campo:
device override -> device profile -> tenant default -> platform default (most specific) (least specific)Así, un override de dispositivo vence a su perfil de dispositivo, que vence al
default del tenant, que vence al default integrado de la plataforma. Por ejemplo, si
un tenant tiene por defecto merkle_batch pero el perfil de dispositivo
critical-sensors establece per_event con required=true, un dispositivo que use
ese perfil se ancla per-event. Los perfiles de dispositivo se describen en
Perfiles de dispositivo.
| Campo | Significado |
|---|---|
mode | merkle_batch, per_event o hash_chain. |
required | Si el anchoring es obligatorio para que el punto sea aceptado. |
max_pending_age_seconds | Edad máxima que un punto puede permanecer pendiente antes de escalar. |
finality_confirmations | Confirmaciones requeridas antes de que una proof sea final (por defecto 6). |
backlog_action | accept_pending, throttle o reject cuando el backlog es alto. |
max_backlog_points | Umbral de backlog que dispara la acción de backlog. |
Cada punto aceptado tiene un registro explícito de ciclo de vida (en Aerospike,
namespace telemetry, set proof_state, indexado por
{tenant_id}:{device_id}:{data_hash_hex}, actualizado con CAS verificado por
generación). Avanza por estos estados:
stateDiagram-v2 [*] --> accepted: hash + lifecycle record written accepted --> validated: written to telemetry stores validated --> pending_batch: assigned to a batch pending_batch --> anchored: anchor tx broadcast (txid known) anchored --> confirmed: block inclusion observed confirmed --> final: confirmation depth >= threshold anchored --> failed_retryable: temporary failure confirmed --> failed_retryable: reorg invalidates tx failed_retryable --> pending_batch: retry scheduled failed_retryable --> failed_terminal: permanent failure final --> [*] failed_terminal --> [*]
| Estado | Significado |
|---|---|
accepted | Pasó la autenticación y el parseo; existe el registro de ciclo de vida. El punto no se reconoce al llamante hasta que esta escritura tiene éxito. |
validated | La validación de dispositivo/perfil pasó; escrito en los almacenes de telemetría. |
pending_batch | Hash asignado a un batch de anchoring. |
anchored | Transacción de anchoring difundida; txid conocido. |
confirmed | ARC o el SPV watcher observó la inclusión en bloque. |
final | La profundidad de confirmación alcanzó el umbral de finality. |
failed_retryable | Fallo temporal; se programa un reintento. |
failed_terminal | Fallo permanente que requiere acción del operador. |
Una transacción confirmada no se trata inmediatamente como irreversible. El
finality watcher rastrea las confirmaciones de cada txid anclado (los
registros de finality viven en Aerospike, namespace anchors, set finality,
indexados por {txid}). Cuando la profundidad de confirmación alcanza el
finality_confirmations de la política (por defecto 6), el registro de finality
se marca como final y cada registro de ciclo de vida de proof de ese txid avanza
de confirmed → final, publicándose un evento anchor.lifecycle.final.<tenant>.
La finality sobrevive a los reinicios: al arrancar, el watcher recarga el estado de finality y no degradará registros ya finales ni reemitirá eventos de finality.
Si una reorganización de la cadena elimina el bloque que contenía una transacción
anclada, la proof no debe reclamar silenciosamente la finality. El watcher detecta,
vía el SPV/ARC watcher, que el bloque que contiene un txid ya no está en la mejor
cadena (best chain), y entonces:
txid a reorged.failed_retryable.txid, block_height y block_hash previos en un campo
reorg_history.corem_anchor_reorg_events_total.Cuando el trabajo pendiente se acumula, el backlog_action de la política decide qué
ocurre con los puntos nuevos una vez que se supera max_backlog_points:
| Acción | Comportamiento |
|---|---|
accept_pending | Sigue aceptando puntos; se encolan como pendientes. |
throttle | Rechaza por encima de la tasa limitada (throttled) permitida con metadatos retry-after; no se crea registro de ciclo de vida para los puntos rechazados. Se escribe un evento de auditoría anchoring.backlog.throttled como mucho una vez por intervalo configurado. |
reject | Rechaza puntos nuevos con RESOURCE_EXHAUSTED / HTTP 429 y reason="anchoring_backlog_exceeded". |
Tanto throttle como reject incrementan sus respectivas métricas
(corem_anchor_backlog_rejections_total{tenant} para los rechazos).
El gasto de anchoring se atribuye de vuelta a los tenants para la contabilidad de
costes. El uso se agrega en Aerospike (namespace anchors, set tenant_usage,
indexado por {tenant_id}:{yyyymmdd}). Cuando se difunde una transacción de
anchoring, los registros de uso de cada tenant representado en ese batch se
actualizan de forma atómica — un batch de 900 puntos para el tenant T1 y 100 para T2
actualiza ambos. Cada registro lleva point_count, batch_count, token_count,
estimated_fee_sats, y la lista de txid, y la actualización es idempotente en
reintento usando el batch_id como clave de idempotencia.
Siguiente
Continúa con Verificación para ver cómo una proof final se comprueba de forma independiente y se exporta como un bundle portable.