Cómo Funciona el Contrato de Garantía (Escrow) No Custodio de Bitcoin

LocalCryptos ha sido lanzado — un nuevo criptomercado entre pares.

En Noviembre del 2019, LocalCryptos lanzó los contratos de garantía (también referidos como ‘escrows’) de Bitcoin. Copiamos el concepto de nuestro escrow de Ethereum y tradujimos el código a un script compatible con Bitcoin.

En este artículo, explicaremos cómo funciona.

Este artículo presupone que entiendes de Bitcoin a un nivel técnico. Trataremos de explicar conceptos sencillos, pero si no sabes qué significa el término UTXO, tal vez tengas problemas siguiéndonos.

Esta configuración es no-custodia de inicio a fin. Los servidores de LocalCryptos solo almacenan blobs cifrados que no se diferencian de pura algarabía. Nuestros servidores no generan ninguna de las transacciones aquí descritas—todo está en el JavaScript de tu navegador.

Nuestras raíces en Ethereum

Antes de renombrar la plataforma a LocalCryptos, solíamos llamarnos LocalEthereum. LocalEthereum fue la primera plataforma de criptocomercio entre pares para Ethereum. También fue la rampa comercial fiat-a-cripto P2P más popular después de PaxFul y LocalBitcoins.

LocalEthereum no se trataba de un simple clon de LocalBitcoins. Aunque la experiencia de usuario fuera similar, lo que había dentro del capó de LocalEthereum era una monstruosidad. Fue la única plataforma con mensajería cifrada de extremo a extremo, y carteras web no custodias. También fue la primera en introducir un “contrato de garantía no custodio”, que suena como un oxímoron. Te explicamos qué significa eso:

En lugar de mantener las criptomonedas en garantía dentro de una cartera en sus servidores, utiliza un contrato inteligente de Ethereum. El ether (ETH) se transferiría del vendedor al contrato inteligente, y de éste al comprador. El contrato inteligente establece las reglas de antemano en forma descentralizada. Al utilizar un contrato inteligente en lugar de un custodio, el escrow está libre de intermediarios.

Ahora, hemos desarrollado lo mismo para Bitcoin. Excepto que Bitcoin no tiene contratos inteligentes—tiene Scripts. Los Scripts son como contratos inteligentes en ciertos casos, pero muy diferentes en otros.

¿Qué hay en una transacción de Bitcoin?

Las transacciones de Bitcoin contienen inputs (entradas) y outputs (salidas). Cada output contiene una dirección recipiente—que es a donde vas a enviar el bitcoin—y cuánto va a recibir dicha dirección. Las inputs apuntan a outputs previas—que son monedas que has recibido, pero no has gastado aún.

Las “direcciones” de Bitcoin son algo raro de describir. En un sentido, no son una parte del protocolo—de hecho, no son mencionadas en el white paper de Satoshi Nakamoto.

1MoNS93aYgeuCcojcYbAJpKxqDN9UuJa9C

Existen diferentes tipos de direcciones Bitcoin. Cuando decodificas una dirección de Bitcoin, te encuentras con dos partes: un identificador de versión, y un payload. El campo versión está al inicio, y le dice a tu cartera Bitcoin el tipo de dirección con la que está lidiando. El uso del payload depende de la versión.

Una dirección que empieza con un 1 es una dirección Pay-to-Public-Key-Hash (P2PKH), la versión de la mayoría de las direcciones. Una dirección que empieza con un 3 es una dirección Pay-to-Script-Hash (P2SH). Quizás llegues a ver otros prefijos de direcciones, como el de una dirección SegWit nativa. Por el bien de este artículo, solamente las direcciones P2SH y P2PKH son relevantes para entender.

Los estándares de una dirección describen cómo crear los puzzles (acertijos), y cómo crear soluciones para desbloquearlos. La solución al puzzle permite al recipiente utilizar un output como un input para otra transacción.

Alice envía a Bob algo de dinero a la escuela antigua

En una dirección P2PKH, el payload que sigue a la versión es un hash de la clave pública del recipiente. La función hash utilizada es “hash160”, que se traduce a RIPEMD160(SHA256(thing)).

Cuando Alice quiere enviar un pago a Bob, ella crea un puzzle conocido como ScriptPubKey que sólo Bob puede resolver. El puzzle se convierte en un output para su transacción de Bitcoin.

Para que Bob pueda gastar este output, necesita utilizarlo como un input en otra transacción de Bitcoin. Y para hacer eso, necesita crear un ScriptSig válido correspondiente al ScriptPubKey.

Todo ScriptPubKey P2PKH sigue esta plantilla:

OP_DUP OP_HASH160 <PubKeyHash> OP_EQUAL OP_CHECKSIG

Y un ScriptSig P2PKH está en el formato:

<Signature> <PubKey>

OP_Que?

Un ScriptPubKey de un output es un pedazo de código. Está en un lenguaje de programación basando en stacks, único a Bitcoin, llamado “Script”.

Un ScriptSig es también un pedazo de código, pero, de acuerdo con las reglas de consenso de Bitcoin, sólo puede contener “datos push”. En palabras simples, no puede hacer más que agregar datos arbitrarios al stack.

En este ejemplo de P2PKH, el ScriptSign de Bob está agregando dos cosas al stack:

Revisando que el ScriptSig esté correcto

Antes de que un minero pueda incluir esta transacción en un bloque, confirmará que el ScriptSig está correcto para el ScriptPubKey.

El minero agrega el ScriptPubKey al final del ScriptSig, y ejecuta el código. Luego de que se corre la última línea de código, el stack debe terminar con el elemento superior como verdadero (distinto de cero). Esto es lo necesario para verificar un ScriptSig.

<Signature> <PubKey> OP_DUP OP_HASH160 <PubKeyHash> OP_EQUALVERIFY OP_CHECKSIG

Como pueden ver, el stack termina en “true” (verdadero). Si quieres saber más sobre P2PKH y por qué es popular, hay muchos recursos en la web. Busca en Google “P2PKH” para saber más.

¿Qué es una dirección P2SH?

Las direcciones Pay-to-Script-Hash transfieren la responsabilidad de proporcionar las condiciones de pago al gastador.

¿Recuerdan cuando dije hace un momento que el ScriptSig del gastador no puede incluir código que no sea de datos? Olviden eso por un momento— el P2SH lo cambia todo.

En lugar de escribir las condiciones de gasto dentro del ScriptPubKey, ese código va dentro de un RedeemScript. Y sí, eso es un nuevo término—en palabras muy sencillas, se refiere al puzzle “real” para el output (salida). Cuando envías las monedas a una dirección P2SH, el ScriptPubKey contiene un hash del código de las condiciones de gasto. Se ve así:

OP_HASH160 <RedeemScriptHash> OP_EQUAL

Un gastador de un input (entrada) deP2SH proporciona dos elementos en su ScriptSig:

Los mineros verificarán, en primer lugar, que el hash del RedeemScript coincida con el hash que hay en el ScriptPubKey. De ser cierto, desempaquetará el RedeemScript, pondrá el Signature por encima, y lo ejecutará.

¿Qué es una dirección P2WSH?

LocalCryptos utiliza direcciones Pay-to-Witness-Script-Hash (P2WSH) para los contratos de garantía, en lugar de P2SH. Para ser precisos, utilizamos un P2WSH envuelto dentro de un P2SH (p.ej. P2SH-P2WSH).

La diferencia entre un P2WSH y un P2SH es que en un P2WSH, el RedeemScript viejo va dentro de un nuevo campo “Witness Script”.

Si aún no has aprendido sobre SegWit, sólo pretende que el contrato de garantía de LocalCryptos utiliza P2SH estándar. Tendrá más sentido así. Usar Testigo Segregado (Segregated Witness) mejora la eficiencia y el costo del contrato de garantía. Más nada.

¿Por qué no usar multi-firma?

De buenas a primeras, hay una alta probabilidad de que asumas que LocalCryptos utiliza direcciones multi-firma (multi-signature). Pero te darás cuenta que OP_CHECKMULTISIG no está en el código.

En un script multi-firma, cada firmante es una parte de la transacción a gastar. En nuestro modelo, LocalCryptos nunca ha tenido que firmar ninguna parte de la transacción—incluso en una disputa de pago.

De manera verdaderamente P2P, nosotros jamás seremos parte de ninguna transacción. Debido a esto, es imposible para nosotros imponer las condiciones de gasto en los escrows—como cúando y cómo puede la parte receptora gastar el bitcoin.

Nuestro mecanismo es especialmente útil para intercambios en persona. Los usuarios son capaces de liberar los Bitcoins del escrow, aun sin tener acceso a internet. Será posible activar la liberación mediante el envío de un SMS con un código único, o mostrando un QR al comprador. Más info sobre ello más tarde.

Generando y firmando claves en lotes

Lo primero que haces cuando creas una cuenta en LocalCryptos es generar una gran cantidad de claves aleatorias y firmarlas. Por supuesto, esto ocurre tras bastidores—el usuario común no se dará cuenta de eso.

Estas claves efímeras vienen en tres categorías, dos de las cuales son relevantes a los escrows BTC.

Generando claves de mensajería de extremo a extremo

La categoría no relacionada de claves aleatorias creadas al momento del registro son claves de cifrado de extremo a extremo. Dichas claves permiten a las personas iniciar conversaciones encriptadas contigo mientras no estás conectado. LocalCryptos tomó esta idea de aplicaciones populares de mensajería cifrada de secreto hacia adelante (como Signal). Puedes aprender más sobre esto en el white paper original de LocalEthereum.

Generando direcciones de cartera

Cuando generas una dirección de Bitcoin en tu cartera no-custodia de LocalCryptos, tambíen estás cargando una versión firmada a la plataforma. Cuando la cartera web se está autoconfigurando, esta crea y firma cientos de direcciones de Bitcoin.

Unas copias encriptadas de tus claves privadas son cargadas también para permitirte iniciar sesión desde otro dispositivo.

El mismo proceso ocurre en las demás carteras web de nuestra página, incluyendo Ethereum.

Esto permite que otros puedan iniciar transacciones contigo y depositar fondos en garantía, incluso si no estás conectado. Los usuarios extraen una de tus direcciones de nosotros, y verifican la firma contra tu clave privada. Hacer esto ayuda a evitar el riesgo de un complejo ataque de man-in-the-middle (hombre en el medio).

Generando claves de escrow

Las claves de escrow son únicas al contrato de garantía de Bitcoin, dado que el sistema escrow de Ethereum es diferente.

Dichas claves son códigos secretos de 32 bytes que puedes revelar más adelante. Generas un hash del código secreto (usando hash160) y lo firmas. Luego, cargas el código hasheado, la firma, y un código secreto encriptado a LocalCryptos.

Fondeando el escrow

Para colocar BTCs en el escrow, el vendedor crea una transacción de Bitcoin contentiva de dos outputs. Uno de ellos es para el monto a depositar en garantía, y el otro es la comisión reembolsable de LocalCryptos.

Antes de hacer esto, el vendedor necesita extraer algunos detalles de LocalCryptos:

  1. Códigos hasheados de las claves de escrow pertenecientes al comprador, el árbitro, y el vendedor (sus propios códigos).
  2. Una firma del comprador que pueda usar para autenticar el mencionado código hasheado.
  3. Una clave pública hasheada del comprador, así como su propia clave.
  4. Una firma del comprador para verificar que la clave pública pertenezca al mismo.
  5. La clave pública hasheada del ábitro, de modo que pueda enviar una pequeña comisión.

El vendedor confirmará que cada firma del comprador sea válida, antes de proceder. Una firma incorrecta significa que un hacker intentó manipular el escrow.

Output del escrow

El output del escrow, que lleva consigo el monto para el comprador, es una dirección P2SH-P2WSH para el siguiente Script:

OP_DUP OP_1 OP_EQUAL
OP_IF
  # Release by seller
  OP_DROP
  <BuyerPubKeyHash>
  <ReleaseCodeFromSellerHash>
OP_ELSE
  OP_DUP OP_2 OP_EQUAL
  OP_IF
    # Release by arbitrator
    OP_DROP
    <BuyerPubKeyHash>
    <ReleaseCodeFromArbitratorHash>
  OP_ELSE
    OP_DUP OP_3 OP_EQUAL
    OP_IF
      # Return by buyer
      OP_DROP
      <SellerPubKeyHash>
      <ReturnCodeFromBuyerHash>
    OP_ELSE
      OP_4 OP_EQUALVERIFY
      # Return by arbitrator
      <SellerPubKeyHash>
      <ReturnCodeFromArbitratorHash>
    OP_ENDIF
  OP_ENDIF
OP_ENDIF
OP_ROT
OP_HASH160
OP_EQUALVERIFY
OP_OVER
OP_HASH160
OP_EQUALVERIFY
OP_CHECKSIG

Output de la comisión

El output de la comisión carga consigo una cantidad de Bitcoin de aproximadamente el 1% del tamaño de la transacción. LocalCryptos cobrará dicha comisión si la transacción fue exitosa. En caso de que esta última sea cancelada, el vendedor puede liberar el output para reclamar un reembolso completo.

El output de la comisión es una dirección P2SH-P2WSH para el siguiente Script:

OP_DUP OP_3 OP_EQUAL
OP_IF
  # Return by buyer
  OP_DROP
  OP_HASH160
  <ReturnCodeFromBuyerHash>
  OP_EQUALVERIFY
  OP_DUP
  OP_HASH160
  <SellerPubKeyHash>
  OP_EQUALVERIFY
  OP_CHECKSIG
OP_ELSE
  OP_DUP OP_4 OP_EQUAL
  OP_IF
    # Return by arbitrator
    OP_DROP
    OP_HASH160
    <ReturnCodeFromArbitratorHash>
    OP_EQUALVERIFY
    OP_DUP
    OP_HASH160
    <SellerPubKeyHash>
    OP_EQUALVERIFY
    OP_CHECKSIG
  OP_ELSE
    # Spend by LocalCryptos
    OP_DUP
    OP_HASH160
    <ArbitratorPubKeyHash>
    OP_EQUALVERIFY
    OP_CHECKSIG
  OP_ENDIF
OP_ENDIF

Esperando por las confirmaciones

LocalCryptos requiere, para la mayoría de los escrows de Bitcoin, que tengan al menos una confirmación en el bloque. Transacciones más grandes necesitarán hasta seis confirmaciones, dependiendo del tamaño del intercambio.

Revelando un código secreto 

El comprador ya tiene uno de los dos inputs necesarios para desbloquear la transacción del escrow: su propia clave privada. La única pieza faltante es el código “releaseBySeller” secreto del vendedor.

Igualmente, el vendedor está a un solo input de desbloquear el escrow. Si lograra hacerse con el código “returnByBuyer” secreto del comprador, podría recuperar el monto depositado en garantía.

El árbitro tiene el código secreto para las claves de escrow “releaseByArbitrator” y “returnByArbitrator”. Si se iniciara una disputa de pago, el árbitro puede tomar una resolución revelando uno de los dos códigos secretos.

Este es el quid del sistema escrow no custodio. El script hasheado incluye el hash de cada código secreto, mas no el producto completo.

Usando un código secreto 

Para gastar un output de escrow, el receptor necesita compilar una firma con los siguientes ítemes:

Los primeros dos ítemes son iguales a gastar un input P2PKH, y los siguientes dos son únicos a LocalCryptos.

El byte de “action” le dirá al script cuáles hashes verificar. En una transacción estándar, un comprador usará el código “release by seller” (0x01). Si el primer ítem es 0x01, el script esperará la clave pública del comprador, y el código de liberación del vendedor.

Hay cuatro acciones para el escrow, que representan todos los escenarios posibles para el mismo:

Acción Byte Código esperado PubKey esperada
ReleaseBySeller 0x01 Del vendedor Del comprador
ReleaseByArbitrator 0x02 Del árbitro Del comprador
ReturnByBuyer 0x03 Del comprador Del vendedor
ReturnByArbitrator 0x04 Del árbitro Del vendedor

Recobrando el output de la comisión

En el caso de una cancelación del escrow, LocalCryptos no cobra ninguna comisión. Solo lo hacemos si el Bitcoin se envía al comprador.

Con un código de escrow de retorno, la mencionada firma también es compatible con un output de comisión. El vendedor puede gastar dicho output del mismo modo que gastaría un UTXO en escrow retirado.

Se registra cuando gastas

Hacer clic en “Liberar” en un escrow Bitcoin de LocalCryptos no genera ningún cambio en la blockchain. Lo que hace es permitir a la parte gastar las monedas desde el escrow (en otras palabras, liberar el UTXO).

La parte recipiente puede elegir gastar estas monedas inmediatamente, o esperar. En la interfaz de usuario, un UTXO de escrow aparecerá en la cartera web, justo al lado de tus direcciones regulares.

Luego de gastar las monedas, la finalización del escrow es agregada permanentemente a la blockchain.

Liberar sin una conexión a internet 

Todo lo que el comprador necesita es el código secreto del vendedor para reclamar el escrow.

Podemos agregar un método para que el vendedor pueda revelar su código sin una conexión a internet. El código es muy largo para escribirlo en papel, pero es perfecto para almacenar en tu teléfono o en un código QR.

LocalCryptos agregará dos nuevas formas de revelar un código:

1. Revelar el código enviándolo en un SMS a uno de nuestros números telefónicos. Nuestros servidores pueden calcular el hash del código para identificar a cuál transacción pertenece, para luego reenviar dicho código al comprador.

2. Mostrar un código QR al comprador. El comprador no necesita de internet para verificar el código; solo requiere de un software que pueda calcular el hash. Este método permitirá los intercambios en persona cuando ninguno tenga una conexión a internet estable. Será de gran utilidad en Venezuela, donde los apagones nacionales están a la orden del día.

Actualmente estamos trabajando en la primera opción. La segunda vendrá una vez que lancemos la aplicación móvil de LocalCryptos.

¿Qué tan seguro es esto?

Ni la mejor supercomputadora puede romper una dirección P2PKH estándar, que utiliza un solo hash. El espacio clave de un hash160 es 160 bits. Nosotros usamos dos hash160s: uno para la parte P2PKH, y otra para el código secreto hasheado. Esto lleva el espacio clave a 320 bits para atacantes externos (la matemática es más compleja que eso, pero se entiende la idea).

Las direcciones del escrow Bitcoin de LocalCryptos son—a todo efecto—imposibles de descifrar.

¿Cuánto cuesta?

Hemos reducido las comisiones de red actualizándonos a Segregated Witness. No obstante, el costo de una transacción de Bitcoin suele ser mayor que en Ethereum.

El costo de un escrow de Bitcoin depende de la congestión de la red. Para transacciones pequeñas por debajo de $10, recomendamos elegir otra criptomoneda.

¿Es esta la versión final?

Es muy probable que no sea la versión final del escrow Bitcoin no custodio de LocalCryptos. Tenemos planes de optimizar el sistema en cuanto a costos y velocidad, en el futuro.