Skip to content

Commit

Permalink
Avoid temporary Vecs when serialising objects with discriminators
Browse files Browse the repository at this point in the history
When serialising objects prefixed by a discriminator, rather then
using BorshSerialize::try_to_vec to create a temporary vector that is
appended to the output vector, create the output in advance, add
discriminator to it and then use BorshSerialize::serialize to
serialise the object directly to it.

Issue: #2231
  • Loading branch information
mina86 committed Nov 14, 2023
1 parent cded9de commit 63e699b
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 17 deletions.
5 changes: 3 additions & 2 deletions cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3803,8 +3803,9 @@ fn serialize_idl(idl: &Idl) -> Result<Vec<u8>> {
}

fn serialize_idl_ix(ix_inner: anchor_lang::idl::IdlInstruction) -> Result<Vec<u8>> {
let mut data = anchor_lang::idl::IDL_IX_TAG.to_le_bytes().to_vec();
data.append(&mut ix_inner.try_to_vec()?);
let mut data = Vec::with_capacity(1024);
data.extend_from_slice(&anchor_lang::idl::IDL_IX_TAG.to_le_bytes());
ix_inner.serialize(&mut data)?;
Ok(data)
}

Expand Down
16 changes: 7 additions & 9 deletions lang/attribute/event/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,9 @@ pub fn event(
let event_name = &event_strct.ident;

let discriminator: proc_macro2::TokenStream = {
let discriminator_preimage = format!("event:{event_name}");
let mut discriminator = [0u8; 8];
discriminator.copy_from_slice(
&anchor_syn::hash::hash(discriminator_preimage.as_bytes()).to_bytes()[..8],
);
format!("{discriminator:?}").parse().unwrap()
let discriminator_preimage = format!("event:{event_name}").into_bytes();
let discriminator = anchor_syn::hash::hash(&discriminator_preimage);
format!("{:?}", &discriminator.0[..8]).parse().unwrap()
};

let ret = quote! {
Expand All @@ -35,9 +32,10 @@ pub fn event(

impl anchor_lang::Event for #event_name {
fn data(&self) -> Vec<u8> {
let mut d = #discriminator.to_vec();
d.append(&mut self.try_to_vec().unwrap());
d
let mut data = Vec::with_capacity(1024);
data.extend_from_slice(&#discriminator);
self.serialize(&mut data).unwrap();
data
}
}

Expand Down
7 changes: 4 additions & 3 deletions lang/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,9 +266,10 @@ pub trait ZeroCopy: Discriminator + Copy + Clone + Zeroable + Pod {}
/// to an instruction.
pub trait InstructionData: Discriminator + AnchorSerialize {
fn data(&self) -> Vec<u8> {
let mut d = Self::discriminator().to_vec();
d.append(&mut self.try_to_vec().expect("Should always serialize"));
d
let mut data = Vec::with_capacity(1024);
data.extend_from_slice(&Self::discriminator());
self.serialize(&mut data).unwrap();
data
}
}

Expand Down
6 changes: 3 additions & 3 deletions lang/syn/src/codegen/program/cpi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ pub fn generate(program: &Program) -> proc_macro2::TokenStream {
) -> #method_ret {
let ix = {
let ix = instruction::#ix_variant;
let mut ix_data = AnchorSerialize::try_to_vec(&ix)
let mut data = Vec::with_capacity(1024);
data.extend_from_slice(&#sighash_tts);
AnchorSerialize::serialize(&ix, &mut data)
.map_err(|_| anchor_lang::error::ErrorCode::InstructionDidNotSerialize)?;
let mut data = #sighash_tts.to_vec();
data.append(&mut ix_data);
let accounts = ctx.to_account_metas(None);
anchor_lang::solana_program::instruction::Instruction {
program_id: ctx.program.key(),
Expand Down

0 comments on commit 63e699b

Please sign in to comment.