summaryrefslogtreecommitdiffstats
path: root/vendor/ff/tests/derive.rs
blob: fa6ee20e9cf39feff633c97f5b5f967a802f0088 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
//! This module exercises the `ff_derive` procedural macros, to ensure that changes to the
//! `ff` crate are reflected in `ff_derive`. It also uses the resulting field to test some
//! of the APIs provided by `ff`, such as batch inversion.

#[macro_use]
extern crate ff;

/// The BLS12-381 scalar field.
#[derive(PrimeField)]
#[PrimeFieldModulus = "52435875175126190479447740508185965837690552500527637822603658699938581184513"]
#[PrimeFieldGenerator = "7"]
#[PrimeFieldReprEndianness = "little"]
struct Bls381K12Scalar([u64; 4]);

mod fermat {
    /// The largest known Fermat prime, used to test the case `t = 1`.
    #[derive(PrimeField)]
    #[PrimeFieldModulus = "65537"]
    #[PrimeFieldGenerator = "3"]
    #[PrimeFieldReprEndianness = "little"]
    struct Fermat65537Field([u64; 1]);
}

mod full_limbs {
    #[derive(PrimeField)]
    #[PrimeFieldModulus = "39402006196394479212279040100143613805079739270465446667948293404245721771496870329047266088258938001861606973112319"]
    #[PrimeFieldGenerator = "19"]
    #[PrimeFieldReprEndianness = "little"]
    struct F384p([u64; 7]);

    #[test]
    fn random_masking_does_not_overflow() {
        use ff::Field;
        use rand::rngs::OsRng;

        let _ = F384p::random(OsRng);
    }
}

#[test]
fn constants() {
    use ff::{Field, PrimeField};

    assert_eq!(
        Bls381K12Scalar::MODULUS,
        "0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001",
    );

    assert_eq!(
        Bls381K12Scalar::from(2) * Bls381K12Scalar::TWO_INV,
        Bls381K12Scalar::ONE,
    );

    assert_eq!(
        Bls381K12Scalar::ROOT_OF_UNITY * Bls381K12Scalar::ROOT_OF_UNITY_INV,
        Bls381K12Scalar::ONE,
    );

    // ROOT_OF_UNITY^{2^s} mod m == 1
    assert_eq!(
        Bls381K12Scalar::ROOT_OF_UNITY.pow(&[1u64 << Bls381K12Scalar::S, 0, 0, 0]),
        Bls381K12Scalar::ONE,
    );

    // DELTA^{t} mod m == 1
    assert_eq!(
        Bls381K12Scalar::DELTA.pow(&[
            0xfffe5bfeffffffff,
            0x09a1d80553bda402,
            0x299d7d483339d808,
            0x73eda753,
        ]),
        Bls381K12Scalar::ONE,
    );
}

#[test]
fn from_u128() {
    use ff::{Field, PrimeField};

    assert_eq!(Bls381K12Scalar::from_u128(1), Bls381K12Scalar::ONE);
    assert_eq!(Bls381K12Scalar::from_u128(2), Bls381K12Scalar::from(2));
    assert_eq!(
        Bls381K12Scalar::from_u128(u128::MAX),
        Bls381K12Scalar::from_str_vartime("340282366920938463463374607431768211455").unwrap(),
    );
}

#[test]
fn batch_inversion() {
    use ff::{BatchInverter, Field};

    let one = Bls381K12Scalar::ONE;

    // [1, 2, 3, 4]
    let values: Vec<_> = (0..4)
        .scan(one, |acc, _| {
            let ret = *acc;
            *acc += &one;
            Some(ret)
        })
        .collect();

    // Test BatchInverter::invert_with_external_scratch
    {
        let mut elements = values.clone();
        let mut scratch_space = vec![Bls381K12Scalar::ZERO; elements.len()];
        BatchInverter::invert_with_external_scratch(&mut elements, &mut scratch_space);
        for (a, a_inv) in values.iter().zip(elements.into_iter()) {
            assert_eq!(*a * a_inv, one);
        }
    }

    // Test BatchInverter::invert_with_internal_scratch
    {
        let mut items: Vec<_> = values.iter().cloned().map(|p| (p, one)).collect();
        BatchInverter::invert_with_internal_scratch(
            &mut items,
            |item| &mut item.0,
            |item| &mut item.1,
        );
        for (a, (a_inv, _)) in values.iter().zip(items.into_iter()) {
            assert_eq!(*a * a_inv, one);
        }
    }

    // Test BatchInvert trait
    #[cfg(feature = "alloc")]
    {
        use ff::BatchInvert;
        let mut elements = values.clone();
        elements.iter_mut().batch_invert();
        for (a, a_inv) in values.iter().zip(elements.into_iter()) {
            assert_eq!(*a * a_inv, one);
        }
    }
}