Skip to content

Commit fdeae1b

Browse files
authored
Use ruzstd to decompress bytecodes in Wasm (#2421)
* Fix name of `DecompressionError` It was incorrectly named `CompressionError`. * Use `ruzstd` to decompress in Wasm Allow decompressing bytecodes when running in `wasm32-unknown-unknown`.
1 parent 11e6b4e commit fdeae1b

File tree

6 files changed

+72
-8
lines changed

6 files changed

+72
-8
lines changed

Cargo.lock

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ quote = "1.0"
108108
rand = { version = "0.8.5", default-features = false }
109109
rand_chacha = { version = "0.3.1", default-features = false }
110110
rand_distr = { version = "0.4.3", default-features = false }
111+
ruzstd = "0.7.1"
111112
k8s-openapi = { version = "0.21.1", features = ["v1_28"] }
112113
pathdiff = "0.2.1"
113114
kube = "0.88.1"

examples/Cargo.lock

+21
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

linera-base/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ tracing-subscriber = { workspace = true, features = ["json", "fmt", "ansi"] }
5656
wasm-bindgen-futures = { workspace = true, optional = true }
5757
web-time = { workspace = true, optional = true }
5858

59+
[target.'cfg(target_arch = "wasm32")'.dependencies]
60+
ruzstd.workspace = true
61+
5962
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
6063
chrono.workspace = true
6164
rand = { workspace = true, features = ["getrandom", "std", "std_rng"] }

linera-base/src/data_types.rs

+34-6
Original file line numberDiff line numberDiff line change
@@ -839,12 +839,18 @@ impl fmt::Debug for Bytecode {
839839
}
840840
}
841841

842-
/// A type for errors happening during compression.
842+
/// A type for errors happening during decompression.
843843
#[derive(Error, Debug)]
844-
pub enum CompressionError {
844+
pub enum DecompressionError {
845845
/// Compressed bytecode is invalid, and could not be decompressed.
846+
#[cfg(not(target_arch = "wasm32"))]
846847
#[error("Bytecode could not be decompressed")]
847848
InvalidCompressedBytecode(#[source] io::Error),
849+
850+
/// Compressed bytecode is invalid, and could not be decompressed.
851+
#[cfg(target_arch = "wasm32")]
852+
#[error("Bytecode could not be decompressed")]
853+
InvalidCompressedBytecode(#[from] ruzstd::frame_decoder::FrameDecoderError),
848854
}
849855

850856
/// A compressed WebAssembly module's bytecode.
@@ -874,19 +880,41 @@ impl From<Bytecode> for CompressedBytecode {
874880

875881
#[cfg(not(target_arch = "wasm32"))]
876882
impl TryFrom<&CompressedBytecode> for Bytecode {
877-
type Error = CompressionError;
883+
type Error = DecompressionError;
878884

879885
fn try_from(compressed_bytecode: &CompressedBytecode) -> Result<Self, Self::Error> {
880886
let bytes = zstd::stream::decode_all(&*compressed_bytecode.compressed_bytes)
881-
.map_err(CompressionError::InvalidCompressedBytecode)?;
887+
.map_err(DecompressionError::InvalidCompressedBytecode)?;
888+
889+
Ok(Bytecode { bytes })
890+
}
891+
}
892+
893+
#[cfg(target_arch = "wasm32")]
894+
impl TryFrom<&CompressedBytecode> for Bytecode {
895+
type Error = DecompressionError;
896+
897+
fn try_from(compressed_bytecode: &CompressedBytecode) -> Result<Self, Self::Error> {
898+
use ruzstd::{io::Read, streaming_decoder::StreamingDecoder};
899+
900+
let compressed_bytes = &*compressed_bytecode.compressed_bytes;
901+
let mut bytes = Vec::new();
902+
let mut decoder = StreamingDecoder::new(compressed_bytes)?;
903+
904+
// Decode multiple frames, if present
905+
// (https://github.com/KillingSpark/zstd-rs/issues/57)
906+
while !decoder.get_ref().is_empty() {
907+
decoder
908+
.read_to_end(&mut bytes)
909+
.expect("Reading from a slice in memory should not result in IO errors");
910+
}
882911

883912
Ok(Bytecode { bytes })
884913
}
885914
}
886915

887-
#[cfg(not(target_arch = "wasm32"))]
888916
impl TryFrom<CompressedBytecode> for Bytecode {
889-
type Error = CompressionError;
917+
type Error = DecompressionError;
890918

891919
fn try_from(compressed_bytecode: CompressedBytecode) -> Result<Self, Self::Error> {
892920
Bytecode::try_from(&compressed_bytecode)

linera-execution/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ use linera_base::{
3333
abi::Abi,
3434
crypto::CryptoHash,
3535
data_types::{
36-
Amount, ApplicationPermissions, ArithmeticError, Blob, BlockHeight, CompressionError,
36+
Amount, ApplicationPermissions, ArithmeticError, Blob, BlockHeight, DecompressionError,
3737
Resources, SendMessageRequest, Timestamp, UserApplicationDescription,
3838
},
3939
doc_scalar, hex_debug,
@@ -125,7 +125,7 @@ pub enum ExecutionError {
125125
#[error(transparent)]
126126
JoinError(#[from] linera_base::task::Error),
127127
#[error(transparent)]
128-
CompressionError(#[from] CompressionError),
128+
DecompressionError(#[from] DecompressionError),
129129
#[error("The given promise is invalid or was polled once already")]
130130
InvalidPromise,
131131

0 commit comments

Comments
 (0)