Ethereum: de historia a labs

Artículo 32 de 48

67%

completado al llegar aquí

Sistemas distribuidosNota de investigación13 min de lectura

Shapella: retirar stake sin romper el consenso

Cómo Shapella habilitó retiros en abril de 2023: credenciales 0x00 y 0x01, barrido automático, objetos Withdrawal en el payload y los cambios de Pectra.

Ruta Ethereum: 0/48

Supón que un miembro de tu equipo depositó 32 ETH en el contrato de depósito de la Beacon Chain a finales de 2020. Durante más de dos años ese ETH generó recompensas, pero no había ninguna operación del protocolo que lo devolviera a una cuenta normal de Ethereum. ¿Cómo se diseña la salida de un sistema de consenso sin abrir una puerta para que alguien drene el stake ajeno o desestabilice el conjunto de validadores?

La respuesta llegó con Shapella, la combinación de Shanghai (capa de ejecución) y Capella (capa de consenso). Se activó en la época 194048, el 12 de abril de 2023, y permitió por primera vez retiros parciales y totales de validadores.

Brújula de lectura

Actor, evidencia y estado

Antes de avanzar, ubica quién actúa, qué prueba queda y qué parte del sistema cambia.

Actor

Proponente de bloque

Calcula los retiros esperados y los incluye en el payload; el validador que cobra no firma nada.

Evidencia

withdrawals_root

La cabecera del bloque de ejecución compromete la lista de retiros con una raíz de trie.

Estado

Dos balances

Baja el balance del validador en consenso y sube el de una dirección en ejecución.

Preguntas guía

  • ¿Por qué un retiro no es una transacción y por qué no paga gas?
  • ¿Qué credencial necesita un validador para recibir fondos y quién la controla?
  • ¿Cómo decide el protocolo qué validadores cobran en cada bloque?
  • ¿Qué cambió en Pectra para salidas, compounding y retiros parciales?

Conexiones dentro de la serie

Historia: por qué el stake estuvo bloqueado hasta 2023

La Beacon Chain arrancó en diciembre de 2020 como una cadena de consenso separada. Su contrato de depósito, en la cadena de ejecución, aceptaba ETH en una sola dirección: hacia el consenso. No existía la vía de vuelta porque las dos cadenas no compartían bloques. Eso cambió con The Merge en septiembre de 2022, cuando cada bloque de consenso pasó a llevar un execution payload. Desde ese momento hubo un lugar natural para escribir "paga X a esta dirección".

Shapella llegó siete meses después. En la capa de ejecución, Shanghai incluyó EIP-3651 (COINBASE caliente), EIP-3855 (PUSH0), EIP-3860 (límite de initcode), EIP-4895 (retiros) y EIP-6049 (aviso de deprecación de SELFDESTRUCT, sin cambio de comportamiento). En consenso, Capella añadió retiros parciales y totales, el mensaje BLSToExecutionChange y nuevos acumuladores históricos.

Estado de credenciales: 0x00, 0x01 y 0x02

Cada validador guarda 32 bytes de withdrawal_credentials. El primer byte dice de qué tipo son. Con prefijo 0x00, los 31 bytes restantes son parte del hash de una clave BLS de retiro: no hay dirección de ejecución a la que pagar. Con prefijo 0x01, los últimos 20 bytes son una dirección normal de Ethereum. Solo los validadores 0x01 (y, desde Pectra, 0x02) pueden recibir retiros.

Para pasar de 0x00 a 0x01, el titular firma un BLSToExecutionChange con la clave BLS de retiro. El protocolo comprueba que el hash de esa clave coincide con la credencial guardada, verifica la firma y reescribe la credencial con la dirección elegida:

python
# consensus-specs, capella/beacon-chain.md (extracto de process_bls_to_execution_change)
assert validator.withdrawal_credentials[:1] == BLS_WITHDRAWAL_PREFIX
assert validator.withdrawal_credentials[1:] == sha256(address_change.from_bls_pubkey)[1:]
...
validator.withdrawal_credentials = Bytes32(
    ETH1_ADDRESS_WITHDRAWAL_PREFIX + b"\x00" * 11 + address_change.to_execution_address
)

El cambio es de una sola vía. Una vez la credencial es 0x01, el assert del prefijo 0x00 ya no se cumple y no hay otra operación que la reescriba. ethereum.org lo dice sin rodeos: cada validador puede tener una única dirección de retiro, asignada una vez, y no se puede cambiar.

Pectra (mayo de 2025) añadió el prefijo 0x02, de compounding. Un validador 0x02 acumula recompensas en su balance efectivo hasta 2048 ETH en lugar de 32. El barrido automático solo le retira lo que supera 2048 ETH; para sacar menos tiene que pedir un retiro parcial desde la capa de ejecución, lo que sí cuesta gas.

Traza de ejecución de un retiro: del barrido al saldo

El diseño de EIP-4895 es de tipo push: el protocolo empuja los fondos hacia la dirección, en lugar de esperar a que el usuario los reclame. En cada bloque, el consenso recorre validadores en orden empezando por next_withdrawal_validator_index, revisa como máximo 16384 y produce como máximo 16 retiros.

Figura 1

Del prefijo 0x00 al saldo en ejecución

Fuentes:

[3]
Del prefijo 0x00 al saldo en ejecución
Cómo leer esta figura

Diagrama en tres columnas. Columna uno, capa de consenso: una credencial con prefijo 0x00 ligada a una clave BLS de retiro pasa, mediante un BLSToExecutionChange firmado, a una credencial 0x01 con dirección de ejecución; una nota indica que el cambio es único. Columna dos, barrido en cada bloque: empieza en next_withdrawal_validator_index, revisa hasta 16384 validadores en orden, primero pregunta si procede una salida total porque el validador es 0x01 y alcanzó su withdrawable_epoch, y si no, si tiene excedente sobre 32 ETH, en cuyo caso sale solo el excedente. Columna tres, capa de ejecución: hasta 16 objetos Withdrawal con index, validator_index, address y amount en Gwei se aplican después de las transacciones del bloque y suman amount al saldo de address sin gas y sin ejecutar código.

Visual original de TrautsLab. Reglas de Capella: la credencial se actualiza una vez, el barrido elige retiros totales o de excedente y el payload los aplica después de las transacciones.

El proponente no elige a quién pagar. process_withdrawals recalcula la lista esperada y exige que coincida exactamente con la del payload; un bloque con otra lista es inválido. En ejecución, cada Withdrawal lleva cuatro campos: un índice global creciente, el índice del validador, la dirección y la cantidad en Gwei. La cabecera añade withdrawals_root, una raíz de trie sobre esa lista.

Texto
withdrawal = RLP([index, validator_index, address, amount])   # amount en Gwei
execution_payload_rlp = RLP([header, transactions, [], withdrawals])

Los retiros se procesan después de todas las transacciones del bloque. Cada uno suma amount (convertido de Gwei a wei) al saldo de la dirección. Es un cambio de balance incondicional: no ejecuta código del destinatario, no puede fallar y no consume gas. Por eso un contrato que recibe retiros no ve una llamada a su receive(): su saldo simplemente aparece más alto.

Ciclo de vida del validador: salir, esperar y cobrar

Un retiro total requiere salir antes. La salida voluntaria es un mensaje firmado con la clave de firma del validador. El protocolo exige que el validador lleve activo al menos SHARD_COMMITTEE_PERIOD = 256 épocas y que no tenga retiros parciales pendientes. Después calcula una época de salida respetando una cola: desde Electra, esa cola se mide en ETH por época, con un tope de 256 ETH para activaciones y salidas en la configuración de mainnet.

Línea de tiempo

De validador activo a ETH en una dirección

Secuencia para un validador 0x01 que sale voluntariamente; la duración de la cola depende de cuánta gente salga a la vez.
  1. época E

    Salida voluntaria firmada

    Firmada con la clave del validador o, desde Pectra, pedida desde la dirección de retiro (EIP-7002).

  2. E + cola

    Época de salida

    Se asigna según el churn disponible; hasta entonces el validador sigue con sus deberes.

  3. salida + 256 épocas

    Retraso de retirabilidad

    MIN_VALIDATOR_WITHDRAWABILITY_DELAY: unas 27 horas en las que aún puede ser slasheado por faltas anteriores.

  4. siguiente pasada

    Barrido

    Cuando el barrido llega a su índice, todo el saldo pasa a la dirección de retiro.

Pectra también cambió quién puede iniciar la salida. Antes, solo la clave de firma del validador podía hacerlo. EIP-7002 permite que la dirección de retiro 0x01 dispare salidas y retiros mediante una solicitud en la capa de ejecución, que el consenso procesa después. El anuncio de Pectra lo presenta como una reducción de confianza en esquemas delegados: el dueño de los fondos ya no depende del operador para salir.

Riesgo operativo: la dirección de retiro es para siempre

El error más caro de este capítulo no es técnico sino de custodia. Si la dirección 0x01 pertenece a un exchange que cierra la cuenta, a un multisig mal configurado o a una clave perdida, el saldo llegará allí de todos modos, sin posibilidad de corrección. La regla de una sola escritura protege contra el robo de la clave BLS de retiro después del cambio, pero no protege contra tu propio error al elegir la dirección.

Comparación

Dos formas de que el saldo llegue a ejecución

Ambas usan el mismo barrido; cambia qué parte del balance sale.

Retiro parcial automático

Validador 0x01 activo con saldo superior a 32 ETH.

Sale
solo el excedente
Acción del titular
ninguna
  • el validador sigue activo
  • llega cada vez que el barrido pasa por su índice

Retiro total

Validador que salió y alcanzó su withdrawable_epoch.

Sale
todo el saldo
Acción del titular
solicitar la salida antes
  • si fue slasheado, espera al menos 8192 épocas
  • si tiene 0x00, el saldo espera hasta que se actualice la credencial

Para auditoría y contabilidad, recuerda que los retiros no aparecen como transacciones ni emiten logs. Un indexador que solo mira transacciones y eventos no verá el ETH que entra en la dirección de un validador. Hay que leer el campo withdrawals del bloque.

Laboratorio mínimo: leer los retiros de un bloque

Con cualquier endpoint JSON-RPC de mainnet o de una testnet puedes ver la lista. El esquema de execution-apis define los cuatro campos y limita la lista a 16 elementos por bloque.

Bash
# Requiere un RPC propio en $RPC_URL y jq instalado.
curl -s -X POST -H 'Content-Type: application/json' \
  --data '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["latest",false],"id":1}' \
  "$RPC_URL" | jq '.result.withdrawals | length, .[0]'

La validación observable es sencilla: la longitud nunca supera 16, amount está en Gwei (en hexadecimal) y la suma de esas cantidades no aparece como transferencia en ninguna transacción del bloque. Si consultas el saldo de address en el bloque anterior y en este, la diferencia incluye el retiro.

Quédate con esta frase: un retiro es una operación del sistema, no una transacción del usuario. Lo decide el consenso, lo aplica la ejecución al final del bloque y llega siempre a la dirección fijada en la credencial.

Referencias

Bibliografía académica

Formato IEEENumerado para ingeniería, sistemas y protocolos.
  1. [1]

    Ethereum Foundation, "Withdrawals are coming: Shapella mainnet announcement," blog.ethereum.org, Mar. 28, 2023.

    official announcementID: ETH-SHAPELLA-2023Abrir fuente (abre en otra pestaña)

    Época de activación, EIPs de Shanghai y cambios de Capella.

  2. [2]

    A. Stokes and D. Ryan, "EIP-4895: Beacon chain push withdrawals as operations," 2022.

    Objeto Withdrawal, withdrawals_root y procesamiento incondicional tras las transacciones.

  3. [3]

    Ethereum consensus-specs, "Capella -- The Beacon Chain," specs/capella/beacon-chain.md.

    Withdrawal, BLSToExecutionChange, MAX_WITHDRAWALS_PER_PAYLOAD y el barrido de validadores.

  4. [4]

    ethereum.org, "Staking withdrawals."

    official docsID: ETH-WITHDRAWALS-DOCSAbrir fuente (abre en otra pestaña)

    Tipos de credencial, barrido automático, compounding y preparación de stakers.

  5. [5]

    Ethereum consensus-specs, "Electra -- The Beacon Chain," specs/electra/beacon-chain.md.

    COMPOUNDING_WITHDRAWAL_PREFIX, MAX_EFFECTIVE_BALANCE_ELECTRA y churn de salida medido en ETH.

  6. [6]

    "EIP-7002: Execution layer triggerable withdrawals," Ethereum Improvement Proposals.

    Solicitudes de salida y retiro desde credenciales 0x01 en la capa de ejecución.

  7. [7]

    Ethereum Foundation, "Pectra mainnet announcement," blog.ethereum.org, Apr. 23, 2025.

    official announcementID: ETH-PECTRA-2025Abrir fuente (abre en otra pestaña)

    Activación en la época 364032 (7 de mayo de 2025), EIP-7251 y EIP-7002.

  8. [8]

    Ethereum execution-apis, "Withdrawal schema," src/schemas/withdrawal.yaml.

    specID: EXEC-APIS-WITHDRAWALAbrir fuente (abre en otra pestaña)

    Campos index, validatorIndex, address y amount; máximo 16 retiros por bloque.

Fuentes primarias, papers seminales y especificaciones técnicas citadas en esta investigación.

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.

Sigue leyendo

Ideas conectadas con este artículo

Una ruta corta para continuar sin abrir veinte pestañas y perder el hilo.

Los comentarios se cargan al final de la lectura para no meter peso antes de tiempo.