Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions content/new-protocol-version.es.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
+++
title = "Nueva versión del protocolo Mostro"
date = "2026-06-18T12:00:00Z"

[extra]
author = "negrunch"
img = "/img/vesion2.jpg"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Image filename typo affects the Spanish post too.

The Spanish post references the same image path /img/vesion2.jpg on line 7. Ensure that once you correct the filename in the English post (line 7, file content/new-protocol-version.md), you also update it here.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@content/new-protocol-version.es.md` at line 7, The img variable assignment in
the Spanish post file contains a typo in the image filename: "vesion2.jpg" is
missing the letter 'r'. Locate the img variable declaration in
content/new-protocol-version.es.md and update the path from "/img/vesion2.jpg"
to "/img/version2.jpg" to match the corrected filename in the English post.

summary = "La versión 2 del protocolo Mostro deja atrás los gift wraps (NIP-59) para el envío de mensajes entre Mostro y los clientes, adoptando en su lugar eventos kind 14 con contenido encriptado mediante NIP-44. Este cambio cierra la ventana de ataque que bautizamos como \"Gift Wrap Apocalypse\", un vector de spam que, cualquiera podría usar para inutilizar un nodo Mostro, sin sacrificar la privacidad, ya que mantenemos la rotación de llaves por cada orden. La mejora llega en la versión 0.18.0 del nodo Mostro y, junto al anti-abuse bond, deja a Mostro listo para producción."
+++

## Cómo empezamos

Cuando comenzamos a trabajar en Mostro, teníamos que decidir de qué manera los clientes y el nodo Mostro se iban a comunicar. Los primeros experimentos los hicimos utilizando NIP-04, con el que encriptábamos la data en Nostr; en ese momento NIP-04 era el estándar.

NIP-04 tenía un problema: filtraba información de los usuarios, y esa información podía servir para que terceros los deanonimizaran. Como en los inicios de Mostro el usuario podía publicar órdenes utilizando cualquier llave privada, empezamos a notar que algunos usuarios usaban la misma llave privada con la que posteaban en clientes como Amethyst, Damus, etc., lo cual era todavía mucho más terrible para su privacidad.

Inmediatamente comenzamos a trabajar en una solución que le permitiera al usuario estar protegido sin afectar la UX de los clientes. Por eso pensamos, implementamos, repensamos y reimplementamos la primera versión del protocolo.

## La primera versión: gift wraps y rotación de llaves

Decidimos utilizar gift wraps (NIP-59), que nos venían como anillo al dedo, ya que ocultaban datos como el origen del mensaje: cada mensaje se envía con una llave efímera. Aun así, seguíamos teniendo un problema. Los mensajes que Mostro enviaba al cliente iban dirigidos a una pubkey única del usuario, y si los usuarios estaban usando la misma pubkey con la que posteaban en Damus, iba a ser muy sencillo vincularlos con Mostro.

Así que decidimos crear un sistema de rotación de llaves. En lugar de permitir al usuario ingresar una llave privada, hicimos que los clientes generaran una seed (BIP-39) y, a partir de ahí, el cliente generara una llave para cada orden que el usuario creara o tomara, al más puro estilo de una wallet de Bitcoin (BIP-32).

La implementación no era sencilla, pero el resultado era que el usuario obtenía un alto grado de privacidad.

## El "Gift Wrap Apocalypse"

En la teoría esto funciona muy bien, pero la utilización de gift wraps en Nostr abre una ventana de ataque a los relays y a los nodos Mostro. A este ataque yo lo llamo "Gift Wrap Apocalypse".

Como los gift wraps se envían con llaves efímeras y el timestamp modificado, un atacante puede enviar cualquier cantidad de estos eventos con basura dentro, espameando, y hasta que Mostro no los desencripte no sabrá si son eventos legítimos o no. Esto hace muy costoso resistir estos ataques, ya que desencriptar requiere recursos de Mostro. En teoría es muy fácil inutilizar un nodo Mostro enviando una gran cantidad de estos eventos; ahora, con IA, cualquier script kiddie sin ningún conocimiento técnico puede atacar a un nodo Mostro hasta dejarlo sin capacidad de respuesta.

Hasta ahora no hemos recibido este temido ataque, pero antes de que ocurra nos hemos adelantado y hemos decidido prescindir de los gift wraps para el envío de mensajes entre Mostro y los clientes. Sí, eliminamos una capa de privacidad, pero, siendo sinceros, al rotar llaves por cada orden seguimos manteniendo un alto grado de privacidad al operar en Mostro.

## La solución: kind 14 + NIP-44

En su lugar utilizamos eventos kind 14 con el contenido encriptado (NIP-44). Así, sin más, tan sencillo como eso. Hemos pasado de tener un contenido encriptado como este:

```json
// external wrap layer
{
"id": "<id>",
"kind": 1059,
"pubkey": "<Buyer's ephemeral pubkey>",
"content": {
// seal
"id": "<seal's id>",
"pubkey": "<index 0 pubkey (identity key)>",
"content": {
// rumor
"id": "<rumor's id>",
"pubkey": "<Index 1 pubkey (trade key)>",
"kind": 1,
"content": [
{
"order": {
"version": 1,
"id": "<Order Id>",
"trade_index": 1,
"action": "take-sell",
"payload": null
}
},
"<index 1 signature of the sha256 hash of the serialized first element of content>"
],
"created_at": 1691518405,
"tags": []
},
"kind": 13,
"created_at": 1686840217,
"tags": [],
"sig": "<index 0 pubkey (identity key) signature>"
},
"tags": [["p", "<Mostro's pubkey>"]],
"created_at": 1234567890,
"sig": "<Buyer's ephemeral pubkey signature>"
}
```

A este:

```json
[
{
"order": {
"version": 2,
"id": "<Order Id>",
"trade_index": 1,
"action": "take-sell",
"payload": null
}
},
"<index 1 signature of the sha256 hash of the serialized first element>",
["<index 0 pubkey (identity key)>", "<index 0 identity proof signature>"]
]
```

No ahondaré en detalles técnicos, ya que esto puedes verlo en la [documentación del protocolo](https://mostro.network/protocol/key_management.html).

## Versionado y disponibilidad

Esta mejora sale en la versión 0.18.0 de Mostro node. A partir de ahí, la versión 1 del protocolo queda deprecada, pero todavía se puede utilizar. En la versión 0.19.0, la opción de protocolo por defecto de Mostro será la "2", y todo rastro de la versión "1" será eliminado: es tiempo suficiente para que todos los clientes Mostro se actualicen.

Con esta mejora, junto al [anti-abuse bond](https://mostro.network/blog/es/anti-abuse-bond/), consideramos que Mostro está listo para ser utilizado en producción. Siempre teniendo en cuenta que es software experimental y seguramente con bugs por arreglar, pero confiamos en que tenemos un producto estable que brinde soluciones a quienes requieran poder comprar y vender Bitcoin libremente, sin miedo a la censura, represalias o vigilancia.
104 changes: 104 additions & 0 deletions content/new-protocol-version.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
+++
title = "A New Version of the Mostro Protocol"
date = "2026-06-18T12:00:00Z"

[extra]
author = "negrunch"
img = "/img/vesion2.jpg"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for image files in the static/img directory
fd -e jpg -e png -e webp 'vesion|version' --search-path static/img 2>/dev/null || echo "No static/img directory found or no matching images"
# Also check the PR diff for the actual filename
git diff HEAD~1 --name-only | grep -i "vesion\|version.*jpg" || echo "No image file changes in diff"

Repository: MostroP2P/blog

Length of output: 316


Correct the image filename from vesion2.jpg to version2.jpg in both front matter files.

The static file currently exists as static/img/vesion2.jpg with a typo (missing 'r'). While the front-matter path correctly matches this filename and the image will load, the filename itself should be corrected to version2.jpg for accuracy. Update both the English and Spanish posts' front matter to reference the corrected filename, and rename the actual static file accordingly.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@content/new-protocol-version.md` at line 7, Fix the typo in the image
filename by correcting `vesion2.jpg` to `version2.jpg`. Update the `img` field
in the front matter of both the English and Spanish versions of the protocol
version posts to reference the corrected filename with the proper spelling.
Additionally, rename the actual static image file from `vesion2.jpg` to
`version2.jpg` to match the corrected reference.

summary = "Version 2 of the Mostro protocol leaves gift wraps (NIP-59) behind for messaging between Mostro and clients, adopting instead kind 14 events with content encrypted via NIP-44. This change closes the attack window we nicknamed the \"Gift Wrap Apocalypse\", a spam vector that, anyone could use to take down a Mostro node, without sacrificing privacy, since we keep rotating keys for every order. The improvement ships in version 0.18.0 of the Mostro node and, together with the anti-abuse bond, makes Mostro ready for production."
+++

## How we started

When we began working on Mostro, we had to decide how clients and the Mostro node would communicate. Our first experiments used NIP-04, which we used to encrypt data on Nostr; at that time NIP-04 was the standard.

NIP-04 had a problem: it leaked user information, and that information could help third parties deanonymize them. Since in Mostro's early days a user could publish orders using any private key, we started to notice that some users were using the same private key they posted with on clients like Amethyst, Damus, etc., which was far more terrible for their privacy.

We immediately started working on a solution that would keep the user protected without hurting the clients' UX. So we thought, implemented, rethought, and reimplemented the first version of the protocol.

## The first version: gift wraps and key rotation

We decided to use gift wraps (NIP-59), which fit us like a glove since they hid data such as the origin of the message: each message is sent with an ephemeral key. Even so, we still had a problem. The messages Mostro sent to the client were addressed to a unique user pubkey, and if users were using the same pubkey they posted with on Damus, it would be very easy to link them to Mostro.

So we decided to create a key rotation system. Instead of letting the user enter a private key, we made the clients generate a seed (BIP-39) and, from there, the client would generate a key for every order the user created or took, in the purest Bitcoin wallet style (BIP-32).

The implementation wasn't simple, but the result was that the user obtained a high degree of privacy.

## The "Gift Wrap Apocalypse"

In theory this works very well, but using gift wraps on Nostr opens an attack window against relays and Mostro nodes. I call this attack the "Gift Wrap Apocalypse".

Since gift wraps are sent with ephemeral keys and a modified timestamp, an attacker can send any number of these events with garbage inside, spamming, and until Mostro decrypts them it won't know whether they are legitimate events or not. This makes resisting these attacks very costly, because decrypting requires Mostro's resources. In theory it's very easy to take down a Mostro node by sending a large number of these events; now, with AI, any script kiddie with no technical knowledge can attack a Mostro node until it's left unable to respond.

So far we haven't received this dreaded attack, but before it happens we've gotten ahead of it and decided to drop gift wraps for messaging between Mostro and clients. Yes, we removed a layer of privacy, but, to be honest, by rotating keys for each order we still maintain a high degree of privacy when operating on Mostro.

## The solution: kind 14 + NIP-44

Instead we use kind 14 events with encrypted content (NIP-44). Just like that, as simple as that. We've gone from having encrypted content like this:

```json
// external wrap layer
{
"id": "<id>",
"kind": 1059,
"pubkey": "<Buyer's ephemeral pubkey>",
"content": {
// seal
"id": "<seal's id>",
"pubkey": "<index 0 pubkey (identity key)>",
"content": {
// rumor
"id": "<rumor's id>",
"pubkey": "<Index 1 pubkey (trade key)>",
"kind": 1,
"content": [
{
"order": {
"version": 1,
"id": "<Order Id>",
"trade_index": 1,
"action": "take-sell",
"payload": null
}
},
"<index 1 signature of the sha256 hash of the serialized first element of content>"
],
"created_at": 1691518405,
"tags": []
},
"kind": 13,
"created_at": 1686840217,
"tags": [],
"sig": "<index 0 pubkey (identity key) signature>"
},
"tags": [["p", "<Mostro's pubkey>"]],
"created_at": 1234567890,
"sig": "<Buyer's ephemeral pubkey signature>"
}
```

To this:

```json
[
{
"order": {
"version": 2,
"id": "<Order Id>",
"trade_index": 1,
"action": "take-sell",
"payload": null
}
},
"<index 1 signature of the sha256 hash of the serialized first element>",
["<index 0 pubkey (identity key)>", "<index 0 identity proof signature>"]
]
```

I won't dive into technical details, since you can see this in the [protocol documentation](https://mostro.network/protocol/key_management.html).

## Versioning and availability

This improvement ships in version 0.18.0 of the Mostro node. From there, version 1 of the protocol is deprecated but can still be used. In version 0.19.0, Mostro's default protocol option will be "2", and every trace of version "1" will be removed: enough time for all Mostro clients to update.

With this improvement, together with the [anti-abuse bond](https://mostro.network/blog/anti-abuse-bond/), we consider Mostro ready to be used in production. Always keeping in mind that it's experimental software and surely has bugs to fix, but we trust we have a stable product that provides solutions to those who need to be able to buy and sell Bitcoin freely, without fear of censorship, retaliation, or surveillance.
Binary file added static/img/vesion2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.