Ethereum: de historia a labs
Artículo 3 de 48
6%
completado al llegar aquí
Sistemas distribuidosNota de investigación13 min de lectura
Frontier, Homestead y The DAO: la red aprendió con golpes
De Frontier a Spurious Dragon: qué cambió Homestead, cómo se drenó The DAO, qué hizo el fork del bloque 1,920,000 y por qué nació EIP-155.
Ruta Ethereum: 0/48
Prerequisitos recomendados
Si alguno de estos conceptos todavía está medio nebuloso, empieza por aquí. Te ahorra tropiezos y un par de cejas fruncidas.
El 17 de junio de 2016, la Ethereum Foundation publicó una alerta: un atacante estaba drenando el ether de The DAO, un contrato de inversión colectiva, hacia un contrato hijo. El protocolo funcionaba bien; el fallo estaba en el contrato. Aun así, la respuesta terminó en un hard fork y en dos cadenas que siguen existiendo hoy. Este capítulo explica cómo se llegó ahí.
Antes hay que ver la red que recibió el golpe. El registro oficial de forks ubica cada paso con fecha y bloque, y es la fuente de las alturas que aparecen aquí. [1]
Línea de tiempo
Los primeros dieciséis meses de la red principal
30 jul. 2015 · bloque 0
Frontier
Génesis. Red funcional pero mínima, pensada para desarrolladores, con un límite de 5,000 de gas por bloque.
7 sep. 2015 · bloque 200,000
Frontier thawing
Se levanta el límite de gas por bloque; ya caben transacciones normales.
14 mar. 2016 · bloque 1,150,000
Homestead
EIP-2, DELEGATECALL y compatibilidad futura de red.
20 jul. 2016 · bloque 1,920,000
DAO fork
Cambio de estado irregular que mueve los fondos de The DAO a un contrato de reembolso.
18 oct. 2016 · bloque 2,463,000
Tangerine Whistle
Primera respuesta a los ataques de denegación de servicio: opcodes de E/S más caros.
22 nov. 2016 · bloque 2,675,000
Spurious Dragon
Protección contra replay, limpieza de cuentas vacías y límite al tamaño del código.
Brújula de lectura
Actor, evidencia y estado
Actor
Operadores de nodosCada operador decidió si instalaba un cliente que aplicaba el fork o uno que lo rechazaba.
Evidencia
EIP-779Especifica la lista de cuentas, el bloque de activación y el contrato destino del cambio.
Estado
Saldos de la lista LSolo cambiaron saldos de cuentas concretas; opcodes y formatos quedaron iguales.
Preguntas guía
- ¿Qué cambió Homestead en la creación de contratos y en las firmas de transacciones?
- ¿Por qué un contrato que envía ether antes de actualizar su contabilidad puede ser vaciado?
- ¿En qué se diferencia el DAO fork de un fork que cambia reglas del protocolo?
- Después de un fork contencioso, ¿por qué una transacción firmada para una cadena puede ejecutarse en la otra?
Conexiones dentro de la serie
- Antes: Antes de Ethereum: Bitcoin, scripts y la máquina mundial explica el modelo de cuentas y gas que aquí se pone a prueba.
- Después: Metropolis a Istanbul: Ethereum madura antes del Merge sigue con los forks de 2017 a 2020.
- Profundización: Reentrancy: la llamada externa que muerde de vuelta desarrolla el patrón de ataque con un lab; Access control: owner, roles, multisig y timelocks trata cómo limitar el daño de un contrato con fallas.
Historia de Frontier y Homestead: una red para desarrolladores
Frontier arrancó el 30 de julio de 2015. ethereum.org la describe como una implementación funcional pero mínima, pensada para usuarios técnicos. Durante las primeras semanas cada bloque tenía un límite de 5,000 de gas, menos que los 21,000 que cuesta una transferencia simple: los mineros podían arrancar, pero nadie podía mover ether todavía. El fork "Frontier thawing" del bloque 200,000 levantó ese límite.
Homestead se activó en el bloque 1,150,000, el 14 de marzo de 2016. Su especificación agrupa tres propuestas: EIP-2, EIP-7 y EIP-8. [2]
EIP-2 es la que más afecta a un desarrollador. Crear un contrato con una transacción pasa a costar 53,000 de gas de base en lugar de 21,000. Si la creación no tiene gas suficiente para guardar el código, falla por completo en lugar de dejar un contrato vacío. Y las firmas con un valor s mayor que la mitad del orden de la curva secp256k1 pasan a ser inválidas, lo que elimina la maleabilidad: antes cualquiera podía invertir s y v y obtener otra firma válida de la misma transacción sin conocer la clave. [3]
EIP-7 añadió el opcode DELEGATECALL: ejecutar el código de otro contrato en el contexto propio (el mismo storage), conservando el emisor y el valor de la llamada original. Es la pieza sobre la que, años después, se construyeron los contratos actualizables mediante proxy. [10]
Traza de ejecución del ataque: llamar antes de actualizar
The DAO custodiaba ether de sus participantes y les permitía "dividirse" (split): salir hacia un contrato hijo, un DAO nuevo, con sus fondos. La alerta de la fundación describe el fallo como una vulnerabilidad de llamada recursiva en la función de división. El atacante hacía que el contrato le enviara ether y, antes de que el contrato registrara el retiro, volvía a pedir. [4]
El patrón se entiende mejor con un contrato mínimo. Este código no es el de The DAO; es una versión reducida del mismo error:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
/// Ilustrativo y vulnerable. NO es el código de The DAO: reproduce el patrón
/// "enviar ether antes de actualizar el saldo".
contract VulnerableVault {
mapping(address => uint256) public balances;
function deposit() external payable {
balances[msg.sender] += msg.value;
}
function withdraw() external {
uint256 amount = balances[msg.sender];
(bool ok, ) = msg.sender.call{value: amount}("");
require(ok, "transfer failed");
// Demasiado tarde: durante la llamada anterior el receptor pudo
// invocar withdraw() otra vez y leer el mismo saldo.
balances[msg.sender] = 0;
}
}La traza es esta. El atacante deposita desde un contrato propio y llama a withdraw. La bóveda envía ether, y eso ejecuta el código del atacante, que vuelve a llamar a withdraw. Como el saldo todavía no se puso a cero, la bóveda paga otra vez. El ciclo se repite hasta agotar el gas o los fondos. La corrección es mover balances[msg.sender] = 0 antes de la llamada externa.
En The DAO había un detalle que dio margen: el ether drenado quedó en un DAO hijo, y la alerta explicaba que el atacante no podría retirarlo durante al menos unos 27 días, el período de creación del hijo. Ese plazo abrió el debate sobre qué hacer.
Invariante rota: un cambio de estado irregular en el bloque 1,920,000
La invariante de la que hablaba el capítulo anterior es que todos los nodos aplican las mismas reglas a las mismas transacciones. El DAO fork no cambió ninguna regla. Según su especificación, opcodes, formato de transacciones y estructura de bloques quedaron iguales. Lo que hizo fue un cambio de estado irregular: una modificación de saldos que no proviene de ninguna transacción. [5]
La mecánica es precisa. En el bloque 1,880,000 se fijó una lista L de cuentas: The DAO, su cuenta extraBalance y todos los DAO hijos con las suyas. Al comienzo del bloque 1,920,000, todo el ether de esas cuentas se transfirió a un contrato de reembolso, WithdrawDAO, en 0xbf4ed7b27f1d666546e30d74d50d173d20bca754. Ese contrato tiene una sola función útil: withdraw, que devuelve 1 ETH por cada 100 tokens DAO.
El DAO fork: una historia común y dos estados distintos
Fuentes:
[5]Cómo leer esta figura
Línea de tiempo horizontal de bloques con una marca vertical en el bloque 1,920,000. A la izquierda, la caja historia común hasta el bloque 1,919,999. De ella salen dos flechas: una verde hacia la caja cadena con el fork, ETH, donde un cambio de estado irregular mueve el ether de las cuentas de la lista L a WithdrawDAO; y una ocre hacia la caja cadena sin el fork, ETC, con las mismas reglas y ningún saldo movido. Debajo, una nota explica que la misma clave y el mismo formato de transacción en ambas cadenas permiten que una firma válida en una también sea válida en la otra, lo que se llama replay. A la derecha, una caja azul: EIP-155, noviembre de 2016, la firma incluye CHAIN_ID.
La decisión no la tomó un administrador. Los clientes publicaron versiones con el fork activado o desactivado, y cada operador eligió. ethereum.org registra que la opción se votó con transacciones en una plataforma abierta a cualquier poseedor de ETH y superó el 85 % de los votos. Algunos mineros rechazaron el fork con el argumento de que el fallo no estaba en el protocolo, y esa cadena siguió como Ethereum Classic.
El día del fork, la fundación informó que el bloque 1,920,000 movió unos 12 millones de ETH desde los contratos del atacante y de un grupo de rescate al contrato de reembolso. [6]
Riesgo operativo: dos cadenas, una misma firma
Ese mismo anuncio advertía a quien siguiera la cadena sin fork que tuviera cuidado con los ataques de replay. Ambas cadenas compartían claves, direcciones y formato de transacción. Una transferencia firmada para una red era válida en la otra, y cualquiera podía retransmitirla.
La solución llegó con Spurious Dragon, en el bloque 2,675,000. Su especificación incluye EIP-155, EIP-160, EIP-161 y EIP-170. [7] EIP-155 hace que la firma cubra también un identificador de cadena (CHAIN_ID, que vale 1 en la red principal). Una transacción firmada así solo es válida en la cadena para la que se firmó. [8]
Entre el DAO fork y Spurious Dragon hubo otro incidente: ataques de denegación de servicio en septiembre y octubre de 2016 que abusaban de opcodes demasiado baratos para el trabajo que imponían a los nodos. Tangerine Whistle, en el bloque 2,463,000, subió esos precios con EIP-150: SLOAD pasó de 50 a 200 de gas, BALANCE de 20 a 400 y CALL y EXTCODESIZE a 700. También introdujo la regla de "todo menos 1/64": una llamada solo puede reenviar como máximo 63/64 del gas que queda. [9]
La lección operativa para un equipo de hoy tiene tres partes. Un contrato con fondos ajenos es un sistema de producción: la regla de "actualizar estado antes de llamar afuera" no es estilo, es seguridad. Un hard fork es una decisión de cada operador de nodo, y tu infraestructura debe saber qué versión corre. Y cualquier sistema que firme transacciones debe fijar el chainId correcto; las librerías actuales lo hacen por defecto, pero conviene verificarlo en las pruebas.
Bibliografía académica
- [1]
ethereum.org, "Timeline of all Ethereum forks (2014 to present)."
Fechas y bloques de Frontier, Homestead, DAO fork, Tangerine Whistle y Spurious Dragon.
- [2]
A. Beregszaszi, "EIP-606: Hardfork Meta: Homestead," Ethereum Improvement Proposals, no. 606, Apr. 2017.
Bloque de activación 1,150,000 y lista de EIPs incluidos en Homestead.
- [3]
V. Buterin, "EIP-2: Homestead Hard-fork Changes," Ethereum Improvement Proposals, no. 2, Nov. 2015.
Costo de creación de contratos, fallo atómico de creación y restricción del valor s en firmas.
- [4]
V. Buterin, "CRITICAL UPDATE Re: DAO Vulnerability," Ethereum Foundation Blog, Jun. 17, 2016.
Descripción contemporánea del ataque recursivo y del plazo de 27 días del DAO hijo.
- [5]
C. Detrio, "EIP-779: Hardfork Meta: DAO Fork," Ethereum Improvement Proposals, no. 779, Nov. 2017.
Especificación del cambio de estado irregular: lista L, bloque 1,920,000 y contrato WithdrawDAO.
- [6]
V. Buterin, "Hard Fork Completed," Ethereum Foundation Blog, Jul. 20, 2016.
Confirmación del fork, ETH movido a WithdrawDAO y advertencia sobre replay en la cadena sin fork.
- [7]
A. Beregszaszi, "EIP-607: Hardfork Meta: Spurious Dragon," Ethereum Improvement Proposals, no. 607, Apr. 2017.
Bloque 2,675,000 y lista de EIPs de Spurious Dragon.
- [8]
V. Buterin, "EIP-155: Simple replay attack protection," Ethereum Improvement Proposals, no. 155, Oct. 2016.
Inclusión de CHAIN_ID en el hash firmado de la transacción.
- [9]
V. Buterin, "EIP-150: Gas cost changes for IO-heavy operations," Ethereum Improvement Proposals, no. 150, Sep. 2016.
Nuevos costos de opcodes de E/S y regla de 63/64 del gas en llamadas.
- [10]
V. Buterin, "EIP-7: DELEGATECALL," Ethereum Improvement Proposals, no. 7, Nov. 2015.
Opcode 0xf4: como CALLCODE pero propagando emisor y valor de la llamada padre.
Rutas vecinas
Si este tema te abrió hambre, sigue por aquí.
Series y labs que comparten área o dependen de esta ruta. Pocas opciones, para no convertir la curiosidad en menú infinito.
Series relacionadas
HotStuff: de cero a estado del arte
Ruta progresiva para entender consenso BFT moderno: quórums, sincronía parcial, locks, taxonomía one/two/three-chain, QC/highQC, multipipeline, view-change, responsiveness, AggQC, Fast-HotStuff, sync y frontera DAG-BFT.
Substrate: del runtime al consenso propio
Serie de 20 capítulos, de neófito a experto, sobre Substrate (Polkadot SDK): runtime en Wasm, FRAME, extrinsics, estado, pesos, actualizaciones sin fork, Aura, BABE, GRANDPA, sincronización, parachains, XCM, Sassafras, BEEFY y cómo conectar un consenso BFT propio a un nodo.
Ruta práctica: activos digitales en la operación
Nueve módulos, de menor a mayor dependencia, para decidir cómo usar custodia, wallets, llaves, firmas multifirma y MPC, AML/KYT y stablecoins con Fireblocks, BitGo, Kaleido, Circle y Tether.
Labs para convertir lectura en práctica
Prueba de trabajo y reajuste de dificultad
Laboratorio determinista para medir el costo de la prueba de trabajo y ver cómo el reajuste por altura de bloque estabiliza el tiempo entre bloques.
Consensus benchmark
Banco reproducible para comparar consenso BFT y documentar los trade-offs de HotStuff-2.
Ethereum local: Anvil, wallet y primera transacción
Laboratorio base para levantar una red local, crear cuentas, firmar transacciones y observar receipts sin gastar ETH real.
RPC y Cast: leer Ethereum con lupa
Ejercicios con JSON-RPC y Cast para consultar bloques, nonces, gas, receipts, logs y errores reproducibles.
Sigue leyendo
Ideas conectadas con este artículo
Una ruta corta para continuar sin abrir veinte pestañas y perder el hilo.
Metropolis a Istanbul: Ethereum madura antes del Merge
Lectura histórica de Byzantium, Constantinople e Istanbul como preparación técnica para una red más segura y escalable.
Antes de Ethereum: Bitcoin, scripts y la máquina mundial
Historia inicial de Ethereum: qué problema vio el whitepaper, por qué los contratos generales importaban y qué cambió frente a Bitcoin.
Por qué Ethereum necesitaba The Merge
Motivos técnicos, económicos y ambientales detrás de la transición de proof-of-work a proof-of-stake.
Ethereum: mapa de lectura antes de tocar Solidity
Ruta completa para aprender Ethereum desde historia y arquitectura hasta EVM, proof-of-stake, L2, seguridad, DeFi y labs reproducibles.