use { crate::{ accumulators::{merkle::MerkleTree, Accumulator}, hashers::{keccak256::Keccak256, keccak256_160::Keccak160, Hasher}, messages::{FeedId, Message, PriceFeedMessage, TwapMessage}, wire::{ to_vec, v1::{ AccumulatorUpdateData, MerklePriceUpdate, Proof, WormholeMerkleRoot, WormholeMessage, WormholePayload, }, PrefixedVec, }, }, byteorder::BigEndian, libsecp256k1::{Message as libsecp256k1Message, PublicKey, RecoveryId, SecretKey, Signature}, rand::{seq::SliceRandom, thread_rng}, serde_wormhole::RawMessage, wormhole_sdk::{ vaa::{Body, Header}, Address, Chain, Vaa, }, }; pub struct DataSource { pub address: Address, pub chain: Chain, } pub const DEFAULT_DATA_SOURCE: DataSource = DataSource { address: Address([1u8; 32]), chain: Chain::Solana, }; pub const DEFAULT_GOVERNANCE_SOURCE: DataSource = DataSource { address: Address([2u8; 32]), chain: Chain::Ethereum, }; pub const WRONG_SOURCE: DataSource = DataSource { address: Address([3u8; 32]), chain: Chain::Bsc, }; pub const SECONDARY_DATA_SOURCE: DataSource = DataSource { address: Address([4u8; 32]), chain: Chain::Polygon, }; pub const SECONDARY_GOVERNANCE_SOURCE: DataSource = DataSource { address: Address([5u8; 32]), chain: Chain::Avalanche, }; pub const DEFAULT_CHAIN_ID: Chain = Chain::Oasis; pub const WRONG_CHAIN_ID: Chain = Chain::Algorand; pub const DEFAULT_VALID_TIME_PERIOD: u64 = 180; const DEFAULT_SEQUENCE: u64 = 2; const NUM_GUARDIANS: u8 = 19; // Matches wormhole mainnet const DEFAULT_NUM_SIGNATURES: usize = 13; // Matches wormhole mainnet pub fn dummy_guardians() -> Vec { let mut result: Vec = vec![]; for i in 0..NUM_GUARDIANS { let mut secret_key_bytes = [0u8; 32]; secret_key_bytes[0] = i + 1; result.push(SecretKey::parse(&secret_key_bytes).unwrap()); } result } pub fn dummy_guardians_addresses() -> Vec<[u8; 20]> { let guardians = dummy_guardians(); guardians .iter() .map(|x| { let mut result: [u8; 20] = [0u8; 20]; let pubkey = &PublicKey::from_secret_key(x).serialize()[1..]; result.copy_from_slice(&Keccak256::hashv(&[&pubkey])[12..]); result }) .collect() } pub fn create_dummy_feed_id(value: i64) -> FeedId { let mut dummy_id = [0; 32]; dummy_id[0] = value as u8; dummy_id } pub fn create_dummy_price_feed_message_with_feed_id(value: i64, feed_id: FeedId) -> Message { let msg = PriceFeedMessage { feed_id, price: value, conf: value as u64, exponent: value as i32, publish_time: value, prev_publish_time: value, ema_price: value, ema_conf: value as u64, }; Message::PriceFeedMessage(msg) } pub fn create_dummy_price_feed_message(value: i64) -> Message { create_dummy_price_feed_message_with_feed_id(value, create_dummy_feed_id(value)) } pub fn create_dummy_twap_message() -> Message { let msg = TwapMessage { feed_id: [0; 32], cumulative_price: 0, cumulative_conf: 0, num_down_slots: 0, exponent: 0, publish_time: 0, prev_publish_time: 0, publish_slot: 0, }; Message::TwapMessage(msg) } pub fn create_accumulator_message( all_feeds: &[&Message], updates: &[&Message], corrupt_wormhole_message: bool, corrupt_messages: bool, data_source_override: Option, ) -> Vec { let mut all_feeds_bytes: Vec<_> = all_feeds .iter() .map(|f| to_vec::<_, BigEndian>(f).unwrap()) .collect(); let mut updates_bytes: Vec<_> = updates .iter() .map(|f| to_vec::<_, BigEndian>(f).unwrap()) .collect(); if corrupt_messages { all_feeds_bytes = all_feeds_bytes .iter() .map(|f| { let mut f_copy = f.clone(); f_copy[0] = 255; f_copy }) .collect(); updates_bytes = updates_bytes .iter() .map(|f| { let mut f_copy = f.clone(); f_copy[0] = 255; f_copy }) .collect(); } let all_feeds_bytes_refs: Vec<_> = all_feeds_bytes.iter().map(|f| f.as_ref()).collect(); let tree = MerkleTree::::new(all_feeds_bytes_refs.as_slice()).unwrap(); let mut price_updates: Vec = vec![]; for update in updates_bytes { let proof = tree.prove(&update).unwrap(); price_updates.push(MerklePriceUpdate { message: PrefixedVec::from(update), proof, }); } let data_source = data_source_override.unwrap_or(DEFAULT_DATA_SOURCE); create_accumulator_message_from_updates( price_updates, tree, corrupt_wormhole_message, data_source.address, data_source.chain, ) } pub fn create_accumulator_message_from_updates( price_updates: Vec, tree: MerkleTree, corrupt_wormhole_message: bool, emitter_address: Address, emitter_chain: Chain, ) -> Vec { let mut root_hash = [0u8; 20]; root_hash.copy_from_slice(&to_vec::<_, BigEndian>(&tree.root).unwrap()[..20]); let wormhole_message = WormholeMessage::new(WormholePayload::Merkle(WormholeMerkleRoot { slot: 0, ring_size: 0, root: root_hash, })); let mut vaa_payload = to_vec::<_, BigEndian>(&wormhole_message).unwrap(); if corrupt_wormhole_message { vaa_payload[0] = 0; } let vaa = create_vaa_from_payload( &vaa_payload, emitter_address, emitter_chain, DEFAULT_SEQUENCE, ); let accumulator_update_data = AccumulatorUpdateData::new(Proof::WormholeMerkle { vaa: PrefixedVec::from(serde_wormhole::to_vec(&vaa).unwrap()), updates: price_updates, }); to_vec::<_, BigEndian>(&accumulator_update_data).unwrap() } pub fn create_vaa_from_payload( payload: &[u8], emitter_address: Address, emitter_chain: Chain, sequence: u64, ) -> Vaa> { let guardians = dummy_guardians(); let body: Body> = Body { emitter_chain, emitter_address, sequence, payload: >::from(payload.to_vec()), ..Default::default() }; let digest = libsecp256k1Message::parse_slice(&body.digest().unwrap().secp256k_hash).unwrap(); let signatures: Vec<(Signature, RecoveryId)> = guardians .iter() .map(|x| libsecp256k1::sign(&digest, &x)) .collect(); let wormhole_signatures: Vec = signatures .iter() .enumerate() .map(|(i, (x, y))| { let mut signature = [0u8; 65]; signature[..64].copy_from_slice(&x.serialize()); signature[64] = y.serialize(); wormhole_sdk::vaa::Signature { index: i as u8, signature, } }) .collect(); let mut wormhole_signatures_subset: Vec = wormhole_signatures .choose_multiple(&mut thread_rng(), DEFAULT_NUM_SIGNATURES) .cloned() .collect(); wormhole_signatures_subset.sort_by(|a, b| a.index.cmp(&b.index)); let header = Header { version: 1, signatures: wormhole_signatures_subset, ..Default::default() }; (header, body).into() } pub fn trim_vaa_signatures(vaa: Vaa<&RawMessage>, n: u8) -> Vaa<&RawMessage> { let mut vaa_copy = vaa.clone(); vaa_copy.signatures = vaa .signatures .choose_multiple(&mut thread_rng(), n.into()) .cloned() .collect(); vaa_copy.signatures.sort_by(|a, b| a.index.cmp(&b.index)); vaa_copy }