# C/C++ API

## Minimum sample

A sample demonstrating BLS12-381 usage:

### C
[sample/pairing_c.c](sample/pairing_c.c)

```bash
cd mcl
make -j4
make bin/pairing_c.exe && bin/pairing_c.exe
```

### C++
[sample/pairing.cpp](sample/pairing.cpp)

```bash
cd mcl
make -j4
make bin/pairing.exe && bin/pairing.exe
```

## Header and libraries

### C
To use BLS12-381, include `<mcl/bn_c384_256.h>` and link `libmcl.{a,so}`.

`384_256` indicates that the maximum bit size of `Fp` is 384, and the size of `Fr` is 256.

### C++
Include `<mcl/bls12_381.hpp>` and link `libmcl.{a,so}`.

## Notation

The elliptic curve equation is `E: y^2 = x^3 + b`.

- `Fp` : a finite field of prime order `p`, over which the curve is defined.
- `Fr` : a finite field of prime order `r`.
- `Fp2` : field extension over Fp of degree 2. Fp[i] / (i^2 + u).
- `Fp6` : field extension over Fp2 of degree 3. Fp2[v] / (v^3 - Xi) where Xi = i + xi_a.
- `Fp12` : field extension over Fp6 of degree 2. Fp6[w] / (w^2 - v).
- `G1` : the cyclic subgroup of E(Fp).
- `G2` : the cyclic subgroup of the inverse image of E'(Fp^2) under a twisting isomorphism from E' to E.
- `GT` : the cyclic subgroup of Fp12.
  - `G1`, `G2`, and `GT` have the order `r`.

The pairing e: G1 x G2 -> GT is the optimal ate pairing.

mcl treats `G1` and `G2` as additive groups and `GT` as a multiplicative group.

- `mclSize` ; `unsigned int` if WebAssembly, otherwise `size_t`

### Curve Parameters
r = |G1| = |G2| = |GT|

curveType   | b|u|xi_a| r and p |
------------|-|-|-|------------------|
BN254       | 2|1|1|r = 0x2523648240000001ba344d8000000007ff9f800000000010a10000000000000d <br> p = 0x2523648240000001ba344d80000000086121000000000013a700000000000013 |
BN_SNARK1|3|1|9|r = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001 <br> p = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47|
BLS12_381   | 4|1|1|r = 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001 <br> p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab |
BLS12_377|1|5|0|r = 0x12ab655e9a2ca55660b44d1e5c37b00159aa76fed00000010a11800000000001 <br> p = 0x1ae3a4617c510eac63b05c06ca1493b1a22d9f300f5138f1ef3622fba094800170b5d44300000008508c00000000001
BN381       | 2|1|1|r = 0x240026400f3d82b2e42de125b00158405b710818ac000007e0042f008e3e00000000001080046200000000000000000d <br> p = 0x240026400f3d82b2e42de125b00158405b710818ac00000840046200950400000000001380052e000000000000000013 |

## C Structures

### `mclBnFp`
This is a struct for `Fp`. The value is stored in Montgomery representation.

### `mclBnFr`
This is a struct for `Fr`. The value is stored in Montgomery representation.

### `mclBnFp2`
This is a struct for `Fp2` with a member `mclBnFp d[2]`.

An element `x` of `Fp2` is represented as `x = d[0] + d[1] i` where `i^2 = -1`.

### `mclBnG1`
This is a struct for `G1` with three members `x`, `y`, `z` of type `mclBnFp`.

An element `P` of `G1` is represented as `P = [x:y:z]` in Jacobian coordinates.

### `mclBnG2`
This is a struct for `G2` with three members `x`, `y`, `z` of type `mclBnFp2`.

An element `Q` of `G2` is represented as `Q = [x:y:z]` in Jacobian coordinates.

### `mclBnGT`

This is a struct for `GT` with a member `mclBnFp d[12]`.

## C++ Structures

The namespace is `mcl`.

### `Fp`
This is a class for `Fp`.

### `Fr`
This is a class for `Fr`.

### `Fp2`
This is a struct for `Fp2` with members `a` and `b` of type `Fp`.

An element `x` of `Fp2` is represented as `x = a + b i` where `i^2 = -1`.

### `Fp6`
This is a struct for `Fp6` with members `a`, `b`, and `c` of type `Fp2`.

An element `x` of `Fp6` is represented as `x = a + b v + c v^2` where `v^3 = xi := 1 + i`.

### `Fp12`
This is a struct for `Fp12` with members `a` and `b` of type `Fp6`.

An element `x` of `Fp12` is represented as `x = a + b w` where `w^2 = v`.

### `G1`
This is a struct for `G1` with three members `x`, `y`, `z` of type `Fp`.

An element `P` of `G1` is represented as `P = [x:y:z]` in Jacobian coordinates.

### `G2`
This is a struct for `G2` with three members `x`, `y`, `z` of type `Fp2`.

An element `Q` of `G2` is represented as `Q = [x:y:z]` in Jacobian coordinates.

### `GT`

`GT` is an alias for `Fp12`.
However, it represents the set `{ x in Fp12 | x^r = 1}`.

### Parameter Settings and Supported Curves
By default, `MCL_FP_BIT=384` and `MCL_FR_BIT=256` are set.
If you want to change these values, use commands such as `make MCL_FP_BIT=256 MCL_FR_BIT=256`.

MCL_FP_BIT|MCL_FR_BIT|sizeof Fr|sizeof Fp|supported curves
-|-|-|-|-
256|256|32|32|MCL_BN254, MCL_BN_SNARK1
384|256|48|32|+MCL_BLS12_381, MCL_BLS12_377
384|384|48|48|+MCL_BN381_1

## Thread safety
All functions except initialization and global setting changes are thread-safe.

## Initialization

### C

Initialize the mcl library. Call this function first before calling other functions.

```c
int mclBn_init(int curve, int compiledTimeVar);
```

- `curve` ; specify the curve type
- `compiledTimeVar` ; set `MCLBN_COMPILED_TIME_VAR`, a macro used to ensure that
the values are consistent between library build time and usage.
- return 0 on success.
- This is not thread safe.

### C++

```c
void initPairing(<curve type>);
```
curve type is defined in `mcl/curve_type.h`.
- BN254
- BN_SNARK1
- BLS12_381
- BLS12_377
- BN381_1

## Global setting

```c
int mclBn_setMapToMode(int mode);
```
- `mode = MCL_MAP_TO_MODE_ORIGINAL` : the old hash-to-curve (for backward compatibility)
- `mode = MCL_MAP_TO_MODE_HASH_TO_CURVE` : the hash-to-curve defined in [Hashing to Elliptic Curves](https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/)

### Control to verify that a point of the elliptic curve has the order `r`.

This function affects `setStr()` and `deserialize()` for G1/G2.

### C
```c
void mclBn_verifyOrderG1(int doVerify);
void mclBn_verifyOrderG2(int doVerify);
```

### C++
```cpp
verifyOrderG1(bool doVerify);
verifyOrderG2(bool doVerify);
```

- verify if `doVerify` is 1, otherwise do not verify. The default parameter is 0 because verification has significant computational cost.
- Set `doVerify = 1` if considering subgroup attack is necessary.
- This is not thread-safe.

### Set DST for hash functions

### C
```c
int mclBnG1_setDst(const char *dst, mclSize dstSize);
int mclBnG2_setDst(const char *dst, mclSize dstSize);
```
return 0 if success else -1

### C++
```cpp
bool setDstG1(const char *dst, size_t dstSize);
bool setDstG2(const char *dst, size_t dstSize);
```
return true if success else false

- set `dst[0, dstSize)` to the DST for hash functions
- The default value:
  - G1 : `BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_POP_`
  - G2 : `BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_`

## Setter / Getter

### Clear
Set `x` to zero.
```cpp
void mclBnFr_clear(mclBnFr *x);
void mclBnFp_clear(mclBnFp *x);
void mclBnFp2_clear(mclBnFp2 *x);
void mclBnG1_clear(mclBnG1 *x);
void mclBnG2_clear(mclBnG2 *x);
void mclBnGT_clear(mclBnGT *x);
```

C++
```c
T::clear();
```

### Set `x` to `y`.
```c
void mclBnFp_setInt(mclBnFp *y, mclInt x);
void mclBnFr_setInt(mclBnFr *y, mclInt x);
void mclBnGT_setInt(mclBnGT *y, mclInt x);
```

C++
```cpp
T x = <integer literal>;
```

### Set `bufSize` bytes from `buf` to `x` with masking according to the following method.
```c
int mclBnFp_setLittleEndian(mclBnFp *x, const void *buf, mclSize bufSize);
int mclBnFr_setLittleEndian(mclBnFr *x, const void *buf, mclSize bufSize);
```

C++
```cpp
T::setArrayMask(const uint8_t *buf, size_t n);
```

1. set x = buf[0..bufSize-1] as little endian
2. x &= (1 << bitLen(r)) - 1
3. if (x >= r), then x &= (1 << (bitLen(r) - 1)) - 1

- always returns 0

### Set `bufSize` bytes from `buf` modulo `p` or `r` to `x`.
```c
int mclBnFp_setLittleEndianMod(mclBnFp *x, const void *buf, mclSize bufSize);
int mclBnFr_setLittleEndianMod(mclBnFr *x, const void *buf, mclSize bufSize);
```

C++
```cpp
T::setLittleEndianMod(const uint8_t *buf, mclSize bufSize);
```

- return 0 if bufSize <= (sizeof(T) * 2), otherwise -1

### Get little-endian byte sequence in `buf` corresponding to `x`
```c
mclSize mclBnFr_getLittleEndian(void *buf, mclSize maxBufSize, const mclBnFr *x);
mclSize mclBnFp_getLittleEndian(void *buf, mclSize maxBufSize, const mclBnFp *x);
```

C++
```cpp
size_t T::getLittleEndian(uint8_t *buf, size_t maxBufSize) const
```

- write `x` to `buf` in little-endian format
- return the written size on success, otherwise 0
- NOTE: `buf[0] = 0` and return 1 if `x` is zero.

### Serialization
### Serialize
```c
mclSize mclBnFr_serialize(void *buf, mclSize maxBufSize, const mclBnFr *x);
mclSize mclBnG1_serialize(void *buf, mclSize maxBufSize, const mclBnG1 *x);
mclSize mclBnG2_serialize(void *buf, mclSize maxBufSize, const mclBnG2 *x);
mclSize mclBnGT_serialize(void *buf, mclSize maxBufSize, const mclBnGT *x);
mclSize mclBnFp_serialize(void *buf, mclSize maxBufSize, const mclBnFp *x);
mclSize mclBnFp2_serialize(void *buf, mclSize maxBufSize, const mclBnFp2 *x);
```

C++
```cpp
mclSize T::serialize(void *buf, mclSize maxBufSize) const;
```

- serialize `x` into `buf[0..maxBufSize-1]`
- return written byte size on success, otherwise 0

### Serialization Format
- `Fp` (resp. `Fr`) ; a little-endian byte sequence with a fixed size
  - the size is the return value of `mclBn_getFpByteSize()` (resp. `mclBn_getFrByteSize()`).
- `G1` ; compressed with a fixed size
  - the size is equal to `mclBn_getG1ByteSize()` (=`mclBn_getFpByteSize()`).
- `G2` ; compressed with a fixed size
  - the size is equal to `mclBn_getG2ByteSize()`.

A pseudo-code to serialize `P` of `G1` (resp. `G2`):
```python
size = mclBn_getG1ByteSize() # resp. mclBn_getG2ByteSize()
if P is zero:
  return [0] * size
else:
  P = P.normalize()
  s = P.x.serialize()
  # x in Fp2 is odd <=> x.a is odd
  if Fp is fullBit:
    s[byte-length(s)] = P.y is odd ? 3 : 2
  elif P.y is odd: # resp. P.y.d[0] is odd
    s[byte-length(s) - 1] |= 0x80
  return s
```

### Ethereum serialization mode for BLS12-381
```c
void mclBn_setETHserialization(int ETHserialization);
```
- Set `ETHserialization = 1` for Ethereum compatibility (default 0).
- See [FAQ](api.md#faq).

### Deserialize
```c
mclSize mclBnFr_deserialize(mclBnFr *x, const void *buf, mclSize bufSize);
mclSize mclBnG1_deserialize(mclBnG1 *x, const void *buf, mclSize bufSize);
mclSize mclBnG2_deserialize(mclBnG2 *x, const void *buf, mclSize bufSize);
mclSize mclBnGT_deserialize(mclBnGT *x, const void *buf, mclSize bufSize);
mclSize mclBnFp_deserialize(mclBnFp *x, const void *buf, mclSize bufSize);
mclSize mclBnFp2_deserialize(mclBnFp2 *x, const void *buf, mclSize bufSize);
```

C++
```cpp
mclSize T::deserialize(const void *buf, mclSize bufSize);
```

- deserialize `x` from `buf[0..bufSize-1]`
- return read size on success, otherwise 0
  - mclBnG1_deserialize and mclBnG2_deserialize check whether the point has the correct order of G1/G2.
  - mclBnGT_deserialize does not check it. Call mclBnGT_isValid if necessary.

## String conversion
### Get string
```c
mclSize mclBnFr_getStr(char *buf, mclSize maxBufSize, const mclBnFr *x, int ioMode);
mclSize mclBnG1_getStr(char *buf, mclSize maxBufSize, const mclBnG1 *x, int ioMode);
mclSize mclBnG2_getStr(char *buf, mclSize maxBufSize, const mclBnG2 *x, int ioMode);
mclSize mclBnGT_getStr(char *buf, mclSize maxBufSize, const mclBnGT *x, int ioMode);
mclSize mclBnFp_getStr(char *buf, mclSize maxBufSize, const mclBnFp *x, int ioMode);
```

C++
```cpp
size_t T::getStr(char *buf, size_t maxBufSize, int iMode = 0) const
```

- write `x` to `buf` according to `ioMode`
- `ioMode`
  - 2 ; binary number
  - 10 ; decimal number
  - 16 ; hexadecimal number
  - `MCLBN_IO_EC_PROJ` ; output as Jacobi coordinate
- return `strlen(buf)` on success, otherwise 0.

The meaning of the output of `G1`:
- `0` ; infinity
- `1 <x> <y>` ; affine coordinate
- `4 <x> <y> <z>` ; Jacobi coordinate
- the element `<x>` of `G2` outputs `d[0] d[1]`.

### Set string
```c
int mclBnFr_setStr(mclBnFr *x, const char *buf, mclSize bufSize, int ioMode);
int mclBnG1_setStr(mclBnG1 *x, const char *buf, mclSize bufSize, int ioMode);
int mclBnG2_setStr(mclBnG2 *x, const char *buf, mclSize bufSize, int ioMode);
int mclBnGT_setStr(mclBnGT *x, const char *buf, mclSize bufSize, int ioMode);
int mclBnFp_setStr(mclBnFp *x, const char *buf, mclSize bufSize, int ioMode);
```

C++
```cpp
void T::setStr(bool *pb, const char *str, int iMode = 0)
void T::setStr(const char *str, int iMode = 0)
```

- set `buf[0..bufSize-1]` to `x` accoring to `ioMode`
  - mask and truncate the value if it is greater than (r or p).
  - See [masking](api.md#set-buf0bufsize-1-to-x-with-masking-according-to-the-following-way)
- deny too large bufSize. The maximum length depends on compile options, but at least the bit length of the type of x.
- The set string of G1/G2 fails if the point is not on the elliptic curve.
  - And check whether the point has the valid order of G1/G2(default).
  - You can disable this check by `mclBn_verifyOrderG1/G2`(0).
- return 0 if success else -1
  - *pb = result of setStr or throw exception if error (C++)
  - mclBnG1_setStr and mclBnG2_setStr check whether the point has the correct order of G1/G2.
  - mclBnGT_setStr does not check it. Call mclBnGT_isValid if necessary.

If you want to use the same BLS12-381 generator as [zkcrypto](https://www.ietf.org/archive/id/draft-irtf-cfrg-pairing-friendly-curves-11.html#section-4.2.1) then,

```c
mclBnG1 P;
const char *g1Str = "1 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb 0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1";
mclBnG1_setStr(&P, g1Str, strlen(g1Str), 16);

mclBnG2 Q;
const char *g2Str = "1 0x24aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e 0x0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801 0x0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be";
mclBnG2_setStr(&Q, g2Str, strlen(g2Str), 16);
```


## Set a random value
Set `x` by a cryptographically secure pseudo-random number generator.
```c
int mclBnFr_setByCSPRNG(mclBnFr *x);
int mclBnFp_setByCSPRNG(mclBnFp *x);
```
C++
```cpp
void T::setByCSPRNG()
```

### Change random generator function
```c
void mclBn_setRandFunc(
  void *self,
  unsigned int (*readFunc)(void *self, void *buf, unsigned int bufSize)
);
```
- `self` ; user-defined pointer
- `readFunc` ; user-defined function, which writes random `bufSize` bytes to `buf` and returns `bufSize` if success else returns 0.
  - `readFunc` must be thread-safe.
- Set the default random function if `self == 0` and `readFunc == 0`.
- This is not thread-safe.

## Arithmetic operations
### neg / inv / sqr / add / sub / mul / div of `Fr`, `Fp`, `Fp2`, `GT`.
```c
void mclBnFr_neg(mclBnFr *y, const mclBnFr *x);
void mclBnFr_inv(mclBnFr *y, const mclBnFr *x);
// y[i] = 1/x[i] if x[i] != 0 else 0
// faster than normalizing each one individually
void mclBnFr_invVec(mclBnFr *y, const mclBnFr *x, mclSize n);
void mclBnFr_sqr(mclBnFr *y, const mclBnFr *x);
void mclBnFr_add(mclBnFr *z, const mclBnFr *x, const mclBnFr *y);
void mclBnFr_sub(mclBnFr *z, const mclBnFr *x, const mclBnFr *y);
void mclBnFr_mul(mclBnFr *z, const mclBnFr *x, const mclBnFr *y);
void mclBnFr_div(mclBnFr *z, const mclBnFr *x, const mclBnFr *y);

void mclBnFp_neg(mclBnFp *y, const mclBnFp *x);
void mclBnFp_inv(mclBnFp *y, const mclBnFp *x);
void mclBnFp_invVec(mclBnFp *y, const mclBnFp *x, mclSize n);
void mclBnFp_sqr(mclBnFp *y, const mclBnFp *x);
void mclBnFp_add(mclBnFp *z, const mclBnFp *x, const mclBnFp *y);
void mclBnFp_sub(mclBnFp *z, const mclBnFp *x, const mclBnFp *y);
void mclBnFp_mul(mclBnFp *z, const mclBnFp *x, const mclBnFp *y);
void mclBnFp_div(mclBnFp *z, const mclBnFp *x, const mclBnFp *y);

void mclBnFp2_neg(mclBnFp2 *y, const mclBnFp2 *x);
void mclBnFp2_inv(mclBnFp2 *y, const mclBnFp2 *x);
void mclBnFp2_sqr(mclBnFp2 *y, const mclBnFp2 *x);
void mclBnFp2_add(mclBnFp2 *z, const mclBnFp2 *x, const mclBnFp2 *y);
void mclBnFp2_sub(mclBnFp2 *z, const mclBnFp2 *x, const mclBnFp2 *y);
void mclBnFp2_mul(mclBnFp2 *z, const mclBnFp2 *x, const mclBnFp2 *y);
void mclBnFp2_div(mclBnFp2 *z, const mclBnFp2 *x, const mclBnFp2 *y);

void mclBnGT_inv(mclBnGT *y, const mclBnGT *x); // y = a - bw for x = a + bw where Fp12 = Fp6[w]
void mclBnGT_sqr(mclBnGT *y, const mclBnGT *x);
void mclBnGT_mul(mclBnGT *z, const mclBnGT *x, const mclBnGT *y);
void mclBnGT_div(mclBnGT *z, const mclBnGT *x, const mclBnGT *y);
```
- use `mclBnGT_invGeneric` for an element in Fp12 - GT.

- NOTE: The following functions do NOT return a GT element because GT is a multiplicative group.

```c
void mclBnGT_neg(mclBnGT *y, const mclBnGT *x);
void mclBnGT_add(mclBnGT *z, const mclBnGT *x, const mclBnGT *y);
void mclBnGT_sub(mclBnGT *z, const mclBnGT *x, const mclBnGT *y);
```

C++
- `+`, `-`, `*`, `/`
```cpp
T::add(T& z, const T& x, const T& y);
T::sub(T& z, const T& x, const T& y);
T::mul(T& z, const T& x, const T& y);
T::div(T& z, const T& x, const T& y);
T::neg(T& y, const T& x);
T::inv(T& y, const T& x);
// y[i] = 1/x[i] if x[i] != 0 else 0
mcl::invVec(T y[], const T x[], size_t n);
```

### pow of `Fr`, `Fp`
- `pow(z, x, y)` means `z = x^y`.
- `powArray(z, x, y, ySize)` means z = x^y where y is a little endian `ySize`-byte sequence.

```c
// z = x^y
void mclBnFp_pow(mclBnFp *z, const mclBnFp *x, const mclBnFp *y);
void mclBnFr_pow(mclBnFr *z, const mclBnFr *x, const mclBnFr *y);

// return 0 if ySize <= mclBn_getFrByteSize() else -1
int mclBnFr_powArray(mclBnFr *z, const mclBnFr *x, const uint8_t *y, mclSize ySize);
// return 0 if ySize <= mclBn_getFpByteSize() else -1
int mclBnFp_powArray(mclBnFp *z, const mclBnFp *x, const uint8_t *y, mclSize ySize);
```

### Square root of `x`.
```c
int mclBnFr_squareRoot(mclBnFr *y, const mclBnFr *x);
int mclBnFp_squareRoot(mclBnFp *y, const mclBnFp *x);
int mclBnFp2_squareRoot(mclBnFp2 *y, const mclBnFp2 *x);
```
C++
```cpp
bool T::squareRoot(T& y, const T& x);
```

- `y` is one of a square root of `x` if `y` exists.
- return 0 if success else -1

### add / sub / dbl / neg for `G1` and `G2`.
```c
void mclBnG1_neg(mclBnG1 *y, const mclBnG1 *x);
void mclBnG1_dbl(mclBnG1 *y, const mclBnG1 *x);
void mclBnG1_add(mclBnG1 *z, const mclBnG1 *x, const mclBnG1 *y);
void mclBnG1_sub(mclBnG1 *z, const mclBnG1 *x, const mclBnG1 *y);

void mclBnG2_neg(mclBnG2 *y, const mclBnG2 *x);
void mclBnG2_dbl(mclBnG2 *y, const mclBnG2 *x);
void mclBnG2_add(mclBnG2 *z, const mclBnG2 *x, const mclBnG2 *y);
void mclBnG2_sub(mclBnG2 *z, const mclBnG2 *x, const mclBnG2 *y);
```
C++
- `+`, `-`
  - T::add(T& z, const T& x, const T& y);
  - T::sub(T& z, const T& x, const T& y);
  - T::neg(T& y, const T& x);

### Convert a point from Jacobi/Projective coordinate to affine.
```c
void mclBnG1_normalize(mclBnG1 *y, const mclBnG1 *x);
void mclBnG2_normalize(mclBnG2 *y, const mclBnG2 *x);

// y[i] = normalize(x[i]) for i = 0, 1, ..., n-1
// faster than normalizing each one individually
void mclBnG1_normalizeVec(mclBnG1 *y, const mclBnG1 *x, mclSize n);
void mclBnG2_normalizeVec(mclBnG2 *y, const mclBnG2 *x, mclSize n);
```

C++
```cpp
T::normalize(T& y, const T& x);
T::normalizeVec(T& y[n], const T& x[n], size_t n);
```

- convert `[x:y:z]` to `[x:y:1]` if `z != 0` else `[*:*:0]`

### scalar multiplication
```c
void mclBnG1_mul(mclBnG1 *z, const mclBnG1 *x, const mclBnFr *y);
void mclBnG2_mul(mclBnG2 *z, const mclBnG2 *x, const mclBnFr *y);
void mclBnGT_pow(mclBnGT *z, const mclBnGT *x, const mclBnFr *y);
```
C++
```cpp
T::mul(const T& z, const T& x, const Fr& y);
```

- z = x * y for G1 / G2
- z = pow(x, y) for GT

- use `mclBnGT_powGeneric` for an element in Fp12 - GT.

### multi-scalar multiplication
```c
void mclBnG1_mulVec(mclBnG1 *z, mclBnG1 *x, const mclBnFr *y, mclSize n);
void mclBnG2_mulVec(mclBnG2 *z, mclBnG2 *x, const mclBnFr *y, mclSize n);
void mclBnGT_powVec(mclBnGT *z, const mclBnGT *x, const mclBnFr *y, mclSize n);
```
C++
```cpp
T::mulVec(T& z, T* x, const Fr *y, size_t n);
```

- z = sum_{i=0}^{n-1} mul(x[i], y[i]) for G1 / G2.
- z = prod_{i=0}^{n-1} pow(x[i], y[i]) for GT.
- `x[]` does not const because they may be normailzed (The value does not change).

### scalar multiplication of each point
```c
void mclBnG1_mulEach(mclBnG1 *x, const mclBnFr *y, mclSize n);
```
C++
```cpp
G1::mulEach(G1 *xVec, const Fr *yVec, size_t n);
```

- xVec[i] *= yVec[i]
- `G1::mulVec` and `G1::mulEach` for BLS12-381 use AVX-512 IFMA if possible

## hash-to-curve function
### Set hash of `buf[0..bufSize-1]` to `x`
```c
int mclBnFr_setHashOf(mclBnFr *x, const void *buf, mclSize bufSize);
int mclBnFp_setHashOf(mclBnFp *x, const void *buf, mclSize bufSize);
```
C++
```cpp
T::setHashOf(const void *msg, size_t msgSize);
```

- always return 0
- use SHA-256 if sizeof(*x) <= 256 else SHA-512
- set according to the same way as `setLittleEndian`.
- This is a function for backward compatibility only. DO'NT use it. Instead of this, use setLittleEndianMod to the hashed value.

### map `x` to G1 / G2.
```c
int mclBnFp_mapToG1(mclBnG1 *y, const mclBnFp *x);
int mclBnFp2_mapToG2(mclBnG2 *y, const mclBnFp2 *x);
```

C++
```cpp
void mapToG1(G1& P, const Fp& x);
void mapToG2(G2& P, const Fp2& x);
```

- See `struct MapTo` in `mcl/bn.hpp` for the detail of the algorithm.
- return 0 if success else -1

If you want to use the MapTo function defined in [Hashing to Elliptic Curves](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve), then use `mclBn_seMapToMode`.

```c
mclBn_setMapToMode(MCL_MAP_TO_MODE_HASH_TO_CURVE);
```
And if you want to change DST (domain separation tag), then use `setDst` functions.

```c
int mclBnG1_setDst(const char *dst, mclSize dstSize);
int mclBnG2_setDst(const char *dst, mclSize dstSize);
```

### hash and map to G1 / G2.
```c
int mclBnG1_hashAndMapTo(mclBnG1 *x, const void *buf, mclSize bufSize);
int mclBnG2_hashAndMapTo(mclBnG2 *x, const void *buf, mclSize bufSize);
```

C++
```cpp
void hashAndMapToG1(G1& P, const void *buf, size_t bufSize);
void hashAndMapToG2(G2& P, const void *buf, size_t bufSize);
```
- Combine `setHashOf` and `mapTo` functions

## Pairing operations
The pairing function `e(P, Q)` is consist of two parts:
  - `MillerLoop(P, Q)`
  - `finalExp(x)`

`finalExp` satisfies the following properties:
  - `e(P, Q) = finalExp(MillerLoop(P, Q))`
  - `e(P1, Q1) e(P2, Q2) = finalExp(MillerLoop(P1, Q1) MillerLoop(P2, Q2))`

### pairing
```c
void mclBn_pairing(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y);
```
C++
```cpp
void pairing(GT& z, const G1& x, const G2& y);
```

### millerLoop
```c
void mclBn_millerLoop(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y);
```
C++
```cpp
void millerLoop(GT& z, const G1& x, const G2& y);
```
### finalExp
```c
void mclBn_finalExp(mclBnGT *y, const mclBnGT *x);
```
C++
```cpp
void finalExp(GT& y, const GT& x);
```

## Variants of MillerLoop
### multi pairing
```c
void mclBn_millerLoopVec(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y, mclSize n);
```
C++
```cpp
void millerLoopVec(GT& z, const G1 *x, const G2 *y, size_t n);
```
- This function is for multi-pairing
  - computes prod_{i=0}^{n-1} MillerLoop(x[i], y[i])
  - prod_{i=0}^{n-1} e(x[i], y[i]) = finalExp(prod_{i=0}^{n-1} MillerLoop(x[i], y[i]))

### pairing for a fixed point of G2
```c
int mclBn_getUint64NumToPrecompute(void);
void mclBn_precomputeG2(uint64_t *Qbuf, const mclBnG2 *Q);
void mclBn_precomputedMillerLoop(mclBnGT *f, const mclBnG1 *P, const uint64_t *Qbuf);
```
These functions is the same computation of `pairing(P, Q);` as the followings:
```c
uint64_t *Qbuf = (uint64_t*)malloc(mclBn_getUint64NumToPrecompute() * sizeof(uint64_t));
mclBn_precomputeG2(Qbuf, Q); // precomputing of Q
mclBn_precomputedMillerLoop(f, P, Qbuf); // pairing of any P of G1 and the fixed Q
free(p);
```

```c
void mclBn_precomputedMillerLoop2(
  mclBnGT *f,
  const mclBnG1 *P1, const uint64_t *Q1buf,
  const mclBnG1 *P2, const uint64_t *Q2buf
);
```
- compute `MillerLoop(P1, Q1buf) * MillerLoop(P2, Q2buf)`


```c
void mclBn_precomputedMillerLoop2mixed(
  mclBnGT *f,
  const mclBnG1 *P1, const mclBnG2 *Q1,
  const mclBnG1 *P2, const uint64_t *Q2buf
);
```
- compute `MillerLoop(P1, Q2) * MillerLoop(P2, Q2buf)`

## Check value
### Check validness
```c
int mclBnFr_isValid(const mclBnFr *x);
int mclBnFp_isValid(const mclBnFp *x);
int mclBnG1_isValid(const mclBnG1 *x);
int mclBnG2_isValid(const mclBnG2 *x);
```
C++
```cpp
bool T::isValid() const;
```
- return 1 if true else 0

### Check the order of a point
```c
int mclBnG1_isValidOrder(const mclBnG1 *x);
int mclBnG2_isValidOrder(const mclBnG2 *x);
```
C++
```cpp
bool T::isValidOrder() const;
```

- Check whether the order of `x` is valid or not
- return 1 if true else 0
- This function always checks according to `mclBn_verifyOrderG1` and `mclBn_verifyOrderG2`.

### Is equal / zero / one / isOdd
```c
int mclBnFr_isEqual(const mclBnFr *x, const mclBnFr *y);
int mclBnFr_isZero(const mclBnFr *x);
int mclBnFr_isOne(const mclBnFr *x);
int mclBnFr_isOdd(const mclBnFr *x);

int mclBnFp_isEqual(const mclBnFp *x, const mclBnFp *y);
int mclBnFp_isZero(const mclBnFp *x);
int mclBnFp_isOne(const mclBnFp *x);
int mclBnFp_isOdd(const mclBnFp *x);

int mclBnFp2_isEqual(const mclBnFp2 *x, const mclBnFp2 *y);
int mclBnFp2_isZero(const mclBnFp2 *x);
int mclBnFp2_isOne(const mclBnFp2 *x);

int mclBnG1_isEqual(const mclBnG1 *x, const mclBnG1 *y);
int mclBnG1_isZero(const mclBnG1 *x);

int mclBnG2_isEqual(const mclBnG2 *x, const mclBnG2 *y);
int mclBnG2_isZero(const mclBnG2 *x);

int mclBnGT_isEqual(const mclBnGT *x, const mclBnGT *y);
int mclBnGT_isZero(const mclBnGT *x);
int mclBnGT_isOne(const mclBnGT *x);
```
C++
```cpp
bool T::operator==(const T& rhs) const;
bool T::isZero() const;
bool T::isOne() const;
```

- return 1 (true) if true else 0 (false)

### isNegative
```c
int mclBnFr_isNegative(const mclBnFr *x);
int mclBnFp_isNegative(const mclBnFr *x);
```
return 1 if x >= half where half = (r + 1) / 2 (resp. (p + 1) / 2).

## Lagrange interpolation

```c
int mclBn_FrLagrangeInterpolation(mclBnFr *out, const mclBnFr *xVec, const mclBnFr *yVec, mclSize k);
int mclBn_G1LagrangeInterpolation(mclBnG1 *out, const mclBnFr *xVec, const mclBnG1 *yVec, mclSize k);
int mclBn_G2LagrangeInterpolation(mclBnG2 *out, const mclBnFr *xVec, const mclBnG2 *yVec, mclSize k);
```
- Lagrange interpolation
- recover out = y(0) from {(xVec[i], yVec[i])} for {i=0..k-1}
- return 0 if success else -1
  - satisfy that xVec[i] != 0, xVec[i] != xVec[j] for i != j

```c
int mclBn_FrEvaluatePolynomial(mclBnFr *out, const mclBnFr *cVec, mclSize cSize, const mclBnFr *x);
int mclBn_G1EvaluatePolynomial(mclBnG1 *out, const mclBnG1 *cVec, mclSize cSize, const mclBnFr *x);
int mclBn_G2EvaluatePolynomial(mclBnG2 *out, const mclBnG2 *cVec, mclSize cSize, const mclBnFr *x);
```
- Evaluate polynomial
- out = f(x) = c[0] + c[1] * x + ... + c[cSize - 1] * x^{cSize - 1}
- return 0 if success else -1
  - satisfy cSize >= 1

## FAQ
### Why the value set by Fp::setStr is different?
The value set by Fp::setStr is masked and truncated if it is greater than p (resp. r).
See [Set string](api.md#set-string)

### What parameters of configuration are for Ethereum?
mcl supports various mode of hash-to-curve function, serialize/deserialize and getStr/setStr
for historical reasons and backwards compatibility.

If using BLS12-381 and Ethereum compatibility mode, set
```cpp
// C++
Fp::setETHserialization(true);
Fr::setETHserialization(true);
bn::setMapToMode(MCL_MAP_TO_MODE_HASH_TO_CURVE);
```
or
```c
// C
mclBn_setETHserialization(1);
mclBn_setMapToMode(MCL_MAP_TO_MODE_HASH_TO_CURVE);
```
and use
```cpp
// C++
void Fp::setBigEndianMod(const uint8_t *x, size_t bufSize);
size_t T::serialize(void *buf, size_t maxBufSize) const
size_t T::deserialize(const void *buf, size_t bufSize);
```
or
```
// C
int mclBnFp_setBigEndianMod(mclBnFp *x, const void *buf, mclSize bufSize);
mclSize mclBnFp_serialize(void *buf, mclSize maxBufSize, const mclBnFp *x);
mclSize mclBnFp_deserialize(mclBnFp *x, const void *buf, mclSize bufSize);
```

Serialization of Fp/Fr
- Fp
  - 48 bytes data in big-endian format
- Fr
  - 32 bytes data in big-endian format
- G1
  - zero : `[0xc0 : (47 bytes zero)]`
  - (x, y) : `d = [48 bytes x]` and `d[0] |= 0x20` if `y < (p+1)/2`.
- G2
  - zero : `[0xc0 : (95 bytes zero)]`
  - (x, y) : `d = [96 bytes x]` and `d[0] |= 0x20` if `b < (p+1)/2` where `y=a+bi`.

See [Point Serialization Procedure](https://www.ietf.org/archive/id/draft-irtf-cfrg-pairing-friendly-curves-08.html#name-point-serialization-procedu) for details.
