Auf Solana wird ein Smart Contract als Programm bezeichnet. Ein Programm ist ein zustandsloses Konto, das ausführbaren Code enthält. Dieser Code ist in Funktionen organisiert, die Anweisungen genannt werden. Benutzer interagieren mit einem Programm, indem sie eine Transaktion senden, die eine oder mehrere Anweisungen enthält. Eine Transaktion kann Anweisungen aus mehreren Programmen enthalten.
Wenn ein Programm bereitgestellt wird, verwendet Solana LLVM, um es in ein ausführbares und verknüpfbares Format (ELF) zu kompilieren. Die ELF- Datei enthält die Programmbinärdatei im Solana Bytecode Format (sBPF) und wird on-chain in einem ausführbaren Konto gespeichert.
sBPF ist Solanas angepasste Version des eBPF Bytecodes.
Programme schreiben
Die Mehrheit der Programme wird in Rust geschrieben, mit zwei gängigen Entwicklungsansätzen:
- Anchor: Anchor ist ein Framework, das für schnelle und einfache Solana-Entwicklung konzipiert wurde. Es verwendet Rust-Makros, um Boilerplate-Code zu reduzieren – ideal für Anfänger.
- Native Rust: Programme in Rust schreiben, ohne Frameworks zu nutzen. Dieser Ansatz bietet mehr Flexibilität, bringt aber auch erhöhte Komplexität mit sich.
Programme aktualisieren
Um ein bestehendes Programm zu
modifizieren,
muss ein Konto als
Upgrade-Authority
festgelegt werden. (Typischerweise dasselbe Konto, das ursprünglich
das Programm deployed hat.) Wenn die
Upgrade-Authority widerrufen und auf None gesetzt wird, kann das Programm
nicht mehr aktualisiert werden.
Programme verifizieren
Solana unterstützt verifizierbare Builds, die es Benutzern ermöglichen zu überprüfen, ob der On-Chain-Code eines Programms mit seinem öffentlichen Quellcode übereinstimmt. Das Anchor-Framework bietet integrierte Unterstützung für die Erstellung eines verifizierbaren Builds.
Um zu überprüfen, ob ein bestehendes Programm verifiziert ist, suchen Sie nach seiner Programm-ID im Solana Explorer. Alternativ können Sie die Ellipsis Labs Solana Verifiable Build CLI verwenden, um On-Chain-Programme unabhängig zu verifizieren.
Integrierte Programme
Das System Program
Das System Program ist das einzige Konto, das neue Konten erstellen kann. Standardmäßig gehören alle neuen Konten dem System Program, obwohl viele bei der Erstellung einem neuen Eigentümer zugewiesen werden. Das System Program erfüllt die folgenden Schlüsselfunktionen:
| Funktion | Beschreibung |
|---|---|
| Erstellung neuer Konten | Nur das System Program kann neue Konten erstellen. |
| Speicherplatzzuweisung | Legt die Bytekapazität für das Datenfeld jedes Kontos fest. |
| Programmeigentum zuweisen | Sobald das System Program ein Konto erstellt hat, kann es den festgelegten Programmeigentümer einem anderen program account zuweisen. So übernehmen benutzerdefinierte Programme die Eigentümerschaft von neuen Konten, die vom System Program erstellt wurden. |
| SOL übertragen | Überträgt Lamports (SOL) von System-Konten auf andere Konten. |
Die Adresse des System Program ist 11111111111111111111111111111111.
Loader-Programme
Jedes Programm gehört einem anderen – seinem Loader. Loader werden verwendet, um Programme zu deployen, erneut zu deployen, zu aktualisieren oder zu schließen. Sie werden auch verwendet, um ein Programm zu finalisieren und die Programmautorität zu übertragen.
Loader-Programme werden manchmal als 'BPF Loaders' bezeichnet.
Derzeit gibt es fünf Loader-Programme, wie in der folgenden Tabelle dargestellt.
| Loader | Programm-ID | Hinweise | Anweisungen-Link |
|---|---|---|---|
| native | NativeLoader1111111111111111111111111111111 | Besitzt die anderen vier Loader | — |
| v1 | BPFLoader1111111111111111111111111111111111 | Management-Anweisungen sind deaktiviert, aber Programme werden weiterhin ausgeführt | — |
| v2 | BPFLoader2111111111111111111111111111111111 | Management-Anweisungen sind deaktiviert, aber Programme werden weiterhin ausgeführt | Anweisungen |
| v3 | BPFLoaderUpgradeab1e11111111111111111111111 | Programme können nach dem Deployment aktualisiert werden. Programm-Executable wird in einem separaten Program-Data-Konto gespeichert | Anweisungen |
| v4 | LoaderV411111111111111111111111111111111111 | In Entwicklung (unveröffentlicht) | Anweisungen |
Programme, die mit loader-v3 oder loader-v4 bereitgestellt wurden, können nach dem Deployment modifizierbar sein, je nachdem, was ihre Upgrade-Authority festlegt.
Wenn ein neues Programm bereitgestellt wird, wird standardmäßig die neueste Loader-Version verwendet.
Vorkompilierte Programme
Zusätzlich zu den Loader-Programmen bietet Solana die folgenden vorkompilierten Programme.
Verifizierung von ed25519-Signaturen
Das ed25519-Programm wird verwendet, um eine oder mehrere ed25519-Signaturen zu verifizieren.
| Programm | Programm-ID | Beschreibung | Anweisungen |
|---|---|---|---|
| Ed25519-Programm | Ed25519SigVerify111111111111111111111111111 | Verifiziert Ed25519-Signaturen. Wenn eine Signatur fehlschlägt, wird ein Fehler zurückgegeben. | Anweisungen |
Das Ed25519-Programm verarbeitet eine Anweisung. Das erste u8 der Anweisung
enthält eine Anzahl der zu überprüfenden Signaturen, gefolgt von einem einzelnen
Byte Padding. Danach wird die folgende Struktur serialisiert, eine für jede zu
überprüfende Signatur.
struct Ed25519SignatureOffsets {signature_offset: u16, // offset to ed25519 signature of 64 bytessignature_instruction_index: u16, // instruction index to find signaturepublic_key_offset: u16, // offset to public key of 32 bytespublic_key_instruction_index: u16, // instruction index to find public keymessage_data_offset: u16, // offset to start of message datamessage_data_size: u16, // size of message datamessage_instruction_index: u16, // index of instruction data to get message data}
process_instruction() {for i in 0..count {// i'th index values referenced:instructions = &transaction.message().instructionsinstruction_index = ed25519_signature_instruction_index != u16::MAX ? ed25519_signature_instruction_index : current_instruction;signature = instructions[instruction_index].data[ed25519_signature_offset..ed25519_signature_offset + 64]instruction_index = ed25519_pubkey_instruction_index != u16::MAX ? ed25519_pubkey_instruction_index : current_instruction;pubkey = instructions[instruction_index].data[ed25519_pubkey_offset..ed25519_pubkey_offset + 32]instruction_index = ed25519_message_instruction_index != u16::MAX ? ed25519_message_instruction_index : current_instruction;message = instructions[instruction_index].data[ed25519_message_data_offset..ed25519_message_data_offset + ed25519_message_data_size]if pubkey.verify(signature, message) != Success {return Error}}return Success}
Verifizierung von secp256k1-Wiederherstellung
Das secp256k1-Programm wird verwendet, um secp256k1-Public-Key-Wiederherstellungsoperationen zu verifizieren.
| Programm | Programm-ID | Beschreibung | Anweisungen |
|---|---|---|---|
| Secp256k1-Programm | KeccakSecp256k11111111111111111111111111111 | Verifiziert secp256k1-Public-Key-Recovery-Operationen (ecrecover). | Anweisungen |
Das secp256k1-Programm verarbeitet eine Anweisung. Das erste Byte der Anweisung enthält die Anzahl der zu überprüfenden öffentlichen Schlüssel. Danach wird die folgende Struktur einmal für jeden öffentlichen Schlüssel erstellt, dann serialisiert und zu den instruction data hinzugefügt.
struct Secp256k1SignatureOffsets {secp_signature_offset: u16, // offset to [signature,recovery_id] of 64+1 bytessecp_signature_instruction_index: u8, // instruction index to find signaturesecp_pubkey_offset: u16, // offset to ethereum_address pubkey of 20 bytessecp_pubkey_instruction_index: u8, // instruction index to find pubkeysecp_message_data_offset: u16, // offset to start of message datasecp_message_data_size: u16, // size of message datasecp_message_instruction_index: u8, // instruction index to find message data}
process_instruction() {for i in 0..count {// i'th index values referenced:instructions = &transaction.message().instructionssignature = instructions[secp_signature_instruction_index].data[secp_signature_offset..secp_signature_offset + 64]recovery_id = instructions[secp_signature_instruction_index].data[secp_signature_offset + 64]ref_eth_pubkey = instructions[secp_pubkey_instruction_index].data[secp_pubkey_offset..secp_pubkey_offset + 20]message_hash = keccak256(instructions[secp_message_instruction_index].data[secp_message_data_offset..secp_message_data_offset + secp_message_data_size])pubkey = ecrecover(signature, recovery_id, message_hash)eth_pubkey = keccak256(pubkey[1..])[12..]if eth_pubkey != ref_eth_pubkey {return Error}}return Success}
Dies ermöglicht dem Benutzer, beliebige instruction data in der Transaktion für Signatur- und Nachrichtendaten anzugeben. Durch Angabe eines speziellen instructions sysvar kann man auch Daten aus der Transaktion selbst empfangen.
Die Kosten der Transaktion werden anhand der Anzahl der zu verifizierenden Signaturen multipliziert mit dem Signaturkosten-Verifizierungsmultiplikator berechnet.
Das Secp256r1-Programm wird verwendet, um bis zu 8 Secp256r1-Signaturen zu verifizieren.
| Programm | Programm-ID | Beschreibung | Anweisungen |
|---|---|---|---|
| Secp256r1-Programm | Secp256r1SigVerify1111111111111111111111111 | Verifiziert bis zu 8 secp256r1-Signaturen. Nimmt eine Signatur, einen öffentlichen Schlüssel und eine Nachricht. Gibt einen Fehler zurück, wenn eine fehlschlägt. | Anweisungen |
Das secp256r1-Programm verarbeitet eine Anweisung. Das erste u8 der Anweisung
enthält die Anzahl der zu überprüfenden Signaturen, gefolgt von einem einzelnen
Byte Padding. Danach wird für jede Signatur die folgende Struktur erstellt, dann
serialisiert und zu den instruction data hinzugefügt.
struct Secp256r1SignatureOffsets {signature_offset: u16, // offset to compact secp256r1 signature of 64 bytessignature_instruction_index: u16, // instruction index to find signaturepublic_key_offset: u16, // offset to compressed public key of 33 bytespublic_key_instruction_index: u16, // instruction index to find public keymessage_data_offset: u16, // offset to start of message datamessage_data_size: u16, // size of message datamessage_instruction_index: u16, // index of instruction data to get message data}
Niedrige S-Werte werden für alle Signaturen erzwungen, um unbeabsichtigte Signaturveränderbarkeit zu vermeiden.
process_instruction() {if data.len() < SIGNATURE_OFFSETS_START {return Error}num_signatures = data[0] as usizeif num_signatures == 0 || num_signatures > 8 {return Error}expected_data_size = num_signatures * SIGNATURE_OFFSETS_SERIALIZED_SIZE + SIGNATURE_OFFSETS_STARTif data.len() < expected_data_size {return Error}for i in 0..num_signatures {offsets = parse_signature_offsets(data, i)signature = get_data_slice(data, instruction_datas, offsets.signature_instruction_index, offsets.signature_offset, SIGNATURE_SERIALIZED_SIZE)if s > half_curve_order {return Error}pubkey = get_data_slice(data, instruction_datas, offsets.public_key_instruction_index, offsets.public_key_offset, COMPRESSED_PUBKEY_SERIALIZED_SIZE)message = get_data_slice(data, instruction_datas, offsets.message_instruction_index, offsets.message_data_offset, offsets.message_data_size)if !verify_signature(signature, pubkey, message) {return Error}}return Success}
Kernprogramme
Die Programme in der folgenden Liste bieten die Kernfunktionalität des Netzwerks.
| Programm | Programm-ID | Beschreibung | Anweisungen |
|---|---|---|---|
| System | 11111111111111111111111111111111 | Erstellt neue Konten, weist Kontodaten zu, weist Konten besitzenden Programmen zu, überträgt Lamports von Konten im Besitz des System-Programms und zahlt Transaktionsgebühren | SystemInstruction |
| Vote | Vote111111111111111111111111111111111111111 | Erstellt und verwaltet Konten, die den Abstimmungsstatus und Belohnungen von Validatoren verfolgen | VoteInstruction |
| Stake | Stake11111111111111111111111111111111111111 | Erstellt und verwaltet Konten, die Stake und Belohnungen für Delegationen an Validatoren repräsentieren | StakeInstruction |
| Config | Config1111111111111111111111111111111111111 | Fügt Konfigurationsdaten zur Chain hinzu, gefolgt von der Liste öffentlicher Schlüssel, die diese ändern dürfen. Im Gegensatz zu anderen Programmen definiert das Config-Programm keine einzelnen Anweisungen. Es hat nur eine implizite Anweisung: "store". Seine instruction data sind eine Reihe von Schlüsseln, die den Zugriff auf das Konto und die darin gespeicherten Daten steuern | ConfigInstruction |
| Compute Budget | ComputeBudget111111111111111111111111111111 | Legt Compute-Unit-Limits und Preise für Transaktionen fest, sodass Benutzer Compute-Ressourcen und Priorisierungsgebühren kontrollieren können | ComputeBudgetInstruction |
| Address Lookup Table | AddressLookupTab1e1111111111111111111111111 | Verwaltet Address-Lookup-Tabellen, die es Transaktionen ermöglichen, auf mehr Konten zu verweisen, als sonst in die Kontenliste der Transaktion passen würden | ProgramInstruction |
| ZK ElGamal Proof | ZkE1Gama1Proof11111111111111111111111111111 | Bietet Zero-Knowledge-Proof-Verifizierung für ElGamal-verschlüsselte Daten | — |
Is this page helpful?