
Bitcoin: Un Sistema de Efectivo Electrónico de Punto a Punto
Una versión puramente de punto a punto de efectivo electrónico permitiría que los pagos en línea se envíen directamente de una parte a otra sin pasar por una institución financiera. Las firmas digitales proporcionan parte de la solución, pero los principales beneficios se pierden si aún se requiere un tercero de confianza para prevenir el doble gasto. Proponemos una solución al problema del doble gasto utilizando una red de punto a punto. La red marca las transacciones por medio de su hash en una cadena continua de prueba de trabajo basada en hash, formando un registro que no puede ser cambiado sin rehacer la prueba de trabajo. La cadena más larga no solo sirve como prueba de la secuencia de eventos presenciados, sino como prueba de que provino de la mayor cantidad de poder de CPU. Mientras una mayoría del poder de CPU sea controlada por nodos que no cooperen para atacar la red, generarán la cadena más larga y superarán a los atacantes. La red en sí requiere una estructura mínima. Los mensajes se transmiten sobre una base de mejor esfuerzo, y los nodos pueden salir y volver a unirse a la red a voluntad, aceptando la cadena de prueba de trabajo más larga como prueba de lo que sucedió mientras estaban ausentes.
1. Introducción El comercio en Internet ha llegado a depender casi exclusivamente de instituciones financieras que actúan como terceros de confianza para procesar pagos electrónicos. Si bien el sistema funciona lo suficientemente bien para la mayoría de las transacciones, aún sufre de las debilidades inherentes del modelo basado en la confianza. Las transacciones completamente no reversibles no son realmente posibles, ya que las instituciones financieras no pueden evitar mediar en disputas. El costo de la mediación aumenta los costos de transacción, limitando el tamaño mínimo práctico de transacción y cortando la posibilidad de transacciones pequeñas y casuales, y hay un costo más amplio en la pérdida de capacidad para realizar pagos no reversibles por servicios no reversibles. Con la posibilidad de reversión, la necesidad de confianza se propaga. Los comerciantes deben ser cautelosos con sus clientes, acosándolos por más información de la que normalmente necesitarían. Se acepta un cierto porcentaje de fraude como inevitable. Estos costos e incertidumbres de pago pueden evitarse en persona utilizando moneda física, pero no existe un mecanismo para realizar pagos a través de un canal de comunicación sin una parte de confianza. Lo que se necesita es un sistema de pago electrónico basado en prueba criptográfica en lugar de confianza, que permita a cualquier par de partes dispuestas transaccionar directamente entre sí sin necesidad de un tercero de confianza. Transacciones que son computacionalmente impracticables de revertir protegerían a los vendedores del fraude, y mecanismos de custodia rutinarios podrían implementarse fácilmente para proteger a los compradores. En este documento, proponemos una solución al problema del doble gasto utilizando un servidor de marca de tiempo distribuido de punto a punto para generar prueba computacional del orden cronológico de las transacciones. El sistema es seguro mientras los nodos honestos controlen colectivamente más poder de CPU que cualquier grupo de nodos atacantes que cooperen.
2. Verificar Transacciones Definimos una moneda electrónica como una cadena de firmas digitales. Cada propietario transfiere la moneda al siguiente firmando digitalmente un hash de la transacción anterior y la clave pública del siguiente propietario y agregando estos al final de la moneda. Un beneficiario puede verificar las firmas para verificar la cadena de propiedad. Transacción Verificar Clave Pública del Propietario 1 Hash Firma del Propietario 0 Clave Privada del Propietario 1 Transacción Clave Pública del Propietario 2 Hash Firma del Propietario 1 Clave Privada del Propietario 2 Transacción Clave Pública del Propietario 3 Hash Firma del Propietario 2 Clave Privada del Propietario 3 El problema, por supuesto, es que el beneficiario no puede verificar que uno de los propietarios no haya gastado la moneda dos veces. Una solución común es introducir una autoridad central de confianza, o acuñadora, que verifique cada transacción por doble gasto. Después de cada transacción, la moneda debe ser devuelta a la acuñadora para emitir una nueva moneda, y solo las monedas emitidas directamente desde la acuñadora son de confianza para no ser gastadas dos veces. El problema con esta solución es que el destino de todo el sistema monetario depende de la empresa que opera la acuñadora, con cada transacción teniendo que pasar por ellos, igual que un banco. Necesitamos una forma para que el beneficiario sepa que los propietarios anteriores no firmaron ninguna transacción anterior. Para nuestros propósitos, la transacción más antigua es la que cuenta, por lo que no nos importa los intentos posteriores de doble gasto. La única forma de confirmar la ausencia de una transacción es ser consciente de todas las transacciones. En el modelo basado en acuñadoras, la acuñadora era consciente de todas las transacciones y decidía cuál llegaba primero. Para lograr esto sin una parte de confianza, las transacciones deben ser anunciadas públicamente [1], y necesitamos un sistema para que los participantes acuerden una única historia del orden en que fueron recibidas. El beneficiario necesita prueba de que en el momento de cada transacción, la mayoría de los nodos acordaron que era la primera recibida.
3. Servidor de Marca de Tiempo La solución que proponemos comienza con un servidor de marca de tiempo. Un servidor de marca de tiempo funciona tomando un hash de un bloque de elementos que se van a marcar y publicando ampliamente el hash, como en un periódico o en una publicación de Usenet [2-5]. La marca de tiempo prueba que los datos debieron haber existido en ese momento, obviamente, para entrar en el hash. Cada marca de tiempo incluye la marca de tiempo anterior en su hash, formando una cadena, con cada marca de tiempo adicional reforzando las anteriores. Hash Hash Bloque Elemento Elemento Bloque ... Elemento Elemento ...
4. Prueba de Trabajo Para implementar un servidor de marca de tiempo distribuido sobre una base de punto a punto, necesitaremos utilizar un sistema de prueba de trabajo similar al Hashcash de Adam Back [6], en lugar de publicaciones en periódicos o Usenet. La prueba de trabajo implica escanear un valor que cuando se hash, como con SHA-256, el hash comienza con un número de bits cero. El trabajo promedio requerido es exponencial en el número de bits cero requeridos y puede ser verificado ejecutando un solo hash. Para nuestra red de marcas de tiempo, implementamos la prueba de trabajo incrementando un nonce en el bloque hasta que se encuentra un valor que da al hash del bloque los bits cero requeridos. Una vez que se ha gastado el esfuerzo de CPU para hacerlo satisfacer la prueba de trabajo, el bloque no puede ser cambiado sin rehacer el trabajo. A medida que se encadenan bloques posteriores, el trabajo para cambiar el bloque incluiría rehacer todos los bloques después de él. Bloque Hash Anterior Tx Bloque Nonce Tx ... Hash Anterior Nonce Tx Tx ... La prueba de trabajo también resuelve el problema de determinar la representación en la toma de decisiones mayoritaria. Si la mayoría se basara en una dirección IP-una-voto, podría ser subvertida por cualquier persona capaz de asignar muchas IP. La prueba de trabajo es esencialmente uno-CPU-uno-voto. La decisión mayoritaria está representada por la cadena más larga, que tiene el mayor esfuerzo de prueba de trabajo invertido en ella. Si una mayoría del poder de CPU es controlada por nodos honestos, la cadena honesta crecerá más rápido y superará a cualquier cadena competidora. Para modificar un bloque pasado, un atacante tendría que rehacer la prueba de trabajo del bloque y todos los bloques después de él y luego alcanzar y superar el trabajo de los nodos honestos. Mostraremos más adelante que la probabilidad de que un atacante más lento alcance disminuye exponencialmente a medida que se añaden bloques subsiguientes. Para compensar el aumento de velocidad del hardware y el interés variable en ejecutar nodos a lo largo del tiempo, la dificultad de la prueba de trabajo se determina mediante un promedio móvil que apunta a un número promedio de bloques por hora. Si se generan demasiado rápido, la dificultad aumenta.
5. Red Los pasos para ejecutar la red son los siguientes: 1) Nuevas transacciones se transmiten a todos los nodos. 2) Cada nodo recopila nuevas transacciones en un bloque. 3) Cada nodo trabaja para encontrar una prueba de trabajo difícil para su bloque. 4) Cuando un nodo encuentra una prueba de trabajo, transmite el bloque a todos los nodos. 5) Los nodos aceptan el bloque solo si todas las transacciones en él son válidas y no han sido gastadas. 6) Los nodos expresan su aceptación del bloque trabajando en crear el siguiente bloque en la cadena, usando el hash del bloque aceptado como el hash anterior. Los nodos siempre consideran que la cadena más larga es la correcta y seguirán trabajando para extenderla. Si dos nodos transmiten diferentes versiones del siguiente bloque simultáneamente, algunos nodos pueden recibir uno u otro primero. En ese caso, trabajan en el primero que recibieron, pero guardan la otra rama en caso de que se vuelva más larga. El empate se romperá cuando se encuentre la siguiente prueba de trabajo y una rama se vuelva más larga; los nodos que estaban trabajando en la otra rama cambiarán entonces a la más larga.
Las transmisiones de nuevas transacciones no necesariamente necesitan llegar a todos los nodos. Siempre que lleguen a muchos nodos, se incluirán en un bloque antes de que pase mucho tiempo. Las transmisiones de bloques también son tolerantes a mensajes perdidos. Si un nodo no recibe un bloque, lo solicitará cuando reciba el siguiente bloque y se dé cuenta de que se perdió uno.
6. Incentivo Por convención, la primera transacción en un bloque es una transacción especial que inicia una nueva moneda propiedad del creador del bloque. Esto añade un incentivo para que los nodos apoyen la red, y proporciona una forma de distribuir inicialmente monedas en circulación, ya que no hay una autoridad central para emitirlas. La adición constante de una cantidad constante de nuevas monedas es análoga a los mineros de oro que gastan recursos para agregar oro a la circulación. En nuestro caso, es tiempo de CPU y electricidad lo que se gasta. El incentivo también puede ser financiado con tarifas de transacción. Si el valor de salida de una transacción es menor que su valor de entrada, la diferencia es una tarifa de transacción que se añade al valor del incentivo del bloque que contiene la transacción. Una vez que un número predeterminado de monedas ha ingresado a circulación, el incentivo puede transitar completamente a tarifas de transacción y estar completamente libre de inflación. El incentivo puede ayudar a alentar a los nodos a permanecer honestos. Si un atacante codicioso puede reunir más poder de CPU que todos los nodos honestos, tendría que elegir entre usarlo para defraudar a las personas robando sus pagos, o usarlo para generar nuevas monedas. Debería encontrar más rentable jugar según las reglas, tales reglas que le favorecen con más nuevas monedas que todos los demás combinados, que socavar el sistema y la validez de su propia riqueza.
7. Recuperación de Espacio en Disco Una vez que la última transacción en una moneda está enterrada bajo suficientes bloques, las transacciones gastadas antes de ella pueden ser descartadas para ahorrar espacio en disco. Para facilitar esto sin romper el hash del bloque, las transacciones se hash en un Árbol de Merkle [7][2][5], con solo la raíz incluida en el hash del bloque. Los bloques antiguos pueden ser compactados eliminando ramas del árbol. Los hashes interiores no necesitan ser almacenados. Bloque Encabezado de Bloque (Hash del Bloque) Hash Anterior Nonce Hash Raíz Hash01 Hash0 Hash1 Hash23 Hash2 Tx0 Tx1 Tx2 Hash3 Tx3 Transacciones Hasheadas en un Árbol de Merkle Bloque Encabezado de Bloque (Hash del Bloque) Hash Anterior Nonce Hash Raíz Hash01 Hash23 Hash2 Hash3 Tx3 Después de Podar Tx0-2 del Bloque Un encabezado de bloque sin transacciones sería de aproximadamente 80 bytes. Si suponemos que los bloques se generan cada 10 minutos, 80 bytes * 6 * 24 * 365 = 4.2MB por año. Con los sistemas informáticos vendiéndose típicamente con 2GB de RAM a partir de 2008, y la Ley de Moore prediciendo un crecimiento actual de 1.2GB por año, el almacenamiento no debería ser un problema incluso si los encabezados de bloque deben mantenerse en memoria.
8. Verificación de Pagos Simplificada Es posible verificar pagos sin ejecutar un nodo de red completo. Un usuario solo necesita mantener una copia de los encabezados de bloque de la cadena de prueba de trabajo más larga, que puede obtener consultando nodos de la red hasta que esté convencido de que tiene la cadena más larga, y obtener la rama de Merkle que vincula la transacción al bloque en el que está marcada. No puede verificar la transacción por sí mismo, pero al vincularla a un lugar en la cadena, puede ver que un nodo de la red la ha aceptado, y los bloques agregados después de ella confirman aún más que la red la ha aceptado. Cadena de Prueba de Trabajo Más Larga Encabezado de Bloque Hash Anterior Nonce Raíz de Merkle Encabezado de Bloque Hash Anterior Raíz de Merkle Hash01 Hash2 Encabezado de Bloque Nonce Hash Anterior Nonce Raíz de Merkle Hash23 Rama de Merkle para Tx3 Hash3 Tx3 Como tal, la verificación es confiable mientras nodos honestos controlen la red, pero es más vulnerable si la red es sobrepasada por un atacante. Aunque los nodos de la red pueden verificar transacciones por sí mismos, el método simplificado puede ser engañado por transacciones fabricadas por un atacante mientras el atacante pueda continuar dominando la red. Una estrategia para protegerse contra esto sería aceptar alertas de nodos de la red cuando detecten un bloque inválido, lo que incitaría al software del usuario a descargar el bloque completo y las transacciones alertadas para confirmar la inconsistencia. Las empresas que reciben pagos frecuentes probablemente aún querrán ejecutar sus propios nodos para mayor seguridad independiente y verificación más rápida.
9. Combinando y Dividiendo Valor Aunque sería posible manejar monedas individualmente, sería poco práctico hacer una transacción separada por cada centavo en una transferencia. Para permitir que el valor se divida y combine, las transacciones contienen múltiples entradas y salidas. Normalmente habrá una sola entrada de una transacción anterior más grande o múltiples entradas combinando cantidades más pequeñas, y como máximo dos salidas: una para el pago y otra devolviendo el cambio, si lo hay, al remitente. Transacción En En Fuera ... ... Cabe señalar que el fan-out, donde una transacción depende de varias transacciones, y esas transacciones dependen de muchas más, no es un problema aquí. Nunca hay necesidad de extraer una copia independiente completa de la historia de una transacción.
10. Privacidad El modelo bancario tradicional logra un nivel de privacidad limitando el acceso a la información a las partes involucradas y al tercero de confianza. La necesidad de anunciar todas las transacciones públicamente excluye este método, pero la privacidad aún se puede mantener rompiendo el flujo de información en otro lugar: manteniendo las claves públicas anónimas. El público puede ver que alguien está enviando una cantidad a otra persona, pero sin información que vincule la transacción a nadie. Esto es similar al nivel de información liberada por las bolsas de valores, donde el tiempo y el tamaño de las transacciones individuales, la "tape", se hacen públicas, pero sin mencionar quiénes eran las partes. Modelo de Privacidad Tradicional Identidades Nuevo Modelo de Privacidad Identidades Transacciones Tercero de Confianza Transacciones Contraparte Pública Pública Como un cortafuegos adicional, se debe utilizar un nuevo par de claves para cada transacción para evitar que se vinculen a un propietario común. Sin embargo, algunos vínculos siguen siendo inevitables con transacciones de múltiples entradas, que necesariamente revelan que sus entradas eran propiedad del mismo propietario. El riesgo es que si se revela la identidad de un propietario de una clave, el enlace podría revelar otras transacciones que pertenecían al mismo propietario.
11. Cálculos Consideramos el escenario de un atacante tratando de generar una cadena alternativa más rápido que la cadena honesta. Incluso si esto se logra, no abre el sistema a cambios arbitrarios, como crear valor de la nada o tomar dinero que nunca perteneció al atacante. Los nodos no van a aceptar una transacción inválida como pago, y los nodos honestos nunca aceptarán un bloque que las contenga. Un atacante solo puede intentar cambiar una de sus propias transacciones para recuperar dinero que gastó recientemente. La carrera entre la cadena honesta y la cadena de un atacante puede caracterizarse como un Paseo Aleatorio Binomial. El evento de éxito es que la cadena honesta se extiende por un bloque, aumentando su ventaja en +1, y el evento de fracaso es que la cadena del atacante se extiende por un bloque, reduciendo la brecha en -1. La probabilidad de que un atacante alcance desde un déficit dado es análoga a un problema de Ruina de Jugador. Supongamos que un jugador con crédito ilimitado comienza en un déficit y juega potencialmente un número infinito de pruebas para tratar de alcanzar el equilibrio. Podemos calcular la probabilidad de que alguna vez alcance el equilibrio, o que un atacante alguna vez alcance a la cadena honesta, de la siguiente manera [8]: p = probabilidad de que un nodo honesto encuentre el siguiente bloque q = probabilidad de que el atacante encuentre el siguiente bloque qz = probabilidad de que el atacante alguna vez alcance desde z bloques atrás qz = { 1 si p≤q q/ pz si pq }
Dada nuestra suposición de que p > q, la probabilidad disminuye exponencialmente a medida que aumenta el número de bloques que el atacante tiene que alcanzar. Con las probabilidades en su contra, si no hace un salto afortunado hacia adelante al principio, sus posibilidades se vuelven insignificantes a medida que se queda más atrás. Ahora consideramos cuánto tiempo necesita esperar el receptor de una nueva transacción antes de estar suficientemente seguro de que el remitente no puede cambiar la transacción. Asumimos que el remitente es un atacante que quiere hacer que el receptor crea que le pagó por un tiempo, luego cambiarlo para pagar de vuelta a sí mismo después de que haya pasado un tiempo. El receptor será alertado cuando eso suceda, pero el remitente espera que sea demasiado tarde. El receptor genera un nuevo par de claves y le da la clave pública al remitente poco antes de firmar. Esto previene que el remitente prepare una cadena de bloques por adelantado al trabajar en ella continuamente hasta que tenga suerte y logre estar lo suficientemente adelante, luego ejecutando la transacción en ese momento. Una vez que se envía la transacción, el remitente deshonesto comienza a trabajar en secreto en una cadena paralela que contiene una versión alternativa de su transacción. El receptor espera hasta que la transacción se haya agregado a un bloque y z bloques se hayan vinculado después de ella. No sabe la cantidad exacta de progreso que ha hecho el atacante, pero asumiendo que los bloques honestos tomaron el tiempo promedio esperado por bloque, el progreso potencial del atacante será una distribución de Poisson con valor esperado: =z q p Para obtener la probabilidad de que el atacante aún pueda alcanzar ahora, multiplicamos la densidad de Poisson por cada cantidad de progreso que podría haber hecho por la probabilidad de que pudiera alcanzar desde ese punto: ∞ ke− ∑ k=0 k! ⋅ { q/ pz−k si k≤z 1 si kz } Reorganizando para evitar sumar la cola infinita de la distribución... 1−∑ k=0 z ke− k! 1−q/ pz−k Convirtiendo a código C... #include <math.h> double AttackerSuccessProbability(double q, int z) { double p = 1.0 - q; double lambda = z * (q / p); double sum = 1.0; int i, k; for (k = 0; k <= z; k++) { double poisson = exp(-lambda); for (i = 1; i <= k; i++) poisson *= lambda / i; sum -= poisson * (1 - pow(q / p, z - k)); } return sum; }
Ejecutando algunos resultados, podemos ver que la probabilidad disminuye exponencialmente con z. q=0.1 z=0 P=1.0000000 z=1 P=0.2045873 z=2 P=0.0509779 z=3 P=0.0131722 z=4 P=0.0034552 z=5 P=0.0009137 z=6 P=0.0002428 z=7 P=0.0000647 z=8 P=0.0000173 z=9 P=0.0000046 z=10 P=0.0000012 q=0.3 z=0 P=1.0000000 z=5 P=0.1773523 z=10 P=0.0416605 z=15 P=0.0101008 z=20 P=0.0024804 z=25 P=0.0006132 z=30 P=0.0001522 z=35 P=0.0000379 z=40 P=0.0000095 z=45 P=0.0000024 z=50 P=0.0000006 Resolviendo para P menos del 0.1%... P < 0.001 q=0.10 z=5 q=0.15 z=8 q=0.20 z=11 q=0.25 z=15 q=0.30 z=24 q=0.35 z=41 q=0.40 z=89 q=0.45 z=340
12. Conclusión Hemos propuesto un sistema para transacciones electrónicas sin depender de la confianza. Comenzamos con el marco habitual de monedas hechas de firmas digitales, que proporciona un control fuerte de propiedad, pero es incompleto sin una forma de prevenir el doble gasto. Para resolver esto, proponemos una red de punto a punto que utiliza prueba de trabajo para registrar una historia pública de transacciones que rápidamente se vuelve computacionalmente impracticable para un atacante cambiar si nodos honestos controlan la mayoría del poder de CPU. La red es robusta en su simplicidad no estructurada. Los nodos trabajan todos a la vez con poca coordinación. No necesitan ser identificados, ya que los mensajes no son enrutados a ningún lugar en particular y solo necesitan ser entregados sobre una base de mejor esfuerzo. Los nodos pueden salir y volver a unirse a la red a voluntad, aceptando la cadena de prueba de trabajo como prueba de lo que sucedió mientras estaban ausentes. Votan con su poder de CPU, expresando su aceptación de bloques válidos al trabajar en extenderlos y rechazando bloques inválidos al negarse a trabajar en ellos. Cualquier regla e incentivos necesarios pueden ser impuestos con este mecanismo de consenso.