Skip to content

Commit 082424b

Browse files
authored
Fix Fr scalar field to reduce modulo r on construction (#1750)
### What `Fr` types for BN254 and BLS12-381 stored raw `U256` values without modular reduction, causing mathematically equal field elements (e.g., 1 and r+1) to compare as not-equal via PartialEq. The fix: apply `rem_euclid(r)` in `From<U256>` for `Fr`, and ensuring all public construction paths produce canonical representations in [0, r). Also introduces modulus validation for BLS12-381 and BN254 base-field element wrappers (Fp/Fp2) and refactor `BytesN` wrapper macros to support validated `from_bytes`.
1 parent 3e529a6 commit 082424b

19 files changed

Lines changed: 1964 additions & 87 deletions

Cargo.lock

Lines changed: 231 additions & 30 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

soroban-sdk/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ proptest-arbitrary-interop = "0.1.0"
5959
libfuzzer-sys = "0.4.7"
6060
expect-test = "1.4.1"
6161
sha2 = "0.10.7"
62+
ark-bn254 = { version = "0.5", default-features = false, features = ["curve"] }
63+
ark-bls12-381 = { version = "0.5", default-features = false, features = ["curve"] }
64+
ark-ff = { version = "0.5", default-features = false }
6265

6366
[features]
6467
alloc = []

soroban-sdk/src/bytes.rs

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -102,14 +102,19 @@ macro_rules! bytesn {
102102
};
103103
}
104104

105+
/// Internal macro that generates all `BytesN` wrapper methods and trait impls
106+
/// *except* `from_bytes`. Types using this macro must provide their own
107+
/// `from_bytes(BytesN<$size>) -> Self` (e.g. to add validation).
108+
///
109+
/// This macro exists for backward compatibility: `impl_bytesn_repr` was
110+
/// accidentally exported via `#[macro_export]` and cannot be changed until the
111+
/// next protocol boundary. Once we remove the `#[macro_export]` from
112+
/// `impl_bytesn_repr`, this macro should be consolidated back into it.
113+
#[doc(hidden)]
105114
#[macro_export]
106-
macro_rules! impl_bytesn_repr {
115+
macro_rules! impl_bytesn_repr_without_from_bytes {
107116
($elem: ident, $size: expr) => {
108117
impl $elem {
109-
pub fn from_bytes(bytes: BytesN<$size>) -> Self {
110-
Self(bytes)
111-
}
112-
113118
pub fn into_bytes(self) -> BytesN<$size> {
114119
self.0
115120
}
@@ -127,7 +132,7 @@ macro_rules! impl_bytesn_repr {
127132
}
128133

129134
pub fn from_array(env: &Env, array: &[u8; $size]) -> Self {
130-
Self(<BytesN<$size>>::from_array(env, array))
135+
Self::from_bytes(BytesN::from_array(env, array))
131136
}
132137

133138
pub fn as_val(&self) -> &Val {
@@ -151,8 +156,8 @@ macro_rules! impl_bytesn_repr {
151156
type Error = ConversionError;
152157

153158
fn try_from_val(env: &Env, val: &Val) -> Result<Self, Self::Error> {
154-
let bytes = <BytesN<$size>>::try_from_val(env, val)?;
155-
Ok($elem(bytes))
159+
let bytes = BytesN::try_from_val(env, val)?;
160+
Ok(Self::from_bytes(bytes))
156161
}
157162
}
158163

@@ -226,6 +231,25 @@ macro_rules! impl_bytesn_repr {
226231
};
227232
}
228233

234+
/// Generates all `BytesN` wrapper methods and trait impls including a default
235+
/// `from_bytes` that wraps the bytes without validation.
236+
///
237+
/// NOTE: This macro was not intended to be exported. Remove the
238+
/// `#[macro_export]` at the next protocol boundary, and consolidate
239+
/// `impl_bytesn_repr_without_from_bytes` back into this macro.
240+
#[macro_export]
241+
macro_rules! impl_bytesn_repr {
242+
($elem: ident, $size: expr) => {
243+
impl $elem {
244+
pub fn from_bytes(bytes: BytesN<$size>) -> Self {
245+
Self(bytes)
246+
}
247+
}
248+
249+
impl_bytesn_repr_without_from_bytes!($elem, $size);
250+
};
251+
}
252+
229253
/// Bytes is a contiguous growable array type containing `u8`s.
230254
///
231255
/// The array is stored in the Host and available to the Guest through the

0 commit comments

Comments
 (0)