nitro-da-blober 0.1.4

The Nitro DA Blober program used to store hashes of blob data.
Documentation
use anchor_lang::prelude::*;

use crate::{blob::Blob, hash_blob, state::blober::Blober, BLOB_DATA_END, BLOB_DATA_START, SEED};

#[derive(Accounts)]
pub struct FinalizeBlob<'info> {
    #[account(
        mut,
        close = payer,
        seeds = [
            SEED,
            payer.key().as_ref(),
            blober.key().as_ref(),
            blob.timestamp.to_le_bytes().as_ref(),
            blob.size.to_le_bytes().as_ref(),
        ],
        bump = blob.bump,
    )]
    pub blob: Account<'info, Blob>,

    #[account(
        mut,
        constraint = blober.caller == payer.key(),
    )]
    pub blober: Account<'info, Blober>,

    #[account(mut)]
    pub payer: Signer<'info>,
}

pub fn finalize_blob_handler(ctx: Context<FinalizeBlob>) -> Result<()> {
    if !ctx.accounts.blob.is_complete() {
        panic!("blob is missing chunks, can't be completed in this state")
    }

    let blob_info = ctx.accounts.blob.to_account_info();

    let blob_digest_and_size = &blob_info.data.borrow()[BLOB_DATA_START..BLOB_DATA_END];

    let blob_hash = hash_blob(blob_info.key, blob_digest_and_size);
    let current_slot_num = Clock::get()?.slot;

    let blober_account = &mut ctx.accounts.blober;
    blober_account.store_hash(&blob_hash, current_slot_num);

    let new_hash = blober_account.hash;

    msg!(
        &format!("slot: {current_slot_num:?}, triggering account hash: {blob_hash:?}, accumulated hash: {new_hash:?}")
    );

    Ok(())
}

#[cfg(test)]
mod tests {
    use anchor_lang::{
        prelude::{AccountMeta, Pubkey},
        ToAccountMetas,
    };

    use crate::accounts::FinalizeBlob;

    #[test]
    fn test_first_account_is_the_blob() {
        let blober = Pubkey::new_unique();
        let blob = Pubkey::new_unique();
        let payer = Pubkey::new_unique();

        let account = FinalizeBlob {
            blober,
            blob,
            payer,
        };

        let expected = AccountMeta {
            pubkey: blob,
            is_signer: false,
            is_writable: true,
        };

        let is_signer = None;
        let actual = &account.to_account_metas(is_signer)[0];
        assert_eq!(actual, &expected);
    }
}