Última actualización de la página: August 9, 2021
Guía de Ethereum
Esta guía introductoria fue publicada originalmente en 2013 por Vitalik Buterin, el fundador de Ethereum, antes del lanzamiento del proyecto en 2015. Vale la pena señalar que Ethereum, al igual que muchos proyectos de software de código abierto impulsados por la comunidad, ha evolucionado desde su inicio.
Aunque tenga varios años de antigüedad, mantenemos este documento porque sigue sirviendo como una referencia útil y una representación precisa de Ethereum y su visión. Para aprender sobre los últimos desarrollos de Ethereum, y cómo se hacen los cambios en el protocolo, recomendamos esta guía.
Un contrato inteligente de nueva generación y una plataforma de aplicación descentralizada
La publicación de Bitcoin en 2009 por parte de Satoshi Nakamoto a menudo se ha aclamado como un avance radical en el ámbito del dinero y las divisas, siendo el primer ejemplo de un activo digital que a la vez no tiene respaldo o valor intrínseco ni un emisor o mando centralizado. Sin embargo, otra parte, quizás más importante, del experimento de Bitcoin es la tecnología subyacente de blockchain como una herramienta de consenso distribuido, aspecto del Bitcoin sobre el cual se está empezando rápidamente a centrar la atención. Las aplicaciones alternativas que se citan comunmente de la tecnología de blockchain incluyen el el uso de los activos digitales blockchain para representar divisas a medida e instrumentos financieros (monedas coloreadas), la propiedad de un artefacto físico subyacente (propiedad inteligente), activos no fungibles como nombres de dominio (Namecoin), así como aplicaciones más complejas que involucran activos digitales controlados directamente por un fragmento de código que implementa reglas arbitrarias (contratos inteligentes) o incluso organizaciones autónomas descentralizadas basadas en blockchain (DAO). Lo que Ethereum pretende es proporcionar una blockchain con un lenguaje integrado Turing completo y plenamente desarrollado que se puede usar para crear "contratos" que, a su vez, se pueden utilizar para codificar funciones arbitrarias de transición de estados, permitiendo a los usuarios crear cualquiera de los sistemas descritos anteriormente, así como otros que todavía no hemos imaginado, tan solo escribiendo la lógica en unas pocas líneas de código.
Introducción a Bitcoin y a los conceptos existentes
Historial
El concepto de moneda digital descentralizada, así como aplicaciones alternativas como los registros de propiedades, ha existido durante décadas. Los protocolos anónimos de dinero digital de los años ochenta y noventa, en su mayoría depentiendes de una primitiva criptográfica conocida como firma digital ciega, proporcionaron una moneda con un alto grado de privacidad, pero fallaron en gran medida al imponerse debido a su dependencia de un intermediario centralizado. En 1998, el b-money se convirtió en la primera propuesta para presentar la idea de crear dinero mediante la resolución de rompecabezas computaciones, así como del consenso descentralizado, pero la propuesta era escasa en detalles sobre cómo se podría implementar el consenso descentralizado en la práctica. En 2005, Hal Finney introdujo el concepto de pruebas de trabajo reutilizables, un sistema que utiliza ideas del b-money junto con los rompecabezas computacionalmente difíciles Hashcash de Adam Back, para crear un concepto de criptomoneda. Sin embargo, una vez más se quedó por debajo del ideal al delegar la computación de confianza a un "backend". En 2009, una moneda descentralizada se implementó por primera vez en la práctica por Satoshi Nakamoto, combinando primitivas consolidadas para gestionar la propiedad a través de la criptografía de clave pública junto con un algoritmo de consenso para mantener un registro de quién es dueño de las monedas, conocido como "prueba de trabajo".
El mecanismo detrás de la prueba de trabajo constituyó un avance en el área porque resolvió dos problemas al mismo tiempo. Primero, proporcionó un algoritmo de consenso simple y moderadamente efectivo, permitiendo que los nodos en la red aceptasen colectivamente un conjunto de actualizaciones canónicas al estado del libro de contabilidad de Bitcoin. Segundo, proporcionó un mecanismo para permitir la entrada libre en el proceso de consenso, resolviendo el problema político de decidir quién llega a influir en el consenso e impidiendo al mismo tiempo los ataques Sybil. Lo hace sustituyendo una barrera formal para la participación, por ejemplo, el requisito de estar registrado como una entidad única en una lista particular, por una barrera económica: el peso de un único nodo en el proceso de votación de consenso es directamente proporcional a la potencia de cálculo que aporta el nodo. Desde entonces, se ha propuesto un enfoque alternativo llamado prueba de participación, que calcula el peso de un nodo como la parte proporcional de sus monedas en propiedad y no sus recursos computacionales; la argumentación de los méritos relativos de ambos enfoques está fuera del alcance de este documento, pero hay que señalar que ambos pueden servir como la columna vertebral de una criptomoneda.
Aquí puedes consultar una entrada del blog de Vitalik Buterin, el fundador de Ethereum, en Prehistorial de Ethereum. Aquí hay otra entrada del blog con más contenido histórico.
Bitcoin como un sistema de transición de estados
Desde un punto de vista técnico, el libro de contabilidad de una criptomoneda como Bitcoin se puede considerar un sistema de transición de estados, donde hay un "estado" que consiste en el estado de propiedad de todos los bitcoins existentes, y una "función de transición de estados" que toma un estado y una transacción y produce un nuevo estado como resultado. En un sistema bancario estándar, por ejemplo, el estado es una hoja de balance, una transacción es una petición para mover $X de A a B, y la función de transición de estado reduce el valor en la cuenta A en $X y aumenta el valor en la cuenta B en $X. Si la cuenta A tiene menos de $X en primer lugar, la función de transición de estado devuelve un error. Por lo tanto, se puede definir formalmente:
APPLY(S,TX) -> S' o ERROR
En el sistema bancario definido anteriormente:
APPLY({ Alice: $50, Bob: $50 },"enviar $20 de Alice a Bob") = { Alice: $30, Bob: $70 }
Pero:
APPLY({ Alice: $50, Bob: $50 },"enviar $70 de Alice a Bob") = ERROR
El "estado" en Bitcoin es el conjunto de todas las monedas (técnicamente, "transacciones de salida no gastadas" o UTXO por sus siglas en inglés) que han sido minadas y no se han gastado aún, junto con cada UTXO que tenga una denominación y un propietario (definido por una dirección de 20 bytes, que es esencialmente una clave pública criptográficafn. 1). Una transacción contiene una o más entradas, donde cada entrada contiene una referencia a una UTXO existente y una firma criptográfica generada por la clave privada asociada con la dirección del propietario, y una o más salidas, donde cada salida contiene una nueva UTXO para ser añadida al estado.
La función de transición de estado APPLY(S,TX) -> S'
puede definirse aproximadamente como sigue:
Para cada entrada en
TX
:- Si la UTXO referenciada no está en
S
, devolver un error. - Si la firma proporcionada no coincide con el propietario de la UTXO, devolver un error.
- Si la UTXO referenciada no está en
Si la suma de las denominaciones de todas las entradas UTXO es menor que la suma de las denominaciones de todas las salidas UTXO, devolver un error.
Devolver
S'
con todas las entradas UTXO eliminadas y todas las salidas UTXO añadidas.
La primera mitad del primer paso impide a los emisores de transacciones que gasten monedas que no existen, la segunda mitad del primer paso impide que los emisores de transacciones gasten las monedas de otras personas, y el segundo paso hace cumplir la conservación del valor. Para poder utilizar esto para hacer pagos, el protocolo es el siguiente. Supongamos que Alice quiere enviar 11,7 BTC a Bob. En primer lugar, Alice buscará un conjunto de UTXO disponibles en su poder que sumen un total de al menos 11,7 BTC. En la práctica, Alice no será capaz de obtener exactamente 11,7 BTC; digamos que la cifra más pequeña que puede obtener es 6+4+2=12. A continuación, crea una transacción con estas tres entradas y dos salidas. La primera salida será 11,7 BTC con la dirección de Bob como propietario, y la segunda salida será el "cambio" restante de 0,3 BTC, siendo la propietaria la misma Alice.
Minería
Si tuviéramos acceso a un servicio centralizado de confianza, este sistema sería trivial de implementar; se podría exactamente como se ha descrito, usando el disco duro de un servidor centralizado para mantener el registro del estado. Sin embargo, con Bitcoin estamos tratando de construir un sistema monetario descentralizado, así que necesitaremos combinar el sistema de transición de estados con un sistema de consenso para asegurarse de que todo el mundo esté de acuerdo en el orden de las transacciones. El proceso de consenso descentralizado de Bitcoin requiere que los nodos que integran la red intenten producir continuamente paquetes de transacciones llamados "bloques". La red está pensada para producir aproximadamente un bloque cada diez minutos, donde cada bloque contiene una marca temporal, un nonce, una referencia (es decir, un hash de) al bloque anterior y una lista de todas las transacciones que han tenido lugar desde el bloque anterior. Con el tiempo, esto crea una "blockchain" persistente, cada vez mayor, que se actualiza constantemente para representar el último estado del libro de contabilidad de Bitcoin.
El algoritmo para comprobar si un bloque es válido, expresado en este paradigma, es el siguiente:
- Evaluar si el bloque anterior al que hace referencia el bloque existe y es válido.
- Evaluar que la marca temporal del bloque sea mayor que la del bloque anteriorfn. 2y menos de 2 horas a futuro
- Evaluar que la prueba de trabajo del bloque es válida.
- Permitir que
S[0]
sea el estado al final del bloque anterior. - Supongamos que
TX
es la lista de transacciones del bloque conn
transacciones. Para todoi
de0... -1
, asignarS[i+1] = APPLY(S[i], X[i])
Si cualquier aplicación devuelve un error, salir y devolver false. - Devolver true, y asignar
S[n]
como estado al final de este bloque.
Fundamentalmente, cada transacción en el bloque debe proporcionar una transición de estado válido de lo que era el estado canónico antes de que la transacción fuera ejecutada a otro nuevo estado. Obsérvese que el estado no se codifica en el bloque en modo alguno; es una abstracción pura que debe ser recordada por el nodo validador y solo puede ser calculada (de forma segura) para cualquier bloque empezando desde el estado de génesis y aplicando secuencialmente cada transacción en cada bloque. Además, hay que tener en cuenta que es importante el orden en el que el minero incluye transacciones en el bloque; si hay dos transacciones A y B en un bloque tal que B gasta un UTXO creado por A, entonces el bloque será válido si A viene antes que B pero no en caso contrario.
La única condición de validación presente en la lista anterior que no se encuentra en otros sistemas es el requisito de la "prueba de trabajo". La condición concreta es que el hash SHA256 doble de cada bloque, tratado como un número de 256 bits, debe ser inferior a un objetivo ajustado dinámicamente, que en el momento de escribir estas líneas es aproximadamente 2187. El propósito de esto es hacer que la creación de bloques sea computacionalmente "difícil", impidiendo así que los atacantes de sybil reconstruyan todo el blockchain en su beneficio. Dado que SHA256 está diseñada para ser una función pseudoraleatoria completamente impredecible, la única forma de crear un bloque válido es mediante simple prueba y error, incrementando repetidamente el nonce y comprobando si el nuevo hash coincide.
Para el objetivo actual de ~2187, la red debe hacer un promedio de ~269 intentos antes de encontrar un bloque válido; en general el objetivo se recalibra por la red cada 2016 blques, por lo que que en promedio se crea un bloque nuevo por parte de algún nodo en la red cada diez minutos. Para compensar a los mineros por este trabajo computacional, el minero de cada bloque tiene derecho a incluir una transacción dándose a si mismo 12,5 BTC creados de la nada. Además, si cualquier transacción tiene un valor total más alto en sus entradas que en sus salidas, la diferencia también se destina al minero como "tarifa de transacción". Por otra parte, este es también el único mecanismo por el cual se emiten BTC; el estado inicial no contenía monedas en absoluto.
Para comprender mejor el propósito de la minería, examinemos que ocurre en el caso de un atacante malicioso. Puesto que se sabe que la criptografía subyacente de Bitcoin es segura, el atacante se enfoncará en una parte del sistema Bitcoin que no está protegida directamente por criptografía: el orden de las transacciones. La estrategia del atacante es simple:
- Envía 100 BTC a un vendedor a cambio de algún producto (preferiblemente un bien digital con entrega rápida)
- Espera a la entrega del producto
- Crea otra transacción en la que se envía los mismos 100 BTC a sí mismo
- Trata de convencer a la red de que la transacción para sí mismo era la que tuvo lugar primero.
Una vez que el paso (1) ha tenido lugar, tras unos minutos algún minero incluirá la transacción en un bloque, digamos el bloque número 270. Tras aproximadamente una hora, se habrán añadido cinco bloques más a la cadena tras ese bloque, con cada uno de esos bloques apuntando indirectamente a la transacción y así "confirmándola". En este punto, el vendedor aceptará el pago, lo tomará como finalizado y entregará el producto; ya que estamos asumiendo que se trata de un bien digital, la entrega es instantánea. Ahora, el atacante crea otra transacción en la que se envía 100 BTC a sí mismo. Si el atacante lo suelta sin más, la transacción no se procesará; los mineros intentarán ejecutar APPLY(S, X)
y observarán que TX
consume una UTXO que ya no está en el estado. En su lugar, el atacante crea una "bifurcación" del blockchain, comenzando por minar otra versión del bloque 270 apuntando al mismo bloque 269 como padre pero con la nueva transacción en lugar de la antigua. Dado que los datos del bloque son diferentes, esto requiere volver a hacer la prueba de trabajo. Además, la nueva versión del bloque 270 del atacante tiene un hash diferente, por lo que los bloques originales 271 a 275 no "apuntan" a él; por lo tanto, la cadena original y la nueva cadena del atacante están completamente separadas. La regla es que en una bifurcación se toma la blockchain más larga como la verdadera, y así los mineros legítimos trabajarán en la cadena 275 mientras el atacante por sí solo está trabajando en la cadena 270. Para que el atacante haga que su blockchain sea el más largo, necesitaría tener más poder computacional que el resto de la red combinada para alcanzarles (de ahí, "ataque del 51%").
Árboles de Merkle
Izquierda: Basta con presentar solo un pequeño número de nodos en un árbol de Merkle para demostrar la validez de una bifurcación.
Derecha: Cualquier intento de cambiar cualquier parte del árbol de Merkle llevará eventualmente a una inconsistencia en algún lugar previo de la cadena.
Una característica importante de escalabilidad de Bitcoin es que el bloque se almacena en una estructura de datos multinivel. El "hash" de un bloque es en realidad solo el hash del encabezado del bloque, aproximadamente 200 bytes de datos que contienen la marca de tiempo, el nonce, el hash del bloque anterior y el hash raíz de una estructura de datos llamada el árbol de Merkle que almacena todas las transacciones en el bloque. Un árbol de Merkle es un tipo de árbol binario, compuesto por un conjunto de nodos con un gran número de nodos hoja en la parte inferior del árbol que contienen los datos subyacentes, un conjunto de nodos intermedios donde cada nodo es el hash de sus dos hijos, y finalmente un único nodo raíz, también formado por el hash de sus dos hijos, representando la parte "superior" del árbol. El propósito del árbol de Merkle es permitir que los datos en un bloque se entreguen fragmentados: un nodo solo puede descargar el encabezado de un bloque de una fuente, la pequeña parte del árbol relevante para ellos de otra fuente, y aún así tener la certeza de que todos los datos son correctos. La razón por la que esto funciona es que los hashes se propagan hacia arriba: si un usuario malicioso intenta insertar una transacción falsa en la parte inferior de un árbol Merkle, este cambio causará un cambio en el nodo anterior, y luego un cambio en el nodo anterior, finalmente cambiando la raíz del árbol y por lo tanto el hash del bloque, causando que el protocolo lo registre como un bloque completamente diferente (casi con total seguridad con una prueba de trabajo no válida).
Se podría decir que el protocolo del árbol de Merkle es esencial para la sostenibilidad a largo plazo. Un "nodo completo" en la red Bitcoin, uno que almacene y procesa la totalidad de todos los bloques, ocupa unos 15 GB de espacio en disco en la red Bitcoin a fecha de abril de 2014, y está creciendo más de un gigabyte al mes. Actualmente, esto es viable para algunos ordenadores de escritorio y no para teléfonos, y más adelante en el futuro sólo las empresas y entusiastas podrán participar. Un protocolo conocido como "verificación de pago simplificada" (SPV) permite que existan otra clase de nodos, llamados "nodos ligeros", que descargan los encabezados del bloque, verifican la prueba de trabajo en los encabezados de bloque, y luego descargan solo las "bifurcaciones" asociadas con las transacciones que son relevantes para ellos. Esto permite que los nodos ligeros determinen con una sólida garantía de seguridad cuál es el estado de cualquier transacción de Bitcoin, y cuál es su saldo actual con tan solo descargar una pequeña porción de toda la blockchain.
Aplicaciones alternativas de la blockchain
La idea de tomar el concepto subyacente de blockchain y aplicarla a otros conceptos también tiene un largo historial. En 1998, Nick Szabo publicó el concepto de títulos de propiedad seguros con autoridad de propietario, un documento que describe como "nuevos avances en la tecnología de bases de datos replicadas" permitirá un sistema basado en blockchain para almacenar un registro de quién es propietario de que terreno, creando un marco elaborado que incluye conceptos tales como la propiedad familiar, la posesión adversa y el impuesto sobre la tierra de Georgia. Lamentablemente, no había ningún sistema efectivo de bases de datos replicadas disponible en ese momento, por lo que el protocolo nunca se implementó en la práctica. Sin embargo, después de 2009, una vez que se desarrolló el consenso descentralizado de Bitcoin, un número de aplicaciones alternativas comenzaron a surgir rápidamente.
- Namecoin - creada en 2010, Namecoin se describe como una base de datos de registro de nombres descentralizada. En protocolos descentralizados como Tor, Bitcoin y BitMessage, es necesario que haya una forma de identificar las cuentas de tal modo que otras personas puedan interactuar con ellas, pero en todas las soluciones existentes la única clase de identificador disponible es un hash pseudoaleatorio, como por ejemplo
1LW79wp5ZBqaHW1jL5TCiBCrhQYtHagUWy
. Idealmente, a uno le gustaría poder tener una cuenta con un nombre como "george". Sin embargo, el problema es que si una persona puede crear una cuenta llamada "george", entonces alguien puede usar el mismo proceso para registrar "george" para y suplantarle. La única solución es un paradigma primero-en-archivar, donde el primer registrador lo realiza satisfactoriamente y el segundo falla, un problema perfectamente adaptado para el protocolo de consenso de Bitcoin. Namecoin es la implementación más antigua y exitosa de un sistema de registro de nombres utilizando tal idea. - Monedas coloreadas - el propósito de las monedas coloreadas es servir como protocolo que permite a la gente crear sus propias monedas digitales, o, en el importante caso trivial de una moneda con una unidad, tokens digitales, en la blockchain de Bitcoin. En el protocolo de monedas coloreadas, alguien "emite" una nueva moneda al asignar públicamente un color a una UTXO de Bitcoin específica, y el protocolo define recursivamente el color de otras UTXO para que sean de color idéntico al de las entradas que la transacción que las creó ha gastado (algunas reglas especiales se aplican en el caso de entradas a color mixto). Esto permite a los usuarios tener carteras que contienen solo UTXO de un color específico y enviarlas por todo el mundo como bitcoins normales, rastreando hacia atrás por la blockchain para determinar el color de cualquier UTXO que reciban.
- Metacoin: La idea detrás de una metacoin es tener un protocolo que está montado sobre Bitcoin, usando transacciones de Bitcoin para almacenar las transacciones de metacoin, pero que tiene una función de transición de estado diferente,
APPLY'
. Dado que el protocolo metacoin no puede evitar que aparezcan transacciones de metacoin inválidas en la blockchain de Bitcoin, se añade una regla por la que siAPPLY'(S,TX)
devuelve un error, el protocolo por defecto aplicaAPPLY'(S,TX) = S
. Esto proporciona un mecanismo fácil para crear un protocolo arbitrario de criptomonedas, con posibles características avanzadas que no pueden ser implementadas dentro del propio Bitcoin, pero con un coste de desarrollo muy bajo, ya que las complejidades de minado y trabajo en red ya las gestiona el protocolo Bitcoin. Las metacoins se han utilizado para implementar algunas clases de contratos financieros, registro de nombres e intercambio descentralizado.
Por lo tanto, en general, hay dos enfoques para la construcción de un protocolo de consenso: construir una red independiente, o construir un protocolo sobre Bitcoin. El primer enfoque, aunque ha sido razonablemente exitoso en el caso de aplicaciones como Namecoin, es difícil de implementar; cada implementación individual necesita iniciar una blockchain independiente, además de construir y probar todas las transiciones de estado necesarias y el código de red. Además, predecimos que el conjunto de aplicaciones para la tecnología de consenso descentralizado seguirá una distribución de ley de potencias donde la gran mayoría de las aplicaciones serían demasiado pequeñas para garantizar su propia blockchain, y observamos que existen grandes clases de aplicaciones descentralizadas, en particular organizaciones autónomas descentralizadas, que necesitan interactuar entre sí.
El enfoque basado en Bitcoin, por otra parte, tiene el defecto de que no hereda las características de verificación de pago simplificada de Bitcoin. SPV funciona en Bitcoin porque puede usar la profundidad de blockchain como indicador de validez; en algún momento, una vez que los antecesores de una transacción van lo suficientemente atrás, se puede afirmar con seguridad que fueron legítimamente parte del estado. Los metaprotocolos basados en blockchain, por otra parte, no pueden forzar a la blockchain a no incluir transacciones que no son válidas en el contexto de sus propios protocolos. Por lo tanto, una implementación de metaprotocolo SPV completamente segura necesitaría escanear hasta el comienzo de la blockchain de Bitcoin para determinar si ciertas transacciones son válidas. Actualmente, todas las implementaciones "ligeras" de los metaprotocolos basados en Bitcoin dependen de un servidor de confianza para proporcionar los datos, lo que es presumiblemente un resultado altamente subóptimo, especialmente cuando uno de los propósitos primarios de una criptomoneda es eliminar la necesidad de confianza.
Scripting
Incluso sin ninguna extensión, el protocolo Bitcoin de hecho facilita una versión débil del concepto de "contratos inteligentes". La UTXO en Bitcoin puede ser propiedad no solo de una clave pública, sino también de un script más complicado expresado en un lenguaje simple de programación basado en pila. En este paradigma, una transacción que gaste esa UTXO debe proporcionar datos que satisfagan el script. De hecho, incluso el mecanismo público básico de propiedad de claves se implementa a través de un script: el script toma una firma de curva elíptica como entrada, lo verifica contra la transacción y la dirección que posee la UTXO, y devuelve 1 si la verificación es correcta y 0 en caso contrario. Existen otros scripts más complicados para varios casos de uso adicionales. Por ejemplo, se puede desarrollar un script que requiere firmas de dos de cada tres claves privadas para la validación ("multisig"), una configuración útil para cuentas corporativas, cuentas de ahorro seguras y algunos contextos de fideicomiso de comerciantes. Los scripts también pueden utilizarse para pagar recompensas por soluciones a problemas computacionales. y uno puede incluso construir un script que diga algo como: "este Bitcoin UTXO es tuyo si puedes proporcionar una prueba de SPV en la que enviaste una transacción de Dogecoin de esta denominación", permitiendo en esencia un intercambio descentralizado de criptomonedas.
Sin embargo, el lenguaje de scripting implementado en Bitcoin tiene varias limitaciones importantes:
- Falta de completitud Turing, es decir, mientras que hay un subconjunto grande de computación que el lenguaje de scripting de Bitcoin admite, no lo admite todo. La categoría principal que falta son los bucles. Esto se hace para evitar bucles infinitos durante la verificación de transacciones; teóricamente es un obstáculo superable para programadores de script, ya que cualquier bucle se puede simular simplemente repitiendo el código base muchas veces con un comando if, pero conduce a scripts que son muy ineficientes en términos de espacio. Por ejemplo, implementar un algoritmo alternativo de firma de la curva elíptica probablemente requeriría 256 rondas de multiplicación repetidas a incluir individualmente en el código.
- Indiferencia al valor: no hay forma de que un script UTXO proporcione un control detallado de la cantidad que se puede retirar. Por ejemplo, un caso de uso importante de un contrato de oráculo sería un contrato de cobertura, en el que A y B ponen 1000 dólares en BTC y después de 30 días el script envía 1000 dólares de BTC a A y el resto a B. Esto requeriría un oráculo para determinar el valor de 1 BTC en USD, pero aún así se trata de una mejora enorme en términos de confianza y e infraestructura con respecto a las soluciones totalmente centralizadas disponibles ahora. Sin embargo, dado que una UTXO es todo o nada, la única manera de lograr esto es a través de un hack muy ineficiente en el que tener muchas UTXO de diferentes denominaciones (por ejemplo, una UTXO de 2k para cada k de hasta 30) y hacer que el oráculo elija qué UTXO enviar a A y cuál a B.
- Falta de estado: una UTXO se puede gastar o no gastar; no hay ninguna posibilidad de contratos multietapa o scripts que mantengan cualquier otro estado interno más allá de eso. Esto hace difícil hacer contratos de opciones multietapa, ofertas de intercambio descentralizadas o protocolos de compromiso criptográficos en dos etapas (necesarios para recompensas computacionales seguras). También significa que UTXO solo puede utilizarse para construir contratos únicos aislados y no más contratos "con estado" complejos, como organizaciones descentralizadas, y dificulta la implementación de metaprotocolos. El estado binario combinado con la indiferencia al valor también implica que otra aplicación importante, el límite de retiro, es imposible.
- Ceguera a la Blockchain: las UTXO son ciegas a los datos de la blockchain como el nonce, la marca temporal y el hash del bloque anterior. Esto limita severamente las aplicaciones en juegos de azar y otras categorías, al privar al lenguaje de scripting de una fuente potencialmente valiosa de aleatoriedad.
Por tanto, consideramos tres enfoques para construir aplicaciones avanzadas encima de las criptomonedas: construir una nueva blockchain, usando scripting por encima de Bitcoin, y construyendo un metaprotocolo encima de Bitcoin. Construir una nueva blockchain permitiría libertad ilimitada al construir un conjunto de funcionalidades, pero a costa del tiempo de desarrollo, esfuerzo para ponerla en marcha, y seguridad. El uso de scripts es fácil de implementar y estandarizar, pero está muy limitado en sus capacidades, y los metaprotocolos, aunque sencillos, sufren de defectos en la escalabilidad. Con Ethereum, pretendemos construir un framework alternativo que proporcione mejoras aún mayores en cuanto a facilidad de desarrollo, así como como propiedades más robustas para clientes ligeros, al tiempo que permite a las aplicaciones compartir un entorno económico y la seguridad de la blockchain.
Ethereum
El propósito de Ethereum es crear un protocolo alternativo para construir aplicaciones descentralizadas, proporcionando un conjunto diferente de contrapartidas que creemos que serán muy útiles para un amplio abanico de aplicaciones descentralizadas, con especial énfasis en situaciones en las que el rápido tiempo de desarrollo, la seguridad para aplicaciones pequeñas y rara vez usadas y la capacidad de las diferentes aplicaciones para interactuar de manera muy eficiente son importantes. Ethereum lo logra construyendo lo que es esencialmente la capa fundacional abstracta definitiva: una blockchain con un lenguaje de programación Turing completo, que permite a cualquiera escribir contratos y aplicaciones descentralizadas donde pueden crear sus propias reglas reglas arbitrarias de propiedad, formatos de transacción y funciones de transición de estado. Una versión básica de Namecoin puede escribirse en dos líneas de código, y otros protocolos como monedas y sistemas de reputación se pueden incorporar en menos de veinte. Los contratos inteligentes, "cajas" criptográficas que contienen valor y sólo lo desbloquean si se cumplen ciertas condiciones también se pueden desarrollar por encima de la plataforma, con mucho más poder que el que ofrece el script de Bitcoin gracias a los poderes añadidos de completitud Turing, conocimiento del valor, conocimiento de la blockchain y estado.
Filosofía
El diseño en el que se basa Ethereum está pensado para seguir los siguientes principios:
- Simplicidad: el protocolo Ethereum debe ser tan simple como sea posible, incluso a costa de cierto almacenamiento de datos o uso del tiempo ineficientes.fn. 3 Un programador promedio debería ser idealmente capaz de entender e implementar toda la especificación,fn. 4 con objeto de comprender totalmente el potencial democratizadr sin precedentes que la criptomoneda trae y profundizar en la visión de Ethereum como un protocolo abierto a todos. Cualquier optimización que añada complejidad no debe incluirse a menos que esa optimización proporcione un beneficio sustancial.
- Universalidad: una parte fundamental de la filosofía de diseño de Ethereum es que Ethereum no tiene "funciones".fn. 5 En su lugar, Ethereum proporciona un lenguaje interno de scripting Turing completo, que un programador puede usar para desarrollar cualquier contrato inteligente o transacción de cualquier tipo que se pueda definir matemáticamente. ¿Quieres inventar tu propio derivado financiero? Con Ethereum, puedes. ¿Quieres crear tu propia moneda? Establécela como un contrato en Ethereum. ¿Quieres configurar un Daemon o una red Skynet a gran escala? Puede que necesites tener unos cuantos miles de contratos entrelazados y asegurarte de alimentarlos generosamente para lograrlo, pero nada te lo impide con Ethereum al alcance de tu mano.
- Modularidad: las partes del protocolo Ethereum deben diseñarse para ser tan modulares y separables como sea posible. En el transcurso del desarrollo, nuestro objetivo es crear un programa donde si uno fuera a hacer una pequeña modificación del protocolo en un solo lugar, la pila de la aplicación continuaría funcionando sin ninguna modificación adicional. Innovaciones como Ethash (consulta el protocolo en el apéndice o el artículo), los árboles de Patricia modificados (protocolo, wiki) y RLP (YP, wiki) deben ser y son, implementados como librerías separadas de funciones completas. Esto es así puesto que, aunque se usan en Ethereum e incluso si Ethereum no requiere ciertas funciones, estas funciones siguen siendo utilizables también en otros protocolos. El desarrollo de Ethereum debe de realizarse al máximo para beneficiar a todo el ecosistema de criptomonedas, no solo a sí mismo.
- Agilidad: los detalles del protocolo de Ethereum no son inamovibles. Aunque seremos extremadamente prudentes a la hora de hacer modificaciones a construcciones de alto nivel, como por ejemplo la hoja de ruta de sharding y la ejecución abstracta, con disponibilidad de datos solo grabada en el consenso. Pruebas computacionales posteriores en el proceso de desarrollo pueden llevarnos a descubrir que ciertas modificaciones, p. ej., en la arquitectura de protocolo o en la máquina virtual de Ethereum (EVM), mejorasen sustancialmente la escalabilidad o seguridad. Si se encuentran estas oportunidades, las explotaremos.
- No discriminación y no censura: el protocolo no debe intentar restringir o prevenir activamente categorías específicas de uso. Todos los mecanismos regulatorios del protocolo deben diseñarse para regular directamente el daño y no tratar de oponerse a aplicaciones específicas indeseables. Un programador puede incluso ejecutar un script en bucle infinito sobre Ethereum mientras esté dispuesto a seguir pagando la tarifa de transacción por paso computacional.
Cuentas de Ethereum
En Ethereum, el estado está compuesto por objetos llamados "cuentas", donde cada cuenta tiene una dirección de 20 bytes y transiciones de estado, que son transferencias directas de valor e información entre cuentas. Una cuenta de Ethereum contiene cuatro campos:
- El nonce, un contador utilizado para asegurarse de que cada transacción solo se puede procesar una vez
- El saldo ether actual de la cuenta
- El código de contrato de la cuenta si está presente
- El almacenamiento de la cuenta (vacío por defecto)
El "Ether" es el principal criptocombustible interno de Ethereum, y se utiliza para pagar las tarifas por transacción. En general, hay dos tipos de cuentas: cuentas de propiedad externa, controladas por claves privadas, y cuentas de contrato, controladas por su código de contrato. Una cuenta de propiedad externa no tiene código, y uno puede enviar mensajes desde una cuenta de propiedad externa creando y firmando una transacción; en una cuenta de contrato, cada vez que la cuenta de contrato recibe un mensaje, su código se activa, permitiéndola leer y escribir en el almacenamiento interno y enviar otros mensajes o crear contratos uno por uno.
Obsérvese que los "contratos" en Ethereum no deben ser vistos como algo que debe ser "satisfecho" o "cumplido"; son más bien parecidos a "agentes autónomos" que viven dentro del entorno de ejecución de Ethereum, siempre ejecutando una pieza específica de código cuando un mensaje o transacción les da "un toque", y tienen control directo sobre su propio saldo ether y su propio almacén de clave/valor para hacer un seguimiento de las variables persistentes.
Mensajes y transacciones
El término "transacción" se utiliza en Ethereum para referirse al paquete de datos firmados que almacena un mensaje para ser enviado desde una cuenta de propiedad externa. Las transacciones contienen:
- El destinatario del mensaje
- Una firma que identifica al remitente
- La cantidad de ether a transferir del remitente al destinatario
- Un campo de datos opcional
- Un valor
STARTGAS
, que representa el número máximo de pasos computacionales que se permite ejecuctar a la transacción - Un valor
GASPRICE
, que representa la tarifa que el remitente paga por paso computacional
Los tres primeros son campos estándar que se esperan en cualquier criptomoneda. El campo de datos no tiene ninguna función por defecto, pero la máquina virtual tiene un opcode que un contrato puede utilizar para acceder a los datos; como ejemplo de caso de uso, si un contrato está funcionando como un servicio de registro de dominio sobre la blockchain, entonces podría querer interpretar los datos que se le pasan como que contienen dos "campos", el primer campo sería un dominio a registra y el segundo campo es la dirección IP a la cual registrarlo. El contrato leería estos valores de los datos del mensaje y los guardaría adecuadamente en el almacenamiento.
Los campos STARTGAS
y GASPRICE
son cruciales para el modelo antidenegación de servicio de Ethereum. Para prevenir bucles infinitos hostiles o accidentales u otro despilfarro computacional en el código, cada transacción tiene que establecer un límite de cuántos pasos computacionales de ejecución de código puede utilizar. La unidad fundamental de cálculo es el "gas"; en general, un paso computacional cuesta 1 gas, pero algunas operaciones cuestan cantidades más altas de gas porque son más caras computacionalmente o incrementan la cantidad de datos que deben almacenarse como parte del estado. También hay una tarifa de 5 gas por cada byte en los datos de la transacción. La intención del sistema de tarifas es obligar a un atacante a pagar proporcionalmente por cada recurso que consuma, incluyendo la computación, ancho de banda y almacenamiento; por lo tanto, cualquier transacción que lleve a la red a consumir una mayor cantidad de cualquiera de estos recursos debe tener una tarifa de gas aproximadamente proporcional al incremento.
Mensajes
Los contratos tienen la capacidad de enviar "mensajes" a otros contratos. Los mensajes son objetos virtuales que nunca se serializan y existen sólo en el entorno de ejecución de Ethereum. Un mensaje contiene:
- El remitente del mensaje (implícito)
- El destinatario del mensaje
- La cantidad de ether a transferir junto con el mensaje
- Un campo de datos opcional
- Un valor de
STARTGAS
En esencia, un mensaje es como una transacción, excepto que la produce un contrato y no un actor externo. Un mensaje se crea cuando un contrato que se encuentra ejecutando código, ejecuta el opcode CALL
, el cual genera y ejecuta un mensaje. Como en una transacción, un mensaje hace que la cuenta del destinatario ejecute su código. Así, los contratos pueden tener relaciones con otros contratos exactamente de la misma manera que los actores externos pueden hacerlo.
Nótese que la cantidad de gas asignada por una transacción o contrato se aplica al gas total consumido por esa transacción y a todas sus subejecuciones. Por ejemplo, si un actor externo A envía una transacción a B con 1000 gas, y B consume 600 gas antes de enviar un mensaje a C, y la ejecución interna de C consume 300 gas antes de regresar, entonces B puede gastar otros 100 gas antes de quedarse sin gas.
Función de transición de estado de Ethereum
La función de transición de estado APPLY(S,TX) -> S'
puede definirse como sigue:
- Comprobar si la transacción está bien formada (es decir, si tiene el número correcto de valores), la firma es válida, y el nonce coincide con el nonce en la cuenta del remitente. Si no, devuelve un error.
- Calcular la tarifa de transacción como
STARTGAS * GASPRICE
y determinar la dirección de envío a partir de la firma. Restar la tarifa del saldo de la cuenta del remitente e incrementar el nonce del remitente. Si no hay suficiente saldo para gastar, devolver un error. - Inicializar
GAS = STARTGAS
y retirar una cierta cantidad de gas por byte para pagar por los bytes de la transacción. - Transferir el valor de la transacción desde la cuenta del remitente a la cuenta receptora. Si la cuenta receptora aún no existe, la crea. Si la cuenta receptora es un contrato, ejecutar el código del contrato hasta su terminación o hasta que la ejecución se quede sin gas.
- Si la transferencia de valor falla porque el remitente no tenía suficiente dinero o se cabó el gas durante la ejecución del código, revertir todos los cambios de estado excepto el pago de las tarifas, y añadir las comisiones a la cuenta del minero.
- En caso contrario, devolver las comisiones por todo el gas restante al remitente y enviar las tarifas pagadas por el gas consumido al minero.
Por ejemplo, supongamos que el código del contrato es:
if !self.storage[calldataload(0)]:
self.storage[calldataload(0)] = calldataload(32)
Ten en cuenta que, en realidad, el código del contrato está escrito en el código de bajo nivel de la EVM; este ejemplo está escrito en Serpent, uno de nuestros lenguajes de alto nivel, para mayor claridad, que puede ser compilado a código de la EVM. Supongamos que el almacenamiento del contrato empieza vacío, y se envía una transacción con valor de 10 ether, 2000 gas, 0,001 de precio de gas ether y 64 bytes de datos, con los bytes 0-31 representando el número 2
y los bytes 32-63 representando la cadena CHARLIE
.fn. 6 El proceso para la función de transición de estado en este caso es el siguiente:
- Comprobar que la transacción es válida y está bien formada.
- Comprobar que el remitente de la transacción tiene al menos 2000 * 0,001 = 2 ether. Si los tiene, restar 2 ether de la cuenta del remitente.
- Inicializar gas = 2000; suponiendo que la transacción tenga 170 bytes de longitud y que la tarifa por byte sea 5, restar 850 y quedarán 1150 gas.
- Restar 10 ether más de la cuenta del remitente y añadirlos a la cuenta del contrato.
- Ejecutar el código. En este caso es simple: comprueba si se utiliza el almacenamiento del contrato en índice
2
, observa que no, por lo que asigna al almacenamiento en el índice2
el valorCHARLIE
. Supongamos que esto consume 187 gas, así que la cantidad restante de gas es 1150 - 187 = 963 - Añadir 963 * 0,001 = 0.963 ether de vuelta a la cuenta del remitente y devolver el estado resultante.
Si no hubiera un contrato en el extremo receptor de la transacción, entonces la tarifa total de transacción sería simplemente igual al GASPRICE
proporcionado multiplicado por la longitud de la transacción en bytes, y los datos enviados junto a la transacción serían irrelevantes.
Ten en cuenta que los mensajes funcionan de forma equivalente a las transacciones en términos de revertirse: si la ejecución de un mensaje se queda sin gas, entonces la ejecución del mensaje y todas las demás ejecuciones activadas por esa ejecución, se revierten, pero las ejecuciones padres no necesitan revertirse. Esto significa que es "seguro" para un contrato llamar a otro contrato, como si A llama a B con G gas, entonces se garantiza que la ejecución de A perdería como máximo G gas. Por último, tener en cuenta que hay un opcode, CREATE
, que crea un contrato; su mecánica de ejecución generalmente es similar a CALL
, con la excepción de que la salida de la ejecución determina el código del contrato recién creado.
Ejecución de código
El código en los contratos de Ethereum está escrito en un lenguaje de bajo nivel bytecode basado en pila, conocido como "código de máquina virtual de Ethereum" o "código de la EVM". El código consiste en una serie de bytes, donde cada byte representa una operación. En general, la ejecución del código es un bucle infinito que consiste en ejecutar repetidamente la operación en el contador actual de programa (que comienza en cero) y luego incrementar el contador del programa en uno, hasta que se alcance el final del código o se detecte un error o una instrucción STOP
o RETURN
. Las operaciones tienen acceso a tres tipos de espacio en el que almacenar datos:
- La pila, un contenedor «último en entrar, primero en salir» cuyos valores se pueden apilar y retirar
- Memoria, un array de bytes expandible infinitamente
- El almacenamiento a largo plazo del contrato, un almacén de clave/valor. A diferencia de la pila y la memoria, que se restablecen una vez termina la computación, el almacenamiento persiste a largo plazo.
El código también puede acceder al valor, remitente y datos del mensaje entrante, así como datos del bloque de cabecera. El código también puede devolver un array de bytes de datos como salida.
El modelo de ejecución formal de código de la EVM es sorprendentemente simple. Mientras que la máquina virtual de Ethereum está en ejecución, su estado computacional completo se puede definir por la tupla (estado_del_bloque, transacción, mensaje, código, memoria, pila, pc, gas)
, donde estado_del_bloque
es el estado global que contiene todas las cuentas e incluye saldos y almacenamiento. Al inicio de cada ronda de ejecución, la instrucción actual se encuentra tomando el pc
-ésimo byte de código
(o 0 si pc >= len(code)
), y cada instrucción tiene su propia definición en términos de como afecta a la tupla. Por ejemplo, ADD
retira dos elementos de la pila y apila su suma, reduce gas
en 1 e incrementa pc
en 1, y SSSTORE
retira los dos elementos superiores de la pila e inserta el segundo elemento en el almacenamiento del contrato en el índice especificado por el primer elemento. Aunque hay muchas maneras de optimizar la ejecución de la máquina virtual de Ethereum mediante la compilación en tiempo de ejecución, una implementación básica de Ethereum puede hacerse en unos pocos cientos de líneas de código.
Blockchain y minería
La blockchain de Ethereum es en muchas maneras similar a la blockchain de Bitcoin, aunque tiene algunas diferencias. La diferencia principal entre Ethereum y Bitcoin en relación a la arquitectura blockchain es que, a diferencia de Bitcoin (que solo contiene una copia de la lista de la transacciones), los bloques de Ethereum contienen una copia tanto de la lista de transacciones como del estado más reciente. Aparte, hay dos valores, el número de bloque y la dificultad, que también se almacenan en el bloque. El algoritmo básico de validación de bloque en Ethereum es el siguiente:
- Comprobar si el bloque anterior referenciado existe y es válido.
- Comprobar que la marca temporal del bloque es mayor que la del bloque anterior referenciado e inferior a 15 minutos en el futuro
- Comprobar que el número de bloque, dificultad, raíz de la transacción, raíz "uncle" límite de gas (diversos conceptos específicos de bajo nivel de Ethereum) son válidos.
- Comprobar que la prueba de trabajo del bloque es válida.
- Dejar que
S[0]
sea el estado al final del bloque anterior. - Sea
TX
es la lista de transacciones del bloque, conn
transacciones. Para todoi
en0...n-1
, asignarS[i+1] = APPLY(S[i],TX[i])
. Si cualquier aplicación devuelve un error, o si el gas total consumido en el bloque hasta este punto excede elGASLIMIT
, devolver un error. - Hacer que
S_FINAL
seaS[n]
, pero añadiendo la recompensa de bloque pagada al minero. - Comprobar si la raíz del árbol Merkle del state
S_FINAL
es igual a la raiz del estado final proporcionada en la cabecera del bloque. Si es así, el bloque es válido; de lo contrario, no es válido.
El enfoque puede parecer muy ineficiente a primera vista, porque necesita almacenar todo el estado con cada bloque, pero en realidad la eficiencia debe ser comparable a la de Bitcoin. La razón es que el estado se almacena en la estructura del árbol, y después de cada bloque sólo una pequeña parte del árbol necesita ser modificada. Por lo tanto, en general, entre dos bloques adyacentes la inmensa mayoría del árbol debe ser idéntico, y por lo tanto los datos pueden ser almacenados una vez y referenciados dos veces usando punteros (esto es, hashes de los subárboles). Un tipo especial de árbol conocido como "árbol Patricia" se utiliza para lograr esto incluyendo una modificación al concepto de árbol Merkle que permite que se inserten y eliminen nodos, y no solo que se cambien, de forma eficiente. Además, dado que toda la información de estado es parte del último bloque, no hay necesidad de almacenar todo el historial de la blockchain, una estrategia que, si se pudiera aplicar a Bitcoin, se calcular que proporcionaría entre 5-20 veces de ahorro de espacio.
Una pregunta habitual es "dónde" se ejecuta el código del contrato, en términos del hardware físico. Esto tiene una respuesta simple: el proceso de ejecución del código del contrato es parte de la definición de la función de transición de estado, que es parte del algoritmo de validación de bloques, así que si una transacción se añade al bloque B
, la ejecución del código generada por esa transacción se ejecutará por todos los nodos, ahora y en el futuro, que descarguen y validen el bloque B
.
Aplicaciones
En general, hay tres tipos de aplicaciones sobre Ethereum. La primera categoría son las aplicaciones financieras, que ofrecen a los usuarios formas más potentes de gestionar y suscribir contratos con su dinero. Esto incluye submonedas, derivados financieros, contratos de cobertura, carteras de ahorros, testamentos e incluso, en última instancia, algunas clases de contratos de empleo a gran escala. La segunda categoría son aplicaciones semifinancieras en las que el dinero está presente, pero también hay una destacada parte no monetaria junto a lo que se está haciendo; un ejemplo perfecto son las recompensas autoaplicadas a soluciones a problemas computacionales. Por último, hay aplicaciones como el voto en línea y el gobierno descentralizado que no son en absoluto financieras.
Sistemas de Token
Los sistemas de tokens en blockchain tienen muchas aplicaciones que van desde submonedas que representan activos como el USD o el oro, hasta acciones de empresas, tokens individuales que representan una propiedad inteligente, cupones seguros infalsificables, e incluso sistemas de tokens sin ningún vínculo con un valor convencional en absoluto, utilizados como sistemas de puntos para incentivos. Los sistemas de token son sorprendentemente fáciles de implementar en Ethereum. El punto clave a entender es que una moneda, o sistema de token, de forma fundamental es una base de datos con una operación: restar X unidades de A y dar X unidades a B, con la disposición de que (1) A tuviera al menos X unidades antes de la transacción y (2) que la transacción sea aprobada por A. Todo lo que se necesita para implementar un sistema de token es implementar esta lógica en un contrato.
El código básico para implementar un sistema de token en Serpent tiene este aspecto:
def send(to, value):
if self.storage[msg.sender] >= value:
self.storage[msg.sender] = self.storage[msg.sender] - value
self.storage[to] = self.storage[to] + value
Esta es en esencia una implementación literal de la función de transición de estado de un "sistema bancario" descrita más arriba en este documento. Hay que añadir algunas líneas de código adicionales para crear en primer lugar el paso inicial en el que se distribuyen las unidades de moneda y otros casos extremos, e idealmente se añadiría una función para permitir que otros contratos puedan consultar el saldo de una dirección. Pero eso es todo lo que hay que hacer. En teoría, los sistemas de token basados en Ethereum que actúan como submonedas pueden incluir potencialmente otra característica importante de la que carecen las metamonedas basadas en la cadena de Bitcoin: la capacidad de pagar las tarifas de transacción directamente en esa moneda. La forma en que se implementaría esto sería haciendo que el contrato mantendría un saldo de ether con el cual reembolsaría el ether utilizado para pagar comisiones al remitente, y recargaría este saldo recolectando las unidades de moneda interna que cobra en tarifas y revenderlas en una subasta en ejecución constante. Así, los usuarios necesitarían "activar" sus cuentas con ether, pero una vez que el ether está ahí, sería reutilizable porque el contrato lo reembolsaría cada vez.
Derivados financieros y monedas de valor estable
Los derivados financieros son la aplicación más común de un "contrato inteligente", y uno de los más sencillos de implementar en código. El desafío principal al implementar contratos financieros es que la mayoría de ellos requieren referencia a un teletipo de precio externo; por ejemplo, una aplicación muy deseable es un contrato inteligente que protege contra la volatilidad del ether (u otra criptomoneda) con respecto al dólar estadounidense, pero para hacer esto es necesario que el contrato sepa cuál es el cambio de ETH/USD. La forma más sencilla de hacer esto es a través de un contrato de "fuente de datos" gestionado por una entidad específica (p. ej., NASDAQ), y diseñado para que esa entidad tenga la capacidad de actualizar el contrato según sea necesario y que proporcione una interfaz que permite a otros contratos enviar un mensaje a ese contrato y recuperar una respuesta que proporcione el precio.
Dado dicho ingrediente crítico, el contrato de cobertura sería siguiente:
- Esperar a que la parte A introduzca 1000 ether.
- Esperar a que la parte B introduzca 1000 ether.
- Almacenar el valor de 1000 ether en USD, calculados mediante consulta al contrato de fuente de datos, en el almacenamiento, digamos que es $x.
- Después de 30 días, permitir a A o B "reactivar" el contrato para enviar $x en ether (calculado mediante consulta al contrato de la fuente de datos para obtener el nuevo precio) a A y el resto a B.
Un contrato así tendría un gran potencial en el comercio en criptomonedas. Uno de los problemas principales que se citan sobre las criptomonedas es el hecho de que son volátiles; aunque muchos usuarios y comerciantes pueden querer la seguridad y conveniencia de operar con activos criptográficos, tal vez no quieran enfrentarse a la perspectiva de perder el 23 % del valor de sus fondos en un solo día. Hasta ahora, la solución más propuesta ha sido la de activos respaldados por emisores; la idea es que un emisor crea una submoneda en la que tiene derecho a emitir y retirar unidades, y proporcionar una unidad de la moneda a cualquiera que les proporcione (fuera de línea) una unidad de un activo subyacente especificado (p. ej., oro, USD). A continuación, el emisor se compromete a proporcionar una unidad del activo subyacente a cualquiera que envíe de vuelta una unidad del criptoactivo. Este mecanismo permite que cualquier activo no criptográfico se "eleve" a activo criptográfico, siempre que se pueda confiar en el emisor.
En la práctica, sin embargo, los emisores no siempre son fiables, y en algunos casos la infraestructura bancaria es demasiado débil o demasiado hostil para que estos servicios existan. Los derivados financieros ofrecen una alternativa. Aquí, en lugar de un único emisor que proporciona los fondos para respaldar un activo, un mercado descentralizado de especuladores que apuestan a que el precio de un activo criptográfico de referencia (p. ej., ETH) subirá, desempeñará ese papel. A diferencia de los emisores, los especuladores no tienen la opción de suspender pagos en su parte del acuerdo, porque el contrato de cobertura mantiene sus fondos en fideicomiso. Nótese que este enfoque no está completamente descentralizado, dado que todavía se necesita una fuente de confianza para proporcionar el teletipo de precios, aunque presumiblemente incluso esto es una mejora enorme en términos de reducción de requisitos de infraestructura (a diferencia de ser un emisor, la emisión de una fuente de precios no requiere ninguna licencia y es probable que se pueda categorizar dentro de la libre expresión) y reducción del riesgo de fraude.
Sistemas de identidad y reputación
La primera de todas las criptomonedas alternativas, Namecoin, intentó usar una blockchain de tipo Bitcoin para proporcionar un sistema de registro de nombres, donde los usuarios pueden registrar sus nombres en una base de datos pública junto con otros datos. El caso de uso más citado es para un sistema DNS, que asigna nombres de dominio como "bitcoin.org" (o, en el caso de Namecoin, "bitcoin.bit") a una dirección IP. Otros casos de uso incluyen autenticación de correo electrónico y sistemas de reputación potencialmente más avanzados. Este es el contrato básico para proporcionar un sistema de registro de nombres similar a Namecoin en Ethereum:
def register(name, value):
if !self.storage[name]:
self.storage[name] = value
El contrato es muy sencillo; es tan solo una base de datos dentro de la red de Ethereum a la que se puede añadir datos, pero no modificarlos ni eliminarlos. Cualquiera puede registrar un nombre asignando cierto valor, y ese registro se queda para siempre. Un contrato de registro de nombres más sofisticado también tendrá una "función de cláusula" que permitiría a otros contratos consultarla, así como un mecanismo para que el "propietario" (es decir, el primer registrador) de un nombre pueda cambiar los datos o transferir la propiedad. Se puede incluso añadir reputación y funcionalidad «web-of-trust» por encima.
Almacenamiento de archivos descentralizado
En los últimos años, han surgido una serie de empresas emergentes populares para almacenar archivos en línea, siendo Dropbox la más destacada, que buscan permitir a los usuarios subir una copia de seguridad de su disco duro y tener un servicio de copia de seguridad y permitir al usuario acceder a este a cambio de una cuota mensual. En este momento, sin embargo, el mercado de almacenamiento de archivos es a veces relativamente ineficiente; una mirada rápida a varias soluciones existentes lo muestra, particularmente en el nivel de "valle inquietante" entre 20-200 GB, en el que ni se activan las cuotas gratuitas ni los descuentos de nivel empresarial, los precios mensuales del coste de almacenamiento de archivos son tan elevados que se paga más de lo que cuesta todo el disco duro en un solo mes. Los contratos de ethereum pueden permitir el desarrollo de un ecosistema de almacenamiento de archivos descentralizado, donde los usuarios individuales pueden ganar pequeñas cantidades de dinero alquilando sus propios discos duros y el espacio no utilizado puede utilizarse para reducir aún más el coste del almacenamiento de archivos.
La pieza clave fundamental de dicho dispositivo sería lo que hemos llamado el "contrato Dropbox descentralizado". Este contrato funciona como se indica a continuación. Primero, se dividen los datos deseados en bloques, cifrando cada bloque por privacidad, y se construye un árbol de Merkle a partir de ellos. Se crea entonces un contracto con la regla de que cada N bloques, el contrato elegirá un índice aleatorio en el árbol de Merkle (usando el hash del bloque anterior, accesible desde el código del contrato, como fuente de aleatoriedad), y dará X ether a la primera entidad que proporcione una transacción con una prueba de propiedad similar a la verificación de pago simplificado del bloque para ese índice específico del árbol. Cuando un usuario quiere volver a descargar su archivo, puede utilizar un protocolo de canal de micropago (p. ej., pagar 1 szabo por cada 32 kilobytes) para recuperar el archivo; la forma más eficiente de tarificación es que el pagador no publique la transacción hasta el final, y en su lugar reemplace la transacción por una ligeramente más lucrativa con el mismo nonce tras cada 32 kilobytes.
Una característica importante del protocolo es que, aunque puede parecer que se confía en que muchos nodos aleatorios decidan no olvidar el archivo, se puede reducir ese riesgo a casi cero dividiendo el archivo en muchas piezas a través del compartido secreto, y observar los contratos para ver que cada pieza sigue en posesión de algunos nodos. Si un contrato sigue pagando dinero, esto proporciona una prueba criptográfica de que alguien todavía está almacenando el archivo.
Organizaciones autonómas descentralizadas
El concepto general de una "organización autónoma descentralizada" (DAO por sus siglas en inglés) es el de una entidad virtual que tiene cierto número de miembros o accionistas que, quizás con una mayoría del 67 %, tienen el derecho a gastar los fondos de la entidad y modificar su código. Los miembros decidirían colectivamente el modo en el que la organización debe destinar sus fondos. Los métodos para destinar los fondos de una DAO podrían variar, desde recompensas y sueldos hasta mecanismos más exóticos, como una moneda interna para recompensar el trabajo. Esto esencialmente replica los elementos legales de una empresa tradicional o sin fines de lucro, pero utiliza solo tecnología criptográfica de blockchain para su cumplimiento. Hasta ahora, gran parte de las conversaciones alrededor de las DAO han tratado acerca del modelo "capitalista" de una "corporación autónoma descentralizada" (DAC por sus siglas en inglés), con accionistas que reciben dividendos y acciones negociables; una alternativa, tal vez descrita como una "comunidad autónoma descentralizada", haría que todos los miembros tuvieran una parte idéntica en la toma de decisiones y requeriría que el 67 % de los miembros existentes aceptaran agregar o eliminar un miembro. El requisito de que una persona puede ser miembro solo una vez necesitaría ser impuesto colectivamente por el grupo.
Un esquema general de cómo implementar un DAO es el siguiente. El diseño más simple es simplemente una sección de código automodificable que cambia si dos tercios de los miembros están de acuerdo en un cambio. Aunque el código es teóricamente inmutable, esto se puede eludir fácilmente y tener mutabilidad de facto al tener fragmentos del código en contratos separados, y teniendo la dirección de a qué contratos llamar guardados en el almacenamiento modificable. En una implementación simple de dicho contrato DAO, habría tres tipos de transacción, diferenciadas por los datos proporcionados en la transacción:
[0,i,K,V]
para registrar una propuesta con índicei
para cambiar la dirección en el índice de almacenamientoK
al valorV
[1,i]
para registrar un voto a favor de la propuestai
[2,i]
para finalizar la propuestai
si tiene los suficientes votos
El contrato tendría entonces cláusulas para cada una de ellas. Mantendría un registro de todos los cambios de almacenamiento abiertos, junto con una lista de quienes han votado por ellos. También tendría una lista de todos los miembros. Cuando cualquier cambio de almacenamiento alcanza el voto de dos tercios de los miembros, una transacción finalizadora podría ejecutar el cambio. Un esquema más sofisticado también tendría capacidad de voto incorporada para funciones tales como el envío de una transacción, añadir y borrar miembros, e incluso puede proporcionar una delegación de votos tipo Democracia líquida (p. ej. cualquiera puede asignar a alguien para votar por él, y dicha asignación es transitiva, de modo que si A asigna a B y B asigna a C, entonces C determina el voto de A). Este diseño permitiría que la DAO crezca orgánicamente como una comunidad descentralizada, permitiendo a la gente a eventualmente delegar la tarea de filtrar quién sería miembro a especialistas, aunque a diferencia de lo que ocurre en el "sistema actual", los especialistas pueden aparecer y desaparecer a medida que los miembros individuales cambian sus posicionamientos.
Hay un modelo alternativo para una corporación descentralizada, donde cualquier cuenta puede tener cero o más acciones, y se necesitan dos tercios de las acciones para tomar una decisión. Un esquema completo implicaría una función de gestión de activos, la posibilidad de hacer una oferta de compraventa de acciones y la capacidad de aceptar ofertas (preferiblemente con un mecanismo de casamiento de órdenes dentro del contrato). La delegación también existiría al estilo de la democracia líquida, generalizando el concepto de un "consejo directivo".
Otras aplicaciones
1. Carteras de ahorro. Supongamos que Alice quiere mantener sus fondos a salvo, pero le preocupa perder su clave privada o que alguien la hackee. Entonces pone ether en un contrato con Bob, un banco, como sigue:
- Alice solo puede retirar un máximo del 1 % de los fondos por día.
- Bob por su parte solo puede retirar un máximo del 1 % de los fondos por día, pero Alice tiene la habilidad de hacer una transacción con su clave que elimine esta capacidad.
- Alice y Bob juntos pueden retirar cualquier cantidad.
Normalmente, el 1 % diario es suficiente para Alice, y si Alice quiere retirar más, puede contactar con Bob para que le ayude. Si la clave de Alice es hackeada, se dirige a Bob con celeridad para trasladar los fondos a un nuevo contrato. Si pierde su clave, Bob podrá sacar los fondos eventualmente. Si Bob resulta ser malicioso, ella puede desactivar su capacidad para retirar fondos.
2. Seguro de cosecha. Se puede hacer fácilmente un contrato de derivados financieros usando una fuente de datos meteorológicos en lugar de cualquier índice de precios. Si un agricultor de Iowa compra un derivado que paga a la inversa de acuerdo a la precipitación de Iowa, entonces si hay una sequía, el agricultor recibirá automáticamente dinero y, si llueve lo suficiente, el agricultor estará contento porque a sus cultivos les va a ir bien. Esto puede ampliarse a los seguros de desastres naturales en general.
3. Una fuente de datos descentralizada. Para contratos financieros por diferencias, podría ser posible descentralizar la fuente de datos a través de un protocolo llamado SchellingCoin. SchellingCoin funciona básicamente de la siguiente manera: N partes introducen en el sistema el valor de un ato determinado (p. ej. el precio del ETH/USD), los valores están ordenados, y todos aquellos entre el percentil 25 y el 75 obtienen un token como recompensa. Todo el mundo tiene el incentivo para proporcionar la respuesta que todos los demás les proporcionarán, y el único valor en el que un gran número de jugadores pueden estar de acuerdo de forma realista es el valor obvio por defecto: el verdadero. Esto crea un protocolo descentralizado que puede proporcionar teóricamente cualquier número de valores, incluidos el precio del ETH/USD, la temperatura en Berlín o incluso el resultado de un cálculo particularmente difícil.
4. Fideicomiso multifirma inteligente. Bitcoin permite contratos de transacción multifirma donde, por ejemplo, tres de las cinco claves dadas pueden gastar los fondos. Ethereum permite más granularidad; por ejemplo, cuatro de cada cinco pueden gastarlo todo, tres de cada cinco pueden gastar hasta un 10 % al día y dos de cada cinco pueden gastar hasta 0,5 % al día. Además, la multifirma de Ethereum es asíncrona: dos partes pueden registrar sus firmas en la blockchain en diferentes momentos y la última firma enviará automáticamente la transacción.
5. Computación en la nube. La tecnología EVM también puede utilizarse para crear un entorno de computación verificable que permite a los usuarios pedir a otros que realicen cálculos y, opcionalmente, pedir pruebas de que los cálculos en ciertos puntos de control seleccionados aleatoriamente se realizaron correctamente. Esto permite la creación de un mercado de computación en la nube donde cualquier usuario puede participar con su escritorio, portátil o servidor especializado, y el control por muestreo junto con depósitos de seguridad se pueden usar para asegurar que el sistema es de confianza (es decir, los nodos no pueden hacer trampa fructuosamente). Aunque tal sistema puede no ser adecuado para todas las tareas; las tareas que requieren un alto nivel de comunicación entre procesos, por ejemplo, no pueden ejecutarse fácilmente en una nube grande de nodos. Otras tareas, sin embargo, son mucho más fáciles de paralelizar; proyectos como SETI@home, folding@home y algoritmos genéticos pueden implementarse fácilmente sobre una plataforma de este tipo.
6. Apuestas entre pares. Cualquier cifra de protocolos de apuestas entre pares, tal y como Cyberdice de Frank Stajano y Richard Clayton, pueden implementarse en la blockchain de Ethereum. El protocolo de apuestas más simple en realidad es simplemente un contrato por diferencias en el siguiente hash de bloque, y a partir de ahí pueden construirse protocolos más avanzados, creando servicios de apuestas con tarifas cercanas a cero en donde no hay la posibilidad de hacer trampas.
7. Mercados de predicciones. Habiendo un oráculo o SchellingCoin, los mercados de predicciones también son fáciles de implementar, y los mercados de predicciones junto con SchellingCoin podrían resultar en la primera aplicación de la futarquía como protocolo de gobierno para organizaciones descentralizadas.
8. Mercados descentralizados sobre la cadena, usando el sistema de identidad y de reputación como base.
Miscelánea y dudas
Implementación de GHOST modificada
El protocolo del "subárbol observado voraz más pesado" (en inglés: Greedy Heaviest Observed Subtree, GHOST) es una innovación presentada por primera vez por Yonatan Sompolinsky y Aviv Zohar en diciembre de 2013. La motivación detrás de GHOST es que las blockchains con tiempos de confirmación rápidos actualmente sufren de una menor seguridad debido a una alta tasa de obsolescencia: puesto que los bloques tardan un cierto tiempo en propagarse a través de la red, si el minero A extrae un bloque y luego el minero B extrae otro bloque antes de que el bloque del minero A se propague a B, el bloque del minero B se desperdiciará y no contribuirá a la seguridad de la red. Además, hay un problema de centralización: si el minero A es una pool de minado con un 30 % de potencia de hash y el minero B tiene un 10 % de potencia de hash, el minero A tendrá el riesgo de producir un bloque obsoleto un 70 % del tiempo (ya que el 30 % restante del tiempo, el minero A produjo el último bloque y también obtendrá datos de minado inmediatamente) mientras que el minero B tendrá el riesgo de producir un bloque obsoleto 90 % del tiempo. Por tanto, si el intervalo de bloque es lo suficientemente corto como para que la tasa de obselescencia sea alta, A será sustancialmente más eficiente simplemente en virtud de su tamaño. Con estos dos efectos combinados, es muy probable que las blockchains que producen bloques rápidamente, hagan que una pool de minado, que tenga un porcentaje lo suficientemente grande de la potencia de hash de red, acabe teniendo el control de facto sobre el proceso de minado.
Como describen Sompolinsky y Zohar, GHOST resuelve el primer problema de pérdida de seguridad de red al incluir bloques obsoletos en el cálculo de qué cadena es la "más larga"; es decir, no solo el padre y los ancestros adicionales de un bloque, sino que también los descendientes obsoletos del ancestro del bloque (en jerga de Ethereum, "uncles", es decir, tíos) se añaden al cálculo de qué bloque tiene la prueba de trabajo total más grande respaldándola. Para resolver el segundo problema del sesgo de la centralización, vamos más allá del protocolo descrito por Sompolinsky y Zohar, y también proporcionamos recompensas de bloque a los obsoletos: un bloque obsoleto recibe el 87,5 % de su recompensa base, y el sobrino que incluye el bloque obsoleto recibe el 12,5 % restante. Sin embargo, las tasas de transacción no se otorgan a los uncles.
Ethereum implementa una versión simplificada de GHOST que solo desciende siete niveles. Concrétamente, se define como sigue:
- Un bloque debe especificar un padre, y debe especificar 0 o más uncles
- Un uncle incluido en el bloque
B
debe tener las siguientes propiedades: - Debe ser un hijo directo del antepasado del ancestro de generación
k
-ésima deB
, donde2 <= k <= 7
. - No puede ser un ancestro de
B
- Un uncle debe ser una cabecera de bloque válido, pero no necesita ser un bloque previamente verificado o incluso válido
- Un uncle debe ser diferente de todos los uncles incluidos en bloques anteriores y todos los demás uncles incluidos en el mismo bloque (no doble inclusión)
- Por cada uncle
U
en el bloqueB
, el minero deB
recibe un 3,125 % adicional que se añade a su recompensa de coinbase y el minero de U obtiene el 93,75 % de una recompensa estándar de coinbase.
Esta versión limitada de GHOST, que permite incluir uncles hasta un límite de 7 generaciones, se utilizó por dos razones. La primera, GHOST ilimitado incluiría demasiadas complicaciones en el cálculo de que uncles para un bloque determinado son válidos. La segunda, GHOST ilimitado con compensación como se usa en Ethereum elimina el incentivo de un minero para minar en la cadena principal y no la cadena de un atacante público.
Tarifas
Puesto que cada transacción publicada en la blockchain impone a la red el coste de la necesidad de descargarla y verificarla, es necesario algún mecanismo regulatorio, que normalmente implica tarifas de transacción, para prevenir abusos. El enfoque por defecto, utilizado en Bitcoin, es tener únicamente comisiones voluntarias, dependiendo de los mineros para que actúen como los guardianes y establezcan mínimos dinámicos. Este enfoque ha sido recibido muy favorablemente en la comunidad de Bitcoin, en particular porque está "basado en el mercado", permitiendo la oferta y la demanda entre los mineros y los remitentes de transacciones determinen el precio. El problema con esta forma de razonar es, no obstante, que el procesado de transacciones no es un mercado; aunque es intuitivamente atractivo interpretar el procesado de transacciones como un servicio que el que el minero ofrece al remitente, en realidad cada transacción que incluye un minero tendrá que ser procesada por todos los nodos de la red. por lo que la gran mayoría del coste del procesado de las transacciones es asumido por terceras partes y no el minero que está tomando la decisión de incluirla o no. Por lo tanto, es muy probable que ocurren problemas de la tragedia de los comunes.
Sin embargo, resulta que este defecto en el mecanismo basado en el mercado, cuando se da un supuesto simplificador inexacto en particular, mágicamente se cancela. El argumento es el siguiente. Supongamos que:
- Una transacción conduce a
k
operaciones, ofreciendo la recompensakR
a cualquier minero que la incluya, dondeR
lo establece el remitente yk
yR
son (aproximadamente) visibles para el minero de antemano. - Una operación tiene un coste de procesamiento de
C
para cualquier nodo (es decir, todos los nodos tienen la misma eficiencia) - Hay
N
nodos de minado, cada uno con exactamente la misma potencia de procesamiento (es decir,1/N
del total) - No existen nodos completos que no minen.
Un minero estará dispuesto a procesar una transacción si la recompensa esperada es mayor que el coste. Por lo tanto, la recompensa esperada es de kR/N
ya que el minero tiene una probabilidad de 1/N
de procesar el siguiente bloque, y el coste de procesamiento para el minero es simplemente kC
. Por lo tanto, los mineros incluirán transacciones donde se cumpla que kR/N > kC
, o R > NC
. Nótese que R
es la tarifa por operación proporcionada por el remitente y es por lo tanto un límite inferior al beneficio que el remitente obtiene de la transacción, y NC
es el coste para toda la red del procesamiento de una operación. Por lo tanto, los mineros tienen el incentivo de incluir solo aquellas transacciones en las que el beneficio utilitario total supere al coste.
Sin embargo, hay varias divergencias importantes de esas suposiciones en la realidad:
- El minero paga un coste mayor para procesar la transacción que otros nodos de verificación, ya que el tiempo de verificación adicional retrasa la propagación del bloque y por lo tanto aumenta la probabilidad de que el bloque se convierta en caducado.
- Existen nodos completos que no minan.
- La distribución de potencia de minado puede acabar siendo radicalmente desigualitaria en la práctica.
- Los especuladores, enemigos políticos y dementes, cuya función de utilidad incluye causar daño a la red, existen y pueden establecer hábilmente contratos cuyo coste es mucho menor que el coste pagado por otros nodos de verificación.
(1) proporciona una tendencia al minero a que incluya menos transacciones, e (2) incrementa NC
; por lo tanto, estos dos efectos al menos parcialmente se cancelan entre sí.[¿Cómo?](https://github. om/ethereum/wiki/issues/447#issuecomment-316972260) (3) y (4) son el principal problema; para resolverlos, simplemente fijamos un límite reajustable: ningún bloque puede tener más operaciones que BLK_LIMIT_FACTOR
veces el promedio de la media móvil exponencial a largo plazo. Específicamente:
blk.oplimit = floor((blk.parent.oplimit \* (EMAFACTOR - 1) +
floor(parent.opcount \* BLK\_LIMIT\_FACTOR)) / EMA\_FACTOR)
BLK_LIMIT_FACTOR
y EMA_FACTOR
son constantes que se les asignará respectivamente los valores 65 536 y 1,5 por el momento, pero probablemente se cambiará después de un análisis más en detalle.
Hay otro factor que desincentiva los tamaños de bloques grandes en Bitcoin: los bloques grandes tardarán más en propagarse y por lo tanto tienen una mayor probabilidad de convertirse en caducados. En Ethereum, los bloques que consumen mucho gas también pueden tardar más en propagarse porque son físicamente más grandes y porque tardan más en procesar las transiciones del estado de la transacción para validarla. Este desincentivo por el retraso es una consideración significativa en Bitcoin, pero menos en Ethereum gracias al protocolo GHOST; por lo tanto, depender de límites de bloques regulados proporciona una base de referencia más estable.
Computación y completitud Turing
Un apunte importante es que la máquina virtual de Ethereum es Turing-completa; esto significa que el código EVM puede codificar cualquier cómputo que se pueda llevar a cabo, incluyendo bucles infinitos. El código de EVM permite hacer bucles de dos maneras. En primer lugar, hay una instrucción JUMP
que permite al programa saltar a un punto anterior del código, y una instrucción JUMPI
para hacer saltos condicionales, lo que permite instrucciones como while x < 27: x = x * 2
. En segundo lugar, los contratos pueden llamar a otros contratos, permitiendo potencialmente hacer bucles a través de la recursividad. Esto naturalmente conduce a un problema: ¿pueden los usuarios maliciosos esencialmente apagar a mineros y nodos completos obligándolos a entrar en un bucle infinito? El problema surge debido a un problema en las ciencias de la computación, conocido como el problema de la parada: no hay manera de determinar, en el caso general, si un programa dado se detendrá o no.
Como se describe en la sección de transición de estados, nuestra solución funciona requiriendo que una transacción establezca un número máximo de pasos computacionales que se le permitirá ejecutar, y si la ejecución requiere de más cómputo, se revierte pero las comisiones aún así hay que pagarlas. Los mensajes funcionan del mismo modo. Para mostrar la motivación detrás de nuestra solución, consideremos los siguientes ejemplos:
- Un atacante crea un contrato que ejecuta un bucle infinito, y a continuación envía una transacción que activa ese bucle al minero. El minero procesará la transacción, ejecutará el bucle infinito y esperará a que se quede sin gas. A pesar de que la ejecución se queda sin gas y se detiene a media ejecución, la transacción sigue siendo válida y el minero sigue recibiendo la tarifa del atacante por cada paso computacional.
- Un atacante crea un bucle infinito muy largo con la intención de forzar al minero a mantener la computación durante tanto tiempo que para el momento que la computación termina, habrán surgido varios bloques más y no será posible que el minero incluya la transacción para reclamar la tarifa. Sin embargo, el atacante tendrá que enviar un valor para
STARTGAS
, que limita el número de pasos computacionales que puede realizar la ejecución, así el minero sabrá por adelantado que la computación llevará un número excesivamente grande de pasos. - Un atacante contempla un contrato con código similar a
send(A,contract.storage[A]); contract.storage[A] = 0
, y envía una transacción con el gas suficiente para ejecutar el primer paso pero no el segundo (es decir, hacer un retiro pero no dejar que el saldo se reduzca). El autor del contrato no necesita preocuparse por protegerse contra estos ataques, porque si la ejecución se detiene sin concluir, los cambios se revierten. - Un contrato financiero funciona tomando la mediana de nueve fuentes de datos propietarias para minimizar el riesgo. Un atacante se apodera de una de las fuentes de datos, que está diseñada para ser modificable a través del mecanismo de llamada de dirección variable descrito en la sección sobre DAOs, y lo transforma para que ejecute un bucle infinito, tratando así de forzar que se quede sin gas cualquier intento de retirar fondos del contrato financiero. Sin embargo, el contrato financiero puede establecer un límite de gas en el mensaje para prevenir este problema.
La alternativa a la completitud Turing es la incompletitud Turing, donde JUMP
y JUMPI
no existen y solo se permite que exista una copia de cada contrato en la pila de llamadas en un momento dado. Con este sistema, el sistema de tarifas descrito y las incertidumbres alrededor de la efectividad de nuestra solución podrían ser innecesarias, ya que el coste de ejecutar un contrato tendría el límite superior establecido por su tamaño. Adicionalmente, la incompletitud Turing no es ni siquiera una limitación tan grande; de todos los ejemplos de contrato que hemos concebido internamente, hasta ahora solo uno requiere de un bucle, e incluso ese bucle se podría eliminar haciendo 26 repeticiones de un fragmento de código de una línea. Dadas las serias implicaciones de la completitud Turing y su beneficio limitado, ¿por qué no sencillamente tener un lenguaje Turing-incompleto? En realidad, sin embargo, la incompletitud Turing dista de ser una solución idónea al problema. Para ver por qué, consideremos los siguientes contratos:
C0: llamada(C1); llamada(C1);
C1: llamada(C2); llamada(C2);
C2: llamada(C3); llamada(C3);
...
C49: llamada (C50); llamada(C50);
C50: (ejecutar un paso de un programa y guardar el cambio en el almacenamiento)
Ahora, enviar una transacción a A. Así, en 51 transacciones, tenemos un contrato que ejecutaría 250 pasos computacionales. Los mineros podrían intentar detectar estas bombas lógicas por adelantado manteniendo un valor junto a cada contrato que especifique el número máximo de pasos computacionales que pueden realizar, y calculando esto para contratos que llaman a otros contratos recursivamente, pero eso requeriría que los mineros prohíban contratos que creen otros contratos (ya que la creación y ejecución de los 26 contratos anteriores se podría agrupar fácilmente en un único contrato). Otro punto problemático es que el campo de dirección de un mensaje es una variable, por lo que en general podría ni siquiera ser posible saber a qué otros contratos llamará con antelación un contrato dado. Por lo tanto, en resumen tenemos una conclusión sorprendente: la completidud Turing es sorprendentemente fácil de gestionar, y la falta de completidud Turing es al igual sorprendentemente difícil de gestionar a menos que existan exactamente los mismos controles, pero en ese caso, ¿por qué no dejar que el protocolo sea sin más Turing-completo?
Moneda y emisión monetaria
La red Ethereum incluye su propia moneda incorporada: ether, el cual cumple el doble propósito de proporcionar una capa de liquidez primaria para permitir un intercambio eficiente entre varios tipos de activos digitales y, aún más importante, el proporcionar un mecanismo para pagar tarifas de transacción. Para comodidad y para evitar futuras discusiones (ver el debate actual mBTC/uBTC/satoshi en Bitcoin), las denominaciones se preetiquetarán:
- 1: wei
- 1012: szabo
- 1015: finney
- 1018: ether
Esto se debe tomar como una versión expandida del concepto de "dólares" y "centavos" o "BTC" y "satoshi". En un futuro cercano, esperamos que "ether" se utilice para transacciones ordinarias, "finney" para microtransacciones y "szabo" y "wei" para análisis técnicos relativos a las tarifas e implementación de protocolos; las denominaciones restantes pueden ser útiles más tarde y no deben ser incluidas en los clientes en este punto.
El modelo de emisión será el siguiente:
- El Ether se lanzará en una venta de moneda al precio de 1000-2000 ether por BTC, un mecanismo destinado a financiar la organización Ethereum y pagar por el desarrollo que ha sido utilizado con éxito por otras plataformas como Mastercoin y NXT. Los primeros compradores se beneficiarán de grandes descuentos. Los BTC que se obtengan de la venta se utilizarán en su totalidad para pagar salarios y recompensas a los desarrolladores e invertirá en varios proyectos con ánimo y sin ánimo de lucro en el ecosistema Ethereum y de criptomonedas.
- 0,099 veces de la cantidad total vendida (60 102 216 ETH) se asignará a la organización para compensar a los primeros contribuyentes y pagar los gastos denominados en ETH antes del bloque génesis.
- 0,099 veces de la cantidad total vendida se mantendrá como una reserva a largo plazo.
- 0,26 veces de la cantidad total vendida se asignará a los mineros por año para siempre después de ese punto.
Grupo | en el lanzamiento tras | 1 año | tras 5 años |
---|---|---|---|
Unidades de moneda | 1,198X | 1,458X | 2,498X |
Compradores | 83,5 % | 68,6 % | 40,0 % |
Reserva gastada antes de la venta | 8,26 % | 6,79 % | 3,96 % |
Reserva utilizada posventa | 8,26 % | 6,79 % | 3,96 % |
Mineros | 0 % | 17,8 % | 52,0 % |
Tasa de crecimiento a largo plazo de la oferta (porcentaje)
A pesar de la emisión lineal de moneda, al igual que con Bitcoin a lo largo del tiempo la tasa de crecimiento de la oferta tiende sin embargo a cero
Las dos opciones principales en el modelo anterior son: (1) la existencia y el tamaño de un fondo de dotación financiera y, (2) la existencia de una oferta lineal en crecimiento permanente, a diferencia de una oferta limitada como en Bitcoin. La justificación de un fondo de dotación financiera es la siguiente. Si el fondo de dotación no existiese, y la emisión lineal se redujera a 0,217 veces para proporcionar la misma tasa de inflación, entonces la cantidad total de ether sería un 16,5 % menos, por lo que cada unidad sería un 19,8 % más valiosa. Por lo tanto, en el equilibrio de 19,8 % se compraría más ether en la venta, por lo que cada unidad sería una vez más tan valiosa como antes. La organización también tendría 1,198 veces de BTC, que puede considerarse como dividido en dos porciones: el BTC original, y un 0,198 adicional. Por lo tanto, esta situación es exactamente equivalente a la dotación, pero con una diferencia importante: la organización guarda exclusivamente BTC, y no tiene el incentivo para apoyar el valor de la unidad de ether.
El modelo de crecimiento lineal permanente de la oferta reduce el riesgo de lo que algunos ven como una concentración excesiva de riqueza en Bitcoin, y da a los individuos que viven en el presente y a los que vivan el futuro una oportunidad justa de adquirir unidades de moneda, mientras que al mismo tiempo mantiene un fuerte incentivo para obtener y poseer el ether porque la "tasa de crecimiento de la oferta" como porcentaje sigue tendiendo a cero con el tiempo. También teorizamos que, dado que las monedas siempre se pierden con el tiempo debido a negligencias, muerte, etc, y que la pérdida de monedas pueden modelarse como un porcentaje de la oferta total por año, que la oferta de moneda total en circulación eventualmente se estabilizará en un valor igual a a la emisión anual dividida entre la tasa de pérdida (p. ej., a una tasa de pérdida de 1 %, una vez que el suministro alcance 26 veces, entonces 0,26 veces se minarán y 0,26 veces se perderán cada año, creando un equilibrio).
Nótese que en el futuro, es probable que Ethereum cambie a un modelo de prueba de participación por seguridad, reduciendo el requisito de emisión a una cantidad de entre cero y 0,05 por año. En el caso de que la organización Ethereum pierda la financiación o desaparezca por cualquier otro motivo, dejamos abierto un "contrato social": cualquiera tiene derecho a crear una futura versión candidata de Ethereum, con la única condición de que la cantidad de ether debe ser como máximo igual a 60102216 * (1.198 + 0.26 * n)
donde n
es el número de años posteriores al bloque génesis. Los creadores son libres de hacer una venta inicial de monedas o asignar de otra forma parte o toda la diferencia entre la expansión de oferta basada en prueba de participación (PoS, por sus siglas en inglés) y la expansión de oferta máxima permitida para pagar por el desarrollo. Las actualizaciones candidatas que no cumplan con el contracto social pueden ser justificadamente bifurcadas a versiones que lo cumplan.
Centralización del minado
El algoritmo de minado de Bitcoin funciona haciendo que los mineros calculen SHA256 en versiones ligeramente modificadas del encabezado del bloque millones de veces una y otra vez, hasta que finalmente un nodo encuentre una versión cuyo hash sea menor que el objetivo (actualmente alrededor de 2192). Sin embargo, este algoritmo de minado es vulnerable a dos formas de centralización. En primer lugar, el ecosistema minero ahora está dominado por los ASIC (circuitos integrados de aplicación específica), chips de ordenador diseñados para la tarea y, por lo tanto, miles de veces más eficientes en la tarea específica de minado de Bitcoin. Esto significa que el minado de Bitcoin ya no es una actividad altamente descentralizada e igualitaria, requiriendo millones de dólares de capital en la práctica para poder participar. En segundo lugar, la mayoría de los mineros de Bitcoin no realizan la validación de bloques localmente; en su lugar, dependen de un "pool" (grupo) de minado centralizado que proporciona los encabezados del bloque. Se puede argumentar que este problema es peor: en el momento de escribir estas líneas, los tres principales pools de minería controlan indirectamente aproximadamente el 50 % del poder de procesamiento en la red de Bitcoin, aunque esto lo mitiga el hecho de que los mineros pueden cambiar a otros pools de minado si un pool o coalición intentan un ataque del 51 %.
El propósito actual de Ethereum es utilizar un algoritmo de minado donde los mineros tienen que obtener datos aleatorios del estado, computar aleatoriamente algunas transacciones seleccionadas de los últimos N bloques en la blockchain, y devolver el hash del resultado. Esto tiene dos ventajas importantes. Primero, los contratos de Ethereum pueden incluir cualquier tipo de cómputo, por lo que un ASIC Ethereum sería esencialmente un ASIC de cómputo general, es decir, una CPU mejor. Segundo, la minería requiere acceso a toda la blockchain, lo que obliga a los mineros a almacenar toda la blockchian y ser al menos capaces de verificar cada transacción. Esto elimina la necesidad de pools de minado centralizadas; aunque las pools de minado pueden seguir desempeñando el papel legítimo de equilibrar la aleatoriedad de la distribución de recompensas, esta función puede realizarse igualmente bien por pools entre pares sin ningún control central.
Este modelo no ha sido probado, y puede haber dificultades a lo largo del camino para evitar ciertas optimizaciones inteligentes cuando se utiliza la ejecución del contrato como algoritmo de minado. Sin embargo, una característica notablemente interesante de este algoritmo es que permite a cualquiera "envenenar el pozo", al introducir un gran número de contratos en la blockchain específicamente diseñados para bloquear ciertos ASIC. Existen incentivos económicos para que los fabricantes de ASIC utilicen un truco así para atacarse mutuamente. Por tanto, la solución que estamos desarrollando es en última instancia, una solución adaptativa humana en vez de una solución puramente técnica.
Escalabilidad
Una preocupación común en Ethereum es la cuestión de la escalabilidad. Al igual que Bitcoin, Ethereum sufre del defecto de que cada transacción tiene que ser procesada por cada nodo de la red. Con Bitcoin, el tamaño de la blockchain actual se sitúa en unos 15 GB, creciendo alrededor de 1 MB por hora. Si la red Bitcoin procesara las 2000 transacciones que procesa Visa por segundo, crecería 1 MB cada tres segundos (1 GB por hora, 8 TB por año). Es probable que Ethereum sufra un patrón de crecimiento similar, empeorado por el hecho de que habrá muchas aplicaciones funcionando encima del blockchain Ethereum, en lugar de solo una moneda como es el caso de Bitcoin, pero mitigado por el hecho de que los nodos completos de Ethereum necesitan almacenar sólo el estado en lugar de todo el historial de la blockchain.
El problema con un tamaño tan grande de blockchain es el riesgo de centralización. Si el tamaño del blockchain aumenta hasta, digamos, 100 TB, entonces el escenario más factible sería que solo un pequeño número de grandes empresas ejecutarían nodos completos, y todos los usuarios normales usarían nodos SPV ligeros. En esta situación, surge el problema potencial de que los nodos completos se unieran y acordasen hacer trampas de algún modo rentable (p. ej., cambiando la recompensa por bloque, darse a si mismos BTC). Los nodos ligeros no tendrían forma de detectar esto inmediatamente. Por supuesto, probablemente existiría al menos un nodo completo honesto, y al cabo de unas horas la información sobre el fraude se iría filtrando a través de canales como Reddit, pero llegados a ese punto sería demasiado tarde: correspondería a los usuarios ordinarios organizar un esfuerzo para elaborar una lista negra de dichos bloques, un problema masivo y probablemente no factible de coordinación a una escala similar a la de lograr con éxito un ataque del 51 %. En el caso de Bitcoin, esto es actualmente un problema, pero existe una modificación de blockchain propuesta por Peter Todd que mitigará este problema.
A corto plazo, Ethereum utilizará dos estrategias adicionales para hacer frente a este problema. Primero, dados los algoritmos de minado basados en blockchain, todos y cada uno de los mineros estarán obligados a ser nodos completos, creando un límite inferior en el número de nodos completos. Segundo, y no obstante más importante, incluiremos una raíz del árbol de estado intermedio en el blockchain después de procesar cada transacción. Incluso si la validación del bloque está centralizada, siempre y cuando exista un nodo de verificación honesto, el problema de la centralización se puede eludir a través de un protocolo de verificación. Si un minero publica un bloque inválido, el bloque o bien estará mal formateado, o el estado S[n]
será incorrecto. Como se sabe que S[0]
es correcto, debe haber algún primer estado S[i]
que es incorrecto, donde S[i-1]
es correcto. El nodo de verificación proporcionaría el índice i
, junto con una "prueba de nulidad" consistente en el subconjunto de nodos de árbol Patricia que necesitan procesar APPLY(S[i-1], X[i]) -> S[i]
. Los nodos podrían usar esos nodos Patricia para ejecutar esa parte del cómputo, y ver que el S[i]
generado no coincide con el S[i]
proporcionado.
Otro ataque más sofisticado consistiría en que los mineros maliciosos publicasen bloques incompletos, por lo que ni siquiera existiría la información completa para determinar si los bloques son válidos o no. La solución a esto es un protocolos desafío-respuesta: los nodos de verificación emiten "desafíos" en forma de índices de transacción objetivo, y al recibir un nodo, un nodo ligero trata el bloque como no fiable hasta que otro nodo, ya sea minero u otro verificador, proporcione un subconjunto de nodos Patricia como prueba de validez.
Conclusión
El protocolo Ethereum fue concebido originalmente como una versión mejorada de una criptomoneda, proporcionando características avanzadas como fideicomiso sobre la blockchain, límites de retiro, contratos financieros, mercados de apuestas y similares a través de un lenguaje de programación de propósito muy general. El protocolo Ethereum no "implementaría" ninguna de las aplicaciones directamente, pero la existencia de un lenguaje de programación Turing completo significa que teóricamente pueden crearse contratos arbitrarios para cualquier tipo de transacción o aplicación. Lo más interesante de Ethereum, sin embargo, es que el protocolo Ethereum va mucho más allá de ser solo una moneda. Los protocolos en torno al almacenamiento de archivos descentralizado, la computación descentralizada y los mercados de predicción descentralizados, entre docenas de otros conceptos de este tipo, tienen el potencial de aumentar sustancialmente la eficiencia de la industria computacional y aportar un impulso masivo a otros protocolos peer-to-peer al añadir por primera vez una capa económica. Por último, también hay un considerable conjunto de aplicaciones que no guardan relación alguna con el dinero.
El concepto de una función de transición de estado arbitraria implementada por el protocolo Ethereum proporciona una plataforma con un potencial único; en lugar de ser un protocolo de un solo propósito cerrado destinado a una serie específica de aplicaciones en el ámbito del almacenamiento de datos, apuestas o finanzas, Ethereum está abierto por diseño y creemos que es extremadamente adecuado para servir como una capa fundacional para un gran número de protocolos financieros y no financieros en los años venideros.
Notas y lecturas adicionales
Notas
- Un lector sofisticado puede haber notado que una dirección de Bitcoin es el hash de la clave pública de la curva elíptica, y no la clave pública en sí. Sin embargo, es perféctamente legítimo en terminología criptográfica el referirse al hash de la clave pública como la clave pública en sí. Esto es porque la la criptografía de Bitcoin se puede considerar un algoritmo personalizado de firma digital, donde la clave pública consiste en el hash de la clave pública CCE, la firma consiste en la clave pública CCE concatenada con la firma CCE, y el algoritmo de verificación involucra verificar la clave pública ECC en la firma contra el hash de la clave pública ECC proporcionada como clave pública y después verificar la firma ECC contra la clave pública ECC.
- Técnicamente, la mediana de los 11 bloques anteriores.
- El protocolo Ethereum debe ser tan simple como práctico, pero puede que sea necesario tener un nivel bastante alto de complejidad, por ejemplo para escalar, para internalizar los costes de almacenamiento, ancho de banda y E/S, para seguridad, privacidad, transparencia, etc. Donde sea necesaria la complejidad, la documentación debe ser tan clara, concisa y actualizada como sea posible. para que alguien completamente sin conocimiento de Ethereum pueda aprender y convertirse en un experto.
- Consulta el documento amarillo de la máquina virtual Ethereum (que es útil como especificación y referencia para construir un cliente Ethereum desde cero), y también hay muchos temas en la wiki de Ethereum , tales como desarrollo de sharding, desarrollo del núcleo, desarrollo de dapp, investigación, Casper, I+D y protocolos de red. Para investigación y posible implementación en el futuro está ethresearch.ch.
- Otra forma de expresar esto es con abstracción. La última hoja de ruta está planeando la ejecución abstracta, permitiendo que los motores de ejecución no tengan que seguir necesariamente una especificación canónica, sino que por ejemplo podría ser diseñados para una aplicación específica, así como para un shard. (Esta heterogeneidad de los motores de ejecución no está explícitamente señalada en la hoja de ruta. También está el sharding heterógeno, que conceptualizó Vlad Zamfir.)
- Internamente, tanto 2 como "CHARLIE" son números, siendo este último representado en base 256 big-endian. Los números pueden ser como mínimo 0 y como máximo 2256-1.
Lecturas adicionales
- Valor intrínseco
- Propiedad inteligente
- Contratos inteligentes
- B-money
- Pruebas de trabajo reutilizables
- Títulos de propiedad seguros con autoridad del propietario
- Informe oficial de Bitcoin
- Namecoin
- Triángulo de Zooko
- Informe oficial de monedas coloreadas
- Informe oficial de Mastercoin
- Corporaciones autónomas descentralizadas, Bitcoin Magazine
- Verificación de pago simplificada
- Árboles de Merkle
- Árboles de Patricia
- GHOST
- StorJ y agentes autónomos, Jeff Garzik
- Mike Hearn, sobre propiedad inteligente en el Turing Festival
- Ethereum RLP
- Árboles de Merkle y Patricia en Ethereum
- Peter Todd sobre los árboles Merkle de suma
Para consultar la historia del libro blanco, ver https://github.com/ethereum/wiki/blob/old-before-deleting-all-files-go-to-wiki-wiki-instead/old-whitepaper-for-historical-reference.md
Ethereum, al igual que muchos proyectos de software de código abierto impulsados por la comunidad, ha evolucionado desde su concepción inicial. Para aprender sobre los últimos desarrollos de Ethereum, y cómo se hacen los cambios en el protocolo, recomendamos esta guía.