buffett-core 0.1.1

Core library for Bitconch:buffett
use bincode::deserialize;
use crate::dynamic_program::DynamicProgram;
use buffett_interface::account::Account;
use buffett_interface::pubkey::Pubkey;
use std::collections::HashMap;
use std::sync::RwLock;
use crate::transaction::Transaction;

#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum SystemProgram {
    CreateAccount {
        tokens: i64,
        space: u64,
        program_id: Pubkey,
    },
    Assign { program_id: Pubkey },
    Move { tokens: i64 },
    Load { program_id: Pubkey, name: String },
}

pub const SYSTEM_PROGRAM_ID: [u8; 32] = [0u8; 32];

impl SystemProgram {
    pub fn check_id(program_id: &Pubkey) -> bool {
        program_id.as_ref() == SYSTEM_PROGRAM_ID
    }

    pub fn id() -> Pubkey {
        Pubkey::new(&SYSTEM_PROGRAM_ID)
    }
    pub fn get_balance(account: &Account) -> i64 {
        account.tokens
    }
    pub fn process_transaction(
        tx: &Transaction,
        accounts: &mut [Account],
        loaded_programs: &RwLock<HashMap<Pubkey, DynamicProgram>>,
    ) {
        if let Ok(syscall) = deserialize(&tx.userdata) {
            trace!("process_transaction: {:?}", syscall);
            match syscall {
                SystemProgram::CreateAccount {
                    tokens,
                    space,
                    program_id,
                } => {
                    if !Self::check_id(&accounts[0].program_id) {
                        return;
                    }
                    if space > 0
                        && (!accounts[1].userdata.is_empty()
                            || !Self::check_id(&accounts[1].program_id))
                    {
                        return;
                    }
                    accounts[0].tokens -= tokens;
                    accounts[1].tokens += tokens;
                    accounts[1].program_id = program_id;
                    accounts[1].userdata = vec![0; space as usize];
                }
                SystemProgram::Assign { program_id } => {
                    if !Self::check_id(&accounts[0].program_id) {
                        return;
                    }
                    accounts[0].program_id = program_id;
                }
                SystemProgram::Move { tokens } => {
                    accounts[0].tokens -= tokens;
                    accounts[1].tokens += tokens;
                }
                SystemProgram::Load { program_id, name } => {
                    let mut hashmap = loaded_programs.write().unwrap();
                    hashmap.insert(program_id, DynamicProgram::new(name));
                }
            }
        } else {
            info!("Invalid transaction userdata: {:?}", tx.userdata);
        }
    }
}