Skip to content

Commit

Permalink
no_std support for fuel-tx and fuel-vm (#582)
Browse files Browse the repository at this point in the history
* WIP

* WIP: use k256 crate for no_std compliant cryptography

* Re-add secp256k1 crate support, add backend selection

* Fix clippy issues with features on/off

* Fmt toml files

* Cleanup for CI

* Add changelog entry

* Doc-tests cleanup

* Rename secp module to secp256

* Fix warnings with no_std target

* Run checks for no_std fuel-crypto

* WIP

* WIP

* WIP: before attempting to un-indirect error types

* Error type rework

* Change deps from last commit to be no_std

* Make cargo check work under --target x86_64-unknown-none --features alloc

* Toml fmt

* Move more stuff out of #[cfg(feature = "std")]

* Cleanup fuel-asm cfgs

* Add changelog

* Move some fuel-asm gates from std to alloc feature

* Clippy fixes

* Add missing no_std/alloc imports for fuel-vm tests (WIP)

* Finalize test import fixes

* Temporarily disable fuel-crypto self-dev-dep

* Some cfg-related import fixes

* Fix changelog

* Re-apply fuel-crypto self-dev-dep

* Compatibility fixes for fuel-core

* Feature-gate fuel-vm tests behind alloc

* Add riscv32imac-unknown-none-elf to cargo make matrix targets

* Remove unneeded alloc feature gating

* Use alloc feature with tests

* Remove a useless import

* Use qualified path instead of an import

Co-authored-by: Green Baneling <XgreenX9999@gmail.com>

* bugfix: StorageRead<ContractsRawCode> of MemoryStorage returned incorrect len

* Update fuel-asm/src/encoding_tests.rs

Co-authored-by: Green Baneling <XgreenX9999@gmail.com>

* WIP: adding fully generic storage error (likely not)

* more wip

* WIP: tests passing again

* Cleanup: clippy

* Minor moments after review

* Change two match'es to map_err's

---------

Co-authored-by: Green Baneling <XgreenX9999@gmail.com>
  • Loading branch information
Dentosal and xgreenx authored Sep 22, 2023
1 parent 85c131d commit 76eb3e0
Show file tree
Hide file tree
Showing 122 changed files with 1,426 additions and 1,197 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ jobs:
args: --target wasm32-unknown-unknown -p fuel-asm --features typescript --crate-type=cdylib
- command: check
args: --target wasm32-unknown-unknown -p fuel-types --features serde --no-default-features
- command: check
args: --target wasm32-unknown-unknown -p fuel-vm --features alloc --no-default-features
- command: bench
args: --workspace --no-run
- command: make
Expand All @@ -95,7 +97,7 @@ jobs:
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.RUST_VERSION }}
targets: "thumbv6m-none-eabi,wasm32-unknown-unknown"
targets: "thumbv6m-none-eabi,riscv32imac-unknown-none-elf,wasm32-unknown-unknown"
components: "clippy"
- name: Install Cargo Make
uses: davidB/rust-cargo-make@v1
Expand Down
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

#### Breaking

- [#578](https://github.com/FuelLabs/fuel-vm/pull/578): Support `no_std` environments for `fuel-crypto`, falling back to a pure-Rust crypto implementation.
- [#582](https://github.com/FuelLabs/fuel-vm/pull/582): Make `fuel-vm` and `fuel-tx` crates compatible with `no_std` + `alloc`. This includes reworking all error handling that used `std::io::Error`, replacing some `std::collection::{HashMap, HashSet}` with `hashbrown::{HashMap, HashSet}` and many changes to feature-gating of APIs.
### Added

- [#586](https://github.com/FuelLabs/fuel-vm/pull/586): Added `default_asset` method to the `ContractIdExt` trait implementation, to mirror the `default` method on AssetId in the Sway std lib.
Expand All @@ -20,7 +24,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
These opcodes charged inadequately low costs in comparison to the amount of work.
This change should make all transactions that used these opcodes much more expensive than before.
- [#533](https://github.com/FuelLabs/fuel-vm/pull/533): Use custom serialization for fuel-types to allow no_std compilation.
- [#578](https://github.com/FuelLabs/fuel-vm/pull/578): Support `no_std` environments for `fuel-crypto`, falling back to a pure-Rust crypto implementation.

## [Version 0.36.1]

Expand Down
1 change: 1 addition & 0 deletions ci_checks.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ cargo check --target thumbv6m-none-eabi -p fuel-asm -p fuel-storage -p fuel-merk
cargo check --target wasm32-unknown-unknown -p fuel-crypto --no-default-features &&
cargo check --target wasm32-unknown-unknown -p fuel-types --features serde --no-default-features &&
cargo check --target wasm32-unknown-unknown -p fuel-tx --features serde --no-default-features &&
cargo check --target wasm32-unknown-unknown -p fuel-vm --features alloc --no-default-features &&
cargo rustc --target wasm32-unknown-unknown -p fuel-types --features typescript --crate-type=cdylib &&
cargo rustc --target wasm32-unknown-unknown -p fuel-asm --features typescript --crate-type=cdylib &&
cargo make check &&
Expand Down
3 changes: 2 additions & 1 deletion fuel-asm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ rstest = "0.16"
[features]
default = ["std"]
typescript = ["wasm-bindgen", "wee_alloc"]
std = ["serde?/default", "fuel-types/std"]
std = ["alloc", "serde?/default", "fuel-types/std"]
alloc = ["fuel-asm/alloc"]
serde = ["dep:serde"]

# docs.rs-specific configuration
Expand Down
1 change: 1 addition & 0 deletions fuel-asm/src/encoding_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use fuel_asm as _;
use strum::IntoEnumIterator;

#[test]
#[cfg(test)]
fn opcode() {
// values picked to test edge cases
let r = RegId::new_checked(0x2d).unwrap();
Expand Down
13 changes: 8 additions & 5 deletions fuel-asm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@
#![deny(unsafe_code)]
#![deny(unused_crate_dependencies)]

#[cfg(feature = "alloc")]
extern crate alloc;

#[cfg(feature = "wee_alloc")]
use wee_alloc as _;

#[cfg(all(no_std, feature = "wee_alloc"))]
// Use `wee_alloc` as the global allocator.
#[cfg(all(no_std, feature = "wee_alloc"))]
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;

Expand Down Expand Up @@ -877,15 +880,15 @@ where

// Collect instructions into bytes or halfwords

#[cfg(feature = "std")]
impl core::iter::FromIterator<Instruction> for Vec<u8> {
#[cfg(feature = "alloc")]
impl core::iter::FromIterator<Instruction> for alloc::vec::Vec<u8> {
fn from_iter<I: IntoIterator<Item = Instruction>>(iter: I) -> Self {
iter.into_iter().flat_map(Instruction::to_bytes).collect()
}
}

#[cfg(feature = "std")]
impl core::iter::FromIterator<Instruction> for Vec<u32> {
#[cfg(feature = "alloc")]
impl core::iter::FromIterator<Instruction> for alloc::vec::Vec<u32> {
fn from_iter<I: IntoIterator<Item = Instruction>>(iter: I) -> Self {
iter.into_iter().map(u32::from).collect()
}
Expand Down
16 changes: 0 additions & 16 deletions fuel-asm/src/panic_reason.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,22 +120,6 @@ impl fmt::Display for PanicReason {
}
}

#[cfg(feature = "std")]
impl std::error::Error for PanicReason {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
None
}
}

#[cfg(feature = "std")]
impl From<PanicReason> for std::io::Error {
fn from(reason: PanicReason) -> Self {
use std::io;

io::Error::new(io::ErrorKind::Other, reason)
}
}

impl From<core::array::TryFromSliceError> for PanicReason {
fn from(_: core::array::TryFromSliceError) -> Self {
Self::MemoryOverflow
Expand Down
2 changes: 1 addition & 1 deletion fuel-crypto/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
#![deny(unsafe_code)]
#![deny(unused_crate_dependencies)]

#[cfg(test)]
// Satisfy unused_crate_dependencies lint for self-dependency enabling test features
#[cfg(test)]
use fuel_crypto as _;

/// Required export for using mnemonic keygen on [`SecretKey::new_from_mnemonic`]
Expand Down
1 change: 1 addition & 0 deletions fuel-crypto/src/secp256/backend/r1/p256.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ pub fn sign_prehashed(

/// Convert the public key point to its uncompressed non-prefixed representation,
/// i.e. 32 bytes of x coordinate and 32 bytes of y coordinate.
#[cfg(feature = "test-helpers")]
pub fn encode_pubkey(key: VerifyingKey) -> [u8; 64] {
let point = key.to_encoded_point(false);
let mut result = [0u8; 64];
Expand Down
2 changes: 1 addition & 1 deletion fuel-merkle/benches/smt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ fn sparse_merkle_tree(c: &mut Criterion) {

let rng = &mut StdRng::seed_from_u64(8586);
let gen = || Some((MerkleTreeKey::new(random_bytes32(rng)), random_bytes32(rng)));
let data = std::iter::from_fn(gen).take(50_000).collect::<Vec<_>>();
let data = core::iter::from_fn(gen).take(50_000).collect::<Vec<_>>();

let expected_root = baseline_root(data.clone().into_iter());
let root = subject_root(data.clone().into_iter());
Expand Down
14 changes: 8 additions & 6 deletions fuel-tx/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,24 @@ fuel-asm = { workspace = true, default-features = false }
fuel-crypto = { workspace = true, default-features = false }
fuel-merkle = { workspace = true, default-features = false, optional = true }
fuel-types = { workspace = true, default-features = false }
hashbrown = { version = "0.14", optional = true }
itertools = { version = "0.10", default-features = false, optional = true }
num-integer = { version = "0.1", default-features = false, optional = true }
num_enum = { version = "0.7", optional = true }
num_enum = { version = "0.7", default-features = false, optional = true }
rand = { version = "0.8", default-features = false, features = ["std_rng"], optional = true }
serde = { version = "1.0", default-features = false, features = ["alloc", "derive"], optional = true }
serde_json = { version = "1.0", default-features = false, features = ["alloc"], optional = true }
strum = { version = "0.24", optional = true }
strum = { version = "0.24", default-features = false, optional = true }
strum_macros = { version = "0.24", optional = true }
thiserror = { version = "1.0", optional = true }

[dev-dependencies]
bincode = { workspace = true }
fuel-crypto = { workspace = true, default-features = false, features = ["random"] }
fuel-tx = { path = ".", features = ["builder", "random"] }
fuel-tx-test-helpers = { path = "test-helpers" }
fuel-types = { workspace = true, default-features = false, features = ["random"] }
hex = { version = "0.4" }
hex = { version = "0.4", default-features = false }
insta = "1.0"
quickcheck = "1.0"
quickcheck_macros = "1.0"
Expand All @@ -40,10 +42,10 @@ rstest = "0.15"

[features]
default = ["fuel-asm/default", "fuel-crypto/default", "fuel-merkle/default", "fuel-types/default", "std"]
alloc = ["fuel-types/alloc", "itertools/use_alloc", "derivative", "fuel-merkle", "num_enum", "num-integer", "strum", "strum_macros"]
builder = ["alloc", "internals"]
internals = []
random = ["fuel-crypto/random", "fuel-types/random", "rand"]
std = ["alloc", "fuel-asm/std", "fuel-crypto/std", "fuel-merkle/std", "fuel-types/std", "itertools/default", "rand?/default", "serde?/default"]
std = ["alloc", "dep:thiserror", "fuel-asm/std", "fuel-crypto/std", "fuel-merkle/std", "fuel-types/std", "itertools/default", "rand?/default", "serde?/default", "hex/std"]
alloc = ["hashbrown", "fuel-types/alloc", "itertools/use_alloc", "derivative", "fuel-merkle", "num_enum", "num-integer", "strum", "strum_macros"]
# serde is requiring alloc because its mandatory for serde_json. to avoid adding a new feature only for serde_json, we just require `alloc` here since as of the moment we don't have a use case of serde without alloc.
serde = ["alloc", "dep:serde", "fuel-asm/serde", "fuel-crypto/serde", "fuel-types/serde", "serde_json"]
serde = ["alloc", "dep:serde", "fuel-asm/serde", "fuel-crypto/serde", "fuel-types/serde", "serde_json", "hashbrown/serde"]
29 changes: 5 additions & 24 deletions fuel-tx/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use crate::{
Executable,
Script,
},
Cacheable,
ConsensusParameters,
ContractParameters,
FeeParameters,
Expand All @@ -28,8 +27,10 @@ use crate::{
Witness,
};

#[cfg(feature = "std")]
use crate::Signable;
use crate::{
Cacheable,
Signable,
};

use fuel_crypto::SecretKey;
use fuel_types::{
Expand Down Expand Up @@ -59,13 +60,8 @@ where
{
}

#[cfg(feature = "std")]
pub trait BuildableStd: Signable + Cacheable {}

#[cfg(not(feature = "std"))]
pub trait BuildableSet: BuildableAloc {}

#[cfg(feature = "std")]
pub trait BuildableSet: BuildableAloc + BuildableStd {}

pub trait Buildable
Expand Down Expand Up @@ -110,12 +106,8 @@ impl<T> BuildableAloc for T where
{
}

#[cfg(feature = "std")]
impl<T> BuildableStd for T where T: Signable + Cacheable {}
#[cfg(feature = "std")]
impl<T> BuildableSet for T where T: BuildableAloc + BuildableStd {}
#[cfg(not(feature = "std"))]
impl<T> BuildableSet for T where T: BuildableAloc {}
impl<T> Buildable for T where T: BuildableSet {}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -326,7 +318,6 @@ impl<Tx: Buildable> TransactionBuilder<Tx> {
self
}

#[cfg(feature = "std")]
pub fn add_unsigned_coin_input(
&mut self,
secret: SecretKey,
Expand All @@ -353,7 +344,7 @@ impl<Tx: Buildable> TransactionBuilder<Tx> {
self
}

#[cfg(all(feature = "rand", feature = "std"))]
#[cfg(feature = "rand")]
pub fn add_random_fee_input(&mut self) -> &mut Self {
use rand::{
Rng,
Expand All @@ -370,7 +361,6 @@ impl<Tx: Buildable> TransactionBuilder<Tx> {
)
}

#[cfg(feature = "std")]
pub fn add_unsigned_message_input(
&mut self,
secret: SecretKey,
Expand Down Expand Up @@ -421,7 +411,6 @@ impl<Tx: Buildable> TransactionBuilder<Tx> {
}

/// Adds a secret to the builder, and adds a corresponding witness if it's a new entry
#[cfg(feature = "std")]
fn upsert_secret(&mut self, secret_key: SecretKey) -> u8 {
let witness_len = self.witnesses().len() as u8;

Expand All @@ -434,7 +423,6 @@ impl<Tx: Buildable> TransactionBuilder<Tx> {
*witness_index
}

#[cfg(feature = "std")]
fn prepare_finalize(&mut self) {
if self.should_prepare_predicate {
self.tx.prepare_init_predicate();
Expand All @@ -445,7 +433,6 @@ impl<Tx: Buildable> TransactionBuilder<Tx> {
}
}

#[cfg(feature = "std")]
fn finalize_inner(&mut self) -> Tx {
self.prepare_finalize();

Expand All @@ -461,7 +448,6 @@ impl<Tx: Buildable> TransactionBuilder<Tx> {
tx
}

#[cfg(feature = "std")]
pub fn finalize_without_signature_inner(&mut self) -> Tx {
self.prepare_finalize();

Expand All @@ -487,7 +473,6 @@ pub trait Finalizable<Tx> {
fn finalize_without_signature(&mut self) -> Tx;
}

#[cfg(feature = "std")]
impl Finalizable<Mint> for TransactionBuilder<Mint> {
fn finalize(&mut self) -> Mint {
let mut tx = core::mem::take(&mut self.tx);
Expand All @@ -501,7 +486,6 @@ impl Finalizable<Mint> for TransactionBuilder<Mint> {
}
}

#[cfg(feature = "std")]
impl Finalizable<Create> for TransactionBuilder<Create> {
fn finalize(&mut self) -> Create {
self.finalize_inner()
Expand All @@ -512,7 +496,6 @@ impl Finalizable<Create> for TransactionBuilder<Create> {
}
}

#[cfg(feature = "std")]
impl Finalizable<Script> for TransactionBuilder<Script> {
fn finalize(&mut self) -> Script {
self.finalize_inner()
Expand All @@ -528,12 +511,10 @@ where
Self: Finalizable<Tx>,
Transaction: From<Tx>,
{
#[cfg(feature = "std")]
pub fn finalize_as_transaction(&mut self) -> Transaction {
self.finalize().into()
}

#[cfg(feature = "std")]
pub fn finalize_without_signature_as_transaction(&mut self) -> Transaction {
self.finalize_without_signature().into()
}
Expand Down
7 changes: 4 additions & 3 deletions fuel-tx/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,10 @@ pub use transaction::{
Witness,
};

#[cfg(feature = "std")]
pub use transaction::Signable;
pub use transaction::UniqueIdentifier;
pub use transaction::{
Signable,
UniqueIdentifier,
};

#[cfg(feature = "alloc")]
#[allow(deprecated)]
Expand Down
Loading

0 comments on commit 76eb3e0

Please sign in to comment.