Skip to content

Commit

Permalink
extract solana-bincode crate (anza-xyz#3020)
Browse files Browse the repository at this point in the history
* extract limited-deserialize crate

* rename solana-limited-deserialize to solana-bincode
  • Loading branch information
kevinheavey authored and ray-kast committed Nov 27, 2024
1 parent f69db79 commit c841899
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 48 deletions.
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ members = [
"sdk/account",
"sdk/account-info",
"sdk/atomic-u64",
"sdk/bincode",
"sdk/cargo-build-sbf",
"sdk/cargo-test-sbf",
"sdk/clock",
Expand Down Expand Up @@ -375,6 +376,7 @@ solana-banks-client = { path = "banks-client", version = "=2.1.0" }
solana-banks-interface = { path = "banks-interface", version = "=2.1.0" }
solana-banks-server = { path = "banks-server", version = "=2.1.0" }
solana-bench-tps = { path = "bench-tps", version = "=2.1.0" }
solana-bincode = { path = "sdk/bincode", version = "=2.1.0" }
solana-bloom = { path = "bloom", version = "=2.1.0" }
solana-bn254 = { path = "curves/bn254", version = "=2.1.0" }
solana-bpf-loader-program = { path = "programs/bpf_loader", version = "=2.1.0" }
Expand Down
10 changes: 10 additions & 0 deletions programs/sbf/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 26 additions & 0 deletions sdk/bincode/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[package]
name = "solana-bincode"
description = "Solana bincode utilities"
documentation = "https://docs.rs/solana-bincode"
version = { workspace = true }
authors = { workspace = true }
repository = { workspace = true }
homepage = { workspace = true }
license = { workspace = true }
edition = { workspace = true }

[dependencies]
bincode = { workspace = true }
serde = { workspace = true }
solana-instruction = { workspace = true, default-features = false, features = [
"std",
] }

[dev-dependencies]
solana-program = { path = "../program" }

[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

[lints]
workspace = true
48 changes: 48 additions & 0 deletions sdk/bincode/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//! Contains a single utility function for deserializing from [bincode].
//!
//! [bincode]: https://docs.rs/bincode
use {bincode::config::Options, solana_instruction::error::InstructionError};

/// Deserialize with a limit based the maximum amount of data a program can expect to get.
/// This function should be used in place of direct deserialization to help prevent OOM errors
pub fn limited_deserialize<T>(instruction_data: &[u8], limit: u64) -> Result<T, InstructionError>
where
T: serde::de::DeserializeOwned,
{
bincode::options()
.with_limit(limit)
.with_fixint_encoding() // As per https://github.com/servo/bincode/issues/333, these two options are needed
.allow_trailing_bytes() // to retain the behavior of bincode::deserialize with the new `options()` method
.deserialize_from(instruction_data)
.map_err(|_| InstructionError::InvalidInstructionData)
}

#[cfg(test)]
pub mod tests {
use {super::*, solana_program::system_instruction::SystemInstruction};

#[test]
fn test_limited_deserialize_advance_nonce_account() {
let item = SystemInstruction::AdvanceNonceAccount;
let mut serialized = bincode::serialize(&item).unwrap();

assert_eq!(
serialized.len(),
4,
"`SanitizedMessage::get_durable_nonce()` may need a change"
);

assert_eq!(
limited_deserialize::<SystemInstruction>(&serialized, 4).as_ref(),
Ok(&item)
);
assert!(limited_deserialize::<SystemInstruction>(&serialized, 3).is_err());

serialized.push(0);
assert_eq!(
limited_deserialize::<SystemInstruction>(&serialized, 4).as_ref(),
Ok(&item)
);
}
}
1 change: 1 addition & 0 deletions sdk/program/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ sha2 = { workspace = true }
sha3 = { workspace = true }
solana-account-info = { workspace = true, features = ["bincode"] }
solana-atomic-u64 = { workspace = true }
solana-bincode = { workspace = true }
solana-clock = { workspace = true, features = ["serde"] }
solana-decode-error = { workspace = true }
solana-frozen-abi = { workspace = true, optional = true, features = ["frozen-abi"] }
Expand Down
49 changes: 1 addition & 48 deletions sdk/program/src/program_utils.rs
Original file line number Diff line number Diff line change
@@ -1,48 +1 @@
//! Contains a single utility function for deserializing from [bincode].
//!
//! [bincode]: https://docs.rs/bincode
use {crate::instruction::InstructionError, bincode::config::Options};

/// Deserialize with a limit based the maximum amount of data a program can expect to get.
/// This function should be used in place of direct deserialization to help prevent OOM errors
pub fn limited_deserialize<T>(instruction_data: &[u8], limit: u64) -> Result<T, InstructionError>
where
T: serde::de::DeserializeOwned,
{
bincode::options()
.with_limit(limit)
.with_fixint_encoding() // As per https://github.com/servo/bincode/issues/333, these two options are needed
.allow_trailing_bytes() // to retain the behavior of bincode::deserialize with the new `options()` method
.deserialize_from(instruction_data)
.map_err(|_| InstructionError::InvalidInstructionData)
}

#[cfg(test)]
pub mod tests {
use {super::*, solana_program::system_instruction::SystemInstruction};

#[test]
fn test_limited_deserialize_advance_nonce_account() {
let item = SystemInstruction::AdvanceNonceAccount;
let mut serialized = bincode::serialize(&item).unwrap();

assert_eq!(
serialized.len(),
4,
"`SanitizedMessage::get_durable_nonce()` may need a change"
);

assert_eq!(
limited_deserialize::<SystemInstruction>(&serialized, 4).as_ref(),
Ok(&item)
);
assert!(limited_deserialize::<SystemInstruction>(&serialized, 3).is_err());

serialized.push(0);
assert_eq!(
limited_deserialize::<SystemInstruction>(&serialized, 4).as_ref(),
Ok(&item)
);
}
}
pub use solana_bincode::limited_deserialize;

0 comments on commit c841899

Please sign in to comment.