Skip to content

Commit 843a30c

Browse files
authored
[solana] Add pre-commit for solana target chain contract (#753)
* precommit * format
1 parent 85b9c80 commit 843a30c

File tree

7 files changed

+100
-92
lines changed

7 files changed

+100
-92
lines changed

.pre-commit-config.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,16 @@ repos:
7878
entry: cargo +nightly clippy --manifest-path ./accumulator_updater/Cargo.toml --tests --fix --allow-dirty --allow-staged -- -D warnings
7979
pass_filenames: false
8080
files: accumulator_updater
81+
# Hooks for solana receiver contract
82+
- id: cargo-fmt-solana-receiver
83+
name: Cargo format for solana target chain contract
84+
language: "rust"
85+
entry: cargo +nightly fmt --manifest-path ./target_chains/solana/Cargo.toml --all -- --config-path rustfmt.toml
86+
pass_filenames: false
87+
files: target_chains/solana
88+
- id: cargo-clippy-solana-receiver
89+
name: Cargo clippy for solana target chain contract
90+
language: "rust"
91+
entry: cargo +nightly clippy --manifest-path ./target_chains/solana/Cargo.toml --tests --fix --allow-dirty --allow-staged -- -D warnings
92+
pass_filenames: false
93+
files: target_chains/solana

target_chains/solana/cli/src/cli.rs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
use {
2-
clap::{
3-
Parser,
4-
Subcommand,
5-
},
1+
use clap::{
2+
Parser,
3+
Subcommand,
64
};
75

86
#[derive(Parser, Debug)]
@@ -12,22 +10,21 @@ use {
1210
)]
1311
pub struct Cli {
1412
#[clap(subcommand)]
15-
pub action: Action,
13+
pub action: Action,
1614
}
1715

1816
#[derive(Subcommand, Debug)]
1917
pub enum Action {
2018
#[clap(about = "Verify, post and receive the price VAA on solana")]
2119
PostAndReceiveVAA {
22-
#[clap(short = 'v', long,
23-
help = "Price VAA from Pythnet")]
20+
#[clap(short = 'v', long, help = "Price VAA from Pythnet")]
2421
vaa: String,
2522
#[clap(
26-
short = 'k', long,
23+
short = 'k',
24+
long,
2725
default_value = "~/.config/solana/id.json",
2826
help = "Keypair of the payer of transactions"
2927
)]
3028
keypair: String,
3129
},
32-
3330
}

target_chains/solana/cli/src/main.rs

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,33 @@
11
pub mod cli;
22

33
use {
4+
anchor_client::anchor_lang::{
5+
AnchorDeserialize,
6+
InstructionData,
7+
Owner,
8+
ToAccountMetas,
9+
},
10+
anyhow::Result,
11+
clap::Parser,
412
cli::{
513
Action,
614
Cli,
715
},
8-
clap::Parser,
9-
anyhow::Result,
10-
16+
pyth_solana_receiver::{
17+
accounts::DecodePostedVaa,
18+
state::AnchorVaa,
19+
ID,
20+
},
21+
solana_client::rpc_client::RpcClient,
1122
solana_sdk::{
23+
instruction::Instruction,
1224
signature::{
1325
read_keypair_file,
1426
Keypair,
1527
},
1628
signer::Signer,
17-
instruction::Instruction,
1829
transaction::Transaction,
1930
},
20-
2131
wormhole::VAA,
2232
wormhole_solana::{
2333
instructions::{
@@ -26,25 +36,10 @@ use {
2636
PostVAAData,
2737
},
2838
Account,
29-
GuardianSet,
3039
Config as WormholeConfig,
40+
GuardianSet,
3141
VAA as WormholeSolanaVAA,
3242
},
33-
34-
pyth_solana_receiver::{
35-
ID,
36-
state::AnchorVaa,
37-
accounts::DecodePostedVaa,
38-
},
39-
40-
anchor_client::anchor_lang::{
41-
Owner,
42-
ToAccountMetas,
43-
InstructionData,
44-
AnchorDeserialize,
45-
},
46-
47-
solana_client::rpc_client::RpcClient,
4843
};
4944

5045
fn main() -> Result<()> {
@@ -111,8 +106,8 @@ fn main() -> Result<()> {
111106
)?;
112107

113108
println!("[5/5] Receive and deserialize the VAA on solana");
114-
let account_metas = DecodePostedVaa::populate(&payer.pubkey(), &posted_vaa_key)
115-
.to_account_metas(None);
109+
let account_metas =
110+
DecodePostedVaa::populate(&payer.pubkey(), &posted_vaa_key).to_account_metas(None);
116111

117112
println!("Receiver program ID is {}", ID);
118113
let invoke_receiver_instruction = Instruction {

target_chains/solana/programs/solana-receiver/src/lib.rs

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,21 @@ pub mod state;
55
mod tests;
66

77
use {
8+
crate::error::ReceiverError::*,
9+
anchor_lang::prelude::*,
10+
hex::ToHex,
11+
pyth_wormhole_attester_sdk::BatchPriceAttestation,
12+
solana_program::{
13+
keccak,
14+
secp256k1_recover::secp256k1_recover,
15+
},
16+
state::AnchorVaa,
817
wormhole::Chain::{
918
self,
10-
Solana,
1119
Pythnet,
20+
Solana,
1221
},
13-
state::AnchorVaa,
14-
anchor_lang::prelude::*,
15-
pyth_wormhole_attester_sdk::BatchPriceAttestation,
16-
solana_program::{ keccak, secp256k1_recover::secp256k1_recover },
1722
};
18-
use hex::ToHex;
19-
use crate::error::ReceiverError::*;
2023

2124
declare_id!("pythKkWXoywbvTQVcWrNDz5ENvWteF7tem7xzW52NBK");
2225

@@ -28,9 +31,12 @@ pub mod pyth_solana_receiver {
2831
let posted_vaa = &ctx.accounts.posted_vaa.payload;
2932
let batch: BatchPriceAttestation =
3033
BatchPriceAttestation::deserialize(posted_vaa.as_slice())
31-
.map_err(|_| DeserializeVAAFailed)?;
34+
.map_err(|_| DeserializeVAAFailed)?;
3235

33-
msg!("There are {} attestations in this batch.", batch.price_attestations.len());
36+
msg!(
37+
"There are {} attestations in this batch.",
38+
batch.price_attestations.len()
39+
);
3440

3541
for attestation in batch.price_attestations {
3642
msg!("product_id: {}", attestation.product_id);
@@ -47,7 +53,12 @@ pub mod pyth_solana_receiver {
4753
Ok(())
4854
}
4955

50-
pub fn update(ctx: Context<Update>, data: Vec<u8>, recovery_id: u8, signature: [u8; 64]) -> Result<()> {
56+
pub fn update(
57+
_ctx: Context<Update>,
58+
data: Vec<u8>,
59+
recovery_id: u8,
60+
signature: [u8; 64],
61+
) -> Result<()> {
5162
// This costs about 10k compute units
5263
let message_hash = {
5364
let mut hasher = keccak::Hasher::default();
@@ -56,13 +67,13 @@ pub mod pyth_solana_receiver {
5667
};
5768

5869
// This costs about 25k compute units
59-
let recovered_pubkey = secp256k1_recover(
60-
&message_hash.0,
61-
recovery_id,
62-
&signature,
63-
).map_err(|_| ProgramError::InvalidArgument)?;
70+
let recovered_pubkey = secp256k1_recover(&message_hash.0, recovery_id, &signature)
71+
.map_err(|_| ProgramError::InvalidArgument)?;
6472

65-
msg!("Recovered key: {}", recovered_pubkey.0.encode_hex::<String>());
73+
msg!(
74+
"Recovered key: {}",
75+
recovered_pubkey.0.encode_hex::<String>()
76+
);
6677

6778
// TODO: Check the pubkey is an expected value.
6879
// Here we are checking the secp256k1 pubkey against a known authorized pubkey.
@@ -78,18 +89,15 @@ pub mod pyth_solana_receiver {
7889
#[derive(Accounts)]
7990
pub struct DecodePostedVaa<'info> {
8091
#[account(mut)]
81-
pub payer: Signer<'info>,
92+
pub payer: Signer<'info>,
8293
#[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)]
83-
pub posted_vaa: Account<'info, AnchorVaa>,
94+
pub posted_vaa: Account<'info, AnchorVaa>,
8495
}
8596

8697
impl crate::accounts::DecodePostedVaa {
87-
pub fn populate(
88-
payer: &Pubkey,
89-
posted_vaa: &Pubkey,
90-
) -> Self {
98+
pub fn populate(payer: &Pubkey, posted_vaa: &Pubkey) -> Self {
9199
crate::accounts::DecodePostedVaa {
92-
payer: *payer,
100+
payer: *payer,
93101
posted_vaa: *posted_vaa,
94102
}
95103
}
@@ -98,5 +106,5 @@ impl crate::accounts::DecodePostedVaa {
98106
#[derive(Accounts)]
99107
pub struct Update<'info> {
100108
#[account(mut)]
101-
pub payer: Signer<'info>,
109+
pub payer: Signer<'info>,
102110
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
use {
2+
anchor_lang::prelude::*,
23
std::{
34
io::Write,
45
ops::Deref,
56
str::FromStr,
67
},
78
wormhole_solana::VAA,
8-
anchor_lang::prelude::*,
99
};
1010

1111
// The current chain's wormhole bridge owns the VAA accounts

target_chains/solana/programs/solana-receiver/src/tests/simulator.rs

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,20 @@ use {
55
self,
66
UpgradeableLoaderState,
77
},
8-
hash::hash,
98
hash::Hash,
10-
instruction::{
11-
AccountMeta,
12-
Instruction,
13-
},
9+
instruction::Instruction,
1410
native_token::LAMPORTS_PER_SOL,
1511
pubkey::Pubkey,
1612
rent::Rent,
1713
stake_history::Epoch,
1814
system_instruction,
19-
system_program,
2015
},
2116
solana_program_test::{
17+
read_file,
2218
BanksClient,
2319
BanksClientError,
2420
ProgramTest,
2521
ProgramTestBanksClientExt,
26-
read_file,
2722
},
2823
solana_sdk::{
2924
account::Account,
@@ -33,16 +28,13 @@ use {
3328
},
3429
transaction::Transaction,
3530
},
36-
std::{
37-
mem::size_of,
38-
path::Path,
39-
},
31+
std::path::Path,
4032
};
4133

4234
/// Simulator for the state of the target chain program on Solana. You can run solana transactions against
4335
/// this struct to test how pyth instructions execute in the Solana runtime.
4436
pub struct ProgramSimulator {
45-
pub program_id: Pubkey,
37+
pub program_id: Pubkey,
4638
banks_client: BanksClient,
4739
/// Hash used to submit the last transaction. The hash must be advanced for each new
4840
/// transaction; otherwise, replayed transactions in different states can return stale
@@ -54,7 +46,6 @@ pub struct ProgramSimulator {
5446
}
5547

5648
impl ProgramSimulator {
57-
5849
/// Deploys the target chain contract as upgradable
5950
pub async fn new() -> ProgramSimulator {
6051
let mut bpf_data = read_file(
Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,21 @@
11
use {
2-
solana_program::{
3-
program_error::ProgramError,
4-
pubkey::Pubkey,
5-
instruction::Instruction,
2+
crate::{
3+
accounts as receiver_accounts,
4+
instruction as receiver_instruction,
5+
tests::simulator::ProgramSimulator,
66
},
7+
anchor_lang::{
8+
prelude::*,
9+
InstructionData,
10+
ToAccountMetas,
11+
},
12+
rand::rngs::OsRng,
13+
solana_program::instruction::Instruction,
714
solana_sdk::{
8-
signature::Signer,
915
keccak,
16+
signature::Signer,
1017
},
11-
crate::instruction as receiver_instruction,
12-
crate::accounts as receiver_accounts,
1318
};
14-
use anchor_lang::prelude::*;
15-
use anchor_lang::Discriminator;
16-
use anchor_lang::{
17-
Owner,
18-
ToAccountMetas,
19-
InstructionData,
20-
AnchorDeserialize,
21-
};
22-
use rand::rngs::OsRng;
23-
24-
use crate::tests::simulator::ProgramSimulator;
2519

2620
#[tokio::test]
2721
async fn test_update_price() {
@@ -38,10 +32,20 @@ async fn test_update_price() {
3832
let secp_message = libsecp256k1::Message::parse(&message_hash.0);
3933
let (signature, recovery_id) = libsecp256k1::sign(&secp_message, &secp256k1_secret_key);
4034

41-
let accounts = receiver_accounts::Update { payer: sim.genesis_keypair.pubkey() }.to_account_metas(None);
42-
let instruction_data = receiver_instruction::Update { data: message.to_vec(), recovery_id: recovery_id.serialize(), signature: signature.serialize() }.data();
35+
let accounts = receiver_accounts::Update {
36+
payer: sim.genesis_keypair.pubkey(),
37+
}
38+
.to_account_metas(None);
39+
let instruction_data = receiver_instruction::Update {
40+
data: message.to_vec(),
41+
recovery_id: recovery_id.serialize(),
42+
signature: signature.serialize(),
43+
}
44+
.data();
4345

4446
let inst = Instruction::new_with_bytes(sim.program_id, &instruction_data, accounts);
4547

46-
let result = sim.process_ix(inst, &vec![], &sim.genesis_keypair.insecure_clone()).await.unwrap();
48+
sim.process_ix(inst, &vec![], &sim.genesis_keypair.insecure_clone())
49+
.await
50+
.unwrap();
4751
}

0 commit comments

Comments
 (0)