Sol.College

Full lesson

kamui

Efficient Elliptic Curve VRF on Solana.

What it does

From the project README:

In `mangekyou`, one can compare all currently implemented cryptographic schemes by running:
Original
mangekyou-labs/kamui
SuperStack fork
Blockchains/kamui @ 62454cc
Stars
1
Last push (original)
2026-05-03
Languages
TypeScript, Rust, JavaScript, Solidity, Shell, Move
Detected stack
Anchorweb3.js
Categories
Other
Licence
Apache-2.0
Homepage
https://kamuipoc.vercel.app

Architecture

268 source files. By extension: .ts ×126, .rs ×89, .sol ×20, .go ×13, .js ×8, .move ×7.

Top-level directorySource files
kamui-program118
iota45
crosschain-prover32
mangekyou30
vrf-server20
kamui-node10
mangekyou-cli5
example-vrf-game5

On-chain programs: kamui-program/programs/kamui-vrf, kamui-program/programs/kamui-vrf-consumer

Dapp: devnet deploy pending

⏳ Devnet deploy pending — goes live when the devnet wallet is topped up. This fork's own dapp is not deployed yet, so there is no program address or transaction to show. It is queued in dapp-queue.txt; once devnet SOL is available it is deployed, exercised with real devnet transactions, and this section switches to the live dapp at /dapps/kamui/. Until then, the lesson and step-by-step guide below are complete, and you can run it locally with the commands below.

Key code, explained

Excerpts chosen automatically where the code uses the most Solana concepts, pinned to the fork's commit.

mangekyou-labs/kamui · kamui-program/programs/kamui-vrf/src/light_compressed_vrf.rs L49–72 @ 62454cc · Apache-2.0 · original
 #[cfg(feature = "light-compression")]#[derive(Accounts)]#[instruction(seed: [u8; 32], callback_data: Vec<u8>, num_words: u32, minimum_confirmations: u8, callback_gas_limit: u64, pool_id: u8)]pub struct CreateCompressedVrfRequest<'info> {    #[account(mut)]    pub signer: Signer<'info>,    #[account(        init,        payer = signer,        space = 8 + std::mem::size_of::<CompressedVrfRequest>() + 200, // Extra space for dynamic data        seeds = [b"COMPRESSED_VRF", seed.as_ref(), signer.key().as_ref()],        bump    )]    pub vrf_request: Account<'info, CompressedVrfRequest>,    pub system_program: Program<'info, System>,} #[cfg(feature = "light-compression")]#[derive(Accounts)]#[instruction(request_id: [u8; 32])]pub struct FulfillCompressedVrfRequest<'info> {    #[account(mut)]    pub authority: Signer<'info>,
  1. Line 55 pub signer: Signer<'info>,: Requires this account to have signed the transaction.
  2. Line 57 init,: Creates and pays for a new account. Space and payer must be specified.
  3. Line 60 seeds = [b"COMPRESSED_VRF", seed.as_ref(), signer.key().as_ref()],: Declares the PDA seeds. Anchor re-derives the address and rejects the account if it doesn't match.
  4. Line 61 bump: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
mangekyou-labs/kamui · kamui-program/programs/kamui-vrf/src/state.rs L325–347 @ 62454cc · Apache-2.0 · original
                expired_count    }} // Context structs for instructions #[derive(Accounts)]pub struct CreateEnhancedSubscription<'info> {    #[account(mut)]    pub owner: Signer<'info>,        #[account(        init,        payer = owner,        space = 8 + EnhancedSubscription::INIT_SPACE,        seeds = [b"subscription", seed.key().as_ref()],        bump    )]    pub subscription: Account<'info, EnhancedSubscription>,        /// CHECK: This account is used only as a seed for the subscription PDA and is not read or written to    pub seed: AccountInfo<'info>,
  1. Line 335 pub owner: Signer<'info>,: Requires this account to have signed the transaction.
  2. Line 338 init,: Creates and pays for a new account. Space and payer must be specified.
  3. Line 341 seeds = [b"subscription", seed.key().as_ref()],: Declares the PDA seeds. Anchor re-derives the address and rejects the account if it doesn't match.
  4. Line 342 bump: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
mangekyou-labs/kamui · kamui-program/programs/kamui-vrf-consumer/src/lib.rs L205–228 @ 62454cc · Apache-2.0 · original
    }} #[derive(Accounts)]pub struct Initialize<'info> {    #[account(mut)]    pub owner: Signer<'info>,        #[account(        init,        payer = owner,        space = 8 + 32 + 1 + 8 + 8 + 8 + 32, // Added space for last_verification_hash        seeds = [b"game", owner.key().as_ref()],        bump    )]    pub game_state: Account<'info, GameState>,        pub system_program: Program<'info, System>,} #[derive(Accounts)]pub struct VerifyVrfProof<'info> {    pub signer: Signer<'info>,}
  1. Line 211 pub owner: Signer<'info>,: Requires this account to have signed the transaction.
  2. Line 214 init,: Creates and pays for a new account. Space and payer must be specified.
  3. Line 217 seeds = [b"game", owner.key().as_ref()],: Declares the PDA seeds. Anchor re-derives the address and rejects the account if it doesn't match.
  4. Line 218 bump: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
mangekyou-labs/kamui · vrf-server/src/processor.rs L349–372 @ 62454cc · Apache-2.0 · original
            proof: proof.clone(),            proof_block: 0, // Will be set by the runtime        };         // Check if VRF result account already exists        let vrf_result_data_len = vrf_result_account.data_len();        if vrf_result_data_len == 0 {            // Create new VRF result account            let space = borsh::to_vec(&vrf_result)?.len() + 8;  // Add 8 bytes for discriminator            let rent = Rent::get()?;            let lamports = rent.minimum_balance(space);             // Verify VRF result PDA            let (expected_vrf_result, bump) = Pubkey::find_program_address(                &[b"vrf_result", requester.as_ref()],                program_id            );            if expected_vrf_result != *vrf_result_account.key {                return Err(ProgramError::InvalidSeeds);            }             invoke_signed(                &system_instruction::create_account(                    oracle.key,
  1. Line 362 let (expected_vrf_result, bump) = Pubkey::find_program_address(: Derives a PDA from seeds and the program ID and returns the address with its canonical bump.
  2. Line 362 let (expected_vrf_result, bump) = Pubkey::find_program_address(: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
  3. Line 370 invoke_signed(: Makes a CPI signed by a PDA. The signer seeds prove the program controls that address.

How to run, build and test

These commands come from the repo's own manifests (package.json scripts, Anchor.toml, Cargo, go.mod, Makefile). Check the README for prerequisites and environment variables.

DirectoryCommandRuns
.npm run devLOG_LEVEL=debug node standalone-vrf-server.js
.npm run startnode standalone-vrf-server.js
.npm run testnode standalone-vrf-server.js --test-cli
.npm run buildcargo build --bin ecvrf-cli --release
crosschain-prover/contractsnpm run devpnpm mud dev-contracts --tsgenOutput ../client/src/mud
crosschain-prover/contractsnpm run buildforge clean && bash build_with_abi.sh
crosschain-prover/contractsnpm run testtsc --noEmit && mud test
crosschain-prover/contractsnpm run lintpnpm run prettier && pnpm run solhint
crosschain-prover/contractsnpm run deploypnpm run initialize && mud deploy --profile=hackathon-testnet
vrf-server/nodejsnpm run startnode vrf-server-nodejs.js
kamui-programnpm run buildanchor build
kamui-programnpm run testanchor test
kamui-program/appnpm run devvite
kamui-program/appnpm run buildtsc && vite build
kamui-program/appnpm run linteslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0
iota/nodenpm run devts-node src/index.ts

What you could build from it