Programme in Rust entwickeln
Solana-Programme werden hauptsächlich mit der Programmiersprache Rust entwickelt. Diese Seite konzentriert sich auf das Schreiben von Solana-Programmen in Rust ohne Verwendung des Anchor- Frameworks, ein Ansatz, der oft als Schreiben von "nativem Rust"-Programmen bezeichnet wird.
Die native Rust-Entwicklung bietet Entwicklern direkte Kontrolle über ihre Solana-Programme. Dieser Ansatz erfordert jedoch mehr manuelle Einrichtung und Boilerplate-Code im Vergleich zur Verwendung des Anchor-Frameworks. Diese Methode wird für Entwickler empfohlen, die:
- Detaillierte Kontrolle über Programmlogik und Optimierungen suchen
- Die zugrundeliegenden Konzepte verstehen möchten, bevor sie zu höheren Frameworks übergehen
Für Anfänger empfehlen wir, mit dem Anchor-Framework zu beginnen. Weitere Informationen finden Sie im Anchor-Abschnitt.
Voraussetzungen
Detaillierte Installationsanweisungen finden Sie auf der Installationsseite.
Bevor Sie beginnen, stellen Sie sicher, dass Sie Folgendes installiert haben:
- Rust: Die Programmiersprache zum Erstellen von Solana-Programmen.
- Solana CLI: Kommandozeilen-Tool für die Solana-Entwicklung.
Erste Schritte
Das folgende Beispiel behandelt die grundlegenden Schritte zur Erstellung Ihres ersten Solana-Programms in Rust. Wir erstellen ein minimales Programm, das "Hello, world!" in das Programmprotokoll schreibt.
Erstellen eines neuen Programms
Erstellen Sie zunächst ein neues Rust-Projekt mit dem Standard cargo new
Befehl und dem --lib
Flag.
$cargo new hello_world --lib
Navigieren Sie zum Projektverzeichnis. Sie sollten die Standard src/lib.rs
und
Cargo.toml
Dateien sehen
$cd hello_world
Aktualisieren Sie das edition
Feld in Cargo.toml
auf 2021
. Andernfalls
könnten Sie beim Erstellen des Programms auf einen Fehler stoßen.
Füge die solana-program Abhängigkeit hinzu
Als nächstes füge die solana-program
Abhängigkeit hinzu. Dies ist die minimale
Abhängigkeit, die für die Erstellung eines Solana-Programms erforderlich ist.
$cargo add solana-program@2.2.0
Füge den crate-type hinzu
Als nächstes füge den folgenden Codeausschnitt zu Cargo.toml
hinzu.
[lib]crate-type = ["cdylib", "lib"]
Wenn du diese Konfiguration nicht einfügst, wird das target/deploy
Verzeichnis beim Erstellen des Programms nicht generiert.
Deine Cargo.toml
Datei sollte wie folgt aussehen:
[package]name = "hello_world"version = "0.1.0"edition = "2021"[lib]crate-type = ["cdylib", "lib"][dependencies]solana-program = "2.2.0"
Füge den Programmcode hinzu
Ersetze als nächstes den Inhalt von src/lib.rs
mit dem folgenden Code. Dies
ist ein minimales Solana-Programm, das "Hello, world!" in das Programmprotokoll
schreibt, wenn das Programm aufgerufen wird.
Das msg!
Makro wird in Solana-Programmen verwendet, um eine Nachricht in das
Programmprotokoll zu schreiben.
use solana_program::{account_info::AccountInfo, entrypoint, entrypoint::ProgramResult, msg, pubkey::Pubkey,};entrypoint!(process_instruction);pub fn process_instruction(_program_id: &Pubkey,_accounts: &[AccountInfo],_instruction_data: &[u8],) -> ProgramResult {msg!("Hello, world!");Ok(())}
Erstelle das Programm
Erstelle als nächstes das Programm mit dem cargo build-sbf
Befehl.
$cargo build-sbf
Dieser Befehl generiert ein target/deploy
Verzeichnis, das zwei wichtige
Dateien enthält:
- Eine
.so
Datei (z.B.hello_world.so
): Dies ist das kompilierte Solana-Programm, das als "Smart Contract" im Netzwerk bereitgestellt wird. - Eine Keypair-Datei (z.B.
hello_world-keypair.json
): Der öffentliche Schlüssel dieses Keypairs wird als Programm-ID bei der Bereitstellung des Programms verwendet.
Um die Programm-ID anzuzeigen, führe den folgenden Befehl in deinem Terminal aus. Dieser Befehl gibt den öffentlichen Schlüssel des Keypairs am angegebenen Dateipfad aus:
$solana address -k ./target/deploy/hello_world-keypair.json
Beispielausgabe:
4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz
Testabhängigkeiten hinzufügen
Als Nächstes testen wir das Programm mit dem litesvm
Crate. Fügen Sie die
folgenden Abhängigkeiten zu Cargo.toml
hinzu.
$cargo add litesvm --dev$cargo add solana-sdk@2.2.0 --dev
Das Programm testen
Fügen Sie den folgenden Test zu src/lib.rs
hinzu, unterhalb des Programmcodes.
Dies ist ein Test- Modul, das das Hello-World-Programm aufruft.
use solana_program::{account_info::AccountInfo, entrypoint, entrypoint::ProgramResult, msg, pubkey::Pubkey,};entrypoint!(process_instruction);pub fn process_instruction(_program_id: &Pubkey,_accounts: &[AccountInfo],_instruction_data: &[u8],) -> ProgramResult {msg!("Hello, world!");Ok(())}#[cfg(test)]mod test {use litesvm::LiteSVM;use solana_sdk::{instruction::Instruction,message::Message,signature::{Keypair, Signer},transaction::Transaction,};#[test]fn test_hello_world() {// Create a new LiteSVM instancelet mut svm = LiteSVM::new();// Create a keypair for the transaction payerlet payer = Keypair::new();// Airdrop some lamports to the payersvm.airdrop(&payer.pubkey(), 1_000_000_000).unwrap();// Load our programlet program_keypair = Keypair::new();let program_id = program_keypair.pubkey();svm.add_program_from_file(program_id, "target/deploy/hello_world.so").unwrap();// Create instruction with no accounts and no datalet instruction = Instruction {program_id,accounts: vec![],data: vec![],};// Create transactionlet message = Message::new(&[instruction], Some(&payer.pubkey()));let transaction = Transaction::new(&[&payer], message, svm.latest_blockhash());// Send transaction and verify it succeedslet result = svm.send_transaction(transaction);assert!(result.is_ok(), "Transaction should succeed");let logs = result.unwrap().logs;println!("Logs: {logs:#?}");}}
Führen Sie den Test mit dem Befehl cargo test
aus. Das Programmprotokoll wird
"Hello, world!" anzeigen.
$cargo test -- --no-capture
Beispielausgabe:
running 1 testLogs: ["Program 9528phXNvdWp5kkR4rgpoeZvR8ZWT5THVywK95YRprkk invoke [1]","Program log: Hello, world!","Program 9528phXNvdWp5kkR4rgpoeZvR8ZWT5THVywK95YRprkk consumed 211 of 200000 compute units","Program 9528phXNvdWp5kkR4rgpoeZvR8ZWT5THVywK95YRprkk success",]test test::test_hello_world ... oktest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.05s
Das Programm bereitstellen
Als Nächstes stellen wir das Programm bereit. Bei der lokalen Entwicklung können
wir den solana-test-validator
verwenden.
Konfigurieren Sie zunächst die Solana CLI für die Verwendung des lokalen Solana-Clusters.
$solana config set -ul
Beispielausgabe:
Config File: /.config/solana/cli/config.ymlRPC URL: http://localhost:8899WebSocket URL: ws://localhost:8900/ (computed)Keypair Path: /.config/solana/id.jsonCommitment: confirmed
Öffnen Sie ein neues Terminal und führen Sie den Befehl solana-test-validators
aus, um den lokalen Validator zu starten.
$solana-test-validator
Während der Test-Validator läuft, führen Sie den Befehl solana program deploy
in einem separaten Terminal aus, um das Programm auf dem lokalen Validator
bereitzustellen.
$solana program deploy ./target/deploy/hello_world.so
Beispielausgabe:
Program Id: 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMzSignature:5osMiNMiDZGM7L1e2tPHxU8wdB8gwG8fDnXLg5G7SbhwFz4dHshYgAijk4wSQL5cXiu8z1MMou5kLadAQuHp7ybH
Du kannst die Programm-ID und die Transaktionssignatur auf dem Solana Explorer überprüfen.
Beachte, dass der Cluster im Solana Explorer ebenfalls auf localhost
eingestellt sein muss. Die Option "Custom RPC URL" im Solana Explorer ist
standardmäßig auf http://localhost:8899
eingestellt.
Beispiel-Client erstellen
Als Nächstes zeigen wir, wie man das Programm mit einem Rust-Client aufruft.
Erstelle zunächst ein Verzeichnis examples
und eine Datei client.rs
.
$mkdir -p examples && touch examples/client.rs
Füge Folgendes zu Cargo.toml
hinzu.
[[example]]name = "client"path = "examples/client.rs"
Füge die Abhängigkeiten solana-client
und tokio
hinzu.
$cargo add solana-client@2.2.0 --dev$cargo add tokio --dev
Client hinzufügen
Füge den folgenden Code zu examples/client.rs
hinzu. Dies ist ein
Rust-Client-Skript, das ein neues keypair mit Guthaben für Transaktions-Fee
ausstattet und dann das Hello World-Programm aufruft.
use solana_client::rpc_client::RpcClient;use solana_sdk::{commitment_config::CommitmentConfig,instruction::Instruction,pubkey::Pubkey,signature::{Keypair, Signer},transaction::Transaction,};use std::str::FromStr;#[tokio::main]async fn main() {// Program ID (replace with your actual program ID)let program_id = Pubkey::from_str("4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz").unwrap();// Connect to the Solana devnetlet rpc_url = String::from("http://localhost:8899");let client = RpcClient::new_with_commitment(rpc_url, CommitmentConfig::confirmed());// Generate a new keypair for the payerlet payer = Keypair::new();// Request airdroplet airdrop_amount = 1_000_000_000; // 1 SOLlet signature = client.request_airdrop(&payer.pubkey(), airdrop_amount).expect("Failed to request airdrop");// Wait for airdrop confirmationloop {let confirmed = client.confirm_transaction(&signature).unwrap();if confirmed {break;}}// Create the instructionlet instruction = Instruction::new_with_borsh(program_id,&(), // Empty instruction datavec![], // No accounts needed);// Add the instruction to new transactionlet mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey()));transaction.sign(&[&payer], client.get_latest_blockhash().unwrap());// Send and confirm the transactionmatch client.send_and_confirm_transaction(&transaction) {Ok(signature) => println!("Transaction Signature: {}", signature),Err(err) => eprintln!("Error sending transaction: {}", err),}}
Programm-ID ersetzen
Bevor du den Client-Code ausführst, ersetze die Programm-ID im Code-Snippet durch die ID deines Programms.
Du kannst deine Programm-ID mit dem folgenden Befehl abrufen.
$solana address -k ./target/deploy/hello_world-keypair.json
Programm aufrufen
Führe das Client-Skript mit dem folgenden Befehl aus.
$cargo run --example client
Beispielausgabe:
Transaction Signature: 54TWxKi3Jsi3UTeZbhLGUFX6JQH7TspRJjRRFZ8NFnwG5BXM9udxiX77bAACjKAS9fGnVeEazrXL4SfKrW7xZFYV
Du kannst die Transaktionssignatur im Solana Explorer (lokaler Cluster) überprüfen, um "Hello, world!" im Programmlog zu sehen.
Programm aktualisieren
Solana-Programme können durch erneutes Deployment mit derselben Programm-ID
aktualisiert werden. Aktualisiere das Programm in src/lib.rs
, um "Hello,
Solana!" anstelle von "Hello, world!" auszugeben.
pub fn process_instruction(_program_id: &Pubkey,_accounts: &[AccountInfo],_instruction_data: &[u8],) -> ProgramResult {-msg!("Hello, world!");+msg!("Hello, Solana!");Ok(())}
Führe den Befehl cargo build-sbf
aus, um eine aktualisierte .so
Datei zu
generieren.
$cargo build-sbf
Teste das aktualisierte Programm, indem du den Befehl cargo test
ausführst.
$cargo test -- --no-capture
Du solltest "Hello, Solana!" im Programmlog sehen.
running 1 testLogs: ["Program 5y8bHrnwfq2dLDgLn3WoTHb9dDuyorj9gyapW6aeyrpV invoke [1]","Program log: Hello, Solana!","Program 5y8bHrnwfq2dLDgLn3WoTHb9dDuyorj9gyapW6aeyrpV consumed 211 of 200000 compute units","Program 5y8bHrnwfq2dLDgLn3WoTHb9dDuyorj9gyapW6aeyrpV success",]test test::test_hello_world ... oktest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.08s
Programm erneut deployen
Deploye das Programm erneut mit demselben Befehl solana program deploy
.
$solana program deploy ./target/deploy/hello_world.so
Führe den Client-Code erneut aus und überprüfe die Transaktionssignatur im Solana Explorer, um "Hello, Solana!" im Programmlog zu sehen.
$cargo run --example client
Programm schließen
Du kannst dein Solana-Programm schließen, um das für das Konto zugewiesene SOL zurückzugewinnen. Das Schließen eines Programms ist irreversibel und sollte daher mit Vorsicht durchgeführt werden.
Um ein Programm zu schließen, verwende den Befehl
solana program close <PROGRAM_ID>
. Zum Beispiel:
$solana program close 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz --bypass-warning
Beispielausgabe:
Closed Program Id 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz, 0.1350588 SOLreclaimed
Beachten Sie, dass sobald ein Programm geschlossen ist, seine Programm-ID nicht wiederverwendet werden kann. Der Versuch, ein Programm mit einer zuvor geschlossenen Programm-ID zu deployen, führt zu einem Fehler.
Error: Program 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz has been closed, usea new Program Id
Ein geschlossenes Programm erneut deployen
Wenn Sie ein Programm mit demselben Quellcode nach dem Schließen eines Programms erneut deployen müssen, müssen Sie eine neue Programm-ID generieren. Um ein neues keypair für das Programm zu generieren, führen Sie den folgenden Befehl aus:
$solana-keygen new -o ./target/deploy/hello_world-keypair.json --force
Alternativ können Sie die vorhandene Keypair-Datei (z.B.
./target/deploy/hello_world-keypair.json
) löschen und cargo build-sbf
erneut ausführen, wodurch eine neue Keypair-Datei generiert wird.
Is this page helpful?