trident-svm 0.2.0

Trident SVM implementation by Ackee Blockchain Security
Documentation
use solana_account::AccountSharedData;
use solana_account::WritableAccount;
use solana_loader_v3_interface::state::UpgradeableLoaderState;
use solana_sysvar::rent::Rent;

#[cfg(feature = "syscall-v2")]
use crate::types::trident_entrypoint::TridentEntrypoint;
#[cfg(feature = "syscall-v2")]
use solana_program_runtime::loaded_programs::ProgramCacheEntry;

use crate::trident_svm::TridentSVM;
use crate::types::trident_program::TridentProgram;

impl TridentSVM {
    pub fn deploy_binary_program(&mut self, program: &TridentProgram) {
        let rent = Rent::default();

        let program_account = &program.program_id;

        let program_data_account =
            solana_loader_v3_interface::get_program_data_address(program_account);

        let state = UpgradeableLoaderState::Program {
            programdata_address: program_data_account,
        };

        let buffer = bincode::serialize(&state).unwrap();
        let account_data = AccountSharedData::create(
            rent.minimum_balance(buffer.len()),
            buffer,
            solana_sdk_ids::bpf_loader_upgradeable::id(),
            true,
            Default::default(),
        );

        self.accounts.set_program(program_account, &account_data);

        let state = UpgradeableLoaderState::ProgramData {
            slot: 0,
            upgrade_authority_address: program.authority,
        };
        let mut header = bincode::serialize(&state).unwrap();

        let mut complement = vec![
            0;
            std::cmp::max(
                0,
                UpgradeableLoaderState::size_of_programdata_metadata().saturating_sub(header.len())
            )
        ];

        let mut buffer: Vec<u8> = program.data.to_vec();
        header.append(&mut complement);
        header.append(&mut buffer);

        let account_data = AccountSharedData::create(
            rent.minimum_balance(header.len()),
            header,
            solana_sdk_ids::bpf_loader_upgradeable::id(),
            true,
            Default::default(),
        );

        self.accounts
            .set_program(&program_data_account, &account_data);
    }

    #[cfg(feature = "syscall-v2")]
    pub fn deploy_entrypoint_program(&mut self, program: &TridentEntrypoint) {
        use crate::utils::create_loadable_account_for_test;

        let entry = match program.entry {
            Some(entry) => entry,
            None => panic!("Native programs have to have entry specified"),
        };

        self.accounts.set_program(
            &program.program_id,
            &create_loadable_account_for_test("program-name"),
        );

        let program_data_account =
            solana_loader_v3_interface::get_program_data_address(&program.program_id);

        let state = UpgradeableLoaderState::ProgramData {
            slot: 0,
            upgrade_authority_address: program.authority,
        };
        let mut header = bincode::serialize(&state).unwrap();

        let mut complement = vec![
            0;
            std::cmp::max(
                0,
                UpgradeableLoaderState::size_of_programdata_metadata().saturating_sub(header.len())
            )
        ];

        let mut buffer: Vec<u8> = vec![];
        header.append(&mut complement);
        header.append(&mut buffer);

        let rent = Rent::default();

        let account_data = AccountSharedData::create(
            rent.minimum_balance(header.len()),
            header,
            solana_sdk_ids::bpf_loader_upgradeable::id(),
            true,
            Default::default(),
        );

        self.accounts
            .set_program(&program_data_account, &account_data);

        self.processor.add_builtin(
            self,
            program.program_id,
            "program-name",
            ProgramCacheEntry::new_builtin(0, "program-name".len(), entry),
        );
    }
}