|
6 | 6 | AccountIndex, AccountSecondaryIndexes, AccountSecondaryIndexesIncludeExclude,
|
7 | 7 | },
|
8 | 8 | bank::{
|
9 |
| - pyth_accumulator::{get_accumulator_keys, ACCUMULATOR_RING_SIZE, ORACLE_PID}, |
| 9 | + pyth_accumulator::{ |
| 10 | + get_accumulator_keys, ACCUMULATOR_RING_SIZE, BATCH_PUBLISH_PID, ORACLE_PID, |
| 11 | + }, |
| 12 | + pyth_batch_publish::publisher_prices_account::{self, PublisherPrice}, |
10 | 13 | Bank,
|
11 | 14 | },
|
12 | 15 | genesis_utils::{create_genesis_config_with_leader, GenesisConfigInfo},
|
13 | 16 | },
|
| 17 | + bytemuck::{cast_slice, checked::from_bytes}, |
14 | 18 | byteorder::{ByteOrder, LittleEndian, ReadBytesExt},
|
15 | 19 | itertools::Itertools,
|
16 | 20 | pyth_oracle::{
|
@@ -45,7 +49,9 @@ fn create_new_bank_for_tests_with_index(genesis_config: &GenesisConfig) -> Bank
|
45 | 49 | AccountSecondaryIndexes {
|
46 | 50 | keys: Some(AccountSecondaryIndexesIncludeExclude {
|
47 | 51 | exclude: false,
|
48 |
| - keys: [*ORACLE_PID, *MESSAGE_BUFFER_PID].into_iter().collect(), |
| 52 | + keys: [*ORACLE_PID, *MESSAGE_BUFFER_PID, *BATCH_PUBLISH_PID] |
| 53 | + .into_iter() |
| 54 | + .collect(), |
49 | 55 | }),
|
50 | 56 | indexes: [AccountIndex::ProgramId].into_iter().collect(),
|
51 | 57 | },
|
@@ -899,3 +905,128 @@ fn test_get_accumulator_keys() {
|
899 | 905 | ];
|
900 | 906 | assert_eq!(accumulator_keys, expected_pyth_keys);
|
901 | 907 | }
|
| 908 | + |
| 909 | +#[test] |
| 910 | +fn test_batch_publish() { |
| 911 | + let leader_pubkey = solana_sdk::pubkey::new_rand(); |
| 912 | + let GenesisConfigInfo { |
| 913 | + mut genesis_config, .. |
| 914 | + } = create_genesis_config_with_leader(5, &leader_pubkey, 3); |
| 915 | + |
| 916 | + // Set epoch length to 32 so we can advance epochs quickly. We also skip past slot 0 here |
| 917 | + // due to slot 0 having special handling. |
| 918 | + let slots_in_epoch = 32; |
| 919 | + genesis_config.epoch_schedule = EpochSchedule::new(slots_in_epoch); |
| 920 | + let mut bank = create_new_bank_for_tests_with_index(&genesis_config); |
| 921 | + |
| 922 | + let generate_publisher = |seed, new_prices| { |
| 923 | + let publisher1_key = keypair_from_seed(seed).unwrap(); |
| 924 | + |
| 925 | + let (publisher1_prices_key, _bump) = Pubkey::find_program_address( |
| 926 | + // TODO: real seed |
| 927 | + &[ |
| 928 | + b"PUBLISHER_PRICES_ACCOUNT", |
| 929 | + &publisher1_key.pubkey().to_bytes(), |
| 930 | + ], |
| 931 | + &BATCH_PUBLISH_PID, |
| 932 | + ); |
| 933 | + let mut publisher1_prices_account = |
| 934 | + AccountSharedData::new(42, publisher_prices_account::size(100), &BATCH_PUBLISH_PID); |
| 935 | + { |
| 936 | + let (header, prices) = publisher_prices_account::create( |
| 937 | + publisher1_prices_account.data_mut(), |
| 938 | + publisher1_key.pubkey().to_bytes(), |
| 939 | + ) |
| 940 | + .unwrap(); |
| 941 | + publisher_prices_account::extend(header, prices, cast_slice(new_prices)).unwrap(); |
| 942 | + } |
| 943 | + bank.store_account(&publisher1_prices_key, &publisher1_prices_account); |
| 944 | + |
| 945 | + publisher1_key |
| 946 | + }; |
| 947 | + |
| 948 | + let publishers = [ |
| 949 | + generate_publisher( |
| 950 | + &[1u8; 32], |
| 951 | + &[ |
| 952 | + PublisherPrice::new(1, 1, 10, 2).unwrap(), |
| 953 | + PublisherPrice::new(2, 1, 20, 3).unwrap(), |
| 954 | + ], |
| 955 | + ), |
| 956 | + generate_publisher( |
| 957 | + &[2u8; 32], |
| 958 | + &[ |
| 959 | + PublisherPrice::new(1, 1, 15, 2).unwrap(), |
| 960 | + PublisherPrice::new(2, 1, 25, 3).unwrap(), |
| 961 | + ], |
| 962 | + ), |
| 963 | + ]; |
| 964 | + |
| 965 | + let generate_price = |seeds, index| { |
| 966 | + let (price_feed_key, _bump) = Pubkey::find_program_address(&[seeds], &ORACLE_PID); |
| 967 | + let mut price_feed_account = |
| 968 | + AccountSharedData::new(42, size_of::<PriceAccount>(), &ORACLE_PID); |
| 969 | + |
| 970 | + let messages = { |
| 971 | + let price_feed_info_key = &price_feed_key.to_bytes().into(); |
| 972 | + let price_feed_info_lamports = &mut 0; |
| 973 | + let price_feed_info_owner = &ORACLE_PID.to_bytes().into(); |
| 974 | + let price_feed_info_data = price_feed_account.data_mut(); |
| 975 | + let price_feed_info = AccountInfo::new( |
| 976 | + price_feed_info_key, |
| 977 | + false, |
| 978 | + true, |
| 979 | + price_feed_info_lamports, |
| 980 | + price_feed_info_data, |
| 981 | + price_feed_info_owner, |
| 982 | + false, |
| 983 | + Epoch::default(), |
| 984 | + ); |
| 985 | + |
| 986 | + let mut price_account = PriceAccount::initialize(&price_feed_info, 0).unwrap(); |
| 987 | + price_account.flags.insert( |
| 988 | + PriceAccountFlags::ACCUMULATOR_V2 | PriceAccountFlags::MESSAGE_BUFFER_CLEARED, |
| 989 | + ); |
| 990 | + price_account.unused_3_ = index; |
| 991 | + price_account.comp_[0].pub_ = publishers[0].pubkey().to_bytes().into(); |
| 992 | + price_account.comp_[1].pub_ = publishers[1].pubkey().to_bytes().into(); |
| 993 | + price_account.num_ = 2; |
| 994 | + }; |
| 995 | + |
| 996 | + bank.store_account(&price_feed_key, &price_feed_account); |
| 997 | + (price_feed_key, messages) |
| 998 | + }; |
| 999 | + |
| 1000 | + assert!(bank |
| 1001 | + .feature_set |
| 1002 | + .is_active(&feature_set::enable_accumulator_sysvar::id())); |
| 1003 | + assert!(bank |
| 1004 | + .feature_set |
| 1005 | + .is_active(&feature_set::move_accumulator_to_end_of_block::id())); |
| 1006 | + assert!(bank |
| 1007 | + .feature_set |
| 1008 | + .is_active(&feature_set::undo_move_accumulator_to_end_of_block::id())); |
| 1009 | + assert!(bank |
| 1010 | + .feature_set |
| 1011 | + .is_active(&feature_set::redo_move_accumulator_to_end_of_block::id())); |
| 1012 | + |
| 1013 | + let prices_with_messages = [ |
| 1014 | + generate_price(b"seeds_1", 1), |
| 1015 | + generate_price(b"seeds_2", 2), |
| 1016 | + generate_price(b"seeds_3", 3), |
| 1017 | + generate_price(b"seeds_4", 4), |
| 1018 | + ]; |
| 1019 | + |
| 1020 | + bank = new_from_parent(&Arc::new(bank)); // Advance slot 1. |
| 1021 | + bank = new_from_parent(&Arc::new(bank)); // Advance slot 2. |
| 1022 | + |
| 1023 | + let new_price_feed1_account = bank.get_account(&prices_with_messages[0].0).unwrap(); |
| 1024 | + let new_price_feed1_data: &PriceAccount = from_bytes(new_price_feed1_account.data()); |
| 1025 | + assert_eq!(new_price_feed1_data.comp_[0].latest_.price_, 10); |
| 1026 | + assert_eq!(new_price_feed1_data.comp_[1].latest_.price_, 15); |
| 1027 | + |
| 1028 | + let new_price_feed2_account = bank.get_account(&prices_with_messages[1].0).unwrap(); |
| 1029 | + let new_price_feed2_data: &PriceAccount = from_bytes(new_price_feed2_account.data()); |
| 1030 | + assert_eq!(new_price_feed2_data.comp_[0].latest_.price_, 20); |
| 1031 | + assert_eq!(new_price_feed2_data.comp_[1].latest_.price_, 25); |
| 1032 | +} |
0 commit comments