nitro_da_blober/
lib.rs

1#![doc = include_str!("../README.md")]
2#![allow(unexpected_cfgs)]
3// Allow unexpected_cfgs because anchor macros add cfgs which are not in the original code
4
5pub mod constants;
6pub mod error;
7pub mod instructions;
8pub mod state;
9#[cfg(test)]
10mod tests;
11
12use anchor_lang::{prelude::*, solana_program::hash};
13pub use constants::*;
14pub use instructions::*;
15pub use state::*;
16
17declare_id!("8xAuVgAygVN2sPXJzycT7AU7c9ZUJkG357HonxdFXjyc");
18
19#[program]
20pub mod blober {
21    use super::*;
22
23    pub fn initialize(ctx: Context<Initialize>, namespace: String, trusted: Pubkey) -> Result<()> {
24        initialize_handler(ctx, namespace, trusted)
25    }
26
27    pub fn declare_blob(ctx: Context<DeclareBlob>, timestamp: u64, blob_size: u32) -> Result<()> {
28        declare_blob_handler(ctx, timestamp, blob_size)
29    }
30
31    pub fn insert_chunk(ctx: Context<InsertChunk>, idx: u16, data: Vec<u8>) -> Result<()> {
32        insert_chunk_handler(ctx, idx, data)
33    }
34
35    pub fn finalize_blob(ctx: Context<FinalizeBlob>) -> Result<()> {
36        finalize_blob_handler(ctx)
37    }
38
39    pub fn discard_blob(ctx: Context<DiscardBlob>) -> Result<()> {
40        discard_blob_handler(ctx)
41    }
42
43    pub fn close(ctx: Context<Close>) -> Result<()> {
44        close_handler(ctx)
45    }
46}
47
48/// Hashes a single chunk on top of the previous hash.
49pub fn hash_leaf(previous_hash: [u8; 32], chunk_index: u16, chunk_data: &[u8]) -> [u8; 32] {
50    hash::hashv(&[&previous_hash, &chunk_index.to_le_bytes(), chunk_data]).to_bytes()
51}
52
53/// Computes a blob digest of all the chunks of a blob.
54pub fn compute_blob_digest<A: AsRef<[u8]>>(chunks: &[(u16, A)]) -> [u8; 32] {
55    chunks
56        .iter()
57        .fold(initial_hash(), |hash, (chunk_index, chunk_data)| {
58            hash_leaf(hash, *chunk_index, chunk_data.as_ref())
59        })
60}
61
62/// Retrieves the PDA address of a blob account to store chunks and digest the data.
63pub fn find_blob_address(
64    program_id: Pubkey,
65    payer: Pubkey,
66    blober: Pubkey,
67    timestamp: u64,
68    blob_size: usize,
69) -> Pubkey {
70    Pubkey::find_program_address(
71        &[
72            SEED,
73            payer.as_ref(),
74            blober.as_ref(),
75            timestamp.to_le_bytes().as_ref(),
76            (blob_size as u32).to_le_bytes().as_ref(),
77        ],
78        &program_id,
79    )
80    .0
81}
82
83/// Retrieves the PDA address of a blober account to store digests and finalize blobs.
84pub fn find_blober_address(program_id: Pubkey, payer: Pubkey, namespace: &str) -> Pubkey {
85    Pubkey::find_program_address(&[SEED, payer.as_ref(), namespace.as_bytes()], &program_id).0
86}
87
88/// Computes the hashed state of a blob account.
89pub fn hash_blob(key: &Pubkey, data: &[u8]) -> [u8; 32] {
90    hash::hashv(&[key.as_ref(), data]).to_bytes()
91}
92
93/// Merges two hashes into a single one. Used when there are multiple blobs to finalize in the same
94/// slot.
95pub fn merge_hashes(current: &[u8; 32], new: &[u8; 32]) -> [u8; 32] {
96    hash::hashv(&[current, new]).to_bytes()
97}