Das Konto Nonce ist das einzige Element in der Transaktionsstruktur, das einen Replay-Angriff verhindert (wie in dieser sehr guten Antwort erläutert ). Es erzwingt im Wesentlichen die Sequenzialisierung der Transaktionen eines Kontos.
Dies verursacht normalerweise keine Probleme, wenn Transaktionen über die web3-Schnittstelle an einen Ethereum-Knoten (z. B. Geth, Parity) gesendet werden, der dann das Signieren durchführt. Die Sequenzierung erfolgt intern durch den Knoten und ist somit für den Endbenutzer transparent.
Dies ist nicht der Fall, wenn Transaktionen von einer Benutzeranwendung (dh nicht Geth oder Parity) erstellt und signiert werden, bevor sie an einen Knoten gesendet werden (zB durch web3.eth.sendRawTransaction).
Die Erstellung der Rohtransaktion erfordert das Abrufen einer Konto-Nonce, was durch web3.eth.getTransactionCount erfolgen kann, wie in dieser Frage erläutert . Dies funktioniert gut, wenn keine Parallelität beteiligt ist.
Stellen Sie sich jedoch einen Endbenutzer vor, der mehrere Transaktionen parallel signieren muss. Die Transaktionssequentialisierung wird eine Verantwortung der Benutzeranwendung.
"web3.eth.getTransactionCount" gibt nur bestätigte Transaktionszahlen zurück (siehe diese Frage ). Wenn Transaktionen parallel signiert werden, wird daher nur eine von ihnen erfolgreich sein, es sei denn, wir manipulieren die Zählung auf intelligente Weise.
Meine Frage ist: Was sind einige gute Muster, um mit dieser Situation umzugehen?
Dies ermöglicht gleichzeitige Transaktionen. Es führt jedoch zu zusätzlicher Komplexität in der Benutzeranwendung. Außerdem ist es nicht zu skalierbar: Überlegen Sie, ob Dutzende oder Hunderte gleichzeitiger Transaktionen erforderlich sind. Angesichts der Tatsache, dass die hierachische deterministische Brieftasche in Ethereum nicht nativ ist (ich weiß, dass es die LightWallet gibt ), klingt dies nicht nach einer einfachen Lösung.
Dadurch wird eine Schleife erstellt, die das Sendeergebnis der Transaktion überprüft. Wenn das Rückgabeergebnis eine doppelte Nonce anzeigt (z. B. würde Geth „Ersatztransaktion unterbewertet“ zurückgeben), versuchen Sie es erneut mit einer neuen Nonce.
Diese Lösung ist nicht portabel: Verschiedene Clients geben für denselben Fehler unterschiedliche Zeichenfolgen zurück. In der Praxis scheint mir aufgefallen zu sein, dass Geth manchmal nicht einmal die obige Zeichenfolge zurückgibt, sondern stillschweigend die anderen Transaktionen verwirft (nicht bestätigt, da ich keinen zuverlässigen Weg zur Reproduktion gefunden habe). Dadurch funktioniert die Erkennung nicht zuverlässig.
Jede Transaktionskonstruktion beinhaltet die "Beantragung" einer Nonce von einem globalen "Nonce-Manager". Der Singleton-"Nonce-Manager" kann über eine intelligente Logik verfügen, um aufsteigende Nonce-Nummern zu verteilen. Dies nutzt das hier diskutierte Verhalten aus .
Dies führt nicht nur zu einem Singleton (möglicherweise ein Anti-Pattern), sondern es klingt auch nicht einfach, es richtig zu machen: Wenn eine Low-Nonce-Transaktion irgendwie fehlschlägt (z. B. nicht einmal an das Netzwerk gesendet wird), der Rest der Transaktionen werden auf unbestimmte Zeit stecken bleiben. Im Allgemeinen ist es eine schlechte Lösung, die mehr Komplexität und Probleme mit sich bringt, als zu versuchen, sie zu lösen.
Das ist nicht wirklich eine Lösung. Das offensichtlichste Problem ist, dass die zusätzliche Abhängigkeit nicht gerechtfertigt zu sein scheint, wenn sie nur für das Nonce-Feld gilt.
Wenn die Benutzeranwendung bereits private Schlüssel verwaltet, führt dies zu zusätzlicher Komplexität: Die privaten Schlüssel müssen vom Geth- oder Paritätsknoten gemeinsam verwaltet (oder kopiert) werden. Auch hier erscheint die Komplexität (und potenzielle Schwachstelle) nicht vertretbar, wenn es nur um den Umgang mit der Nonce geht.
Off-Topic. Es scheint mir, dass das Konto Nonce nicht das beste Design in Ethereum ist. Es zwingt Benutzeranwendungen, entweder Low-Level-Protokolldetails zu handhaben oder eine Abhängigkeit von einem Knoten (Geth/Parity) einzuführen. In jedem Fall fügt es den Benutzeranwendungen eine unverhältnismäßige Sperrigkeit hinzu.
Ich bin noch nicht an dem Punkt angelangt, an dem ich eines dieser Dinge testen kann, aber mein Bauchgefühl ist, dass der Singleton Nonce Manager mit einigen Verbesserungen der richtige Weg wäre:
Die Implementierungsdetails würden eine genaue Vertrautheit mit gleichzeitiger Programmierung, Sperren, Mutex, Asynchronität oder was auch immer erfordern. Im Wesentlichen ist das Obige eine Vermutung, da ich noch nicht direkt mit den RPC-Aufrufen gearbeitet habe und es nicht testen kann, aber ich denke, das ist das Grundgerüst der Route, die ich gehen würde. Ich sehe, dass die Warteschlangenstruktur eine interne API zum Auflisten von ausstehenden Transaktionen, verarbeiteten und unterstützenden anderen UI-Operationen als Bonus bieten würde.
getTransactionCount kann auch ausstehende Transaktionen enthalten, wodurch die Nonce für eine nachfolgende Rohtransaktion besser bestimmt werden kann. Diese Lösung ist einfach, aber unwahrscheinlich ohne eigene Probleme. Aber für das Abfeuern einer Handvoll Transaktionen in enger Folge scheint es wie erwartet zu funktionieren.
nonce: web3.toHex(web3.eth.getTransactionCount(fromAddress, "pending")),
Es hängt alles von Ihrem Kontext ab. Wenn Sie ein Endbenutzer sind, der versucht, selbst mehrere Transaktionen auszuführen, können Sie die Nonce einfach irgendwo speichern und bei jeder parallelen Transaktion erhöhen. Natürlich möchten Sie vermeiden, Lücken in der Nonce zu schaffen, aber solange Sie zu 100 % sicher sind, dass Sie die Mittel decken können, wenn die Transaktionen ausgeführt werden, ist eine Lücke vorübergehend in Ordnung. Das Schlimmste, was passieren kann, ist, dass eine Nonce zweimal gespielt wird. In diesem Fall haben Sie ungültige Transaktionen erstellt.
Wenn Sie im Namen eines Benutzers handeln und versuchen, Massentransaktionen auszuführen, könnten Sie einfach eine atomare Datenbankoperation verwenden , um die Nonce zu speichern. Dies könnte in einer hypothetischen Batching-Wallet funktionieren, die versucht, mehrere Transaktionen gleichzeitig zu senden. Sie möchten wahrscheinlich einen Haftungsausschluss darauf setzen, dass ein Benutzer die Verwendung des Schlüssels vermeiden sollte , während er mit der Brieftasche interagiert, um zu verhindern, dass der interne Zähler nicht mehr synchron ist.
Linmao-Lied
Wächter
Böser Jordan
Linmao-Lied
Runen