Deserialize only the discriminant in the entrypoint.

It would seem that Borsh, when deserializing an enum will consume a
large amount of stack space proportional to the number of discriminants.
This causes the entrypoint to trigger stack frame access violations
during the initial deserialization.

This change uses an enum represented by a u8 instead, and removes the
association between the discriminant and the data. Deserializing the
associated data is now pushed down to within the entrypoint match arms
instead.

Change-Id: I2dcb466bf7820b3344e175ad92988bb89f30cb15
This commit is contained in:
Reisen 2021-07-20 09:38:27 +00:00 committed by David Paryente
parent 1fc6842917
commit 1cc90e54db
7 changed files with 28 additions and 26 deletions

View File

@ -67,7 +67,7 @@ pub fn initialize(
AccountMeta::new_readonly(sysvar::rent::id(), false),
AccountMeta::new_readonly(solana_program::system_program::id(), false),
],
data: crate::instruction::Instruction::Initialize(InitializeData {
data: (crate::instruction::Instruction::Initialize, InitializeData {
initial_guardians: initial_guardians.to_vec(),
fee,
fee_persistent,
@ -122,7 +122,7 @@ pub fn post_message(
AccountMeta::new_readonly(solana_program::system_program::id(), false),
],
data: crate::instruction::Instruction::PostMessage(PostMessageData {
data: (crate::instruction::Instruction::PostMessage, PostMessageData {
nonce,
payload: payload.clone(),
persist,
@ -163,7 +163,7 @@ pub fn verify_signatures(
AccountMeta::new_readonly(solana_program::system_program::id(), false),
],
data: crate::instruction::Instruction::VerifySignatures(data).try_to_vec()?,
data: (crate::instruction::Instruction::VerifySignatures, data).try_to_vec()?,
})
}
@ -211,7 +211,7 @@ pub fn post_vaa(program_id: Pubkey, payer: Pubkey, vaa: PostVAAData) -> Instruct
AccountMeta::new_readonly(solana_program::system_program::id(), false),
],
data: crate::instruction::Instruction::PostVAA(vaa)
data: (crate::instruction::Instruction::PostVAA, vaa)
.try_to_vec()
.unwrap(),
}
@ -246,7 +246,7 @@ pub fn upgrade_contract(
AccountMeta::new(spill, false),
],
data: crate::instruction::Instruction::UpgradeContract(UpgradeContractData {})
data: (crate::instruction::Instruction::UpgradeContract, UpgradeContractData {})
.try_to_vec()
.unwrap(),
}
@ -294,7 +294,7 @@ pub fn upgrade_guardian_set(
AccountMeta::new_readonly(solana_program::system_program::id(), false),
],
data: crate::instruction::Instruction::UpgradeGuardianSet(UpgradeGuardianSetData {})
data: (crate::instruction::Instruction::UpgradeGuardianSet, UpgradeGuardianSetData {})
.try_to_vec()
.unwrap(),
}
@ -328,7 +328,7 @@ pub fn set_fees(
AccountMeta::new_readonly(solana_program::system_program::id(), false),
],
data: crate::instruction::Instruction::SetFees(SetFeesData {})
data: (crate::instruction::Instruction::SetFees, SetFeesData {})
.try_to_vec()
.unwrap(),
}
@ -368,7 +368,7 @@ pub fn transfer_fees(
AccountMeta::new_readonly(solana_program::system_program::id(), false),
],
data: crate::instruction::Instruction::TransferFees(TransferFeesData {})
data: (crate::instruction::Instruction::TransferFees, TransferFeesData {})
.try_to_vec()
.unwrap(),
}

View File

@ -10,6 +10,7 @@ name = "token_bridge"
[features]
no-entrypoint = ["solitaire/no-entrypoint"]
trace = ["solitaire/trace"]
client = ["solitaire-client", "solitaire/client", "no-entrypoint"]
cpi = ["no-entrypoint"]
default = []

View File

@ -84,7 +84,7 @@ pub fn attest_token(
// Populate fields
}
let params = bridge::instruction::Instruction::PostMessage(PostMessageData {
let params = (bridge::instruction::Instruction::PostMessage, PostMessageData {
nonce: data.nonce,
payload: payload.try_to_vec()?,
persist: true,

View File

@ -148,7 +148,7 @@ pub fn transfer_native(
to_chain: data.target_chain,
fee: U256::from(data.fee),
};
let params = bridge::instruction::Instruction::PostMessage(PostMessageData {
let params = (bridge::instruction::Instruction::PostMessage, PostMessageData {
nonce: data.nonce,
payload: payload.try_to_vec()?,
persist: true,
@ -272,7 +272,7 @@ pub fn transfer_wrapped(
to_chain: data.target_chain,
fee: U256::from(data.fee),
};
let params = bridge::instruction::Instruction::PostMessage(PostMessageData {
let params = (bridge::instruction::Instruction::PostMessage, PostMessageData {
nonce: data.nonce,
payload: payload.try_to_vec()?,
persist: true,

View File

@ -43,7 +43,7 @@ pub fn initialize(
AccountMeta::new(solana_program::sysvar::rent::id(), false),
AccountMeta::new(solana_program::system_program::id(), false),
],
data: crate::instruction::Instruction::Initialize(bridge).try_to_vec()?,
data: (crate::instruction::Instruction::Initialize, bridge).try_to_vec()?,
})
}
@ -90,7 +90,7 @@ pub fn complete_native(
// Program
AccountMeta::new_readonly(bridge_id, false),
],
data: crate::instruction::Instruction::CompleteNative(data).try_to_vec()?,
data: (crate::instruction::Instruction::CompleteNative, data).try_to_vec()?,
})
}
@ -139,7 +139,7 @@ pub fn complete_wrapped(
// Program
AccountMeta::new_readonly(bridge_id, false),
],
data: crate::instruction::Instruction::CompleteWrapped(data).try_to_vec()?,
data: (crate::instruction::Instruction::CompleteWrapped, data).try_to_vec()?,
})
}
@ -194,7 +194,7 @@ pub fn create_wrapped(
// Program
AccountMeta::new_readonly(bridge_id, false),
],
data: crate::instruction::Instruction::CreateWrapped(data).try_to_vec()?,
data: (crate::instruction::Instruction::CreateWrapped, data).try_to_vec()?,
})
}
@ -231,7 +231,7 @@ pub fn register_chain(
// Program
AccountMeta::new_readonly(bridge_id, false),
],
data: crate::instruction::Instruction::RegisterChain(data).try_to_vec()?,
data: (crate::instruction::Instruction::RegisterChain, data).try_to_vec()?,
})
}
@ -324,7 +324,7 @@ pub fn transfer_native(
AccountMeta::new_readonly(bridge_id, false),
AccountMeta::new_readonly(spl_token::id(), false),
],
data: crate::instruction::Instruction::TransferNative(data).try_to_vec()?,
data: (crate::instruction::Instruction::TransferNative, data).try_to_vec()?,
})
}
@ -410,7 +410,7 @@ pub fn transfer_wrapped(
AccountMeta::new_readonly(bridge_id, false),
AccountMeta::new_readonly(spl_token::id(), false),
],
data: crate::instruction::Instruction::TransferWrapped(data).try_to_vec()?,
data: (crate::instruction::Instruction::TransferWrapped, data).try_to_vec()?,
})
}
@ -473,7 +473,7 @@ pub fn attest(
// Program
AccountMeta::new_readonly(bridge_id, false),
],
data: crate::instruction::Instruction::AttestToken(AttestTokenData { nonce })
data: (crate::instruction::Instruction::AttestToken, AttestTokenData { nonce })
.try_to_vec()?,
})
}

View File

@ -1,5 +1,4 @@
#![feature(const_generics)]
#![feature(const_generics_defaults)]
#![allow(warnings)]
// #![cfg(all(target_arch = "bpf", not(feature = "no-entrypoint")))]
@ -12,7 +11,7 @@ pub mod api;
pub mod messages;
pub mod types;
use api::{
pub use api::{
attest_token, complete_native, complete_wrapped, create_wrapped, initialize, register_chain,
transfer_native, transfer_wrapped, AttestToken, AttestTokenData, CompleteNative,
CompleteNativeData, CompleteWrapped, CompleteWrappedData, CreateWrapped, CreateWrappedData,

View File

@ -47,23 +47,25 @@ macro_rules! solitaire {
/// This Instruction contains a 1-1 mapping for each enum variant to function call. The
/// function calls can be found below in the `api` module.
#[repr(u8)]
#[derive(BorshSerialize, BorshDeserialize)]
pub enum Instruction {
$($row($kind),)*
$($row,)*
}
/// This entrypoint is generated from the enum above, it deserializes incoming bytes
/// and automatically dispatches to the correct method.
pub fn dispatch<'a, 'b: 'a, 'c>(p: &Pubkey, a: &'c [AccountInfo<'b>], d: &[u8]) -> Result<()> {
match Instruction::try_from_slice(d).map_err(|e| SolitaireError::InstructionDeserializeFailed(e))? {
match d[0] {
$(
Instruction::$row(ix_data) => {
n if n == Instruction::$row as u8 => {
trace!("Dispatch: {}", stringify!($row));
let (mut accounts): ($row) = FromAccounts::from(p, &mut a.iter(), &())?;
let ix_data: $kind = BorshDeserialize::try_from_slice(&d[1..]).map_err(|e| SolitaireError::InstructionDeserializeFailed(e))?;
let mut accounts: $row = FromAccounts::from(p, &mut a.iter(), &())?;
$fn(&ExecutionContext{program_id: p, accounts: a}, &mut accounts, ix_data)?;
Persist::persist(&accounts, p)?;
Ok(())
}
},
)*
_ => {