|
|
@@ -1,10 +1,12 @@
|
|
|
use {
|
|
|
anchor_lang::AnchorSerialize,
|
|
|
+ libsecp256k1::PublicKey,
|
|
|
program_simulator::ProgramSimulator,
|
|
|
pyth_solana_receiver::{
|
|
|
instruction::Initialize,
|
|
|
sdk::{
|
|
|
get_config_address,
|
|
|
+ get_guardian_set_address,
|
|
|
get_treasury_address,
|
|
|
},
|
|
|
state::config::{
|
|
|
@@ -13,23 +15,13 @@ use {
|
|
|
},
|
|
|
ID,
|
|
|
},
|
|
|
- pythnet_sdk::{
|
|
|
- accumulators::{
|
|
|
- merkle::MerkleTree,
|
|
|
- Accumulator,
|
|
|
- },
|
|
|
- hashers::keccak256_160::Keccak160,
|
|
|
- messages::{
|
|
|
- Message,
|
|
|
- PriceFeedMessage,
|
|
|
- },
|
|
|
- wire::{
|
|
|
- v1::MerklePriceUpdate,
|
|
|
- PrefixedVec,
|
|
|
- },
|
|
|
+ pythnet_sdk::test_utils::{
|
|
|
+ dummy_guardians,
|
|
|
+ DEFAULT_DATA_SOURCE,
|
|
|
},
|
|
|
serde_wormhole::RawMessage,
|
|
|
solana_program::{
|
|
|
+ keccak,
|
|
|
pubkey::Pubkey,
|
|
|
rent::Rent,
|
|
|
},
|
|
|
@@ -42,111 +34,38 @@ use {
|
|
|
wormhole_core_bridge_solana::{
|
|
|
state::{
|
|
|
EncodedVaa,
|
|
|
+ GuardianSet,
|
|
|
Header,
|
|
|
ProcessingStatus,
|
|
|
},
|
|
|
ID as BRIDGE_ID,
|
|
|
},
|
|
|
- wormhole_sdk::{
|
|
|
- Chain,
|
|
|
- Vaa,
|
|
|
- },
|
|
|
+ wormhole_sdk::Vaa,
|
|
|
};
|
|
|
|
|
|
-pub fn dummy_receiver_config(data_source: DataSource) -> Config {
|
|
|
+pub const DEFAULT_GUARDIAN_SET_INDEX: u32 = 0;
|
|
|
+
|
|
|
+pub fn default_receiver_config() -> Config {
|
|
|
Config {
|
|
|
governance_authority: Pubkey::new_unique(),
|
|
|
target_governance_authority: None,
|
|
|
wormhole: BRIDGE_ID,
|
|
|
valid_data_sources: vec![DataSource {
|
|
|
- chain: data_source.chain,
|
|
|
- emitter: data_source.emitter,
|
|
|
+ chain: DEFAULT_DATA_SOURCE.chain.into(),
|
|
|
+ emitter: Pubkey::from(DEFAULT_DATA_SOURCE.address.0),
|
|
|
}],
|
|
|
single_update_fee_in_lamports: 1,
|
|
|
minimum_signatures: 5,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-pub fn dummy_data_source() -> DataSource {
|
|
|
- let emitter_address = Pubkey::new_unique().to_bytes();
|
|
|
- let emitter_chain = Chain::Pythnet;
|
|
|
- DataSource {
|
|
|
- chain: emitter_chain.into(),
|
|
|
- emitter: Pubkey::from(emitter_address),
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-pub fn dummy_price_messages() -> Vec<PriceFeedMessage> {
|
|
|
- vec![
|
|
|
- PriceFeedMessage {
|
|
|
- feed_id: [0u8; 32],
|
|
|
- price: 1,
|
|
|
- conf: 2,
|
|
|
- exponent: 3,
|
|
|
- publish_time: 4,
|
|
|
- prev_publish_time: 5,
|
|
|
- ema_price: 6,
|
|
|
- ema_conf: 7,
|
|
|
- },
|
|
|
- PriceFeedMessage {
|
|
|
- feed_id: [8u8; 32],
|
|
|
- price: 9,
|
|
|
- conf: 10,
|
|
|
- exponent: 11,
|
|
|
- publish_time: 12,
|
|
|
- prev_publish_time: 13,
|
|
|
- ema_price: 14,
|
|
|
- ema_conf: 15,
|
|
|
- },
|
|
|
- ]
|
|
|
-}
|
|
|
|
|
|
-pub fn dummy_price_updates(
|
|
|
- price_feed_messages: Vec<PriceFeedMessage>,
|
|
|
-) -> (MerkleTree<Keccak160>, Vec<MerklePriceUpdate>) {
|
|
|
- let messages = price_feed_messages
|
|
|
- .iter()
|
|
|
- .map(|x| Message::PriceFeedMessage(*x))
|
|
|
- .collect::<Vec<Message>>();
|
|
|
- let price_feed_message_as_vec: Vec<Vec<u8>> = messages
|
|
|
- .iter()
|
|
|
- .map(|x| pythnet_sdk::wire::to_vec::<_, byteorder::BigEndian>(&x).unwrap())
|
|
|
- .collect();
|
|
|
-
|
|
|
- let merkle_tree_accumulator =
|
|
|
- MerkleTree::<Keccak160>::from_set(price_feed_message_as_vec.iter().map(|x| x.as_ref()))
|
|
|
- .unwrap();
|
|
|
- let merkle_price_updates: Vec<MerklePriceUpdate> = price_feed_message_as_vec
|
|
|
- .iter()
|
|
|
- .map(|x| MerklePriceUpdate {
|
|
|
- message: PrefixedVec::<u16, u8>::from(x.clone()),
|
|
|
- proof: merkle_tree_accumulator.prove(x.as_ref()).unwrap(),
|
|
|
- })
|
|
|
- .collect();
|
|
|
-
|
|
|
- (merkle_tree_accumulator, merkle_price_updates)
|
|
|
+pub struct ProgramTestFixtures {
|
|
|
+ pub program_simulator: ProgramSimulator,
|
|
|
+ pub encoded_vaa_addresses: Vec<Pubkey>,
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-pub fn build_merkle_root_encoded_vaa(
|
|
|
- merkle_tree_accumulator: MerkleTree<Keccak160>,
|
|
|
- data_source: &DataSource,
|
|
|
-) -> Account {
|
|
|
- let merkle_tree_payload: Vec<u8> = merkle_tree_accumulator.serialize(1, 1);
|
|
|
-
|
|
|
- let vaa_header: Vaa<Box<RawMessage>> = Vaa {
|
|
|
- version: 1,
|
|
|
- guardian_set_index: 0,
|
|
|
- signatures: vec![],
|
|
|
- timestamp: 0,
|
|
|
- nonce: 0,
|
|
|
- emitter_chain: Chain::from(data_source.chain),
|
|
|
- emitter_address: wormhole_sdk::Address(data_source.emitter.to_bytes()),
|
|
|
- sequence: 0,
|
|
|
- consistency_level: 0,
|
|
|
- payload: <Box<RawMessage>>::from(merkle_tree_payload),
|
|
|
- };
|
|
|
-
|
|
|
+pub fn build_encoded_vaa_account_from_vaa(vaa: Vaa<&RawMessage>) -> Account {
|
|
|
let encoded_vaa_data = (
|
|
|
<EncodedVaa as anchor_lang::Discriminator>::DISCRIMINATOR,
|
|
|
Header {
|
|
|
@@ -154,12 +73,11 @@ pub fn build_merkle_root_encoded_vaa(
|
|
|
write_authority: Pubkey::new_unique(),
|
|
|
version: 1,
|
|
|
},
|
|
|
- serde_wormhole::to_vec(&vaa_header).unwrap(),
|
|
|
+ serde_wormhole::to_vec(&vaa).unwrap(),
|
|
|
)
|
|
|
.try_to_vec()
|
|
|
.unwrap();
|
|
|
|
|
|
-
|
|
|
Account {
|
|
|
lamports: Rent::default().minimum_balance(encoded_vaa_data.len()),
|
|
|
data: encoded_vaa_data,
|
|
|
@@ -169,37 +87,61 @@ pub fn build_merkle_root_encoded_vaa(
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+pub fn build_guardian_set_account() -> Account {
|
|
|
+ let guardian_set = GuardianSet {
|
|
|
+ index: DEFAULT_GUARDIAN_SET_INDEX,
|
|
|
+ keys: dummy_guardians()
|
|
|
+ .iter()
|
|
|
+ .map(|x| {
|
|
|
+ let mut result: [u8; 20] = [0u8; 20];
|
|
|
+ result.copy_from_slice(
|
|
|
+ &keccak::hashv(&[&PublicKey::from_secret_key(x).serialize()[1..]]).0[12..],
|
|
|
+ );
|
|
|
+ result
|
|
|
+ })
|
|
|
+ .collect::<Vec<[u8; 20]>>(),
|
|
|
+ creation_time: 0.into(),
|
|
|
+ expiration_time: 0.into(),
|
|
|
+ };
|
|
|
|
|
|
-pub struct ProgramTestFixtures {
|
|
|
- pub program_simulator: ProgramSimulator,
|
|
|
- pub encoded_vaa_address: Pubkey,
|
|
|
- pub merkle_price_updates: Vec<MerklePriceUpdate>,
|
|
|
+ let guardian_set_data = (
|
|
|
+ <GuardianSet as anchor_lang::Discriminator>::DISCRIMINATOR,
|
|
|
+ guardian_set,
|
|
|
+ )
|
|
|
+ .try_to_vec()
|
|
|
+ .unwrap();
|
|
|
+
|
|
|
+ Account {
|
|
|
+ lamports: Rent::default().minimum_balance(guardian_set_data.len()),
|
|
|
+ data: guardian_set_data,
|
|
|
+ owner: BRIDGE_ID,
|
|
|
+ executable: false,
|
|
|
+ rent_epoch: 0,
|
|
|
+ }
|
|
|
}
|
|
|
/**
|
|
|
* Setup to test the Pyth Receiver. The return values are a tuple composed of :
|
|
|
* - The program simulator, which is used to send transactions
|
|
|
- * - The pubkey of an encoded VAA account, which is pre-populated and can be used to test post_updates
|
|
|
- * - A vector of MerklePriceUpdate, corresponding to that VAA
|
|
|
+ * - The pubkeys of the encoded VAA accounts corresponding to the VAAs passed as argument, these accounts are prepopulated and can be used to test post_updates
|
|
|
*/
|
|
|
-pub async fn setup_pyth_receiver(
|
|
|
- price_feed_messages: Vec<PriceFeedMessage>,
|
|
|
-) -> ProgramTestFixtures {
|
|
|
+pub async fn setup_pyth_receiver(vaas: Vec<Vaa<&RawMessage>>) -> ProgramTestFixtures {
|
|
|
let mut program_test = ProgramTest::default();
|
|
|
program_test.add_program("pyth_solana_receiver", ID, None);
|
|
|
|
|
|
- let (merkle_tree_accumulator, merkle_price_updates) = dummy_price_updates(price_feed_messages);
|
|
|
- let data_source = dummy_data_source();
|
|
|
- let merkle_root_encoded_vaa =
|
|
|
- build_merkle_root_encoded_vaa(merkle_tree_accumulator, &data_source);
|
|
|
-
|
|
|
- let encoded_vaa_address = Pubkey::new_unique();
|
|
|
- program_test.add_account(encoded_vaa_address, merkle_root_encoded_vaa);
|
|
|
-
|
|
|
+ let mut encoded_vaa_addresses: Vec<Pubkey> = vec![];
|
|
|
+ for vaa in vaas {
|
|
|
+ let encoded_vaa_address = Pubkey::new_unique();
|
|
|
+ encoded_vaa_addresses.push(encoded_vaa_address);
|
|
|
+ program_test.add_account(encoded_vaa_address, build_encoded_vaa_account_from_vaa(vaa));
|
|
|
+ }
|
|
|
+ program_test.add_account(
|
|
|
+ get_guardian_set_address(BRIDGE_ID, DEFAULT_GUARDIAN_SET_INDEX),
|
|
|
+ build_guardian_set_account(),
|
|
|
+ );
|
|
|
|
|
|
let mut program_simulator = ProgramSimulator::start_from_program_test(program_test).await;
|
|
|
|
|
|
- let initial_config = dummy_receiver_config(data_source);
|
|
|
-
|
|
|
+ let initial_config = default_receiver_config();
|
|
|
let setup_keypair: Keypair = program_simulator.get_funded_keypair().await.unwrap();
|
|
|
|
|
|
program_simulator
|
|
|
@@ -225,7 +167,6 @@ pub async fn setup_pyth_receiver(
|
|
|
|
|
|
ProgramTestFixtures {
|
|
|
program_simulator,
|
|
|
- encoded_vaa_address,
|
|
|
- merkle_price_updates,
|
|
|
+ encoded_vaa_addresses,
|
|
|
}
|
|
|
}
|