validator-exit-bus
Autobús de Salida de Validadores: Explicación Detallada
El Autobús de Salida de Validadores Oracle es un mecanismo dentro del protocolo Lido responsable de solicitar la salida de validadores para cubrir los retiros de los usuarios cuando el protocolo necesita fondos adicionales. Este documento describe paso a paso el proceso para calcular y ejecutar las salidas de los validadores.
Pasos para el Cálculo del Informe
- Calcular la cantidad de retiros a cubrir con ether.
- Calcular la predicción de recompensas en ether por época.
- Calcular la época de retiro para el próximo validador elegible para salir y cubrir las solicitudes de retiro si es necesario.
- Preparar la cola de orden de salida de validadores.
- Recorrer la cola hasta que los saldos de los validadores salientes cubran todas las solicitudes de retiro (considerando el saldo final predicho de cada validador).
Algoritmo para el Próximo Validador en Salir
El algoritmo para la salida de validadores se basa en el algoritmo descrito en el foro de investigación.
El algoritmo supone corregir el número futuro de validadores para cada Operador de Nodo. Supongamos que los validadores y depósitos en proceso de uno de los Operadores de Nodo se representan de la siguiente manera, donde los validadores están ordenados por sus índices:
El algoritmo asume que los validadores más antiguos salen primero. Por lo tanto, los validadores previamente solicitados se pueden separar para salir sabiendo el índice del último solicitado.
Cabe destacar que cada validador tiene un estado. Algunos validadores pueden estar castigados o haber salido sin una solicitud del protocolo:
Entre todos los validadores, los proyectados son el punto de interés. Incluyen todos los validadores activos y depósitos en proceso, pero excluyen los validadores cuyo exit_epoch != FAR_FUTURE_EPOCH
y aquellos validadores que fueron solicitados para salir.
Unas horas después, podría verse de la siguiente manera:
Nota que el algoritmo descrito está buscando un validador para salir solo entre aquellos que pueden salir, mientras usa el número proyectado de validadores, que incluye validadores aún no existentes. Son solo ponderaciones, por lo que no hay malentendidos aquí.
Secuencia de Predicados para el Orden de Salida
- Validador cuyo operador tenga el menor número de validadores retrasados.
- Validador cuyo operador tenga el mayor número de validadores objetivo para salir.
- Validador cuyo operador tenga el mayor peso de participación.
- Validador cuyo operador tenga el mayor número de validadores.
- Validador con el índice más bajo.
Obtener Información para Preparar la Cola Ordenada
Para preparar una cola de validadores para salir, se involucran las siguientes acciones y consideraciones:
- El número máximo de validadores que pueden ser solicitados para salir en un informe.
- Porcentaje de penetración en la red del operador: solo si la participación del operador es mayor al 1%.
- Validadores 'exiteables' de Lido.
- Obtener estadísticas de los operadores de nodos para ordenar los validadores exiteables.
- Total de validadores predecibles.
- Índices de los últimos validadores solicitados.
Límites del Informe
maxValidatorExitRequestsPerReport
: número máximo de solicitudes de salida permitidas en el informe alValidatorsExitBusOracle
desdeOracleReportSanityChecker.getOracleReportLimits()
.VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS
: un parámetro del contratoOracleDaemonConfig
usado para calcular los validadores que van a salir.NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP
: un parámetro delOracleDaemonConfig
que se tiene en cuenta al determinar la penetración del operador en la red.
Obtener Validadores Exiteables
Un validador es 'exiteable' si NO se cumplen estrictamente dos condiciones:
validator.exit_epoch != FAR_FUTURE_EPOCH
yvalidator.index <= last_requested_to_exit_index
.
Estadísticas del Operador de Nodo
Estadísticas para cada operador de nodo, necesarias para ordenar sus validadores en orden de salida:
- Número de validadores que aún no están en CL.
- Validadores que están en CL y aún no han sido solicitados para salir y no están en salida.
- Validadores que están en CL y se han solicitado para salir pero no están en salida y no se han solicitado para salir recientemente.
- Número objetivo de validadores.
- Comprueba si la bandera de límite de objetivo está habilitada.
NB: Un validador no puede considerarse retrasado si se solicitó su salida en los últimos VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS
slots.
Índices de los Últimos Validadores Solicitados
El contrato ValidatorsExitBusOracle
almacena el índice del último validador que se solicitó para salir. Dado que los validadores se solicitan en un orden estricto desde el validatorIndex
más bajo hasta el más alto, los índices ayudan a encontrar todos los validadores solicitados previamente sin necesidad de obtener todos los eventos.
Devuelve los índices de los últimos validadores que se solicitaron para salir para los operator_indexes
dados en el module
dado. Para los operadores de nodo que nunca solicitaron la salida de ningún validador, el índice se establece en -1
.
ValidatorsExitBusOracle.getLastRequestedValidatorIndices(
uint256 moduleId,
uint256[] nodeOpIds
): int256[]
Recopilación de Estado
Para encontrar los próximos validadores que saldrán, el Autobús de Salida de Validadores Oracle recopila el siguiente estado tanto de las capas de Consenso de Ethereum como de Ejecución.
- Del contrato OracleDaemonConfig:
- PREDICTION_DURATION_IN_SLOTS
- VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS
- De la Cola de Retiros:
- Obtener la cantidad total de solicitudes de retiro no finalizadas
- Del contrato Lido:
- Balance reciente postCL/preCL y retiros de las recompensas de la Capa de Ejecución y de los cofres de retiro a través de eventos
- Del nodo de la Capa de Consenso:
- Todos los validadores y sus estados en el slot de referencia
- Del Staking Router:
- Claves públicas de todos los validadores de Lido
- Índices del último validador solicitado para salir para cada Operador de Nodo
- Estadísticas de claves de validadores para cada Operador de Nodo
- Del contrato Oracle:
- Número máximo de solicitudes de salida para el marco actual
- Claves públicas solicitadas recientemente a través del Autobús de Salida
Obtener Datos
Obtener la Cantidad de Solicitudes de Retiro de stETH No Cubiertas
Recopila la cantidad de stETH en la cola aún por finalizar de WithdrawalQueue.unfinalizedStETH()
Calcular la Velocidad Promedio de Recompensas por Época
Obtiene los eventos ETHDistributed
y TokenRebased
del contrato Lido
y calcula la cantidad promedio de recompensas por época. El período de predicción de recompensas se obtiene del contrato OracleDaemonConfig.
Para obtener eventos en el pasado, abordando los casos donde puede haber slots con bloque perdido, se introduce el siguiente esquema:
- Obtener el valor
PREDICTION_DURATION_IN_SLOTS
del contrato OracleDaemonConfig. - Obtener eventos
TokenRebased
de Lido. - Obtener eventos
ETHDistributed
de Lido. - Agrupar esos eventos por hash de transacción.
- Recopilar de los eventos:
total_rewards
comopostCLBalance + withdrawalsWithdrawn - preCLBalance executionLayerRewardsWithdrawn
.time_spent
como suma detimeElapsed
de cada evento.
- Calcular
rewards_speed_per_epoch
comomax(total_rewards * chain_configs.seconds_per_slot * chain_configs.slots_per_epoch // time_spent, 0)
.
Calcular las Épocas Necesarias para el Barrido
Predicción Promedio del Barrido
Predice las épocas promedio del ciclo de barrido. En la especificación: get expected withdrawals, process withdrawals.
Validadores retirables
- Verifica si
validator
tiene las credenciales de retiro "eth1" con prefijo 0x01, y - Verifica si
validator
es parcialmente retirable, o - Verifica si
validator
es completamente retirable
Predicción del ether disponible antes del próximo retiro
Para estimar la cantidad necesaria para cubrir completamente las solicitudes de retiro no finalizadas, se calculan los siguientes valores:
- Recompensas futuras
- Cantidad futura de retiros
- Saldo total disponible
- Suma acumulativa de los validadores a expulsar
- Balance que se va a retirar
Para calcular las recompensas futuras, es necesario predecir un epoch en el cual todos los validadores en la cola y validators_to_eject
serán retirados:
- Calcula el número de epoch de salida más reciente y la cantidad de validadores que están saliendo en este epoch.
- Si la cola está vacía, el epoch de salida se calculará como
epoch actual + MAX_SEED_LOOK AHEAD + 1
. La constante MAX_SEED_LOOKAHEAD ayuda a mitigar algunos ataques, más detalles aquí. - Calcula el límite de churn - similar a un límite de velocidad en los cambios al conjunto de validadores. El mínimo es de 4 validadores por epoch y se recalcula cada
CHURN_LIMIT_QUOTIENT = 2**16
. Por ejemplo, cuando el número de validadores activos alcanza hasta 327,680, el límite de churn aumenta a 5, especificación. - Calcula la capacidad de slots para la salida:
remain_exits_capacity_for_epoch = churn_limit - (cantidad de validadores que están saliendo en este epoch)
- Calcula el epoch para retirar todos los
validators_to_eject_count
:
epochs_required_to_exit_validators = (validators_to_eject_count - remain_exits_capacity_for_epoch) // churn_limit + 1
- Entonces el epoch predecible para retirar:
withdrawal_epoch = max_exit_epoch_number + epochs_required_to_exit_validators + MIN_VALIDATOR_WITHDRAWABILITY_DELAY
MIN_VALIDATOR_WITHDRAWABILITY_DELAY aquí
Ahora podemos calcular la cantidad (y el número de validadores) necesarios para cubrir completamente la cantidad de solicitudes de retiro no finalizadas en la cola de retirada.
Calcular el saldo esperado a retirar
Recompensas futuras
future_rewards = (withdrawal_epoch + epochs_to_sweep - blockstamp.ref_epoch) * rewards_speed_per_epoch
Cantidad futura de retiros
Obtener el saldo total de los validadores que pueden ser retirados completamente.
Saldo total disponible
Obtén el saldo total como suma de:
Lido.getBufferedEther()
+- Saldo de
elRewardsVault
+ - Saldo de
withdrawalVault
Suma acumulativa de los validadores a expulsar
Obtén el saldo del próximo validador en la cola de salida.
Validadores que van a salir
Recupera eventos ValidatorExitRequest
emitidos recientemente del contrato ValidatorsExitBusOracle
y extrae claves públicas de ellos. La configuración de timeout diferido se obtiene del contrato OracleDaemonConfig
.
Validadores que han solicitado salir, pero no han enviado un mensaje de salida:
- Si el epoch de activación no es lo suficientemente antiguo para iniciar la salida.
- Si el operador del nodo no tuvo suficiente tiempo para enviar el mensaje de salida (VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS).
Para obtener los validadores, el oráculo calcula:
lido_validators_by_operator
- Recupera todas las claves Lido utilizadas desde Keys API + Recupera todos los validadores en el slot de referencia y los fusiona con las claves.ejected_indexes
- Obtiene los operadores con los últimos índices de validadores que han salido de todos los módulos de estaca y operadores de nodos medianteValidatorsExitBusOracle.getLastRequestedValidatorIndices(module_id, uint256[] nodeOpIds)
.recent_pubkeys
- Obtiene las últimas claves públicas solicitadas para salir del eventoValidatorExitRequest
.
Para cada lido_validators_by_operator
, el oráculo intenta encontrar validadores no salidos:
- Si no
validator_asked_to_exit
-> devuelve Falso. - Si
is_on_exit
-> devuelve Falso. - Si
validator_recently_asked_to_exit
-> devuelve Verdadero. - Si no
validator_eligible_to_exit
-> devuelve Verdadero. - De lo contrario, devuelve Falso.
El oráculo calcula going_to_withdraw_balance
para todos los validadores no salidos.
Comparar saldo esperado vs. saldo a retirar
El saldo esperado es:
expected_balance = (
future_withdrawals + # Validadores que tienen epoch de retiro
future_rewards + # Recompensas que obtenemos hasta que se retire el último validador en validators_to_eject
total_available_balance + # Saldo actual de EL (el vault, wc vault, buffered eth)
validator_to_eject_balance_sum + # Validadores que esperamos que sean expulsados (solicitados para salir, no demorados)
going_to_withdraw_balance # Saldo de validadores_to_eject
)
Primero, se verifica sin sacar al validador si el protocolo ya tiene suficiente ether disponible para cubrir las solicitudes de retiro en la cola. Si es así, no es razonable expulsar validadores.
Si no hay suficiente, se considera sacar a un validador más y se vuelve a calcular el saldo esperado. El proceso continúa hasta que el saldo esperado sea mayor o igual a la cantidad de solicitudes de retiro no finalizadas.