# Architektur

> Apogee VM von Anfang bis Ende. Was ein Beweis aussagt, der Weg von einem Gastprogramm-Binary zu einem Contract-Aufruf, wie die großen Komponenten zusammenspielen und welche Designentscheidungen sie prägen.

Apogee beweist Ausführungen von RV32IMAC-Programmen. Dieser Abschnitt beschreibt das System auf der Ebene seiner großen Komponenten: was jede davon tut, warum sie so gebaut ist, wie sie gebaut ist, und wie sie an die nächste übergibt. Der Abschnitt [Auditoren](https://apogee.gweb3networks.com/docs/auditors) enthält dasselbe System auf der Ebene jeder Spalte und jedes Gates.

## Was ein Beweis aussagt

Ein Verifier besitzt drei Dinge, die er nicht auf das Wort des Provers hin übernimmt:

- die **Programmidentität**, ein einziges Körperelement, das die Befehlstabellen des Programms, sein anfängliches Speicher-Image, seinen Einsprung-pc und seine Konfiguration zu einem Digest verdichtet;
- den **SRS-Digest** der Zeremonie, den ein Verifikationsschlüssel tragen muss;
- einen **Verifikationsschlüssel**, der von beliebiger Seite stammen darf, weil beim Laden die Identität und der SRS-Digest aus seinem eigenen Inhalt neu berechnet und seine Schaltkreise mit der Registry des Verifiers abgeglichen werden.

Die Aussage des Beweises enthält die öffentliche Eingabe, die öffentliche Ausgabe (das **Journal**), den Exit-Status und die Aufzeichnung der Form der Ausführung: die Shard-Zahlen, die Speicherfenster, die finalen Register und den finalen pc sowie die Speicher-Commitments und Wurzeln jedes Shards. Ein Beweis, der die Verifikation besteht, begründet, dass das Programm dieser Identität, gestartet an seinem Einsprung-pc auf seinem Image, mit der öffentlichen Eingabe in seinem Eingabefenster und irgendwelchen vom Prover gewählten Hilfsdaten (Advice), Befehl für Befehl bis zu `EXIT` mit diesem Status ausgeführt wird und dabei dieses Journal geschrieben hat. Über die Hilfsdaten wird nichts behauptet, und nichts wird verborgen: Kein Commitment und kein Beweis ist verblindet.

## Vom Binary zum Contract-Aufruf

> Figure: Die vier Stufen. Das Programm steht fest, bevor irgendetwas läuft; die Ausführung wird in Shards geschnitten; jeder Shard wird für sich bewiesen, mit Ausnahme des Speicherarguments, das sich einmal über alle Shards schließt; die Abwicklung komprimiert den Block für einen Contract.

1. **Das Programm.** Der Loader liest das ELF in ein `ProgramImage` ein und expandiert dabei komprimierte Befehle an Ort und Stelle. Der Decoder ordnet jeden Befehl einer von sieben Befehlsfamilien zu, baut die dekodierte Tabelle jeder Familie mit einer Zeile pro Halbwort Code und committet dann all das als Programmidentität. [Programme und Identität](https://apogee.gweb3networks.com/docs/architecture/program).
2. **Ausführung.** Der Emulator führt das Gastprogramm (Guest) auf einem Hart aus. Ein Zyklus ist eine Zeile der Familie, der sein Befehl gehört, und zeichnet mit Zeitstempeln versehene Lese- und Schreibzugriffe auf pc, Register und RAM auf. Hashing und Arithmetik mit großen Ganzzahlen werden delegiert: Ein `ecall` benennt einen Frame im RAM, und eine Zeile einer Delegationsfamilie erledigt die Arbeit darauf. [Ausführung, Familien und Shards](https://apogee.gweb3networks.com/docs/architecture/execution).
3. **Shards.** Die Zeilen einer Familie werden in Shards der Höhe dieser Familie geschnitten, einer Zweierpotenz zwischen `2^8` und `2^22`. Den Speicher, den eine Ausführung berührt, decken Shards der Fensterfamilien ab, die jedem Wort seinen Anfangs- und seinen Endwert geben. Ein Shard ist die Einheit des Beweisens; ein Block umfasst Hunderte davon.
4. **Der Beweis eines Shards.** Seine Spalten werden mit [Mercury](https://apogee.gweb3networks.com/docs/architecture/mercury) committet. Den Schaltkreis der Familie durchläuft die [GKR-Engine](https://apogee.gweb3networks.com/docs/architecture/gkr) rückwärts, von seinen Ausgaben bis zu diesen Spalten, mit einem Sumcheck pro Schicht, und jede Spalte wird an dem einen Punkt, an dem dieser Durchlauf endet, in einer einzigen gebündelten Öffnung geöffnet.
5. **Der Block.** Ein `BlockProof` besteht aus der Aussage und ihren Shard-Beweisen. Die Verifikation führt einmal das globale Transkript, die Prüfungen jedes Shards und einmal den [Speicherabgleich](https://apogee.gweb3networks.com/docs/architecture/memory-lookups) über die Wurzeln aller Shards aus.
6. **Rekursion und Abwicklung.** Verifier-Programme, die Apogee selbst beweist, verifizieren Reihen von Shards und falten deren aufgeschobene Pairings. Ein Baum aus ihnen endet in einer Wurzel, ein Groth16-Schaltkreis verifiziert die Wurzel erneut, und `ApogeeVerifier.sol` prüft diesen Beweis und das gefaltete Pairing. [Rekursion und Abwicklung](https://apogee.gweb3networks.com/docs/architecture/recursion).

Der Prover führt das Gastprogramm zweimal aus: einmal, um die Speicherspalten jedes Shards zu committen, was die Aussage und ihre Challenges festlegt, und einmal, um jeden Shard zu beweisen, sobald er gefüllt ist. Sein Speicherbedarf ist durch die gleichzeitig bearbeiteten Shards beschränkt, nicht durch die Länge der Ausführung. [Der Streaming-Prover](https://apogee.gweb3networks.com/docs/architecture/streaming).

## Die Entscheidungen, die das System prägen

**Ein Körper, eine Kurve.** Alles liegt über dem Skalarkörper von BN254: die Schaltkreise, das Transkript, die Commitments und die Rekursion. Deshalb kann ein Knoten des Rekursionsbaums Basis-Shards in seiner eigenen Arithmetik verifizieren, und deshalb kann der Baum in einem Groth16-Beweis enden, den Ethereum mit seinem Pairing-Precompile prüft.

**Geschichtete GKR-Schaltkreise statt committeter Constraint-Tabellen.** Der Schaltkreis einer Familie ist ein Stapel von Gate-Schichten vom Grad 2 über ihren committeten Spalten. Nur die unterste Schicht wird committet; jede Schicht darüber wird in einem einzigen Rückwärtsdurchlauf per Sumcheck bewiesen und nie committet. Der Durchlauf endet mit Behauptungen über jede committete Spalte an ein und demselben Punkt; ein Shard braucht also genau eine Öffnung. [Die GKR-Engine](https://apogee.gweb3networks.com/docs/architecture/gkr) erklärt, warum darin die zentrale Ersparnis der Engine liegt.

**Eine Öffnung konstanter Größe.** Mercury öffnet ein multilineares Commitment mit acht Kurvenpunkten und sechs Körperelementen, 704 Byte, unabhängig von der Größe des Polynoms und davon, wie viele Spalten sich den Punkt teilen. Seine Prüfungen haben die Form `e(A, [1]_2) = e(B, [x]_2)`, die die Rekursion falten kann, statt Pairings zu berechnen.

**Ein Speicherargument für die gesamte Ausführung.** Jeder Zugriff, in jedem Shard jeder Familie, ist ein Tupel in einer einzigen Lese-/Schreib-Multimenge, und der Verifier gleicht die Produkte einmal pro Aussage ab. Der pc ist eine Zelle dieser Multimenge; Reihenfolge, Kontinuität und Eindeutigkeit der Zyklen über Shards hinweg brauchen also kein weiteres Argument, und kein Shard muss sich mit seinem Nachbarn verketten.

**Delegationen als Familien, nicht als Befehle.** Eine teure Funktion erhält eine eigene Schaltkreisfamilie, aufgerufen durch einen `ecall` über einem Frame aus RAM und über dieselbe Multimenge eins zu eins mit ihrer Anfrage gepaart. Die Befehlsschaltkreise bleiben klein, und ein Gastprogramm bezahlt für eine Delegation nur, wenn es sie aufruft.

**Streaming statt Materialisierung.** Der Trace wäre mit etwa 300 Byte pro Zyklus das größte Objekt im System; deshalb existiert er nie. Der Prover führt zweimal aus und hält nur die Shards, die gerade bearbeitet werden.

**Keine geliehene Kryptografie.** Körper, Kurve, Pairing, MSM, Hash, Polynom-Commitment, GKR und Groth16 sind im Repository implementiert und Seite für Seite spezifiziert. arkworks, Plonky3 und zkhash kommen nur als Testorakel vor.

## Wie sich die Soundness zusammensetzt

Der GKR-Durchlauf und die Öffnung jedes Shards binden die Ausgaben seines Schaltkreises an committete Spalten. Darüber hinaus erstrecken sich diese Argumente über die gesamte Ausführung:

| Behauptung | Getragen von |
| --- | --- |
| Jede Zeile befolgt ihren Befehl | den Constraint-Gates des Familienschaltkreises, null auf jeder Zeile |
| Der Befehl einer Zeile ist der des Programms an ihrem pc | einem Lookup von pc und Feldern der Zeile in der dekodierten Tabelle der Familie, die die Identität committet |
| Jeder Lesezugriff liefert den letzten Schreibzugriff | einer einzigen Multimenge über alle Shards; der Verifier multipliziert die Lese- und Schreibwurzeln jedes Shards mit Randfaktoren für die Register und den pc |
| Die Zeilen bilden einen einzigen Pfad vom Einsprung-pc zum Exit, in Programmreihenfolge | dem pc als Zelle dieser Multimenge, die mindestens vier Zeitstempel nach ihrem Lesen geschrieben wird |
| Ein Wert ist ein Byte, ein Wort, ein Vorzeichen, ein XOR | LogUp-Kanälen über Bereichs-, Byte- und generischen Tabellen |
| Die öffentliche Eingabe und das Journal sind die behaupteten Bytes | den Anfangs- und Endspalten der beiden öffentlichen Fenster, gebunden an die multilinearen Erweiterungen der Bytes |
| Eine delegierte Berechnung ist die der Funktion | Aufrufzeilen, die den Frame über dieselbe Multimenge lesen und schreiben, eins zu eins mit ihrem `ecall` gepaart |

Die Challenges stammen aus einem Poseidon2-Duplex-Transkript. Das globale Transkript absorbiert die gesamte Aussage, einschließlich der Speicher-Commitments jedes Shards, bevor es die Speicher-Challenges gibt; das Transkript jedes Shards wird aus dem Endzustand des globalen Transkripts initialisiert. Die [Soundness-Karte](https://apogee.gweb3networks.com/docs/auditors/soundness-map) führt jede Zeile dieser Tabelle bis zu den Abschnitten, die sie beweisen.

## Der Code, nach Schichten

| Schicht | Crates | Rolle |
| --- | --- | --- |
| Arithmetik | `field`, `curve`, `poly`, `sumcheck` | `Fr`; der `Fq`-Turm, G1, G2, das Pairing, MSM; multilineare Polynome; der Zerocheck |
| Fiat–Shamir und Setup | `transcript`, `srs` | Poseidon2 und das Duplex-Transkript; Einlesen der Zeremonie, KZG, Phase 1 von Groth16 |
| Commitments | `pcs`, `pcs-verify` | Mercury und seine aufgeschobene Verifikation |
| Das Programm | `loader`, `isa`, `program` | ELF zu Image, der Decoder, dekodierte Tabellen, `VmConfig` und Identität |
| Ausführung | `emulator`, `trace` | der Executor und seine Tracer; Zeilen, Speicherzustand, Spalten-Builder |
| Schaltkreise | `constraints`, `gkr-verify`, `gkr` | jeder Schaltkreis als Daten; der GKR-Verifier und der GKR-Prover |
| Beweis und Verifikation | `verifier-core`, `verifier`, `prover` | Aussage, Transkripte, Schlüssel, jede Prüfung; der Streaming-Prover |
| Abwicklung | `host`, `groth16`, `contracts/` | das Host-SDK, der Rekursionsbaum und der Decider; `ApogeeVerifier.sol` |
| Absicherung | `checker`, `tools/` | unabhängige Validatoren, die Manipulations-Suite, Benchmarks, Profiler, Orakel |

Der Verifier ist die einzige Partei, der vertraut wird: Der Prover validiert nichts, und eine falsche Eingabe führt bei einem ehrlichen Prover zu einem Beweis, der fehlschlägt. [Das Sicherheitsmodell](https://apogee.gweb3networks.com/docs/architecture/security) führt genau auf, auf welchen Crates die Soundness beruht.
