# Delegationen

> Hashing, Körper- und Kurvenarithmetik haben eigene Schaltkreise. Welche SDK-Aufrufe sie erreichen, was sie kosten, die Regeln für ihre Operanden und die mitgelieferten Crates, die Bibliothekscode zu ihnen leiten.

Manche Berechnungen lassen sich mit einem eigens für sie gebauten Schaltkreis weit günstiger beweisen denn als Folge von RISC-V-Befehlen. Apogee nennt sie **Delegationen**. Eine Delegation ist eine Schaltkreisfamilie, die eine Funktion über einem Frame aus Wörtern im RAM beweist und über einen `ecall` aufgerufen wird, und das Guest-SDK setzt diese Aufrufe für Sie hinter gewöhnlichen Funktionen ab. Sie schreiben nie selbst einen `ecall`.

## Was Sie aufrufen und was es erreicht

| Sie rufen auf | Delegation | Ein Aufruf beweist |
| --- | --- | --- |
| `guest_sdk::keccak256(&[u8]) -> [u8; 32]` | `KECCAK_F` | eine Runde von keccak-f[1600]; eine Permutation sind 24 Aufrufe, und Sponge und Padding sind Code des Gastprogramms (Guest) |
| `guest_sdk::sha256(&[u8]) -> [u8; 32]` | `SHA256_COMP` | vier Runden der Kompression; eine Kompression sind 16 Aufrufe |
| `guest_sdk::ec_add`, `ec_mul`, `ec_identity` | `EC_ADD` | ein Drittel einer vollständigen Punktaddition auf secp256k1 oder BN254 G1 |
| `guest_sdk::poseidon2_permute(&mut [u8; 96])` | `POSEIDON2` | eine Poseidon2-Permutation der Breite 3 über `Fr` |
| `field::Fr`: Addition, Multiplikation, Inversion | `FR_ARITH` | eine `Fr`-Operation, auf dem Target der Gastprogramme, ohne dass etwas benannt werden muss |
| `transcript::poseidon2_permute` | `POSEIDON2` | dieselbe Permutation, über das Transkript-Crate |
| `guest_sdk::recursion::mod_mul` über einem `ModMulFrame` | `MOD_MUL` | ein 256-Bit-`a·b mod m`, wobei `m` einer von vier Ethereum-Moduln ist |

Die Funktionen sind bitgenau identisch mit ihren Software-Definitionen. `keccak256` ist das Keccak von Ethereum, nicht SHA3-256. `sha256` ist FIPS 180-4. `ec_add` verwendet die vollständige Formel von Renes, Costello und Batina (2015, Algorithmus 7); Verdopplung, `P + (−P)`, das neutrale Element und jedes `Z` brauchen also keinen Sonderfall.

```rust title="Hashing und Kurvenarithmetik aus einem Gastprogramm"
use guest_sdk::{ec_mul, keccak256, recursion::SECP256K1_GROUPS, ProjectivePoint};

let digest: [u8; 32] = keccak256(b"blockchain-native");

// A point is homogeneous projective (x = X/Z, y = Y/Z), each coordinate eight
// little-endian u32 limbs below the field modulus. The scalar is eight limbs too.
fn times(p: &ProjectivePoint, k: &[u32; 8]) -> ProjectivePoint {
    ec_mul(&SECP256K1_GROUPS, p, k).expect("EC_ADD is implemented on Apogee")
}
```

## Auch Bibliothekscode erreicht sie

Der Gastprogramm-Workspace patcht drei Crates so, dass der Code in ihnen auf dem Target der Gastprogramme Delegationen aufruft, mit dem Upstream-Code als Fallback-Pfad:

| Crate | Version | Erreicht |
| --- | --- | --- |
| `k256` | 0.13.4 | `MOD_MUL` aus Körper- und Skalarmultiplikation; `EC_ADD` aus Addition, gemischter Addition und Verdopplung von `ProjectivePoint` |
| `ark-ff` | 0.6.0 | `MOD_MUL` aus der Montgomery-Multiplikation und -Quadrierung von BN254, in beiden seiner Körper |
| `revm-precompile` | 43.0.2 | `SHA256_COMP` für das Precompile `0x02`; `EC_ADD` für `0x06` und `0x07` |

Ein Gastprogramm, das von diesen Crates abhängt, erhält die gepatchten Kopien automatisch über das `[patch.crates-io]` in `guests/Cargo.toml`. Ungepatcht machten allein die Körpermultiplikation und -quadrierung von `k256` 44 % der Zyklen eines Mainnet-Blocks aus. Die secp256k1-Signatur-Recovery ist gewöhnlicher `k256`-Code, den die Patches in delegierte Arithmetik verwandeln.

## Was eine Delegation kostet

Eine Delegationsfamilie ist nur dann Teil eines Programms, wenn das Programm einen ihrer Shims linkt, und ein Aufruf kostet Shards der Höhe dieser Familie:

- **Gelinkt und nie aufgerufen: nichts.** Die Familie ist deklariert und beweist null Shards.
- **Einmal aufgerufen: ein ganzer Shard.** Ein Shard kostet seine volle Höhe, unabhängig von seiner Belegung.
- **Oft aufgerufen: sehr wenig pro Aufruf.** Der Beweis eines Shards wächst mit dessen Höhe nur um eine Sumcheck-Runde pro Variable.

| Familie | Höhe | Arbeitseinheit | Aufrufe pro Einheit | Einheiten pro Shard |
| --- | --- | --- | --- | --- |
| `KECCAK_F` | `2^18` | keccak-f[1600] | 24 | 10.922 |
| `SHA256_COMP` | `2^18` | eine Kompression | 16 | 16.384 |
| `EC_ADD` | `2^16` | eine vollständige Addition | 3 | 21.845 |
| `MOD_MUL` | `2^16` | ein `a·b mod m` | 1 | 65.536 |
| `POSEIDON2` | `2^8` | eine Permutation | 1 | 256 |
| `FR_ARITH` | `2^8` | eine `Fr`-Operation | 1 | 256 |

Der Preis ist eher Speicher als Zeit: Der Vorwärtsdurchlauf eines `KECCAK_F`-Shards der Höhe `2^18` hält etwa 42 GiB an Körperelementen, und zwei davon, gleichzeitig in Bearbeitung, bestimmten die Spitze des gemessenen Ethereum-Blocks.

## Regeln für Operanden

- **Operanden unterhalb ihres Moduls.** Ein Operand von `MOD_MUL` oder `EC_ADD`, der den Modul, den sein Selektor benennt, erreicht oder übersteigt, hat keinen Beweis: Der Executor weist den Frame als fatalen `DelegationFrame`-Fehler zurück. Das mitgelieferte `k256` reduziert seine verzögert reduzierten Körperelemente vor dem Aufruf.
- **Punkte werden nicht für Sie geprüft.** `EC_ADD` beweist die Arithmetik der Formel. Ob ein Punkt auf der Kurve liegt, ist eine Frage an den aufrufenden Code, und ein Gastprogramm, das Punkte aus Hilfsdaten (Advice) übernimmt, muss sie stellen.
- **Operationen aus mehreren Aufrufen sind jeweils eine SDK-Funktion.** Eine Keccak-Permutation sind 24 Aufrufe auf einem Frame, eine SHA-256-Kompression 16, eine Punktaddition 3. Jeder Aufruf beweist seinen eigenen Schritt, und nichts weist eine falsche Reihenfolge zurück: Es wird dann schlicht etwas anderes berechnet. Verwenden Sie `keccak256`, `sha256` und `ec_add`, die die Aufrufe in der richtigen Reihenfolge absetzen, statt der rohen Shims.
- **Exit 72** bedeutet, dass eine Delegation etwas geantwortet hat, das ihr Shim zurückweist. Auf dem eigenen Executor von Apogee kommt das bei einem wohlgeformten Frame nicht vor.

## Was nicht delegiert wird

- `MULMOD` der EVM mit beliebigem Modul, `MODEXP`, BLS12-381 und jedes Primitiv außerhalb der obigen Tabelle laufen als Befehle.
- Kein Signaturverfahren und kein Pairing wird als Ganzes delegiert. Die secp256k1-Recovery ist `k256` über `MOD_MUL` und `EC_ADD`; ein BN254-Pairing ist `ark-bn254` über `MOD_MUL`.
- Eine Delegation ist der Kern einer Operation. Padding, Sponges, Blockschleifen und die Leiter einer Skalarmultiplikation sind Code des Gastprogramms und werden als Befehle bewiesen.

Signaturverfahren für Gastprogramme stehen auf der [Roadmap für v2.0.0](https://apogee.gweb3networks.com/docs/quantum-leap/signatures).

## Lohnt sich eine neue Delegation?

Der Zyklus-Profiler bepreist die naheliegenden Kandidaten in jedem Bericht, als Obergrenze der Zyklen, die eine Delegation einsparen könnte:

```text
removable = max(0, cycles − calls·(4 + 2·frame_words))
```

`cycles` ist der Anteil der Kategorie am Lauf, `calls` die Zahl der Einsprünge in die Funktionen des Kandidaten und `4 + 2·frame_words` der Shim, den eine Delegation zurücklassen würde: die Schreibzugriffe für den Frame, der `ecall` und die Lesezugriffe für das Ergebnis. Die Formel veranschlagt nichts für die Shards der neuen Familie; behandeln Sie sie also als obere Schranke. [Ausführen und profilieren](https://apogee.gweb3networks.com/docs/launch/run#profiler) zeigt einen Bericht.

Die Spezifikation jeder Delegation, Spalte für Spalte, steht unter [Delegationsschaltkreise](https://apogee.gweb3networks.com/docs/auditors/spec/delegation-circuits).
