Skip to content
Merged
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
29 changes: 1 addition & 28 deletions program/c/src/oracle/oracle.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,33 +59,6 @@ static bool valid_writable_account( SolParameters *prm,
is_rent_exempt( *ka->lamports, ka->data_len );
}

static uint64_t init_mapping( SolParameters *prm, SolAccountInfo *ka )
{
// Verify that the new account is signed and writable, with correct
// ownership and size
if ( prm->ka_num != 2 ||
!valid_funding_account( &ka[0] ) ||
!valid_signable_account( prm, &ka[1], sizeof( pc_map_table_t ) ) ) {
return ERROR_INVALID_ARGUMENT;
}

// Check that the account has not already been initialized
pc_map_table_t *tptr = (pc_map_table_t*)ka[1].data;
if ( tptr->magic_ != 0 || tptr->ver_ != 0 ) {
return ERROR_INVALID_ARGUMENT;
}

// Initialize by setting to zero again (just in case) and setting
// the version number
cmd_hdr_t *hdr = (cmd_hdr_t*)prm->data;
sol_memset( tptr, 0, sizeof( pc_map_table_t ) );
tptr->magic_ = PC_MAGIC;
tptr->ver_ = hdr->ver_;
tptr->type_ = PC_ACCTYPE_MAPPING;
tptr->size_ = sizeof( pc_map_table_t ) - sizeof( tptr->prod_ );
return SUCCESS;
}

static uint64_t add_mapping( SolParameters *prm, SolAccountInfo *ka )
{
// Account (1) is the tail or last mapping account in the chain
Expand Down Expand Up @@ -539,7 +512,7 @@ static uint64_t dispatch( SolParameters *prm, SolAccountInfo *ka )
case e_cmd_agg_price: return upd_price( prm, ka );
case e_cmd_upd_price_no_fail_on_error: return upd_price_no_fail_on_error( prm, ka );
// init_mapping is overridden in Rust, but still implemented here to make the C unit tests pass.
case e_cmd_init_mapping: return init_mapping( prm, ka );
case e_cmd_init_mapping: return ERROR_INVALID_ARGUMENT;
case e_cmd_add_mapping: return add_mapping( prm, ka );
case e_cmd_add_product: return add_product( prm, ka );
case e_cmd_upd_product: return upd_product( prm, ka );
Expand Down
75 changes: 0 additions & 75 deletions program/c/src/oracle/test_oracle.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,81 +7,6 @@ uint64_t MAPPING_ACCOUNT_LAMPORTS = 143821440;
uint64_t PRODUCT_ACCOUNT_LAMPORTS = 4454400;
uint64_t PRICE_ACCOUNT_LAMPORTS = 23942400;

Test(oracle, init_mapping) {

// start with perfect inputs
cmd_hdr_t idata = {
.ver_ = PC_VERSION,
.cmd_ = e_cmd_init_mapping
};
SolPubkey p_id = {.x = { 0xff, }};
SolPubkey p_id2 = {.x = { 0xfe, }};
SolPubkey pkey = {.x = { 1, }};
SolPubkey mkey = {.x = { 2, }};
uint64_t pqty = 100;
pc_map_table_t mptr[1];
sol_memset( mptr, 0, sizeof( pc_map_table_t ) );
SolAccountInfo acc[] = {{
.key = &pkey,
.lamports = &pqty,
.data_len = 0,
.data = NULL,
.owner = NULL,
.rent_epoch = 0,
.is_signer = true,
.is_writable = true,
.executable = false
},{
.key = &mkey,
.lamports = &MAPPING_ACCOUNT_LAMPORTS,
.data_len = sizeof( pc_map_table_t ),
.data = (uint8_t*)mptr,
.owner = &p_id,
.rent_epoch = 0,
.is_signer = true,
.is_writable = true,
.executable = false
}};
SolParameters prm = {
.ka = acc,
.ka_num = 2,
.data = (const uint8_t*)&idata,
.data_len = sizeof( idata ),
.program_id = &p_id
};
cr_assert( SUCCESS == dispatch( &prm, acc ) );
cr_assert( mptr->ver_ == PC_VERSION );
cr_assert( mptr->type_ == PC_ACCTYPE_MAPPING );

// cant reinitialize because version has been set
cr_assert( ERROR_INVALID_ARGUMENT == dispatch( &prm, acc ) );
sol_memset( mptr, 0, sizeof( pc_map_table_t ) );

// check other params
prm.ka_num = 1;
cr_assert( ERROR_INVALID_ARGUMENT == dispatch( &prm, acc ) );
prm.ka_num = 2;
acc[0].is_signer = false;
cr_assert( ERROR_INVALID_ARGUMENT == dispatch( &prm, acc ) );
acc[0].is_signer = true;
acc[1].is_signer = false;
cr_assert( ERROR_INVALID_ARGUMENT == dispatch( &prm, acc ) );
acc[1].is_signer = true;
acc[0].is_writable = false;
cr_assert( ERROR_INVALID_ARGUMENT == dispatch( &prm, acc ) );
acc[0].is_writable = true;
acc[1].is_writable = false;
cr_assert( ERROR_INVALID_ARGUMENT == dispatch( &prm, acc ) );
acc[1].is_writable = true;
acc[1].owner = &p_id2;
cr_assert( ERROR_INVALID_ARGUMENT == dispatch( &prm, acc ) );
acc[1].owner = &p_id;
acc[1].data_len = 0;
cr_assert( ERROR_INVALID_ARGUMENT == dispatch( &prm, acc ) );
acc[1].data_len = sizeof( pc_map_table_t );
cr_assert( SUCCESS == dispatch( &prm, acc ) );
}

Test(oracle, add_mapping ) {
// start with perfect inputs
cmd_hdr_t idata = {
Expand Down
1 change: 1 addition & 0 deletions program/rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ mod error;
mod log;
mod processor;
mod rust_oracle;
mod test_oracle;
mod time_machine_types;

use crate::c_oracle_header::SUCCESSFULLY_UPDATED_AGGREGATE;
Expand Down
8 changes: 4 additions & 4 deletions program/rust/src/rust_oracle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ use bytemuck::{
try_from_bytes_mut,
Pod,
};
use solana_program::account_info::AccountInfo;
use solana_program::entrypoint::SUCCESS;
use solana_program::program_error::ProgramError;
use solana_program::program_memory::sol_memset;
use solana_program::pubkey::Pubkey;
use solana_program::rent::Rent;
use solana_program::sysvar::slot_history::AccountInfo;

use crate::c_oracle_header::{
cmd_hdr_t,
Expand Down Expand Up @@ -110,7 +110,7 @@ fn valid_fresh_account(account: &AccountInfo) -> bool {
}

/// Sets the data of account to all-zero
fn clear_account(account: &AccountInfo) -> Result<(), ProgramError> {
pub fn clear_account(account: &AccountInfo) -> Result<(), ProgramError> {
let mut data = account
.try_borrow_mut_data()
.map_err(|_| ProgramError::InvalidArgument)?;
Expand All @@ -131,7 +131,7 @@ fn load_mut<T: Pod>(data: &mut [u8]) -> Result<&mut T, ProgramError> {
}

/// Get the data stored in `account` as a value of type `T`
fn load_account_as<'a, T: Pod>(account: &'a AccountInfo) -> Result<Ref<'a, T>, ProgramError> {
pub fn load_account_as<'a, T: Pod>(account: &'a AccountInfo) -> Result<Ref<'a, T>, ProgramError> {
let data = account.try_borrow_data()?;

Ok(Ref::map(data, |data| {
Expand All @@ -141,7 +141,7 @@ fn load_account_as<'a, T: Pod>(account: &'a AccountInfo) -> Result<Ref<'a, T>, P

/// Mutably borrow the data in `account` as a value of type `T`.
/// Any mutations to the returned value will be reflected in the account data.
fn load_account_as_mut<'a, T: Pod>(
pub fn load_account_as_mut<'a, T: Pod>(
account: &'a AccountInfo,
) -> Result<RefMut<'a, T>, ProgramError> {
let data = account.try_borrow_mut_data()?;
Expand Down
182 changes: 182 additions & 0 deletions program/rust/src/test_oracle.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
#[cfg(test)]
mod test {
use crate::c_oracle_header::{
cmd_hdr_t,
command_t_e_cmd_init_mapping,
pc_map_table_t,
PC_ACCTYPE_MAPPING,
PC_MAGIC,
PC_VERSION,
};
use crate::rust_oracle::{
clear_account,
init_mapping,
load_account_as,
};
use bytemuck::bytes_of;
use solana_program::account_info::AccountInfo;
use solana_program::clock::Epoch;
use solana_program::native_token::LAMPORTS_PER_SOL;
use solana_program::program_error::ProgramError;
use solana_program::pubkey::Pubkey;
use solana_program::rent::Rent;
use solana_program::system_program;
use std::cell::RefCell;
use std::mem::size_of;
use std::rc::Rc;

#[test]
fn test_init_mapping() {
let hdr: cmd_hdr_t = cmd_hdr_t {
ver_: PC_VERSION,
cmd_: command_t_e_cmd_init_mapping as i32,
};
let instruction_data = bytes_of::<cmd_hdr_t>(&hdr);

let program_id = Pubkey::new_unique();
let program_id_2 = Pubkey::new_unique();
let funding_key = Pubkey::new_unique();
let mapping_key = Pubkey::new_unique();
let system_program = system_program::id();

let mut funding_balance = LAMPORTS_PER_SOL.clone();
let mut funding_account = AccountInfo::new(
&funding_key,
true,
true,
&mut funding_balance,
&mut [],
&system_program,
false,
Epoch::default(),
);

let mut mapping_balance =
Rent::minimum_balance(&Rent::default(), size_of::<pc_map_table_t>());
let mut mapping_raw_data = [0u8; size_of::<pc_map_table_t>()];

let mut mapping_account = AccountInfo::new(
&mapping_key,
true,
true,
&mut mapping_balance,
&mut mapping_raw_data,
&program_id,
false,
Epoch::default(),
);

assert!(init_mapping(
&program_id,
&[funding_account.clone(), mapping_account.clone()],
instruction_data
)
.is_ok());

{
let mapping_data = load_account_as::<pc_map_table_t>(&mapping_account).unwrap();

assert_eq!(mapping_data.ver_, PC_VERSION);
assert_eq!(mapping_data.magic_, PC_MAGIC);
assert_eq!(mapping_data.type_, PC_ACCTYPE_MAPPING);
assert_eq!(mapping_data.size_, 56);
}

assert_eq!(
init_mapping(
&program_id,
&[funding_account.clone(), mapping_account.clone()],
instruction_data
),
Err(ProgramError::InvalidArgument)
);

clear_account(&mapping_account).unwrap();

assert_eq!(
init_mapping(&program_id, &[funding_account.clone()], instruction_data),
Err(ProgramError::InvalidArgument)
);

funding_account.is_signer = false;

assert_eq!(
init_mapping(
&program_id,
&[funding_account.clone(), mapping_account.clone()],
instruction_data
),
Err(ProgramError::InvalidArgument)
);

funding_account.is_signer = true;
mapping_account.is_signer = false;

assert_eq!(
init_mapping(
&program_id,
&[funding_account.clone(), mapping_account.clone()],
instruction_data
),
Err(ProgramError::InvalidArgument)
);

mapping_account.is_signer = true;
funding_account.is_writable = false;

assert_eq!(
init_mapping(
&program_id,
&[funding_account.clone(), mapping_account.clone()],
instruction_data
),
Err(ProgramError::InvalidArgument)
);

funding_account.is_writable = true;
mapping_account.is_writable = false;

assert_eq!(
init_mapping(
&program_id,
&[funding_account.clone(), mapping_account.clone()],
instruction_data
),
Err(ProgramError::InvalidArgument)
);

mapping_account.is_writable = true;
mapping_account.owner = &program_id_2;

assert_eq!(
init_mapping(
&program_id,
&[funding_account.clone(), mapping_account.clone()],
instruction_data
),
Err(ProgramError::InvalidArgument)
);

mapping_account.owner = &program_id;
let prev_data = mapping_account.data;
mapping_account.data = Rc::new(RefCell::new(&mut []));

assert_eq!(
init_mapping(
&program_id,
&[funding_account.clone(), mapping_account.clone()],
instruction_data
),
Err(ProgramError::InvalidArgument)
);

mapping_account.data = prev_data;

assert!(init_mapping(
&program_id,
&[funding_account.clone(), mapping_account.clone()],
instruction_data
)
.is_ok());
}
}