Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7ba1540

Browse files
committed
checkpoint
1 parent 7aae599 commit 7ba1540

File tree

1 file changed

+233
-109
lines changed

1 file changed

+233
-109
lines changed

runtime/src/bank/pyth_accumulator_tests.rs

Lines changed: 233 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,11 @@ use {
1414
byteorder::{ByteOrder, LittleEndian, ReadBytesExt},
1515
itertools::Itertools,
1616
pyth_oracle::{
17-
solana_program::account_info::AccountInfo, PriceAccount, PriceAccountFlags, PythAccount,
17+
solana_program::{account_info::AccountInfo, message}, PriceAccount, PriceAccountFlags, PythAccount,
1818
PythOracleSerialize,
1919
},
2020
pythnet_sdk::{
21-
accumulators::{merkle::MerkleAccumulator, Accumulator},
22-
hashers::{keccak256_160::Keccak160, Hasher},
23-
wormhole::{AccumulatorSequenceTracker, MessageData, PostedMessageUnreliableData},
24-
ACCUMULATOR_EMITTER_ADDRESS,
21+
accumulators::{merkle::MerkleAccumulator, Accumulator}, hashers::{keccak256_160::Keccak160, Hasher}, publisher_stake_caps::StakeCapParameters, wormhole::{AccumulatorSequenceTracker, MessageData, PostedMessageUnreliableData}, ACCUMULATOR_EMITTER_ADDRESS
2522
},
2623
solana_sdk::{
2724
account::{AccountSharedData, ReadableAccount, WritableAccount},
@@ -694,119 +691,76 @@ fn test_accumulator_v2_mixed() {
694691
test_accumulator_v2([true, true, false, false]);
695692
}
696693

697-
fn test_accumulator_v2(generate_buffers: [bool; 4]) {
698-
let leader_pubkey = solana_sdk::pubkey::new_rand();
699-
let GenesisConfigInfo {
700-
mut genesis_config, ..
701-
} = create_genesis_config_with_leader(5, &leader_pubkey, 3);
702-
703-
// Set epoch length to 32 so we can advance epochs quickly. We also skip past slot 0 here
704-
// due to slot 0 having special handling.
705-
let slots_in_epoch = 32;
706-
genesis_config.epoch_schedule = EpochSchedule::new(slots_in_epoch);
707-
let mut bank = create_new_bank_for_tests_with_index(&genesis_config);
694+
fn generate_price(bank : &Bank, seeds: &[u8], generate_buffers: bool, publishers : &[Pubkey]) -> (Pubkey, Vec<Vec<u8>>) {
695+
let (price_feed_key, _bump) = Pubkey::find_program_address(&[seeds], &ORACLE_PID);
696+
let mut price_feed_account =
697+
AccountSharedData::new(42, size_of::<PriceAccount>(), &ORACLE_PID);
698+
699+
let messages = {
700+
let price_feed_info_key = &price_feed_key.to_bytes().into();
701+
let price_feed_info_lamports = &mut 0;
702+
let price_feed_info_owner = &ORACLE_PID.to_bytes().into();
703+
let price_feed_info_data = price_feed_account.data_mut();
704+
let price_feed_info = AccountInfo::new(
705+
price_feed_info_key,
706+
false,
707+
true,
708+
price_feed_info_lamports,
709+
price_feed_info_data,
710+
price_feed_info_owner,
711+
false,
712+
Epoch::default(),
713+
);
708714

709-
let generate_price = |seeds, generate_buffers: bool| {
710-
let (price_feed_key, _bump) = Pubkey::find_program_address(&[seeds], &ORACLE_PID);
711-
let mut price_feed_account =
712-
AccountSharedData::new(42, size_of::<PriceAccount>(), &ORACLE_PID);
713-
714-
let messages = {
715-
let price_feed_info_key = &price_feed_key.to_bytes().into();
716-
let price_feed_info_lamports = &mut 0;
717-
let price_feed_info_owner = &ORACLE_PID.to_bytes().into();
718-
let price_feed_info_data = price_feed_account.data_mut();
719-
let price_feed_info = AccountInfo::new(
720-
price_feed_info_key,
721-
false,
722-
true,
723-
price_feed_info_lamports,
724-
price_feed_info_data,
725-
price_feed_info_owner,
726-
false,
727-
Epoch::default(),
715+
let mut price_account = PriceAccount::initialize(&price_feed_info, 0).unwrap();
716+
if !generate_buffers {
717+
price_account.flags.insert(
718+
PriceAccountFlags::ACCUMULATOR_V2 | PriceAccountFlags::MESSAGE_BUFFER_CLEARED,
728719
);
729-
730-
let mut price_account = PriceAccount::initialize(&price_feed_info, 0).unwrap();
731-
if !generate_buffers {
732-
price_account.flags.insert(
733-
PriceAccountFlags::ACCUMULATOR_V2 | PriceAccountFlags::MESSAGE_BUFFER_CLEARED,
734-
);
735-
}
736-
737-
vec![
738-
price_account
739-
.as_price_feed_message(&price_feed_key.to_bytes().into())
740-
.to_bytes(),
741-
price_account
742-
.as_twap_message(&price_feed_key.to_bytes().into())
743-
.to_bytes(),
744-
]
745-
};
746-
747-
bank.store_account(&price_feed_key, &price_feed_account);
748-
749-
if generate_buffers {
750-
let message_buffer_bytes = create_message_buffer_bytes(messages.clone());
751-
752-
let mut seed = vec![1; 32];
753-
seed[..seeds.len()].copy_from_slice(seeds);
754-
// Create a Message account.
755-
let price_message_key = keypair_from_seed(&seed).unwrap();
756-
let mut price_message_account = bank
757-
.get_account(&price_message_key.pubkey())
758-
.unwrap_or_default();
759-
760-
price_message_account.set_lamports(1_000_000_000);
761-
price_message_account
762-
.set_owner(Pubkey::new_from_array(pythnet_sdk::MESSAGE_BUFFER_PID));
763-
price_message_account.set_data(message_buffer_bytes);
764-
765-
// Store Message account so the accumulator sysvar updater can find it.
766-
bank.store_account(&price_message_key.pubkey(), &price_message_account);
720+
}
721+
price_account.num_ = publishers.len() as u32;
722+
for (i, publisher) in publishers.into_iter().enumerate() {
723+
price_account.comp_[i].pub_ = publisher.to_bytes().into();
767724
}
768725

769-
(price_feed_key, messages)
726+
vec![
727+
price_account
728+
.as_price_feed_message(&price_feed_key.to_bytes().into())
729+
.to_bytes(),
730+
price_account
731+
.as_twap_message(&price_feed_key.to_bytes().into())
732+
.to_bytes(),
733+
]
770734
};
771735

772-
assert!(bank
773-
.feature_set
774-
.is_active(&feature_set::enable_accumulator_sysvar::id()));
775-
assert!(bank
776-
.feature_set
777-
.is_active(&feature_set::move_accumulator_to_end_of_block::id()));
778-
assert!(bank
779-
.feature_set
780-
.is_active(&feature_set::undo_move_accumulator_to_end_of_block::id()));
781-
assert!(bank
782-
.feature_set
783-
.is_active(&feature_set::redo_move_accumulator_to_end_of_block::id()));
784-
785-
let prices_with_messages = [
786-
generate_price(b"seeds_1", generate_buffers[0]),
787-
generate_price(b"seeds_2", generate_buffers[1]),
788-
generate_price(b"seeds_3", generate_buffers[2]),
789-
generate_price(b"seeds_4", generate_buffers[3]),
790-
];
791-
792-
bank = new_from_parent(&Arc::new(bank)); // Advance slot 1.
793-
bank = new_from_parent(&Arc::new(bank)); // Advance slot 2.
736+
bank.store_account(&price_feed_key, &price_feed_account);
794737

795-
let messages = prices_with_messages
796-
.iter()
797-
.flat_map(|(_, messages)| messages)
798-
.map(|message| &message[..])
799-
.sorted_unstable()
800-
.dedup()
801-
.collect::<Vec<_>>();
802-
assert_eq!(messages.len(), 8);
738+
if generate_buffers {
739+
let message_buffer_bytes = create_message_buffer_bytes(messages.clone());
740+
741+
let mut seed = vec![1; 32];
742+
seed[..seeds.len()].copy_from_slice(seeds);
743+
// Create a Message account.
744+
let price_message_key = keypair_from_seed(&seed).unwrap();
745+
let mut price_message_account = bank
746+
.get_account(&price_message_key.pubkey())
747+
.unwrap_or_default();
748+
749+
price_message_account.set_lamports(1_000_000_000);
750+
price_message_account
751+
.set_owner(Pubkey::new_from_array(pythnet_sdk::MESSAGE_BUFFER_PID));
752+
price_message_account.set_data(message_buffer_bytes);
753+
754+
// Store Message account so the accumulator sysvar updater can find it.
755+
bank.store_account(&price_message_key.pubkey(), &price_message_account);
756+
757+
}
803758

804-
// Trigger Aggregation. We freeze instead of new_from_parent so
805-
// we can keep access to the bank.
806-
let sequence_tracker_before_bank_freeze = get_acc_sequence_tracker(&bank);
807-
bank.freeze();
759+
(price_feed_key, messages)
760+
}
808761

809-
// Get the wormhole message generated by freezed. We don't need
762+
fn check_accumulator_state_matches_messages(bank: &Bank, sequence_tracker_before_bank_freeze: &AccumulatorSequenceTracker, messages: &[&[u8]]) {
763+
// Get the wormhole message generated by freezed. We don't need
810764
// to offset the ring index as our test is always below 10K slots.
811765
let wormhole_message_account = get_wormhole_message_account(&bank, bank.slot() as u32);
812766
assert_ne!(wormhole_message_account.data().len(), 0);
@@ -883,6 +837,176 @@ fn test_accumulator_v2(generate_buffers: [bool; 4]) {
883837
sequence_tracker_before_bank_freeze.sequence + 1
884838
);
885839
}
840+
841+
fn test_accumulator_v2(generate_buffers: [bool; 4]) {
842+
let leader_pubkey = solana_sdk::pubkey::new_rand();
843+
let GenesisConfigInfo {
844+
mut genesis_config, ..
845+
} = create_genesis_config_with_leader(5, &leader_pubkey, 3);
846+
847+
genesis_config
848+
.accounts
849+
.remove(&feature_set::add_publisher_stake_caps_to_the_accumulator::id())
850+
.unwrap();
851+
852+
// Set epoch length to 32 so we can advance epochs quickly. We also skip past slot 0 here
853+
// due to slot 0 having special handling.
854+
let slots_in_epoch = 32;
855+
genesis_config.epoch_schedule = EpochSchedule::new(slots_in_epoch);
856+
let mut bank = create_new_bank_for_tests_with_index(&genesis_config);
857+
858+
assert!(bank
859+
.feature_set
860+
.is_active(&feature_set::enable_accumulator_sysvar::id()));
861+
assert!(bank
862+
.feature_set
863+
.is_active(&feature_set::move_accumulator_to_end_of_block::id()));
864+
assert!(bank
865+
.feature_set
866+
.is_active(&feature_set::undo_move_accumulator_to_end_of_block::id()));
867+
assert!(bank
868+
.feature_set
869+
.is_active(&feature_set::redo_move_accumulator_to_end_of_block::id()));
870+
871+
let prices_with_messages = [
872+
generate_price(&bank, b"seeds_1", generate_buffers[0], &[]),
873+
generate_price(&bank, b"seeds_2", generate_buffers[1], &[]),
874+
generate_price(&bank,b"seeds_3", generate_buffers[2], &[]),
875+
generate_price(&bank,b"seeds_4", generate_buffers[3], &[])
876+
];
877+
878+
bank = new_from_parent(&Arc::new(bank)); // Advance slot 1.
879+
bank = new_from_parent(&Arc::new(bank)); // Advance slot 2.
880+
881+
let messages = prices_with_messages
882+
.iter()
883+
.flat_map(|(_, messages)| messages)
884+
.map(|message| &message[..])
885+
.sorted_unstable()
886+
.dedup()
887+
.collect::<Vec<_>>();
888+
assert_eq!(messages.len(), 8);
889+
890+
// Trigger Aggregation. We freeze instead of new_from_parent so
891+
// we can keep access to the bank.
892+
let sequence_tracker_before_bank_freeze = get_acc_sequence_tracker(&bank);
893+
bank.freeze();
894+
895+
check_accumulator_state_matches_messages(&bank, &sequence_tracker_before_bank_freeze, &messages);
896+
}
897+
898+
#[test]
899+
fn test_publisher_stake_caps() {
900+
let leader_pubkey = solana_sdk::pubkey::new_rand();
901+
let GenesisConfigInfo {
902+
mut genesis_config, ..
903+
} = create_genesis_config_with_leader(5, &leader_pubkey, 3);
904+
905+
genesis_config
906+
.accounts
907+
.remove(&feature_set::add_publisher_stake_caps_to_the_accumulator::id())
908+
.unwrap();
909+
910+
// Set epoch length to 32 so we can advance epochs quickly. We also skip past slot 0 here
911+
// due to slot 0 having special handling.
912+
let slots_in_epoch = 32;
913+
genesis_config.epoch_schedule = EpochSchedule::new(slots_in_epoch);
914+
let mut bank = create_new_bank_for_tests_with_index(&genesis_config);
915+
916+
assert!(bank
917+
.feature_set
918+
.is_active(&feature_set::enable_accumulator_sysvar::id()));
919+
assert!(bank
920+
.feature_set
921+
.is_active(&feature_set::move_accumulator_to_end_of_block::id()));
922+
assert!(bank
923+
.feature_set
924+
.is_active(&feature_set::undo_move_accumulator_to_end_of_block::id()));
925+
assert!(bank
926+
.feature_set
927+
.is_active(&feature_set::redo_move_accumulator_to_end_of_block::id()));
928+
929+
let new_m = 1_000_000_000_000;
930+
let new_z = 3;
931+
932+
let mut publishers_with_expected_caps : [(Pubkey, u64, u64) ; 4] = [
933+
(solana_sdk::pubkey::new_rand(),StakeCapParameters::default().m * 5 / 4, new_m / 3 + new_m / 4),
934+
(solana_sdk::pubkey::new_rand(),StakeCapParameters::default().m * 3 / 4, new_m / 3 + new_m / 4),
935+
(solana_sdk::pubkey::new_rand(),StakeCapParameters::default().m * 3 / 4, new_m / 3 + new_m / 4),
936+
(solana_sdk::pubkey::new_rand(),StakeCapParameters::default().m * 5 / 4, new_m / 3 + new_m / 4)
937+
];
938+
939+
let expected_caps = [[
940+
StakeCapParameters::default().m * 5 / 4,
941+
StakeCapParameters::default().m * 3 / 4,
942+
StakeCapParameters::default().m * 2 / 4,
943+
StakeCapParameters::default().m * 1 / 4,
944+
],[new_m / 3 + new_m / 4,new_m / 3 + new_m / 4,new_m / 3 + new_m / 4,new_m / 3 + new_m / 4 ]];
945+
946+
let prices_with_messages = [
947+
generate_price(&bank, b"seeds_1", false, &[publishers_with_expected_caps[0].0]),
948+
generate_price(&bank, b"seeds_2", false, &[publishers_with_expected_caps[1].0, publishers_with_expected_caps[2].0]),
949+
generate_price(&bank,b"seeds_3", true, &[publishers_with_expected_caps[3].0]),
950+
generate_price(&bank,b"seeds_4", true, &[publishers_with_expected_caps[3].0, publishers_with_expected_caps[1].0, publishers_with_expected_caps[0].0, publishers_with_expected_caps[2].0])
951+
];
952+
953+
publishers_with_expected_caps.sort_by_key(|(pk,_,_)| *pk);
954+
955+
bank = new_from_parent(&Arc::new(bank)); // Advance slot 1.
956+
bank = new_from_parent(&Arc::new(bank)); // Advance slot 2.
957+
958+
959+
let mut messages = prices_with_messages
960+
.iter()
961+
.flat_map(|(_, messages)| messages)
962+
.map(|message| &message[..])
963+
.sorted_unstable()
964+
.dedup()
965+
.collect::<Vec<_>>();
966+
assert_eq!(messages.len(), 8);
967+
968+
let feature_id = feature_set::add_publisher_stake_caps_to_the_accumulator::id();
969+
let feature = Feature {
970+
activated_at: Some(30),
971+
};
972+
bank.store_account(&feature_id, &feature::create_account(&feature, 42));
973+
974+
bank.compute_active_feature_set(true);
975+
976+
// Trigger Aggregation. We freeze instead of new_from_parent so
977+
// we can keep access to the bank.
978+
let sequence_tracker_before_bank_freeze = get_acc_sequence_tracker(&bank);
979+
bank.freeze();
980+
981+
check_accumulator_state_matches_messages(&bank, &sequence_tracker_before_bank_freeze, &messages);
982+
983+
// Enable Publisher Stake Caps
984+
985+
for _ in 0..slots_in_epoch {
986+
bank = new_from_parent(&Arc::new(bank));
987+
}
988+
989+
let publisher_caps_message = {
990+
let mut result = vec![];
991+
result.extend_from_slice(&bank.unix_timestamp_from_genesis().to_be_bytes());
992+
result.extend_from_slice(&4u16.to_be_bytes());
993+
for (pk, m, _) in publishers_with_expected_caps {
994+
result.extend_from_slice(&pk.to_bytes());
995+
result.extend_from_slice(&m.to_be_bytes()); }
996+
result
997+
};
998+
999+
1000+
messages.push(&publisher_caps_message);
1001+
1002+
let sequence_tracker_before_bank_freeze = get_acc_sequence_tracker(&bank);
1003+
bank.freeze();
1004+
check_accumulator_state_matches_messages(&bank, &sequence_tracker_before_bank_freeze, &messages);
1005+
1006+
1007+
}
1008+
1009+
8861010
#[test]
8871011
fn test_get_accumulator_keys() {
8881012
use pythnet_sdk::{pythnet, ACCUMULATOR_EMITTER_ADDRESS, MESSAGE_BUFFER_PID};

0 commit comments

Comments
 (0)