浏览代码

[solana] Add pre-commit for solana target chain contract (#753)

* precommit

* format
Jayant Krishnamurthy 2 年之前
父节点
当前提交
843a30c2c7

+ 13 - 0
.pre-commit-config.yaml

@@ -78,3 +78,16 @@ repos:
         entry: cargo +nightly clippy --manifest-path ./accumulator_updater/Cargo.toml --tests --fix --allow-dirty --allow-staged -- -D warnings
         pass_filenames: false
         files: accumulator_updater
+      # Hooks for solana receiver contract
+      - id: cargo-fmt-solana-receiver
+        name: Cargo format for solana target chain contract
+        language: "rust"
+        entry: cargo +nightly fmt --manifest-path ./target_chains/solana/Cargo.toml --all -- --config-path rustfmt.toml
+        pass_filenames: false
+        files: target_chains/solana
+      - id: cargo-clippy-solana-receiver
+        name: Cargo clippy for solana target chain contract
+        language: "rust"
+        entry: cargo +nightly clippy --manifest-path ./target_chains/solana/Cargo.toml --tests --fix --allow-dirty --allow-staged -- -D warnings
+        pass_filenames: false
+        files: target_chains/solana

+ 7 - 10
target_chains/solana/cli/src/cli.rs

@@ -1,8 +1,6 @@
-use {
-    clap::{
-        Parser,
-        Subcommand,
-    },
+use clap::{
+    Parser,
+    Subcommand,
 };
 
 #[derive(Parser, Debug)]
@@ -12,22 +10,21 @@ use {
 )]
 pub struct Cli {
     #[clap(subcommand)]
-    pub action:     Action,
+    pub action: Action,
 }
 
 #[derive(Subcommand, Debug)]
 pub enum Action {
     #[clap(about = "Verify, post and receive the price VAA on solana")]
     PostAndReceiveVAA {
-        #[clap(short = 'v', long,
-               help = "Price VAA from Pythnet")]
+        #[clap(short = 'v', long, help = "Price VAA from Pythnet")]
         vaa:     String,
         #[clap(
-            short = 'k', long,
+            short = 'k',
+            long,
             default_value = "~/.config/solana/id.json",
             help = "Keypair of the payer of transactions"
         )]
         keypair: String,
     },
-
 }

+ 18 - 23
target_chains/solana/cli/src/main.rs

@@ -1,23 +1,33 @@
 pub mod cli;
 
 use {
+    anchor_client::anchor_lang::{
+        AnchorDeserialize,
+        InstructionData,
+        Owner,
+        ToAccountMetas,
+    },
+    anyhow::Result,
+    clap::Parser,
     cli::{
         Action,
         Cli,
     },
-    clap::Parser,
-    anyhow::Result,
-
+    pyth_solana_receiver::{
+        accounts::DecodePostedVaa,
+        state::AnchorVaa,
+        ID,
+    },
+    solana_client::rpc_client::RpcClient,
     solana_sdk::{
+        instruction::Instruction,
         signature::{
             read_keypair_file,
             Keypair,
         },
         signer::Signer,
-        instruction::Instruction,
         transaction::Transaction,
     },
-
     wormhole::VAA,
     wormhole_solana::{
         instructions::{
@@ -26,25 +36,10 @@ use {
             PostVAAData,
         },
         Account,
-        GuardianSet,
         Config as WormholeConfig,
+        GuardianSet,
         VAA as WormholeSolanaVAA,
     },
-
-    pyth_solana_receiver::{
-        ID,
-        state::AnchorVaa,
-        accounts::DecodePostedVaa,
-    },
-
-    anchor_client::anchor_lang::{
-        Owner,
-        ToAccountMetas,
-        InstructionData,
-        AnchorDeserialize,
-    },
-
-    solana_client::rpc_client::RpcClient,
 };
 
 fn main() -> Result<()> {
@@ -111,8 +106,8 @@ fn main() -> Result<()> {
             )?;
 
             println!("[5/5] Receive and deserialize the VAA on solana");
-            let account_metas = DecodePostedVaa::populate(&payer.pubkey(), &posted_vaa_key)
-                .to_account_metas(None);
+            let account_metas =
+                DecodePostedVaa::populate(&payer.pubkey(), &posted_vaa_key).to_account_metas(None);
 
             println!("Receiver program ID is {}", ID);
             let invoke_receiver_instruction = Instruction {

+ 32 - 24
target_chains/solana/programs/solana-receiver/src/lib.rs

@@ -5,18 +5,21 @@ pub mod state;
 mod tests;
 
 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::{
         self,
-        Solana,
         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");
 
@@ -28,9 +31,12 @@ pub mod pyth_solana_receiver {
         let posted_vaa = &ctx.accounts.posted_vaa.payload;
         let batch: BatchPriceAttestation =
             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 {
             msg!("product_id: {}", attestation.product_id);
@@ -47,7 +53,12 @@ pub mod pyth_solana_receiver {
         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
         let message_hash = {
             let mut hasher = keccak::Hasher::default();
@@ -56,13 +67,13 @@ pub mod pyth_solana_receiver {
         };
 
         // 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.
         // Here we are checking the secp256k1 pubkey against a known authorized pubkey.
@@ -78,18 +89,15 @@ pub mod pyth_solana_receiver {
 #[derive(Accounts)]
 pub struct DecodePostedVaa<'info> {
     #[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)]
-    pub posted_vaa:     Account<'info, AnchorVaa>,
+    pub posted_vaa: Account<'info, AnchorVaa>,
 }
 
 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 {
-            payer: *payer,
+            payer:      *payer,
             posted_vaa: *posted_vaa,
         }
     }
@@ -98,5 +106,5 @@ impl crate::accounts::DecodePostedVaa {
 #[derive(Accounts)]
 pub struct Update<'info> {
     #[account(mut)]
-    pub payer:          Signer<'info>,
+    pub payer: Signer<'info>,
 }

+ 1 - 1
target_chains/solana/programs/solana-receiver/src/state.rs

@@ -1,11 +1,11 @@
 use {
+    anchor_lang::prelude::*,
     std::{
         io::Write,
         ops::Deref,
         str::FromStr,
     },
     wormhole_solana::VAA,
-    anchor_lang::prelude::*,
 };
 
 // The current chain's wormhole bridge owns the VAA accounts

+ 4 - 13
target_chains/solana/programs/solana-receiver/src/tests/simulator.rs

@@ -5,25 +5,20 @@ use {
             self,
             UpgradeableLoaderState,
         },
-        hash::hash,
         hash::Hash,
-        instruction::{
-            AccountMeta,
-            Instruction,
-        },
+        instruction::Instruction,
         native_token::LAMPORTS_PER_SOL,
         pubkey::Pubkey,
         rent::Rent,
         stake_history::Epoch,
         system_instruction,
-        system_program,
     },
     solana_program_test::{
+        read_file,
         BanksClient,
         BanksClientError,
         ProgramTest,
         ProgramTestBanksClientExt,
-        read_file,
     },
     solana_sdk::{
         account::Account,
@@ -33,16 +28,13 @@ use {
         },
         transaction::Transaction,
     },
-    std::{
-        mem::size_of,
-        path::Path,
-    },
+    std::path::Path,
 };
 
 /// Simulator for the state of the target chain program on Solana. You can run solana transactions against
 /// this struct to test how pyth instructions execute in the Solana runtime.
 pub struct ProgramSimulator {
-    pub program_id:            Pubkey,
+    pub program_id:        Pubkey,
     banks_client:          BanksClient,
     /// Hash used to submit the last transaction. The hash must be advanced for each new
     /// transaction; otherwise, replayed transactions in different states can return stale
@@ -54,7 +46,6 @@ pub struct ProgramSimulator {
 }
 
 impl ProgramSimulator {
-
     /// Deploys the target chain contract as upgradable
     pub async fn new() -> ProgramSimulator {
         let mut bpf_data = read_file(

+ 25 - 21
target_chains/solana/programs/solana-receiver/src/tests/test_update_price.rs

@@ -1,27 +1,21 @@
 use {
-    solana_program::{
-        program_error::ProgramError,
-        pubkey::Pubkey,
-        instruction::Instruction,
+    crate::{
+        accounts as receiver_accounts,
+        instruction as receiver_instruction,
+        tests::simulator::ProgramSimulator,
     },
+    anchor_lang::{
+        prelude::*,
+        InstructionData,
+        ToAccountMetas,
+    },
+    rand::rngs::OsRng,
+    solana_program::instruction::Instruction,
     solana_sdk::{
-        signature::Signer,
         keccak,
+        signature::Signer,
     },
-    crate::instruction as receiver_instruction,
-    crate::accounts as receiver_accounts,
 };
-use anchor_lang::prelude::*;
-use anchor_lang::Discriminator;
-use anchor_lang::{
-Owner,
-ToAccountMetas,
-InstructionData,
-AnchorDeserialize,
-};
-use rand::rngs::OsRng;
-
-use crate::tests::simulator::ProgramSimulator;
 
 #[tokio::test]
 async fn test_update_price() {
@@ -38,10 +32,20 @@ async fn test_update_price() {
     let secp_message = libsecp256k1::Message::parse(&message_hash.0);
     let (signature, recovery_id) = libsecp256k1::sign(&secp_message, &secp256k1_secret_key);
 
-    let accounts = receiver_accounts::Update { payer: sim.genesis_keypair.pubkey() }.to_account_metas(None);
-    let instruction_data = receiver_instruction::Update { data: message.to_vec(), recovery_id: recovery_id.serialize(), signature: signature.serialize() }.data();
+    let accounts = receiver_accounts::Update {
+        payer: sim.genesis_keypair.pubkey(),
+    }
+    .to_account_metas(None);
+    let instruction_data = receiver_instruction::Update {
+        data:        message.to_vec(),
+        recovery_id: recovery_id.serialize(),
+        signature:   signature.serialize(),
+    }
+    .data();
 
     let inst = Instruction::new_with_bytes(sim.program_id, &instruction_data, accounts);
 
-    let result = sim.process_ix(inst, &vec![], &sim.genesis_keypair.insecure_clone()).await.unwrap();
+    sim.process_ix(inst, &vec![], &sim.genesis_keypair.insecure_clone())
+        .await
+        .unwrap();
 }