¿Cómo hacer que el minero mina solo cuando hay transacciones pendientes?

A partir de ahora, el minero geth que se ejecuta en mi sistema extrae incluso bloques vacíos. Todo lo que quería es que el minero debe minar solo cuando hay Transacciones para minar, después de minar, el minero debería dormir inmediatamente.

¿Cómo lograr esto?

Respuestas (6)

Puedes cargar este script en tu consola geth

¡La mía solo cuando hay transacciones!

var mining_threads = 1

function checkWork() {
    if (eth.getBlock("pending").transactions.length > 0) {
        if (eth.mining) return;
        console.log("== Pending transactions! Mining...");
        miner.start(mining_threads);
    } else {
        miner.stop();
        console.log("== No transactions! Mining stopped.");
    }
}

eth.filter("latest", function(err, block) { checkWork(); });
eth.filter("pending", function(err, block) { checkWork(); });

checkWork();

Vea otros fragmentos útiles aquí

Minería hasta que se hayan logrado x confirmaciones

Esta pregunta es particularmente relevante para las cadenas privadas donde las transacciones pueden ser más esporádicas que en las cadenas públicas. En algunas aplicaciones, puede ser beneficioso continuar con la extracción de un número determinado de bloques después de la última transacción para garantizar que se alcancen las confirmaciones adecuadas antes de que se detenga la extracción y evitar que la última transacción solo reciba una confirmación (por ejemplo, cuando se usa mist en redes privadas, le gusta ver 12 confirmaciones):

var mining_threads = 1
var txBlock = 0

function checkWork() {
if (eth.getBlock("pending").transactions.length > 0) {
    txBlock = eth.getBlock("pending").number
    if (eth.mining) return;
    console.log("  Transactions pending. Mining...");
    miner.start(mining_threads)
    while (eth.getBlock("latest").number < txBlock + 12) {
      if (eth.getBlock("pending").transactions.length > 0) txBlock = eth.getBlock("pending").number;
        }
    console.log("  12 confirmations achieved; mining stopped.");
    miner.stop()
}
else {
    miner.stop()
     }
}

eth.filter("latest", function(err, block) { checkWork(); });
eth.filter("pending", function(err, block) { checkWork(); });

checkWork();

Esto también puede guardarse como un script .js y precargarse usando la función --preload al iniciar geth:

geth --preload "/path/to/mineWhenNeeded.js"
Esta respuesta se puede mejorar enumerando la fuente (el enlace a la otra respuesta SE no es la fuente original).
@JeffreyW. siéntase libre de editar y agregar la fuente.
para borrar/detener el script de minería automáticacheckWork=null
¿Cómo puedo editar el primer script de manera que espere un período definido cuando una transacción esté pendiente antes de extraer las transacciones? Lo intenté admin.sleep()pero esto parece no funcionar. La minería se realiza al instante.
@Tobias considere agregar un problema aquí e intentaré resolverlo por usted
@niksmac Creé un problema. Muchas gracias por tu ayuda.
¿Cómo mantenemos este script ejecutándose mientras la consola geth está cerrada? Estoy ejecutando nodos en AWS, por lo que es imposible mantener todas sus consolas abiertas y conectadas. --precarga no parece hacer el truco ..

Si está utilizando geth POA, puede establecer el período de sellado del bloque en 0 en el archivo de génesis, esto forzará automáticamente a geth a crear solo un nuevo bloque cada vez que haya una transacción en la red.

Para cadenas de período 0, rechace sellar bloques vacíos

Desafortunadamente, esto solo funciona para el primer bloque (en mi intento). Entonces, si inicializo una nueva cadena y envío la primera transacción, esta transacción se extrae directamente, pero si envío una nueva transacción, quedará pendiente para siempre, la minería no funciona. ¿Alguna idea de por qué podría ser esto? De todos modos, con el script anterior proporcionado por @niksmac funciona.
@Tobias ¿Estas transacciones son de trufa o directamente de web3? Lo haría si comparte gethregistros cuando las transacciones están pendientes.

En POA, en continuación a la respuesta de @ jadd22, durante la migración de trufas nos enfrentamos al siguiente problema.

https://github.com/trufflesuite/truffle/issues/853

Para superar esto, podemos ejecutar suficientes números de transacciones ficticias de forma asincrónica, {from:"0xAcc1",to:"0xAcc1",value:0} para garantizar el éxito de la implementación.

Después de la implementación, todas las demás operaciones se llevan a cabo según sea necesario, es decir, la extracción ocurre solo cuando hay transacciones pendientes. Sin generación innecesaria de bloques vacíos.

Podemos usar "clique.period" dentro del archivo genesis.json a cero, como se indica a continuación, para garantizar la extracción solo cuando sea necesario sin generar bloques vacíos. (Solo para POA)

clique": {
        "period": 0,
        "epoch": 30000
    }, 

Solo necesitamos manejar la migración de trufas con algunas transacciones ficticias. Espero que esto no sea necesario si la implementación de los contratos se realiza mediante programación utilizando compiladores web3 y solc.

Lo siento @M.Gupal, en una segunda lectura borré la bandera.

Si usa PoW, puede modificar el código Go en

consenso/ethash/sealer.go

y agregue una condición para rechazar el sello si no hay transacciones:

// Seal implements consensus.Engine, attempting to find a nonce that satisfies
// the block's difficulty requirements.
func (ethash *Ethash) Seal(chain consensus.ChainReader, block *types.Block, stop <-chan struct{}) (*types.Block, error) {
.....
if len(block.Transactions()) == 0 {
    log.Info("Sealing paused, waiting for transactions")
    return nil, nil
}
.....

Después de eso, ejecute make gethpara regenerar los ejecutables con el nuevo código.

Estaba usando la respuesta de @niksmac para minar hasta que se lograron n confirmaciones, pero el ciclo while causó un uso de CPU muy alto (más del 110%). Lo cambié por un intervalo y ahora el uso de la CPU está por debajo del 5%. Compruebo cada 600 ms, pero cualquier número que sea < tiempo de bloque funcionaría.

var minimum_confirmations = 3;
var mining_threads = 1
var txBlock = 0
function checkWork() {
    if (eth.getBlock("pending").transactions.length > 0) {
        txBlock = eth.getBlock("pending").number
        if (eth.mining) return;
        console.log("  Transactions pending. Mining...");
        miner.start(mining_threads)
        interval = setInterval(function () {
            if (eth.getBlock("latest").number < txBlock + minimum_confirmations) {
                if (eth.getBlock("pending").transactions.length > 0) txBlock = eth.getBlock("pending").number;
            } else {
                console.log(minimum_confirmations + " confirmations achieved; mining stopped.");
                miner.stop()
                clearInterval(interval);
            }
        }, 600)
    }
}

eth.filter("latest", function (err, block) { checkWork(); });
eth.filter("pending", function (err, block) { checkWork(); });

checkWork();
También puede hacer admin.sleep(1)para dormir por 1 segundo
@rustyx Tendré que intentarlo porque mi solución propuesta a veces no funciona como se esperaba.

Puede instalar eth-mine-when-need . Que inicia un cliente web3 y escucha eventos. Cuando haya transacciones pendientes o transacciones aún por confirmar, iniciará el minero hasta que se confirmen. Funciona igual que la respuesta de @niksmac. Pero no tiene que ejecutar el script cada vez que inicia ethy le permite especificar la cantidad de subprocesos para la minería y la cantidad de bloques que se necesitan para decir que una transacción está confirmada al pasar esos valores como argumentos (para detalles puede ver el archivo Léame en npm).