Ist es möglich zu überprüfen, ob die Blocknummer des Client-Knotens mit der besten (neuesten) Blocknummer der Blockchain übereinstimmt?

Ich habe eine sortierte verknüpfte Liste, die ungefähr 1000 Elemente enthält. Wenn ich einen neuen Artikel erhalte, ist es mein Ziel, den Artikel in die Liste zu verschieben, wobei die sortierte Reihenfolge beibehalten wird. Wenn ich also einen sehr kleinen Wert erhalte, muss ich die gesamte Liste durchlaufen, um das Ende der Liste zu finden. Ich habe vorgeschlagen, dass ich den Index über eine konstante Funktion abrufen könnte und meine Transaktionsfunktion den zurückgegebenen Indexwert verwenden könnte, um das Element an die richtige Position zu verschieben, ohne Gas auszugeben, um die Liste zu durchlaufen.

Mein Ziel ist es, diesem Leitfaden ( https://ethereum.stackexchange.com/a/13855/4575 ) zu folgen , um eine konstante Funktion aufzurufen und ihren Rückgabewert an eine Transaktionsfunktion zu senden.

getIndex() => constant 
setArray() => transaction

setArray( getIndex() );

Es stellt sich folgende Frage: Wenn ich eine konstante Funktion auf meinem Client-Knoten aufrufe, ist es möglich zu überprüfen, ob die Blocknummer meines Client-Knotens die beste Blocknummer ist oder hinterherhinkt. Wenn es zurückliegt, kann die konstante Funktion falsche Informationen zurückgeben.

Zum Beispiel ist der beste Block der Blockchain 100. Aber mein Knoten befindet sich derzeit bei blockNumber 90 (im Grunde hinter der Blockchain). Wenn also der Client-Knoten den Index der Liste bis zu den ersten 90 Blöcken erhält und Elemente vermisst, die auf den verbleibenden 10 Blöcken generiert wurden.

[F] Ist es möglich zu überprüfen, ob die Blocknummer des Client-Knotens mit der besten Blocknummer der Blockchain übereinstimmt, die die neueste Blocknummer ist?

Wie Sie auf dem Beispielbild sehen können, kann die Blocknummer auf den Client-Knoten variieren. Die beste Blocknummer ist 1.002.312, aber die Blocknummer ist 1.002.304 auf dem Knoten oben. Aber manchmal sind alle Knoten auf der neuesten Blocknummer. Daher ist es schwierig, dem Verhalten des Knotens zu vertrauen.

Geben Sie hier die Bildbeschreibung ein

Folgende Antwort scheint zu funktionieren:

web3.eth.syncing;
sync.highestBlock

Aber die zurückgegebene highestBlockNummer scheint immer noch ein paar Blöcke kleiner zu sein als meine beste Blocknummer in meiner privaten Kette. Handelt es sich um einen Normalfall?

Antworten (3)

Ethereum ist ein probabilistisches System.

Meiner Meinung nach gibt es einfach keine Möglichkeit, sicher zu sein, dass man den letzten Block betrachtet, der es letztendlich in die längste Kette schafft, mit verschwindend geringer Wahrscheinlichkeit, dass eine Kettenreorganisation die Dinge neu ordnet. Daher glaube ich nicht, dass das Vertrauen auf einen Kundenzeugen ein guter Weg ist, um einen Sortierprozess zu informieren.

Ich glaube fest an das Prinzip, dass ein Smart Contract die Integrität der internen Datenspeicherung gewährleisten muss. Wenn die Daten in sortierter Reihenfolge zugänglich sein müssen (nicht unbedingt ein On-Chain-Anliegen), dann liegt die Reihenfolge der Daten im Rahmen der „garantierten internen Integrität“.

Aus diesem Grund muss das Vertrauen auf korrekte Informationen aus den von call()Ihnen beschriebenen und die Notwendigkeit, dass sie aktuell sind, verschwinden . Es ist eine inakzeptable externe Abhängigkeit und wahrscheinlich nicht zufriedenstellend lösbar.

Betrachten Sie drei allgemeine Ansätze

  • Füge "Bob" ein
  • Füge "Bob" nach "Alice" ein
  • Fügen Sie "Bob" neben "Alice" ein

Die erste erfordert möglicherweise eine beträchtliche Tiefe bei der internen Suche und lässt sich nicht gut skalieren. Der zweite Ansatz ist auf verlässliche Informationen von außen angewiesen; Zuverlässigkeit können wir wahrscheinlich nicht erreichen. Der dritte Ansatz setzt auf einen Hinweis zur Gaseffizienz, überlässt es aber dem Vertrag, die endgültige, richtige Entscheidung zu treffen.

"In der Nähe" ist im Grunde ein Vorsprung beim Suchvorgang. Wichtig ist, dass der Vertrag die Suche abschließt und seine eigenen Schlussfolgerungen darüber zieht, wo und wie „Bob“ angesichts des aktuellen Stands der geordneten Liste einzufügen ist. Jede Liste in jedem Zustand in jedem Block auf jeder Kette müsste korrekt geordnet sein, da sie nicht von einer präzisen externen Anleitung abhängig ist.

Zusammenfassend:

Ich würde erstmal überlegen, ob die Sorte wirklich unbedingt an der Kette sein muss.

Wenn die Sortierung unvermeidbar ist, organisieren Sie im Vertrag eine sortierte verkettete Liste oder ein ähnliches Indexschema. Der Vertrag allein sollte die korrekten Einfügepunkte bestimmen. Ein "Hinweis" kann die dafür erforderliche interne Suche reduzieren, wodurch die Benzinkosten gesenkt werden und sichergestellt wird, dass der Prozess mit einer Liste beliebiger Größe funktioniert.

Ich hoffe es hilft.

Dasselbe Problem, aber mit einem anderen Szenario. Stellen Sie sich vor, ich habe auf meinem Knoten einen Artikel gekauft. Als Zeitstempel möchte ich die höchste Blocknummer verwenden. Der Knoten weist den Zeitstempel als blk.num zu, aber seine lokale Blocknummer ist möglicherweise kleiner als die höchste Blocknummer. Der Zeitstempel des Kaufs kann also früher angezeigt werden, da die blk.num des Knotens zurückliegt. In diesem Fall ist mein externer Algorithmus nicht in der Lage, dem Zeitstempel als Blocknummer als Kaufzeit zu vertrauen. Grundsätzlich unterscheidet sich der Zeitstempel jedes Knotens als block.number zum Zeitpunkt T voneinander, wobei der Zeitstempel von blk.num nicht vertrauenswürdig ist. @Rob Hitchens
Sie scheinen darüber nachzudenken, dass der Knoten unabhängig handelt und besondere Befugnisse über die Transaktion hat. Es tut nicht. Der Knoten, der zum Übermitteln der Transaktion an das Netzwerk verwendet wird, ist lediglich ein Glied in einer Kommunikationskette. Es hat keine besonderen Privilegien oder besonderen Einfluss auf das Ergebnis der Transaktion. Die block.number kann nicht falsch sein. Es stimmt mit der block.number überein, wenn die Transaktion vom Netzwerk abgebaut wird. Da Miner einen gewissen Spielraum haben, wann sie eine Transaktion einbeziehen, ist sie nur lose mit der Einreichungszeit gekoppelt, aber sie ist unbestreitbar korrekt in Bezug auf das, was sie darstellt.
Unabhängig von einer Transaktion möchte ich, dass der Knoten anstelle seiner lokalen Blocknummer die höchste Blocknummer aus der Blockchain erhält. web3.eth.syncing;funktioniert nicht immer und wenn es keine gültigen Informationen zurückgibt, kann sich die neueste Nummer der Blockchain auch ändern, bis eine gültige Information zurückgegeben wird. Ethereum ist ein probabilistisches System, wie Sie sagten, ich kann es kaum erwarten, wann genau das Netzwerk antwortet, denke ich. Entschuldigung für zu viele Fragen... @RobHitchens
Danke für diesen Beitrag. Es war insofern nützlich, als es mich indirekt zu einer anderen Schlussfolgerung führte, und Sie werden meine kleine Debugging-Geschichte vielleicht interessant finden. Ich habe hier einen Tweet-Thread darüber geschrieben , den ich für falsch befunden habe, dann hier einen Folge-Tweet-Thread . Das Leben als Blockchain-Entwickler im Umgang mit Heisenbugs in der Produktion! 😉
Ich bin mir nicht sicher, ob es hilfreich ist oder eine weitere Ebene der Verwirrung hinzufügt. Beim OP geht es um einen Beobachter und Annahmen über den Zustand beim Einfügen einer Transaktion in die Kette. Der Beobachter wird immer nur wissen, was er weiß, und nicht wissen, was er nicht weiß. Und der Zustand wird sich möglicherweise ändern, bevor eine Transaktion abgebaut wird. On-Chain, in Verträgen ist die Zeit immer „jetzt“ und der Zustand ist immer aktuell. Dies gilt in Ketten von Verträgen, die sich gegenseitig anrufen. Es gibt einen Zustand und Dinge passieren im Kontext dieses Zustands, aber das Wissen der Beobachter hinkt immer hinterher.

Ja, es ist möglich zu prüfen, ob die Blocknummer mit der besten (neuesten) Blocknummer der Blockchain übereinstimmt.

Die Schritte wären

  1. Fragen Sie eine öffentliche Blockchain-API ab, um die neueste Blocknummer zu erhalten
  2. Prüfung gegen Kundenblock Nr.

Der Teil der Übermittlung der Transaktion erfordert einige Änderungen in der Kern-/API-Schicht.

Wie kann ich eine öffentliche Blockchain-API abfragen? Wenn ich über eine Vertragsfunktion eine Funktion aufrufe, die block.number zurückgibt, wie ich es verstehe, sollte die neueste Blocknummer zurückgegeben werden. Ich habe nicht verstanden, was Sie mit "Änderungen in der Kern-/API-Schicht" gemeint haben. @niksmac
@Avatar etherscan.io/blocks Hier ist eine öffentliche Informationstafel, diese Seite zeigt den höchsten (besten) Block aus seiner Perspektive.
Ich arbeite an einer privaten Kette, daher hilft mir der Link etherscan.io/blocks nicht. Ich ziehe es auch vor, den Wert von einem Funktionsaufruf zu erhalten, ohne in eine GUI zu schauen. @Yuanfei Zhu
Könnte die öffentliche Blockchain-API eine konstante oder nicht konstante Funktion sein? Da die Konstante aus ihren lokalen Daten liest, hilft es nicht. @niksmac
@Avatar wie könnte das konstant sein? das ist die Nummer des letzten Blocks, oder? Die Informationen von Yuanfei Zhu sind korrekt.
Entschuldigung, ich habe falsch identifiziert: call function == constant* function @niksmac
Ich persönlich halte es für sehr wichtig, eine scharfe Unterscheidung zwischen „können Sie es tun“ und „können Sie es dezentral tun“ zu machen. Als Antwort auf die erste Frage: "Ja, verwenden Sie die öffentliche API eines Blockchain-Explorers" (obwohl dies in diesem Fall nicht funktioniert). Auf die zweite Frage (vollständig dezentralisiert) lautet die einzige Antwort: "Die höchste Blocknummer in einem vollständig dezentralisierten Sinne IST der Block, der von Ihrem lokalen Knoten zurückgegeben wird." Meine Sorge ist, dass Antworten wie diese diese Unterscheidung vollständig auslöschen. Wenn man auf eine zentrale Lösung zurückgreifen will, warum überhaupt eine Blockchain?
@Thomas Jay Rush: Ihr Punkt ist richtig. In meinem Fall verwende ich eine private Kette, die wenige Knoten hat und das Netzwerk dazu zwingt, sehr zerbrechlich zu sein. Knoten also meine paar Blöcke hinter der höchsten Blocknummer. Siehe hier: ethereum.stackexchange.com/q/15310/4575

Die RPC-API hält Ihnen den Rücken frei.

Verwenden Sie einfach diese Funktion, um Ihren letzten Block und den des Kunden zu überprüfen. Je nachdem, wie sehr Sie dem Client vertrauen möchten, können Sie die Werte auf der Client-Seite vergleichen oder sicherstellen, dass sie ohne Manipulation an Sie zurückübertragen werden.

Funktion zum Abrufen des neuesten Blocks:

web3.currentProvider.sendAsync({
  method: "eth_blockNumber",
  params: [],
  jsonrpc: "2.0",
  id: 83
} function (error, result) {...})

Weitere Details zur JSON-RPC-API und wie Sie sie auf vielfältige Weise verwenden können (z. B. mit curl): Hier

Sie können übrigens curl verwenden, um die aktuelle Blockierung des Clients aus der Ferne zu überprüfen, ob seine Knoten- und Firewall-Einstellungen die Verbindung zulassen.

Vergessen Sie natürlich nicht, das Ergebnis in eine Dezimalzahl umzuwandeln, parseInt(value, 16).

Ein Beispiel zur Implementierung solcher web3-Funktionen finden Sie hier.

Ich habe Ihren Vorschlag ausprobiert curl --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":83}' -X POST localhost:8545. Dies gibt auch die aktuelle Blocknummer des Knotens zurück, nicht die höchste erreichte Blocknummer. Das Erhalten der Blocknummer des Kunden ist nicht das Problem, aber es kann hinter der höchsten Blocknummer liegen. @NikitaFuchs
Tun Sie dies einfach mit einem Knoten, dem Sie vertrauen, dass er sich auf der neuesten Blocknummer befindet, dann haben Sie etwas zum Vergleichen. Das wollte ich mit meiner ursprünglichen Antwort sagen.