|
@@ -5,18 +5,21 @@ pub mod state;
|
|
|
mod tests;
|
|
mod tests;
|
|
|
|
|
|
|
|
use {
|
|
use {
|
|
|
|
|
+ crate::error::ReceiverError::*,
|
|
|
|
|
+ anchor_lang::prelude::*,
|
|
|
|
|
+ hex::ToHex,
|
|
|
|
|
+ pyth_wormhole_attester_sdk::BatchPriceAttestation,
|
|
|
|
|
+ solana_program::{
|
|
|
|
|
+ keccak,
|
|
|
|
|
+ secp256k1_recover::secp256k1_recover,
|
|
|
|
|
+ },
|
|
|
|
|
+ state::AnchorVaa,
|
|
|
wormhole::Chain::{
|
|
wormhole::Chain::{
|
|
|
self,
|
|
self,
|
|
|
- Solana,
|
|
|
|
|
Pythnet,
|
|
Pythnet,
|
|
|
|
|
+ Solana,
|
|
|
},
|
|
},
|
|
|
- state::AnchorVaa,
|
|
|
|
|
- anchor_lang::prelude::*,
|
|
|
|
|
- pyth_wormhole_attester_sdk::BatchPriceAttestation,
|
|
|
|
|
- solana_program::{ keccak, secp256k1_recover::secp256k1_recover },
|
|
|
|
|
};
|
|
};
|
|
|
-use hex::ToHex;
|
|
|
|
|
-use crate::error::ReceiverError::*;
|
|
|
|
|
|
|
|
|
|
declare_id!("pythKkWXoywbvTQVcWrNDz5ENvWteF7tem7xzW52NBK");
|
|
declare_id!("pythKkWXoywbvTQVcWrNDz5ENvWteF7tem7xzW52NBK");
|
|
|
|
|
|
|
@@ -28,9 +31,12 @@ pub mod pyth_solana_receiver {
|
|
|
let posted_vaa = &ctx.accounts.posted_vaa.payload;
|
|
let posted_vaa = &ctx.accounts.posted_vaa.payload;
|
|
|
let batch: BatchPriceAttestation =
|
|
let batch: BatchPriceAttestation =
|
|
|
BatchPriceAttestation::deserialize(posted_vaa.as_slice())
|
|
BatchPriceAttestation::deserialize(posted_vaa.as_slice())
|
|
|
- .map_err(|_| DeserializeVAAFailed)?;
|
|
|
|
|
|
|
+ .map_err(|_| DeserializeVAAFailed)?;
|
|
|
|
|
|
|
|
- msg!("There are {} attestations in this batch.", batch.price_attestations.len());
|
|
|
|
|
|
|
+ msg!(
|
|
|
|
|
+ "There are {} attestations in this batch.",
|
|
|
|
|
+ batch.price_attestations.len()
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
for attestation in batch.price_attestations {
|
|
for attestation in batch.price_attestations {
|
|
|
msg!("product_id: {}", attestation.product_id);
|
|
msg!("product_id: {}", attestation.product_id);
|
|
@@ -47,7 +53,12 @@ pub mod pyth_solana_receiver {
|
|
|
Ok(())
|
|
Ok(())
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- pub fn update(ctx: Context<Update>, data: Vec<u8>, recovery_id: u8, signature: [u8; 64]) -> Result<()> {
|
|
|
|
|
|
|
+ pub fn update(
|
|
|
|
|
+ _ctx: Context<Update>,
|
|
|
|
|
+ data: Vec<u8>,
|
|
|
|
|
+ recovery_id: u8,
|
|
|
|
|
+ signature: [u8; 64],
|
|
|
|
|
+ ) -> Result<()> {
|
|
|
// This costs about 10k compute units
|
|
// This costs about 10k compute units
|
|
|
let message_hash = {
|
|
let message_hash = {
|
|
|
let mut hasher = keccak::Hasher::default();
|
|
let mut hasher = keccak::Hasher::default();
|
|
@@ -56,13 +67,13 @@ pub mod pyth_solana_receiver {
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
// This costs about 25k compute units
|
|
// This costs about 25k compute units
|
|
|
- let recovered_pubkey = secp256k1_recover(
|
|
|
|
|
- &message_hash.0,
|
|
|
|
|
- recovery_id,
|
|
|
|
|
- &signature,
|
|
|
|
|
- ).map_err(|_| ProgramError::InvalidArgument)?;
|
|
|
|
|
|
|
+ let recovered_pubkey = secp256k1_recover(&message_hash.0, recovery_id, &signature)
|
|
|
|
|
+ .map_err(|_| ProgramError::InvalidArgument)?;
|
|
|
|
|
|
|
|
- msg!("Recovered key: {}", recovered_pubkey.0.encode_hex::<String>());
|
|
|
|
|
|
|
+ msg!(
|
|
|
|
|
+ "Recovered key: {}",
|
|
|
|
|
+ recovered_pubkey.0.encode_hex::<String>()
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
// TODO: Check the pubkey is an expected value.
|
|
// TODO: Check the pubkey is an expected value.
|
|
|
// Here we are checking the secp256k1 pubkey against a known authorized pubkey.
|
|
// Here we are checking the secp256k1 pubkey against a known authorized pubkey.
|
|
@@ -78,18 +89,15 @@ pub mod pyth_solana_receiver {
|
|
|
#[derive(Accounts)]
|
|
#[derive(Accounts)]
|
|
|
pub struct DecodePostedVaa<'info> {
|
|
pub struct DecodePostedVaa<'info> {
|
|
|
#[account(mut)]
|
|
#[account(mut)]
|
|
|
- pub payer: Signer<'info>,
|
|
|
|
|
|
|
+ pub payer: Signer<'info>,
|
|
|
#[account(constraint = (Chain::from(posted_vaa.emitter_chain) == Solana || Chain::from(posted_vaa.emitter_chain) == Pythnet) @ EmitterChainNotSolanaOrPythnet, constraint = (&posted_vaa.magic == b"vaa" || &posted_vaa.magic == b"msg" || &posted_vaa.magic == b"msu") @PostedVaaHeaderWrongMagicNumber)]
|
|
#[account(constraint = (Chain::from(posted_vaa.emitter_chain) == Solana || Chain::from(posted_vaa.emitter_chain) == Pythnet) @ EmitterChainNotSolanaOrPythnet, constraint = (&posted_vaa.magic == b"vaa" || &posted_vaa.magic == b"msg" || &posted_vaa.magic == b"msu") @PostedVaaHeaderWrongMagicNumber)]
|
|
|
- pub posted_vaa: Account<'info, AnchorVaa>,
|
|
|
|
|
|
|
+ pub posted_vaa: Account<'info, AnchorVaa>,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
impl crate::accounts::DecodePostedVaa {
|
|
impl crate::accounts::DecodePostedVaa {
|
|
|
- pub fn populate(
|
|
|
|
|
- payer: &Pubkey,
|
|
|
|
|
- posted_vaa: &Pubkey,
|
|
|
|
|
- ) -> Self {
|
|
|
|
|
|
|
+ pub fn populate(payer: &Pubkey, posted_vaa: &Pubkey) -> Self {
|
|
|
crate::accounts::DecodePostedVaa {
|
|
crate::accounts::DecodePostedVaa {
|
|
|
- payer: *payer,
|
|
|
|
|
|
|
+ payer: *payer,
|
|
|
posted_vaa: *posted_vaa,
|
|
posted_vaa: *posted_vaa,
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -98,5 +106,5 @@ impl crate::accounts::DecodePostedVaa {
|
|
|
#[derive(Accounts)]
|
|
#[derive(Accounts)]
|
|
|
pub struct Update<'info> {
|
|
pub struct Update<'info> {
|
|
|
#[account(mut)]
|
|
#[account(mut)]
|
|
|
- pub payer: Signer<'info>,
|
|
|
|
|
|
|
+ pub payer: Signer<'info>,
|
|
|
}
|
|
}
|