Has llegado al final de la sección de Anchoring
Vuelve a la Visión general del anchoring, o repasa el commitment exacto en Hashing y Merkle trees.
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:
device_id, timestamp (segundos Unix), y el payload
de telemetría.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.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.
Úsalo cuando tienes los campos originales y quieres que CORE-M calcule el hash por
ti. Recomputa SHA256(device_id_utf8 || timestamp_uint64_be || jcs_payload_utf8) —
el mismo algoritmo que el servicio de telemetría — busca el resultado, y devuelve la
misma forma de respuesta que verificar-por-hash.
curl -X POST https://<host>/api/v1/verify/raw \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "device_id": "D1", "timestamp": "2024-03-21T05:46:40Z", "numeric_values": {"temperature": 22.5, "humidity": 65}, "string_values": {} }'Si los datos suministrados difieren aunque sea ligeramente de lo que se ancló, el
hash recomputado no coincidirá con ninguna proof almacenada y la respuesta es
NOT_FOUND.
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.
Un verificador no tiene que confiar en el flag verified de la API — puede rehacer
la proof de principio a fin. Cuatro pasos:
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.
Recorre el Merkle path. Partiendo de data_hash, pliega (fold) cada hermano
usando su dirección hasta llegar al root:
current = data_hashfor step in merkle_path: if step.is_right: current = SHA256(current || step.hash) else: current = SHA256(step.hash || current)# current is the reconstructed Merkle rootComprueba 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.
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}.
{"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.merkle_path de arriba — ambas
is_right — plegando el hash hacia la derecha en cada paso para llegar al root.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.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:
| Campo | Propósito |
|---|---|
canonical_hash_inputs | El device_id exacto, el timestamp en segundos Unix, y el payload JCS usados para calcular el hash. |
merkle_path | Los hashes hermanos con direcciones, de la hoja al root. |
merkle_root | El root reconstruido/comprometido. |
txid | El ID de la transacción de anchoring. |
raw_tx o beef_hex | La transacción, como BEEF o cruda, para comprobación offline. |
block_header_chain | Cabeceras de bloque que establecen la inclusión y el contexto de cadena. |
confirmation_depth | Cuántas confirmaciones de profundidad tiene la transacción. |
anchor_mode | merkle_batch, per_event o hash_chain. |
verification_steps | Pasos legibles por humanos que reflejan el procedimiento de arriba. |
schema_version | Versió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:
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.
Has llegado al final de la sección de Anchoring
Vuelve a la Visión general del anchoring, o repasa el commitment exacto en Hashing y Merkle trees.