Skip to content

Commit 8395f54

Browse files
committed
Add VM sections module
Move encode_sections() to own module
1 parent 96430c8 commit 8395f54

File tree

3 files changed

+73
-115
lines changed

3 files changed

+73
-115
lines changed

packages/vm/src/imports.rs

Lines changed: 2 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ use crate::errors::{CommunicationError, VmError, VmResult};
1818
#[cfg(feature = "iterator")]
1919
use crate::memory::maybe_read_region;
2020
use crate::memory::{read_region, write_region};
21+
#[cfg(target_arch = "wasm32")]
22+
use crate::sections::encode_sections;
2123
use crate::serde::to_vec;
2224
use crate::GasInfo;
2325

@@ -424,53 +426,6 @@ fn do_next<A: BackendApi, S: Storage, Q: Querier>(
424426
write_to_contract::<A, S, Q>(env, &out_data)
425427
}
426428

427-
/// Encodes multiple sections of data into one vector.
428-
///
429-
/// Each section is suffixed by a section length encoded as big endian uint32.
430-
/// Using suffixes instead of prefixes allows reading sections in reverse order,
431-
/// such that the first element does not need to be re-allocated if the contract's
432-
/// data structure supports truncation (such as a Rust vector).
433-
///
434-
/// The resulting data looks like this:
435-
///
436-
/// ```ignore
437-
/// section1 || section1_len || section2 || section2_len || section3 || section3_len || …
438-
/// ```
439-
#[allow(dead_code)]
440-
fn encode_sections(sections: &[Vec<u8>]) -> VmResult<Vec<u8>> {
441-
let mut out_len: usize = sections.iter().map(|section| section.len()).sum();
442-
out_len += 4 * sections.len();
443-
let mut out_data = Vec::with_capacity(out_len);
444-
for section in sections {
445-
let section_len = to_u32(section.len())?.to_be_bytes();
446-
out_data.extend(section);
447-
out_data.extend_from_slice(&section_len);
448-
}
449-
debug_assert_eq!(out_data.len(), out_len);
450-
debug_assert_eq!(out_data.capacity(), out_len);
451-
Ok(out_data)
452-
}
453-
454-
/// Returns the data shifted by 32 bits towards the most significant bit.
455-
///
456-
/// This is independent of endianness. But to get the idea, it would be
457-
/// `data || 0x00000000` in big endian representation.
458-
#[inline]
459-
fn to_high_half(data: u32) -> u64 {
460-
// See https://stackoverflow.com/a/58956419/2013738 to understand
461-
// why this is endianness agnostic.
462-
(data as u64) << 32
463-
}
464-
465-
/// Returns the data copied to the 4 least significant bytes.
466-
///
467-
/// This is independent of endianness. But to get the idea, it would be
468-
/// `0x00000000 || data` in big endian representation.
469-
#[inline]
470-
fn to_low_half(data: u32) -> u64 {
471-
data.into()
472-
}
473-
474429
#[cfg(test)]
475430
mod tests {
476431
use super::*;
@@ -1854,72 +1809,4 @@ mod tests {
18541809
e => panic!("Unexpected error: {:?}", e),
18551810
}
18561811
}
1857-
1858-
#[test]
1859-
fn encode_sections_works_for_empty_sections() {
1860-
let enc = encode_sections(&[]).unwrap();
1861-
assert_eq!(enc, b"" as &[u8]);
1862-
let enc = encode_sections(&[vec![]]).unwrap();
1863-
assert_eq!(enc, b"\0\0\0\0" as &[u8]);
1864-
let enc = encode_sections(&[vec![], vec![]]).unwrap();
1865-
assert_eq!(enc, b"\0\0\0\0\0\0\0\0" as &[u8]);
1866-
let enc = encode_sections(&[vec![], vec![], vec![]]).unwrap();
1867-
assert_eq!(enc, b"\0\0\0\0\0\0\0\0\0\0\0\0" as &[u8]);
1868-
}
1869-
1870-
#[test]
1871-
fn encode_sections_works_for_one_element() {
1872-
let enc = encode_sections(&[]).unwrap();
1873-
assert_eq!(enc, b"" as &[u8]);
1874-
let enc = encode_sections(&[vec![0xAA]]).unwrap();
1875-
assert_eq!(enc, b"\xAA\0\0\0\x01" as &[u8]);
1876-
let enc = encode_sections(&[vec![0xAA, 0xBB]]).unwrap();
1877-
assert_eq!(enc, b"\xAA\xBB\0\0\0\x02" as &[u8]);
1878-
let enc = encode_sections(&[vec![0x9D; 277]]).unwrap();
1879-
assert_eq!(enc, b"\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\0\0\x01\x15" as &[u8]);
1880-
}
1881-
1882-
#[test]
1883-
fn encode_sections_works_for_multiple_elements() {
1884-
let enc = encode_sections(&[vec![0xAA]]).unwrap();
1885-
assert_eq!(enc, b"\xAA\0\0\0\x01" as &[u8]);
1886-
let enc = encode_sections(&[vec![0xAA], vec![0xDE, 0xDE]]).unwrap();
1887-
assert_eq!(enc, b"\xAA\0\0\0\x01\xDE\xDE\0\0\0\x02" as &[u8]);
1888-
let enc = encode_sections(&[vec![0xAA], vec![0xDE, 0xDE], vec![]]).unwrap();
1889-
assert_eq!(enc, b"\xAA\0\0\0\x01\xDE\xDE\0\0\0\x02\0\0\0\0" as &[u8]);
1890-
let enc = encode_sections(&[vec![0xAA], vec![0xDE, 0xDE], vec![], vec![0xFF; 19]]).unwrap();
1891-
assert_eq!(enc, b"\xAA\0\0\0\x01\xDE\xDE\0\0\0\x02\0\0\0\0\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\0\0\x13" as &[u8]);
1892-
}
1893-
1894-
#[test]
1895-
fn to_high_half_works() {
1896-
assert_eq!(
1897-
to_high_half(0),
1898-
u64::from_be_bytes([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
1899-
);
1900-
assert_eq!(
1901-
to_high_half(1),
1902-
u64::from_be_bytes([0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00])
1903-
);
1904-
assert_eq!(
1905-
to_high_half(u32::from_be_bytes([0x12, 0x34, 0x56, 0x78])),
1906-
u64::from_be_bytes([0x12, 0x34, 0x56, 0x78, 0x00, 0x00, 0x00, 0x00])
1907-
);
1908-
}
1909-
1910-
#[test]
1911-
fn to_low_half_works() {
1912-
assert_eq!(
1913-
to_low_half(0),
1914-
u64::from_be_bytes([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
1915-
);
1916-
assert_eq!(
1917-
to_low_half(1),
1918-
u64::from_be_bytes([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01])
1919-
);
1920-
assert_eq!(
1921-
to_low_half(u32::from_be_bytes([0x12, 0x34, 0x56, 0x78])),
1922-
u64::from_be_bytes([0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x78])
1923-
);
1924-
}
19251812
}

packages/vm/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ mod limited;
1717
mod memory;
1818
mod middleware;
1919
mod modules;
20+
mod sections;
2021
mod serde;
2122
mod size;
2223
mod static_analysis;

packages/vm/src/sections.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
use crate::conversion::to_u32;
2+
use crate::errors::VmResult;
3+
4+
/// Encodes multiple sections of data into one vector.
5+
///
6+
/// Each section is suffixed by a section length encoded as big endian uint32.
7+
/// Using suffixes instead of prefixes allows reading sections in reverse order,
8+
/// such that the first element does not need to be re-allocated if the contract's
9+
/// data structure supports truncation (such as a Rust vector).
10+
///
11+
/// The resulting data looks like this:
12+
///
13+
/// ```ignore
14+
/// section1 || section1_len || section2 || section2_len || section3 || section3_len || …
15+
/// ```
16+
#[allow(dead_code)]
17+
pub fn encode_sections(sections: &[Vec<u8>]) -> VmResult<Vec<u8>> {
18+
let mut out_len: usize = sections.iter().map(|section| section.len()).sum();
19+
out_len += 4 * sections.len();
20+
let mut out_data = Vec::with_capacity(out_len);
21+
for section in sections {
22+
let section_len = to_u32(section.len())?.to_be_bytes();
23+
out_data.extend(section);
24+
out_data.extend_from_slice(&section_len);
25+
}
26+
debug_assert_eq!(out_data.len(), out_len);
27+
debug_assert_eq!(out_data.capacity(), out_len);
28+
Ok(out_data)
29+
}
30+
31+
#[cfg(test)]
32+
mod tests {
33+
use super::*;
34+
35+
#[test]
36+
fn encode_sections_works_for_empty_sections() {
37+
let enc = encode_sections(&[]).unwrap();
38+
assert_eq!(enc, b"" as &[u8]);
39+
let enc = encode_sections(&[vec![]]).unwrap();
40+
assert_eq!(enc, b"\0\0\0\0" as &[u8]);
41+
let enc = encode_sections(&[vec![], vec![]]).unwrap();
42+
assert_eq!(enc, b"\0\0\0\0\0\0\0\0" as &[u8]);
43+
let enc = encode_sections(&[vec![], vec![], vec![]]).unwrap();
44+
assert_eq!(enc, b"\0\0\0\0\0\0\0\0\0\0\0\0" as &[u8]);
45+
}
46+
47+
#[test]
48+
fn encode_sections_works_for_one_element() {
49+
let enc = encode_sections(&[]).unwrap();
50+
assert_eq!(enc, b"" as &[u8]);
51+
let enc = encode_sections(&[vec![0xAA]]).unwrap();
52+
assert_eq!(enc, b"\xAA\0\0\0\x01" as &[u8]);
53+
let enc = encode_sections(&[vec![0xAA, 0xBB]]).unwrap();
54+
assert_eq!(enc, b"\xAA\xBB\0\0\0\x02" as &[u8]);
55+
let enc = encode_sections(&[vec![0x9D; 277]]).unwrap();
56+
assert_eq!(enc, b"\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\0\0\x01\x15" as &[u8]);
57+
}
58+
59+
#[test]
60+
fn encode_sections_works_for_multiple_elements() {
61+
let enc = encode_sections(&[vec![0xAA]]).unwrap();
62+
assert_eq!(enc, b"\xAA\0\0\0\x01" as &[u8]);
63+
let enc = encode_sections(&[vec![0xAA], vec![0xDE, 0xDE]]).unwrap();
64+
assert_eq!(enc, b"\xAA\0\0\0\x01\xDE\xDE\0\0\0\x02" as &[u8]);
65+
let enc = encode_sections(&[vec![0xAA], vec![0xDE, 0xDE], vec![]]).unwrap();
66+
assert_eq!(enc, b"\xAA\0\0\0\x01\xDE\xDE\0\0\0\x02\0\0\0\0" as &[u8]);
67+
let enc = encode_sections(&[vec![0xAA], vec![0xDE, 0xDE], vec![], vec![0xFF; 19]]).unwrap();
68+
assert_eq!(enc, b"\xAA\0\0\0\x01\xDE\xDE\0\0\0\x02\0\0\0\0\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\0\0\x13" as &[u8]);
69+
}
70+
}

0 commit comments

Comments
 (0)