Blockchain Basics in Rust
9 examples to get you started with blockchain development in Rust - 7 basic and 2 intermediate.
Search across all documentation pages
9 examples to get you started with blockchain development in Rust - 7 basic and 2 intermediate.
cargo new chain-playground && cd chain-playground
cargo add sha2 ed25519-dalek hex serde --features derive
cargo add tokio --features fullTooling: Examples target Rust 1.97.0 (edition 2024). On-chain targets may use older editions per SDK - follow each chain's template.
Block and transaction IDs start with cryptographic hashes.
use sha2::{Digest, Sha256};
fn hash_hex(data: &[u8]) -> String {
let digest = Sha256::digest(data);
hex::encode(digest)
}Related: Applied Cryptography - primitive catalog
Modern chains use Ed25519 for fast signatures and small keys.
use ed25519_dalek::SigningKey;
use rand::rngs::OsRng;
fn new_keypair() -> SigningKey {
SigningKey::generate(&mut OsRng)
}SigningKey must stay secret; VerifyingKey is public.Related: Wallets & Key Management
Signatures prove authorization without revealing the private key.
use ed25519_dalek::{Signer, SigningKey, Verifier, VerifyingKey};
fn sign_verify(key: &SigningKey, msg: &[u8]) -> bool {
let sig = key.sign(msg);
let vk: VerifyingKey = key.verifying_key();
vk.verify(msg, &sig).is_ok()
}msg to prevent cross-protocol replay.Chain configs and genesis files use structured serialization.
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
struct GenesisAccount {
pubkey: String,
balance: u64,
}u64) for token amounts in configs.Overflow panics become exploits in token contracts.
fn transfer(balance: u64, amount: u64) -> Option<u64> {
balance.checked_sub(amount)
}checked_* returns None on overflow instead of wrapping.f64 for token amounts in consensus code.Related: Security & Auditing - integer bugs
Keep on-chain structs small and copy-friendly where programs require it.
#[derive(Clone, Debug)]
struct Tx {
from: [u8; 32],
to: [u8; 32],
lamports: u64,
}Related: Solana Programs
Nodes expose HTTP/WebSocket APIs for chain interaction.
use reqwest::Client;
use serde_json::json;
async fn get_balance(client: &Client, url: &str, address: &str) -> reqwest::Result<serde_json::Value> {
let body = json!({
"jsonrpc": "2.0",
"id": 1,
"method": "getBalance",
"params": [address]
});
let res = client.post(url).json(&body).send().await?;
res.json().await
}Light clients verify inclusion with merkle proofs.
use sha2::{Digest, Sha256};
fn merkle_root(leaves: &[Vec<u8>]) -> [u8; 32] {
if leaves.is_empty() {
return [0u8; 32];
}
let mut layer: Vec<[u8; 32]> = leaves.iter().map(|l| Sha256::digest(l).into()).collect();
while layer.len() > 1 {
let mut next = Vec::new();
for chunk in layer.chunks(2) {
let mut h = Sha256::new();
h.update(chunk[0]);
h.update(chunk.get(1).unwrap_or(&chunk[0]));
next.push(h.finalize().into());
}
layer = next;
}
layer[0]
}Related: Consensus & P2P
Keep off-chain tooling separate from on-chain program crates.
[dependencies]
anchor-lang = { version = "0.30", optional = true }
[features]
on-chain = ["anchor-lang"]Related: Substrate & ink!
Stack versions: This page was written for Rust 1.97.0 (edition 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, and Polars 0.46+.
Reviewed by Chris St. John·Last updated Jul 16, 2026