CIP-94: Voto de la DAO en cadena para los parámetros de la cadena

Resumen simple
Este CIP propone utilizar la votación de la DAO en la cadena para decidir y actualizar los parámetros de las recompensas sin necesidad de un hardfork.

Resumen
Actualmente, todos los parámetros de recompensa están codificados en el código. Este CIP propone almacenar estos parámetros como parte del estado global, de modo que podamos utilizar los poderes de votación existentes en la cadena (estacando y bloqueando CFXs a través del contrato interno de estacado) para votar los cambios de parámetros sin un hardfork. La votación se inicia periódicamente (cada 2 meses), y sólo hay un número fijo de opciones (aumentar el parámetro, disminuir el parámetro, o mantenerlo sin cambios). Las cuentas pueden emitir su voto mediante el envío de transacciones. El estado del parámetro se actualiza cuando termina un periodo de votación.

Motivación
Tradicionalmente, todas las actualizaciones de los parámetros de la cadena son cambios incompatibles y tienen que pasar por un hardfork. Dado que se espera que los hardforks sean infrecuentes y se necesita un tiempo relativamente largo para prepararlos, no podemos actualizar los parámetros a tiempo cuando el entorno cambia rápidamente.

Además, el cambio de un parámetro y la forma de cambiarlo se han decidido a menudo mediante una votación de DAO de gobierno. Sin embargo, todavía depende de los desarrolladores decidir si se siguen estas decisiones y de los mineros decidir si se aplica este hardfork. Esto hace que la votación no sea tan obligatoria como queremos.

Integrando la actualización de parámetros y la votación DAO en la cadena, podemos tener un mecanismo de actualización de parámetros regular sin hardfork.

Especificación
Cuando se ejecuta el bloque número BN, se inicializa un nuevo contrato interno de ParameterControl y se almacenan los parámetros por defecto para la recompensa base de PoW y el interés de recompensa de PoS como entradas de almacenamiento especiales (el interés de recompensa de PoS se ha mantenido en el almacenamiento antes de este CIP, y la recompensa base de PoW se almacenará bajo la clave “pow_base_reward” en el contrato ParameterControl). Además del valor del parámetro utilizado actualmente, las entradas de almacenamiento para guardar el resumen de la votación en curso y la votación resuelta también se inicializan como CURRENT_VOTES_ENTRIES y SETTLED_VOTES_ENTRIES.

La lista de parámetros a votar son:

  1. Recompensa de bloque base PoW.
  2. Tipo de interés de la recompensa base PoS.

Y las opciones de cada parámetro son:

  1. Permanecer sin cambios.
  2. Aumentar en un 100%.
  3. Disminuir en un 50%.

El contrato interno ParameterControl tiene una estructura Vote como
struct Vote
{
uint16 index;
uint256[3] votes;
}
donde el index es el índice del parámetro vote y el array votes es el número de votos emitidos a cada opción (es decir, unchange, increase y decrease en orden).

El contrato tiene dos interfaces para emitir el voto y para leer el voto:

  • function castVote(uint64 version, Vote[] vote_data) external;. El primer parámetro es un número de versión para indicar de qué periodo de votación se trata. El segundo parámetro es una lista codificada de Vote.
    *function readVote(address addr) external view devuelve (Vote[]). Lee los datos de los votos de una cuenta.

Una cuenta puede distribuir su poder de voto a diferentes opciones del mismo parámetro. Para cualquier parámetro, el total de votos de sus opciones no debe superar el poder de voto total actual de la cuenta. Y para cada llamada de castVote, un parámetro sólo puede ser votado como máximo una vez. Si la función se llama varias veces dentro de un periodo de votación, para cada parámetro, sólo la última llamada con éxito tiene efecto y anula los votos anteriores. Por ejemplo, si una cuenta ha votado por ambos parámetros en la primera transacción TX1 y ha votado por el parámetro 2 en la segunda transacción TX2, su voto por el parámetro 1 sigue siendo el mismo que el de TX1 y su voto por el parámetro 2 se cambia por el de TX2.

Al final de un periodo de votación (contado como números de bloque), se utiliza SETTLED_VOTES_ENTRIES para calcular los nuevos valores de los parámetros. En concreto, si el total de votos para cada opción de un parámetro es[n_cambio, n_aumento, n_disminución], el nuevo valor de este parámetro se calcula como

new = old * 2 ** ((n_increase - n_decrease) / (n_increase + n_decease + n_unchange))

Una vez actualizados los parámetros en el almacén, movemos los votos actuales CURRENT_VOTES_ENTRIES a SETTLED_VOTES_ENTRIES y reseteamos los valores de CURRENT_VOTES_ENTRIES a 0 para los votos del siguiente periodo.

También se emite un evento por cada voto exitoso. Para cada cuenta, los últimos votos y la versión para estos votos también se almacenarán como entradas de almacenamiento en el contrato ParamsControl.

El período de votación se establece en 2 meses y se basa en el número de bloques, por lo que cada período es de 2 * 60 * 60 * 24 * 30 * 2 = 10.368.000 bloques.

Justificación
La razón de almacenar los resultados de la votación en SETTLED_VOTES_ENTRIES en lugar de aplicarla inmediatamente es que, si el resultado se manipula inesperadamente, todavía hay una oportunidad de revertirlo con un hardfork. Y añadir un retraso permite que se voten más parámetros (relacionados con la validez de la cabecera, como la dificultad) en el futuro, porque el último estado para un nuevo bloque puede no estar disponible.

Queremos que una cuenta vote por varias opciones por dos razones. Una es que el contrato del pool de PoS ahora puede recoger las opciones de sus usuarios y ayudar a emitir sus votos. Otra razón es que una cuenta puede combinar estas opciones para tener una opción de grano fino para un parámetro. Esto nos permite hacer que el rango de cambio de las opciones sea relativamente grande sin un efecto secundario.

Hacemos que las votaciones posteriores anulen las votaciones tempranas a nivel de parámetro por razones de eficiencia, porque si una cuenta sólo vota por un parámetro, sólo necesitamos leer los datos de este parámetro para su validación. Si queremos que cada llamada anule todas las votaciones, tendremos que leer todas las entradas para ver si han sido votadas antes.

Compatibilidad con el pasado
Este es un cambio de ruptura porque añade un nuevo contrato interno y añade nuevas entradas en el estado.

Casos de prueba
TBA

Implementación
TBA

Consideraciones de seguridad
TBA

Derechos de autor
Derechos de autor y derechos relacionados renunciados a través de CC0.

Link Original: CIP-94: On-chain DAO Vote for Chain Parameters