Skip to content

Commit da9b5ff

Browse files
committed
solana: begin fallback processor clean up
clean up initialize fast market order
1 parent e844aff commit da9b5ff

File tree

3 files changed

+174
-168
lines changed

3 files changed

+174
-168
lines changed
Lines changed: 126 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,76 @@
1-
use anchor_lang::prelude::*;
2-
use anchor_lang::Discriminator;
3-
use anchor_spl::token_interface::spl_token_metadata_interface::borsh::BorshDeserialize;
1+
use anchor_lang::{prelude::*, Discriminator};
42
use bytemuck::{Pod, Zeroable};
5-
use solana_program::instruction::Instruction;
6-
use solana_program::keccak;
7-
use solana_program::program::invoke_signed_unchecked;
8-
use wormhole_svm_shim::verify_vaa::VerifyHash;
9-
use wormhole_svm_shim::verify_vaa::VerifyHashAccounts;
10-
use wormhole_svm_shim::verify_vaa::VerifyHashData;
3+
use solana_program::{instruction::Instruction, keccak, program::invoke_signed_unchecked};
4+
use wormhole_svm_shim::verify_vaa;
115

12-
use super::helpers::create_account_reliably;
13-
14-
use super::helpers::require_min_account_infos_len;
15-
use super::FallbackMatchingEngineInstruction;
16-
use crate::error::MatchingEngineError;
17-
use crate::state::FastMarketOrder as FastMarketOrderState;
18-
use crate::ID;
6+
use crate::{error::MatchingEngineError, state::FastMarketOrder, ID};
197

208
pub struct InitializeFastMarketOrderAccounts<'ix> {
21-
/// The signer of the transaction
9+
/// Lamports from this signer will be used to create the new fast market
10+
/// order account. This account will be the only authority allowed to
11+
/// close this account.
12+
/// TODO: Rename to "payer".
2213
pub signer: &'ix Pubkey,
23-
/// The fast market order account pubkey (that is created by the instruction)
14+
/// The fast market order account pubkey (that is created by the
15+
/// instruction).
16+
/// TODO: Rename to "new_fast_market_order".
2417
pub fast_market_order_account: &'ix Pubkey,
25-
/// The guardian set account pubkey
18+
/// Wormhole guardian set account used to check recovered pubkeys using
19+
/// [Self::guardian_set_signatures].
20+
/// TODO: Rename to "wormhole_guardian_set"
2621
pub guardian_set: &'ix Pubkey,
27-
/// The guardian set signatures account pubkey (created by the post verify vaa shim program)
22+
/// The guardian set signatures of fast market order VAA.
23+
/// TODO: Rename to "shim_guardian_signatures".
2824
pub guardian_set_signatures: &'ix Pubkey,
29-
/// The verify vaa shim program pubkey
3025
pub verify_vaa_shim_program: &'ix Pubkey,
31-
/// The system program account pubkey
26+
/// TODO: Remove.
3227
pub system_program: &'ix Pubkey,
3328
}
3429

35-
impl<'ix> InitializeFastMarketOrderAccounts<'ix> {
36-
pub fn to_account_metas(&self) -> Vec<AccountMeta> {
37-
vec![
38-
AccountMeta::new(*self.signer, true), // This will be the refund recipient
39-
AccountMeta::new(*self.fast_market_order_account, false),
40-
AccountMeta::new_readonly(*self.guardian_set, false),
41-
AccountMeta::new_readonly(*self.guardian_set_signatures, false),
42-
AccountMeta::new_readonly(*self.verify_vaa_shim_program, false),
43-
AccountMeta::new_readonly(*self.system_program, false),
44-
]
45-
}
46-
}
47-
4830
#[derive(Debug, Copy, Clone, Pod, Zeroable)]
4931
#[repr(C)]
5032
pub struct InitializeFastMarketOrderData {
5133
/// The fast market order as the bytemuck struct
52-
pub fast_market_order: FastMarketOrderState,
34+
pub fast_market_order: FastMarketOrder,
5335
/// The guardian set bump
5436
pub guardian_set_bump: u8,
5537
/// Padding to ensure bytemuck deserialization works
5638
_padding: [u8; 7],
5739
}
40+
5841
impl InitializeFastMarketOrderData {
5942
// Adds the padding to the InitializeFastMarketOrderData
60-
pub fn new(fast_market_order: FastMarketOrderState, guardian_set_bump: u8) -> Self {
43+
pub fn new(fast_market_order: FastMarketOrder, guardian_set_bump: u8) -> Self {
6144
Self {
6245
fast_market_order,
6346
guardian_set_bump,
64-
_padding: [0_u8; 7],
47+
_padding: Default::default(),
6548
}
6649
}
6750

68-
/// Deserializes the InitializeFastMarketOrderData from a byte slice
51+
/// Deserializes the InitializeFastMarketOrderData from a byte slice.
6952
///
7053
/// # Arguments
7154
///
72-
/// * `data` - A byte slice containing the InitializeFastMarketOrderData
55+
/// * `data` - A byte slice containing the InitializeFastMarketOrderData.
7356
///
7457
/// # Returns
7558
///
76-
/// Option<&Self> - The deserialized InitializeFastMarketOrderData or None if the byte slice is not the correct length
59+
/// Option<&Self> - The deserialized `InitializeFastMarketOrderData`` or
60+
/// `None` if the byte slice is not the correct length.
7761
pub fn from_bytes(data: &[u8]) -> Option<&Self> {
78-
bytemuck::try_from_bytes::<Self>(data).ok()
62+
bytemuck::try_from_bytes(data).ok()
7963
}
8064
}
8165

66+
/// Initializes the fast market order account.
67+
///
68+
/// The verify shim program first checks that the digest of the fast market
69+
/// order is correct, and that the guardian signature is correct and
70+
/// recoverable. If this is the case, the fast market order account is created.
71+
/// The fast market order account is owned by the matching engine program. It
72+
/// can be closed by the close fast market order instruction, which returns the
73+
/// lamports to the close account refund recipient.
8274
pub struct InitializeFastMarketOrder<'ix> {
8375
pub program_id: &'ix Pubkey,
8476
pub accounts: InitializeFastMarketOrderAccounts<'ix>,
@@ -87,113 +79,120 @@ pub struct InitializeFastMarketOrder<'ix> {
8779

8880
impl InitializeFastMarketOrder<'_> {
8981
pub fn instruction(&self) -> Instruction {
82+
let InitializeFastMarketOrderAccounts {
83+
signer: payer,
84+
fast_market_order_account: new_fast_market_order,
85+
guardian_set: wormhole_guardian_set,
86+
guardian_set_signatures: shim_guardian_signatures,
87+
verify_vaa_shim_program,
88+
system_program: _,
89+
} = self.accounts;
90+
9091
Instruction {
9192
program_id: *self.program_id,
92-
accounts: self.accounts.to_account_metas(),
93-
data: FallbackMatchingEngineInstruction::InitializeFastMarketOrder(&self.data).to_vec(),
93+
accounts: vec![
94+
AccountMeta::new(*payer, true),
95+
AccountMeta::new(*new_fast_market_order, false),
96+
AccountMeta::new_readonly(*wormhole_guardian_set, false),
97+
AccountMeta::new_readonly(*shim_guardian_signatures, false),
98+
AccountMeta::new_readonly(*verify_vaa_shim_program, false),
99+
AccountMeta::new_readonly(solana_program::system_program::ID, false),
100+
],
101+
data: super::FallbackMatchingEngineInstruction::InitializeFastMarketOrder(&self.data)
102+
.to_vec(),
94103
}
95104
}
96105
}
97106

98-
/// Initializes the fast market order account
99-
///
100-
/// The verify shim program first checks that the digest of the fast market order is correct, and that the guardian signature is correct and recoverable.
101-
/// If this is the case, the fast market order account is created. The fast market order account is owned by the matching engine program. It can be closed
102-
/// by the close fast market order instruction, which returns the lamports to the close account refund recipient.
103-
///
104-
/// # Arguments
105-
///
106-
/// * `accounts` - The accounts of the fast market order and the guardian set
107-
///
108-
/// # Returns
109-
///
110-
/// Result<()>
111-
pub fn initialize_fast_market_order(
107+
pub(super) fn process(
112108
accounts: &[AccountInfo],
113109
data: &InitializeFastMarketOrderData,
114110
) -> Result<()> {
115-
require_min_account_infos_len(accounts, 6)?;
116-
117-
let signer = &accounts[0];
118-
let fast_market_order_account = &accounts[1];
119-
let guardian_set = &accounts[2];
120-
let guardian_set_signatures = &accounts[3];
121-
122-
let InitializeFastMarketOrderData {
123-
fast_market_order,
124-
guardian_set_bump,
125-
_padding: _,
126-
} = data;
127-
// Start of cpi call to verify the shim.
128-
// ------------------------------------------------------------------------------------------------
111+
super::helpers::require_min_account_infos_len(accounts, 6)?;
112+
113+
let fast_market_order = &data.fast_market_order;
114+
115+
// Generate the VAA digest, which will be used to verify the guardian
116+
// signatures.
129117
let fast_market_order_vaa_digest = fast_market_order.digest();
130-
let fast_market_order_vaa_digest_hash =
131-
keccak::Hash::try_from_slice(&fast_market_order_vaa_digest).unwrap();
132-
let verify_hash_data =
133-
VerifyHashData::new(*guardian_set_bump, fast_market_order_vaa_digest_hash);
134-
let verify_hash_shim_ix = VerifyHash {
135-
program_id: &wormhole_svm_definitions::solana::VERIFY_VAA_SHIM_PROGRAM_ID,
136-
accounts: VerifyHashAccounts {
137-
guardian_set: &guardian_set.key(),
138-
guardian_signatures: &guardian_set_signatures.key(),
139-
},
140-
data: verify_hash_data,
141-
}
142-
.instruction();
143-
// Make the cpi call to verify the shim.
144-
invoke_signed_unchecked(&verify_hash_shim_ix, accounts, &[])?;
145-
// ------------------------------------------------------------------------------------------------
146-
// End of cpi call to verify the shim.
147-
148-
// Start of fast market order account creation
149-
// ------------------------------------------------------------------------------------------------
150-
let fast_market_order_key = fast_market_order_account.key();
151-
let space = 8_usize.saturating_add(std::mem::size_of::<FastMarketOrderState>());
152-
let (fast_market_order_pda, fast_market_order_bump) = Pubkey::find_program_address(
118+
119+
// This payer will send lamports to the new fast market order account and
120+
// will be the "owner" of this account. Only this account can close the
121+
// fast market order account.
122+
let payer_info = &accounts[0];
123+
124+
// Verify that the fast market order account's key is derived correctly.
125+
let new_fast_market_order_info = &accounts[1];
126+
let fast_market_order_key = new_fast_market_order_info.key;
127+
let (expected_fast_market_order_key, fast_market_order_bump) = Pubkey::find_program_address(
153128
&[
154-
FastMarketOrderState::SEED_PREFIX,
155-
fast_market_order_vaa_digest.as_ref(),
129+
FastMarketOrder::SEED_PREFIX,
130+
&fast_market_order_vaa_digest,
156131
fast_market_order.close_account_refund_recipient.as_ref(),
157132
],
158133
&ID,
159134
);
160135

161-
if fast_market_order_pda != fast_market_order_key {
162-
msg!("Fast market order pda is invalid");
163-
return Err(MatchingEngineError::InvalidPda.into())
164-
.map_err(|e: Error| e.with_pubkeys((fast_market_order_key, fast_market_order_pda)));
136+
if fast_market_order_key != &expected_fast_market_order_key {
137+
return Err(MatchingEngineError::InvalidPda.into()).map_err(|e: Error| {
138+
e.with_account_name("fast_market_order")
139+
.with_pubkeys((*fast_market_order_key, expected_fast_market_order_key))
140+
});
165141
}
166-
let fast_market_order_seeds = [
167-
FastMarketOrderState::SEED_PREFIX,
168-
fast_market_order_vaa_digest.as_ref(),
169-
fast_market_order.close_account_refund_recipient.as_ref(),
170-
&[fast_market_order_bump],
171-
];
172-
let fast_market_order_signer_seeds = &[&fast_market_order_seeds[..]];
173-
// Create the account using the system program. The create account reliably ensures that the account creation cannot be raced.
174-
create_account_reliably(
175-
&signer.key(),
176-
&fast_market_order_key,
177-
fast_market_order_account.lamports(),
178-
space,
142+
143+
// These accounts will be used by the Verify VAA shim program.
144+
let wormhole_guardian_set_info = &accounts[2];
145+
let shim_guardian_signatures_info = &accounts[3];
146+
147+
// Verify the VAA digest with the Verify VAA shim program.
148+
invoke_signed_unchecked(
149+
&verify_vaa::VerifyHash {
150+
program_id: &wormhole_svm_definitions::solana::VERIFY_VAA_SHIM_PROGRAM_ID,
151+
accounts: verify_vaa::VerifyHashAccounts {
152+
guardian_set: wormhole_guardian_set_info.key,
153+
guardian_signatures: shim_guardian_signatures_info.key,
154+
},
155+
data: verify_vaa::VerifyHashData::new(
156+
data.guardian_set_bump,
157+
keccak::Hash(fast_market_order_vaa_digest),
158+
),
159+
}
160+
.instruction(),
179161
accounts,
180-
&ID,
181-
fast_market_order_signer_seeds,
162+
&[],
182163
)?;
183-
// Borrow the account data mutably
184-
let mut fast_market_order_account_data = fast_market_order_account.try_borrow_mut_data()?;
185164

186-
// Write the discriminator to the first 8 bytes
187-
let discriminator = FastMarketOrderState::discriminator();
188-
fast_market_order_account_data[0..8].copy_from_slice(&discriminator);
165+
// Create the new fast market order account and serialize the instruction
166+
// data into it.
167+
168+
const DISCRIMINATOR_LEN: usize = FastMarketOrder::DISCRIMINATOR.len();
169+
const FAST_MARKET_ORDER_DATA_LEN: usize =
170+
DISCRIMINATOR_LEN + std::mem::size_of::<FastMarketOrder>();
171+
172+
super::helpers::create_account_reliably(
173+
payer_info.key,
174+
fast_market_order_key,
175+
new_fast_market_order_info.lamports(),
176+
FAST_MARKET_ORDER_DATA_LEN,
177+
accounts,
178+
&ID,
179+
&[&[
180+
FastMarketOrder::SEED_PREFIX,
181+
&fast_market_order_vaa_digest,
182+
// TODO: Replace with payer_info.key.
183+
fast_market_order.close_account_refund_recipient.as_ref(),
184+
&[fast_market_order_bump],
185+
]],
186+
)?;
189187

190-
let fast_market_order_bytes = bytemuck::bytes_of(fast_market_order);
188+
let mut new_fast_market_order_info_data = new_fast_market_order_info.try_borrow_mut_data()?;
191189

192-
// Write the fast_market_order struct to the account
193-
fast_market_order_account_data[8..8_usize.saturating_add(fast_market_order_bytes.len())]
194-
.copy_from_slice(fast_market_order_bytes);
195-
// End of fast market order account creation
196-
// ------------------------------------------------------------------------------------------------
190+
// Write provided fast market order data to account starting with its
191+
// discriminator.
192+
new_fast_market_order_info_data[0..DISCRIMINATOR_LEN]
193+
.copy_from_slice(&FastMarketOrder::DISCRIMINATOR);
194+
new_fast_market_order_info_data[DISCRIMINATOR_LEN..FAST_MARKET_ORDER_DATA_LEN]
195+
.copy_from_slice(bytemuck::bytes_of(fast_market_order));
197196

198197
Ok(())
199198
}
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
pub mod process_instruction;
2-
pub use process_instruction::*;
31
pub mod burn_and_post;
42
pub mod close_fast_market_order;
53
pub mod execute_order;
4+
pub mod helpers;
65
pub mod initialize_fast_market_order;
76
pub mod place_initial_offer;
87
pub mod prepare_order_response;
8+
pub mod process_instruction;
99

10-
pub mod helpers;
10+
pub use process_instruction::*;

0 commit comments

Comments
 (0)