OTSkit.ts
← Paquetes·v0.2.0

@otskit/core

La implementación TypeScript pura del protocolo OpenTimestamps. Sin dependencias externas, validación estricta y control total sobre pruebas .ots, operaciones criptográficas, attestations y Merkle trees.

Zero depsTypeScriptNode ≥ 20ESM + CJSMITFail-closed

Qué es Core

Qué es Core

Core es la capa de bajo nivel. Te da las piezas del protocolo: DetachedTimestampFile, Timestamp, operaciones hash, attestations, serialización binaria y verificación contra block headers.

Core trabaja con el protocolo y el formato .ots. No es el SDK de red para hablar con calendarios. Para stamp → upgrade → verify en producción, usa @otskit/client.

Cuándo usarlo

Cuándo usarlo

Usa Core si…

  • Quieres manipular .ots directamente
  • Quieres construir Merkle trees
  • Quieres verificar contra block headers
  • Quieres integrar el protocolo en otra herramienta

Usa Client si…

  • Quieres sellar archivos contra calendarios
  • Quieres retries, circuit breaker y upgrade automático
  • Quieres una API stamp / upgrade / verify lista para producción
  • Quieres empezar rápido

Mapa del protocolo

Mapa del protocolo

bytes / hashDetachedTimestampFileTimestampOpsAttestations.ots bytes
bytes / hash
El contenido del archivo o un digest ya calculado.
DetachedTimestampFile
Envoltorio del .ots: liga el digest con su árbol de prueba.
Timestamp
El árbol de prueba. Cada nodo es un mensaje intermedio.
Ops
Las operaciones que transforman un nodo en el siguiente.
Attestations
Hojas del árbol: pending, Bitcoin o Litecoin.
.ots bytes
El árbol serializado al formato binario OTS.

Primitivas

Primitivas del protocolo

DetachedTimestampFile

El envoltorio del .ots. Liga el digest del archivo con su árbol de prueba y se encarga de serializar y deserializar.

Timestamp

Un nodo del árbol de prueba. Se construye aplicando operaciones y se fusiona con merge() para unir ramas y attestations.

Ops

Las operaciones del protocolo: SHA-256, SHA-1, RIPEMD-160 y append / prepend / reverse / hexlify.

Attestations

Las hojas del árbol: pending (referencia a un calendario), Bitcoin, Litecoin y unknown para tipos futuros.

Merkle

Construye un solo árbol Merkle a partir de muchos documentos para sellar miles de pruebas con una única ancla.

Serialization

Lee y escribe el formato binario OTS. Estricta con Uint8Array, sin coerciones silenciosas.

Instalación

Instalación

$ npm install @otskit/core
$ pnpm add @otskit/core
$ yarn add @otskit/core

Ejemplos

Ejemplos

Estos ejemplos crean y manipulan la prueba localmente. Para enviarla a calendarios y hacer upgrade, usa @otskit/client.

Crear una prueba .ots local

Construye el árbol desde los bytes del archivo y le añade una attestation pending — una referencia al calendario, todavía sin confirmar en Bitcoin.

create.tsnode
import { DetachedTimestampFile, OpSHA256, makePending } from '@otskit/core'
import { readFileSync, writeFileSync } from 'node:fs'

const content = new Uint8Array(readFileSync('document.pdf'))
const dtf = DetachedTimestampFile.fromBytes(new OpSHA256(), content)

dtf.timestamp.attestations.push(
  makePending('https://alice.btc.calendar.opentimestamps.org')
)

writeFileSync('document.pdf.ots', dtf.serializeToBytes())
user@host:~/project$ node create.ts

Leer un .ots

Deserializa una prueba existente e inspecciona su digest y si ya está completa.

read.tsnode
import { DetachedTimestampFile } from '@otskit/core'

const otsBytes = new Uint8Array(readFileSync('document.pdf.ots'))
const dtf = DetachedTimestampFile.deserialize(otsBytes)

console.log('Hash op:  ', dtf.fileHashOp.tagName)
console.log('Digest:   ', Buffer.from(dtf.fileDigest()).toString('hex'))
console.log('Complete: ', dtf.timestamp.isTimestampComplete())
user@host:~/project$ node read.ts
Hash op: SHA256
Digest: a3f1c2...d84e
Complete: true

Verificar contra un block header

Recorre las attestations Bitcoin del árbol y comprueba el digest contra el Merkle root del bloque.

verify.tsnode
import { DetachedTimestampFile, verifyAgainstBlockheader } from '@otskit/core'

const dtf = DetachedTimestampFile.deserialize(new Uint8Array(readFileSync('document.pdf.ots')))

for (const { msg, attestation } of dtf.timestamp.allAttestations()) {
  if (attestation.tagName === 'bitcoin') {
    const ok = verifyAgainstBlockheader(msg, blockHeader)
    console.log('Bloque', attestation.height, ok ? '✓ verificado' : '✗ fallo')
  }
}

Crear un Merkle tree

Une muchos documentos en un solo árbol — una única ancla para miles de pruebas.

merkle.tsnode
import { makeMerkleTree, makePending, DetachedTimestampFile, OpSHA256 } from '@otskit/core'

const files = ['a.pdf', 'b.pdf', 'c.pdf']
const dtfs = files.map(f =>
  DetachedTimestampFile.fromBytes(new OpSHA256(), new Uint8Array(readFileSync(f)))
)

// Un solo árbol Merkle — una sola ancla para todos
const root = makeMerkleTree(dtfs.map(d => d.timestamp))
root.attestations.push(makePending('https://alice.btc.calendar.opentimestamps.org'))

files.forEach((f, i) => writeFileSync(`${f}.ots`, dtfs[i].serializeToBytes()))

Fail-closed por diseño

Fail-closed por diseño

Una attestation pending no es una confirmación Bitcoin: es una referencia a un calendario. La prueba se vuelve completa cuando aparece una attestation Bitcoin o Litecoin. Core nunca finge que una prueba está completa cuando no lo está.

Rechaza entradas malformadas

Cada frontera valida antes de seguir. Un .ots corrupto falla en la deserialización, no más tarde.

Uint8Array estricto

No acepta strings ni Buffers ambiguos donde espera bytes. El tipo es el contrato.

Sin coerciones silenciosas

Nunca adivina ni rellena valores por ti. Si algo no encaja, lo dice.

Errores tipados

Errores distintos para deserialización, operaciones, verificación y Merkle. Puedes ramificar con instanceof.

API surface

API surface

DetachedTimestampFile

DetachedTimestampFile.fromBytes(op, content)Crea desde bytes de archivo
DetachedTimestampFile.fromHash(op, digest)Crea desde digest pre-computado
.deserialize(bytes: Uint8Array)Parsea archivo .ots — solo Uint8Array, fail-closed
.serializeToBytes()Serializa a bytes .ots
.fileDigest()Retorna el digest del archivo
.timestampNodo raíz del árbol de prueba

Timestamp

new Timestamp(msg)Crea nodo hoja
.add(op)Aplica operación, retorna sub-timestamp
.merge(other)Fusiona attestations y ramas
.isTimestampComplete()true si existe attestation Bitcoin o Litecoin
.allAttestations()Todos los pares {msg, attestation} en el árbol

Operaciones criptográficas

OpSHA256SHA-256 (tag 0x08)
OpSHA1SHA-1 (tag 0x02)
OpRIPEMD160RIPEMD-160 (tag 0x03)
OpAppend(suffix)Concatena sufijo (tag 0xf0)
OpPrepend(prefix)Prepend prefijo (tag 0xf1)

Attestations y Merkle

makePending(uri)Attestation pendiente de calendario
makeBitcoin(height)Attestation de blockchain Bitcoin
makeLitecoin(height)Attestation de blockchain Litecoin
makeMerkleTree(timestamps)Construye Merkle-Mountain-Range
verifyAgainstBlockheader(digest, header)Verifica digest contra Merkle root de bloque

Siguiente paso

Si quieres usar esto en producción contra calendarios OpenTimestamps, sigue con @otskit/client.

@otskit/client — SDK de producción →