Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

impl_modulus! is unusable for bigints starting from U3072 #577

Open
annenkov opened this issue Feb 28, 2024 · 6 comments
Open

impl_modulus! is unusable for bigints starting from U3072 #577

annenkov opened this issue Feb 28, 2024 · 6 comments

Comments

@annenkov
Copy link

Description

When using the impl_modulus! macro with U3072 and bigger types, the R2 constant computation takes several seconds. The Rust compilers version >= 1.73 with an error. In some cases (not for the example below, probably depends on how the constants are used, see here) compiler v1.76 panics.

Ways to reproduce

The example below fails to compile with 1.73.

use crypto_bigint::{impl_modulus, modular::ConstMontyParams, U3072};


impl_modulus!(
    StandardModulusP,
    U3072,
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB17217F7D1CF79ABC9E3B39803F2F6AF40F343267298B62D8A0D175B8BAAFA2BE7B876206DEBAC98559552FB4AFA1B10ED2EAE35C138214427573B291169B8253E96CA16224AE8C51ACBDA11317C387EB9EA9BC3B136603B256FA0EC7657F74B72CE87B19D6548CAF5DFA6BD38303248655FA1872F20E3A2DA2D97C50F3FD5C607F4CA11FB5BFB90610D30F88FE551A2EE569D6DFC1EFA157D2E23DE1400B39617460775DB8990E5C943E732B479CD33CCCC4E659393514C4C1A1E0BD1D6095D25669B333564A3376A9C7F8A5E148E82074DB6015CFE7AA30C480A5417350D2C955D5179B1E17B9DAE313CDB6C606CB1078F735D1B2DB31B5F50B5185064C18B4D162DB3B365853D7598A1951AE273EE5570B6C68F96983496D4E6D330AF889B44A02554731CDC8EA17293D1228A4EF98D6F5177FBCF0755268A5C1F9538B98261AFFD446B1CA3CF5E9222B88C66D3C5422183EDC99421090BBB16FAF3D949FF"
);

fn main() {
    println!("R2: {:?}", StandardModulusP::R2)
}

Console output

error: constant evaluation is taking a long time
  --> /home/danil/.cargo/registry/src/index.crates.io-6f17d22bba15001f/crypto-bigint-0.6.0-pre.12/src/uint/shr.rs:70:9
   |
70 | /         while i < LIMBS - shift_num {
71 | |             limbs[i] = self.limbs[i + shift_num];
72 | |             i += 1;
73 | |         }
   | |_________^
   |
   = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval.
           If your compilation actually takes a long time, you can safely allow the lint.
help: the constant being evaluated
  --> src/main.rs:4:1
   |
4  | / impl_modulus!(
5  | |     StandardModulusP,
6  | |     U3072,
7  | | "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB17217F7D1CF79ABC9E3B39803F2F6AF40F343267298B62D8A0D175B8BAAFA2BE7B876206DEBAC98559552FB4AFA1B10ED2EAE35C138214427573B291169B8253E96CA16224AE8C51ACBDA11317C387EB9EA9BC3B136603B256FA0EC7657F74B72CE87B19D6548CAF5DFA6BD38303248655FA1872F20E...
8  | | );
   | |_^
   = note: `#[deny(long_running_const_eval)]` on by default
   = note: this error originates in the macro `impl_modulus` (in Nightly builds, run with -Z macro-backtrace for more info)

note: erroneous constant used
  --> src/main.rs:45:26
   |
45 |     println!("R2: {:?}", StandardModulusP::R2)
   |                          ^^^^^^^^^^^^^^^^^^^^

note: erroneous constant used
  --> src/main.rs:45:26
   |
45 |     println!("R2: {:?}", StandardModulusP::R2)
   |                          ^^^^^^^^^^^^^^^^^^^^
   |
   = note: this note originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)

error: could not compile `crypto-bigint-example` (bin "crypto-bigint-example") due to previous error
danil@danil-ThinkPad:~/Projects/exercises/rust/crypto-bigint-example$ cargo run
   Compiling crypto-bigint-example v0.1.0 (/home/danil/Projects/exercises/rust/crypto-bigint-example)
error: constant evaluation is taking a long time
  --> .../.cargo/registry/src/index.crates.io-6f17d22bba15001f/crypto-bigint-0.6.0-pre.12/src/uint/shr.rs:70:9
   |
70 | /         while i < LIMBS - shift_num {
71 | |             limbs[i] = self.limbs[i + shift_num];
72 | |             i += 1;
73 | |         }
   | |_________^
   |
   = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval.
           If your compilation actually takes a long time, you can safely allow the lint.
help: the constant being evaluated
  --> src/main.rs:4:1
   |
4  | / impl_modulus!(
5  | |     StandardModulusP,
6  | |     U3072,
7  | | "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB17217F7D1CF79ABC9E3B39803F2F6AF40F343267298B62D8A0D175B8BAAFA2BE7B876206DEBAC98559552FB4AFA1B10ED2EAE35C138214427573B291169B8253E96CA16224AE8C51ACBDA11317C387EB9EA9BC3B136603B256FA0EC7657F74B72CE87B19D6548CAF5DFA6BD38303248655FA1872F20E...
8  | | );
   | |_^
   = note: `#[deny(long_running_const_eval)]` on by default
   = note: this error originates in the macro `impl_modulus` (in Nightly builds, run with -Z macro-backtrace for more info)

note: erroneous constant used
  --> src/main.rs:11:26
   |
11 |     println!("R2: {:?}", StandardModulusP::R2)
   |                          ^^^^^^^^^^^^^^^^^^^^

note: erroneous constant used
  --> src/main.rs:11:26
   |
11 |     println!("R2: {:?}", StandardModulusP::R2)
   |                          ^^^^^^^^^^^^^^^^^^^^
   |
   = note: this note originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)

error: could not compile `crypto-bigint-example` (bin "crypto-bigint-example") due to previous error

Using the Rust compiler v1.76

Misc

It is possible to create StandardModulusP and the corresponding implementation by hand (or copy-paste the expanded macro) and allow long_running_const_eval:

    #[allow(long_running_const_eval)]
    const R2: U4096 =
        crypto_bigint::Uint::rem_wide_vartime(Self::ONE.square_wide(), Self::MODULUS.as_nz_ref());

In this case, computing the constant in compile time takes ~7s on ThinkPad X1.

@tarcieri
Copy link
Member

tarcieri commented Feb 28, 2024

There's not a whole lot we can do here. The core problem is Miri performance. You can allow(long_running_const_eval), but the compile times seem perhaps prohibitively slow.

In such cases where computing the Montgomery parameters at compile time is too slow given current Miri limitations, you may need to take the path of just precomputing them, i.e. copy-paste the expanded macro as you suggested.

@spitters
Copy link

Just curious, AWS has their (formally verified) s2n bignum assembly library.
https://github.com/awslabs/s2n-bignum

It looks like there may be rust bindings for it. Would that solve any of these issues?

@tarcieri
Copy link
Member

@spitters it won't help here, since this question is about const fn usage, and s2n-bignum is a C/ASM library which isn't callable from const fn contexts

@tarcieri
Copy link
Member

@spitters note, however, that we do have a general tracking issue for incorporating the assembly from s2n-bignum: #572

@spitters
Copy link

From @protz:

HACL* extracted as pure safe Rust (dubbed "HACL-rs") lives here: https://github.com/hacl-star/hacl-star/tree/afromher_rs/dist/rs

In there, you'll find bignums in src/hacl:

  • bignum.rs, bignum64.rs: variable-length, 32 and 64-bit versions (scattered across these two files, this needs to be done better)
  • bignum{4096,256}.rs: fixed-length, 32-bit limbs
  • bignum{4096,256}_64.rs: fixed-length, 64-bit limbs

Since HACL-rs still preliminary, but the C code is documented properly, e.g. https://github.com/hacl-star/hacl-star/blob/afromher_rs/dist/gcc-compatible/Hacl_Bignum64.h.

For performance one should make sure to use "release mode".

@andrewwhitehead
Copy link
Contributor

andrewwhitehead commented Oct 2, 2024

FWIW this performs much better on recent versions since rem_wide_vartime was optimized. I tested the code above with U4096 and cargo build --release after cargo clean completed in 4.6 seconds (Rust 1.81 on a 2021 Macbook Pro).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants