diff --git a/Cargo.lock b/Cargo.lock index 5b3311fdd..fac3bf1f8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3041,6 +3041,7 @@ dependencies = [ name = "solana-frozen-abi" version = "3.1.0" dependencies = [ + "bincode", "bitflags 2.8.0", "boxcar", "bs58", @@ -3051,6 +3052,7 @@ dependencies = [ "log", "memmap2", "rand", + "rand_chacha", "serde", "serde_bytes", "serde_derive", diff --git a/frozen-abi-macro/src/lib.rs b/frozen-abi-macro/src/lib.rs index 8e2d70009..d82830116 100644 --- a/frozen-abi-macro/src/lib.rs +++ b/frozen-abi-macro/src/lib.rs @@ -345,9 +345,9 @@ fn quote_for_test( quote! { #[test] fn test_abi_digest() { - use ::rand::{SeedableRng, RngCore}; - use ::rand_chacha::ChaCha8Rng; - use ::bincode; + use ::solana_frozen_abi::rand::{SeedableRng, RngCore}; + use ::solana_frozen_abi::rand_chacha::ChaCha8Rng; + use ::solana_frozen_abi::bincode; use ::solana_frozen_abi::stable_abi::StableAbi; let mut rng = ChaCha8Rng::seed_from_u64(20666175621446498); diff --git a/frozen-abi/Cargo.toml b/frozen-abi/Cargo.toml index d7dedcddf..7d8e851ac 100644 --- a/frozen-abi/Cargo.toml +++ b/frozen-abi/Cargo.toml @@ -35,9 +35,14 @@ solana-frozen-abi-macro = { workspace = true } thiserror = { workspace = true } [target.'cfg(not(target_os = "solana"))'.dependencies] +# This dependency is used only to back `frozen-abi` StableAbi API +bincode = "1.3.3" im = { workspace = true, features = ["rayon", "serde"] } memmap2 = { workspace = true } -rand = { workspace = true } +# These dependencies are used only to back `frozen-abi` StableAbi API, +# to avoid version skew and keep digest computation stable regardless of consumer dependencies. +rand = "0.8.5" +rand_chacha = "0.3.1" [target.'cfg(not(target_os = "solana"))'.dev-dependencies] bitflags = { workspace = true, features = ["serde"] } diff --git a/frozen-abi/src/lib.rs b/frozen-abi/src/lib.rs index 43037ac51..ecc18fd76 100644 --- a/frozen-abi/src/lib.rs +++ b/frozen-abi/src/lib.rs @@ -19,6 +19,16 @@ pub mod stable_abi; #[macro_use] extern crate solana_frozen_abi_macro; +#[cfg(feature = "frozen-abi")] +#[cfg(not(target_os = "solana"))] +pub use bincode; +#[cfg(feature = "frozen-abi")] +#[cfg(not(target_os = "solana"))] +pub use rand; +#[cfg(feature = "frozen-abi")] +#[cfg(not(target_os = "solana"))] +pub use rand_chacha; + // Not public API. Previously referenced by macro-generated code. Remove the // `log` dependency from Cargo.toml when this is cleaned up in the next major // version bump diff --git a/frozen-abi/src/stable_abi.rs b/frozen-abi/src/stable_abi.rs index e479f629a..475ae86a3 100644 --- a/frozen-abi/src/stable_abi.rs +++ b/frozen-abi/src/stable_abi.rs @@ -5,6 +5,6 @@ pub trait StableAbi: Sized { where Standard: rand::distributions::Distribution, { - rng.gen::() + rng.r#gen::() } } diff --git a/scripts/test-frozen-abi.sh b/scripts/test-frozen-abi.sh index 0fa7f4f62..12431017a 100755 --- a/scripts/test-frozen-abi.sh +++ b/scripts/test-frozen-abi.sh @@ -5,5 +5,5 @@ here="$(dirname "$0")" src_root="$(readlink -f "${here}/..")" cd "${src_root}" -./cargo nightly hack --features frozen-abi --ignore-unknown-features test --lib -- test_abi_digest --nocapture -./cargo nightly hack --features frozen-abi --ignore-unknown-features test --lib -- test_api_digest --nocapture +./cargo nightly test --features frozen-abi --lib -- test_abi_digest --nocapture +./cargo nightly test --features frozen-abi --lib -- test_api_digest --nocapture diff --git a/transaction/src/lib.rs b/transaction/src/lib.rs index c27f28680..e988680e1 100644 --- a/transaction/src/lib.rs +++ b/transaction/src/lib.rs @@ -110,6 +110,9 @@ //! # Ok::<(), anyhow::Error>(()) //! ``` +#[cfg(feature = "frozen-abi")] +use solana_frozen_abi_macro::{frozen_abi, AbiExample, StableAbi}; + #[cfg(feature = "serde")] use { serde_derive::{Deserialize, Serialize}, @@ -176,8 +179,11 @@ const NONCED_TX_MARKER_IX_INDEX: u8 = 0; /// redundantly specifying the fee-payer is not strictly required. #[cfg_attr( feature = "frozen-abi", - derive(solana_frozen_abi_macro::AbiExample), - solana_frozen_abi_macro::frozen_abi(digest = "BLig4G2ysd7dcensK9bhKtnKvCQc1n65XdanyzsdWGXN") + derive(AbiExample, StableAbi), + frozen_abi( + api_digest = "BLig4G2ysd7dcensK9bhKtnKvCQc1n65XdanyzsdWGXN", + abi_digest = "BrQZ2jZhf9FDME3M3yNdhDBga8bHuLiAwWvZRvGwFrGh" + ) )] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] #[derive(Debug, PartialEq, Default, Eq, Clone)] @@ -198,6 +204,37 @@ pub struct Transaction { pub message: Message, } +#[cfg(feature = "frozen-abi")] +impl solana_frozen_abi::rand::prelude::Distribution + for solana_frozen_abi::rand::distributions::Standard +{ + fn sample(&self, rng: &mut R) -> Transaction { + let signatures: Vec = (0..rng.r#gen_range(1..100)) + .map(|_| Signature::from(std::array::from_fn(|_| rng.r#gen::()))) + .collect(); + let accounts: Vec = (0..rng.r#gen_range(1..100)) + .map(|_| AccountMeta { + pubkey: Address::new_from_array(rng.r#gen()), + is_signer: rng.r#gen(), + is_writable: rng.r#gen(), + }) + .collect(); + let data: Vec = (0..rng.r#gen_range(1..1000)).map(|_| rng.r#gen()).collect(); + let instructions: Vec = (0..rng.r#gen_range(1..100)) + .map(|_| Instruction { + program_id: Address::new_from_array(rng.r#gen()), + accounts: accounts.clone(), + data: data.clone(), + }) + .collect(); + + Transaction { + signatures, + message: Message::new(&instructions, Some(&Address::new_from_array(rng.r#gen()))), + } + } +} + impl Sanitize for Transaction { fn sanitize(&self) -> result::Result<(), SanitizeError> { if self.message.header.num_required_signatures as usize > self.signatures.len() {