DEV Community

이관호(Gwanho LEE)
이관호(Gwanho LEE)

Posted on

➡️ Rust Dev's Pallas Journey: Cardano in Rust Intro

source code(https://github.com/leepl37/Pallas-Explorer-Demo)

dive into Pallas, TxPipe's Rust toolkit for Cardano.

Modular Rust for blockchain without Haskell.

summary of pallas.

  1. pallas-codec

CBOR serialization/deserialization foundation.

Example:

use pallas_codec::{Encode, Decode};
use pallas_codec::minicbor::Decoder;

#[derive(Encode, Decode)]
enum MyEnum { Value(u64) }

fn main() {
    let val = MyEnum::Value(42);
    let encoded = val.encode_to_vec().unwrap();
    let mut decoder = Decoder::new(&encoded);
    let decoded: MyEnum = decoder.decode().unwrap();
    if let MyEnum::Value(n) = decoded { println!("Decoded: {}", n); }
}
Enter fullscreen mode Exit fullscreen mode
  1. pallas-primitives

Ledger data structs across eras.

Example:


use pallas_primitives::MultiEraTx;

fn main() {
    let tx_bytes = vec![]; // CBOR bytes
    let tx = MultiEraTx::from_cbor_bytes(&tx_bytes).unwrap();
    println!("Fee: {:?}", tx.fees());
}
Enter fullscreen mode Exit fullscreen mode
  1. pallas-crypto

Hashes, sigs, VRF for security.

Example:

use pallas_crypto::{Blake2b256, Ed25519Bip32SecretKey, Ed25519Signature};
use rand::rngs::OsRng;
use rand::RngCore;

fn main() {
    let mut sk_bytes = [0u8; 32];
    OsRng.fill_bytes(&mut sk_bytes);
    let sk = Ed25519Bip32SecretKey::from_bytes(sk_bytes).unwrap();
    let data = b"test";
    let sig = Ed25519Signature::sign(&sk, data);
    println!("Sig valid: {}", sig.verify(&sk.public_key(), data));
}
Enter fullscreen mode Exit fullscreen mode
  1. pallas-addresses

Address encoding/decoding.

Example:


use pallas_addresses::Address;

fn main() {
    let addr = Address::from_bech32("addr1q...").unwrap();
    if let Address::Shelley(s) = addr {
        println!("Payment: {:?}", s.payment);
    }
}
Enter fullscreen mode Exit fullscreen mode
  1. pallas-txbuilder

Tx construction builder.

Example:

use pallas_txbuilder::Builder;
use pallas_primitives::ProtocolParameters;

fn main() {
    let params = ProtocolParameters::default();
    let mut builder = Builder::new(params);
    let min_fee = builder.min_fee().unwrap();
    println!("Min fee: {}", min_fee);
}
Enter fullscreen mode Exit fullscreen mode
  1. pallas-traverse

Data analysis/traversal.

Example:

use pallas_traverse::MultiEraBlock;

fn main() {
    let block_bytes = vec![]; // Bytes
    let block = MultiEraBlock::decode(&block_bytes).unwrap();
    for tx in block.txs() {
        println!("Inputs: {:?}", tx.inputs().len());
    }
}
Enter fullscreen mode Exit fullscreen mode
  1. pallas-network

Node communication stack.

Example:

use pallas_network::n2c::connect;

#[tokio::main]
async fn main() {
    let _mux = connect("relay.example:3001").await.unwrap();
}
Enter fullscreen mode Exit fullscreen mode
  1. pallas-hardano

Haskell node artifact interop.

Example:

use pallas_hardano::ImmutableFile;

use std::path::PathBuf;

fn main() {
    let path = PathBuf::from("chunk.file");
    let mut reader = ImmutableFile::open(&path).unwrap();
    if let Some(block) = reader.next() {
        println!("Block: {:?}", block.unwrap().header);
    }
}
Enter fullscreen mode Exit fullscreen mode
  1. pallas-math

Math utils for ledger/consensus.

Example:

use pallas_math::slot_to_epoch;

fn main() {
    let epoch = slot_to_epoch(1000000, 432000);
    println!("Epoch: {}", epoch); // ~2
}
Enter fullscreen mode Exit fullscreen mode
  1. pallas-utxorpc

UTxO-RPC querying.

Example:

use pallas_utxorpc::Client;

#[tokio::main]
async fn main() {
    let client = Client::connect("grpc://node:50051").await.unwrap();
    let tip = client.get_chain_tip().await.unwrap();
    println!("Tip: {:?}", tip);
}
Enter fullscreen mode Exit fullscreen mode

easy to remember.

Layer 1: The Atoms

These modules handle the low-level rules of the universe: math, serialization, and cryptography.

  • pallas-codec:

    • What: Implements CBOR (Concise Binary Object Representation) serialization.
    • Why: Cardano uses binary CBOR, not JSON. This module maps Rust Structs to raw bytes using efficient macros.
  • pallas-crypto:

    • What: Handles hashing (Blake2b) and signatures (Ed25519).
    • Why: Bitcoin relies on SHA-256; Cardano relies on Blake2b-256 for performance and security.
  • pallas-math:

    • What: Implements precise fixed-point arithmetic.
    • Why: Floating-point errors (e.g., 0.1 + 0.2 != 0.3) are forbidden in consensus. This ensures exact agreement on staking rewards.

Layer 2: The Data

These modules define the data structures that populate the blockchain.

  • pallas-primitives:

    • What: Defines the Rust Structs for TransactionBody, Block, and Header.
    • Key Concept: Eras. Because of Hard Forks, a "Block" has different shapes in different years (Byron, Shelley, Alonzo, Babbage).
  • pallas-addresses:

    • What: Parses human-readable strings (addr1...) into data.
    • Key Concept: Bech32. It validates checksums and extracts the Payment Key (Ownership) and Stake Key (Voting Rights).

Layer 3: The Tools

These are the libraries you use to read and write data.

  • pallas-traverse:

    • What: The most essential tool for reading chain data.
    • Why: It provides a MultiEraBlock wrapper. This allows you to query data (e.g., block.tx_count()) without writing complex if/else logic for every hard fork era.
  • pallas-txbuilder:

    • What: A helper to construct valid transaction binaries.
    • Why: It manages the complexity of UTXO inputs, fee calculation, and change addresses.

Layer 4: The Infrastructure

These modules connect your code to the physical network.

  • pallas-network:
    • What: Implements the Ouroboros mini-protocols (Handshake, ChainSync, TxSubmission).
    • Why: Allows Rust code to connect directly to Mainnet nodes via TCP.
  • pallas-hardano:
    • What: Reads raw ImmutableDB files directly from the hard drive.
    • Why: Critical for high-performance local indexing (used heavily by Mithril).
  • pallas-utxorpc:
    • What: A modern gRPC bridge to access blockchain data without managing Ouroboros state machines.

The Transaction Lifecycle

the life of a transaction on the Cardano Mainnet.

  1. Creation: A Wallet builds a Tx using pallas-txbuilder (logic) and pallas-primitives (structs).

  2. Submission: The Wallet pushes the Tx to a local Relay Node using pallas-network (TxSubmission protocol).

  3. Propagation (Gossip): Relay nodes check validity and "gossip" the Tx to the Slot Leader's Mempool.

  4. Consensus: The Slot Leader checks its VRF (Verifiable Random Function). If it wins the lottery, it mints a block.

  5. Distribution: The Slot Leader broadcasts the new block using pallas-network (ChainSync protocol).

  6. Observation: Your Pallas Client downloads the block and decodes it using pallas-traverse.

Top comments (0)