Cómo escribir smart contracts en Midnight

Una introducción práctica al desarrollo privacy-first

Midnight es una blockchain diseñada desde cero para resolver uno de los mayores problemas del ecosistema: cómo construir aplicaciones descentralizadas sin exponer datos sensibles. A diferencia de la mayoría de las blockchains —donde todo es público o todo es privado— Midnight introduce un modelo más fino: selective disclosure.

En este artículo veremos cómo se escribe un smart contract en Midnight, qué lo hace distinto y cómo pensar el desarrollo cuando la privacidad no es un parche, sino una propiedad del lenguaje.

El modelo mental: privacidad por defecto

Antes de escribir una sola línea de código, hay que cambiar el enfoque.

En Midnight:

Todo lo que viene del usuario es privado por defecto

Nada se puede hacer público “por accidente”

La privacidad se controla explícitamente, no implícitamente

Esto se logra gracias a Compact, el lenguaje de smart contracts de Midnight, y al uso de Zero-Knowledge Proofs (zkSNARKs) para validar transacciones sin revelar datos.

¿Qué es Compact?

Compact es un lenguaje declarativo diseñado específicamente para construir aplicaciones privacy-first.

Cuando escribes un contrato en Compact:

Defines la lógica de negocio

Defines qué datos son públicos

Defines qué datos permanecen privados

El compilador genera:

APIs en JavaScript / TypeScript para tu DApp

Los artefactos criptográficos necesarios para generar pruebas ZK

Todo esto ocurre localmente en el entorno del desarrollador.

Componentes básicos de un contrato en Compact

Todo contrato en Midnight se construye a partir de los mismos bloques:

  1. Ledger state (estado público)

Datos que viven en la cadena y son visibles para todos.

export ledger value: Uint<64>;

  1. Witnesses (entradas privadas)

Los witnesses representan datos que vienen del usuario o del frontend.
Son privados por defecto y Compact no permite que se filtren accidentalmente.

witness getSecret(): Bytes<32>;

  1. Circuits (lógica verificable)

Los circuits definen qué puede hacer el contrato.
Solo los circuits marcados como export pueden ser llamados desde fuera.

export circuit get(): Uint<64> {
return value;
}

  1. Constructor

Se ejecuta una sola vez, al crear el contrato.

constructor(sk: Bytes<32>, v: Uint<64>) {
value = v;
}

Selective disclosure: disclose()

Una de las reglas más importantes de Compact es esta:

No puedes hacer público un dato privado sin decirlo explícitamente.

Si intentas usar un witness directamente en el ledger o como retorno, el compilador falla.

Forma correcta:

export ledger publicData: Bytes<32>;

export circuit record(): [] {
publicData = disclose(getSecret());
}

Forma incorrecta (error de compilación):

publicData = getSecret(); // ❌

Esto elimina una clase completa de errores comunes en otros ecosistemas.

Opaque types: cuando Compact no debe “mirar” el dato

Compact permite tipos opacos como:

Opaque<‘string’>

Estos tipos:

Pueden almacenarse o transferirse

No pueden ser inspeccionados dentro del contrato

Son visibles en el frontend (TypeScript), pero no manipulables en Compact

Son útiles para:

Mensajes

Metadatos

Contenido arbitrario (ej. bulletin boards)

Compromisos y hashing

Para probar propiedades sobre datos sin revelarlos, Compact incluye primitivas criptográficas:

persistentCommit(value, random);
transientCommit(value);

Estas funciones son clave para:

Votaciones privadas

Identidad verificable

Autenticación sin revelar credenciales

El rol del proof server

Toda la magia ZK ocurre fuera de la blockchain.

El proof server:

Corre localmente o en infraestructura controlada

Nunca expone datos privados a la red

Solo devuelve pruebas criptográficas válidas

Esto permite que:

La blockchain valide hechos

Sin conocer los datos subyacentes

Cómo pensar un contrato en Midnight

Al escribir en Midnight, conviene preguntarse:

¿Este dato realmente debe ser público?

¿Qué necesita verificar la red y qué no?

¿Puedo probar esta condición sin revelar el valor?

¿Quién controla el proof server?

Compact no solo te da herramientas, te obliga a pensar bien el modelo de datos.

Conclusión

Escribir smart contracts en Midnight no es solo aprender un nuevo lenguaje.
Es adoptar una forma distinta de diseñar aplicaciones descentralizadas:

Privacidad por defecto

Disclosure explícito

Separación clara entre datos, lógica y pruebas

Seguridad reforzada a nivel de compilador

Si vienes de ecosistemas como Solidity o Plutus, Compact puede sentirse distinto al principio. Pero una vez que el modelo hace clic, es difícil volver atrás.

La privacidad deja de ser un “feature” y pasa a ser parte del lenguaje.

Similar Posts