Skip to content

Commit 21d1199

Browse files
authored
feat: no_std support for starknet-core (#428)
Adds a new `std` feature to `starknet-core` that's enabled by default. When disabled, the crate compiles in a `no_std` environment.
1 parent a776122 commit 21d1199

File tree

13 files changed

+90
-42
lines changed

13 files changed

+90
-42
lines changed

.github/workflows/test.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,3 +168,9 @@ jobs:
168168
--target thumbv6m-none-eabi \
169169
--no-default-features \
170170
--features alloc
171+
172+
- name: Build starknet-core
173+
run: |
174+
cargo build --package starknet-core \
175+
--target thumbv6m-none-eabi \
176+
--no-default-features

starknet-core/Cargo.toml

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,16 @@ keywords = ["ethereum", "starknet", "web3"]
1616
all-features = true
1717

1818
[dependencies]
19-
starknet-crypto = { version = "0.5.1", path = "../starknet-crypto" }
20-
starknet-ff = { version = "0.3.4", path = "../starknet-ff", features = [
21-
"serde",
22-
] }
23-
base64 = "0.21.0"
24-
flate2 = "1.0.25"
25-
hex = "0.4.3"
26-
serde = { version = "1.0.160", features = ["derive"] }
19+
starknet-crypto = { version = "0.5.1", path = "../starknet-crypto", default-features = false, features = [ "alloc" ] }
20+
starknet-ff = { version = "0.3.4", path = "../starknet-ff", default-features = false, features = ["serde"] }
21+
base64 = { version = "0.21.0", default-features = false, features = ["alloc"] }
22+
flate2 = { version = "1.0.25", optional = true }
23+
hex = { version = "0.4.3", default-features = false }
24+
serde = { version = "1.0.160", default-features = false, features = ["derive"] }
2725
serde_json = { version = "1.0.96", default-features = false, features = ["alloc", "raw_value"] }
2826
serde_json_pythonic = { version = "0.1.2", default-features = false, features = ["alloc", "raw_value"] }
29-
serde_with = "2.3.2"
30-
sha3 = "0.10.7"
27+
serde_with = { version = "2.3.2", default-features = false, features = ["alloc", "macros"] }
28+
sha3 = { version = "0.10.7", default-features = false }
3129

3230
[dev-dependencies]
3331
criterion = { version = "0.4.0", default-features = false }
@@ -37,7 +35,8 @@ starknet-core = { path = ".", features = ["no_unknown_fields"] }
3735
wasm-bindgen-test = "0.3.34"
3836

3937
[features]
40-
default = ["bigdecimal"]
38+
default = ["std", "bigdecimal"]
39+
std = ["dep:flate2", "starknet-ff/std", "starknet-crypto/std"]
4140
bigdecimal = ["starknet-ff/bigdecimal", "starknet-crypto/bigdecimal"]
4241
no_unknown_fields = []
4342

starknet-core/src/crypto.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use starknet_crypto::{rfc6979_generate_k, sign, verify, SignError, VerifyError};
55

66
mod errors {
77
use core::fmt::{Display, Formatter, Result};
8-
use std::error::Error;
98

109
#[derive(Debug)]
1110
pub enum EcdsaSignError {
@@ -20,7 +19,8 @@ mod errors {
2019
SignatureSOutOfRange,
2120
}
2221

23-
impl Error for EcdsaSignError {}
22+
#[cfg(feature = "std")]
23+
impl std::error::Error for EcdsaSignError {}
2424

2525
impl Display for EcdsaSignError {
2626
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
@@ -30,7 +30,8 @@ mod errors {
3030
}
3131
}
3232

33-
impl Error for EcdsaVerifyError {}
33+
#[cfg(feature = "std")]
34+
impl std::error::Error for EcdsaVerifyError {}
3435

3536
impl Display for EcdsaVerifyError {
3637
fn fmt(&self, f: &mut Formatter<'_>) -> Result {

starknet-core/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#![cfg_attr(not(feature = "std"), no_std)]
12
#![allow(clippy::comparison_chain)]
23
#![doc = include_str!("../README.md")]
34

@@ -10,3 +11,5 @@ pub mod crypto;
1011
pub mod utils;
1112

1213
pub mod chain_id;
14+
15+
extern crate alloc;

starknet-core/src/serde/byte_array.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
pub mod base64 {
2+
use alloc::{format, string::String, vec::Vec};
3+
24
use base64::{engine::general_purpose::STANDARD, Engine};
35
use serde::{Deserialize, Deserializer, Serializer};
46

starknet-core/src/serde/num_hex.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
pub mod u64 {
2+
use alloc::{format, string::String};
3+
24
use serde::{Deserialize, Deserializer, Serializer};
35

46
pub fn serialize<S>(value: &u64, serializer: S) -> Result<S::Ok, S::Error>

starknet-core/src/serde/unsigned_field_element.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use alloc::{format, string::String};
2+
13
use serde::{de::Error as DeError, Deserialize, Deserializer, Serializer};
24
use serde_with::{DeserializeAs, SerializeAs};
35

starknet-core/src/types/codegen.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// https://github.com/xJonathanLEI/starknet-jsonrpc-codegen
44

55
// Code generated with version:
6-
// https://github.com/xJonathanLEI/starknet-jsonrpc-codegen#73397c9d87962949675bca8fdc08faa88aa8ffb4
6+
// https://github.com/xJonathanLEI/starknet-jsonrpc-codegen#5dbdcd62529ab8e3af4e9ef752945f8ae7e85ab9
77

88
// Code generation requested but not implemented for these types:
99
// - `BLOCK_ID`
@@ -18,7 +18,7 @@
1818
// - `TXN`
1919
// - `TXN_RECEIPT`
2020

21-
use std::sync::Arc;
21+
use alloc::{format, string::String, vec::Vec};
2222

2323
use serde::{Deserialize, Deserializer, Serialize, Serializer};
2424
use serde_with::serde_as;
@@ -30,6 +30,11 @@ use crate::{
3030

3131
use super::{serde_impls::NumAsHex, *};
3232

33+
#[cfg(all(not(no_rc), not(no_sync), target_has_atomic = "ptr"))]
34+
pub type OwnedPtr<T> = alloc::sync::Arc<T>;
35+
#[cfg(not(all(not(no_rc), not(no_sync), target_has_atomic = "ptr")))]
36+
pub type OwnedPtr<T> = alloc::boxed::Box<T>;
37+
3338
/// Block status.
3439
///
3540
/// The status of the block.
@@ -127,7 +132,7 @@ pub struct BroadcastedDeclareTransactionV1 {
127132
/// Nonce
128133
pub nonce: FieldElement,
129134
/// The class to be declared
130-
pub contract_class: Arc<CompressedLegacyContractClass>,
135+
pub contract_class: OwnedPtr<CompressedLegacyContractClass>,
131136
/// The address of the account contract sending the declaration transaction
132137
pub sender_address: FieldElement,
133138
}
@@ -144,7 +149,7 @@ pub struct BroadcastedDeclareTransactionV2 {
144149
/// Nonce
145150
pub nonce: FieldElement,
146151
/// The class to be declared
147-
pub contract_class: Arc<FlattenedSierraClass>,
152+
pub contract_class: OwnedPtr<FlattenedSierraClass>,
148153
/// The address of the account contract sending the declaration transaction
149154
pub sender_address: FieldElement,
150155
/// The hash of the cairo assembly resulting from the sierra compilation
@@ -1016,10 +1021,11 @@ pub enum StarknetError {
10161021
ClassAlreadyDeclared,
10171022
}
10181023

1024+
#[cfg(feature = "std")]
10191025
impl std::error::Error for StarknetError {}
10201026

1021-
impl std::fmt::Display for StarknetError {
1022-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1027+
impl core::fmt::Display for StarknetError {
1028+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
10231029
match self {
10241030
Self::FailedToReceiveTransaction => write!(f, "Failed to write transaction"),
10251031
Self::ContractNotFound => write!(f, "Contract not found"),
@@ -1481,7 +1487,7 @@ impl<'de> Deserialize<'de> for BroadcastedDeclareTransactionV1 {
14811487
max_fee: tagged.max_fee,
14821488
signature: tagged.signature,
14831489
nonce: tagged.nonce,
1484-
contract_class: Arc::new(tagged.contract_class),
1490+
contract_class: OwnedPtr::new(tagged.contract_class),
14851491
sender_address: tagged.sender_address,
14861492
})
14871493
}
@@ -1565,7 +1571,7 @@ impl<'de> Deserialize<'de> for BroadcastedDeclareTransactionV2 {
15651571
max_fee: tagged.max_fee,
15661572
signature: tagged.signature,
15671573
nonce: tagged.nonce,
1568-
contract_class: Arc::new(tagged.contract_class),
1574+
contract_class: OwnedPtr::new(tagged.contract_class),
15691575
sender_address: tagged.sender_address,
15701576
compiled_class_hash: tagged.compiled_class_hash,
15711577
})

starknet-core/src/types/contract/legacy.rs

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,28 @@
1+
use alloc::{boxed::Box, collections::BTreeMap, format, string::String, vec::Vec};
2+
13
use crate::{
24
crypto::compute_hash_on_elements,
35
serde::{num_hex::u64 as u64_hex, unsigned_field_element::UfeHex},
46
types::{
5-
contract::{CompressProgramError, ComputeClassHashError, JsonError},
6-
CompressedLegacyContractClass, FieldElement, FunctionStateMutability,
7-
LegacyContractAbiEntry, LegacyContractEntryPoint, LegacyEntryPointsByType,
8-
LegacyEventAbiEntry, LegacyEventAbiType, LegacyFunctionAbiEntry, LegacyFunctionAbiType,
9-
LegacyStructAbiEntry, LegacyStructAbiType, LegacyStructMember, LegacyTypedParameter,
7+
contract::{ComputeClassHashError, JsonError},
8+
FieldElement, FunctionStateMutability, LegacyContractAbiEntry, LegacyContractEntryPoint,
9+
LegacyEntryPointsByType, LegacyEventAbiEntry, LegacyEventAbiType, LegacyFunctionAbiEntry,
10+
LegacyFunctionAbiType, LegacyStructAbiEntry, LegacyStructAbiType, LegacyStructMember,
11+
LegacyTypedParameter,
1012
},
1113
utils::{cairo_short_string_to_felt, starknet_keccak},
1214
};
1315

14-
use flate2::{write::GzEncoder, Compression};
1516
use serde::{
1617
de::Error as DeError, ser::SerializeSeq, Deserialize, Deserializer, Serialize, Serializer,
1718
};
1819
use serde_json_pythonic::to_string_pythonic;
1920
use serde_with::{serde_as, SerializeAs};
20-
use std::{collections::BTreeMap, io::Write};
21+
22+
#[cfg(feature = "std")]
23+
use crate::types::{contract::CompressProgramError, CompressedLegacyContractClass};
24+
#[cfg(feature = "std")]
25+
use flate2::{write::GzEncoder, Compression};
2126

2227
const API_VERSION: FieldElement = FieldElement::ZERO;
2328

@@ -396,13 +401,13 @@ impl<'de> Deserialize<'de> for RawLegacyAbiEntry {
396401

397402
impl LegacyContractClass {
398403
pub fn class_hash(&self) -> Result<FieldElement, ComputeClassHashError> {
399-
let mut elements = vec![];
404+
let mut elements = Vec::new();
400405

401406
elements.push(API_VERSION);
402407

403408
// Hashes external entry points
404409
elements.push({
405-
let mut buffer = vec![];
410+
let mut buffer = Vec::new();
406411
for entrypoint in self.entry_points_by_type.external.iter() {
407412
buffer.push(entrypoint.selector);
408413
buffer.push(entrypoint.offset.into());
@@ -412,7 +417,7 @@ impl LegacyContractClass {
412417

413418
// Hashes L1 handler entry points
414419
elements.push({
415-
let mut buffer = vec![];
420+
let mut buffer = Vec::new();
416421
for entrypoint in self.entry_points_by_type.l1_handler.iter() {
417422
buffer.push(entrypoint.selector);
418423
buffer.push(entrypoint.offset.into());
@@ -422,7 +427,7 @@ impl LegacyContractClass {
422427

423428
// Hashes constructor entry points
424429
elements.push({
425-
let mut buffer = vec![];
430+
let mut buffer = Vec::new();
426431
for entrypoint in self.entry_points_by_type.constructor.iter() {
427432
buffer.push(entrypoint.selector);
428433
buffer.push(entrypoint.offset.into());
@@ -474,6 +479,7 @@ impl LegacyContractClass {
474479
Ok(starknet_keccak(serialized.as_bytes()))
475480
}
476481

482+
#[cfg(feature = "std")]
477483
pub fn compress(&self) -> Result<CompressedLegacyContractClass, CompressProgramError> {
478484
Ok(CompressedLegacyContractClass {
479485
program: self.program.compress()?,
@@ -490,7 +496,10 @@ impl LegacyContractClass {
490496
}
491497

492498
impl LegacyProgram {
499+
#[cfg(feature = "std")]
493500
pub fn compress(&self) -> Result<Vec<u8>, CompressProgramError> {
501+
use std::io::Write;
502+
494503
#[serde_as]
495504
#[derive(Serialize)]
496505
pub struct ProgramWithoutDebugInfo<'a> {

starknet-core/src/types/contract/mod.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use alloc::{format, string::String, vec::Vec};
2+
13
use serde::{ser::SerializeSeq, Deserialize, Deserializer, Serialize, Serializer};
24
use serde_json_pythonic::to_string_pythonic;
35
use serde_with::serde_as;
@@ -239,15 +241,16 @@ pub enum EventFieldKind {
239241
}
240242

241243
mod errors {
244+
use alloc::string::String;
242245
use core::fmt::{Display, Formatter, Result};
243-
use std::error::Error;
244246

245247
#[derive(Debug)]
246248
pub enum ComputeClassHashError {
247249
InvalidBuiltinName,
248250
Json(JsonError),
249251
}
250252

253+
#[cfg(feature = "std")]
251254
#[derive(Debug)]
252255
pub enum CompressProgramError {
253256
Json(JsonError),
@@ -259,7 +262,8 @@ mod errors {
259262
pub(crate) message: String,
260263
}
261264

262-
impl Error for ComputeClassHashError {}
265+
#[cfg(feature = "std")]
266+
impl std::error::Error for ComputeClassHashError {}
263267

264268
impl Display for ComputeClassHashError {
265269
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
@@ -270,8 +274,10 @@ mod errors {
270274
}
271275
}
272276

273-
impl Error for CompressProgramError {}
277+
#[cfg(feature = "std")]
278+
impl std::error::Error for CompressProgramError {}
274279

280+
#[cfg(feature = "std")]
275281
impl Display for CompressProgramError {
276282
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
277283
match self {
@@ -281,15 +287,19 @@ mod errors {
281287
}
282288
}
283289

284-
impl Error for JsonError {}
290+
#[cfg(feature = "std")]
291+
impl std::error::Error for JsonError {}
285292

286293
impl Display for JsonError {
287294
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
288295
write!(f, "{}", self.message)
289296
}
290297
}
291298
}
292-
pub use errors::{CompressProgramError, ComputeClassHashError, JsonError};
299+
pub use errors::{ComputeClassHashError, JsonError};
300+
301+
#[cfg(feature = "std")]
302+
pub use errors::CompressProgramError;
293303

294304
impl SierraClass {
295305
pub fn class_hash(&self) -> Result<FieldElement, ComputeClassHashError> {

0 commit comments

Comments
 (0)