Skip to content

Commit b255bb4

Browse files
committed
add no-std support
1 parent d048057 commit b255bb4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+171
-104
lines changed

.github/workflows/main.yml

+17
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,23 @@ jobs:
2424
with:
2525
command: build
2626

27+
build_no_std:
28+
name: build with no_std
29+
runs-on: ubuntu-latest
30+
# Skip ed448 which does not support it.
31+
strategy:
32+
matrix:
33+
crate: [ristretto255, ed25519, p256, secp256k1, rerandomized]
34+
steps:
35+
- uses: actions/[email protected]
36+
- uses: dtolnay/rust-toolchain@master
37+
with:
38+
toolchain: stable
39+
targets: thumbv6m-none-eabi
40+
- run: cargo build -p frost-${{ matrix.crate }} --no-default-features --target thumbv6m-none-eabi
41+
- run: cargo build -p frost-${{ matrix.crate }} --target thumbv6m-none-eabi
42+
- run: cargo build -p frost-${{ matrix.crate }} --features serde --target thumbv6m-none-eabi
43+
2744
test_beta:
2845
name: test on beta
2946
runs-on: ubuntu-latest

frost-core/CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ Entries are listed in reverse chronological order.
44

55
## Unreleased
66

7+
* Add no-std support to all crates except frost-ed448. Note that you don't need
8+
to use `default-features = false`; there is no `std` feature that is enabled
9+
by default. Also note that it always links to an external `alloc` crate (i.e.
10+
there is no `alloc` feature either).
11+
712
## Released
813

914
## 1.0.0

frost-core/Cargo.toml

+8-8
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,20 @@ features = ["serde"]
2222
rustdoc-args = ["--cfg", "docsrs"]
2323

2424
[dependencies]
25-
byteorder = "1.4"
26-
const-crc32 = "1.2.0"
25+
byteorder = { version = "1.4", default-features = false }
26+
const-crc32 = { version = "1.2.0", package = "const-crc32-nostd" }
2727
document-features = "0.2.7"
2828
debugless-unwrap = "0.0.4"
2929
derive-getters = "0.3.0"
30-
hex = "0.4.3"
31-
postcard = { version = "1.0.0", features = ["use-std"], optional = true }
32-
rand_core = "0.6"
33-
serde = { version = "1.0.160", features = ["derive"], optional = true }
30+
hex = { version = "0.4.3", default-features = false, features = ["alloc"] }
31+
postcard = { version = "1.0.0", features = ["alloc"], optional = true }
32+
rand_core = { version = "0.6", default-features = false }
33+
serde = { version = "1.0.160", default-features = false, features = ["derive"], optional = true }
3434
serdect = { version = "0.2.0", optional = true }
35-
thiserror = "1.0"
35+
thiserror = { version = "1.0", package = "thiserror-nostd-notrait", default-features = false }
3636
visibility = "0.1.0"
3737
zeroize = { version = "1.5.4", default-features = false, features = ["derive"] }
38-
itertools = "0.12.0"
38+
itertools = { version = "0.12.0", default-features = false }
3939

4040
# Test dependencies used with the test-impl feature
4141
proptest = { version = "1.0", optional = true }

frost-core/src/batch.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
//! of caller code (which must assemble a batch of signatures across
88
//! work-items), and loss of the ability to easily pinpoint failing signatures.
99
10-
use std::iter::once;
11-
1210
use rand_core::{CryptoRng, RngCore};
1311

1412
use crate::{scalar_mul::VartimeMultiscalarMul, Ciphersuite, Element, *};
@@ -132,7 +130,7 @@ where
132130
VKs.push(item.vk.element);
133131
}
134132

135-
let scalars = once(&P_coeff_acc)
133+
let scalars = core::iter::once(&P_coeff_acc)
136134
.chain(VK_coeffs.iter())
137135
.chain(R_coeffs.iter());
138136

@@ -155,6 +153,8 @@ where
155153
C: Ciphersuite,
156154
{
157155
fn default() -> Self {
158-
Self { signatures: vec![] }
156+
Self {
157+
signatures: Vec::new(),
158+
}
159159
}
160160
}

frost-core/src/benches.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
//! Ciphersuite-generic benchmark functions.
22
#![allow(clippy::unwrap_used)]
33

4-
use std::collections::BTreeMap;
4+
use core::iter;
55

6-
use criterion::{BenchmarkId, Criterion, Throughput};
6+
use alloc::{collections::BTreeMap, format, vec::Vec};
77
use rand_core::{CryptoRng, RngCore};
88

9+
use criterion::{BenchmarkId, Criterion, Throughput};
10+
911
use crate as frost;
1012
use crate::{batch, Ciphersuite, Signature, SigningKey, VerifyingKey};
1113

@@ -18,7 +20,7 @@ fn sigs_with_distinct_keys<C: Ciphersuite, R: RngCore + CryptoRng + Clone>(
1820
rng: &mut R,
1921
) -> impl Iterator<Item = Item<C>> {
2022
let mut rng = rng.clone();
21-
std::iter::repeat_with(move || {
23+
iter::repeat_with(move || {
2224
let msg = b"Bench";
2325
let sk = SigningKey::new(&mut rng);
2426
let vk = VerifyingKey::from(&sk);

frost-core/src/identifier.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! FROST participant identifiers
22
3-
use std::{
3+
use core::{
44
fmt::{self, Debug},
55
hash::{Hash, Hasher},
66
};
@@ -117,7 +117,7 @@ impl<C> Ord for Identifier<C>
117117
where
118118
C: Ciphersuite,
119119
{
120-
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
120+
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
121121
let serialized_self = <<C::Group as Group>::Field>::little_endian_serialize(&self.0);
122122
let serialized_other = <<C::Group as Group>::Field>::little_endian_serialize(&other.0);
123123
// The default cmp uses lexicographic order; so we need the elements in big endian
@@ -133,12 +133,12 @@ impl<C> PartialOrd for Identifier<C>
133133
where
134134
C: Ciphersuite,
135135
{
136-
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
136+
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
137137
Some(self.cmp(other))
138138
}
139139
}
140140

141-
impl<C> std::ops::Mul<Scalar<C>> for Identifier<C>
141+
impl<C> core::ops::Mul<Scalar<C>> for Identifier<C>
142142
where
143143
C: Ciphersuite,
144144
{
@@ -149,7 +149,7 @@ where
149149
}
150150
}
151151

152-
impl<C> std::ops::MulAssign<Identifier<C>> for Scalar<C>
152+
impl<C> core::ops::MulAssign<Identifier<C>> for Scalar<C>
153153
where
154154
C: Ciphersuite,
155155
{
@@ -158,7 +158,7 @@ where
158158
}
159159
}
160160

161-
impl<C> std::ops::Sub for Identifier<C>
161+
impl<C> core::ops::Sub for Identifier<C>
162162
where
163163
C: Ciphersuite,
164164
{

frost-core/src/keys.rs

+12-11
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
//! FROST keys, keygen, key shares
22
#![allow(clippy::type_complexity)]
33

4-
use std::{
5-
collections::{BTreeMap, BTreeSet, HashSet},
6-
convert::TryFrom,
7-
default::Default,
4+
use core::iter;
5+
6+
use alloc::vec::Vec;
7+
use alloc::{
8+
collections::{BTreeMap, BTreeSet},
89
fmt::{self, Debug},
9-
iter,
1010
};
1111

1212
use derive_getters::Getters;
@@ -17,11 +17,12 @@ use rand_core::{CryptoRng, RngCore};
1717
use zeroize::{DefaultIsZeroes, Zeroize};
1818

1919
use crate::{
20-
serialization::{Deserialize, Serialize},
21-
Ciphersuite, Element, Error, Field, Group, Header, Identifier, Scalar, SigningKey,
22-
VerifyingKey,
20+
Ciphersuite, Element, Error, Field, Group, Header, Identifier, Scalar, SigningKey, VerifyingKey,
2321
};
2422

23+
#[cfg(feature = "serialization")]
24+
use crate::serialization::{Deserialize, Serialize};
25+
2526
#[cfg(feature = "serde")]
2627
use crate::serialization::{ElementSerialization, ScalarSerialization};
2728

@@ -126,7 +127,7 @@ impl<C> Debug for SigningShare<C>
126127
where
127128
C: Ciphersuite,
128129
{
129-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
130+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> core::fmt::Result {
130131
f.debug_tuple("SigningShare").field(&"<redacted>").finish()
131132
}
132133
}
@@ -325,7 +326,7 @@ impl<C> Debug for CoefficientCommitment<C>
325326
where
326327
C: Ciphersuite,
327328
{
328-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
329+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> core::fmt::Result {
329330
f.debug_tuple("CoefficientCommitment")
330331
.field(&hex::encode(self.serialize()))
331332
.finish()
@@ -900,7 +901,7 @@ pub(crate) fn generate_secret_shares<C: Ciphersuite>(
900901
let (coefficients, commitment) =
901902
generate_secret_polynomial(secret, max_signers, min_signers, coefficients)?;
902903

903-
let identifiers_set: HashSet<_> = identifiers.iter().collect();
904+
let identifiers_set: BTreeSet<_> = identifiers.iter().collect();
904905
if identifiers_set.len() != identifiers.len() {
905906
return Err(Error::DuplicatedIdentifier);
906907
}

frost-core/src/keys/dkg.rs

+13-8
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@
3030
//! [Feldman's VSS]: https://www.cs.umd.edu/~gasarch/TOPICS/secretsharing/feldmanVSS.pdf
3131
//! [secure broadcast channel]: https://frost.zfnd.org/terminology.html#broadcast-channel
3232
33-
use std::{collections::BTreeMap, iter};
33+
use core::iter;
34+
35+
use alloc::collections::BTreeMap;
3436

3537
use rand_core::{CryptoRng, RngCore};
3638

@@ -39,6 +41,9 @@ use crate::{
3941
SigningKey, VerifyingKey,
4042
};
4143

44+
#[cfg(feature = "serialization")]
45+
use crate::serialization::{Deserialize, Serialize};
46+
4247
use super::{
4348
evaluate_polynomial, generate_coefficients, generate_secret_polynomial,
4449
validate_num_of_signers, KeyPackage, PublicKeyPackage, SecretShare, SigningShare,
@@ -47,11 +52,10 @@ use super::{
4752

4853
/// DKG Round 1 structures.
4954
pub mod round1 {
55+
use alloc::vec::Vec;
5056
use derive_getters::Getters;
5157
use zeroize::Zeroize;
5258

53-
use crate::serialization::{Deserialize, Serialize};
54-
5559
use super::*;
5660

5761
/// The package that must be broadcast by each participant to all other participants
@@ -135,11 +139,11 @@ pub mod round1 {
135139
}
136140
}
137141

138-
impl<C> std::fmt::Debug for SecretPackage<C>
142+
impl<C> core::fmt::Debug for SecretPackage<C>
139143
where
140144
C: Ciphersuite,
141145
{
142-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
146+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
143147
f.debug_struct("SecretPackage")
144148
.field("identifier", &self.identifier)
145149
.field("coefficients", &"<redacted>")
@@ -167,7 +171,8 @@ pub mod round2 {
167171
use derive_getters::Getters;
168172
use zeroize::Zeroize;
169173

170-
use crate::serialization::{Deserialize, Serialize};
174+
#[cfg(feature = "serialization")]
175+
use alloc::vec::Vec;
171176

172177
use super::*;
173178

@@ -239,11 +244,11 @@ pub mod round2 {
239244
pub(crate) max_signers: u16,
240245
}
241246

242-
impl<C> std::fmt::Debug for SecretPackage<C>
247+
impl<C> core::fmt::Debug for SecretPackage<C>
243248
where
244249
C: Ciphersuite,
245250
{
246-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
251+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
247252
f.debug_struct("SecretPackage")
248253
.field("identifier", &self.identifier)
249254
.field("commitment", &self.commitment)

frost-core/src/keys/repairable.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
//! The RTS is used to help a signer (participant) repair their lost share. This is achieved
55
//! using a subset of the other signers know here as `helpers`.
66
7-
use std::collections::{BTreeMap, BTreeSet};
7+
use alloc::collections::{BTreeMap, BTreeSet};
8+
9+
use alloc::vec::Vec;
810

911
use crate::{
1012
compute_lagrange_coefficient, Ciphersuite, CryptoRng, Error, Field, Group, Header, Identifier,

frost-core/src/lib.rs

+13-8
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#![no_std]
12
#![allow(non_snake_case)]
23
// It's emitting false positives; see https://github.com/rust-lang/rust-clippy/issues/9413
34
#![allow(clippy::derive_partial_eq_without_eq)]
@@ -10,11 +11,15 @@
1011
#![doc = include_str!("../README.md")]
1112
#![doc = document_features::document_features!()]
1213

13-
use std::{
14+
#[macro_use]
15+
extern crate alloc;
16+
17+
use core::marker::PhantomData;
18+
19+
use alloc::{
1420
collections::{BTreeMap, BTreeSet},
15-
default::Default,
1621
fmt::{self, Debug},
17-
marker::PhantomData,
22+
vec::Vec,
1823
};
1924

2025
use derive_getters::Getters;
@@ -87,7 +92,7 @@ impl<C> Debug for Challenge<C>
8792
where
8893
C: Ciphersuite,
8994
{
90-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
95+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
9196
f.debug_tuple("Secret")
9297
.field(&hex::encode(<<C::Group as Group>::Field>::serialize(
9398
&self.0,
@@ -111,7 +116,7 @@ fn challenge<C>(R: &Element<C>, verifying_key: &VerifyingKey<C>, msg: &[u8]) ->
111116
where
112117
C: Ciphersuite,
113118
{
114-
let mut preimage = vec![];
119+
let mut preimage = Vec::new();
115120

116121
preimage.extend_from_slice(<C::Group>::serialize(R).as_ref());
117122
preimage.extend_from_slice(<C::Group>::serialize(&verifying_key.element).as_ref());
@@ -153,7 +158,7 @@ struct Header<C: Ciphersuite> {
153158
serde(deserialize_with = "crate::serialization::ciphersuite_deserialize::<_, C>")
154159
)]
155160
ciphersuite: (),
156-
#[serde(skip)]
161+
#[cfg_attr(feature = "serde", serde(skip))]
157162
phantom: PhantomData<C>,
158163
}
159164

@@ -404,7 +409,7 @@ where
404409
verifying_key: &VerifyingKey<C>,
405410
additional_prefix: &[u8],
406411
) -> Vec<(Identifier<C>, Vec<u8>)> {
407-
let mut binding_factor_input_prefix = vec![];
412+
let mut binding_factor_input_prefix = Vec::new();
408413

409414
// The length of a serialized verifying key of the same cipersuite does
410415
// not change between runs of the protocol, so we don't need to hash to
@@ -423,7 +428,7 @@ where
423428
self.signing_commitments()
424429
.keys()
425430
.map(|identifier| {
426-
let mut binding_factor_input = vec![];
431+
let mut binding_factor_input = Vec::new();
427432

428433
binding_factor_input.extend_from_slice(&binding_factor_input_prefix);
429434
binding_factor_input.extend_from_slice(identifier.serialize().as_ref());

0 commit comments

Comments
 (0)