Woher weiß ich, dass mir programmgesteuert das Benzin ausgegangen ist?

Das taucht immer wieder in den Gitter-Foren auf, also dachte ich, ich stelle und beantworte diese Frage: Woher weißt du, dass dir das Benzin ausgegangen ist?

Antworten (5)

Es gibt derzeit kein klares Signal, dass Ihnen das Benzin ausgegangen ist. Einer zukünftigen Version wird eine Protokollnachricht hinzugefügt.

Derzeit überprüfe ich, ob gasSent == gasUsed ist. Dazu muss sich Ihr Code die Menge an Gas merken, die Sie bei einer bestimmten Transaktion gesendet haben, und warten, bis die Transaktion abgebaut wird. Wenn gasSent == gasUsed ist, ist Ihnen höchstwahrscheinlich das Benzin ausgegangen. In meinem Javascript-Code werfe ich eine Ausnahme. Das hat mir mehrere peinliche Forenbeiträge und einiges an Zeit erspart.

Theoretisch könnte die Transaktion abgebaut werden, wenn sie genau die verbrauchte Gasmenge benötigt. Ich kann mir jetzt keine Möglichkeit vorstellen, das herauszufinden, vielleicht könnte jemand diese Antwort ergänzen. Wenn Sie so nah am Rand des Benzinmangels sind, sollten Sie wahrscheinlich sowieso mehr Gas geben.

Ich biete kostenlos einen Code an, den ich verwendet habe, um die Web3-Funktionalität zu erweitern, die darauf wartet, dass eine Transaktion von einem lokalen Knoten abgebaut wird. Es verwendet Promises, aber die Anpassung an den Callback-Stil sollte nicht schwierig sein, wenn Sie keine Promises verwenden möchten. Ich plane, dies in Zukunft zu erweitern, um den Konsens mehrerer Knoten abzuwarten, aber ich werde das wahrscheinlich nicht teilen.

Sie können diesen Code nicht kopieren und in Ihren Code einfügen, wenn Sie kein Protokoll instanziiert oder eine Hilfsfunktion erstellt haben, um zu sehen, ob eine Variable festgelegt ist. Wenn Sie das noch nicht getan haben, sollten Sie...

Es sollte viel kleinerer Code sein, um dies für Contract-Contract-Aufrufe zu schreiben, daher werde ich dieses Beispiel nicht zeigen. Gleiches Konzept - prüfen Sie einfach, ob gasSent == gasUsed ist.

(Und ja, Promise-Fans, ich verwende ein Promise-Anti-Pattern. Ich bin nur nicht dazu gekommen, es neu zu schreiben. Die Funktionalität ist korrekt.)

Object.getPrototypeOf(web3.eth).awaitConsensus = function(txhash, gasSent) {
var deferred = Promise.pending();
ethP = this;
filter = this.filter('latest');         // XXX make async
callstack = new Error().stack;
filter.watch(function(error, result) {
    // this callback is called multiple times, so can't promise-then it
    ethP.getTransactionReceiptAsync(txhash).then(function(receipt)  {
    // XXX should probably only wait max 2 events before failing XXX 
    if (receipt && receipt.transactionHash == txhash) {
        filter.stopWatching();
        log.info({txreceipt: receipt});

        if (js.isSet(gasSent)) {
            // note corner case of gasUsed == gasSent.  It could
            // mean used EXACTLY that amount of gas and succeeded.
            // this is a limitation of ethereum.  Hopefully they fix it
            if (receipt.gasUsed >= gasSent) {
                log.error({ badReceipt: receipt });
                log.error({ originalStack: callstack });
                throw(Error("ran out of gas, transaction likely failed!"
                                                                + callstack));
            }
        }

        deferred.resolve(receipt);
    }
    });
});
return deferred.promise.timeout(60000, "awaitConsensus timed out after 60000ms")
        .catch(function(e) {
            log.error(e);
            process.exit(1);
        });

}

Quittungen haben jetzt ein statusFeld (ich habe meine Antwort aktualisiert) und Sie könnten daran interessiert sein, den Code zu aktualisieren :)
Ja, viele Dinge sind mit web3.js v1.0 veraltet, wahrscheinlich dank vieler Rückmeldungen in diesem Forum. Ich bin mir nicht sicher, was ich damit machen soll. Vielleicht sollte eine Meta-Diskussion beginnen, anstatt eine für jede relevante Frage.
Guter Punkt über web3.js v1.0 und das Posten auf Meta. Mein Kommentar hier war, dass Sie den Timer entfernen und einfach das statusFeld in Byzanz überprüfen können.

Da Block 4370000 (Byzanz) eth.getTransactionReceipt(transactionHash)ein statusFeld zurückgibt, das einen Wert hat, 0wann eine Transaktion fehlgeschlagen ist und 1wann die Transaktion erfolgreich war.

Hier ist ein Beispiel, das das statusFeld zeigt:

{ blockHash: '0xb1fcff633029ee18ab6482b58ff8b6e95dd7c82a954c852157152a7a6d32785e',
  blockNumber: 4370000,
  contractAddress: null,
  cumulativeGasUsed: 21000,
  gasUsed: 21000,
  logs: [],
  logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
  root: null,
  status: 1, // **** HERE IS THE STATUS FIELD *****
  transactionHash: '0x1421a887a02301ae127bf2cd4c006116053c9dc4a255e69ea403a2d77c346cf5',
  transactionIndex: 0 }

(Blöcke vor 4370000 haben einen statusNullwert.)

Näheres hier .

Ich verwende web3j. Weder der Transaktionsbeleg noch das Transaktionsobjekt haben einen Feldstatus
@rahul Ich bin mir über den Status der Java-Implementierungen nicht sicher, da es sich in erster Linie um Community-Bemühungen handelt. Ein Vorschlag ist, ein Problem in ihrem Github-Repo zu melden.
Gibt es andere Gründe, warum eine Transaktion außer Benzinmangel fehlschlagen kann? Wenn dies der Fall ist, müssen noch einige zusätzliche Überprüfungen durchgeführt werden, um festzustellen, warum die Transaktion fehlgeschlagen ist.
@PaulS Die anderen Fehler, zum Beispiel ungültiger Opcode, werden nicht auftreten, wenn ein anständiger Compiler verwendet wird ethereum.stackexchange.com/questions/2307/… Ja, es ist möglich, dass a statusvon 0 etwas anderes als Out of Gas bedeutet, aber derzeit Menschen, die mit handgefertigten EVM-Baugruppen interagieren, sind selten. Trotzdem hilfreich, dass Sie darauf hinweisen, und eine Referenz für Fehler ist ethereum.github.io/yellowpaper/paper.pdf mit dem Suchbegriff „außergewöhnlich“.

Hier ist mein Python-Code, um dies mit Populus und web3.py zu überprüfen :

from web3 import Web3
from populus.utils.transactions import wait_for_transaction_receipt

class TransactionConfirmationError(Exception):
    """A transaction was not correctly included in blockchain."""


def confirm_transaction(web3: Web3, txid: str, timeout=60) -> dict:
    """Make sure a transaction was correctly performed.

    Confirm that

    * The transaction has been mined in blockchain

    * The transaction did not throw an error (used up all its gas)

    http://ethereum.stackexchange.com/q/6007/620

    :raise TransactionConfirmationError: If we did not get it confirmed in time
    :return: Transaction receipt
    """

    try:
        receipt = wait_for_transaction_receipt(web3, txid, timeout)
    except Timeout as e:
        raise TransactionConfirmationError("Could not confirm tx {} within timeout {}".format(txid, timeout)) from e

    tx = web3.eth.getTransaction(txid)

    if tx["gas"] == receipt["gasUsed"]:
        raise TransactionConfirmationError("Transaction failed (out of gas, thrown): {}".format(txid))

    return receipt

Es gibt 2 Hauptfehlerfälle, nachdem eine Transaktion geschürft wurde

  • der evm ist das gas ausgegangen: in der Tat ist der beste Weg zum Testen gasUsed==gas
  • Der bereitgestellte Vertrag konnte nicht bereitgestellt werden: getCode(address)==0x

Zur systematischen Nutzung dieser Fälle habe ich diese in ein npm-Paket ethereum-web3-plus gepackt , wer will.

es wird so verwendet:

web3.waitFor(  web3.newInstanceTx("Example"), // your txHash
             function(tx, contract, error) {
                  console.log("callback:", tx, contract, error);
                  // Possible errors : full gas used: <gas used>
                  //                   created contract has no bytecodes
                  if(contract) E = web3.instanceAt("Example", contract);
             } );

Vielleicht eine naive Frage - warum ist dies nicht nur als Markierung in der Transaktionsquittung enthalten. Die Quittung wird generiert, sobald der Block abgebaut ist (daher enthält die txn-Quittung die Blocknummer) und enthält auch das verbrauchte Gas, so dass zum Zeitpunkt der Generierung der Quittung die Transaktion ausgeführt wurde. Warum erfordert die Quittung also keine Bestätigung? davon, ob die Transaktion abgeschlossen ist? Scheint etwas beängstigend zu sein, dass Vertragsaufrufe mit so wenig Sichtbarkeit ausgeführt werden können, ob der Status tatsächlich gemäß dem erwarteten Vertragsverhalten aktualisiert wurde

Hi. Ich fürchte, Sie müssen dies als separate Frage stellen, anstatt als Antwort auf eine vorhandene Frage zu posten.
Willkommen bei Ethereum! Wenn Sie eine andere Frage haben, stellen Sie diese bitte, indem Sie auf die Schaltfläche „ Frage stellen“ klicken .