diff --git a/src/processor/create_proof.rs b/src/processor/create_proof.rs index 62b39aa..50998e9 100644 --- a/src/processor/create_proof.rs +++ b/src/processor/create_proof.rs @@ -5,7 +5,13 @@ use solana_program::{ program_error::ProgramError, pubkey::Pubkey, system_program, }; -use crate::{instruction::CreateProofArgs, loaders::*, state::Proof, utils::create_pda, PROOF}; +use crate::{ + instruction::CreateProofArgs, + loaders::*, + state::{Discriminator, Proof}, + utils::create_pda, + PROOF, +}; pub fn process_create_proof<'a, 'info>( _program_id: &Pubkey, @@ -27,12 +33,13 @@ pub fn process_create_proof<'a, 'info>( create_pda( proof_info, &crate::id(), - size_of::(), + 8 + size_of::(), &[PROOF, signer.key.as_ref(), &[args.bump]], system_program, signer, )?; let mut proof_data = proof_info.data.borrow_mut(); + proof_data[0] = Proof::discriminator() as u8; let mut proof = Proof::try_from_bytes_mut(&mut proof_data)?; proof.bump = args.bump as u64; proof.authority = *signer.key; diff --git a/src/processor/initialize.rs b/src/processor/initialize.rs index a3132b9..9f84403 100644 --- a/src/processor/initialize.rs +++ b/src/processor/initialize.rs @@ -8,6 +8,7 @@ use solana_program::{ }; use spl_token::state::Mint; +use crate::state::Discriminator; use crate::{instruction::*, BUS, INITIAL_DIFFICULTY, MINT_ADDRESS, TREASURY_ADDRESS}; use crate::{ loaders::*, @@ -70,31 +71,30 @@ pub fn process_initialize<'a, 'info>( create_pda( bus_infos[i], &crate::id(), - size_of::(), + 8 + size_of::(), &[BUS, &[i as u8], &[bus_bumps[i]]], system_program, signer, )?; - bus_infos[i].try_borrow_mut_data()?.copy_from_slice( - Bus { - bump: bus_bumps[i] as u32, - id: i as u32, - available_rewards: 0, - } - .to_bytes(), - ); + let mut bus_data = bus_infos[i].try_borrow_mut_data()?; + bus_data[0] = Bus::discriminator() as u8; + let mut bus = Bus::try_from_bytes_mut(&mut bus_data)?; + bus.bump = bus_bumps[i] as u32; + bus.id = i as u32; + bus.available_rewards = 0; } // Initialize treasury create_pda( treasury_info, &crate::id(), - size_of::(), + 8 + size_of::(), &[TREASURY, &[args.treasury_bump]], system_program, signer, )?; let mut treasury_data = treasury_info.data.borrow_mut(); + treasury_data[0] = Treasury::discriminator() as u8; let mut treasury = Treasury::try_from_bytes_mut(&mut treasury_data)?; treasury.bump = args.treasury_bump as u64; treasury.admin = *signer.key; diff --git a/src/state/bus.rs b/src/state/bus.rs index 8ebc1ca..cfa403b 100644 --- a/src/state/bus.rs +++ b/src/state/bus.rs @@ -2,6 +2,8 @@ use bytemuck::{Pod, Zeroable}; use crate::{impl_account_from_bytes, impl_to_bytes}; +use super::{AccountDiscriminator, Discriminator}; + #[repr(C)] #[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)] pub struct Bus { @@ -15,5 +17,11 @@ pub struct Bus { pub available_rewards: u64, } +impl Discriminator for Bus { + fn discriminator() -> super::AccountDiscriminator { + AccountDiscriminator::Bus + } +} + impl_to_bytes!(Bus); impl_account_from_bytes!(Bus); diff --git a/src/state/hash.rs b/src/state/hash.rs index 6e0b457..5a51937 100644 --- a/src/state/hash.rs +++ b/src/state/hash.rs @@ -3,7 +3,7 @@ use std::mem::transmute; use bytemuck::{Pod, Zeroable}; use solana_program::keccak::{Hash as KeccakHash, HASH_BYTES}; -use crate::{impl_account_from_bytes, impl_to_bytes}; +use crate::impl_to_bytes; #[repr(C)] #[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)] @@ -24,4 +24,4 @@ impl From for KeccakHash { } impl_to_bytes!(Hash); -impl_account_from_bytes!(Hash); +// impl_account_from_bytes!(Hash); diff --git a/src/state/mod.rs b/src/state/mod.rs index 64809b4..a646e53 100644 --- a/src/state/mod.rs +++ b/src/state/mod.rs @@ -5,5 +5,18 @@ mod treasury; pub use bus::*; pub use hash::*; +use num_enum::{IntoPrimitive, TryFromPrimitive}; pub use proof::*; pub use treasury::*; + +#[repr(u8)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, IntoPrimitive, TryFromPrimitive)] +pub enum AccountDiscriminator { + Bus = 100, + Proof = 101, + Treasury = 102, +} + +pub trait Discriminator { + fn discriminator() -> AccountDiscriminator; +} diff --git a/src/state/proof.rs b/src/state/proof.rs index c949158..0bd30bc 100644 --- a/src/state/proof.rs +++ b/src/state/proof.rs @@ -3,7 +3,7 @@ use solana_program::pubkey::Pubkey; use crate::{impl_account_from_bytes, impl_to_bytes}; -use super::Hash; +use super::{AccountDiscriminator, Discriminator, Hash}; #[repr(C)] #[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)] @@ -27,5 +27,11 @@ pub struct Proof { pub total_rewards: u64, } +impl Discriminator for Proof { + fn discriminator() -> super::AccountDiscriminator { + AccountDiscriminator::Proof + } +} + impl_to_bytes!(Proof); impl_account_from_bytes!(Proof); diff --git a/src/state/treasury.rs b/src/state/treasury.rs index 5e2f8bf..97dcf72 100644 --- a/src/state/treasury.rs +++ b/src/state/treasury.rs @@ -3,7 +3,7 @@ use solana_program::pubkey::Pubkey; use crate::{impl_account_from_bytes, impl_to_bytes}; -use super::Hash; +use super::{AccountDiscriminator, Discriminator, Hash}; #[repr(C)] #[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)] @@ -27,5 +27,11 @@ pub struct Treasury { pub total_claimed_rewards: u64, } +impl Discriminator for Treasury { + fn discriminator() -> super::AccountDiscriminator { + AccountDiscriminator::Treasury + } +} + impl_to_bytes!(Treasury); impl_account_from_bytes!(Treasury); diff --git a/src/utils.rs b/src/utils.rs index a982106..044e777 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -50,14 +50,20 @@ macro_rules! impl_account_from_bytes { pub fn try_from_bytes( data: &[u8], ) -> Result<&Self, solana_program::program_error::ProgramError> { - bytemuck::try_from_bytes::(data).or(Err( + if (Self::discriminator() as u8).ne(&data[0]) { + return Err(solana_program::program_error::ProgramError::InvalidAccountData); + } + bytemuck::try_from_bytes::(&data[8..]).or(Err( solana_program::program_error::ProgramError::InvalidAccountData, )) } pub fn try_from_bytes_mut( data: &mut [u8], ) -> Result<&mut Self, solana_program::program_error::ProgramError> { - bytemuck::try_from_bytes_mut::(data).or(Err( + if (Self::discriminator() as u8).ne(&data[0]) { + return Err(solana_program::program_error::ProgramError::InvalidAccountData); + } + bytemuck::try_from_bytes_mut::(&mut data[8..]).or(Err( solana_program::program_error::ProgramError::InvalidAccountData, )) } diff --git a/tests/test_initialize.rs b/tests/test_initialize.rs index c4ad471..aa879c0 100644 --- a/tests/test_initialize.rs +++ b/tests/test_initialize.rs @@ -93,6 +93,12 @@ async fn test_initialize() { assert_eq!(bus.bump as u8, bus_pdas[i].1); assert_eq!(bus.id as u8, i as u8); assert_eq!(bus.available_rewards, 0); + println!( + "Bus {:?} {:?} {:?}", + bus_pdas[i].0, + bus_account, + bs64::encode(&bus_account.data) + ); } // Test treasury state @@ -105,6 +111,12 @@ async fn test_initialize() { assert_eq!(treasury.epoch_start_at as u8, 0); assert_eq!(treasury.reward_rate, INITIAL_REWARD_RATE); assert_eq!(treasury.total_claimed_rewards as u8, 0); + println!( + "Treasury {:?} {:?} {:?}", + treasury_pda.0, + treasury_account, + bs64::encode(&treasury_account.data) + ); // Test mint state let mint_account = banks.get_account(mint_pda.0).await.unwrap().unwrap(); @@ -133,13 +145,6 @@ async fn test_initialize() { assert_eq!(treasury_tokens.delegated_amount, 0); assert_eq!(treasury_tokens.close_authority, COption::None); - // println!( - // "Treasury {:?} {:?} {:?}", - // treasury_pda.0, - // treasury_account, - // bs64::encode(&treasury_account.data) - // ); - // assert!(false); } diff --git a/tests/test_mine.rs b/tests/test_mine.rs index f88705c..cbd3204 100644 --- a/tests/test_mine.rs +++ b/tests/test_mine.rs @@ -74,7 +74,6 @@ async fn test_mine() { AccountMeta::new_readonly(treasury_pda.0, false), // AccountMeta::new(treasury_pda.0, false), // AccountMeta::new(proof_pda.0, false), - // AccountMeta::new(bus_pda.0, false), AccountMeta::new_readonly(sysvar::slot_hashes::id(), false), ], data: [ @@ -126,49 +125,49 @@ async fn setup_program_test_env() -> (BanksClient, Keypair, solana_program::hash Pubkey::from_str("2uwqyH2gKqstgAFCSniirx73X4iQek5ETc2vVJKUiNMg").unwrap(), 1002240, ore::id(), - "/wAAAAAAAACAsuYOAAAAAA==", + "ZAAAAAAAAAD/AAAAAAAAAICy5g4AAAAA", ); program_test.add_account_with_base64_data( Pubkey::from_str("FRMC6jVczm1cRaEs5EhDsfw7X8vsmSDpf3bJWVkawngu").unwrap(), 1002240, ore::id(), - "/gAAAAEAAACAsuYOAAAAAA==", + "ZAAAAAAAAAD+AAAAAQAAAICy5g4AAAAA", ); program_test.add_account_with_base64_data( Pubkey::from_str("9nWyycs4GHjnLujPR2sbA1A8K8CkiLc5VzxWUD4hg2uM").unwrap(), 1002240, ore::id(), - "/wAAAAIAAACAsuYOAAAAAA==", + "ZAAAAAAAAAD/AAAAAgAAAICy5g4AAAAA", ); program_test.add_account_with_base64_data( Pubkey::from_str("Kt7kqD3MyvxLbj4ek9urXUxkDoxaMuQn82K2VdYD1jM").unwrap(), 1002240, ore::id(), - "+gAAAAMAAACAsuYOAAAAAA==", + "ZAAAAAAAAAD6AAAAAwAAAICy5g4AAAAA", ); program_test.add_account_with_base64_data( Pubkey::from_str("8r9mXYnFQXhwrNfvatGUTxbbNSqxScuCwp4sBTSxDVTJ").unwrap(), 1002240, ore::id(), - "/QAAAAQAAACAsuYOAAAAAA==", + "ZAAAAAAAAAD9AAAABAAAAICy5g4AAAAA", ); program_test.add_account_with_base64_data( Pubkey::from_str("D9cEH32k8p9uWc4w5RrStK9rWssU8NuX1Dg5YaUim4wL").unwrap(), 1002240, ore::id(), - "/wAAAAUAAACAsuYOAAAAAA==", + "ZAAAAAAAAAD/AAAABQAAAICy5g4AAAAA", ); program_test.add_account_with_base64_data( Pubkey::from_str("H1RKMYADPzd4C1j1RZu51NvRSVktoTYEJyeVy98Kmdyu").unwrap(), 1002240, ore::id(), - "/wAAAAYAAACAsuYOAAAAAA==", + "ZAAAAAAAAAD/AAAABgAAAICy5g4AAAAA", ); program_test.add_account_with_base64_data( Pubkey::from_str("3XbdZNbBjjp8qnDJjv1RxaKisyfx6ahznYkSigs6dayy").unwrap(), 1002240, ore::id(), - "+QAAAAcAAACAsuYOAAAAAA==", + "ZAAAAAAAAAD5AAAABwAAAICy5g4AAAAA", ); // Treasury (difficulty = MAX) @@ -176,8 +175,7 @@ async fn setup_program_test_env() -> (BanksClient, Keypair, solana_program::hash Pubkey::from_str("67PLJej6iZm915WbEu6NLeZtRZtnHc5nSVQvkHRZyPiC").unwrap(), 1559040, ore::id(), - "/wAAAAAAAADHPztpT4Jpqy1n9x6y1psKOUdDt07/OgR6noRFAOuOcP//////////////////////////////////////////ZAAAAAAAAAD0AQAAAAAAAAAAAAAAAAAA" - // "/wAAAAAAAACO+OozfX3xTr9I8U/aRel4qp0ixaw9/PjyseBa6CcLyv//////////////////////////////////////////AAAAAAAAAADoAwAAAAAAAAAAAAAAAAAA" + "ZgAAAAAAAAD/AAAAAAAAAI9MXkItHZzhz/U8d4MsXPzDSQZSRgZsJnNpvgvcborr//////////////////////////////////////////9kAAAAAAAAAPQBAAAAAAAAAAAAAAAAAAA=", ); // Mint diff --git a/tests/test_reset.rs b/tests/test_reset.rs index 3d73df8..a8bb6cb 100644 --- a/tests/test_reset.rs +++ b/tests/test_reset.rs @@ -93,7 +93,7 @@ async fn test_reset() { assert_eq!(treasury.bump as u8, treasury_pda.1); assert_eq!( treasury.admin, - Pubkey::from_str("EQn4AkZ9UvLcwRgyx1B8Y9sRM3KjfKyti8mjUJW1kL6B").unwrap() + Pubkey::from_str("AeNqnoLwFanMd3ig9WoMxQZVwQHtCtqKMMBsT1sTrvz6").unwrap() ); assert_eq!(treasury.difficulty, INITIAL_DIFFICULTY.into()); assert_eq!(treasury.epoch_start_at as u8, 100); @@ -115,12 +115,12 @@ async fn test_reset() { assert_eq!(mint.decimals, ore::TOKEN_DECIMALS); assert_eq!(mint.is_initialized, true); assert_eq!(mint.freeze_authority, COption::None); - println!( - "Mint {:?} {:?} {:?}", - mint_pda.0, - mint_account, - bs64::encode(&mint_account.data) - ); + // println!( + // "Mint {:?} {:?} {:?}", + // mint_pda.0, + // mint_account, + // bs64::encode(&mint_account.data) + // ); // Test treasury token state let treasury_tokens_account = banks @@ -138,12 +138,12 @@ async fn test_reset() { assert_eq!(treasury_tokens.is_native, COption::None); assert_eq!(treasury_tokens.delegated_amount, 0); assert_eq!(treasury_tokens.close_authority, COption::None); - println!( - "Treasury tokens {:?} {:?} {:?}", - treasury_tokens_address, - treasury_tokens_account, - bs64::encode(&treasury_tokens_account.data) - ); + // println!( + // "Treasury tokens {:?} {:?} {:?}", + // treasury_tokens_address, + // treasury_tokens_account, + // bs64::encode(&treasury_tokens_account.data) + // ); // assert!(false); } @@ -157,49 +157,49 @@ async fn setup_program_test_env() -> (BanksClient, Keypair, Hash) { Pubkey::from_str("2uwqyH2gKqstgAFCSniirx73X4iQek5ETc2vVJKUiNMg").unwrap(), 1002240, ore::id(), - "/wAAAAAAAAAAAAAAAAAAAA==", + "ZAAAAAAAAAD/AAAAAAAAAAAAAAAAAAAA", ); program_test.add_account_with_base64_data( Pubkey::from_str("FRMC6jVczm1cRaEs5EhDsfw7X8vsmSDpf3bJWVkawngu").unwrap(), 1002240, ore::id(), - "/gAAAAEAAAAAAAAAAAAAAA==", + "ZAAAAAAAAAD+AAAAAQAAAAAAAAAAAAAA", ); program_test.add_account_with_base64_data( Pubkey::from_str("9nWyycs4GHjnLujPR2sbA1A8K8CkiLc5VzxWUD4hg2uM").unwrap(), 1002240, ore::id(), - "/wAAAAIAAAAAAAAAAAAAAA==", + "ZAAAAAAAAAD/AAAAAgAAAAAAAAAAAAAA", ); program_test.add_account_with_base64_data( Pubkey::from_str("Kt7kqD3MyvxLbj4ek9urXUxkDoxaMuQn82K2VdYD1jM").unwrap(), 1002240, ore::id(), - "+gAAAAMAAAAAAAAAAAAAAA==", + "ZAAAAAAAAAD6AAAAAwAAAAAAAAAAAAAA", ); program_test.add_account_with_base64_data( Pubkey::from_str("8r9mXYnFQXhwrNfvatGUTxbbNSqxScuCwp4sBTSxDVTJ").unwrap(), 1002240, ore::id(), - "/QAAAAQAAAAAAAAAAAAAAA==", + "ZAAAAAAAAAD9AAAABAAAAAAAAAAAAAAA", ); program_test.add_account_with_base64_data( Pubkey::from_str("D9cEH32k8p9uWc4w5RrStK9rWssU8NuX1Dg5YaUim4wL").unwrap(), 1002240, ore::id(), - "/wAAAAUAAAAAAAAAAAAAAA==", + "ZAAAAAAAAAD/AAAABQAAAAAAAAAAAAAA", ); program_test.add_account_with_base64_data( Pubkey::from_str("H1RKMYADPzd4C1j1RZu51NvRSVktoTYEJyeVy98Kmdyu").unwrap(), 1002240, ore::id(), - "/wAAAAYAAAAAAAAAAAAAAA==", + "ZAAAAAAAAAD/AAAABgAAAAAAAAAAAAAA", ); program_test.add_account_with_base64_data( Pubkey::from_str("3XbdZNbBjjp8qnDJjv1RxaKisyfx6ahznYkSigs6dayy").unwrap(), 1002240, ore::id(), - "+QAAAAcAAAAAAAAAAAAAAA==", + "ZAAAAAAAAAD5AAAABwAAAAAAAAAAAAAA", ); // Treasury @@ -207,7 +207,7 @@ async fn setup_program_test_env() -> (BanksClient, Keypair, Hash) { Pubkey::from_str("67PLJej6iZm915WbEu6NLeZtRZtnHc5nSVQvkHRZyPiC").unwrap(), 1559040, ore::id(), - "/wAAAAAAAADHPztpT4Jpqy1n9x6y1psKOUdDt07/OgR6noRFAOuOcAAA////////////////////////////////////////AAAAAAAAAADoAwAAAAAAAAAAAAAAAAAA", + "ZgAAAAAAAAD/AAAAAAAAAI9MXkItHZzhz/U8d4MsXPzDSQZSRgZsJnNpvgvcborrAAD///////////////////////////////////////8AAAAAAAAAAOgDAAAAAAAAAAAAAAAAAAA=", ); // Mint