Skip to content

Commit

Permalink
test: test aggregation toggle
Browse files Browse the repository at this point in the history
  • Loading branch information
Reisen committed Jul 10, 2024
1 parent 847b3f5 commit e91ffb8
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 62 deletions.
3 changes: 3 additions & 0 deletions program/c/src/oracle/upd_aggregate.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ static inline bool upd_aggregate( pc_price_t *ptr, uint64_t slot, int64_t timest
ptr->num_qt_ = numv;
if ( numv == 0 || numv < ptr->min_pub_ ) {
ptr->agg_.status_ = PC_STATUS_UNKNOWN;
__builtin_printf("numv == 0 || numv < min_pub_ %d\n", numv);
return false;
}

Expand All @@ -206,6 +207,7 @@ static inline bool upd_aggregate( pc_price_t *ptr, uint64_t slot, int64_t timest
// positive confidences given the current pricing model
if( agg_conf <= (int64_t)0 ) {
ptr->agg_.status_ = PC_STATUS_UNKNOWN;
__builtin_printf("agg_conf <= 0\n");
return false;
}
}
Expand All @@ -216,6 +218,7 @@ static inline bool upd_aggregate( pc_price_t *ptr, uint64_t slot, int64_t timest
ptr->agg_.price_ = agg_price;
ptr->agg_.conf_ = (uint64_t)agg_conf;

__builtin_printf("success\n");
return true;
}

Expand Down
2 changes: 1 addition & 1 deletion program/rust/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![deny(warnings)]
// #![deny(warnings)]
// Allow non upper case globals from C
#![allow(non_upper_case_globals)]

Expand Down
182 changes: 121 additions & 61 deletions program/rust/src/tests/test_aggregate_v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,96 +6,156 @@ use {
PriceAccountFlags,
PythAccount,
},
c_oracle_header::PC_VERSION,
deserialize::load_checked,
c_oracle_header::{PC_STATUS_TRADING, PC_VERSION},
deserialize::{load_checked, load_mut},
instruction::{
AddPublisherArgs,
OracleCommand,
OracleCommand, UpdPriceArgs,
},
processor::{
process_instruction,
ENABLE_ACCUMULATOR_V2,
process_instruction, DISABLE_ACCUMULATOR_V2, ENABLE_ACCUMULATOR_V2
},
tests::test_utils::AccountSetup,
},
bytemuck::bytes_of,
solana_program::{
tests::test_utils::{update_clock_slot, AccountSetup},
}, bytemuck::bytes_of, solana_program::{
pubkey::Pubkey,
rent::Rent,
},
}, solana_sdk::account_info::AccountInfo, std::mem::size_of
};

#[test]
fn test_aggregate_v2() {
let program_id = Pubkey::new_unique();
let publisher = Pubkey::new_unique();

let mut cmd = AddPublisherArgs {
header: OracleCommand::AddPublisher.into(),
publisher,
};
let mut instruction_data = bytes_of::<AddPublisherArgs>(&cmd);

let mut funding_setup = AccountSetup::new_funding();
let funding_account = funding_setup.as_account_info();
struct Accounts {
program_id: Pubkey,
publisher_account: AccountSetup,
funding_account: AccountSetup,
price_account: AccountSetup,
permissions_account: AccountSetup,
clock_account: AccountSetup,
}

let mut price_setup = AccountSetup::new::<PriceAccount>(&program_id);
let price_account = price_setup.as_account_info();
PriceAccount::initialize(&price_account, PC_VERSION).unwrap();
impl Accounts {
fn new() -> Self {
let program_id = Pubkey::new_unique();
let publisher_account = AccountSetup::new_funding();
let clock_account = AccountSetup::new_clock();
let mut funding_account = AccountSetup::new_funding();
let mut permissions_account = AccountSetup::new_permission(&program_id);
let mut price_account = AccountSetup::new::<PriceAccount>(&program_id);

**price_account.try_borrow_mut_lamports().unwrap() = 100;
PriceAccount::initialize(&price_account.as_account_info(), PC_VERSION).unwrap();

let mut permissions_setup = AccountSetup::new_permission(&program_id);
let permissions_account = permissions_setup.as_account_info();
{
let permissions_account_info = permissions_account.as_account_info();
let mut permissions_account_data =
PermissionAccount::initialize(&permissions_account_info, PC_VERSION).unwrap();
permissions_account_data.master_authority = *funding_account.as_account_info().key;
permissions_account_data.data_curation_authority = *funding_account.as_account_info().key;
permissions_account_data.security_authority = *funding_account.as_account_info().key;
}

{
let mut permissions_account_data =
PermissionAccount::initialize(&permissions_account, PC_VERSION).unwrap();
permissions_account_data.master_authority = *funding_account.key;
permissions_account_data.data_curation_authority = *funding_account.key;
permissions_account_data.security_authority = *funding_account.key;
Self {
program_id,
publisher_account,
funding_account,
price_account,
permissions_account,
clock_account,
}
}
}

// Give the price account enough lamports to be rent exempt
**price_account.try_borrow_mut_lamports().unwrap() =
Rent::minimum_balance(&Rent::default(), PriceAccount::MINIMUM_SIZE);
fn add_publisher(accounts: &mut Accounts, publisher: Option<Pubkey>) {
let args = AddPublisherArgs {
header: OracleCommand::AddPublisher.into(),
publisher: publisher.unwrap_or(*accounts.publisher_account.as_account_info().key),
};

assert!(process_instruction(
&program_id,
&accounts.program_id,
&[
funding_account.clone(),
price_account.clone(),
permissions_account.clone(),
accounts.funding_account.as_account_info(),
accounts.price_account.as_account_info(),
accounts.permissions_account.as_account_info(),
],
instruction_data
bytes_of::<AddPublisherArgs>(&args)
)
.is_ok());
}

{
let price_data = load_checked::<PriceAccount>(&price_account, PC_VERSION).unwrap();
assert_eq!(price_data.num_, 1);
assert_eq!(price_data.header.size, PriceAccount::INITIAL_SIZE);
assert!(price_data.comp_[0].pub_ == publisher);
// Make sure that v2 aggregation is disabled
assert!(!price_data.flags.contains(PriceAccountFlags::ACCUMULATOR_V2));
}
fn update_price(accounts: &mut Accounts, price: i64, conf: u64, slot: u64) {
let instruction_data = &mut [0u8; size_of::<UpdPriceArgs>()];
let mut cmd = load_mut::<UpdPriceArgs>(instruction_data).unwrap();
cmd.header = OracleCommand::UpdPrice.into();
cmd.status = PC_STATUS_TRADING;
cmd.price = price;
cmd.confidence = conf;
cmd.publishing_slot = slot;
cmd.unused_ = 0;

cmd.publisher = ENABLE_ACCUMULATOR_V2.into();
instruction_data = bytes_of::<AddPublisherArgs>(&cmd);
assert!(process_instruction(
&program_id,
let mut clock = accounts.clock_account.as_account_info();
clock.is_signer = false;
clock.is_writable = false;

process_instruction(
&accounts.program_id,
&[
funding_account.clone(),
price_account.clone(),
permissions_account.clone(),
accounts.publisher_account.as_account_info(),
accounts.price_account.as_account_info(),
clock,
],
instruction_data
)
.is_ok());
.unwrap();
}

#[test]
fn test_aggregate_v2_toggle() {
let accounts = &mut Accounts::new();

// Add an initial Publisher to test with.
add_publisher(accounts, None);

// Update the price, no aggregation will happen on the first slot.
{
update_clock_slot(&mut accounts.clock_account.as_account_info(), 1);
update_price(accounts, 42, 2, 1);
let info = accounts.price_account.as_account_info();
let price_data = load_checked::<PriceAccount>(&info, PC_VERSION).unwrap();
assert_eq!(price_data.last_slot_, 0);
assert!(!price_data.flags.contains(PriceAccountFlags::ACCUMULATOR_V2));
}

// Update again, component is now TRADING so aggregation should trigger.
{
update_clock_slot(&mut accounts.clock_account.as_account_info(), 2);
update_price(accounts, 42, 2, 2);
let info = accounts.price_account.as_account_info();
let price_data = load_checked::<PriceAccount>(&info, PC_VERSION).unwrap();
assert_eq!(price_data.last_slot_, 2);
assert!(!price_data.flags.contains(PriceAccountFlags::ACCUMULATOR_V2));
}

// Make sure that v2 aggregation is enabled
// Enable v2 Aggregation
add_publisher(accounts, Some(ENABLE_ACCUMULATOR_V2.into()));

// Update again, with accumulator bit set, aggregation should not have
// happened, as its now the validators job.
{
let price_data = load_checked::<PriceAccount>(&price_account, PC_VERSION).unwrap();
update_clock_slot(&mut accounts.clock_account.as_account_info(), 3);
update_price(accounts, 42, 2, 3);
let info = accounts.price_account.as_account_info();
let price_data = load_checked::<PriceAccount>(&info, PC_VERSION).unwrap();
assert_eq!(price_data.last_slot_, 2);
assert!(price_data.flags.contains(PriceAccountFlags::ACCUMULATOR_V2));
}

add_publisher(accounts, Some(DISABLE_ACCUMULATOR_V2.into()));

// Confirm disabling v2 Aggregation re-enables the aggregation flow.
{
update_clock_slot(&mut accounts.clock_account.as_account_info(), 4);
update_price(accounts, 42, 2, 4);
let info = accounts.price_account.as_account_info();
let price_data = load_checked::<PriceAccount>(&info, PC_VERSION).unwrap();
assert_eq!(price_data.last_slot_, 4);
assert!(!price_data.flags.contains(PriceAccountFlags::ACCUMULATOR_V2));
}
}

0 comments on commit e91ffb8

Please sign in to comment.