¿Cómo incluir inmediatamente transacciones en bloques si todavía hay espacio?

  • Versión Geth: 1.8.12-estable
  • Sistema operativo y versión: Linux/OSX

Comportamiento esperado

Las transacciones se distribuyen a la red directamente en su número de bloque enviado y se implementan dentro de eso.


Comportamiento real

Las transacciones se retrasan un bloque de tiempo para ser distribuidas a través de la red y, en consecuencia, se implementan un bloque de tiempo tarde.


Explicación

Tengo un pequeño grupo que está conectado a una cadena privada de Ethereum que usa POAy el tiempo de bloqueo se fija en 15 segundos. El clúster tiene cuatro nodos, todos los nodos están conectados entre sí. Tenga en cuenta que hay tres nodos de firma en mi clúster.

Cuando envío una transacción desde un nodo; la transacción no llega a todos los nodos firmantes del bloque actual, sino que se transfiere al siguiente bloque. Pero observo que la transacción enviada fue recibida por el nodo no firmante justo después de enviarla.

Por ejemplo; cuando envié una transacción dentro del bloque actual, no se implementará en el bloque actual sino en el próximo bloque. Entonces, esto obliga a la red a implementar una transacción en 2 bloques de tiempo, que está entre 15 y 30 segundos.

Entonces, si envié mi transacción en el primer segundo del bloque, primero debo esperar 14 segundos para que llegue el siguiente bloque. Y espere 15 segundos más en el siguiente bloque para que se implemente esa transacción, por lo que en total debo esperar 29 segundos.


Caso de ejemplo: alper@home es un nodo no firmante y otros nodos son nodos firmantes.

Envié una transacción dentro del número de bloque 869,334del nodo denominado eBloc@netlab(nodo firmante) y la transacción aparece justo después en alper@homeel nodo designado (nodo no firmante) en el número de bloque 869,334 , pero no aparece en los nodos firmantes ni siquiera en el nodo que envié desde.

ingrese la descripción de la imagen aquí

En el siguiente bloque ( 869,335) observo que todos los nodos reciben las transacciones.

ingrese la descripción de la imagen aquí

Y finalmente en el bloque número ( 869,336) se despliega la transacción.

ingrese la descripción de la imagen aquí

=> Si la transacción se distribuyó a todo el clúster justo después de enviarla, debe implementarse en el número de bloque ( 869,334), pero usó 1 bloque de tiempo adicional para esto.

[P1] ¿Por qué la transacción enviada la reciben los nodos no firmantes justo después de enviarla, pero no los nodos firmantes?

[P2] ¿Es normal que la transacción enviada no se transfiera a toda la red justo después de enviarla, pero lleva 1 bloque de tiempo adicional incluso si todos los nodos están conectados entre sí? ¿Hay alguna forma de forzar la transferencia de una transacción a todos mis nodos de firmante justo después de que se haya enviado?

Nota: Se puede ver más discusión sobre un problema abierto en go-ethereum.

Sin embargo, me hubiera encantado obtener la recompensa :/
Según entiendo por los comentarios del desarrollador, mi caso de ejemplo es un caso normal para la red principal, donde los nodos firmantes obtienen y firman transacciones con 1 bloque de retraso, el sistema fuerza esto. Pero esta implementación también cubre redes de prueba, por lo que no importa qué sistema obligue a que las transacciones se distribuyan a los nodos firmantes con 1 bloque retrasado, incluso el bloque está completamente vacío. En mi pregunta, estaba buscando una solución para este problema, pero supongo que dependo de la decisión/implementación del desarrollador para encontrar una solución. @NikitaFuchs

Respuestas (2)

Este problema ha sido resuelto por el go-ethereumequipo.

@karalabe:

La transacción debe propagarse a través de la red al mismo tiempo.

Sin embargo, no está incluido en el bloque actual, porque el bloque que se está extrayendo actualmente ya está finalizado. Es costoso recrear un nuevo bloque cada vez que aparece una nueva transacción. Y en el caso de la red principal, los bloques están llenos de cualquier manera, por lo que no tiene mucho sentido. Es por eso que siempre hay un retraso de 1 bloque entre el envío y la extracción.

Sin embargo, para las redes de prueba, tenemos un código que vuelve a trabajar con el minero y, entre otras cosas, también queremos tener la funcionalidad para incluir inmediatamente transacciones en bloques si todavía hay espacio.


Hemos rediseñado el minero en la rama principal. El código actual regenerará bloques cada 3 segundos durante la minería, por lo que si hay más/mejores transacciones para ingresar, el nodo las elegirá.

En una red pública (blockchain de prueba de trabajo), a los mineros no les interesa incluir transacciones tan pronto como se les dice chismes. Una razón para ello se puede derivar del siguiente extracto del documento amarillo (Página 7, publicación revisada EIP 150):

Debido a que el nonce debe satisfacer los requisitos [de validación del bloque], y debido a que su satisfacción depende del contenido del bloque y, a su vez, de sus transacciones compuestas , es difícil crear bloques nuevos y válidos...

En otras palabras, cuando intenta encontrar el bloque nonce, el minero ya necesita tener una raíz Merkle de todas las transacciones para incluir en el bloque. Si agregara constantemente nuevas transacciones, el hash raíz cambiaría y tendría que comenzar a minar desde el principio.

No sé exactamente sobre el retraso de dos bloques entre la transmisión y la minería, pero esto es lo que asumo: si el Bloque n es el bloque en el que se extrae su transacción, entonces

Bloque n-2: las transacciones se transmiten al mempool del minero.

Bloque n-1: el minero selecciona y ejecuta/valida las transacciones lo más rápido posible, para tener "todo listo" para competir por extraer el siguiente bloque válido, solo esperando recibir el hash del bloque principal.

Bloque n: Miner obtuvo el hash del bloque principal, nada más cambia en su candidato de bloque, extrae el nonce correcto y sella el bloque.

Por supuesto, uno podría cambiar este comportamiento en el cliente del nodo de minería, esto requeriría algunas habilidades en go or rust, por supuesto;)

Consulte ( github.com/ethereum/go-ethereum/issues/… ); Supongo que esto ( functionality to immediately include transactions into blocks if there is still space) se consideraría implementado en el futuro para las redes de prueba .@Nikita Fuchs
No hay un nodo minero en la Prueba de autoridad, por lo tanto, solo hay un par de nodos de firma. El problema es que estoy observando que las transacciones se pueden distribuir a los nodos que no son firmantes justo después de que se envían, pero no importa qué transacciones se distribuyan al nodo firmante en 1 bloque de tiempo de retraso, incluso el bloque está vacío. @Nikita Fuchs
No existe tal cosa como un firmante en una red PoA, ni tal cosa como un retraso forzado en la transmisión de transacciones. En PoA, es solo que solo los nodos autorizados pueden extraer un bloque y, a partir de ahí, todo está de acuerdo con mi respuesta anterior: cada transacción se transmite de inmediato, los mineros solo necesitan tener todo listo de antemano para no tener que comenzar. sobre la minería de nuevo.
Existe esta función clique.getSigners(), consulte ( ethereum.stackexchange.com/a/15779/4575 ). Como mostré en mi pregunta cuando envié una transacción, no aparecerá en el bloque actual que se extraería inmediatamente en el bloque que se envía, incluso si no existe otra transacción en el bloque. Entonces, si envié mi transacción en el primer segundo del bloque, primero debo esperar 14 segundos para que llegue el siguiente bloque. Y espere 15 segundos más para que se implemente esa transacción, por lo que en total debo esperar 29 segundos.