Skip to content

Commit

Permalink
sdk: Only compile wasm-bindgen when target_arch = "wasm32" (#1658)
Browse files Browse the repository at this point in the history
* move wasm-bindgen dep under cfg(target_arch = "wasm32") in sdk and program

* remove wasm_bindgen_stub (we don't need it where we're going)

* put wasm_bindgen usage behind #[cfg(target_arch = "wasm32")]

* remove doc comments from skippeed fields

* add missing attribute

* another missing attribute

* add doc comments explaining duplicated structs

* fmt

* fix wasm comments

* Update sdk/program/src/instruction.rs

---------

Co-authored-by: Jon C <me@jonc.dev>
  • Loading branch information
kevinheavey and joncinque committed Jun 18, 2024
1 parent ef80b59 commit 25ec304
Show file tree
Hide file tree
Showing 11 changed files with 87 additions and 54 deletions.
2 changes: 1 addition & 1 deletion sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,11 @@ solana-program = { workspace = true }
solana-sdk-macro = { workspace = true }
thiserror = { workspace = true }
uriparse = { workspace = true }
wasm-bindgen = { workspace = true }

[target.'cfg(target_arch = "wasm32")'.dependencies]
getrandom = { version = "0.1", features = ["wasm-bindgen"] }
js-sys = { workspace = true }
wasm-bindgen = { workspace = true }

[dev-dependencies]
anyhow = { workspace = true }
Expand Down
28 changes: 0 additions & 28 deletions sdk/macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -378,34 +378,6 @@ pub fn pubkeys(input: TokenStream) -> TokenStream {
TokenStream::from(quote! {#pubkeys})
}

// The normal `wasm_bindgen` macro generates a .bss section which causes the resulting
// SBF program to fail to load, so for now this stub should be used when building for SBF
#[proc_macro_attribute]
pub fn wasm_bindgen_stub(_attr: TokenStream, item: TokenStream) -> TokenStream {
match parse_macro_input!(item as syn::Item) {
syn::Item::Struct(mut item_struct) => {
if let syn::Fields::Named(fields) = &mut item_struct.fields {
// Strip out any `#[wasm_bindgen]` added to struct fields. This is custom
// syntax supplied by the normal `wasm_bindgen` macro.
for field in fields.named.iter_mut() {
field.attrs.retain(|attr| {
!attr
.path()
.segments
.iter()
.any(|segment| segment.ident == "wasm_bindgen")
});
}
}
quote! { #item_struct }
}
item => {
quote!(#item)
}
}
.into()
}

// Sets padding in structures to zero explicitly.
// Otherwise padding could be inconsistent across the network and lead to divergence / consensus failures.
#[proc_macro_derive(CloneZeroed)]
Expand Down
2 changes: 1 addition & 1 deletion sdk/program/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ itertools = { workspace = true }
libsecp256k1 = { workspace = true }
num-bigint = { workspace = true }
rand = { workspace = true }
wasm-bindgen = { workspace = true }

[target.'cfg(not(target_os = "solana"))'.dev-dependencies]
arbitrary = { workspace = true, features = ["derive"] }
Expand All @@ -69,6 +68,7 @@ console_error_panic_hook = { workspace = true }
console_log = { workspace = true }
getrandom = { workspace = true, features = ["js", "wasm-bindgen"] }
js-sys = { workspace = true }
wasm-bindgen = { workspace = true }

[target.'cfg(not(target_pointer_width = "64"))'.dependencies]
parking_lot = { workspace = true }
Expand Down
6 changes: 4 additions & 2 deletions sdk/program/src/hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
//! [SHA-256]: https://en.wikipedia.org/wiki/SHA-2
//! [`Hash`]: struct@Hash

#[cfg(target_arch = "wasm32")]
use crate::wasm_bindgen;
#[cfg(feature = "borsh")]
use borsh::{BorshDeserialize, BorshSchema, BorshSerialize};
use {
crate::{sanitize::Sanitize, wasm_bindgen},
crate::sanitize::Sanitize,
bytemuck::{Pod, Zeroable},
sha2::{Digest, Sha256},
std::{convert::TryFrom, fmt, mem, str::FromStr},
Expand All @@ -28,7 +30,7 @@ const MAX_BASE58_LEN: usize = 44;
/// [blake3]: https://github.com/BLAKE3-team/BLAKE3
/// [`blake3`]: crate::blake3
/// [`Message::hash`]: crate::message::Message::hash
#[wasm_bindgen]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen)]
#[cfg_attr(feature = "frozen-abi", derive(AbiExample))]
#[cfg_attr(
feature = "borsh",
Expand Down
21 changes: 17 additions & 4 deletions sdk/program/src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@

#![allow(clippy::arithmetic_side_effects)]

#[cfg(target_arch = "wasm32")]
use crate::wasm_bindgen;
#[cfg(feature = "borsh")]
use borsh::BorshSerialize;
use {
crate::{pubkey::Pubkey, sanitize::Sanitize, short_vec, wasm_bindgen},
crate::{pubkey::Pubkey, sanitize::Sanitize, short_vec},
bincode::serialize,
serde::Serialize,
thiserror::Error,
Expand Down Expand Up @@ -325,16 +327,27 @@ pub enum InstructionError {
/// Programs may require signatures from some accounts, in which case they
/// should be specified as signers during `Instruction` construction. The
/// program must still validate during execution that the account is a signer.
#[wasm_bindgen]
#[cfg(not(target_arch = "wasm32"))]
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub struct Instruction {
/// Pubkey of the program that executes this instruction.
#[wasm_bindgen(skip)]
pub program_id: Pubkey,
/// Metadata describing accounts that should be passed to the program.
#[wasm_bindgen(skip)]
pub accounts: Vec<AccountMeta>,
/// Opaque data passed to the program for its own interpretation.
pub data: Vec<u8>,
}

/// wasm-bindgen version of the Instruction struct.
/// This duplication is required until https://github.com/rustwasm/wasm-bindgen/issues/3671
/// is fixed. This must not diverge from the regular non-wasm Instruction struct.
#[cfg(target_arch = "wasm32")]
#[wasm_bindgen]
pub struct Instruction {
#[wasm_bindgen(skip)]
pub program_id: Pubkey,
#[wasm_bindgen(skip)]
pub accounts: Vec<AccountMeta>,
#[wasm_bindgen(skip)]
pub data: Vec<u8>,
}
Expand Down
7 changes: 1 addition & 6 deletions sdk/program/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -545,12 +545,7 @@ pub mod address_lookup_table_account {
pub use crate::address_lookup_table::AddressLookupTableAccount;
}

#[cfg(target_os = "solana")]
pub use solana_sdk_macro::wasm_bindgen_stub as wasm_bindgen;
/// Re-export of [wasm-bindgen].
///
/// [wasm-bindgen]: https://rustwasm.github.io/docs/wasm-bindgen/
#[cfg(not(target_os = "solana"))]
#[cfg(target_arch = "wasm32")]
pub use wasm_bindgen::prelude::wasm_bindgen;

/// The [config native program][np].
Expand Down
35 changes: 31 additions & 4 deletions sdk/program/src/message/legacy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

#![allow(clippy::arithmetic_side_effects)]

#[cfg(target_arch = "wasm32")]
use crate::wasm_bindgen;
#[allow(deprecated)]
pub use builtins::{BUILTIN_PROGRAMS_KEYS, MAYBE_BUILTIN_KEY_OR_SYSVAR};
use {
Expand All @@ -21,7 +23,7 @@ use {
message::{compiled_keys::CompiledKeys, MessageHeader},
pubkey::Pubkey,
sanitize::{Sanitize, SanitizeError},
short_vec, system_instruction, system_program, sysvar, wasm_bindgen,
short_vec, system_instruction, system_program, sysvar,
},
std::{collections::HashSet, convert::TryFrom, str::FromStr},
};
Expand Down Expand Up @@ -117,7 +119,7 @@ fn compile_instructions(ixs: &[Instruction], keys: &[Pubkey]) -> Vec<CompiledIns
/// redundantly specifying the fee-payer is not strictly required.
// NOTE: Serialization-related changes must be paired with the custom serialization
// for versioned messages in the `RemainingLegacyMessage` struct.
#[wasm_bindgen]
#[cfg(not(target_arch = "wasm32"))]
#[cfg_attr(
feature = "frozen-abi",
frozen_abi(digest = "2KnLEqfLcTBQqitE22Pp8JYkaqVVbAkGbCfdeHoyxcAU"),
Expand All @@ -128,11 +130,9 @@ fn compile_instructions(ixs: &[Instruction], keys: &[Pubkey]) -> Vec<CompiledIns
pub struct Message {
/// The message header, identifying signed and read-only `account_keys`.
// NOTE: Serialization-related changes must be paired with the direct read at sigverify.
#[wasm_bindgen(skip)]
pub header: MessageHeader,

/// All the account keys used by this transaction.
#[wasm_bindgen(skip)]
#[serde(with = "short_vec")]
pub account_keys: Vec<Pubkey>,

Expand All @@ -141,6 +141,33 @@ pub struct Message {

/// Programs that will be executed in sequence and committed in one atomic transaction if all
/// succeed.
#[serde(with = "short_vec")]
pub instructions: Vec<CompiledInstruction>,
}

/// wasm-bindgen version of the Message struct.
/// This duplication is required until https://github.com/rustwasm/wasm-bindgen/issues/3671
/// is fixed. This must not diverge from the regular non-wasm Message struct.
#[cfg(target_arch = "wasm32")]
#[wasm_bindgen]
#[cfg_attr(
feature = "frozen-abi",
frozen_abi(digest = "2KnLEqfLcTBQqitE22Pp8JYkaqVVbAkGbCfdeHoyxcAU"),
derive(AbiExample)
)]
#[derive(Serialize, Deserialize, Default, Debug, PartialEq, Eq, Clone)]
#[serde(rename_all = "camelCase")]
pub struct Message {
#[wasm_bindgen(skip)]
pub header: MessageHeader,

#[wasm_bindgen(skip)]
#[serde(with = "short_vec")]
pub account_keys: Vec<Pubkey>,

/// The id of a recent ledger entry.
pub recent_blockhash: Hash,

#[wasm_bindgen(skip)]
#[serde(with = "short_vec")]
pub instructions: Vec<CompiledInstruction>,
Expand Down
6 changes: 4 additions & 2 deletions sdk/program/src/pubkey.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

#![allow(clippy::arithmetic_side_effects)]

#[cfg(target_arch = "wasm32")]
use crate::wasm_bindgen;
#[cfg(test)]
use arbitrary::Arbitrary;
#[cfg(feature = "borsh")]
use borsh::{BorshDeserialize, BorshSchema, BorshSerialize};
use {
crate::{decode_error::DecodeError, hash::hashv, wasm_bindgen},
crate::{decode_error::DecodeError, hash::hashv},
bytemuck::{Pod, Zeroable},
num_derive::{FromPrimitive, ToPrimitive},
std::{
Expand Down Expand Up @@ -68,7 +70,7 @@ impl From<u64> for PubkeyError {
/// [ed25519]: https://ed25519.cr.yp.to/
/// [pdas]: https://solana.com/docs/core/cpi#program-derived-addresses
/// [`Keypair`]: https://docs.rs/solana-sdk/latest/solana_sdk/signer/keypair/struct.Keypair.html
#[wasm_bindgen]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen)]
#[repr(transparent)]
#[cfg_attr(feature = "frozen-abi", derive(AbiExample))]
#[cfg_attr(
Expand Down
4 changes: 3 additions & 1 deletion sdk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ pub use signer::signers;
pub use solana_program::program_stubs;
// These solana_program imports could be *-imported, but that causes a bunch of
// confusing duplication in the docs due to a rustdoc bug. #26211
#[cfg(target_arch = "wasm32")]
pub use solana_program::wasm_bindgen;
pub use solana_program::{
account_info, address_lookup_table, alt_bn128, big_mod_exp, blake3, bpf_loader,
bpf_loader_deprecated, bpf_loader_upgradeable, clock, config, custom_heap_default,
Expand All @@ -51,7 +53,7 @@ pub use solana_program::{
program_memory, program_option, program_pack, rent, sanitize, secp256k1_program,
secp256k1_recover, serde_varint, serialize_utils, short_vec, slot_hashes, slot_history,
stable_layout, stake, stake_history, syscalls, system_instruction, system_program, sysvar,
unchecked_div_by_const, vote, wasm_bindgen,
unchecked_div_by_const, vote,
};
#[allow(deprecated)]
pub use solana_program::{address_lookup_table_account, sdk_ids};
Expand Down
5 changes: 3 additions & 2 deletions sdk/src/signer/keypair.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#![cfg(feature = "full")]

#[cfg(target_arch = "wasm32")]
use wasm_bindgen::prelude::*;
use {
crate::{
derivation_path::DerivationPath,
Expand All @@ -16,11 +18,10 @@ use {
io::{Read, Write},
path::Path,
},
wasm_bindgen::prelude::*,
};

/// A vanilla Ed25519 key pair
#[wasm_bindgen]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen)]
#[derive(Debug)]
pub struct Keypair(ed25519_dalek::Keypair);

Expand Down
25 changes: 22 additions & 3 deletions sdk/src/transaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@

#![cfg(feature = "full")]

#[cfg(target_arch = "wasm32")]
use crate::wasm_bindgen;
use {
crate::{
hash::Hash,
Expand All @@ -124,7 +126,6 @@ use {
short_vec,
signature::{Signature, SignerError},
signers::Signers,
wasm_bindgen,
},
serde::Serialize,
solana_program::{system_instruction::SystemInstruction, system_program},
Expand Down Expand Up @@ -167,7 +168,7 @@ pub type Result<T> = result::Result<T, TransactionError>;
/// if the caller has knowledge that the first account of the constructed
/// transaction's `Message` is both a signer and the expected fee-payer, then
/// redundantly specifying the fee-payer is not strictly required.
#[wasm_bindgen]
#[cfg(not(target_arch = "wasm32"))]
#[cfg_attr(
feature = "frozen-abi",
derive(AbiExample),
Expand All @@ -184,11 +185,29 @@ pub struct Transaction {
/// [`MessageHeader`]: crate::message::MessageHeader
/// [`num_required_signatures`]: crate::message::MessageHeader::num_required_signatures
// NOTE: Serialization-related changes must be paired with the direct read at sigverify.
#[wasm_bindgen(skip)]
#[serde(with = "short_vec")]
pub signatures: Vec<Signature>,

/// The message to sign.
pub message: Message,
}

/// wasm-bindgen version of the Transaction struct.
/// This duplication is required until https://github.com/rustwasm/wasm-bindgen/issues/3671
/// is fixed. This must not diverge from the regular non-wasm Transaction struct.
#[cfg(target_arch = "wasm32")]
#[wasm_bindgen]
#[cfg_attr(
feature = "frozen-abi",
derive(AbiExample),
frozen_abi(digest = "FZtncnS1Xk8ghHfKiXE5oGiUbw2wJhmfXQuNgQR3K6Mc")
)]
#[derive(Debug, PartialEq, Default, Eq, Clone, Serialize, Deserialize)]
pub struct Transaction {
#[wasm_bindgen(skip)]
#[serde(with = "short_vec")]
pub signatures: Vec<Signature>,

#[wasm_bindgen(skip)]
pub message: Message,
}
Expand Down

0 comments on commit 25ec304

Please sign in to comment.