Entwicklung von Programmen in Rust
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 init
Befehl und der --lib
Flag.
cargo init hello_world --lib
Navigieren Sie zum Projektverzeichnis. Sie sollten die Standard src/lib.rs
und
Cargo.toml
Dateien sehen
cd hello_world
Fügen Sie als Nächstes die solana-program
Abhängigkeit hinzu. Dies ist die
minimale Abhängigkeit, die zum Erstellen eines Solana-Programms erforderlich
ist.
cargo add solana-program@1.18.26
Füge als Nächstes den folgenden Codeausschnitt zu Cargo.toml
hinzu. Wenn du
diese Konfiguration nicht einfügst, wird das Verzeichnis target/deploy
beim
Erstellen des Programms nicht generiert.
[lib]crate-type = ["cdylib", "lib"]
Deine Datei Cargo.toml
sollte wie folgt aussehen:
[package]name = "hello_world"version = "0.1.0"edition = "2021"[lib]crate-type = ["cdylib", "lib"][dependencies]solana-program = "1.18.26"
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 Makro msg!
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(())}
Programm erstellen
Erstelle als Nächstes das Programm mit dem Befehl cargo build-sbf
.
cargo build-sbf
Dieser Befehl generiert ein Verzeichnis target/deploy
mit zwei wichtigen
Dateien:
- 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
Programm testen
Teste als Nächstes das Programm mit der Crate solana-program-test
. Füge die
folgenden Abhängigkeiten zu Cargo.toml
hinzu.
cargo add solana-program-test@1.18.26 --devcargo add solana-sdk@1.18.26 --devcargo add tokio --dev
Füge den folgenden Test zu src/lib.rs
unterhalb des Programmcodes hinzu. Dies
ist ein Test- Modul, das das Hello-World-Programm aufruft.
#[cfg(test)]mod test {use solana_program_test::*;use solana_sdk::{instruction::Instruction, pubkey::Pubkey, signature::Signer, transaction::Transaction,};#[tokio::test]async fn test_hello_world() {let program_id = Pubkey::new_unique();let mut program_test = ProgramTest::default();program_test.add_program("hello_world", program_id, None);let (mut banks_client, payer, recent_blockhash) = program_test.start().await;// Create instructionlet instruction = Instruction {program_id,accounts: vec![],data: vec![],};// Create transaction with instructionlet mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey()));// Sign transactiontransaction.sign(&[&payer], recent_blockhash);let transaction_result = banks_client.process_transaction(transaction).await;assert!(transaction_result.is_ok());}}
Führe den Test mit dem Befehl cargo test-sbf
aus. Das Programmprotokoll wird
"Hello, world!" anzeigen.
cargo test-sbf
Beispielausgabe:
running 1 test[2024-10-18T21:24:54.889570000Z INFO solana_program_test] "hello_world" SBF program from /hello_world/target/deploy/hello_world.so, modified 35 seconds, 828 ms, 268 µs and 398 ns ago[2024-10-18T21:24:54.974294000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM invoke [1][2024-10-18T21:24:54.974814000Z DEBUG solana_runtime::message_processor::stable_log] Program log: Hello, world![2024-10-18T21:24:54.976848000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM consumed 140 of 200000 compute units[2024-10-18T21:24:54.976868000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM successtest test::test_hello_world ... oktest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.13s
Programm bereitstellen
Als Nächstes stellen Sie 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
Sie können die Programm-ID und die Transaktionssignatur auf
Solana Explorer
überprüfen. Beachten Sie, dass der Cluster im Solana Explorer ebenfalls
localhost sein muss. Die Option "Custom RPC URL" im Solana Explorer ist
standardmäßig auf http://localhost:8899
eingestellt.
Programm aufrufen
Als Nächstes zeigen wir, wie man das Programm mit einem Rust-Client aufruft.
Erstellen Sie zunächst ein Verzeichnis examples
und eine Datei client.rs
.
mkdir -p examplestouch examples/client.rs
Fügen Sie Folgendes zu Cargo.toml
hinzu.
[[example]]name = "client"path = "examples/client.rs"
Fügen Sie die Abhängigkeit solana-client
hinzu.
cargo add solana-client@1.18.26 --dev
Fügen Sie den folgenden Code zu examples/client.rs
hinzu. Dies ist ein
Rust-Client-Skript, das ein neues Keypair finanziert, um Transaktionsgebühren zu
bezahlen, 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://127.0.0.1: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),}}
Bevor Sie das Skript ausführen, ersetzen Sie die Programm-ID im obigen Codeausschnitt durch die ID Ihres Programms.
Sie können Ihre Programm-ID mit dem folgenden Befehl abrufen.
solana address -k ./target/deploy/hello_world-keypair.json
#[tokio::main]async fn main() {- let program_id = Pubkey::from_str("4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz").unwrap();+ let program_id = Pubkey::from_str("YOUR_PROGRAM_ID).unwrap();}}
Führen Sie das Client-Skript mit dem folgenden Befehl aus.
cargo run --example client
Beispielausgabe:
Transaction Signature: 54TWxKi3Jsi3UTeZbhLGUFX6JQH7TspRJjRRFZ8NFnwG5BXM9udxiX77bAACjKAS9fGnVeEazrXL4SfKrW7xZFYV
Sie können die Transaktionssignatur im Solana Explorer (lokaler Cluster) überprüfen, um "Hello, world!" im Programmlog zu sehen.
Programm aktualisieren
Solana-Programme können durch erneutes Bereitstellen unter derselben Programm-ID
aktualisiert werden. Aktualisieren Sie 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(())}
Testen Sie das aktualisierte Programm, indem Sie den Befehl cargo test-sbf
ausführen.
cargo test-sbf
Sie sollten "Hello, Solana!" im Programmlog sehen.
running 1 test[2024-10-23T19:28:28.842639000Z INFO solana_program_test] "hello_world" SBF program from /code/misc/delete/hello_world/target/deploy/hello_world.so, modified 4 minutes, 31 seconds, 435 ms, 566 µs and 766 ns ago[2024-10-23T19:28:28.934854000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM invoke [1][2024-10-23T19:28:28.936735000Z DEBUG solana_runtime::message_processor::stable_log] Program log: Hello, Solana![2024-10-23T19:28:28.938774000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM consumed 140 of 200000 compute units[2024-10-23T19:28:28.938793000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM successtest test::test_hello_world ... oktest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.14s
Führen Sie den Befehl cargo build-sbf
aus, um eine aktualisierte .so
-Datei
zu generieren.
cargo build-sbf
Stellen Sie das Programm erneut bereit, indem Sie den Befehl
solana program deploy
verwenden.
solana program deploy ./target/deploy/hello_world.so
Führen Sie den Client-Code erneut aus und überprüfen Sie die Transaktionssignatur im Solana Explorer, um "Hello, Solana!" im Programmlog zu sehen.
cargo run --example client
Programm schließen
Sie können Ihr Solana-Programm schließen, um das dem Konto zugewiesene SOL zurückzufordern. Das Schließen eines Programms ist irreversibel und sollte daher mit Vorsicht durchgeführt werden.
Um ein Programm zu schließen, verwenden Sie 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
Wenn Sie ein Programm mit demselben Quellcode nach dem Schließen 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, was eine neue keypair-Datei generieren wird.
Is this page helpful?