Storage Trie – werden Trie-Knoten für zwei Vertragsinstanzen mit demselben Speicherinhalt wiederverwendet?

Wenn ich den Geth-Code und verschiedene Beiträge hier lese, glaube ich, dass ich jetzt ein gutes Verständnis dafür habe, wie die Daten in Ethereum gespeichert werden (bitte korrigieren Sie mich, wenn ich mich irgendwann irre).

Auf der untersten Ebene haben wir eine Key-Value-Datenbank

Auf der nächsten Ebene haben wir eine generische Datenstruktur namens trie

Und auf der Ethereum-Blockchain-Ebene haben wir so etwas wie (nur relevante Teile genannt):

block -> state trie -> account* -> storage trie

[Q1] : Für Zustandsversuche stellen die Pfade die Kontoadressen dar. Was sind die Pfade im Speicherversuch? Speicherindizes?

[Q2] : Wenn wir einen einfachen Vertrag der Form haben:

contract C {
    uint256 public x = 100;
}

Wenn wir zwei Instanzen dieses Vertrags instanziieren. Werden sie denselben Storage-Root-Hash haben? Wenn ja, teilen sie genau dasselbe Schlüssel/Wert-Paar in der Datenbank (auf der untersten Ebene) bzw. denselben Trie-Knoten im Speicher-Trie?

Antworten (2)

Bei Zustandsversuchen stellen die Pfade die Kontoadressen dar. Was sind die Pfade im Speicherversuch? Speicherindizes?

Das ist richtig, außer dass die Adressen und Indizes gehasht werden, bevor sie im Trie gespeichert werden. Dies geschieht zum Schutz vor DoS: Warum werden Schlüssel in Merkle Patricia Trie gehasht?

Wenn wir zwei Instanzen dieses Vertrags instanziieren. Werden sie denselben Storage-Root-Hash haben?

Ja.

werden sie genau dasselbe Schlüssel/Wert-Paar in der Datenbank (auf der untersten Ebene) bzw. denselben Trie-Knoten im Speicher-Trie teilen?

Ja, da der Trie-Stamm für beide Verträge gleich ist, teilen sie sich die Schlüssel/Werte in der zugrunde liegenden Datenbank. Es scheint zunächst kontraintuitiv oder unsicher zu sein, dass 2 Verträge "denselben Speicher teilen". Da die Trie-Struktur jedoch unveränderlich ist, wird immer dann, wenn ein neuer Eintrag zum Trie hinzugefügt wird, eine modifizierte Instanz mit eigener Wurzel erstellt. Der alte unmodifizierte Trie ist noch in der zugrunde liegenden Datenbank vorhanden und andere Verträge können immer noch darauf verweisen.

Sie können versuchen, 2 Verträge mit demselben Speicher zu erstellen und dann ihre Speicherwurzeln und Inhalte mit diesem nodejs-Code https://ethereum.stackexchange.com/a/40280/18932 zu lesen

Danke für die hervorragende Antwort! Ich habe das gefragt, weil ich es cool fände, einen neuen Vertrag mit dem Inhalt eines alten Vertrags instanziieren zu können. Wenn ich alles richtig verstehe, ginge es auf evm-Ebene nur darum, für den neuen Vertrag den gleichen Speicherstamm zu setzen, anstatt mit einem leeren Speicher zu beginnen. Das wäre ziemlich cooles Zeug aus der Perspektive der Upgradefähigkeit von Verträgen. Ich weiß, dass wir Delegatecall für die Aufrüstbarkeit verwenden können, aber IMHO ist der direkteste Weg, den Speicher schnell zu kopieren.
Ich denke technisch ist es möglich. Der knifflige Teil besteht darin, sicherzustellen, dass die neuen Vertragsvariablen auf die gleichen Slots wie die alten Vertragsvariablen zeigen. Wenn Sie z. B. 2 Felder im alten Vertrag hatten und dann 1 weiteres zwischen diesen 2 im neuen Vertrag hinzufügen, wird der Slot auf den 3. Platz verschoben Feld. Vielleicht kann es in Solidity irgendwie gelöst werden, indem Anmerkungen eingeführt werden.
Ja, sicher.. das gleiche Problem wie beim Delegiertenruf.

Verträge haben tatsächlich einen Speicher-Root-Hash und einen Code-Root-Hash (der weniger ein Root-Hash als vielmehr ein regulärer Hash ist, da Code ein Blob ist). Wenn zwei Verträge genau denselben Code und damit denselben Code-Hash haben, sollte der Blob, der diesem Hash entspricht, vom Knoten nur einmal in der Datenbank gespeichert werden, aber ich kann nicht sagen, ob dies tatsächlich der Fall ist oder nicht das.

Dasselbe gilt für den Status-Root-Hash eines Vertrags, aber da sich dieser von Block zu Block ändern kann, kann es in der db etwas komplizierter sein. Ich gehe davon aus, dass es nicht dupliziert wird, da die Datenbank größtenteils ein Schlüsselwertspeicher ist, aber ich kann mir nicht sicher sein.