Desarrollando programas en Rust
Los programas de Solana se desarrollan principalmente utilizando el lenguaje de programación Rust. Esta página se centra en escribir programas de Solana en Rust sin utilizar el framework Anchor, un enfoque que a menudo se conoce como escribir programas "Rust nativo".
El desarrollo en Rust nativo proporciona a los desarrolladores un control directo sobre sus programas de Solana. Sin embargo, este enfoque requiere más configuración manual y código repetitivo en comparación con el uso del framework Anchor. Este método es recomendado para desarrolladores que:
- Buscan un control granular sobre la lógica del programa y las optimizaciones
- Quieren aprender los conceptos subyacentes antes de pasar a frameworks de más alto nivel
Para principiantes, recomendamos comenzar con el framework Anchor. Consulta la sección Anchor para más información.
Requisitos previos
Para instrucciones detalladas de instalación, visita la página de instalación.
Antes de comenzar, asegúrate de tener instalado lo siguiente:
- Rust: El lenguaje de programación para construir programas de Solana.
- Solana CLI: Herramienta de línea de comandos para el desarrollo en Solana.
Primeros pasos
El ejemplo a continuación cubre los pasos básicos para crear tu primer programa de Solana escrito en Rust. Crearemos un programa mínimo que imprima "Hello, world!" en el registro del programa.
Crear un nuevo programa
Primero, crea un nuevo proyecto de Rust utilizando el comando estándar
cargo init
con la bandera --lib
.
cargo init hello_world --lib
Navega al directorio del proyecto. Deberías ver los archivos predeterminados
src/lib.rs
y Cargo.toml
cd hello_world
A continuación, añade la dependencia solana-program
. Esta es la dependencia
mínima requerida para construir un programa de Solana.
cargo add solana-program@1.18.26
A continuación, añade el siguiente fragmento a Cargo.toml
. Si no incluyes esta
configuración, el directorio target/deploy
no se generará cuando compiles el
programa.
[lib]crate-type = ["cdylib", "lib"]
Tu archivo Cargo.toml
debería verse así:
[package]name = "hello_world"version = "0.1.0"edition = "2021"[lib]crate-type = ["cdylib", "lib"][dependencies]solana-program = "1.18.26"
A continuación, reemplaza el contenido de src/lib.rs
con el siguiente código.
Este es un programa mínimo de Solana que imprime "Hello, world!" en el registro
del programa cuando se invoca el programa.
La macro msg!
se utiliza en los programas de Solana para imprimir un mensaje
en el registro del programa.
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(())}
Compilar el programa
A continuación, compila el programa usando el comando cargo build-sbf
.
cargo build-sbf
Este comando genera un directorio target/deploy
que contiene dos archivos
importantes:
- Un archivo
.so
(p. ej.,hello_world.so
): Este es el programa de Solana compilado que se desplegará en la red como un "contrato inteligente". - Un archivo keypair (p. ej.,
hello_world-keypair.json
): La clave pública de este keypair se utiliza como ID del programa al desplegarlo.
Para ver el ID del programa, ejecuta el siguiente comando en tu terminal. Este comando imprime la clave pública del keypair en la ruta de archivo especificada:
solana address -k ./target/deploy/hello_world-keypair.json
Ejemplo de salida:
4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz
Probar el programa
A continuación, prueba el programa usando el crate solana-program-test
. Añade
las siguientes dependencias a Cargo.toml
.
cargo add solana-program-test@1.18.26 --devcargo add solana-sdk@1.18.26 --devcargo add tokio --dev
Añade la siguiente prueba a src/lib.rs
, debajo del código del programa. Este
es un módulo de prueba que invoca el programa hello world.
#[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());}}
Ejecuta la prueba usando el comando cargo test-sbf
. El registro del programa
mostrará "Hello, world!".
cargo test-sbf
Ejemplo de salida:
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
Desplegar el programa
A continuación, despliega el programa. Durante el desarrollo local, podemos usar
el solana-test-validator
.
Primero, configura la CLI de Solana para usar el clúster local de Solana.
solana config set -ul
Ejemplo de salida:
Config File: /.config/solana/cli/config.ymlRPC URL: http://localhost:8899WebSocket URL: ws://localhost:8900/ (computed)Keypair Path: /.config/solana/id.jsonCommitment: confirmed
Abre una nueva terminal y ejecuta el comando solana-test-validators
para
iniciar el validator local.
solana-test-validator
Mientras el validator de prueba está en ejecución, ejecuta el comando
solana program deploy
en una terminal separada para desplegar el programa en
el validator local.
solana program deploy ./target/deploy/hello_world.so
Ejemplo de salida:
Program Id: 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMzSignature:5osMiNMiDZGM7L1e2tPHxU8wdB8gwG8fDnXLg5G7SbhwFz4dHshYgAijk4wSQL5cXiu8z1MMou5kLadAQuHp7ybH
Puedes inspeccionar el ID del programa y la firma de la transacción en
Solana Explorer.
Ten en cuenta que el clúster en Solana Explorer también debe ser localhost. La
opción "Custom RPC URL" en Solana Explorer tiene por defecto
http://localhost:8899
.
Invocar el programa
A continuación, demostraremos cómo invocar el programa usando un cliente Rust.
Primero crea un directorio examples
y un archivo client.rs
.
mkdir -p examplestouch examples/client.rs
Añade lo siguiente a Cargo.toml
.
[[example]]name = "client"path = "examples/client.rs"
Añade la dependencia solana-client
.
cargo add solana-client@1.18.26 --dev
Añade el siguiente código a examples/client.rs
. Este es un script cliente en
Rust que financia un nuevo keypair para pagar las tarifas de transacción y luego
invoca el programa hello world.
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),}}
Antes de ejecutar el script, reemplaza el ID del programa en el fragmento de código anterior con el de tu programa.
Puedes obtener el ID de tu programa ejecutando el siguiente comando.
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();}}
Ejecuta el script cliente con el siguiente comando.
cargo run --example client
Ejemplo de salida:
Transaction Signature: 54TWxKi3Jsi3UTeZbhLGUFX6JQH7TspRJjRRFZ8NFnwG5BXM9udxiX77bAACjKAS9fGnVeEazrXL4SfKrW7xZFYV
Puedes inspeccionar la firma de la transacción en Solana Explorer (clúster local) para ver "Hello, world!" en el registro del programa.
Actualizar el programa
Los programas de Solana pueden actualizarse redeployando al mismo ID de
programa. Actualiza el programa en src/lib.rs
para que imprima "Hello,
Solana!" en lugar de "Hello, world!".
pub fn process_instruction(_program_id: &Pubkey,_accounts: &[AccountInfo],_instruction_data: &[u8],) -> ProgramResult {- msg!("Hello, world!");+ msg!("Hello, Solana!");Ok(())}
Prueba el programa actualizado ejecutando el comando cargo test-sbf
.
cargo test-sbf
Deberías ver "Hello, Solana!" en el registro del programa.
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
Ejecuta el comando cargo build-sbf
para generar un archivo .so
actualizado.
cargo build-sbf
Redespliega el programa usando el comando solana program deploy
.
solana program deploy ./target/deploy/hello_world.so
Ejecuta el código cliente nuevamente e inspecciona la firma de la transacción en Solana Explorer para ver "Hello, Solana!" en el registro del programa.
cargo run --example client
Cerrar el programa
Puedes cerrar tu programa de Solana para recuperar el SOL asignado a la cuenta. Cerrar un programa es irreversible, por lo que debe hacerse con precaución.
Para cerrar un programa, utiliza el comando solana program close <PROGRAM_ID>
.
Por ejemplo:
solana program close 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz--bypass-warning
Ejemplo de salida:
Closed Program Id 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz, 0.1350588 SOLreclaimed
Ten en cuenta que una vez que un programa se cierra, su ID de programa no puede reutilizarse. Intentar desplegar un programa con un ID de programa previamente cerrado resultará en un error.
Error: Program 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz has been closed, usea new Program Id
Si necesitas volver a desplegar un programa con el mismo código fuente después de cerrar un programa, debes generar un nuevo ID de programa. Para generar un nuevo keypair para el programa, ejecuta el siguiente comando:
solana-keygen new -o ./target/deploy/hello_world-keypair.json --force
Alternativamente, puedes eliminar el archivo de keypair existente (por ejemplo
./target/deploy/hello_world-keypair.json
) y ejecutar cargo build-sbf
nuevamente, lo que generará un nuevo archivo de keypair.
Is this page helpful?