Warum gibt sendSignedTransaction einen tx-Hash zurück, ABER postet nicht an das Rinkeby-Netzwerk (React, Metamask, web3, infura)

Ich entwickle eine sehr einfache React-Anwendung, bei der ein Benutzer auf eine Schaltfläche klickt und etwas Ether von einem Konto an ein anderes gesendet wird. Derzeit erstellt die Funktion onClick sendEther eine ordnungsgemäß signierte, serialisierte Transaktion und gibt (häufig) einen Transaktions-Hash zurück. Die Transaktion geht jedoch nie wirklich durch das Rinkeby-Testnetzwerk (auf das über Etherscan zugegriffen wird).

Meine Vermutung ist, dass ich Infura missbrauche (das ich in meinem DOMContentLoaded-Ereignis eingerichtet habe, siehe unten).

//1. Aufstellen

document.addEventListener('DOMContentLoaded', () => {
   const endpoint = 'https://rinkeby.infura.io/APIKEY';
   window.web3 = new Web3(new Web3.providers.HttpProvider(endpoint));
}); 

//2. Frontend-Komponente reagieren.

sendEther() {
    const fromAccount = **acct1**;
    const toAccount   = **acct2**;

    const rawTransaction    = this.makeRawTransaction(fromAccount, toAccount);
    const signedTransaction = this.makeSignedTransaction(rawTransaction);
    const serializedTransaction = `0x${signedTransaction.serialize().toString('hex')}`;

    window.web3.eth.sendSignedTransaction(serializedTransaction, (error, result) => {
        if(!error) {
          console.log(`Transaction hash is: ${result}`);
          this.setState({
            etherscanUrl: `https://rinkeby.etherscan.io/tx/${result}`,
            error: null
          });

        } else {
          this.setState({ error: error.message })
          console.error(error);
        }
    });
  }

  makeSignedTransaction(rawTransaction) {
    const privateKey   = '**************';
    const privateKeyX  = new Buffer(privateKey, 'hex');
    const transaction  = new EthTx(rawTransaction);
    transaction.sign(privateKeyX);

    return transaction;
  }

  makeRawTransaction(fromAccount, toAccount) {
    const { exchangeRate } = this.props;
    const amount = (1 / exchangeRate) * 5;

    return ({
      nonce: window.web3.utils.toHex(window.web3.eth.getTransactionCount(fromAccount)),
      to: toAccount,
      gasPrice: window.web3.utils.toHex(100000000000),
      gasLimit: window.web3.utils.toHex(100000),
      value: window.web3.utils.toHex(window.web3.utils.toWei(`${amount}`, 'ether')),
      data: ''
    });
  }
Nur eine Anmerkung: Etherscan ist nicht allmächtig. Auch wenn etwas in Etherscan nicht auftaucht, bedeutet das nicht, dass es nicht erfolgreich gewesen sein könnte. Vielleicht sieht Etherscan es einfach nicht?

Antworten (2)

Diese Linie ...

nonce: window.web3.utils.toHex(window.web3.eth.getTransactionCount(fromAccount)),

... setzt auf eine zuverlässige Transaktionszählung von Infura. Das Problem ist, dass es nicht so zuverlässig (oder sogar nahe) ist, wie Sie es brauchen. Wie Sie beobachtet haben, führt diese Methode zu unzuverlässigen, inkonsistenten Ergebnissen.

Einige Hintergrundinformationen helfen zu erklären, was vor sich geht und wie Sie damit umgehen können.

Ethereum verwendet einen noncefür jedes Konto, um sich vor Replay-Angriffen zu schützen. Es gibt einige subtile Implementierungsdetails.

  1. Transaktionen von demselben Konto werden mit Sicherheit der Reihe nach abgebaut nonce.
  2. Wenn eine Transaktion nicht abgebaut werden kann (verloren, Gas zu niedrig, um in einen Block aufgenommen zu werden), werden alle Transaktionen mit einem höheren Wert blockiert nonce. Eine blockierte Transaktion kann normalerweise abgebrochen werden (siehe Nr. 4).
  3. Von Software-Clients (Knoten, Brieftaschen) wird erwartet, dass sie die Nonce verfolgen und an Transaktionen anhängen. Auf diese Weise kennen die Knoten die richtige Ausführungsreihenfolge, selbst wenn geklatschte Transaktionen nicht in der richtigen Reihenfolge ankommen.
  4. Eine Transaktion kann durch eine andere Transaktion mit demselben nonceoder einem höheren Wert storniert werden, gaswenn der Ersatz zuerst abgebaut wird. Eine übliche Methode zum Stornieren einer Transaktion besteht darin, die ETH zu wiederholen und vom Konto an sich selbst zu noncesenden .0
  5. getTransactionCount()Berücksichtigt bestenfalls nicht die Transaktionen, die möglicherweise in der ausstehenden Warteschlange vorhanden sind.
  6. Die ausstehende Warteschlange ist "inoffiziell", wenn dies im verteilten Konsens über irgendetwas gesagt werden kann. Nodes können nur die ausstehenden Transaktionen melden, von denen sie wissen . Sie können und Sie werden unterschiedliche Meinungen von verschiedenen Knoten erhalten, wenn vorgeschlagene Transaktionen das Netzwerk durchlaufen. Das Mining von Blöcken ist der Prozess, der die Mehrdeutigkeit zusammenbricht.
  7. Infura ist hochgradig parallel, sodass die Antwort, selbst wenn Sie auf einen Endpunkt schlagen, von jedem nach außen gerichteten Knoten mit Lastenausgleich kommen kann.

Alles in allem gibt es bekannte Gründe, warum Ihr Prozess unzuverlässig ist.

Der übliche Ansatz besteht darin, den Softwareclient zum Manager der nonce. Das am einfachsten zu beschreibende Szenario ist der Fall, in dem es keine ausstehenden Transaktionen gibt, weil das Konto ruhig war oder es sich um ein neues Konto handelt.

Beginnen Sie bei 0, oder der Transaktionsanzahl, und erhöhen Sie die Nonce, während Sie fortfahren, ohne sich auf Knoten zu verlassen. Sie müssen Ihrer eigenen Zählung mehr vertrauen als einem Signal aus dem Netzwerk.

Weitere Informationen finden Sie hier: Gleichzeitigkeitsmuster für das Konto Nonce

Ich hoffe es hilft.

Wie Rob Hitchens erklärte, ist Infura über einen Load Balancer mit mehreren Knoten dahinter aufgebaut. Dies bedeutet, dass zwei gleiche Anfragen an Infura zu unterschiedlichen Antworten führen können, da jede Anfrage einen anderen Knoten treffen könnte. Manchmal erhalten Sie Antworten von veralteten Blöcken, Knoten mit unterschiedlichen Transaktionen in ihren Mempools oder Knoten, die nicht den neuesten Block enthalten. Eine Alternative zu diesem Problem ist die Verwendung eines Dienstes wie Alchemy

Willkommen beim Ethereum Stack Exchange! Dies wurde als Spam markiert. Bitte überprüfen Sie meta.stackexchange.com/questions/57497/… , da es ein Muster gibt, Alchemy in Ihren Antworten zu erwähnen, und es sollte offengelegt werden, wenn Sie für sie arbeiten.
Können Sie erklären, warum Alchemie besser ist?