Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ bytemuck.workspace = true
num_enum.workspace = true
const-crypto.workspace = true


pinocchio.workspace = true
pinocchio-log.workspace = true
pinocchio-pubkey.workspace = true
Expand Down
75 changes: 74 additions & 1 deletion program/src/instruction/tape/tape_finalize.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,78 @@
use tape_api::prelude::*;

use pinocchio::{account_info::AccountInfo, program_error::ProgramError, ProgramResult};
use tape_api::state::{Archive, Tape, Writer};

pub fn process_tape_finalize(accounts: &[AccountInfo], _data: &[u8]) -> ProgramResult {
let [signer_info, tape_info, writer_info, archive_info, _system_program_info, _rent_sysvar_info, _remaining @ ..] =
accounts
else {
return Err(ProgramError::NotEnoughAccountKeys);
};

if !signer_info.is_signer() {
return Err(ProgramError::MissingRequiredSignature);
}

let mut tape_data = tape_info.try_borrow_mut_data()?;
let tape = Tape::unpack_mut(&mut tape_data)?;

if tape.authority != *signer_info.key() {
return Err(ProgramError::MissingRequiredSignature);
}

if !tape_info.is_owned_by(&tape_api::ID) {
return Err(ProgramError::IncorrectProgramId);
}

if !writer_info.is_owned_by(&tape_api::ID) {
return Err(ProgramError::IncorrectProgramId);
}

let mut writer_data = writer_info.try_borrow_mut_data()?;
let writer = Writer::unpack_mut(&mut writer_data)?;

if writer.tape != *tape_info.key() {
return Err(ProgramError::InvalidAccountData);
}

let mut archive_data = archive_info.try_borrow_mut_data()?;
let archive = Archive::unpack_mut(&mut archive_data)?;

let (tape_address, _tape_bump) = tape_pda(*signer_info.key(), &tape.name);

let (writer_address, _writer_bump) = writer_pda(tape_address);

if tape_info.key() != &tape_address {
return Err(ProgramError::InvalidAccountData.into());
}

if writer_info.key() != &writer_address {
return Err(ProgramError::InvalidAccountData.into());
}

check_condition(
tape.state == TapeState::Writing as u64,
TapeError::UnexpectedState,
)?;

check_condition(tape.can_finalize(), TapeError::InsufficientRent)?;

archive.tapes_stored = archive.tapes_stored.saturating_add(1);
archive.segments_stored = archive.segments_stored.saturating_add(tape.total_segments);

tape.number = archive.tapes_stored;
tape.state = TapeState::Finalized as u64;
// tape.merkle_root = writer.state.get_root().into();

*signer_info.try_borrow_mut_lamports()? += *writer_info.try_borrow_lamports()?;
*writer_info.try_borrow_mut_lamports()? = 0;
writer_info.close()?;

FinalizeEvent {
tape: tape.number,
address: tape_address,
};

pub fn process_tape_finalize(accounts: &[AccountInfo], data: &[u8]) -> ProgramResult {
Ok(())
}
47 changes: 47 additions & 0 deletions program/src/instruction/tape/tape_subsidize.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,52 @@
use pinocchio::{account_info::AccountInfo, program_error::ProgramError, ProgramResult};
use pinocchio_token::instructions::Transfer;
use tape_api::prelude::*;

#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, shank::ShankType)]
pub struct SubsidizeIxData {
pub amount: u64,
}

impl DataLen for SubsidizeIxData {
const LEN: usize = core::mem::size_of::<SubsidizeIxData>();
}

pub fn process_tape_subsidize_rent(accounts: &[AccountInfo], data: &[u8]) -> ProgramResult {
let [signer_info, ata_info, tape_info, treasury_ata_info, _token_program_info, _remaining @ ..] =
accounts
else {
return Err(ProgramError::NotEnoughAccountKeys);
};

if !signer_info.is_signer() {
return Err(ProgramError::MissingRequiredSignature);
}

if !tape_info.is_owned_by(&tape_api::ID) {
return Err(ProgramError::IncorrectProgramId);
}

let mut tape_data = tape_info.try_borrow_mut_data()?;
let tape = Tape::unpack_mut(&mut tape_data)?;

if !treasury_ata_info.is_writable() {
return Err(ProgramError::Immutable);
}

let args = unsafe { load_ix_data::<SubsidizeIxData>(&data)? };

let amount = args.amount;

Transfer {
from: &ata_info,
to: &treasury_ata_info,
authority: &signer_info,
amount,
}
.invoke()?;

tape.balance = tape.balance.saturating_add(amount);

Ok(())
}
87 changes: 87 additions & 0 deletions program/src/instruction/tape/tape_write.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,92 @@
use core::fmt::Write;

use pinocchio::sysvars::clock::Clock;
use pinocchio::sysvars::Sysvar;
use pinocchio::{account_info::AccountInfo, program_error::ProgramError, ProgramResult};
use tape_api::prelude::*;
use tape_api::{error::TapeError, SEGMENT_SIZE};

pub fn process_tape_write(accounts: &[AccountInfo], data: &[u8]) -> ProgramResult {
let current_slot = Clock::get()?.slot;

let [signer_info, tape_info, writer_info, _remaining @ ..] = accounts else {
return Err(ProgramError::NotEnoughAccountKeys);
};

if !signer_info.is_signer() {
return Err(ProgramError::MissingRequiredSignature);
}

if !tape_info.is_owned_by(&tape_api::ID) {
return Err(ProgramError::IncorrectProgramId);
}

let mut tape_data = tape_info.try_borrow_mut_data()?;
let tape = Tape::unpack_mut(&mut tape_data)?;

if tape.authority != *signer_info.key() {
return Err(ProgramError::MissingRequiredSignature);
}

if !writer_info.is_owned_by(&tape_api::ID) {
return Err(ProgramError::IncorrectProgramId);
}

let mut writer_data = writer_info.try_borrow_mut_data()?;
let writer = Writer::unpack_mut(&mut writer_data)?;

if writer.tape != *tape_info.key() {
return Err(ProgramError::InvalidAccountData);
}

let (tape_address, _tape_bump) = tape_pda(*signer_info.key(), &tape.name);
let (writer_address, _writer_bump) = writer_pda(tape_address);

if tape_info.key() != &tape_address {
return Err(ProgramError::InvalidAccountData.into());
}

if writer_info.key() != &writer_address {
return Err(ProgramError::InvalidAccountData.into());
}

check_condition(
tape.state == TapeState::Created as u64 || tape.state == TapeState::Writing as u64,
TapeError::UnexpectedState,
)?;

let segments = data.chunks(SEGMENT_SIZE);
let segment_count = segments.len() as u64;

check_condition(
tape.total_segments + segment_count <= MAX_SEGMENTS_PER_TAPE as u64,
TapeError::TapeTooLong,
)?;

for (segment_number, segment) in segments.enumerate() {
let canonical_segment = padded_array::<SEGMENT_SIZE>(segment);

// write_segment(
// &mut writer.state,
// tape.total_segments + segment_number as u64,
// &canonical_segment,
// )?;
}

let prev_slot = tape.tail_slot;

tape.total_segments += segment_count;
// tape.merkle_root = writer.state.get_root().to_bytes();
tape.state = TapeState::Writing as u64;
tape.tail_slot = current_slot;

WriteEvent {
prev_slot,
num_added: segment_count,
num_total: tape.total_segments,
address: tape_address,
}
.log();

Ok(())
}