Wie kann man Miner nur dann minen, wenn es ausstehende Transaktionen gibt?

Ab sofort schürft der auf meinem System laufende Geth-Miner sogar leere Blöcke. Alles, was ich wollte, ist, dass der Miner nur abbauen sollte, wenn es Transaktionen zum Minen gibt, nach dem Mining sollte der Miner sofort schlafen.

Wie erreicht man das?

Antworten (6)

Sie können dieses Skript in Ihre Geth-Konsole laden

Mine nur, wenn es Transaktionen gibt!

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();

Weitere nützliche Snippets finden Sie hier

Mining bis x Bestätigungen erreicht wurden

Diese Frage ist besonders relevant für private Ketten, wo Transaktionen sporadischer sein können als bei öffentlichen Ketten. In einigen Anwendungen kann es vorteilhaft sein, nach der letzten Transaktion für eine bestimmte Anzahl von Blöcken weiter zu minen, um sicherzustellen, dass angemessene Bestätigungen erreicht werden, bevor das Mining stoppt, und um zu vermeiden, dass die letzte Transaktion nur eine Bestätigung erhält (z. B. wenn Nebel in privaten Netzwerken verwendet wird, die es gerne sieht). 12 Bestätigungen):

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();

Dies kann auch als .js-Skript gespeichert und mit der Funktion --preload beim Start von geth vorgeladen werden:

geth --preload "/path/to/mineWhenNeeded.js"
Diese Antwort kann durch Auflisten der Quelle verbessert werden (der Link zur anderen SE-Antwort ist nicht die ursprüngliche Quelle).
@JeffreyW. Fühlen Sie sich frei, Quelle zu bearbeiten und hinzuzufügen.
um das Auto-Mining-Skript zu löschen/stoppencheckWork=null
Wie kann ich das erste Skript so bearbeiten, dass es für einen definierten Zeitraum wartet, wenn eine Transaktion ansteht, bevor es die Transaktionen abbaut? Ich habe es versucht admin.sleep(), aber das scheint nicht zu funktionieren. Der Abbau erfolgt sofort.
@Tobias erwäge, hier ein Problem hinzuzufügen, und ich werde versuchen, es für dich zu erledigen
@niksmac Ich habe ein Problem erstellt. Tausend Dank für deine Hilfe.
Wie halten wir dieses Skript am Laufen, während die Geth-Konsole geschlossen ist? Ich betreibe Knoten auf AWS, daher ist es unmöglich, alle ihre Konsolen offen und verbunden zu halten. --preload scheint nicht zu funktionieren.

Wenn Sie Geth POA verwenden, können Sie die Blockversiegelungsperiode in der Genesis-Datei auf 0 setzen, dies zwingt Geth automatisch dazu, nur dann einen neuen Block zu erstellen, wenn es eine Transaktion im Netzwerk gibt.

Weigern Sie sich bei 0-Perioden-Ketten, leere Blöcke zu versiegeln

Leider funktioniert dies nur für den ersten Block (bei meinem Versuch). Wenn ich also eine neue Kette initialisiere und die erste Transaktion sende, wird diese Transaktion direkt abgebaut, aber wenn ich eine neue Transaktion sende, wird sie für immer anstehen, das Mining funktioniert nicht. Irgendeine Idee, warum das sein könnte? Wie auch immer, mit dem obigen Skript von @niksmac funktioniert es.
@Tobias Diese Transaktionen stammen von truffle oder direkt von web3? Es wäre, wenn Sie gethProtokolle teilen, wenn Transaktionen ausstehen.

In POA, in Fortsetzung der Antwort von @ jadd22, stoßen wir während der Trüffelmigration auf das folgende Problem.

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

Um dies zu umgehen, können wir genügend Nummern-Dummy-Transaktionen asynchron ausführen, {from:"0xAcc1",to:"0xAcc1",value:0}, um den Bereitstellungserfolg sicherzustellen.

Nach der Bereitstellung werden alle anderen Operationen nach Bedarf ausgeführt, dh Mining findet nur statt, wenn ausstehende Transaktionen vorhanden sind. Keine unnötige leere Blockgenerierung.

Wir können „clique.period“ innerhalb der genesis.json-Datei auf Null setzen, wie unten angegeben, um sicherzustellen, dass das Mining nur bei Bedarf ohne die Generierung leerer Blöcke sichergestellt wird. (Nur für POA)

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

Nur müssen wir die Truffle-Migration mit einigen Dummy-Transaktionen handhaben. Hoffentlich ist dies nicht erforderlich, wenn die Bereitstellung der Verträge programmgesteuert mit Web3- und Solc-Compilern erfolgt.

Entschuldigung @M.Gupal, beim zweiten Lesen habe ich die Flagge gelöscht.

Wenn Sie PoW verwenden, können Sie den Go-Code unter ändern

konsens/ethash/sealer.go

und fügen Sie eine Bedingung hinzu, um das Siegel abzulehnen, wenn es keine Transaktionen gibt:

// 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
}
.....

Führen Sie danach aus make geth, um die ausführbaren Dateien mit dem neuen Code neu zu generieren.

Ich habe @niksmac answer für das Mining verwendet, bis n Bestätigungen erreicht wurden, aber die While-Schleife verursachte eine sehr hohe CPU-Auslastung (über 110 %). Ich habe es für ein Intervall geändert und jetzt liegt die CPU-Auslastung unter 5%. Ich überprüfe alle 600 ms, aber jede Zahl, die < Blockzeit ist, würde funktionieren.

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();
Kann auch admin.sleep(1)für 1 Sekunde schlafen
@rustyx Das muss ich ausprobieren, da mein Lösungsvorschlag manchmal nicht wie erwartet funktioniert.

Sie können eth-mine-when-need installieren . Welches einen Web3-Client startet und auf Ereignisse lauscht. Wenn ausstehende oder noch zu bestätigende Transaktionen vorhanden sind, wird der Miner gestartet, bis sie bestätigt sind. Es funktioniert genauso wie die Antwort von @niksmac . Sie müssen das Skript jedoch nicht bei jedem Start ausführen, ethund Sie können die Anzahl der Threads für das Mining und die Anzahl der Blöcke angeben, die erforderlich sind, um zu sagen, dass eine Transaktion bestätigt wird, indem Sie diese Werte als Argumente übergeben (für Details Sie können die Readme-Datei unter npm) sehen.