Ir al contenido

Verificación

El sentido del anchoring es que un tercero puede demostrar que un punto de datos existió y no está alterado sin necesidad de confiar en CORE-M. Esta página muestra las dos APIs de verificación, el procedimiento manual que sigue un verificador, el bundle de proof portable y autocontenido, y qué es BEEF. Asume que conoces el hash canónico y el Merkle path de Hashing y Merkle trees.

Para verificar un punto solo necesitas:

  1. Los datos originalesdevice_id, timestamp (segundos Unix), y el payload de telemetría.
  2. La proof — el Merkle path, el txid, y la transacción BEEF, de la API de verificación de CORE-M, del proof store de PostgreSQL, o de un bundle portable compartido fuera de banda.
  3. Acceso a la blockchain — cualquier nodo o explorador de bloques.

No se requiere acceso a los servicios en ejecución de CORE-M para la verificación en sí.

CORE-M expone dos endpoints que automatizan la búsqueda. Consulta Visión general de la API para la autenticación y las URLs base.

Úsalo cuando ya dispones del data_hash de 32 bytes.

GET /api/v1/verify/hash/<data_hash_hex>

Busca en el proof store y devuelve la proof de ese hash. Si no existe ninguna proof, la respuesta es NOT_FOUND con "no blockchain proof found for this data hash — it may be pending or nonexistent". Si el mismo hash se ancló en más de un batch (re-anchoring), se devuelve la proof más reciente — la que tiene el block_height más alto.

Ambos endpoints devuelven la misma proof:

{
"txid": "c3d4e5f6a1b2...",
"block_height": 850000,
"block_hash": "00000000000000000abc...",
"confirmed_at": "2024-03-21T08:31:12Z",
"batch_id": "8f14e45f-ceea-467a-9f3b-2c1d4e5f6a7b",
"merkle_path": [
{ "hash": "9a0c...", "is_right": true },
{ "hash": "4f7b...", "is_right": true }
],
"beef_hex": "0100beef..."
}

merkle_path es un array de entradas {hash, direction} (la dirección se expresa como is_right), y beef_hex es la transacción BEEF codificada en hex — explicada más abajo.

Cómo verifica un tercero de forma independiente

Sección titulada «Cómo verifica un tercero de forma independiente»

Un verificador no tiene que confiar en el flag verified de la API — puede rehacer la proof de principio a fin. Cuatro pasos:

  1. Recomputa el data hash. A partir del tenant_id, el device_id, el timestamp (segundos Unix) y el payload originales, calcula el leaf hash de doble SHA-256 SHA256(SHA256(preimage)) exactamente como en Hashing y Merkle trees — incluyendo el byte de versión, los prefijos de longitud de tenant_id/device_id, y el propio tenant_id. Confirma que equivale al data_hash de la proof. Esto prueba que los datos no han sido alterados.

  2. Recorre el Merkle path. Partiendo de data_hash, pliega (fold) cada hermano usando su dirección hasta llegar al root (doble SHA-256 en cada paso):

    current = data_hash
    for step in merkle_path:
    if step.is_right:
    current = SHA256(SHA256(current || step.hash))
    else:
    current = SHA256(SHA256(step.hash || current))
    # current is the reconstructed Merkle root
  3. Comprueba el OP_RETURN en la transacción BEEF. Decodifica el blob BEEF, localiza la salida OP_FALSE OP_RETURN, y lee su payload: "CORE-M" || merkle_root(32) || batch_id(16) || timestamp(8) || count(4). Confirma que el merkle_root incrustado equivale al root que reconstruiste en el paso 2. Esto prueba que tu punto está comprometido por esta transacción on-chain.

  4. Confirma la inclusión en bloque. La proof registra el block_height y el block_hash que ARC reportó al confirmar la transacción. CORE-M no verifica de forma independiente la inclusión en bloque ni la pertenencia a la cadena más larga offline — la confirmación confía en el bloque reportado por ARC. Para comprobar la inclusión tú mismo, contrasta el txid contra cualquier nodo de la blockchain o explorador de bloques en el block_height declarado. La posición del bloque en la cadena es tu cota inferior de cuándo existieron los datos.

Toma el punto de Hashing y Merkle trees: device_id="D1", timestamp=1711000000, payload {"temperature":22.5,"humidity":65}.

  1. Recomputa. Canonicaliza a {"humidity":65,"temperature":22.5}, luego construye el preimage 0x01 · tenant_id (con prefijo de longitud, T1) · device_id (con prefijo de longitud, D1) · timestamp 0x0000000065FBC9C0 · los bytes del payload JCS, y haz SHA256(SHA256(...)). Para este punto el leaf hash es 9774d8af1f5e5a0457275ec82b482e0e1b46f6fc421720a279d0e661f99755d2. Confirma que equivale al data_hash devuelto por la API.
  2. Recorre. Aplica las dos entradas de merkle_path de arriba — ambas is_right — plegando el hash hacia la derecha en cada paso para llegar al root.
  3. Decodifica BEEF. Extrae el payload del OP_RETURN de la transacción BEEF, lee el merkle_root de 32 bytes en el offset 6, y comprueba que coincide con tu root reconstruido.
  4. Confirma. Verifica que la Merkle proof de la transacción la sitúa en el bloque 850000, y (opcionalmente) que un explorador de bloques coincide en que el bloque a la altura 850000 tiene el hash 00000000000000000abc... y contiene el txid.

Si los cuatro pasos pasan, el punto existió de forma demostrable en el momento de ese bloque y no ha cambiado desde entonces.

Para cualquier punto de datos final, la API puede devolver un bundle de proof portable autocontenido (solicita include_bundle=true en verificar-por-hash). Lleva todo lo que un verificador externo necesita para validar el commitment sin volver a llamar a CORE-M tras la descarga.

El bundle contiene:

CampoPropósito
canonical_hash_inputsEl device_id exacto, el timestamp en segundos Unix, y el payload JCS usados para calcular el hash.
merkle_pathLos hashes hermanos con direcciones, de la hoja al root.
merkle_rootEl root reconstruido/comprometido.
txidEl ID de la transacción de anchoring.
raw_tx o beef_hexLa transacción, como BEEF o cruda, para comprobación offline.
block_header_chainCabeceras de bloque que establecen la inclusión y el contexto de cadena.
confirmation_depthCuántas confirmaciones de profundidad tiene la transacción.
anchor_modemerkle, per_event o chain.
verification_stepsPasos legibles por humanos que reflejan el procedimiento de arriba.
schema_versionVersión del schema del bundle.

El bundle se valida contra el JSON schema publicado, de modo que un verificador puede comprobar su estructura por máquina antes de confiar en su contenido.

BEEF — Background Evaluation Extended Format — es un formato binario compacto asociado a las proofs SPV (Simplified Payment Verification). CORE-M almacena una variante interna de Core-M de BEEF BRC-62: una única transacción (la transacción de anchoring) más, cuando está disponible, su Merkle path on-chain (un BUMP). No agrupa transacciones ancestras (de financiación) ni cabeceras de bloque, y no está pensada para intercambiarse con consumidores externos de BEEF — es un formato de almacenamiento interno para el registro de proof.

CORE-M construye este blob cuando la transacción de anchoring se confirma y almacena el hex con el registro de proof. Un verificador lo decodifica para extraer el OP_RETURN y leer el merkle_root comprometido (paso 3). Como el blob no lleva cabeceras de bloque, la inclusión en bloque no se re-verifica de forma independiente a partir de él — ver el paso 4.

Las proofs confirmadas se persisten en PostgreSQL (anchor_proofs): data_hash, batch_id, merkle_path (JSONB), txid, beef_hex, block_height, block_hash, confirmed_at, tenant_id, y device_id.