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 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 de BSV — 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 device_id, el timestamp (segundos Unix) y el payload originales, calcula SHA256(device_id_utf8 || timestamp_uint64_be || jcs_payload_utf8) exactamente como en Hashing y Merkle trees. 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:

    current = data_hash
    for step in merkle_path:
    if step.is_right:
    current = SHA256(current || step.hash)
    else:
    current = 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. El blob BEEF lleva la Merkle proof de la transacción dentro de su bloque, así que puedes verificar la inclusión en el block_height declarado de forma offline. Opcionalmente, contrasta contra cualquier nodo de BSV o explorador de bloques que el hash del bloque a esa altura coincide y contiene el txid. 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}, codifica "D1" como 0x4431 y el timestamp como 0x0000000065FBC9C0, concatena device_id || timestamp || payload, y haz SHA-256 del resultado. 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_batch, per_event o hash_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 para proofs SPV (Simplified Payment Verification). En lugar de requerir un nodo completo y toda la cadena de cabeceras de bloque, BEEF agrupa en un solo blob todo lo necesario para verificar una transacción:

  1. La transacción en sí.
  2. Sus transacciones ancestras (probando que las entradas son válidas).
  3. Merkle proofs que enlazan cada transacción con su cabecera de bloque.
  4. Las cabeceras de bloque relevantes.

CORE-M construye el blob BEEF cuando la transacción de anchoring se confirma — combinando la transacción de anchoring, su transacción ancestra (de financiación), y las Merkle proofs de ambas — y almacena el hex con el registro de proof. Un verificador decodifica BEEF para extraer el OP_RETURN, verificar la inclusión en bloque vía la Merkle proof incrustada, y confirmar que la transacción pertenece a la cadena más larga — todo lo cual es lo que hace posibles los pasos 3 y 4 de arriba de forma offline.

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.