Skip to content

Commit 1ceb2ed

Browse files
committed
refactor(lazer): keep good names for new types and methods
1 parent 47230d7 commit 1ceb2ed

File tree

7 files changed

+96
-100
lines changed

7 files changed

+96
-100
lines changed

lazer/Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lazer/contracts/solana/programs/pyth-lazer-solana-contract/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "pyth-lazer-solana-contract"
3-
version = "0.1.0"
3+
version = "0.2.0"
44
edition = "2021"
55
description = "Pyth Lazer Solana contract and SDK."
66
license = "Apache-2.0"

lazer/contracts/solana/programs/pyth-lazer-solana-contract/src/lib.rs

Lines changed: 25 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ mod signature;
33
use {
44
crate::signature::VerifiedMessage,
55
anchor_lang::{prelude::*, solana_program::pubkey::PUBKEY_BYTES, system_program},
6-
std::io::Cursor,
7-
std::mem::size_of,
6+
std::{io::Cursor, mem::size_of},
87
};
98

109
pub use {
@@ -24,6 +23,7 @@ fn test_ids() {
2423
);
2524
}
2625

26+
pub const ANCHOR_DISCRIMINATOR_BYTES: usize = 8;
2727
pub const MAX_NUM_TRUSTED_SIGNERS: usize = 2;
2828
pub const SPACE_FOR_TRUSTED_SIGNERS: usize = 5;
2929
pub const EXTRA_SPACE: usize = 100;
@@ -39,15 +39,15 @@ impl TrustedSignerInfo {
3939
}
4040

4141
/// TODO: remove this legacy storage type
42-
#[account]
43-
pub struct Storage {
42+
#[derive(AnchorDeserialize)]
43+
pub struct StorageV010 {
4444
pub top_authority: Pubkey,
4545
pub num_trusted_signers: u8,
4646
pub trusted_signers: [TrustedSignerInfo; MAX_NUM_TRUSTED_SIGNERS],
4747
}
4848

49-
impl Storage {
50-
const SERIALIZED_LEN: usize = PUBKEY_BYTES
49+
impl StorageV010 {
50+
pub const SERIALIZED_LEN: usize = PUBKEY_BYTES
5151
+ size_of::<u8>()
5252
+ TrustedSignerInfo::SERIALIZED_LEN * MAX_NUM_TRUSTED_SIGNERS;
5353

@@ -57,7 +57,7 @@ impl Storage {
5757
}
5858

5959
#[account]
60-
pub struct StorageV2 {
60+
pub struct Storage {
6161
pub top_authority: Pubkey,
6262
pub treasury: Pubkey,
6363
pub single_update_fee_in_lamports: u64,
@@ -66,7 +66,7 @@ pub struct StorageV2 {
6666
pub _extra_space: [u8; EXTRA_SPACE],
6767
}
6868

69-
impl StorageV2 {
69+
impl Storage {
7070
const SERIALIZED_LEN: usize = PUBKEY_BYTES
7171
+ PUBKEY_BYTES
7272
+ size_of::<u64>()
@@ -83,16 +83,12 @@ pub const STORAGE_SEED: &[u8] = b"storage";
8383

8484
#[program]
8585
pub mod pyth_lazer_solana_contract {
86-
use super::*;
86+
use anchor_lang::Discriminator;
8787

88-
/// TODO: remove this legacy instruction
89-
pub fn initialize(ctx: Context<Initialize>, top_authority: Pubkey) -> Result<()> {
90-
ctx.accounts.storage.top_authority = top_authority;
91-
Ok(())
92-
}
88+
use super::*;
9389

94-
pub fn initialize_v2(
95-
ctx: Context<InitializeV2>,
90+
pub fn initialize(
91+
ctx: Context<Initialize>,
9692
top_authority: Pubkey,
9793
treasury: Pubkey,
9894
) -> Result<()> {
@@ -102,20 +98,25 @@ pub mod pyth_lazer_solana_contract {
10298
Ok(())
10399
}
104100

105-
pub fn migrate_to_storage_v2(ctx: Context<MigrateToStorageV2>, treasury: Pubkey) -> Result<()> {
106-
let old_storage = Storage::try_deserialize(&mut &**ctx.accounts.storage.data.borrow())?;
101+
pub fn migrate_from_0_1_0(ctx: Context<MigrateFrom010>, treasury: Pubkey) -> Result<()> {
102+
let old_data = ctx.accounts.storage.data.borrow();
103+
if old_data[0..ANCHOR_DISCRIMINATOR_BYTES] != Storage::DISCRIMINATOR {
104+
return Err(ProgramError::InvalidAccountData.into());
105+
}
106+
let old_storage = StorageV010::deserialize(&mut &old_data[ANCHOR_DISCRIMINATOR_BYTES..])?;
107107
if old_storage.top_authority != ctx.accounts.top_authority.key() {
108108
return Err(ProgramError::MissingRequiredSignature.into());
109109
}
110+
drop(old_data);
110111

111-
let space = 8 + StorageV2::SERIALIZED_LEN;
112+
let space = ANCHOR_DISCRIMINATOR_BYTES + Storage::SERIALIZED_LEN;
112113
ctx.accounts.storage.realloc(space, false)?;
113114
let min_lamports = Rent::get()?.minimum_balance(space);
114115
if ctx.accounts.storage.lamports() < min_lamports {
115116
return Err(ProgramError::AccountNotRentExempt.into());
116117
}
117118

118-
let mut new_storage = StorageV2 {
119+
let mut new_storage = Storage {
119120
top_authority: old_storage.top_authority,
120121
treasury,
121122
single_update_fee_in_lamports: 1,
@@ -228,7 +229,7 @@ pub struct Initialize<'info> {
228229
#[account(
229230
init,
230231
payer = payer,
231-
space = 8 + Storage::SERIALIZED_LEN,
232+
space = ANCHOR_DISCRIMINATOR_BYTES + Storage::SERIALIZED_LEN,
232233
seeds = [STORAGE_SEED],
233234
bump,
234235
)]
@@ -237,7 +238,7 @@ pub struct Initialize<'info> {
237238
}
238239

239240
#[derive(Accounts)]
240-
pub struct MigrateToStorageV2<'info> {
241+
pub struct MigrateFrom010<'info> {
241242
pub top_authority: Signer<'info>,
242243
#[account(
243244
mut,
@@ -249,21 +250,6 @@ pub struct MigrateToStorageV2<'info> {
249250
pub system_program: Program<'info, System>,
250251
}
251252

252-
#[derive(Accounts)]
253-
pub struct InitializeV2<'info> {
254-
#[account(mut)]
255-
pub payer: Signer<'info>,
256-
#[account(
257-
init,
258-
payer = payer,
259-
space = 8 + StorageV2::SERIALIZED_LEN,
260-
seeds = [STORAGE_SEED],
261-
bump,
262-
)]
263-
pub storage: Account<'info, StorageV2>,
264-
pub system_program: Program<'info, System>,
265-
}
266-
267253
#[derive(Accounts)]
268254
pub struct Update<'info> {
269255
pub top_authority: Signer<'info>,
@@ -273,7 +259,7 @@ pub struct Update<'info> {
273259
bump,
274260
has_one = top_authority,
275261
)]
276-
pub storage: Account<'info, StorageV2>,
262+
pub storage: Account<'info, Storage>,
277263
}
278264

279265
#[derive(Accounts)]
@@ -285,7 +271,7 @@ pub struct VerifyMessage<'info> {
285271
bump,
286272
has_one = treasury
287273
)]
288-
pub storage: Account<'info, StorageV2>,
274+
pub storage: Account<'info, Storage>,
289275
/// CHECK: this account doesn't need additional constraints.
290276
pub treasury: AccountInfo<'info>,
291277
pub system_program: Program<'info, System>,

lazer/contracts/solana/programs/pyth-lazer-solana-contract/src/signature.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use {
2-
crate::StorageV2,
2+
crate::Storage,
33
anchor_lang::{
44
prelude::{borsh, AccountInfo, Clock, ProgramError, Pubkey, SolanaSysvar},
55
solana_program::{ed25519_program, pubkey::PUBKEY_BYTES, sysvar},
@@ -158,7 +158,7 @@ impl From<SignatureVerificationError> for anchor_lang::error::Error {
158158
/// - `message_offset` is the offset of the signed message within the
159159
/// input data for the current instruction.
160160
pub fn verify_message(
161-
storage: &StorageV2,
161+
storage: &Storage,
162162
instructions_sysvar: &AccountInfo,
163163
message_data: &[u8],
164164
ed25519_instruction_index: u16,

lazer/contracts/solana/programs/pyth-lazer-solana-contract/tests/test1.rs

Lines changed: 64 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,47 @@
11
use {
22
anchor_lang::{prelude::AccountMeta, InstructionData},
3-
pyth_lazer_solana_contract::ed25519_program_args,
3+
pyth_lazer_solana_contract::{ed25519_program_args, ANCHOR_DISCRIMINATOR_BYTES},
44
solana_program_test::{BanksClient, ProgramTest},
55
solana_sdk::{
6-
ed25519_program, hash::Hash, instruction::Instruction, pubkey::Pubkey, signature::Keypair,
7-
signer::Signer, system_instruction, system_program, system_transaction, sysvar,
6+
account::Account,
7+
ed25519_program,
8+
hash::Hash,
9+
instruction::Instruction,
10+
pubkey::{Pubkey, PUBKEY_BYTES},
11+
signature::Keypair,
12+
signer::Signer,
13+
system_instruction, system_program, system_transaction, sysvar,
814
transaction::Transaction,
915
},
1016
std::env,
1117
};
1218

19+
fn program_test() -> ProgramTest {
20+
if env::var("SBF_OUT_DIR").is_err() {
21+
env::set_var(
22+
"SBF_OUT_DIR",
23+
format!(
24+
"{}/../../../../target/sbf-solana-solana/release",
25+
env::var("CARGO_MANIFEST_DIR").unwrap()
26+
),
27+
);
28+
}
29+
println!("if add_program fails, run `cargo build-sbf` first.");
30+
ProgramTest::new(
31+
"pyth_lazer_solana_contract",
32+
pyth_lazer_solana_contract::ID,
33+
None,
34+
)
35+
}
36+
1337
struct Setup {
1438
banks_client: BanksClient,
1539
payer: Keypair,
1640
recent_blockhash: Hash,
1741
}
1842

1943
impl Setup {
20-
async fn new() -> Self {
21-
if env::var("SBF_OUT_DIR").is_err() {
22-
env::set_var(
23-
"SBF_OUT_DIR",
24-
format!(
25-
"{}/../../../../target/sbf-solana-solana/release",
26-
env::var("CARGO_MANIFEST_DIR").unwrap()
27-
),
28-
);
29-
}
30-
println!("if add_program fails, run `cargo build-sbf` first.");
31-
let program_test = ProgramTest::new(
32-
"pyth_lazer_solana_contract",
33-
pyth_lazer_solana_contract::ID,
34-
None,
35-
);
44+
async fn with_program_test(program_test: ProgramTest) -> Self {
3645
let (banks_client, payer, recent_blockhash) = program_test.start().await;
3746
Self {
3847
banks_client,
@@ -41,6 +50,10 @@ impl Setup {
4150
}
4251
}
4352

53+
async fn new() -> Self {
54+
Self::with_program_test(program_test()).await
55+
}
56+
4457
async fn create_treasury(&mut self) -> Pubkey {
4558
let treasury =
4659
Pubkey::create_with_seed(&self.payer.pubkey(), "treasury", &system_program::ID)
@@ -154,14 +167,14 @@ impl Setup {
154167
}
155168

156169
#[tokio::test]
157-
async fn test_with_init_v2() {
170+
async fn test_basic() {
158171
let mut setup = Setup::new().await;
159172
let treasury = setup.create_treasury().await;
160173

161174
let mut transaction_init_contract = Transaction::new_with_payer(
162175
&[Instruction::new_with_bytes(
163176
pyth_lazer_solana_contract::ID,
164-
&pyth_lazer_solana_contract::instruction::InitializeV2 {
177+
&pyth_lazer_solana_contract::instruction::Initialize {
165178
top_authority: setup.payer.pubkey(),
166179
treasury,
167180
}
@@ -195,32 +208,33 @@ async fn test_with_init_v2() {
195208
}
196209

197210
#[tokio::test]
198-
async fn test_with_init_v1_and_migrate() {
199-
let mut setup = Setup::new().await;
200-
let treasury = setup.create_treasury().await;
201-
202-
let mut transaction_init_contract = Transaction::new_with_payer(
203-
&[Instruction::new_with_bytes(
204-
pyth_lazer_solana_contract::ID,
205-
&pyth_lazer_solana_contract::instruction::Initialize {
206-
top_authority: setup.payer.pubkey(),
207-
}
208-
.data(),
209-
vec![
210-
AccountMeta::new(setup.payer.pubkey(), true),
211-
AccountMeta::new(pyth_lazer_solana_contract::STORAGE_ID, false),
212-
AccountMeta::new_readonly(system_program::ID, false),
213-
],
214-
)],
215-
Some(&setup.payer.pubkey()),
211+
async fn test_migrate_from_0_1_0() {
212+
let mut program_test = program_test();
213+
// Create a storage PDA account with the data that was produced by the program v0.1.0.
214+
let mut old_storage_data = hex::decode(
215+
"d175ffb9c4af4409aa4dcb5d31150b162b664abd843cb231cee5c0ebf759ce371d9cb36ffc653796\
216+
0174313a6525edf99936aa1477e94c72bc5cc617b21745f5f03296f3154461f214ffffffffffffff7\
217+
f00000000000000000000000000000000000000000000000000000000000000000000000000000000",
218+
)
219+
.unwrap();
220+
let top_authority = Keypair::new();
221+
// Replace top authority pubkey in storage PDA data to allow successful migration.
222+
old_storage_data[ANCHOR_DISCRIMINATOR_BYTES..ANCHOR_DISCRIMINATOR_BYTES + PUBKEY_BYTES]
223+
.copy_from_slice(&top_authority.pubkey().to_bytes());
224+
program_test.add_account(
225+
pyth_lazer_solana_contract::STORAGE_ID,
226+
Account {
227+
lamports: 1733040,
228+
data: old_storage_data,
229+
owner: pyth_lazer_solana_contract::ID,
230+
executable: false,
231+
rent_epoch: 18446744073709551615,
232+
},
216233
);
217-
transaction_init_contract.sign(&[&setup.payer], setup.recent_blockhash);
218-
setup
219-
.banks_client
220-
.process_transaction(transaction_init_contract)
221-
.await
222-
.unwrap();
234+
let mut setup = Setup::with_program_test(program_test).await;
235+
let treasury = setup.create_treasury().await;
223236

237+
// Make sure storage PDA will be rent-exempt after resize.
224238
let tx_transfer = system_transaction::transfer(
225239
&setup.payer,
226240
&pyth_lazer_solana_contract::STORAGE_ID,
@@ -236,31 +250,30 @@ async fn test_with_init_v1_and_migrate() {
236250
let mut transaction_migrate_contract = Transaction::new_with_payer(
237251
&[Instruction::new_with_bytes(
238252
pyth_lazer_solana_contract::ID,
239-
&pyth_lazer_solana_contract::instruction::MigrateToStorageV2 { treasury }.data(),
253+
&pyth_lazer_solana_contract::instruction::MigrateFrom010 { treasury }.data(),
240254
vec![
241-
AccountMeta::new(setup.payer.pubkey(), true),
255+
AccountMeta::new(top_authority.pubkey(), true),
242256
AccountMeta::new(pyth_lazer_solana_contract::STORAGE_ID, false),
243257
AccountMeta::new_readonly(system_program::ID, false),
244258
],
245259
)],
246260
Some(&setup.payer.pubkey()),
247261
);
248-
transaction_migrate_contract.sign(&[&setup.payer], setup.recent_blockhash);
262+
transaction_migrate_contract.sign(&[&setup.payer, &top_authority], setup.recent_blockhash);
249263
setup
250264
.banks_client
251265
.process_transaction(transaction_migrate_contract)
252266
.await
253267
.unwrap();
254268

255-
let verifying_key =
256-
hex::decode("74313a6525edf99936aa1477e94c72bc5cc617b21745f5f03296f3154461f214").unwrap();
257269
let message = hex::decode(
258270
"b9011a82e5cddee2c1bd364c8c57e1c98a6a28d194afcad410ff412226c8b2ae931ff59a57147cb47c7307\
259271
afc2a0a1abec4dd7e835a5b7113cf5aeac13a745c6bed6c60074313a6525edf99936aa1477e94c72bc5cc61\
260272
7b21745f5f03296f3154461f2141c0075d3c7931c9773f30a240600010102000000010000e1f50500000000",
261273
)
262274
.unwrap();
263275

264-
setup.set_trusted(verifying_key.try_into().unwrap()).await;
276+
// The contract will recognize the trusted signer without calling `set_trusted`
277+
// because it was present in the original storage PDA data.
265278
setup.verify_message(&message, treasury).await;
266279
}

0 commit comments

Comments
 (0)