Timeout für Web3-Ereignisfilterung

Dies ist der Code, den ich verwende, um alle Ereignisse aus einem bestimmten Vertrag abzurufen.

Solidität:

event NewEvent(address indexed contractAddress, address newBOPAddress, address payer, uint commitThreshold, bool hasDefaultRelease, uint defaultTimeoutLength, string initialPayerString);

Web3-Code:

event = Factory.contractInstance.NewBOP({contractAddress:'0x384da3....'},{"fromBlock": 0, "toBlock": 'latest'});

event.get(function(err, res) {
  if(err){
    console.log(err.message);
  }
  else{
    console.log(res);
  }
});

Wenn ich einen relativ jungen fromBlock spezifiziere, erhalte ich eine schnelle Antwort und alles funktioniert einwandfrei, wenn ich einen Block verwende, der ungefähr 200.000 Blöcke in der Vergangenheit liegt, erhalte ich diesen Timeout-Fehler:

Gateway-Zeitüberschreitung. Die Bearbeitung der Anfrage hat zu lange gedauert. Dies kann passieren, wenn Protokolle über einen zu großen Blockbereich abgefragt werden.

Ich habe dies auf Ropsten mit verschiedenen Knoten (Metamask, Myetherapi, Infura) versucht, habe aber immer das gleiche Problem. Ich habe mit quicknode.io einen privaten Knoten erworben , der das Problem nicht löst, für Benutzer, die öffentliche Knoten verwenden müssen. Ich weiß, dass ich einen neueren "fromBlock" verwenden könnte, aber ich möchte die Ereignisse meines Fabrikvertrags als historische Daten verwenden, damit ich sie dem Benutzer anzeigen kann. Und ich habe ein paar Quellen gefunden, die unterstützen, dass es technisch möglich ist, insbesondere mit indizierten Argumenten zu filtern:

https://media.consensys.net/technical-introduction-to-events-and-logs-in-ethereum-a074d65dd61e (Teil 3)

Wie greife ich auf das Ereignisprotokoll zu, wenn ich die Vertragsadresse (web3) kenne? (verwendet verschiedene Filteroptionen)

Meine genaue Frage ist: Brauche ich in jedem Fall einen vollständigen privaten Knoten für die gewünschte Leistung, oder gibt es andere Gründe / Möglichkeiten, die Ereignisfilterung schneller zu machen (um das Timeout zu stoppen)?

Danke für jede Antwort!

Ich habe das gleiche Problem, hast du eine Möglichkeit gefunden, es zu beheben? Danke!

Antworten (2)

Selbst mit einem privaten Knoten glaube ich nicht, dass dies funktionieren wird. Die Blockchain ist nicht so abfragbar wie eine relationale oder nicht relationale Datenbank. Sein Hauptziel ist es, die Konsistenz und einen globalen Zustand in jedem Block beizubehalten, nicht die Leistung beim Lesen vergangener Ereignisse. Ihre Option besteht also darin, die Paginierung zu verwenden und mit einem fromBlock und toBlock mit einer Differenz von beispielsweise 1000 zu iterieren, bis Sie den neuesten Block erreichen. Wenn Sie dies aber einem Benutzer zeigen möchten, wird es noch einige Zeit dauern, daher empfehle ich, die Daten per Paginierung abzurufen und in einer Datenbank zu speichern. Dann in Ihrer Benutzer-App einfach aus der Datenbank abfragen.

Benötige ich für die gewünschte Performance in jedem Fall einen Full Private Node, oder gibt es andere Gründe/Möglichkeiten, die Ereignisfilterung schneller zu machen (um den Timeout zu stoppen)?

Für die Leistung, die in Situationen wie dieser entscheidend ist

  • Sie pflegen Ihre eigene zentrale Datenbank zB SQL

  • Diese Datenbank bietet Abfragen für die Ereignisse innerhalb aller von Ihnen gewünschten Leistungskriterien

  • Die Datenbank wird aus den vergangenen Ereignissen gefüllt

  • Ein Live-Daemon liest alle neu eingehenden Blöcke und fügt daraus Ereignisse zur Datenbank hinzu

Wie in den Antworten beschrieben, ist der Ethereum-Knoten nicht für leistungskritische Abfragen optimiert, und es ist besser, dies selbst zu tun.

Etwas Python-Code, der Ereignisse aus dem Ethereum-Knoten liest und die SQL-Datenbank mit ihnen füllt