Skip to main content

data_anchor_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::{
13    prelude::*,
14    solana_program::hash::{self, HASH_BYTES},
15};
16pub use constants::*;
17pub use instructions::*;
18pub use state::*;
19
20declare_id!("anchorE4RzhiFx3TEFep6yRNK9igZBzMVWziqjbGHp2");
21
22#[program]
23pub mod blober {
24    use super::*;
25
26    pub fn initialize(ctx: Context<Initialize>, namespace: String, trusted: Pubkey) -> Result<()> {
27        initialize_handler(ctx, namespace, trusted)
28    }
29
30    pub fn declare_blob(ctx: Context<DeclareBlob>, timestamp: u64, blob_size: u32) -> Result<()> {
31        declare_blob_handler(ctx, timestamp, blob_size)
32    }
33
34    pub fn insert_chunk(ctx: Context<InsertChunk>, idx: u16, data: Vec<u8>) -> Result<()> {
35        insert_chunk_handler(ctx, idx, data)
36    }
37
38    pub fn finalize_blob(ctx: Context<FinalizeBlob>) -> Result<()> {
39        finalize_blob_handler(ctx)
40    }
41
42    pub fn discard_blob(ctx: Context<DiscardBlob>) -> Result<()> {
43        discard_blob_handler(ctx)
44    }
45
46    pub fn close(ctx: Context<Close>) -> Result<()> {
47        close_handler(ctx)
48    }
49
50    pub fn configure_checkpoint(
51        ctx: Context<ConfigureCheckpoint>,
52        authority: Pubkey,
53    ) -> Result<()> {
54        configure_checkpoint_handler(ctx, authority)
55    }
56
57    pub fn create_checkpoint(
58        ctx: Context<CreateCheckpoint>,
59        blober: Pubkey,
60        proof: [u8; GROTH16_PROOF_SIZE],
61        public_values: Vec<u8>,
62        verification_key: String,
63        slot: u64,
64    ) -> Result<()> {
65        create_checkpoint_handler(ctx, blober, proof, public_values, verification_key, slot)
66    }
67}
68
69/// Hashes a single chunk on top of the previous hash.
70pub fn hash_leaf(
71    previous_hash: [u8; HASH_BYTES],
72    chunk_index: u16,
73    chunk_data: &[u8],
74) -> [u8; HASH_BYTES] {
75    hash::hashv(&[&previous_hash, &chunk_index.to_le_bytes(), chunk_data]).to_bytes()
76}
77
78/// Computes a blob digest of all the chunks of a blob.
79pub fn compute_blob_digest<A: AsRef<[u8]>>(chunks: &[(u16, A)]) -> [u8; HASH_BYTES] {
80    chunks
81        .iter()
82        .fold(initial_hash(), |hash, (chunk_index, chunk_data)| {
83            hash_leaf(hash, *chunk_index, chunk_data.as_ref())
84        })
85}
86
87/// Retrieves the PDA address of a blob account to store chunks and digest the data.
88pub fn find_blob_address(
89    program_id: Pubkey,
90    payer: Pubkey,
91    blober: Pubkey,
92    timestamp: u64,
93    blob_size: usize,
94) -> Pubkey {
95    Pubkey::find_program_address(
96        &[
97            SEED,
98            payer.as_ref(),
99            blober.as_ref(),
100            timestamp.to_le_bytes().as_ref(),
101            (blob_size as u32).to_le_bytes().as_ref(),
102        ],
103        &program_id,
104    )
105    .0
106}
107
108/// Retrieves the PDA address of a blober account to store digests and finalize blobs.
109pub fn find_blober_address(program_id: Pubkey, payer: Pubkey, namespace: &str) -> Pubkey {
110    Pubkey::find_program_address(&[SEED, payer.as_ref(), namespace.as_bytes()], &program_id).0
111}
112
113/// Retrieves the PDA address of a checkpoint account to store proofs and public values.
114pub fn find_checkpoint_address(program_id: Pubkey, blober: Pubkey) -> Pubkey {
115    Pubkey::find_program_address(&[SEED, CHECKPOINT_SEED, blober.as_ref()], &program_id).0
116}
117
118/// Retrieves the PDA address of a checkpoint configuration account to store authority and other
119pub fn find_checkpoint_config_address(program_id: Pubkey, blober: Pubkey) -> Pubkey {
120    Pubkey::find_program_address(
121        &[
122            SEED,
123            CHECKPOINT_SEED,
124            CHECKPOINT_CONFIG_SEED,
125            blober.as_ref(),
126        ],
127        &program_id,
128    )
129    .0
130}
131
132/// Retrieves the PDA address of a checkpoint PDA signer account to sign the checkoint modifying
133/// instruction.
134pub fn find_checkpoint_signer_address(program_id: Pubkey, blober: Pubkey) -> Pubkey {
135    Pubkey::find_program_address(
136        &[
137            SEED,
138            CHECKPOINT_SEED,
139            CHECKPOINT_PDA_SIGNER_SEED,
140            blober.as_ref(),
141        ],
142        &program_id,
143    )
144    .0
145}
146
147/// Computes the hashed state of a blob account.
148pub fn hash_blob(key: &Pubkey, data: &[u8]) -> [u8; HASH_BYTES] {
149    hash::hashv(&[key.as_ref(), data]).to_bytes()
150}
151
152/// Merges two hashes into a single one. Used when there are multiple blobs to finalize in the same
153/// slot.
154pub fn merge_hashes(current: &[u8; HASH_BYTES], new: &[u8; HASH_BYTES]) -> [u8; HASH_BYTES] {
155    hash::hashv(&[current, new]).to_bytes()
156}