Rust
Pinocchio Quantum Vault

Pinocchio Quantum Vault

7 Graduates

The Quantum Vault

Pinocchio Quantum Vault Challenge

A vault is a fundamental building block in DeFi that provides a secure way for users to store their assets.

In this challenge, we'll build a vault that uses Winternitz signatures for transaction verification. This is particularly interesting because Winternitz Signature is the first post-quantum signature integrated on Solana.

If you're unfamiliar with Winternitz Signature, start by reading Winternitz Signature on Solana to understand the core concepts and underlying cryptography.

In this challenge, we'll update the simple lamport vault that we built in the Pinocchio Vault Challenge to allow Winternitz Signatures as a verification method for transactions.

Installation

Before you begin, make sure Rust and Pinocchio are installed. Then, run the following in your terminal:

bash
# create workspace
cargo new blueshift-pinocchio-quantum-vault --lib --edition 2021
cd blueshift-pinocchio-quantum-vault

Add pinocchio, pinocchio-system, and solana-nostd-sha256 and solana-winternitz:

bash
cargo add pinocchio pinocchio-system solana-nostd-sha256 solana-winternitz

Declare the crate types in Cargo.toml to generate deployment artifacts in target/deploy:

toml
[lib]
crate-type = ["lib", "cdylib"]

You're now ready to write your quantum vault program.

Template

This time, we'll split the program into small, focused modules instead of placing everything in lib.rs. The folder tree will look roughly like this:

 
src
├── instructions
│       ├── close.rs
│       ├── open.rs
│       ├── mod.rs
│       └── split.rs
└── lib.rs

Note: Remember to change the program ID to 22222222222222222222222222222222222222222222 since we use this under the hood to test your program.

The entrypoint in lib.rs is very similar to what we covered in the Introduction to Pinocchio Course.

rust
pub mod instructions;
use instructions::*;
 
use pinocchio::{
    account_info::AccountInfo, program_entrypoint, program_error::ProgramError,
    pubkey::Pubkey, ProgramResult,
};
 
program_entrypoint!(process_instruction);
 
// 22222222222222222222222222222222222222222222
pub const ID: Pubkey = [
    0x0f, 0x1e, 0x6b, 0x14, 0x21, 0xc0, 0x4a, 0x07, 
    0x04, 0x31, 0x26, 0x5c, 0x19, 0xc5, 0xbb, 0xee, 
    0x19, 0x92, 0xba, 0xe8, 0xaf, 0xd1, 0xcd, 0x07, 
    0x8e, 0xf8, 0xaf, 0x70, 0x47, 0xdc, 0x11, 0xf7, 
];
 
fn process_instruction(
    _program_id: &Pubkey,
    accounts: &[AccountInfo],
    instruction_data: &[u8],
) -> ProgramResult {    
    match instruction_data.split_first() {
        Some((OpenVault::DISCRIMINATOR, data)) => OpenVault::try_from((data, accounts))?.process(),
        Some((SplitVault::DISCRIMINATOR, data)) => SplitVault::try_from((data, accounts))?.process(),
        Some((CloseVault::DISCRIMINATOR, data)) => CloseVault::try_from((data, accounts))?.process(),
        _ => Err(ProgramError::InvalidInstructionData)
    }
}

We don't need any state setup for this, so we're just going to move into creating our instructions.

Next PageOpen Vault
OR SKIP TO THE CHALLENGE
Ready to take the challenge?
Contents
View Source
Blueshift © 2025Commit: 0ec4e4d