Skip to content

Commit 9deb630

Browse files
authored
Merge pull request #14 from rustopian/master
sync
2 parents 24212c9 + c654e5f commit 9deb630

File tree

16 files changed

+282
-42
lines changed

16 files changed

+282
-42
lines changed

.github/actions/setup/action.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ inputs:
2828
miri:
2929
description: Install Miri if `true`. Defaults to `false`.
3030
required: false
31+
rust-src:
32+
description: Install rust-src if `true`. Defaults to `false`.
33+
required: false
3134
llvm-tools-preview:
3235
description: Install llvm-tools-preview if `true`. Defaults to `false`.
3336
required: false
@@ -118,6 +121,13 @@ runs:
118121
toolchain: ${{ env.RUST_NIGHTLY }}
119122
components: llvm-tools-preview
120123

124+
- name: Install rust-src
125+
if: ${{ inputs.rust-src == 'true' }}
126+
uses: dtolnay/rust-toolchain@master
127+
with:
128+
toolchain: ${{ env.RUST_NIGHTLY }}
129+
components: rust-src
130+
121131
- name: Install Agave build dependencies
122132
if: ${{ inputs.agave == 'true' }}
123133
shell: bash

.github/workflows/main.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,3 +551,22 @@ jobs:
551551

552552
- name: Run benches
553553
run: ./scripts/test-bench.sh
554+
555+
check-no-std:
556+
name: Check no_std build
557+
runs-on: ubuntu-latest
558+
needs: [sanity]
559+
steps:
560+
- name: Git Checkout
561+
uses: actions/checkout@v4
562+
563+
- name: Setup Environment
564+
uses: ./.github/actions/setup
565+
with:
566+
nightly-toolchain: true
567+
rust-src: true
568+
cargo-cache-key: cargo-nightly-no-std
569+
cargo-cache-fallback-key: cargo-nightly
570+
571+
- name: Run check
572+
run: ./scripts/check-no-std.sh

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

account/src/lib.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,22 @@ impl AccountSharedData {
712712
pub fn serialize_data<T: serde::Serialize>(&mut self, state: &T) -> Result<(), bincode::Error> {
713713
shared_serialize_data(self, state)
714714
}
715+
716+
pub fn create_from_existing_shared_data(
717+
lamports: u64,
718+
data: Arc<Vec<u8>>,
719+
owner: Pubkey,
720+
executable: bool,
721+
rent_epoch: Epoch,
722+
) -> AccountSharedData {
723+
AccountSharedData {
724+
lamports,
725+
data,
726+
owner,
727+
executable,
728+
rent_epoch,
729+
}
730+
}
715731
}
716732

717733
pub type InheritableAccountFields = (u64, Epoch);

commitment-config/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//! Definitions of commitment levels.
2-
2+
#![no_std]
33
use core::{fmt, str::FromStr};
44

55
#[cfg_attr(
@@ -110,8 +110,8 @@ impl FromStr for CommitmentLevel {
110110
}
111111
}
112112

113-
impl std::fmt::Display for CommitmentLevel {
114-
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
113+
impl fmt::Display for CommitmentLevel {
114+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
115115
let s = match self {
116116
CommitmentLevel::Processed => "processed",
117117
CommitmentLevel::Confirmed => "confirmed",

scripts/check-no-std.sh

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#!/usr/bin/env bash
2+
3+
set -eo pipefail
4+
5+
here="$(dirname "$0")"
6+
src_root="$(readlink -f "${here}/..")"
7+
8+
cd "${src_root}"
9+
10+
no_std_crates=(
11+
-p solana-address
12+
-p solana-clock
13+
-p solana-commitment-config
14+
-p solana-define-syscall
15+
-p solana-fee-calculator
16+
-p solana-program-error
17+
-p solana-program-memory
18+
-p solana-rent
19+
-p solana-sanitize
20+
-p solana-signature
21+
)
22+
# Use the upstream BPF target, which doesn't support std, to make sure that our
23+
# no_std support really works.
24+
target="bpfel-unknown-none"
25+
26+
./cargo nightly check -Zbuild-std=core \
27+
"--target=$target" \
28+
--no-default-features \
29+
"${no_std_crates[@]}"

sdk-wasm-js/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ solana-hash = { workspace = true }
2424
solana-instruction = { workspace = true, features = ["std"] }
2525
solana-keypair = { workspace = true }
2626
solana-message = { workspace = true }
27+
solana-packet = { workspace = true }
2728
solana-signature = { workspace = true }
2829
solana-signer = { workspace = true }
2930
solana-transaction = { workspace = true, features = ["bincode", "verify"] }

sdk-wasm-js/src/address.rs

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use {
44
crate::display_to_jsvalue,
55
js_sys::{Array, Uint8Array},
6+
solana_address::{ADDRESS_BYTES, MAX_SEEDS, MAX_SEED_LEN},
67
wasm_bindgen::{prelude::wasm_bindgen, JsCast, JsValue},
78
};
89

@@ -15,20 +16,33 @@ pub struct Address {
1516
crate::conversion::impl_inner_conversion!(Address, solana_address::Address);
1617

1718
fn js_value_to_seeds_vec(array_of_uint8_arrays: &[JsValue]) -> Result<Vec<Vec<u8>>, JsValue> {
18-
let vec_vec_u8 = array_of_uint8_arrays
19+
if array_of_uint8_arrays.len() > MAX_SEEDS {
20+
return Err(JsValue::from(std::format!(
21+
"Too many seeds: {} > {}",
22+
array_of_uint8_arrays.len(),
23+
MAX_SEEDS
24+
)));
25+
}
26+
27+
array_of_uint8_arrays
1928
.iter()
20-
.filter_map(|u8_array| {
21-
u8_array
29+
.enumerate()
30+
.map(|(i, u8_array_js)| {
31+
let u8_array = u8_array_js
2232
.dyn_ref::<Uint8Array>()
23-
.map(|u8_array| u8_array.to_vec())
24-
})
25-
.collect::<Vec<_>>();
33+
.ok_or_else(|| JsValue::from(std::format!("Invalid seed type at index {}", i)))?;
34+
if u8_array.length() as usize > MAX_SEED_LEN {
35+
return Err(JsValue::from(std::format!(
36+
"Seed {} too long: {} > {}",
37+
i,
38+
u8_array.length(),
39+
MAX_SEED_LEN
40+
)));
41+
}
2642

27-
if vec_vec_u8.len() != array_of_uint8_arrays.len() {
28-
Err("Invalid Array of Uint8Arrays".into())
29-
} else {
30-
Ok(vec_vec_u8)
31-
}
43+
Ok(u8_array.to_vec())
44+
})
45+
.collect::<Result<Vec<_>, _>>()
3246
}
3347

3448
#[allow(non_snake_case)]
@@ -45,26 +59,40 @@ impl Address {
4559
.map(Into::into)
4660
.map_err(display_to_jsvalue)
4761
} else if let Some(uint8_array) = value.dyn_ref::<Uint8Array>() {
48-
solana_address::Address::try_from(uint8_array.to_vec())
49-
.map(Into::into)
50-
.map_err(|err| JsValue::from(std::format!("Invalid Uint8Array address: {err:?}")))
62+
if uint8_array.length() as usize != ADDRESS_BYTES {
63+
return Err(std::format!(
64+
"Invalid Uint8Array length: expected {}, got {}",
65+
ADDRESS_BYTES,
66+
uint8_array.length()
67+
)
68+
.into());
69+
}
70+
let mut bytes = [0u8; ADDRESS_BYTES];
71+
uint8_array.copy_to(&mut bytes);
72+
Ok(solana_address::Address::new_from_array(bytes).into())
5173
} else if let Some(array) = value.dyn_ref::<Array>() {
52-
let mut bytes = std::vec![];
74+
if array.length() as usize != ADDRESS_BYTES {
75+
return Err(std::format!(
76+
"Invalid Array length: expected {}, got {}",
77+
ADDRESS_BYTES,
78+
array.length()
79+
)
80+
.into());
81+
}
82+
let mut bytes = [0u8; ADDRESS_BYTES];
5383
let iterator = js_sys::try_iter(&array.values())?.expect("array to be iterable");
54-
for x in iterator {
84+
for (i, x) in iterator.enumerate() {
5585
let x = x?;
5686

5787
if let Some(n) = x.as_f64() {
5888
if n >= 0. && n <= 255. {
59-
bytes.push(n as u8);
89+
bytes[i] = n as u8;
6090
continue;
6191
}
6292
}
6393
return Err(std::format!("Invalid array argument: {:?}", x).into());
6494
}
65-
solana_address::Address::try_from(bytes)
66-
.map(Into::into)
67-
.map_err(|err| JsValue::from(std::format!("Invalid Array address: {err:?}")))
95+
Ok(solana_address::Address::new_from_array(bytes).into())
6896
} else if value.is_undefined() {
6997
Ok(solana_address::Address::default().into())
7098
} else {

sdk-wasm-js/src/hash.rs

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
//! Wrapper over `solana_hash::Hash` with wasm-bindgen
22
use {
33
js_sys::{Array, Uint8Array},
4-
std::{boxed::Box, format, string::String, vec},
4+
solana_hash::HASH_BYTES,
5+
std::{boxed::Box, format, string::String},
56
wasm_bindgen::{prelude::*, JsCast},
67
};
78

@@ -27,28 +28,41 @@ impl Hash {
2728
.map(Into::into)
2829
.map_err(|x| JsValue::from(x.to_string()))
2930
} else if let Some(uint8_array) = value.dyn_ref::<Uint8Array>() {
30-
<[u8; solana_hash::HASH_BYTES]>::try_from(uint8_array.to_vec())
31-
.map(solana_hash::Hash::new_from_array)
32-
.map(Into::into)
33-
.map_err(|err| format!("Invalid Hash value: {err:?}").into())
31+
if uint8_array.length() as usize != HASH_BYTES {
32+
return Err(format!(
33+
"Invalid Uint8Array length: expected {}, got {}",
34+
HASH_BYTES,
35+
uint8_array.length()
36+
)
37+
.into());
38+
}
39+
let mut bytes = [0u8; HASH_BYTES];
40+
uint8_array.copy_to(&mut bytes);
41+
Ok(solana_hash::Hash::new_from_array(bytes).into())
3442
} else if let Some(array) = value.dyn_ref::<Array>() {
35-
let mut bytes = vec![];
43+
if array.length() as usize != HASH_BYTES {
44+
return Err(format!(
45+
"Invalid Array length: expected {}, got {}",
46+
HASH_BYTES,
47+
array.length()
48+
)
49+
.into());
50+
}
51+
52+
let mut bytes = [0u8; HASH_BYTES];
3653
let iterator = js_sys::try_iter(&array.values())?.expect("array to be iterable");
37-
for x in iterator {
54+
for (i, x) in iterator.enumerate() {
3855
let x = x?;
3956

4057
if let Some(n) = x.as_f64() {
4158
if n >= 0. && n <= 255. {
42-
bytes.push(n as u8);
59+
bytes[i] = n as u8;
4360
continue;
4461
}
4562
}
4663
return Err(format!("Invalid array argument: {:?}", x).into());
4764
}
48-
<[u8; solana_hash::HASH_BYTES]>::try_from(bytes)
49-
.map(solana_hash::Hash::new_from_array)
50-
.map(Into::into)
51-
.map_err(|err| format!("Invalid Hash value: {err:?}").into())
65+
Ok(solana_hash::Hash::new_from_array(bytes).into())
5266
} else if value.is_undefined() {
5367
Ok(solana_hash::Hash::default().into())
5468
} else {

sdk-wasm-js/src/instruction.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@
33
//! (ref: https://github.com/rustwasm/wasm-bindgen/issues/111)
44
#![allow(non_snake_case)]
55

6-
use {crate::address::Address, wasm_bindgen::prelude::*};
6+
use {
7+
crate::address::Address, js_sys::Uint8Array, solana_packet::PACKET_DATA_SIZE,
8+
wasm_bindgen::prelude::*,
9+
};
10+
11+
const MAX_INSTRUCTION_DATA_LEN: usize = PACKET_DATA_SIZE;
712

813
/// wasm-bindgen version of the Instruction struct.
914
/// This duplication is required until https://github.com/rustwasm/wasm-bindgen/issues/3671
@@ -25,8 +30,18 @@ impl Instruction {
2530
.into()
2631
}
2732

28-
pub fn setData(&mut self, data: &[u8]) {
33+
pub fn setData(&mut self, data: Uint8Array) -> Result<(), JsValue> {
34+
if data.length() as usize > MAX_INSTRUCTION_DATA_LEN {
35+
return Err(std::format!(
36+
"Instruction data too large: {} > {}",
37+
data.length(),
38+
MAX_INSTRUCTION_DATA_LEN
39+
)
40+
.into());
41+
}
42+
2943
self.inner.data = data.to_vec();
44+
Ok(())
3045
}
3146

3247
pub fn addAccount(&mut self, account_meta: AccountMeta) {

0 commit comments

Comments
 (0)