Können wir davon ausgehen, dass Ethereum-Ereignisse (auch bekannt als Protokolle) der Reihe nach sind?

Betrachten wir einen einfachen Vertrag, der eine Variable verfolgen soll. Eine Client-App muss auf den Verlauf dieser Variablen zugreifen, um ein Diagramm anzuzeigen.

Ich kann ein Array innerhalb des Vertrags erstellen und push()den Wert jederzeit wie folgt (ungetesteter Code):

contract Price {
    uint[] public priceHistory;
    function logPrice(uint price) public {
        priceHistory.push(price);
    }
}

Vielleicht ist es eine billigere und bessere Option, Ereignisse ähnlich der folgenden auszugeben:

contract Price {
    event PriceChanged(uint price);
    function logPrice(uint price) public {
       emit PriceChanged(price);
    }
}

Gemäß (3) einer billigeren Form der Speicherung ist der zweite Ansatz kostengünstig. Meine Frage ist, können wir zuverlässig davon ausgehen, dass die Protokolle in zeitlicher Reihenfolge geschrieben werden (damit wir daraus eine Historie rekonstruieren können).

Die nächste Frage ist, wenn dieser Vertrag andere Verträge aufruft, die demselben Entwurfsmuster folgen (die gesamte Speicherung erfolgt in Protokollen), wie können wir eine Historie mit der richtigen Zeitordnung zusammenweben? dh das Einrichten ClientApp -> ContractA - ContractB -> ContractCaus dem Lesen von Ereignisprotokollen für alle drei Verträge.

Ein Gedanke könnte sein, Transaktions-Hash vom ersten user -> contractAufruf an bis zu nachfolgenden contract -> contractAufrufen weiterzugeben.

Wenn dies ein monolithisches System wäre, hätte timestamp helfen können. Aber da es sich um ein verteiltes System handelt, frage ich mich, wie wir hier den Begriff einer Sequenz etablieren ?

Antworten (2)

Ja, aber mit einigen Nuancen, damit die Garantien gut verstanden werden.

Ereignisprotokolleinträge sind Teil der Transaktionen in Blöcken. Als solches können Sie über Ereignissequenzzusicherungen mit den gleichen Prinzipien argumentieren, die Sie verwenden würden, um über die Transaktionsreihenfolge zu argumentieren. Sie werden in der gleichen Reihenfolge eintreffen wie die Transaktionsminen.

Die Idee, Ereignisprotokolle als kostengünstigen Speicher zu verwenden, wird manchmal als „zustandsloses“ Muster bezeichnet. Der Hauptvorbehalt besteht darin, dass solche Einträge für die Vertragslogik nicht (leicht) zugänglich sind.

Ich bin mir nicht 100% sicher, was das bedeutet:

ClientApp -> VertragA -> VertragB -> VertragC

  1. Wenn die Client-App drei Aufrufe zu drei Verträgen tätigt, gibt es keine Zusicherung der Bestellung, da das Mining entscheidet.
  2. Wenn der Client aufruft , der wiederum aufruft, ContractAdann ist es deterministisch und Sie können es in der Reihenfolge haben, in der die Funktionen aufgerufen wurden, oder in umgekehrter Reihenfolge, je nachdem, wie Sie die Vertragsfunktionen schreiben.ContractBContractC

Wenn Sie den Emitter des Ereignisses gewöhnlich zuerst platzieren, erhalten Sie „bereit (a), Ziel (b), Feuer (c). Alle drei Ereignisse kommen mit der bestätigten Transaktion in dieser Reihenfolge an.

emit LogReady(...
contractB.aim(...

Wenn Sie den Vertragsaufruf vor dem Ereignis platzieren, erhalten Sie Feuer (c), Bereit (b), Ziel (a) in dieser Reihenfolge, wenn die geschürfte Transaktion eintrifft.

contractB.aim(...
emit LogReady(...

Der zweite Weg ist intuitiver – erledige zuerst etwas und protokolliere dann, was du getan hast. Es führt zu eigenartigen (umgekehrten) Protokollen für lange Funktionsketten. Der erste Weg ist nicht so intuitiv, aber er ergibt eine schöne Sequenz, unabhängig davon, wie viele separate event LogName()Protokolle beteiligt sind.

Ich hoffe es hilft.

Danke Rob. Es bestätigt mein Verständnis, dass EVM die Kausalitätsabhängigkeit der Ereignisse aufrechterhält. Irgendwelche Gedanken zu meiner zweiten Frage hier ... wie erstelle ich eine Abfolge von Ereignissen für Vorgänge, die sich über mehrere Verträge erstrecken? Ist das Übergeben von txn-Hashes von ContA->ContB->ContC eine praktikable Lösung?
@Rob - Was meinst du mit "Es führt zu eigenartigen (umgekehrten) Protokollen für lange Funktionsketten." Können Sie das näher erläutern?
Es heißt "Feuer!", "Fertig!", "Zielen!" wenn eine Kette von Verträgen Ereignisse ausgibt, nachdem sie sich gegenseitig aufgerufen haben. Sie erhalten Protokolle wie „Received(1)“, gefolgt von „Sent(1)“. Gehen Sie "emittieren, rufen" statt "rufen, emittieren". Eine andere Möglichkeit, sich daran zu erinnern, besteht darin, das Ereignis als Zustandsänderung zu behandeln und es vor der Interaktion mit anderen Verträgen (Prüfungen, Effekten, Interaktionen) zu übernehmen.
@RobHitchens Kann die "eigenartige" Reihenfolge (zuerst interagieren, als zweites aussenden) zu Sicherheitsproblemen oder ungültigem Verhalten bei dApps führen, die mit dem Vertrag interagieren? Wenn eine dApp auf diese 3 Ereignisse ( Fire, Ready, Aim) reagiert, wie würde sich die umgekehrte Reihenfolge auf die Logik der dApp auswirken? Die Anwendung dieser „eigentümlichen“ Reihenfolge klingt eher so, als könnte sie den dApp-Code fehlerhaft machen oder sich auf unerwartete Weise verhalten und zu web2-Sicherheitsproblemen führen. Was sind Ihre Erkenntnisse zu den potenziellen Sicherheitsauswirkungen dieser eigentümlichen Emissionsreihenfolge?
Es wird die Sicherheit des Vertrages oder anderer Verträge nicht beeinträchtigen, aber es wird die Situation für die Client-Entwickler sicherlich nicht verbessern.

Ereignisse haben garantiert dieselbe Reihenfolge wie Transaktionen. (Es gibt eine gewisse Zufälligkeit in der Reihenfolge der Transaktionen aufgrund der Art und Weise, wie Transaktionen für das Mining von Nodes ausgewählt werden.)

Transaktionen werden bestellt

  1. Bei den Blöcken, zu denen diese gehören
  2. Transaktionsfolge innerhalb eines Blocks

Sie können

  1. Scannen Sie nach allen Blöcken und Transaktionen innerhalb der Blöcke
  2. Finden Sie Ereignisse, die von jeder Transaktion ausgegeben werden

Der Code dafür wird in folgendem Thread bereitgestellt: web3: How do I get past events of myContract.myEvent?

Es gibt eine gewisse Zufälligkeit in der Reihenfolge der Transaktionen aufgrund der Art und Weise, wie Transaktionen für das Mining von Knoten ausgewählt werden - ich frage mich, ob dies wirklich der Fall ist. Ich meine, eine Finanztransaktion reagiert so sensibel auf Bestellungen, dass selbst eine Transaktion, die nicht in Ordnung ist, das gesamte Hauptbuch inkonsistent machen würde.
Sobald eine Transaktion Teil des Hauptbuchs ist, ist die Ordnung garantiert. Mining ist der Prozess, der Transaktionen im Hauptbuch umfasst. Zum Vergleich mit der realen Welt, wenn ein Bankkonto nur 10 $ hat und 8 Transaktionen von jeweils 2 $ gleichzeitig eingereicht werden; Es wird eine gewisse Zufälligkeit darüber geben, welche dieser 8 Transaktionen abgelehnt werden.