¿Cuál es el orden predeterminado de las transacciones durante la minería?

Sé que el papel amarillo no especifica cómo se ordenarán las transacciones en un bloque y esto lo decide el minero. Pero estoy interesado en cómo se maneja esto prácticamente (supongo que no llamaré a alguna función rand para ordenar). Esta respuesta a una pregunta relacionada sugiere que el precio del gas juega un papel. ¿Cómo, por ejemplo, geth ordena las transacciones durante el proceso de minería?

¡Gran pregunta! Sería interesante si esto obtiene una respuesta de una variedad de clientes.

Respuestas (3)

Editar: 23 de junio de 2017 - Se agregaron detalles de paridad (ver más abajo)


Geth

Para la implementación de Vanilla Geth, la commitNewWork()función en worker.go ordena de la siguiente manera:

//approach 2
transactions := self.eth.TxPool().GetTransactions() <--- fetch from pool
types.SortByPriceAndNonce(transactions)      <---------- order

es decir, clasifica por precio de gas y valor de nonce (y por cuenta de propietario; consulte a continuación).

Hay otros dos enfoques en el código que están comentados, pero pueden dar una pista sobre ideas anteriores (o dar ejemplos a los mineros que quieran usar su propia implementación). Están:

  • enfoque 1: ordenar solo por nonce
  • enfoque 3: ordenar por propietario (tratando las transacciones de uno o varios propietarios de manera diferente), luego por precio y nonce

SortByPriceAndNonce()se define en la transacción.go :

// This method first sorts the separates the list of transactions into individual
// sender accounts and sorts them by nonce. After the account nonce ordering is
// satisfied, the results are merged back together by price, always comparing only
// the head transaction from each account. This is done via a heap to keep it fast

Una vez clasificadas, las transacciones se analizan aún más commitTransactions()para eliminar las que tengan "gasificación baja".


Paridad

Para Parity las cosas son un poco más fáciles: hay una opción CLI. Esto permitirá, al menos, cambiar el orden de algunas formas básicas.

 --tx-queue-strategy S          Prioritization strategy used to order transactions
                                 in the queue. S may be:
                                 gas - Prioritize txs with low gas limit;
                                 gas_price - Prioritize txs with high gas price;
                                 gas_factor - Prioritize txs using gas price
                                 and gas limit ratio (default: gas_price).
solo para aclarar, SortByPriceAndNonceordena primero por precio y luego (para tx del mismo precio) ordena por nonce: github.com/ethereum/go-ethereum/blob/master/core/types/…
De acuerdo con la siguiente respuesta, las transacciones se ordenan primero por nonce: ethereum.stackexchange.com/a/13402/7132
Creo que es un poco más complicado que solo "x antes de y": básicamente se trata de clasificar por ambos al mismo tiempo. "SortByPriceAndNonce ordena las transacciones por precio de tal manera que se mantienen los pedidos de nonce dentro de una sola cuenta".
Por ejemplo, se seleccionarán las 5 transacciones principales con los precios de gas más altos, donde todas tienen un costo de gas de 6 millones. Si se seleccionan dos de ellos, se superará el límite de gas de transacción actual, que es de 10 millones. Entonces, ¿cómo manejan los mineros este caso? @RichardHorrocks

Para agregar la excelente respuesta de Richard Horrocks:

Estudié los últimos 1000 bloques:

  • ~85% de los bloques parecen ordenarse primero por el precio alto del gas (respetando el orden nonce para una sola dirección de remitente) (la configuración predeterminada tanto para Parity como para Geth)
  • ~ 9% de los bloques parecen ordenarse primero por Low Gas Limit (estrategia de tx-queue de "gas" de Parity)
  • No pude descifrar el pedido del último 6%. Sospecho que podrían estar en el orden en que el minero se enteró de ellos.
  • No parece que los bloques estén ordenados solo por Nonce.

Paridad

El código fuente para las diferentes estrategias de ordenamiento de transacciones se puede encontrar aquí .

Esta es la lógica de ordenación predeterminada:

  1. Las transacciones que tardan más de un cierto tiempo en ejecutarse son penalizadas y se colocarán al final de la lista. Si un remitente envía 16 transacciones infractoras, está prohibido.
  2. Las transacciones que se originen en el nodo minero se pondrán primero.
  3. Se comprueba la "altura de nonce". Supongo que esto garantiza que los nonces están en el orden correcto para un usuario determinado.
  4. Luego se aplica la estrategia seleccionada.
  5. Si todos son iguales, se ordenan en el orden en que llegaron.

TL;RD

Al final, tenga en cuenta que este es un software de código abierto y que no hay reglas sobre cómo se deben ordenar las transacciones. Cada minero es libre de enviar transacciones en el orden que desee, por lo que no hay forma de garantizar el orden de la transacción, pero parece que un precio de gasolina alto y un límite de gasolina razonable deberían asegurarle un buen lugar en la mayoría de los casos.

Creo que la respuesta de Horrock es un poco difícil de entender, y la "clasificación" es un tipo extraño de clasificación que necesita un poco más de explicación.

Digamos que usted es el minero y tiene 100 transacciones para clasificar. Digamos que 80 personas únicas enviaron 80 transacciones únicas. Luego, digamos que 10 personas únicas enviaron 2 transacciones cada una. Son 10 transacciones "primeras" y 10 transacciones "segundas", para esas 10 personas. 100 totales.

La idea es agrupar las 80 transacciones únicas y las 10 transacciones "primeras", en un grupo G.

while gasLimitNotReached:
   T = highestGasPrice(G)
   G.remove(T)
   if T was some Account."first":
      G.append(Account."second")
   Commit(T)

Creo que puede ver cómo esto se extiende a algunas cuentas que tienen tres transacciones o cuatro transacciones. La idea es que solo permita que G tenga transacciones de cuentas únicas. Si la misma cuenta tiene muchos txs, solo considere el nonce más pequeño, independientemente del precio de la gasolina de esos nonces más grandes. Luego, haga un bucle sobre G, haciendo estallar en orden de precio de la gasolina. Cada vez que se deshaga de una transacción, verifique si esa cuenta tiene más transacciones de mayor valor y luego agregue ese tx nuevamente a G si existe.

Fuente: https://github.com/ethereum/go-ethereum/blob/290e851f57f5d27a1d5f0f7ad784c836e017c337/core/types/transaction.go#L372 , de la respuesta de Horrick.