[bls12-381-syscall] Add solana-bls12-381-syscall crate (#11)

* add `bls12-381-syscall` crate

* add benchmark check in the CI

* cargo fmt

* remove 16 pair bench since the maximum bound is set to 8
This commit is contained in:
Sam Kim 2026-04-22 09:33:15 +09:00 committed by GitHub
parent 1384fe1040
commit 77b39b268d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 2840 additions and 100 deletions

View file

@ -32,6 +32,9 @@ jobs:
- name: Check formatting
run: cargo fmt --all -- --check
- name: Check benchmarks compile
run: cargo bench --workspace --all-targets --no-run
- name: Lint
run: cargo clippy --workspace --all-targets -- -D warnings

272
Cargo.lock generated
View file

@ -2,17 +2,6 @@
# It is not intended for manual editing.
version = 4
[[package]]
name = "addchain"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e33f6a175ec6a9e0aca777567f9ff7c3deefc255660df887e7fa3585e9801d8"
dependencies = [
"num-bigint 0.3.3",
"num-integer",
"num-traits",
]
[[package]]
name = "aho-corasick"
version = "1.1.4"
@ -118,12 +107,63 @@ dependencies = [
"hybrid-array",
]
[[package]]
name = "blst"
version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcdb4c7013139a150f9fc55d123186dbfaba0d912817466282c73ac49e71fb45"
dependencies = [
"cc",
"glob",
"threadpool",
"zeroize",
]
[[package]]
name = "blstrs"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a8a8ed6fefbeef4a8c7b460e4110e12c5e22a5b7cf32621aae6ad650c4dcf29"
dependencies = [
"blst",
"byte-slice-cast",
"ff",
"group",
"pairing",
"rand_core 0.6.4",
"serde",
"subtle",
]
[[package]]
name = "bumpalo"
version = "3.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb"
[[package]]
name = "byte-slice-cast"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d"
[[package]]
name = "bytemuck"
version = "1.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec"
[[package]]
name = "bytemuck_derive"
version = "1.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "cast"
version = "0.3.0"
@ -343,7 +383,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.117",
"syn",
]
[[package]]
@ -419,7 +459,7 @@ dependencies = [
"p3-merkle-tree",
"p3-symmetric",
"p3-uni-stark",
"rand 0.9.2",
"rand 0.9.4",
"serde",
"sha2 0.11.0",
"solana-ed25519",
@ -470,6 +510,17 @@ version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6"
[[package]]
name = "ff"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393"
dependencies = [
"bitvec",
"rand_core 0.6.4",
"subtle",
]
[[package]]
name = "fiat-crypto"
version = "0.2.9"
@ -553,6 +604,25 @@ dependencies = [
"wasip3",
]
[[package]]
name = "glob"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
[[package]]
name = "group"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63"
dependencies = [
"ff",
"rand 0.8.6",
"rand_core 0.6.4",
"rand_xorshift 0.3.0",
"subtle",
]
[[package]]
name = "half"
version = "2.7.1"
@ -604,6 +674,12 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "hex-literal"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e712f64ec3850b98572bffac52e2c6f282b29fe6c5fa6d42334b30be438d95c1"
[[package]]
name = "home"
version = "0.5.12"
@ -730,17 +806,6 @@ version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
[[package]]
name = "num-bigint"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-bigint"
version = "0.4.6"
@ -769,6 +834,16 @@ dependencies = [
"autocfg",
]
[[package]]
name = "num_cpus"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "once_cell"
version = "1.21.4"
@ -842,11 +917,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ebfdb6ef992ae64e9e8f449ac46516ffa584f11afbdf9ee244288c2a633cdf4"
dependencies = [
"itertools 0.14.0",
"num-bigint 0.4.6",
"num-bigint",
"p3-maybe-rayon",
"p3-util",
"paste",
"rand 0.9.2",
"rand 0.9.4",
"serde",
"tracing",
]
@ -866,7 +941,7 @@ dependencies = [
"p3-matrix",
"p3-maybe-rayon",
"p3-util",
"rand 0.9.2",
"rand 0.9.4",
"serde",
"thiserror",
"tracing",
@ -907,7 +982,7 @@ dependencies = [
"p3-monty-31",
"p3-poseidon2",
"p3-symmetric",
"rand 0.9.2",
"rand 0.9.4",
]
[[package]]
@ -920,7 +995,7 @@ dependencies = [
"p3-field",
"p3-maybe-rayon",
"p3-util",
"rand 0.9.2",
"rand 0.9.4",
"serde",
"tracing",
"transpose",
@ -945,7 +1020,7 @@ dependencies = [
"p3-field",
"p3-symmetric",
"p3-util",
"rand 0.9.2",
"rand 0.9.4",
]
[[package]]
@ -961,7 +1036,7 @@ dependencies = [
"p3-maybe-rayon",
"p3-symmetric",
"p3-util",
"rand 0.9.2",
"rand 0.9.4",
"serde",
"thiserror",
"tracing",
@ -974,7 +1049,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57a981d60da3d8cbf8561014e2c186068578405fd69098fa75b43d4afb364a47"
dependencies = [
"itertools 0.14.0",
"num-bigint 0.4.6",
"num-bigint",
"p3-dft",
"p3-field",
"p3-matrix",
@ -984,7 +1059,7 @@ dependencies = [
"p3-symmetric",
"p3-util",
"paste",
"rand 0.9.2",
"rand 0.9.4",
"serde",
"spin",
"tracing",
@ -1001,7 +1076,7 @@ dependencies = [
"p3-mds",
"p3-symmetric",
"p3-util",
"rand 0.9.2",
"rand 0.9.4",
]
[[package]]
@ -1044,6 +1119,15 @@ dependencies = [
"serde",
]
[[package]]
name = "pairing"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81fec4625e73cf41ef4bb6846cafa6d44736525f442ba45e407c4a000a13996f"
dependencies = [
"group",
]
[[package]]
name = "paste"
version = "1.0.15"
@ -1119,7 +1203,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
dependencies = [
"proc-macro2",
"syn 2.0.117",
"syn",
]
[[package]]
@ -1141,9 +1225,9 @@ dependencies = [
"bit-vec",
"bitflags",
"num-traits",
"rand 0.9.2",
"rand 0.9.4",
"rand_chacha",
"rand_xorshift",
"rand_xorshift 0.4.0",
"regex-syntax",
"rusty-fork",
"tempfile",
@ -1185,9 +1269,18 @@ checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
[[package]]
name = "rand"
version = "0.9.2"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a"
dependencies = [
"rand_core 0.6.4",
]
[[package]]
name = "rand"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea"
dependencies = [
"rand_chacha",
"rand_core 0.9.5",
@ -1238,6 +1331,15 @@ version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba"
[[package]]
name = "rand_xorshift"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f"
dependencies = [
"rand_core 0.6.4",
]
[[package]]
name = "rand_xorshift"
version = "0.4.0"
@ -1305,44 +1407,6 @@ dependencies = [
"semver",
]
[[package]]
name = "rustcrypto-ff"
version = "0.14.0-pre.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa9cd37111549306f79b09aa2618e15b1e8241b7178c286821e3dd71579db4db"
dependencies = [
"bitvec",
"rand_core 0.10.0",
"rustcrypto-ff_derive",
"subtle",
]
[[package]]
name = "rustcrypto-ff_derive"
version = "0.14.0-pre.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2aef88cb4ddb3b1c83beff963f9197607dac780cc39a09f19c041dacbb0b6a5"
dependencies = [
"addchain",
"num-bigint 0.3.3",
"num-integer",
"num-traits",
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "rustcrypto-group"
version = "0.14.0-pre.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e394cd734b5f97dfc3484fa42aad7acd912961c2bcd96c99aa05b3d6cab7cafd"
dependencies = [
"rand_core 0.10.0",
"rustcrypto-ff",
"subtle",
]
[[package]]
name = "rustix"
version = "0.38.44"
@ -1435,7 +1499,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.117",
"syn",
]
[[package]]
@ -1488,6 +1552,20 @@ dependencies = [
"rand_core 0.6.4",
]
[[package]]
name = "solana-bls12-381-syscall"
version = "0.1.0"
dependencies = [
"blst",
"blstrs",
"bytemuck",
"bytemuck_derive",
"criterion",
"group",
"hex-literal",
"pairing",
]
[[package]]
name = "solana-curve25519-cuda"
version = "0.1.0"
@ -1513,6 +1591,8 @@ dependencies = [
"ed25519",
"ed25519-dalek",
"ed25519-zebra",
"ff",
"group",
"hashbrown 0.15.5",
"hex",
"pkcs8",
@ -1520,8 +1600,6 @@ dependencies = [
"rand 0.10.0",
"rand_core 0.10.0",
"rustc_version",
"rustcrypto-ff",
"rustcrypto-group",
"serde",
"sha2 0.11.0",
"subtle",
@ -1559,17 +1637,6 @@ version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.117"
@ -1617,7 +1684,16 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.117",
"syn",
]
[[package]]
name = "threadpool"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa"
dependencies = [
"num_cpus",
]
[[package]]
@ -1658,7 +1734,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.117",
"syn",
]
[[package]]
@ -1782,7 +1858,7 @@ dependencies = [
"bumpalo",
"proc-macro2",
"quote",
"syn 2.0.117",
"syn",
"wasm-bindgen-shared",
]
@ -1978,7 +2054,7 @@ dependencies = [
"heck",
"indexmap",
"prettyplease",
"syn 2.0.117",
"syn",
"wasm-metadata",
"wit-bindgen-core",
"wit-component",
@ -1994,7 +2070,7 @@ dependencies = [
"prettyplease",
"proc-macro2",
"quote",
"syn 2.0.117",
"syn",
"wit-bindgen-core",
"wit-bindgen-rust",
]
@ -2062,7 +2138,7 @@ checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.117",
"syn",
]
[[package]]
@ -2082,7 +2158,7 @@ checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.117",
"syn",
]
[[package]]

View file

@ -3,11 +3,16 @@ members = [
"curve25519/curve25519-cuda",
"curve25519/solana-ed25519",
"experimental/ed25519-pokos",
"syscall/bls12-381-syscall",
]
resolver = "2"
[workspace.dependencies]
bincode = "1"
blst = "0.3.16"
blstrs = "0.7.1"
bytemuck = "1.25.0"
bytemuck_derive = "1.10.2"
cc = "1.0"
cfg-if = "1"
criterion = { version = "0.5", features = ["html_reports"] }
@ -19,10 +24,12 @@ digest = { version = "0.11.0-rc.4", default-features = false, features = ["block
ed25519 = { version = "2.2.3", default-features = false }
ed25519-dalek = "2.2.0"
ed25519-zebra = "4.2.0"
ff = { version = "=0.14.0-pre.0", package = "rustcrypto-ff", default-features = false }
group = { version = "=0.14.0-pre.0", package = "rustcrypto-group", default-features = false }
ff = { version = "0.13.0", default-features = false }
group = { version = "0.13.0", default-features = false }
hashbrown = "0.15"
hex = "0.4.2"
hex-literal = "1.1.0"
pairing = "0.23.0"
pkcs8 = { version = "0.10.1", features = ["pem"] }
proptest = "1"
rand = "0.10.0-rc.5"

View file

@ -0,0 +1,29 @@
[package]
name = "solana-bls12-381-syscall"
description = "Solana BLS12-381 Syscall"
documentation = "https://docs.rs/solana-bls12-381-syscall"
version = "0.1.0"
authors = ["Anza Maintainers <maintainers@anza.xyz>"]
repository = "https://github.com/anza-xyz/cryptography"
homepage = "https://anza.xyz/"
license = "Apache-2.0"
edition = "2024"
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
blst = { workspace = true }
blstrs = { workspace = true }
bytemuck = { workspace = true, features = ["min_const_generics"] }
bytemuck_derive = { workspace = true }
group = "0.13.0"
pairing = { workspace = true }
[dev-dependencies]
criterion = { workspace = true }
hex-literal = { workspace = true }
[[bench]]
name = "bench_main"
harness = false

View file

@ -0,0 +1,183 @@
#![allow(deprecated)]
mod test_vectors;
use {
bytemuck::pod_read_unaligned,
criterion::{BenchmarkId, Criterion, criterion_group, criterion_main},
solana_bls12_381_syscall::*,
test_vectors::*,
};
// Helper to construct pairing batches by repeating the single-pair test vector
fn build_pairing_input<const N: usize>(one_pair_vec: &[u8]) -> ([PodG1Point; N], [PodG2Point; N]) {
// ONE_PAIR vector is structured as [G1 (96) | G2 (192)]
let g1_bytes = &one_pair_vec[0..96];
let g2_bytes = &one_pair_vec[96..288];
let p1: PodG1Point = pod_read_unaligned(g1_bytes);
let p2: PodG2Point = pod_read_unaligned(g2_bytes);
let g1_arr = [p1; N];
let g2_arr = [p2; N];
(g1_arr, g2_arr)
}
fn bench_g1_ops(c: &mut Criterion) {
let mut group = c.benchmark_group("G1 Operations");
for endianness in [Endianness::BE, Endianness::LE] {
let label = match endianness {
Endianness::BE => "BE",
Endianness::LE => "LE",
};
// Select static vectors based on endianness
let (add_input, sub_input, mul_input, decompress_input, validate_input) = match endianness {
Endianness::BE => (
INPUT_BE_G1_ADD_WORST_CASE,
INPUT_BE_G1_SUB_WORST_CASE,
INPUT_BE_G1_MUL_WORST_CASE,
INPUT_BE_G1_DECOMPRESS_WORST_CASE,
INPUT_BE_G1_VALIDATE_WORST_CASE,
),
Endianness::LE => (
INPUT_LE_G1_ADD_WORST_CASE,
INPUT_LE_G1_SUB_WORST_CASE,
INPUT_LE_G1_MUL_WORST_CASE,
INPUT_LE_G1_DECOMPRESS_WORST_CASE,
INPUT_LE_G1_VALIDATE_WORST_CASE,
),
};
group.bench_function(BenchmarkId::new("Addition", label), |b| {
let (p1_bytes, p2_bytes) = add_input.split_at(96);
let p1: PodG1Point = pod_read_unaligned(p1_bytes);
let p2: PodG1Point = pod_read_unaligned(p2_bytes);
b.iter(|| bls12_381_g1_addition_unchecked(Version::V0, &p1, &p2, endianness).unwrap())
});
group.bench_function(BenchmarkId::new("Subtraction", label), |b| {
let (p1_bytes, p2_bytes) = sub_input.split_at(96);
let p1: PodG1Point = pod_read_unaligned(p1_bytes);
let p2: PodG1Point = pod_read_unaligned(p2_bytes);
b.iter(|| {
bls12_381_g1_subtraction_unchecked(Version::V0, &p1, &p2, endianness).unwrap()
})
});
group.bench_function(BenchmarkId::new("Multiplication", label), |b| {
let (point_bytes, scalar_bytes) = mul_input.split_at(96);
let point: PodG1Point = pod_read_unaligned(point_bytes);
let scalar: PodScalar = pod_read_unaligned(scalar_bytes);
b.iter(|| {
bls12_381_g1_multiplication(Version::V0, &point, &scalar, endianness).unwrap()
})
});
group.bench_function(BenchmarkId::new("Decompression", label), |b| {
let input: PodG1Compressed = pod_read_unaligned(decompress_input);
b.iter(|| bls12_381_g1_decompress(Version::V0, &input, endianness).unwrap())
});
group.bench_function(BenchmarkId::new("Validation", label), |b| {
let input: PodG1Point = pod_read_unaligned(validate_input);
b.iter(|| bls12_381_g1_point_validation(Version::V0, &input, endianness))
});
}
group.finish();
}
fn bench_g2_ops(c: &mut Criterion) {
let mut group = c.benchmark_group("G2 Operations");
for endianness in [Endianness::BE, Endianness::LE] {
let label = match endianness {
Endianness::BE => "BE",
Endianness::LE => "LE",
};
let (add_input, sub_input, mul_input, decompress_input, validate_input) = match endianness {
Endianness::BE => (
INPUT_BE_G2_ADD_WORST_CASE,
INPUT_BE_G2_SUB_WORST_CASE,
INPUT_BE_G2_MUL_WORST_CASE,
INPUT_BE_G2_DECOMPRESS_WORST_CASE,
INPUT_BE_G2_VALIDATE_WORST_CASE,
),
Endianness::LE => (
INPUT_LE_G2_ADD_WORST_CASE,
INPUT_LE_G2_SUB_WORST_CASE,
INPUT_LE_G2_MUL_WORST_CASE,
INPUT_LE_G2_DECOMPRESS_WORST_CASE,
INPUT_LE_G2_VALIDATE_WORST_CASE,
),
};
group.bench_function(BenchmarkId::new("Addition", label), |b| {
let (p1_bytes, p2_bytes) = add_input.split_at(192);
let p1: PodG2Point = pod_read_unaligned(p1_bytes);
let p2: PodG2Point = pod_read_unaligned(p2_bytes);
b.iter(|| bls12_381_g2_addition_unchecked(Version::V0, &p1, &p2, endianness).unwrap())
});
group.bench_function(BenchmarkId::new("Subtraction", label), |b| {
let (p1_bytes, p2_bytes) = sub_input.split_at(192);
let p1: PodG2Point = pod_read_unaligned(p1_bytes);
let p2: PodG2Point = pod_read_unaligned(p2_bytes);
b.iter(|| {
bls12_381_g2_subtraction_unchecked(Version::V0, &p1, &p2, endianness).unwrap()
})
});
group.bench_function(BenchmarkId::new("Multiplication", label), |b| {
let (point_bytes, scalar_bytes) = mul_input.split_at(192);
let point: PodG2Point = pod_read_unaligned(point_bytes);
let scalar: PodScalar = pod_read_unaligned(scalar_bytes);
b.iter(|| {
bls12_381_g2_multiplication(Version::V0, &point, &scalar, endianness).unwrap()
})
});
group.bench_function(BenchmarkId::new("Decompression", label), |b| {
let input: PodG2Compressed = pod_read_unaligned(decompress_input);
b.iter(|| bls12_381_g2_decompress(Version::V0, &input, endianness).unwrap())
});
group.bench_function(BenchmarkId::new("Validation", label), |b| {
let input: PodG2Point = pod_read_unaligned(validate_input);
b.iter(|| bls12_381_g2_point_validation(Version::V0, &input, endianness))
});
}
group.finish();
}
macro_rules! bench_pair_size {
($group:expr, $N:expr) => {{
// Construct inputs deterministically from the ONE_PAIR test vector
let (g1_be, g2_be) = build_pairing_input::<$N>(INPUT_BE_PAIRING_WORST_CASE);
let (g1_le, g2_le) = build_pairing_input::<$N>(INPUT_LE_PAIRING_WORST_CASE);
// Bench BE
$group.bench_with_input(BenchmarkId::new("BE", $N), &$N, |b, &_count| {
b.iter(|| bls12_381_pairing_map(Version::V0, &g1_be, &g2_be, Endianness::BE).unwrap())
});
// Bench LE
$group.bench_with_input(BenchmarkId::new("LE", $N), &$N, |b, &_count| {
b.iter(|| bls12_381_pairing_map(Version::V0, &g1_le, &g2_le, Endianness::LE).unwrap())
});
}};
}
fn bench_pairing(c: &mut Criterion) {
let mut group = c.benchmark_group("Pairing");
bench_pair_size!(group, 1);
bench_pair_size!(group, 2);
bench_pair_size!(group, 4);
bench_pair_size!(group, 8);
group.finish();
}
criterion_group!(benches, bench_g1_ops, bench_g2_ops, bench_pairing);
criterion_main!(benches);

View file

@ -0,0 +1,81 @@
use hex_literal::hex;
// --- G1 Operations ---
pub const INPUT_BE_G1_ADD_WORST_CASE: &[u8] = &hex!(
"0408fcfce79d55404c279812a8bdfc02525f215e70f717cbf9f97c305f6845d6661f3a5a46c513a24cf706410e878a2c12aca07fea5564f2bdcf28ba9f12f2d88c85ae28b1a2c33f965cad4a1af3c796ee6d33fc7e322cc8954b223f53febd330eea76a913985d932eea073ebf8e86d21c6e4d4c8bfbef927c006abe860b51282629eea7b197385deb9057e603aa9c6e1104b5ffaabfe1d55de81f8acc668c913479611296668293535b602ab8cf24797522ad15ca4a2e8f898855d94d0a58fe"
);
pub const INPUT_LE_G1_ADD_WORST_CASE: &[u8] = &hex!(
"2c8a870e4106f74ca213c5465a3a1f66d645685f307cf9f9cb17f7705e215f5202fcbda81298274c40559de7fcfc080433bdfe533f224b95c82c327efc336dee96c7f31a4aad5c963fc3a2b128ae858cd8f2129fba28cfbdf26455ea7fa0ac126e9caa03e65790eb5d3897b1a7ee292628510b86be6a007c92effb8b4c4d6e1cd2868ebf3e07ea2e935d9813a976ea0efe580a4dd95588898f2e4aca15ad22757924cfb82a605b539382669612617934918c66cc8a1fe85dd5e1bfaaffb50411"
);
pub const INPUT_BE_G1_SUB_WORST_CASE: &[u8] = &hex!(
"0408fcfce79d55404c279812a8bdfc02525f215e70f717cbf9f97c305f6845d6661f3a5a46c513a24cf706410e878a2c12aca07fea5564f2bdcf28ba9f12f2d88c85ae28b1a2c33f965cad4a1af3c796ee6d33fc7e322cc8954b223f53febd330eea76a913985d932eea073ebf8e86d21c6e4d4c8bfbef927c006abe860b51282629eea7b197385deb9057e603aa9c6e1104b5ffaabfe1d55de81f8acc668c913479611296668293535b602ab8cf24797522ad15ca4a2e8f898855d94d0a58fe"
);
pub const INPUT_LE_G1_SUB_WORST_CASE: &[u8] = &hex!(
"2c8a870e4106f74ca213c5465a3a1f66d645685f307cf9f9cb17f7705e215f5202fcbda81298274c40559de7fcfc080433bdfe533f224b95c82c327efc336dee96c7f31a4aad5c963fc3a2b128ae858cd8f2129fba28cfbdf26455ea7fa0ac126e9caa03e65790eb5d3897b1a7ee292628510b86be6a007c92effb8b4c4d6e1cd2868ebf3e07ea2e935d9813a976ea0efe580a4dd95588898f2e4aca15ad22757924cfb82a605b539382669612617934918c66cc8a1fe85dd5e1bfaaffb50411"
);
pub const INPUT_BE_G1_MUL_WORST_CASE: &[u8] = &hex!(
"0408fcfce79d55404c279812a8bdfc02525f215e70f717cbf9f97c305f6845d6661f3a5a46c513a24cf706410e878a2c12aca07fea5564f2bdcf28ba9f12f2d88c85ae28b1a2c33f965cad4a1af3c796ee6d33fc7e322cc8954b223f53febd3373eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000"
);
pub const INPUT_LE_G1_MUL_WORST_CASE: &[u8] = &hex!(
"2c8a870e4106f74ca213c5465a3a1f66d645685f307cf9f9cb17f7705e215f5202fcbda81298274c40559de7fcfc080433bdfe533f224b95c82c327efc336dee96c7f31a4aad5c963fc3a2b128ae858cd8f2129fba28cfbdf26455ea7fa0ac1200000000fffffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73"
);
pub const INPUT_BE_G1_DECOMPRESS_WORST_CASE: &[u8] = &hex!(
"a408fcfce79d55404c279812a8bdfc02525f215e70f717cbf9f97c305f6845d6661f3a5a46c513a24cf706410e878a2c"
);
pub const INPUT_LE_G1_DECOMPRESS_WORST_CASE: &[u8] = &hex!(
"2c8a870e4106f74ca213c5465a3a1f66d645685f307cf9f9cb17f7705e215f5202fcbda81298274c40559de7fcfc08a4"
);
pub const INPUT_BE_G1_VALIDATE_WORST_CASE: &[u8] = &hex!(
"0408fcfce79d55404c279812a8bdfc02525f215e70f717cbf9f97c305f6845d6661f3a5a46c513a24cf706410e878a2c12aca07fea5564f2bdcf28ba9f12f2d88c85ae28b1a2c33f965cad4a1af3c796ee6d33fc7e322cc8954b223f53febd33"
);
pub const INPUT_LE_G1_VALIDATE_WORST_CASE: &[u8] = &hex!(
"2c8a870e4106f74ca213c5465a3a1f66d645685f307cf9f9cb17f7705e215f5202fcbda81298274c40559de7fcfc080433bdfe533f224b95c82c327efc336dee96c7f31a4aad5c963fc3a2b128ae858cd8f2129fba28cfbdf26455ea7fa0ac12"
);
// --- G2 Operations ---
pub const INPUT_BE_G2_ADD_WORST_CASE: &[u8] = &hex!(
"03bd018dadd58e94c755ae7e3ca3a2359582282475a85ad70d94d051298f2cbcc86d5440032e927e432f2c7b2f28dcb90169a750864019b9aaaf37c7e5a005a525b70e3e52d04ea58874a79af8b835b68eba547558e9627d6e2051f080b560d307a3d35f55ddb9732ee23283533f7aed5b6b702f932ef3cad72cc79d31cb953700d0bd3fe12230c989e9d199ef580989119af50a55aeedc4b0a7972bbcb2d4a1da1a53f469b49f89458271bb84d341065afca90fae7b9cabf2245622cc2e08730377679657a9200ab2be940cb280e114de3ec7ba85bd35f33b7abb97844ae37d4dc01f39cbb981e6ca64b561c42e28b8074753c2c1ae0f67b96f5eccee6db19581a8d8d72d736929e1126970d0dfb62c64022f37b10fb65328ceb8282d56afc10457daadf9144fb306599b420c3787b5d388ea5eb48d997873a5c0316a71564132fa3c08122f85948c926b98e5074a2f048865ccd58cf6e3afc55b59b382ff03df30d63fa09f1622f3f62663e0ff5203c370fb2019e5caa9eeba9d29b17470ed"
);
pub const INPUT_LE_G2_ADD_WORST_CASE: &[u8] = &hex!(
"d360b580f051206e7d62e9587554ba8eb635b8f89aa77488a54ed0523e0eb725a505a0e5c737afaab919408650a76901b9dc282f7b2c2f437e922e0340546dc8bc2c8f2951d0940dd75aa8752428829535a2a33c7eae55c7948ed5ad8d01bd0373082ecc225624f2ab9c7bae0fa9fc5a0641d384bb718245899fb469f4531adaa1d4b2bc2b97a7b0c4edae550af59a11890958ef99d1e989c93022e13fbdd0003795cb319dc72cd7caf32e932f706b5bed7a3f538332e22e73b9dd555fd3a307c1af562d28b8ce2853b60fb1372f02642cb6dfd0706912e12969732dd7d8a88195b16deecc5e6fb9670faec1c2534707b8282ec461b564cae681b9cb391fc04d7de34a8497bb7a3bf335bd85bac73ede14e180b20c94beb20a20a95796677703ed7074b1299dbaeea9cae51920fb70c30352ffe06326f6f322169fa03fd630df03ff82b3595bc5afe3f68cd5cc6588042f4a07e5986b928c94852f12083cfa324156716a31c0a57378998db45eea88d3b587370c429b5906b34f14f9adda5704"
);
pub const INPUT_BE_G2_SUB_WORST_CASE: &[u8] = &hex!(
"03bd018dadd58e94c755ae7e3ca3a2359582282475a85ad70d94d051298f2cbcc86d5440032e927e432f2c7b2f28dcb90169a750864019b9aaaf37c7e5a005a525b70e3e52d04ea58874a79af8b835b68eba547558e9627d6e2051f080b560d307a3d35f55ddb9732ee23283533f7aed5b6b702f932ef3cad72cc79d31cb953700d0bd3fe12230c989e9d199ef580989119af50a55aeedc4b0a7972bbcb2d4a1da1a53f469b49f89458271bb84d341065afca90fae7b9cabf2245622cc2e08730377679657a9200ab2be940cb280e114de3ec7ba85bd35f33b7abb97844ae37d4dc01f39cbb981e6ca64b561c42e28b8074753c2c1ae0f67b96f5eccee6db19581a8d8d72d736929e1126970d0dfb62c64022f37b10fb65328ceb8282d56afc10457daadf9144fb306599b420c3787b5d388ea5eb48d997873a5c0316a71564132fa3c08122f85948c926b98e5074a2f048865ccd58cf6e3afc55b59b382ff03df30d63fa09f1622f3f62663e0ff5203c370fb2019e5caa9eeba9d29b17470ed"
);
pub const INPUT_LE_G2_SUB_WORST_CASE: &[u8] = &hex!(
"d360b580f051206e7d62e9587554ba8eb635b8f89aa77488a54ed0523e0eb725a505a0e5c737afaab919408650a76901b9dc282f7b2c2f437e922e0340546dc8bc2c8f2951d0940dd75aa8752428829535a2a33c7eae55c7948ed5ad8d01bd0373082ecc225624f2ab9c7bae0fa9fc5a0641d384bb718245899fb469f4531adaa1d4b2bc2b97a7b0c4edae550af59a11890958ef99d1e989c93022e13fbdd0003795cb319dc72cd7caf32e932f706b5bed7a3f538332e22e73b9dd555fd3a307c1af562d28b8ce2853b60fb1372f02642cb6dfd0706912e12969732dd7d8a88195b16deecc5e6fb9670faec1c2534707b8282ec461b564cae681b9cb391fc04d7de34a8497bb7a3bf335bd85bac73ede14e180b20c94beb20a20a95796677703ed7074b1299dbaeea9cae51920fb70c30352ffe06326f6f322169fa03fd630df03ff82b3595bc5afe3f68cd5cc6588042f4a07e5986b928c94852f12083cfa324156716a31c0a57378998db45eea88d3b587370c429b5906b34f14f9adda5704"
);
pub const INPUT_BE_G2_MUL_WORST_CASE: &[u8] = &hex!(
"03bd018dadd58e94c755ae7e3ca3a2359582282475a85ad70d94d051298f2cbcc86d5440032e927e432f2c7b2f28dcb90169a750864019b9aaaf37c7e5a005a525b70e3e52d04ea58874a79af8b835b68eba547558e9627d6e2051f080b560d307a3d35f55ddb9732ee23283533f7aed5b6b702f932ef3cad72cc79d31cb953700d0bd3fe12230c989e9d199ef580989119af50a55aeedc4b0a7972bbcb2d4a1da1a53f469b49f89458271bb84d341065afca90fae7b9cabf2245622cc2e087373eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000"
);
pub const INPUT_LE_G2_MUL_WORST_CASE: &[u8] = &hex!(
"d360b580f051206e7d62e9587554ba8eb635b8f89aa77488a54ed0523e0eb725a505a0e5c737afaab919408650a76901b9dc282f7b2c2f437e922e0340546dc8bc2c8f2951d0940dd75aa8752428829535a2a33c7eae55c7948ed5ad8d01bd0373082ecc225624f2ab9c7bae0fa9fc5a0641d384bb718245899fb469f4531adaa1d4b2bc2b97a7b0c4edae550af59a11890958ef99d1e989c93022e13fbdd0003795cb319dc72cd7caf32e932f706b5bed7a3f538332e22e73b9dd555fd3a30700000000fffffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73"
);
pub const INPUT_BE_G2_DECOMPRESS_WORST_CASE: &[u8] = &hex!(
"83bd018dadd58e94c755ae7e3ca3a2359582282475a85ad70d94d051298f2cbcc86d5440032e927e432f2c7b2f28dcb90169a750864019b9aaaf37c7e5a005a525b70e3e52d04ea58874a79af8b835b68eba547558e9627d6e2051f080b560d3"
);
pub const INPUT_LE_G2_DECOMPRESS_WORST_CASE: &[u8] = &hex!(
"d360b580f051206e7d62e9587554ba8eb635b8f89aa77488a54ed0523e0eb725a505a0e5c737afaab919408650a76901b9dc282f7b2c2f437e922e0340546dc8bc2c8f2951d0940dd75aa8752428829535a2a33c7eae55c7948ed5ad8d01bd83"
);
pub const INPUT_BE_G2_VALIDATE_WORST_CASE: &[u8] = &hex!(
"02298dc5b07ca647c4f87741130b540b7c2410f40bc644ffb5de3f85c6b116f09323fdd675774b9507e1898a5e32ae990a01305b6d86169d57048a21f8144f4a7706eadc687e81b2cd47bea2152ca6c467be4fdb4a7ce8038deede79b40e7d9a0e83c50a4e6f3cfb1333cea38add85a7ca08a351ca2e208f9282e6a224081fa16343263da17e1f37132209f399c5b915140a85dd41147c0346f6bae0719c2ad94a1893901e99ea3a493c57e1827bb65db214b403de77e52d050b17f46f8fe2f1"
);
pub const INPUT_LE_G2_VALIDATE_WORST_CASE: &[u8] = &hex!(
"9a7d0eb479deee8d03e87c4adb4fbe67c4a62c15a2be47cdb2817e68dcea06774a4f14f8218a04579d16866d5b30010a99ae325e8a89e107954b7775d6fd2393f016b1c6853fdeb5ff44c60bf410247c0b540b134177f8c447a67cb0c58d2902f1e28f6ff4170b052de577de03b414b25db67b82e1573c493aea991e9093184ad92a9c71e0baf646037c1441dd850a1415b9c599f3092213371f7ea13d264363a11f0824a2e682928f202eca51a308caa785dd8aa3ce3313fb3c6f4e0ac5830e"
);
// --- Pairing Operations ---
pub const INPUT_BE_PAIRING_WORST_CASE: &[u8] = &hex!(
"023d85d0663f73ae66687d68dc64927752a9ca27de3b1118ba0aaeaa4a6ecb03907530f12c79f8bf2859b6c286f9a93315e8ef5d9d9d224906d22a13683e4419e2463b728ade94b1569e4210c0f6d50765062d57c92027148db03e245d52a57f19dbe2d5c1b709b81868241ce0a838a2ad95c5f3f85f9f619bc5f542f8ec518af5d15ee6b0bcabb81f926ea9b314afdf13df5d30b648ce7429bfc057710c5e936fcfe5330188512344fad45797d34dd278c0ee96353cafec4435eedd5bc0c08508fa6979ce323b0172f90cb94ed927011860bc41e3be0ff6db84427cc750432281f3903f57b291faec6ca7fc438eeb1012ec3ae72921a2fd455262e7e26f3c20f47c2f83a4fffce5d2a562b9e9f35cbb5a689217fa6a18c7e2337f59d4be0876"
);
pub const INPUT_LE_PAIRING_WORST_CASE: &[u8] = &hex!(
"33a9f986c2b65928bff8792cf130759003cb6e4aaaae0aba18113bde27caa952779264dc687d6866ae733f66d0853d027fa5525d243eb08d142720c9572d066507d5f6c010429e56b194de8a723b46e219443e68132ad20649229d9d5defe81585c0c05bddee3544ecaf3c3596eec078d24dd39757d4fa442351880133e5cf6f935e0c7157c0bf2974ce48b6305ddf13dfaf14b3a96e921fb8abbcb0e65ed1f58a51ecf842f5c59b619f5ff8f3c595ada238a8e01c246818b809b7c1d5e2db197608bed4597f33e2c7186afa1792685abb5cf3e9b962a5d2e5fcffa4832f7cf4203c6fe2e7625245fda22129e73aec1210eb8e43fca76cecfa91b2573f90f381224350c77c4284dbf60fbee341bc60180127d94eb90cf972013b32ce7969fa08"
);

View file

@ -0,0 +1,230 @@
use {
crate::{
Version,
encoding::{Endianness, PodG1Point, PodG2Point, swap_fq_endianness, swap_g2_c0_c1},
},
blstrs::{G1Projective, G2Projective},
};
/// Performs point addition on G1: `P1 + P2`.
/// Does not check if points are in the correct subgroup for efficiency.
pub fn bls12_381_g1_addition_unchecked(
_version: Version,
p1: &PodG1Point,
p2: &PodG1Point,
endianness: Endianness,
) -> Option<PodG1Point> {
// skip subgroup check for efficiency
let p1_affine = p1.to_affine_subgroup_unchecked(endianness)?;
let p2_affine = p2.to_affine_subgroup_unchecked(endianness)?;
#[allow(clippy::arithmetic_side_effects)]
let sum_proj = G1Projective::from(p1_affine) + p2_affine;
let sum_affine = sum_proj.to_uncompressed();
let mut result = PodG1Point(sum_affine);
if matches!(endianness, Endianness::LE) {
swap_fq_endianness(&mut result.0);
}
Some(result)
}
/// Performs point addition on G2: `P1 + P2`.
pub fn bls12_381_g2_addition_unchecked(
_version: Version,
p1: &PodG2Point,
p2: &PodG2Point,
endianness: Endianness,
) -> Option<PodG2Point> {
// skip subgroup check for efficiency
let p1_affine = p1.to_affine_subgroup_unchecked(endianness)?;
let p2_affine = p2.to_affine_subgroup_unchecked(endianness)?;
#[allow(clippy::arithmetic_side_effects)]
let sum_proj = G2Projective::from(p1_affine) + p2_affine;
let sum_affine = sum_proj.to_uncompressed();
let mut result = PodG2Point(sum_affine);
if matches!(endianness, Endianness::LE) {
swap_g2_c0_c1(&mut result.0);
swap_fq_endianness(&mut result.0);
}
Some(result)
}
#[cfg(test)]
mod tests {
use {super::*, crate::test_vectors::*, bytemuck::pod_read_unaligned};
fn to_pod_g1(bytes: &[u8]) -> PodG1Point {
pod_read_unaligned(bytes)
}
fn to_pod_g2(bytes: &[u8]) -> PodG2Point {
pod_read_unaligned(bytes)
}
fn run_g1_test(
test_name: &str,
input_be: &[u8],
output_be: &[u8],
input_le: &[u8],
output_le: &[u8],
) {
// G1 Input is [P1 (96) | P2 (96)]
let (p1_be, p2_be) = input_be.split_at(96);
let p1_be = to_pod_g1(p1_be);
let p2_be = to_pod_g1(p2_be);
let expected_be = to_pod_g1(output_be);
// Test Big Endian
let result_be =
bls12_381_g1_addition_unchecked(Version::V0, &p1_be, &p2_be, Endianness::BE);
assert_eq!(
result_be,
Some(expected_be),
"G1 {test_name} BE Test Failed",
);
// Test Little Endian
let (p1_le, p2_le) = input_le.split_at(96);
let p1_le = to_pod_g1(p1_le);
let p2_le = to_pod_g1(p2_le);
let expected_le = to_pod_g1(output_le);
let result_le =
bls12_381_g1_addition_unchecked(Version::V0, &p1_le, &p2_le, Endianness::LE);
assert_eq!(
result_le,
Some(expected_le),
"G1 {test_name} LE Test Failed",
);
}
fn run_g2_test(
test_name: &str,
input_be: &[u8],
output_be: &[u8],
input_le: &[u8],
output_le: &[u8],
) {
// G2 Input is [P1 (192) | P2 (192)]
let (p1_be, p2_be) = input_be.split_at(192);
let p1_be = to_pod_g2(p1_be);
let p2_be = to_pod_g2(p2_be);
let expected_be = to_pod_g2(output_be);
// Test Big Endian
let result_be =
bls12_381_g2_addition_unchecked(Version::V0, &p1_be, &p2_be, Endianness::BE);
assert_eq!(
result_be,
Some(expected_be),
"G2 {test_name} BE Test Failed",
);
// Test Little Endian
let (p1_le, p2_le) = input_le.split_at(192);
let p1_le = to_pod_g2(p1_le);
let p2_le = to_pod_g2(p2_le);
let expected_le = to_pod_g2(output_le);
let result_le =
bls12_381_g2_addition_unchecked(Version::V0, &p1_le, &p2_le, Endianness::LE);
assert_eq!(
result_le,
Some(expected_le),
"G2 {test_name} LE Test Failed",
);
}
#[test]
fn test_g1_addition_random() {
run_g1_test(
"ADD: P (Rand) + Q (Rand)",
INPUT_BE_G1_ADD_RANDOM,
OUTPUT_BE_G1_ADD_RANDOM,
INPUT_LE_G1_ADD_RANDOM,
OUTPUT_LE_G1_ADD_RANDOM,
);
}
#[test]
fn test_g1_addition_doubling() {
run_g1_test(
"ADD: P + P (Doubling)",
INPUT_BE_G1_ADD_DOUBLING,
OUTPUT_BE_G1_ADD_DOUBLING,
INPUT_LE_G1_ADD_DOUBLING,
OUTPUT_LE_G1_ADD_DOUBLING,
);
}
#[test]
fn test_g1_addition_infinity_edge_cases() {
// P + Inf
run_g1_test(
"ADD: P + Inf",
INPUT_BE_G1_ADD_P_PLUS_INF,
OUTPUT_BE_G1_ADD_P_PLUS_INF,
INPUT_LE_G1_ADD_P_PLUS_INF,
OUTPUT_LE_G1_ADD_P_PLUS_INF,
);
// Inf + Inf
run_g1_test(
"ADD: Inf + Inf",
INPUT_BE_G1_ADD_INF_PLUS_INF,
OUTPUT_BE_G1_ADD_INF_PLUS_INF,
INPUT_LE_G1_ADD_INF_PLUS_INF,
OUTPUT_LE_G1_ADD_INF_PLUS_INF,
);
}
#[test]
fn test_g2_addition_random() {
run_g2_test(
"ADD: P (Rand) + Q (Rand)",
INPUT_BE_G2_ADD_RANDOM,
OUTPUT_BE_G2_ADD_RANDOM,
INPUT_LE_G2_ADD_RANDOM,
OUTPUT_LE_G2_ADD_RANDOM,
);
}
#[test]
fn test_g2_addition_doubling() {
run_g2_test(
"ADD: P + P (Doubling)",
INPUT_BE_G2_ADD_DOUBLING,
OUTPUT_BE_G2_ADD_DOUBLING,
INPUT_LE_G2_ADD_DOUBLING,
OUTPUT_LE_G2_ADD_DOUBLING,
);
}
#[test]
fn test_g2_addition_infinity_edge_cases() {
// P + Inf
run_g2_test(
"ADD: P + Inf",
INPUT_BE_G2_ADD_P_PLUS_INF,
OUTPUT_BE_G2_ADD_P_PLUS_INF,
INPUT_LE_G2_ADD_P_PLUS_INF,
OUTPUT_LE_G2_ADD_P_PLUS_INF,
);
// Inf + Inf
run_g2_test(
"ADD: Inf + Inf",
INPUT_BE_G2_ADD_INF_PLUS_INF,
OUTPUT_BE_G2_ADD_INF_PLUS_INF,
INPUT_LE_G2_ADD_INF_PLUS_INF,
OUTPUT_LE_G2_ADD_INF_PLUS_INF,
);
}
}

View file

@ -0,0 +1,267 @@
use {
crate::{
Version,
encoding::{
Endianness, PodG1Compressed, PodG1Point, PodG2Compressed, PodG2Point,
swap_fq_endianness, swap_g2_c0_c1,
},
},
blstrs::{G1Affine, G2Affine},
};
/// Decompresses a compressed G1 point.
pub fn bls12_381_g1_decompress(
_version: Version,
input: &PodG1Compressed,
endianness: Endianness,
) -> Option<PodG1Point> {
let p1 = match endianness {
// `G2Affine::from_compressed_unchecked` performs field and on-curve checks
Endianness::BE => G1Affine::from_compressed_unchecked(&input.0).into_option()?,
Endianness::LE => {
let mut bytes = input.0;
swap_fq_endianness(&mut bytes);
// After reversal, the flag byte (originally at end) is now at index 0.
// This matches the [Zcash BE format][zcash-be-format] expected by
// `G1Affine::from_compressed_unchecked`.
//
// [zcash-be-format]: https://github.com/zkcrypto/pairing/blob/34aa52b0f7bef705917252ea63e5a13fa01af551/src/bls12_381/README.md#serialization
G1Affine::from_compressed_unchecked(&bytes).into_option()?
}
};
// field and on-curve checks are already performed, so just check subgroup
if !bool::from(p1.is_torsion_free()) {
return None;
}
let mut result = PodG1Point(p1.to_uncompressed());
if matches!(endianness, Endianness::LE) {
swap_fq_endianness(&mut result.0);
}
Some(result)
}
/// Decompresses a compressed G2 point.
pub fn bls12_381_g2_decompress(
_version: Version,
input: &PodG2Compressed,
endianness: Endianness,
) -> Option<PodG2Point> {
let p2 = match endianness {
// `G1Affine::from_compressed_unchecked` performs field and on-curve checks
Endianness::BE => G2Affine::from_compressed_unchecked(&input.0).into_option()?,
Endianness::LE => {
let mut bytes = input.0;
swap_fq_endianness(&mut bytes);
swap_g2_c0_c1(&mut bytes); // Swap c0/c1 for G2
// After reversal, the flag byte (originally at end) is now at index 0.
// This matches the [Zcash BE format][zcash-be-format] expected by
// `G2Affine::from_compressed_unchecked`.
//
// [zcash-be-format]: https://github.com/zkcrypto/pairing/blob/34aa52b0f7bef705917252ea63e5a13fa01af551/src/bls12_381/README.md#serialization
G2Affine::from_compressed_unchecked(&bytes).into_option()?
}
};
// field and on-curve checks are already performed, so just check subgroup
if !bool::from(p2.is_torsion_free()) {
return None;
}
let mut result = PodG2Point(p2.to_uncompressed());
if matches!(endianness, Endianness::LE) {
swap_g2_c0_c1(&mut result.0);
swap_fq_endianness(&mut result.0);
}
Some(result)
}
#[cfg(test)]
mod tests {
use {super::*, crate::test_vectors::*, bytemuck::pod_read_unaligned};
fn to_pod_g1(bytes: &[u8]) -> PodG1Point {
pod_read_unaligned(bytes)
}
fn to_pod_g2(bytes: &[u8]) -> PodG2Point {
pod_read_unaligned(bytes)
}
// New helpers for compressed pods
fn to_pod_g1_compressed(bytes: &[u8]) -> PodG1Compressed {
pod_read_unaligned(bytes)
}
fn to_pod_g2_compressed(bytes: &[u8]) -> PodG2Compressed {
pod_read_unaligned(bytes)
}
fn run_g1_test(
test_name: &str,
input_be: &[u8],
output_be: Option<&[u8]>,
input_le: &[u8],
output_le: Option<&[u8]>,
) {
// Test Big Endian
let input_be_pod = to_pod_g1_compressed(input_be);
let result_be = bls12_381_g1_decompress(Version::V0, &input_be_pod, Endianness::BE);
match output_be {
Some(expected) => assert_eq!(
result_be,
Some(to_pod_g1(expected)),
"G1 {test_name} BE Test Failed",
),
None => assert!(result_be.is_none(), "G1 {test_name} BE expected failure"),
}
// Test Little Endian
let input_le_pod = to_pod_g1_compressed(input_le);
let result_le = bls12_381_g1_decompress(Version::V0, &input_le_pod, Endianness::LE);
match output_le {
Some(expected) => assert_eq!(
result_le,
Some(to_pod_g1(expected)),
"G1 {test_name} LE Test Failed",
),
None => assert!(result_le.is_none(), "G1 {test_name} LE expected failure"),
}
}
fn run_g2_test(
test_name: &str,
input_be: &[u8],
output_be: Option<&[u8]>,
input_le: &[u8],
output_le: Option<&[u8]>,
) {
// Test Big Endian
let input_be_pod = to_pod_g2_compressed(input_be);
let result_be = bls12_381_g2_decompress(Version::V0, &input_be_pod, Endianness::BE);
match output_be {
Some(expected) => assert_eq!(
result_be,
Some(to_pod_g2(expected)),
"G2 {test_name} BE Test Failed",
),
None => assert!(result_be.is_none(), "G2 {test_name} BE expected failure"),
}
// Test Little Endian
let input_le_pod = to_pod_g2_compressed(input_le);
let result_le = bls12_381_g2_decompress(Version::V0, &input_le_pod, Endianness::LE);
match output_le {
Some(expected) => assert_eq!(
result_le,
Some(to_pod_g2(expected)),
"G2 {test_name} LE Test Failed",
),
None => assert!(result_le.is_none(), "G2 {test_name} LE expected failure"),
}
}
#[test]
fn test_g1_decompress_random() {
run_g1_test(
"Decompress: RANDOM",
INPUT_BE_G1_DECOMPRESS_RANDOM,
Some(OUTPUT_BE_G1_DECOMPRESS_RANDOM),
INPUT_LE_G1_DECOMPRESS_RANDOM,
Some(OUTPUT_LE_G1_DECOMPRESS_RANDOM),
);
}
#[test]
fn test_g1_decompress_infinity() {
run_g1_test(
"Decompress: INFINITY",
INPUT_BE_G1_DECOMPRESS_INFINITY,
Some(OUTPUT_BE_G1_DECOMPRESS_INFINITY),
INPUT_LE_G1_DECOMPRESS_INFINITY,
Some(OUTPUT_LE_G1_DECOMPRESS_INFINITY),
);
}
#[test]
fn test_g1_decompress_generator() {
run_g1_test(
"Decompress: GENERATOR",
INPUT_BE_G1_DECOMPRESS_GENERATOR,
Some(OUTPUT_BE_G1_DECOMPRESS_GENERATOR),
INPUT_LE_G1_DECOMPRESS_GENERATOR,
Some(OUTPUT_LE_G1_DECOMPRESS_GENERATOR),
);
}
#[test]
fn test_g1_decompress_invalid() {
run_g1_test(
"Decompress: INVALID_CURVE",
INPUT_BE_G1_DECOMPRESS_RANDOM_INVALID_CURVE,
None,
INPUT_LE_G1_DECOMPRESS_RANDOM_INVALID_CURVE,
None,
);
run_g1_test(
"Decompress: INVALID_FIELD",
INPUT_BE_G1_DECOMPRESS_FIELD_TOO_LARGE_INVALID,
None,
INPUT_LE_G1_DECOMPRESS_FIELD_TOO_LARGE_INVALID,
None,
);
}
#[test]
fn test_g2_decompress_random() {
run_g2_test(
"Decompress: RANDOM",
INPUT_BE_G2_DECOMPRESS_RANDOM,
Some(OUTPUT_BE_G2_DECOMPRESS_RANDOM),
INPUT_LE_G2_DECOMPRESS_RANDOM,
Some(OUTPUT_LE_G2_DECOMPRESS_RANDOM),
);
}
#[test]
fn test_g2_decompress_infinity() {
run_g2_test(
"Decompress: INFINITY",
INPUT_BE_G2_DECOMPRESS_INFINITY,
Some(OUTPUT_BE_G2_DECOMPRESS_INFINITY),
INPUT_LE_G2_DECOMPRESS_INFINITY,
Some(OUTPUT_LE_G2_DECOMPRESS_INFINITY),
);
}
#[test]
fn test_g2_decompress_generator() {
run_g2_test(
"Decompress: GENERATOR",
INPUT_BE_G2_DECOMPRESS_GENERATOR,
Some(OUTPUT_BE_G2_DECOMPRESS_GENERATOR),
INPUT_LE_G2_DECOMPRESS_GENERATOR,
Some(OUTPUT_LE_G2_DECOMPRESS_GENERATOR),
);
}
#[test]
fn test_g2_decompress_invalid() {
run_g2_test(
"Decompress: INVALID_CURVE",
INPUT_BE_G2_DECOMPRESS_RANDOM_INVALID_CURVE,
None,
INPUT_LE_G2_DECOMPRESS_RANDOM_INVALID_CURVE,
None,
);
run_g2_test(
"Decompress: INVALID_FIELD",
INPUT_BE_G2_DECOMPRESS_FIELD_TOO_LARGE_INVALID,
None,
INPUT_LE_G2_DECOMPRESS_FIELD_TOO_LARGE_INVALID,
None,
);
}
}

View file

@ -0,0 +1,312 @@
use {
blst::{blst_fp12, blst_lendian_from_fp},
blstrs::{G1Affine, G2Affine, Gt, Scalar},
bytemuck::Zeroable,
bytemuck_derive::{Pod, Zeroable as DeriveZeroable},
};
/// Size of a base field element (`Fq`) in bytes.
pub const FQ_SIZE: usize = 48;
/// Size of a quadratic extension field element (`Fq2`) in bytes.
pub const FQ2_SIZE: usize = 2 * FQ_SIZE;
/// Size of a target group element (`Gt` or `Fq12`) in bytes.
pub const GT_SIZE: usize = 12 * FQ_SIZE;
/// G1 affine point size (uncompressed coordinates).
/// G1 uncompressed = x (48) + y (48) = 96 bytes.
pub const G1_UNCOMPRESSED_SIZE: usize = 2 * FQ_SIZE;
/// G1 compressed point size.
/// G1 compressed = x (48 bytes) with flags encoded in MSB.
pub const G1_COMPRESSED_SIZE: usize = FQ_SIZE;
/// G2 affine point size (uncompressed coordinates).
/// G2 uncompressed = x (96) + y (96) = 192 bytes.
pub const G2_UNCOMPRESSED_SIZE: usize = 2 * FQ2_SIZE;
/// G2 compressed point size.
/// G2 compressed = x (96 bytes) with flags encoded in MSB.
pub const G2_COMPRESSED_SIZE: usize = FQ2_SIZE;
/// Scalar size in bytes.
pub const SCALAR_SIZE: usize = 32;
/// G1 compressed point (48 bytes).
#[derive(Clone, Copy, Debug, PartialEq, Eq, Pod, DeriveZeroable)]
#[repr(transparent)]
pub struct PodG1Compressed(pub [u8; G1_COMPRESSED_SIZE]);
/// G1 affine point (96 bytes).
/// Represents `x` (48 bytes) and `y` (48 bytes).
#[derive(Clone, Copy, Debug, PartialEq, Eq, Pod, DeriveZeroable)]
#[repr(transparent)]
pub struct PodG1Point(pub [u8; G1_UNCOMPRESSED_SIZE]);
impl PodG1Point {
/// Deserializes to an affine point, skipping the subgroup check.
///
/// Checks: Field validity, Curve equation (`y^2 = x^3 + 4`).
/// Skips: Subgroup membership
pub fn to_affine_subgroup_unchecked(&self, endianness: Endianness) -> Option<G1Affine> {
let mut bytes = self.0;
if matches!(endianness, Endianness::LE) {
swap_fq_endianness(&mut bytes);
}
// reject point if the compressed or parity flag is set
if bytes[0] & 0xa0 != 0 {
return None;
}
// `G1Affine::from_uncompressed_unchecked` already performs field and on-curve checks
G1Affine::from_uncompressed_unchecked(&bytes).into_option()
}
/// Deserializes to an affine point with full validation.
///
/// Checks: Field validity, Curve equation (`y^2 = x^3 + 4`), Subgroup membership.
pub fn to_affine(&self, endianness: Endianness) -> Option<G1Affine> {
let affine = self.to_affine_subgroup_unchecked(endianness)?;
if bool::from(affine.is_torsion_free()) {
Some(affine)
} else {
None
}
}
}
/// G2 compressed point (96 bytes).
#[derive(Clone, Copy, Debug, PartialEq, Eq, Pod, DeriveZeroable)]
#[repr(transparent)]
pub struct PodG2Compressed(pub [u8; G2_COMPRESSED_SIZE]);
/// G2 affine point (192 bytes).
/// Represents `x` (96 bytes) and `y` (96 bytes).
#[derive(Clone, Copy, Debug, PartialEq, Eq, Pod, DeriveZeroable)]
#[repr(transparent)]
pub struct PodG2Point(pub [u8; G2_UNCOMPRESSED_SIZE]);
impl PodG2Point {
/// Deserializes to an affine point, skipping the subgroup check.
///
/// Checks: Field validity, Curve equation (`y^2 = x^3 + 4(1+u)^{-1}`).
/// Skips: Subgroup membership
pub fn to_affine_subgroup_unchecked(&self, endianness: Endianness) -> Option<G2Affine> {
let mut bytes = self.0;
if matches!(endianness, Endianness::LE) {
swap_fq_endianness(&mut bytes);
swap_g2_c0_c1(&mut bytes);
}
// reject point if the compressed or parity flag is set
if bytes[0] & 0xa0 != 0 {
return None;
}
// `G2Affine::from_uncompressed_unchecked` already performs field and on-curve checks
G2Affine::from_uncompressed_unchecked(&bytes).into_option()
}
/// Deserializes to an affine point with full validation.
///
/// Checks: Field validity, Curve equation (`y^2 = x^3 + 4(1+u)^{-1}`), Subgroup membership.
pub fn to_affine(&self, endianness: Endianness) -> Option<G2Affine> {
let affine = self.to_affine_subgroup_unchecked(endianness)?;
if bool::from(affine.is_torsion_free()) {
Some(affine)
} else {
None
}
}
}
/// Scalar value (32 bytes).
#[derive(Clone, Copy, Debug, PartialEq, Eq, Pod, DeriveZeroable)]
#[repr(transparent)]
pub struct PodScalar(pub [u8; SCALAR_SIZE]);
impl PodScalar {
pub fn to_scalar(&self, endianness: Endianness) -> Option<Scalar> {
match endianness {
Endianness::BE => Scalar::from_bytes_be(&self.0).into_option(),
Endianness::LE => Scalar::from_bytes_le(&self.0).into_option(),
}
}
}
/// Target group element (Gt).
/// Represents an element in the extension field Fq12 (576 bytes).
#[derive(Clone, Copy, Debug, PartialEq, Eq, Pod, DeriveZeroable)]
#[repr(transparent)]
pub struct PodGtElement(pub [u8; GT_SIZE]);
/// Specifies the byte ordering for BLS12-381 field elements.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Endianness {
/// Canonical Big-Endian encoding, following the [Zcash][zcash] and [IETF][ietf]
/// standards.
///
/// [zcash]: https://github.com/zkcrypto/pairing/tree/master/src/bls12_381#serialization
/// [ietf]: https://www.ietf.org/archive/id/draft-irtf-cfrg-pairing-friendly-curves-11.html#name-bls-curves-for-the-128-bit-
BE,
/// Little-Endian encoding.
/// Base field elements (`Fq`) are reversed compared to BE.
LE,
}
/// Toggles the endianness of `Fq` (base field) elements in place.
///
/// Since a BLS12-381 `Fq` element is represented by 48 bytes, this function
/// iterates through the input buffer in 48-byte chunks and reverses the byte
/// order of each chunk.
pub(crate) fn swap_fq_endianness(bytes: &mut [u8]) {
for chunk in bytes.chunks_mut(FQ_SIZE) {
chunk.reverse();
}
}
/// Swaps the real (`c_0`) and imaginary (`c_1`) components of `Fq2` elements in place.
///
/// In the Zcash/IETF Big-Endian standard, `Fq2` elements are ordered as `c1` then `c0`.
/// In the Little-Endian variant, they are ordered as `c0` then `c1` to match
/// standard polynomial representation ($c_0 + c_1 u$).
///
/// This function expects 96-byte chunks (representing one `Fq2` element or a G2 coordinate)
/// and swaps the first 48 bytes with the last 48 bytes.
pub(crate) fn swap_g2_c0_c1(bytes: &mut [u8]) {
for fq2_chunk in bytes.chunks_exact_mut(FQ2_SIZE) {
let (c0, c1) = fq2_chunk.split_at_mut(FQ_SIZE);
c0.swap_with_slice(c1);
}
}
/// Helper to serialize Fp12 (Gt) according to SIMD Endianness rules.
///
/// `Fp12 = c0(Fp6) + c1(Fp6)w`.
/// `Fp6 = c0(Fp2) + c1(Fp2)v + c2(Fp2)v^2`.
/// `Fp2 = c0(Fp) + c1(Fp)u`.
///
/// # Rules
/// 1. **Fq (`Fp`)**:
/// - BE: Big-Endian bytes.
/// - LE: Little-Endian bytes.
/// 2. **Coefficient Ordering**:
/// - BE: Highest degree coefficients first (reverses the entire tower).
/// - LE: Lowest degree coefficients first (canonical memory order).
pub(crate) fn serialize_gt(gt: Gt, endianness: Endianness) -> PodGtElement {
// `blstrs::Gt` is `repr(transparent)` over `blst_fp12`.
// We transmute to access the internal coefficients directly because
// blstrs does not expose the `Fp12`/`Fp6`/`Fp2`/`Fp` types publicly.
// Safe because layout is guaranteed by `repr(transparent)` wrapping the blst type.
// We also verify in `test_gt_layout_safety` that layout sizes and alignment match.
let val: blst_fp12 = unsafe { std::mem::transmute(gt) };
let mut out = PodGtElement::zeroed();
let mut ptr = out.0.as_mut_ptr();
unsafe {
for fp6 in val.fp6.iter() {
for fp2 in fp6.fp2.iter() {
// In LE, we write c0 (Real) then c1 (Imaginary)
let c0 = &fp2.fp[0];
let c1 = &fp2.fp[1];
blst_lendian_from_fp(ptr, c0);
ptr = ptr.add(FQ_SIZE);
blst_lendian_from_fp(ptr, c1);
ptr = ptr.add(FQ_SIZE);
}
}
}
// If Big Endian is requested, simply reverse the entire byte array, which
// achieves both of the following simultaneously:
// - flips coefficient order (c0...c11 -> c11...c0)
// - flips coefficient bytes (LE -> BE)
if matches!(endianness, Endianness::BE) {
out.0.reverse();
}
out
}
#[cfg(test)]
mod tests {
use {super::*, blstrs::Gt, group::Group};
#[test]
fn test_swap_fq_endianness() {
// Create a buffer with 2 chunks (96 bytes)
// Chunk 0: 0..48
// Chunk 1: 48..96
let mut input = Vec::new();
for i in 0..96u8 {
input.push(i);
}
let mut expected = input.clone();
expected[0..48].reverse();
expected[48..96].reverse();
swap_fq_endianness(&mut input);
assert_eq!(input, expected);
}
#[test]
fn test_swap_g2_c0_c1() {
// Create a buffer with 1 G2 point (96 bytes)
// c0: 48 bytes of 0xAA
// c1: 48 bytes of 0xBB
let mut input = Vec::new();
input.extend_from_slice(&[0xAAu8; 48]);
input.extend_from_slice(&[0xBBu8; 48]);
// Expected result: c1 then c0
let mut expected = Vec::new();
expected.extend_from_slice(&[0xBBu8; 48]);
expected.extend_from_slice(&[0xAAu8; 48]);
swap_g2_c0_c1(&mut input);
assert_eq!(input, expected);
}
#[test]
fn test_serialize_gt_identity() {
let identity = Gt::identity();
// BE
let be_bytes = serialize_gt(identity, Endianness::BE);
assert_eq!(&be_bytes.0[0..48], &[0u8; 48]);
let mut one_be = [0u8; 48];
one_be[47] = 1;
assert_eq!(&be_bytes.0[528..576], &one_be);
// LE
let le_bytes = serialize_gt(identity, Endianness::LE);
let mut one_le = [0u8; 48];
one_le[0] = 1; // [01, 00, ... 00]
assert_eq!(&le_bytes.0[0..48], &one_le);
assert_eq!(&le_bytes.0[48..96], &[0u8; 48]);
}
#[test]
fn test_gt_layout_safety() {
// Critical Safety Check:
// verify that blstrs::Gt is indeed a transparent wrapper around blst_fp12
// before we rely on unsafe transmutes in the main code.
assert_eq!(
std::mem::size_of::<Gt>(),
std::mem::size_of::<blst_fp12>(),
"Size mismatch between blstrs::Gt and blst_fp12. Unsafe transmute is invalid."
);
assert_eq!(
std::mem::align_of::<Gt>(),
std::mem::align_of::<blst_fp12>(),
"Alignment mismatch between blstrs::Gt and blst_fp12. Unsafe transmute is invalid."
);
}
}

View file

@ -0,0 +1,62 @@
//! Implementation of the BLS12-381 Elliptic Curve operations for Solana syscalls.
//!
//! This crate provides the native implementations for the syscalls defined in
//! [SIMD-0388](https://github.com/solana-foundation/solana-improvement-documents/pull/388).
//!
//! # Supported Operations
//!
//! - **Group Operations** (G1 & G2): Addition, Subtraction, Scalar Multiplication.
//! - **Pairing**: Product of pairings over G1/G2 point pairs (multi-Miller loop + final exponentiation).
//! - **Validation**: Subgroup and on-curve checks.
//! - **Decompression**: Converting compressed byte representations to affine points.
//!
//! # Encoding and Endianness
//!
//! The operations support two encoding formats defined in [`Endianness`]:
//! 1. **Big-Endian (BE)**: Follows the [Zcash BLS12-381 specification][zcash] and
//! [IETF draft][ietf].
//! 2. **Little-Endian (LE)**: This mirrors the Zcash structure but utilizes little-endian
//! byte ordering for base field elements.
//!
//! [zcash]: https://github.com/zkcrypto/pairing/tree/master/src/bls12_381#serialization
//! [ietf]: https://www.ietf.org/archive/id/draft-irtf-cfrg-pairing-friendly-curves-11.html#name-bls-curves-for-the-128-bit-
pub use crate::{
addition::{bls12_381_g1_addition_unchecked, bls12_381_g2_addition_unchecked},
decompression::{bls12_381_g1_decompress, bls12_381_g2_decompress},
encoding::{
Endianness, PodG1Compressed, PodG1Point, PodG2Compressed, PodG2Point, PodGtElement,
PodScalar,
},
multiplication::{bls12_381_g1_multiplication, bls12_381_g2_multiplication},
pairing::bls12_381_pairing_map,
subtraction::{bls12_381_g1_subtraction_unchecked, bls12_381_g2_subtraction_unchecked},
validation::{bls12_381_g1_point_validation, bls12_381_g2_point_validation},
};
pub(crate) mod addition;
pub(crate) mod decompression;
pub(crate) mod encoding;
pub(crate) mod multiplication;
pub(crate) mod pairing;
pub(crate) mod subtraction;
#[cfg(test)]
pub(crate) mod test_vectors;
pub(crate) mod validation;
/// Version identifier for the syscall interface.
///
/// Modifying the behavior of syscalls is a consensus-critical operation.
/// Any change in behavior across the network without proper coordination will result
/// in a network fork.
///
/// If a change to the syscall behavior is required:
/// 1. The change must first be proposed and approved via a
/// [Solana Improvement Document (SIMD)](https://github.com/solana-foundation/solana-improvement-documents).
/// 2. Once the SIMD is accepted, a new variant should be added to this enum (e.g., `V1`).
/// 3. The implementation of every function in this crate must be scoped to handle the
/// specific logic for each version variant.
pub enum Version {
/// SIMD-388: BLS12-381 Elliptic Curve Syscalls
V0,
}

View file

@ -0,0 +1,252 @@
use {
crate::{
Version,
encoding::{
Endianness, PodG1Point, PodG2Point, PodScalar, swap_fq_endianness, swap_g2_c0_c1,
},
},
blstrs::{G1Projective, G2Projective},
};
/// Performs scalar multiplication on G1: `P * s`.
pub fn bls12_381_g1_multiplication(
_version: Version,
point: &PodG1Point,
scalar: &PodScalar,
endianness: Endianness,
) -> Option<PodG1Point> {
// perform full validation of points
let p1_affine = point.to_affine(endianness)?;
let scalar_val = scalar.to_scalar(endianness)?;
#[allow(clippy::arithmetic_side_effects)]
let result_proj = G1Projective::from(p1_affine) * scalar_val;
let result_affine = result_proj.to_uncompressed();
let mut result = PodG1Point(result_affine);
if matches!(endianness, Endianness::LE) {
swap_fq_endianness(&mut result.0);
}
Some(result)
}
/// Performs scalar multiplication on G2: `P * s`.
pub fn bls12_381_g2_multiplication(
_version: Version,
point: &PodG2Point,
scalar: &PodScalar,
endianness: Endianness,
) -> Option<PodG2Point> {
// perform full validation of points
let p1_affine = point.to_affine(endianness)?;
let scalar_val = scalar.to_scalar(endianness)?;
#[allow(clippy::arithmetic_side_effects)]
let result_proj = G2Projective::from(p1_affine) * scalar_val;
let result_affine = result_proj.to_uncompressed();
let mut result = PodG2Point(result_affine);
if matches!(endianness, Endianness::LE) {
swap_g2_c0_c1(&mut result.0);
swap_fq_endianness(&mut result.0);
}
Some(result)
}
#[cfg(test)]
mod tests {
use {super::*, crate::test_vectors::*, bytemuck::pod_read_unaligned};
fn to_pod_g1(bytes: &[u8]) -> PodG1Point {
pod_read_unaligned(bytes)
}
fn to_pod_g2(bytes: &[u8]) -> PodG2Point {
pod_read_unaligned(bytes)
}
fn to_pod_scalar(bytes: &[u8]) -> PodScalar {
pod_read_unaligned(bytes)
}
fn run_g1_test(
test_name: &str,
input_be: &[u8],
output_be: &[u8],
input_le: &[u8],
output_le: &[u8],
) {
// G1 Input is [Point (96) | Scalar (32)]
let (point_be, scalar_be) = input_be.split_at(96);
let point_be = to_pod_g1(point_be);
let scalar_be = to_pod_scalar(scalar_be);
let expected_be = to_pod_g1(output_be);
let result_be =
bls12_381_g1_multiplication(Version::V0, &point_be, &scalar_be, Endianness::BE);
assert_eq!(
result_be,
Some(expected_be),
"G1 {test_name} BE Test Failed",
);
// G1 Input is [Point (96) | Scalar (32)]
let (point_le, scalar_le) = input_le.split_at(96);
let point_le = to_pod_g1(point_le);
let scalar_le = to_pod_scalar(scalar_le);
let expected_le = to_pod_g1(output_le);
let result_le =
bls12_381_g1_multiplication(Version::V0, &point_le, &scalar_le, Endianness::LE);
assert_eq!(
result_le,
Some(expected_le),
"G1 {test_name} LE Test Failed",
);
}
fn run_g2_test(
test_name: &str,
input_be: &[u8],
output_be: &[u8],
input_le: &[u8],
output_le: &[u8],
) {
// G2 Input is [Point (192) | Scalar (32)]
let (point_be, scalar_be) = input_be.split_at(192);
let point_be = to_pod_g2(point_be);
let scalar_be = to_pod_scalar(scalar_be);
let expected_be = to_pod_g2(output_be);
let result_be =
bls12_381_g2_multiplication(Version::V0, &point_be, &scalar_be, Endianness::BE);
assert_eq!(
result_be,
Some(expected_be),
"G2 {test_name} BE Test Failed",
);
let (point_le, scalar_le) = input_le.split_at(192);
let point_le = to_pod_g2(point_le);
let scalar_le = to_pod_scalar(scalar_le);
let expected_le = to_pod_g2(output_le);
let result_le =
bls12_381_g2_multiplication(Version::V0, &point_le, &scalar_le, Endianness::LE);
assert_eq!(
result_le,
Some(expected_le),
"G2 {test_name} LE Test Failed",
);
}
#[test]
fn test_g1_multiplication_random() {
run_g1_test(
"MUL: P * Scalar (Random)",
INPUT_BE_G1_MUL_RANDOM,
OUTPUT_BE_G1_MUL_RANDOM,
INPUT_LE_G1_MUL_RANDOM,
OUTPUT_LE_G1_MUL_RANDOM,
);
}
#[test]
fn test_g1_multiplication_zero() {
run_g1_test(
"MUL: P * 0",
INPUT_BE_G1_MUL_SCALAR_ZERO,
OUTPUT_BE_G1_MUL_SCALAR_ZERO,
INPUT_LE_G1_MUL_SCALAR_ZERO,
OUTPUT_LE_G1_MUL_SCALAR_ZERO,
);
}
#[test]
fn test_g1_multiplication_one() {
run_g1_test(
"MUL: P * 1",
INPUT_BE_G1_MUL_SCALAR_ONE,
OUTPUT_BE_G1_MUL_SCALAR_ONE,
INPUT_LE_G1_MUL_SCALAR_ONE,
OUTPUT_LE_G1_MUL_SCALAR_ONE,
);
}
#[test]
fn test_g1_multiplication_minus_one() {
run_g1_test(
"MUL: P * -1",
INPUT_BE_G1_MUL_SCALAR_MINUS_ONE,
OUTPUT_BE_G1_MUL_SCALAR_MINUS_ONE,
INPUT_LE_G1_MUL_SCALAR_MINUS_ONE,
OUTPUT_LE_G1_MUL_SCALAR_MINUS_ONE,
);
}
#[test]
fn test_g1_multiplication_infinity() {
run_g1_test(
"MUL: Infinity * Scalar",
INPUT_BE_G1_MUL_POINT_INFINITY,
OUTPUT_BE_G1_MUL_POINT_INFINITY,
INPUT_LE_G1_MUL_POINT_INFINITY,
OUTPUT_LE_G1_MUL_POINT_INFINITY,
);
}
#[test]
fn test_g2_multiplication_random() {
run_g2_test(
"MUL: P * Scalar (Random)",
INPUT_BE_G2_MUL_RANDOM,
OUTPUT_BE_G2_MUL_RANDOM,
INPUT_LE_G2_MUL_RANDOM,
OUTPUT_LE_G2_MUL_RANDOM,
);
}
#[test]
fn test_g2_multiplication_zero() {
run_g2_test(
"MUL: P * 0",
INPUT_BE_G2_MUL_SCALAR_ZERO,
OUTPUT_BE_G2_MUL_SCALAR_ZERO,
INPUT_LE_G2_MUL_SCALAR_ZERO,
OUTPUT_LE_G2_MUL_SCALAR_ZERO,
);
}
#[test]
fn test_g2_multiplication_one() {
run_g2_test(
"MUL: P * 1",
INPUT_BE_G2_MUL_SCALAR_ONE,
OUTPUT_BE_G2_MUL_SCALAR_ONE,
INPUT_LE_G2_MUL_SCALAR_ONE,
OUTPUT_LE_G2_MUL_SCALAR_ONE,
);
}
#[test]
fn test_g2_multiplication_minus_one() {
run_g2_test(
"MUL: P * -1",
INPUT_BE_G2_MUL_SCALAR_MINUS_ONE,
OUTPUT_BE_G2_MUL_SCALAR_MINUS_ONE,
INPUT_LE_G2_MUL_SCALAR_MINUS_ONE,
OUTPUT_LE_G2_MUL_SCALAR_MINUS_ONE,
);
}
#[test]
fn test_g2_multiplication_infinity() {
run_g2_test(
"MUL: Inf * Scalar",
INPUT_BE_G2_MUL_POINT_INFINITY,
OUTPUT_BE_G2_MUL_POINT_INFINITY,
INPUT_LE_G2_MUL_POINT_INFINITY,
OUTPUT_LE_G2_MUL_POINT_INFINITY,
);
}
}

View file

@ -0,0 +1,190 @@
#![allow(clippy::arithmetic_side_effects)]
use {
crate::{
Version,
encoding::{Endianness, PodG1Point, PodG2Point, PodGtElement, serialize_gt},
},
blstrs::{Bls12, G1Affine, G2Prepared, Gt},
group::Group,
pairing::{MillerLoopResult, MultiMillerLoop},
};
/// Maximum number of pairs allowed in a single pairing operation.
const MAX_PAIRING_LENGTH: usize = 8;
/// Computes the product of pairings for a batch of G1 and G2 points.
///
/// Mathematically, this computes:
/// `e(P_1, Q_1) * e(P_2, Q_2) * ... * e(P_n, Q_n)`
pub fn bls12_381_pairing_map(
_version: Version,
g1_points: &[PodG1Point],
g2_points: &[PodG2Point],
endianness: Endianness,
) -> Option<PodGtElement> {
if g1_points.len() != g2_points.len() {
return None;
}
if g1_points.len() > MAX_PAIRING_LENGTH {
return None;
}
if g1_points.is_empty() {
return Some(serialize_gt(Gt::identity(), endianness));
}
let count = g1_points.len();
let mut g1_affines = Vec::with_capacity(count);
let mut g2_prepareds = Vec::with_capacity(count);
for (p1_pod, p2_pod) in g1_points.iter().zip(g2_points.iter()) {
let p1 = p1_pod.to_affine(endianness)?;
let p2 = p2_pod.to_affine(endianness)?;
g1_affines.push(p1);
g2_prepareds.push(G2Prepared::from(p2));
}
let refs: Vec<(&G1Affine, &G2Prepared)> = g1_affines.iter().zip(g2_prepareds.iter()).collect();
let miller_out = Bls12::multi_miller_loop(&refs);
let gt = miller_out.final_exponentiation();
Some(serialize_gt(gt, endianness))
}
#[cfg(test)]
mod tests {
use {super::*, crate::test_vectors::*, bytemuck::cast_slice};
fn run_pairing_test(
test_name: &str,
num_pairs: u64,
input_be: &[u8],
output_be: &[u8],
input_le: &[u8],
output_le: &[u8],
) {
let num_pairs = num_pairs as usize;
let g1_len_bytes = num_pairs * 96;
// --- Test Big Endian ---
let (g1_bytes_be, g2_bytes_be) = input_be.split_at(g1_len_bytes);
let g1_pods_be: &[PodG1Point] = cast_slice(g1_bytes_be);
let g2_pods_be: &[PodG2Point] = cast_slice(g2_bytes_be);
assert_eq!(g1_pods_be.len(), num_pairs);
assert_eq!(g2_pods_be.len(), num_pairs);
let result_be = bls12_381_pairing_map(Version::V0, g1_pods_be, g2_pods_be, Endianness::BE);
let expected_be = PodGtElement(output_be.try_into().expect("valid output length"));
assert_eq!(
result_be,
Some(expected_be),
"Pairing {test_name} BE Test Failed",
);
// --- Test Little Endian ---
let (g1_bytes_le, g2_bytes_le) = input_le.split_at(g1_len_bytes);
let g1_pods_le: &[PodG1Point] = cast_slice(g1_bytes_le);
let g2_pods_le: &[PodG2Point] = cast_slice(g2_bytes_le);
let result_le = bls12_381_pairing_map(Version::V0, g1_pods_le, g2_pods_le, Endianness::LE);
let expected_le = PodGtElement(output_le.try_into().expect("valid output length"));
assert_eq!(
result_le,
Some(expected_le),
"Pairing {test_name} LE Test Failed",
);
}
#[test]
fn test_pairing_identity() {
run_pairing_test(
"Pair: IDENTITY",
0,
INPUT_BE_PAIRING_IDENTITY,
OUTPUT_BE_PAIRING_IDENTITY,
INPUT_LE_PAIRING_IDENTITY,
OUTPUT_LE_PAIRING_IDENTITY,
);
}
#[test]
fn test_pairing_one_pair() {
run_pairing_test(
"Pair: ONE_PAIR",
1,
INPUT_BE_PAIRING_ONE_PAIR,
OUTPUT_BE_PAIRING_ONE_PAIR,
INPUT_LE_PAIRING_ONE_PAIR,
OUTPUT_LE_PAIRING_ONE_PAIR,
);
}
#[test]
fn test_pairing_two_pairs() {
run_pairing_test(
"Pair: TWO_PAIRS",
2,
INPUT_BE_PAIRING_TWO_PAIRS,
OUTPUT_BE_PAIRING_TWO_PAIRS,
INPUT_LE_PAIRING_TWO_PAIRS,
OUTPUT_LE_PAIRING_TWO_PAIRS,
);
}
#[test]
fn test_pairing_three_pairs() {
run_pairing_test(
"Pair: THREE_PAIRS",
3,
INPUT_BE_PAIRING_THREE_PAIRS,
OUTPUT_BE_PAIRING_THREE_PAIRS,
INPUT_LE_PAIRING_THREE_PAIRS,
OUTPUT_LE_PAIRING_THREE_PAIRS,
);
}
#[test]
fn test_pairing_bilinearity() {
// e(aP, Q) * e(P, -aQ) == 1
run_pairing_test(
"Pair: BILINEARITY_IDENTITY",
2,
INPUT_BE_PAIRING_BILINEARITY_IDENTITY,
OUTPUT_BE_PAIRING_BILINEARITY_IDENTITY,
INPUT_LE_PAIRING_BILINEARITY_IDENTITY,
OUTPUT_LE_PAIRING_BILINEARITY_IDENTITY,
);
}
#[test]
fn test_pairing_length_limits() {
let (g1_bytes, g2_bytes) = INPUT_BE_PAIRING_ONE_PAIR.split_at(96);
let p1: PodG1Point = cast_slice::<u8, PodG1Point>(g1_bytes)[0];
let p2: PodG2Point = cast_slice::<u8, PodG2Point>(g2_bytes)[0];
let count_ok = MAX_PAIRING_LENGTH;
let g1_vec_ok = vec![p1; count_ok];
let g2_vec_ok = vec![p2; count_ok];
assert!(
bls12_381_pairing_map(Version::V0, &g1_vec_ok, &g2_vec_ok, Endianness::BE).is_some(),
"Pairing with 8 pairs should succeed"
);
let count_fail = MAX_PAIRING_LENGTH + 1;
let g1_vec_fail = vec![p1; count_fail];
let g2_vec_fail = vec![p2; count_fail];
assert_eq!(
bls12_381_pairing_map(Version::V0, &g1_vec_fail, &g2_vec_fail, Endianness::BE),
None,
"Pairing with 9 pairs should fail"
);
}
}

View file

@ -0,0 +1,232 @@
use {
crate::{
Version,
encoding::{Endianness, PodG1Point, PodG2Point, swap_fq_endianness, swap_g2_c0_c1},
},
blstrs::{G1Projective, G2Projective},
group::prime::PrimeCurveAffine,
};
/// Performs point subtraction on G1: `P1 - P2`.
/// Does not check if points are in the correct subgroup for efficiency.
pub fn bls12_381_g1_subtraction_unchecked(
_version: Version,
p1: &PodG1Point,
p2: &PodG1Point,
endianness: Endianness,
) -> Option<PodG1Point> {
// skip subgroup check for efficiency
let p1_affine = p1.to_affine_subgroup_unchecked(endianness)?;
let p2_affine = p2.to_affine_subgroup_unchecked(endianness)?;
let diff_affine = if bool::from(p1_affine.is_identity()) {
#[allow(clippy::arithmetic_side_effects)]
(-p2_affine).to_uncompressed()
} else {
#[allow(clippy::arithmetic_side_effects)]
(G1Projective::from(p1_affine) - p2_affine).to_uncompressed()
};
let mut result = PodG1Point(diff_affine);
if matches!(endianness, Endianness::LE) {
swap_fq_endianness(&mut result.0);
}
Some(result)
}
/// Performs point subtraction on G2: `P1 - P2`.
/// Does not check if points are in the correct subgroup for efficiency.
pub fn bls12_381_g2_subtraction_unchecked(
_version: Version,
p1: &PodG2Point,
p2: &PodG2Point,
endianness: Endianness,
) -> Option<PodG2Point> {
// skip subgroup check for efficiency
let p1_affine = p1.to_affine_subgroup_unchecked(endianness)?;
let p2_affine = p2.to_affine_subgroup_unchecked(endianness)?;
let diff_affine = if bool::from(p1_affine.is_identity()) {
#[allow(clippy::arithmetic_side_effects)]
(-p2_affine).to_uncompressed()
} else {
#[allow(clippy::arithmetic_side_effects)]
(G2Projective::from(p1_affine) - p2_affine).to_uncompressed()
};
let mut result = PodG2Point(diff_affine);
if matches!(endianness, Endianness::LE) {
swap_g2_c0_c1(&mut result.0);
swap_fq_endianness(&mut result.0);
}
Some(result)
}
#[cfg(test)]
mod tests {
use {super::*, crate::test_vectors::*, bytemuck::pod_read_unaligned};
fn to_pod_g1(bytes: &[u8]) -> PodG1Point {
pod_read_unaligned(bytes)
}
fn to_pod_g2(bytes: &[u8]) -> PodG2Point {
pod_read_unaligned(bytes)
}
fn run_g1_test(
test_name: &str,
input_be: &[u8],
output_be: &[u8],
input_le: &[u8],
output_le: &[u8],
) {
let (p1_be, p2_be) = input_be.split_at(96);
let p1_be = to_pod_g1(p1_be);
let p2_be = to_pod_g1(p2_be);
let expected_be = to_pod_g1(output_be);
let result_be =
bls12_381_g1_subtraction_unchecked(Version::V0, &p1_be, &p2_be, Endianness::BE);
assert_eq!(
result_be,
Some(expected_be),
"G1 {test_name} BE Test Failed",
);
let (p1_le, p2_le) = input_le.split_at(96);
let p1_le = to_pod_g1(p1_le);
let p2_le = to_pod_g1(p2_le);
let expected_le = to_pod_g1(output_le);
let result_le =
bls12_381_g1_subtraction_unchecked(Version::V0, &p1_le, &p2_le, Endianness::LE);
assert_eq!(
result_le,
Some(expected_le),
"G1 {test_name} LE Test Failed",
);
}
fn run_g2_test(
test_name: &str,
input_be: &[u8],
output_be: &[u8],
input_le: &[u8],
output_le: &[u8],
) {
let (p1_be, p2_be) = input_be.split_at(192);
let p1_be = to_pod_g2(p1_be);
let p2_be = to_pod_g2(p2_be);
let expected_be = to_pod_g2(output_be);
let result_be =
bls12_381_g2_subtraction_unchecked(Version::V0, &p1_be, &p2_be, Endianness::BE);
assert_eq!(
result_be,
Some(expected_be),
"G2 {test_name} BE Test Failed",
);
let (p1_le, p2_le) = input_le.split_at(192);
let p1_le = to_pod_g2(p1_le);
let p2_le = to_pod_g2(p2_le);
let expected_le = to_pod_g2(output_le);
let result_le =
bls12_381_g2_subtraction_unchecked(Version::V0, &p1_le, &p2_le, Endianness::LE);
assert_eq!(
result_le,
Some(expected_le),
"G2 {test_name} LE Test Failed",
);
}
#[test]
fn test_g1_subtraction_random() {
run_g1_test(
"SUB: P (Rand) - Q (Rand)",
INPUT_BE_G1_SUB_RANDOM,
OUTPUT_BE_G1_SUB_RANDOM,
INPUT_LE_G1_SUB_RANDOM,
OUTPUT_LE_G1_SUB_RANDOM,
);
}
#[test]
fn test_g1_subtraction_p_minus_p() {
// Result should be Identity
run_g1_test(
"SUB: P - P",
INPUT_BE_G1_SUB_P_MINUS_P,
OUTPUT_BE_G1_SUB_P_MINUS_P,
INPUT_LE_G1_SUB_P_MINUS_P,
OUTPUT_LE_G1_SUB_P_MINUS_P,
);
}
#[test]
fn test_g1_subtraction_infinity_edge_cases() {
// Inf - P (Should result in -P)
run_g1_test(
"SUB: Inf - P",
INPUT_BE_G1_SUB_INF_MINUS_P,
OUTPUT_BE_G1_SUB_INF_MINUS_P,
INPUT_LE_G1_SUB_INF_MINUS_P,
OUTPUT_LE_G1_SUB_INF_MINUS_P,
);
// P - Inf (Should result in P)
run_g1_test(
"SUB: P - Inf",
INPUT_BE_G1_SUB_P_MINUS_INF,
OUTPUT_BE_G1_SUB_P_MINUS_INF,
INPUT_LE_G1_SUB_P_MINUS_INF,
OUTPUT_LE_G1_SUB_P_MINUS_INF,
);
}
#[test]
fn test_g2_subtraction_random() {
run_g2_test(
"SUB: P (Rand) - Q (Rand)",
INPUT_BE_G2_SUB_RANDOM,
OUTPUT_BE_G2_SUB_RANDOM,
INPUT_LE_G2_SUB_RANDOM,
OUTPUT_LE_G2_SUB_RANDOM,
);
}
#[test]
fn test_g2_subtraction_p_minus_p() {
// Result should be Identity
run_g2_test(
"SUB: P - P",
INPUT_BE_G2_SUB_P_MINUS_P,
OUTPUT_BE_G2_SUB_P_MINUS_P,
INPUT_LE_G2_SUB_P_MINUS_P,
OUTPUT_LE_G2_SUB_P_MINUS_P,
);
}
#[test]
fn test_g2_subtraction_infinity_edge_cases() {
// Inf - P (Should result in -P)
run_g2_test(
"SUB: Inf - P",
INPUT_BE_G2_SUB_INF_MINUS_P,
OUTPUT_BE_G2_SUB_INF_MINUS_P,
INPUT_LE_G2_SUB_INF_MINUS_P,
OUTPUT_LE_G2_SUB_INF_MINUS_P,
);
// P - Inf (Should result in P)
run_g2_test(
"SUB: P - Inf",
INPUT_BE_G2_SUB_P_MINUS_INF,
OUTPUT_BE_G2_SUB_P_MINUS_INF,
INPUT_LE_G2_SUB_P_MINUS_INF,
OUTPUT_LE_G2_SUB_P_MINUS_INF,
);
}
}

View file

@ -0,0 +1,113 @@
use hex_literal::hex;
// Test Case: G1_ADD_RANDOM
pub const INPUT_BE_G1_ADD_RANDOM: &[u8] = &hex!(
"0956a9d4ecf511657fb7380d6364b785396b60dcc6c502d7e1afd439a88f687f75f2b4c8a287489b589a3a5a3a2ef8b00ace1970f00139590a1ea55ea4fcdbe185d6a10476b17b353935e9ff7075f1f7b9c3e8247b1fdd0639b0fba3c32723af0d203dd7537cbabd52004ff443a7153230e5086b330f132f4b4df6b93f428f6dedd39992a3af4a4532c6ebda09aae12e16d37454207382e06afacd8fee734acfeec1e8103b8c14fc0722902f8938beaaebbdee2d613ac7ca2da48bc8bed7093b"
);
pub const INPUT_LE_G1_ADD_RANDOM: &[u8] = &hex!(
"b0f82e3a5a3a9a589b4887a2c8b4f2757f688fa839d4afe1d702c5c6dc606b3985b764630d38b77f6511f5ecd4a95609af2327c3a3fbb03906dd1f7b24e8c3b9f7f17570ffe93539357bb17604a1d685e1dbfca45ea51e0a593901f07019ce0a2ee1aa09daebc632454aafa39299d3ed6d8f423fb9f64d4b2f130f336b08e5303215a743f44f0052bdba7c53d73d200d3b09d7bec88ba42dcac73a612deebdebaabe38892f902207fc148c3b10e8c1eecf4a73ee8fcdfa6ae08273205474d316"
);
pub const OUTPUT_BE_G1_ADD_RANDOM: &[u8] = &hex!(
"173eff899dbc6256c06688abbb319b53cc85d99089670f04744b7f411d59df9320a15b6860d3ef66e95f3082cf9a13bd127066912449111b2f60742d381910bf381556d885f5cf479e1f1d3354b9868a404437a13799d69bfa15e904037529ef"
);
pub const OUTPUT_LE_G1_ADD_RANDOM: &[u8] = &hex!(
"bd139acf82305fe966efd360685ba12093df591d417f4b74040f678990d985cc539b31bbab8866c05662bc9d89ff3e17ef29750304e915fa9bd69937a13744408a86b954331d1f9e47cff585d8561538bf1019382d74602f1b11492491667012"
);
// Test Case: G1_ADD_DOUBLING
pub const INPUT_BE_G1_ADD_DOUBLING: &[u8] = &hex!(
"0956a9d4ecf511657fb7380d6364b785396b60dcc6c502d7e1afd439a88f687f75f2b4c8a287489b589a3a5a3a2ef8b00ace1970f00139590a1ea55ea4fcdbe185d6a10476b17b353935e9ff7075f1f7b9c3e8247b1fdd0639b0fba3c32723af0956a9d4ecf511657fb7380d6364b785396b60dcc6c502d7e1afd439a88f687f75f2b4c8a287489b589a3a5a3a2ef8b00ace1970f00139590a1ea55ea4fcdbe185d6a10476b17b353935e9ff7075f1f7b9c3e8247b1fdd0639b0fba3c32723af"
);
pub const INPUT_LE_G1_ADD_DOUBLING: &[u8] = &hex!(
"b0f82e3a5a3a9a589b4887a2c8b4f2757f688fa839d4afe1d702c5c6dc606b3985b764630d38b77f6511f5ecd4a95609af2327c3a3fbb03906dd1f7b24e8c3b9f7f17570ffe93539357bb17604a1d685e1dbfca45ea51e0a593901f07019ce0ab0f82e3a5a3a9a589b4887a2c8b4f2757f688fa839d4afe1d702c5c6dc606b3985b764630d38b77f6511f5ecd4a95609af2327c3a3fbb03906dd1f7b24e8c3b9f7f17570ffe93539357bb17604a1d685e1dbfca45ea51e0a593901f07019ce0a"
);
pub const OUTPUT_BE_G1_ADD_DOUBLING: &[u8] = &hex!(
"14673e7a2b8871c549e78b4470a0659e6590ab002cd0c141a41db171d508f90310f07dfaf61a1d5bc83cfc80c5b6c4351700fec75600968a207694b7dcf41b177b8ab65a1887260d5584735c34f53758144328bc7866736fc05be9cce148356c"
);
pub const OUTPUT_LE_G1_ADD_DOUBLING: &[u8] = &hex!(
"35c4b6c580fc3cc85b1d1af6fa7df01003f908d571b11da441c1d02c00ab90659e65a070448be749c571882b7a3e67146c3548e1cce95bc06f736678bc2843145837f5345c7384550d2687185ab68a7b171bf4dcb79476208a960056c7fe0017"
);
// Test Case: G1_ADD_P_PLUS_INF
pub const INPUT_BE_G1_ADD_P_PLUS_INF: &[u8] = &hex!(
"0956a9d4ecf511657fb7380d6364b785396b60dcc6c502d7e1afd439a88f687f75f2b4c8a287489b589a3a5a3a2ef8b00ace1970f00139590a1ea55ea4fcdbe185d6a10476b17b353935e9ff7075f1f7b9c3e8247b1fdd0639b0fba3c32723af400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
pub const INPUT_LE_G1_ADD_P_PLUS_INF: &[u8] = &hex!(
"b0f82e3a5a3a9a589b4887a2c8b4f2757f688fa839d4afe1d702c5c6dc606b3985b764630d38b77f6511f5ecd4a95609af2327c3a3fbb03906dd1f7b24e8c3b9f7f17570ffe93539357bb17604a1d685e1dbfca45ea51e0a593901f07019ce0a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
pub const OUTPUT_BE_G1_ADD_P_PLUS_INF: &[u8] = &hex!(
"0956a9d4ecf511657fb7380d6364b785396b60dcc6c502d7e1afd439a88f687f75f2b4c8a287489b589a3a5a3a2ef8b00ace1970f00139590a1ea55ea4fcdbe185d6a10476b17b353935e9ff7075f1f7b9c3e8247b1fdd0639b0fba3c32723af"
);
pub const OUTPUT_LE_G1_ADD_P_PLUS_INF: &[u8] = &hex!(
"b0f82e3a5a3a9a589b4887a2c8b4f2757f688fa839d4afe1d702c5c6dc606b3985b764630d38b77f6511f5ecd4a95609af2327c3a3fbb03906dd1f7b24e8c3b9f7f17570ffe93539357bb17604a1d685e1dbfca45ea51e0a593901f07019ce0a"
);
// Test Case: G1_ADD_INF_PLUS_INF
pub const INPUT_BE_G1_ADD_INF_PLUS_INF: &[u8] = &hex!(
"400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
pub const INPUT_LE_G1_ADD_INF_PLUS_INF: &[u8] = &hex!(
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
pub const OUTPUT_BE_G1_ADD_INF_PLUS_INF: &[u8] = &hex!(
"400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
pub const OUTPUT_LE_G1_ADD_INF_PLUS_INF: &[u8] = &hex!(
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
// Test Case: G2_ADD_RANDOM
pub const INPUT_BE_G2_ADD_RANDOM: &[u8] = &hex!(
"0b53153e04ae7b83a3133ed8c03019b839cf5046fd3381a957b68e019466cb63566fcf37cc75528ac75983cf9ef4cc8b1297d6c99e2765fcbd35fbeccd1b98a3e86535c512eef146b6716ff9637a2adc377f37f7aca4b7a992e5dab990b056ae1584961df1f1d74d0c4bee67175abdbf5548b5d655fdb7969e08fab2dca9d7f392d5960c0628bcc538d22e7d57051107181ba01663720907f46cb3c9262199db0ad302d44a5f97dfc86079a60aba7a28de5722e331a6c38b25dd2ce35677be290e6eb4ae2e4a917d5e1c27cd6b7e35bc2445a262694f319488e50580c5bb00ea8dc9f6df674bb121024b5a218b989c59195b9e64140c8782bfb505295ec35924b56fee18bbb2b38f11b544cbb886b9c3b01b5a021da5d1108f0be0fb3fbcda2917475b5aca6c50a0c8c2a26dc86005669cf52bf7dd8b94fefdb7a153fdf71647855d247fa2f83140adc911d208d6124107de0b0478115531cd5f84d098885c13c3b088275acf11c30ed721bfe83b03564e4e95a5b391a1bef743f3fc89012747"
);
pub const INPUT_LE_G2_ADD_RANDOM: &[u8] = &hex!(
"ae56b090b9dae592a9b7a4acf7377f37dc2a7a63f96f71b646f1ee12c53565e8a3981bcdecfb35bdfc65279ec9d697128bccf49ecf8359c78a5275cc37cf6f5663cb6694018eb657a98133fd4650cf39b81930c0d83e13a3837bae043e15530b29be7756e32cdd258bc3a631e32257de287aba0aa67960c8df975f4ad402d30adb992126c9b36cf40709726316a01b18071105577d2ed238c5bc28060c96d592f3d7a9dcb2fa089e96b7fd55d6b54855bfbd5a1767ee4b0c4dd7f1f11d96841529dabc3ffbe00b8f10d1a51d025a1bb0c3b986b8cb44b5118fb3b2bb18ee6fb52459c35e2905b5bf82870c14649e5b19599c988b215a4b0221b14b67dff6c98dea00bbc58005e58894314f6962a24524bc357e6bcd271c5e7d914a2eaeb46e0e47270189fcf343f7bea191b3a5954e4e56033be8bf21d70ec311cf5a2788b0c3135c8898d0845fcd31551178040bde074112d608d211c9ad4031f8a27f245d854716f7fd53a1b7fdfe948bddf72bf59c660560c86da2c2c8a0506cca5a5b4717"
);
pub const OUTPUT_BE_G2_ADD_RANDOM: &[u8] = &hex!(
"159d0afb9c3818ae185b62c92125444c29a10ca61080a11f6c1f5cd838c5c642d206406a9a608739aa77dcd2ee4962530f924a7a4628ba7bbf8b0bf9dd140c3e5125bf16f8714e7c1d9de4dcbb06fc0f3bec62c6fccdb0bec0c79ad55c7ebd37026d080f80be1f6ab48260d77d320b7c4777531c41d1802f072ed49de6c733628fdc9dfeb3cbba74294c231c7bcf361105f824f7c1c97476cac97dc9c80d44f427cf46ce0c75cec009e83e218958491079be8b5b9e5093cf7d17b15de3846759"
);
pub const OUTPUT_LE_G2_ADD_RANDOM: &[u8] = &hex!(
"37bd7e5cd59ac7c0beb0cdfcc662ec3b0ffc06bbdce49d1d7c4e71f816bf25513e0c14ddf90b8bbf7bba28467a4a920f536249eed2dc77aa3987609a6a4006d242c6c538d85c1f6c1fa18010a60ca1294c442521c9625b18ae18389cfb0a9d15596784e35db1177dcf93509e5b8bbe7910495889213ee809c0ce750cce46cf27f4440dc8c97dc9ca7674c9c1f724f8051136cf7b1c234c2974bacbb3fe9ddc8f6233c7e69dd42e072f80d1411c5377477c0b327dd76082b46a1fbe800f086d02"
);
// Test Case: G2_ADD_DOUBLING
pub const INPUT_BE_G2_ADD_DOUBLING: &[u8] = &hex!(
"0b53153e04ae7b83a3133ed8c03019b839cf5046fd3381a957b68e019466cb63566fcf37cc75528ac75983cf9ef4cc8b1297d6c99e2765fcbd35fbeccd1b98a3e86535c512eef146b6716ff9637a2adc377f37f7aca4b7a992e5dab990b056ae1584961df1f1d74d0c4bee67175abdbf5548b5d655fdb7969e08fab2dca9d7f392d5960c0628bcc538d22e7d57051107181ba01663720907f46cb3c9262199db0ad302d44a5f97dfc86079a60aba7a28de5722e331a6c38b25dd2ce35677be290b53153e04ae7b83a3133ed8c03019b839cf5046fd3381a957b68e019466cb63566fcf37cc75528ac75983cf9ef4cc8b1297d6c99e2765fcbd35fbeccd1b98a3e86535c512eef146b6716ff9637a2adc377f37f7aca4b7a992e5dab990b056ae1584961df1f1d74d0c4bee67175abdbf5548b5d655fdb7969e08fab2dca9d7f392d5960c0628bcc538d22e7d57051107181ba01663720907f46cb3c9262199db0ad302d44a5f97dfc86079a60aba7a28de5722e331a6c38b25dd2ce35677be29"
);
pub const INPUT_LE_G2_ADD_DOUBLING: &[u8] = &hex!(
"ae56b090b9dae592a9b7a4acf7377f37dc2a7a63f96f71b646f1ee12c53565e8a3981bcdecfb35bdfc65279ec9d697128bccf49ecf8359c78a5275cc37cf6f5663cb6694018eb657a98133fd4650cf39b81930c0d83e13a3837bae043e15530b29be7756e32cdd258bc3a631e32257de287aba0aa67960c8df975f4ad402d30adb992126c9b36cf40709726316a01b18071105577d2ed238c5bc28060c96d592f3d7a9dcb2fa089e96b7fd55d6b54855bfbd5a1767ee4b0c4dd7f1f11d968415ae56b090b9dae592a9b7a4acf7377f37dc2a7a63f96f71b646f1ee12c53565e8a3981bcdecfb35bdfc65279ec9d697128bccf49ecf8359c78a5275cc37cf6f5663cb6694018eb657a98133fd4650cf39b81930c0d83e13a3837bae043e15530b29be7756e32cdd258bc3a631e32257de287aba0aa67960c8df975f4ad402d30adb992126c9b36cf40709726316a01b18071105577d2ed238c5bc28060c96d592f3d7a9dcb2fa089e96b7fd55d6b54855bfbd5a1767ee4b0c4dd7f1f11d968415"
);
pub const OUTPUT_BE_G2_ADD_DOUBLING: &[u8] = &hex!(
"1530e89c2912b7761679a292a428089239f047c47d3656ea16abf60fe5e7f3e50fc5f95f38de7ccb1c2b5fdd7aed524d0eaeb83d207093219506de0b08f0e4e9a4dc47a7a9862b0108e128b2d805f0cbfd9a7aaa5f302637102ce607f0cbbdce174d83a7b7176827d5bc9513c76c88cdbb0befd3eefea516bb06fc46b15da1bf8d48a8420c8725ee96d2d25d5ca205d6027b96fc85a504b88078dddb68a57c9038f77673b9064095bf4f9adbbd18ae7834b7ed5a212eb7238781f6a096511f30"
);
pub const OUTPUT_LE_G2_ADD_DOUBLING: &[u8] = &hex!(
"cebdcbf007e62c103726305faa7a9afdcbf005d8b228e108012b86a9a747dca4e9e4f0080bde0695219370203db8ae0e4d52ed7add5f2b1ccb7cde385ff9c50fe5f3e7e50ff6ab16ea56367dc447f039920828a492a2791676b712299ce83015301f5196a0f6818723b72e215aedb73478ae18bddb9a4fbf954006b97376f738907ca568dbdd7880b804a585fc967b02d605a25c5dd2d296ee25870c42a8488dbfa15db146fc06bb16a5feeed3ef0bbbcd886cc71395bcd5276817b7a7834d17"
);
// Test Case: G2_ADD_P_PLUS_INF
pub const INPUT_BE_G2_ADD_P_PLUS_INF: &[u8] = &hex!(
"0b53153e04ae7b83a3133ed8c03019b839cf5046fd3381a957b68e019466cb63566fcf37cc75528ac75983cf9ef4cc8b1297d6c99e2765fcbd35fbeccd1b98a3e86535c512eef146b6716ff9637a2adc377f37f7aca4b7a992e5dab990b056ae1584961df1f1d74d0c4bee67175abdbf5548b5d655fdb7969e08fab2dca9d7f392d5960c0628bcc538d22e7d57051107181ba01663720907f46cb3c9262199db0ad302d44a5f97dfc86079a60aba7a28de5722e331a6c38b25dd2ce35677be29400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
pub const INPUT_LE_G2_ADD_P_PLUS_INF: &[u8] = &hex!(
"ae56b090b9dae592a9b7a4acf7377f37dc2a7a63f96f71b646f1ee12c53565e8a3981bcdecfb35bdfc65279ec9d697128bccf49ecf8359c78a5275cc37cf6f5663cb6694018eb657a98133fd4650cf39b81930c0d83e13a3837bae043e15530b29be7756e32cdd258bc3a631e32257de287aba0aa67960c8df975f4ad402d30adb992126c9b36cf40709726316a01b18071105577d2ed238c5bc28060c96d592f3d7a9dcb2fa089e96b7fd55d6b54855bfbd5a1767ee4b0c4dd7f1f11d968415000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
pub const OUTPUT_BE_G2_ADD_P_PLUS_INF: &[u8] = &hex!(
"0b53153e04ae7b83a3133ed8c03019b839cf5046fd3381a957b68e019466cb63566fcf37cc75528ac75983cf9ef4cc8b1297d6c99e2765fcbd35fbeccd1b98a3e86535c512eef146b6716ff9637a2adc377f37f7aca4b7a992e5dab990b056ae1584961df1f1d74d0c4bee67175abdbf5548b5d655fdb7969e08fab2dca9d7f392d5960c0628bcc538d22e7d57051107181ba01663720907f46cb3c9262199db0ad302d44a5f97dfc86079a60aba7a28de5722e331a6c38b25dd2ce35677be29"
);
pub const OUTPUT_LE_G2_ADD_P_PLUS_INF: &[u8] = &hex!(
"ae56b090b9dae592a9b7a4acf7377f37dc2a7a63f96f71b646f1ee12c53565e8a3981bcdecfb35bdfc65279ec9d697128bccf49ecf8359c78a5275cc37cf6f5663cb6694018eb657a98133fd4650cf39b81930c0d83e13a3837bae043e15530b29be7756e32cdd258bc3a631e32257de287aba0aa67960c8df975f4ad402d30adb992126c9b36cf40709726316a01b18071105577d2ed238c5bc28060c96d592f3d7a9dcb2fa089e96b7fd55d6b54855bfbd5a1767ee4b0c4dd7f1f11d968415"
);
// Test Case: G2_ADD_INF_PLUS_INF
pub const INPUT_BE_G2_ADD_INF_PLUS_INF: &[u8] = &hex!(
"400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
pub const INPUT_LE_G2_ADD_INF_PLUS_INF: &[u8] = &hex!(
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
pub const OUTPUT_BE_G2_ADD_INF_PLUS_INF: &[u8] = &hex!(
"400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
pub const OUTPUT_LE_G2_ADD_INF_PLUS_INF: &[u8] = &hex!(
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);

View file

@ -0,0 +1,117 @@
use hex_literal::hex;
// Test Case: G1_DECOMPRESS_RANDOM
pub const INPUT_BE_G1_DECOMPRESS_RANDOM: &[u8] = &hex!(
"af9ff5448e60bc9a718f463ac102bd6f8772e6460c19076a6c89d5806e5a8ef44b6f3b8af09e37a4e564987a26b9deda"
);
pub const INPUT_LE_G1_DECOMPRESS_RANDOM: &[u8] = &hex!(
"dadeb9267a9864e5a4379ef08a3b6f4bf48e5a6e80d5896c6a07190c46e672876fbd02c13a468f719abc608e44f59faf"
);
pub const OUTPUT_BE_G1_DECOMPRESS_RANDOM: &[u8] = &hex!(
"0f9ff5448e60bc9a718f463ac102bd6f8772e6460c19076a6c89d5806e5a8ef44b6f3b8af09e37a4e564987a26b9deda124f01f63e23a2ea926d07552c680afa9e1fb5f475c11b35b84fa0eda83329c83a046b5ff6abf1ca78e4878764327b3a"
);
pub const OUTPUT_LE_G1_DECOMPRESS_RANDOM: &[u8] = &hex!(
"dadeb9267a9864e5a4379ef08a3b6f4bf48e5a6e80d5896c6a07190c46e672876fbd02c13a468f719abc608e44f59f0f3a7b32648787e478caf1abf65f6b043ac82933a8eda04fb8351bc175f4b51f9efa0a682c55076d92eaa2233ef6014f12"
);
// Test Case: G1_DECOMPRESS_INFINITY
pub const INPUT_BE_G1_DECOMPRESS_INFINITY: &[u8] = &hex!(
"c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
pub const INPUT_LE_G1_DECOMPRESS_INFINITY: &[u8] = &hex!(
"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0"
);
pub const OUTPUT_BE_G1_DECOMPRESS_INFINITY: &[u8] = &hex!(
"400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
pub const OUTPUT_LE_G1_DECOMPRESS_INFINITY: &[u8] = &hex!(
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
// Test Case: G1_DECOMPRESS_GENERATOR
pub const INPUT_BE_G1_DECOMPRESS_GENERATOR: &[u8] = &hex!(
"97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb"
);
pub const INPUT_LE_G1_DECOMPRESS_GENERATOR: &[u8] = &hex!(
"bbc622db0af03afbef1a7af93fe8556c58ac1b173f3a4ea105b974974f8c68c30faca94f8c63952694d79731a7d3f197"
);
pub const OUTPUT_BE_G1_DECOMPRESS_GENERATOR: &[u8] = &hex!(
"17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1"
);
pub const OUTPUT_LE_G1_DECOMPRESS_GENERATOR: &[u8] = &hex!(
"bbc622db0af03afbef1a7af93fe8556c58ac1b173f3a4ea105b974974f8c68c30faca94f8c63952694d79731a7d3f117e1e7c5462923aa0ce48a88a244c73cd0edb3042ccb18db00f60ad0d595e0f5fce48a1d74ed309ea0f1a0aae381f4b308"
);
// Test Case: G1_DECOMPRESS_RANDOM_INVALID_CURVE
pub const INPUT_BE_G1_DECOMPRESS_RANDOM_INVALID_CURVE: &[u8] = &hex!(
"af9ff5448e60bc9a718f463ac102bd6f8772e6460c19076a6c89d5806e5a8ef44b6f3b8af09e37a4e564987a26b9dedb"
);
pub const INPUT_LE_G1_DECOMPRESS_RANDOM_INVALID_CURVE: &[u8] = &hex!(
"dbdeb9267a9864e5a4379ef08a3b6f4bf48e5a6e80d5896c6a07190c46e672876fbd02c13a468f719abc608e44f59faf"
);
// Test Case: G1_DECOMPRESS_FIELD_TOO_LARGE_INVALID
pub const INPUT_BE_G1_DECOMPRESS_FIELD_TOO_LARGE_INVALID: &[u8] = &hex!(
"9a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab"
);
pub const INPUT_LE_G1_DECOMPRESS_FIELD_TOO_LARGE_INVALID: &[u8] = &hex!(
"abaafffffffffeb9ffff53b1feffab1e24f6b0f6a0d23067bf1285f3844b7764d7ac4b43b6a71b4b9ae67f39ea11019a"
);
// Test Case: G2_DECOMPRESS_RANDOM
pub const INPUT_BE_G2_DECOMPRESS_RANDOM: &[u8] = &hex!(
"8f6a12dc289804e48b236892b34acdac92890b6a4a2a878935f940fbade830d17dde0dd179eeb9b36f6947df2730c3681718aa3b6f6aa733e7bae0b6ac490f12d38f3b0273bec4a36f0b24855660bc871025d8af47b6de1fcf9b10ff704ef26f"
);
pub const INPUT_LE_G2_DECOMPRESS_RANDOM: &[u8] = &hex!(
"6ff24e70ff109bcf1fdeb647afd8251087bc605685240b6fa3c4be73023b8fd3120f49acb6e0bae733a76a6f3baa181768c33027df47696fb3b9ee79d10dde7dd130e8adfb40f93589872a4a6a0b8992accd4ab39268238be4049828dc126a8f"
);
pub const OUTPUT_BE_G2_DECOMPRESS_RANDOM: &[u8] = &hex!(
"0f6a12dc289804e48b236892b34acdac92890b6a4a2a878935f940fbade830d17dde0dd179eeb9b36f6947df2730c3681718aa3b6f6aa733e7bae0b6ac490f12d38f3b0273bec4a36f0b24855660bc871025d8af47b6de1fcf9b10ff704ef26f0bd9f453c96fb6a8abcdb776c755829d5f459f7e7a1b5c54fd9360b04a390de4b26ff69d4a78aeff925c20d6a438ce900d3b6ffbaa559fdb6cbb1f0f6ab040bf384dd95790c494150cab63798078bbe0c06b68b24bcd7640eaa8d60b7d993705"
);
pub const OUTPUT_LE_G2_DECOMPRESS_RANDOM: &[u8] = &hex!(
"6ff24e70ff109bcf1fdeb647afd8251087bc605685240b6fa3c4be73023b8fd3120f49acb6e0bae733a76a6f3baa181768c33027df47696fb3b9ee79d10dde7dd130e8adfb40f93589872a4a6a0b8992accd4ab39268238be4049828dc126a0f0537997d0bd6a8ea4076cd4bb2686bc0e0bb78807963ab0c1594c49057d94d38bf40b06a0f1fbb6cdb9f55aafb6f3b0d90ce38a4d6205c92ffae784a9df66fb2e40d394ab06093fd545c1b7a7e9f455f9d8255c776b7cdaba8b66fc953f4d90b"
);
// Test Case: G2_DECOMPRESS_INFINITY
pub const INPUT_BE_G2_DECOMPRESS_INFINITY: &[u8] = &hex!(
"c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
pub const INPUT_LE_G2_DECOMPRESS_INFINITY: &[u8] = &hex!(
"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0"
);
pub const OUTPUT_BE_G2_DECOMPRESS_INFINITY: &[u8] = &hex!(
"400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
pub const OUTPUT_LE_G2_DECOMPRESS_INFINITY: &[u8] = &hex!(
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
// Test Case: G2_DECOMPRESS_GENERATOR
pub const INPUT_BE_G2_DECOMPRESS_GENERATOR: &[u8] = &hex!(
"93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8"
);
pub const INPUT_LE_G2_DECOMPRESS_GENERATOR: &[u8] = &hex!(
"b8bd21c1c85680d4efbb05a82603ac0b77d1e37a640b51b4023b40fad47ae4c65110c52d27050826910a8ff0b2a24a027e2b045d057dace5575d941312f14c3349507fdcbb61dab51ab62099d0d06b59654f2788a0d3ac7d609f7152602be093"
);
pub const OUTPUT_BE_G2_DECOMPRESS_GENERATOR: &[u8] = &hex!(
"13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801"
);
pub const OUTPUT_LE_G2_DECOMPRESS_GENERATOR: &[u8] = &hex!(
"b8bd21c1c85680d4efbb05a82603ac0b77d1e37a640b51b4023b40fad47ae4c65110c52d27050826910a8ff0b2a24a027e2b045d057dace5575d941312f14c3349507fdcbb61dab51ab62099d0d06b59654f2788a0d3ac7d609f7152602be0130128b808865493e189a2ac3bccc93a922cd16051699a426da7d3bd8caa9bfdad1a352edac6cdc98c116e7d7227d5e50cbe795ff05f07a9aaa11dec5c270d373fab992e57ab927426af63a7857e283ecb998bc22bb0d2ac32cc34a72ea0c40606"
);
// Test Case: G2_DECOMPRESS_RANDOM_INVALID_CURVE
pub const INPUT_BE_G2_DECOMPRESS_RANDOM_INVALID_CURVE: &[u8] = &hex!(
"8f6a12dc289804e48b236892b34acdac92890b6a4a2a878935f940fbade830d17dde0dd179eeb9b36f6947df2730c3681718aa3b6f6aa733e7bae0b6ac490f12d38f3b0273bec4a36f0b24855660bc871025d8af47b6de1fcf9b10ff704ef270"
);
pub const INPUT_LE_G2_DECOMPRESS_RANDOM_INVALID_CURVE: &[u8] = &hex!(
"70f24e70ff109bcf1fdeb647afd8251087bc605685240b6fa3c4be73023b8fd3120f49acb6e0bae733a76a6f3baa181768c33027df47696fb3b9ee79d10dde7dd130e8adfb40f93589872a4a6a0b8992accd4ab39268238be4049828dc126a8f"
);
// Test Case: G2_DECOMPRESS_FIELD_TOO_LARGE_INVALID
pub const INPUT_BE_G2_DECOMPRESS_FIELD_TOO_LARGE_INVALID: &[u8] = &hex!(
"8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab"
);
pub const INPUT_LE_G2_DECOMPRESS_FIELD_TOO_LARGE_INVALID: &[u8] = &hex!(
"abaafffffffffeb9ffff53b1feffab1e24f6b0f6a0d23067bf1285f3844b7764d7ac4b43b6a71b4b9ae67f39ea11011a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080"
);

View file

@ -0,0 +1,10 @@
pub use {
addition::*, decompression::*, multiplication::*, pairing::*, subtraction::*, validation::*,
};
pub mod addition;
pub mod decompression;
pub mod multiplication;
pub mod pairing;
pub mod subtraction;
pub mod validation;

View file

@ -0,0 +1,141 @@
use hex_literal::hex;
// Test Case: G1_MUL_RANDOM
pub const INPUT_BE_G1_MUL_RANDOM: &[u8] = &hex!(
"1412e9c96ece3820082c8c7925c49d38b486a421b48293071aefb7a3db558fc5f7f375fcc9ab9c5ad2072b5c5982a5e005651836bd16494c9188633b33ff7c2b3d08791e765afe0c7e5c984e2ce77e38dc23367502afbe698abcca24ab0ce7e11dc06f97bb256d5b81dfbce1750378a26b429fff3d802920f25fe8ca6abc9a93"
);
pub const INPUT_LE_G1_MUL_RANDOM: &[u8] = &hex!(
"e0a582595c2b07d25a9cabc9fc75f3f7c58f55dba3b7ef1a079382b421a486b4389dc425798c2c082038ce6ec9e91214e1e70cab24cabc8a69beaf02753623dc387ee72c4e985c7e0cfe5a761e79083d2b7cff333b6388914c4916bd36186505939abc6acae85ff22029803dff9f426ba2780375e1bcdf815b6d25bb976fc01d"
);
pub const OUTPUT_BE_G1_MUL_RANDOM: &[u8] = &hex!(
"166548ff03f727daea75d05b9e727e37a647e3cd067c37ffa7429aed538f08b362b9a2a4aa3e8d0401b329315fd48be3127df50aa9c9abac980169519fa0fcb8503ba5aab972f8d0e46fe5c8ddcc0978998e58f0e4a49d4f483777ef3868363a"
);
pub const OUTPUT_LE_G1_MUL_RANDOM: &[u8] = &hex!(
"e38bd45f3129b301048d3eaaa4a2b962b3088f53ed9a42a7ff377c06cde347a6377e729e5bd075eada27f703ff4865163a366838ef7737484f9da4e4f0588e997809ccddc8e56fe4d0f872b9aaa53b50b8fca09f51690198acabc9a90af57d12"
);
// Test Case: G1_MUL_SCALAR_ZERO
pub const INPUT_BE_G1_MUL_SCALAR_ZERO: &[u8] = &hex!(
"1412e9c96ece3820082c8c7925c49d38b486a421b48293071aefb7a3db558fc5f7f375fcc9ab9c5ad2072b5c5982a5e005651836bd16494c9188633b33ff7c2b3d08791e765afe0c7e5c984e2ce77e38dc23367502afbe698abcca24ab0ce7e10000000000000000000000000000000000000000000000000000000000000000"
);
pub const INPUT_LE_G1_MUL_SCALAR_ZERO: &[u8] = &hex!(
"e0a582595c2b07d25a9cabc9fc75f3f7c58f55dba3b7ef1a079382b421a486b4389dc425798c2c082038ce6ec9e91214e1e70cab24cabc8a69beaf02753623dc387ee72c4e985c7e0cfe5a761e79083d2b7cff333b6388914c4916bd361865050000000000000000000000000000000000000000000000000000000000000000"
);
pub const OUTPUT_BE_G1_MUL_SCALAR_ZERO: &[u8] = &hex!(
"400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
pub const OUTPUT_LE_G1_MUL_SCALAR_ZERO: &[u8] = &hex!(
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
// Test Case: G1_MUL_SCALAR_ONE
pub const INPUT_BE_G1_MUL_SCALAR_ONE: &[u8] = &hex!(
"1412e9c96ece3820082c8c7925c49d38b486a421b48293071aefb7a3db558fc5f7f375fcc9ab9c5ad2072b5c5982a5e005651836bd16494c9188633b33ff7c2b3d08791e765afe0c7e5c984e2ce77e38dc23367502afbe698abcca24ab0ce7e10000000000000000000000000000000000000000000000000000000000000001"
);
pub const INPUT_LE_G1_MUL_SCALAR_ONE: &[u8] = &hex!(
"e0a582595c2b07d25a9cabc9fc75f3f7c58f55dba3b7ef1a079382b421a486b4389dc425798c2c082038ce6ec9e91214e1e70cab24cabc8a69beaf02753623dc387ee72c4e985c7e0cfe5a761e79083d2b7cff333b6388914c4916bd361865050100000000000000000000000000000000000000000000000000000000000000"
);
pub const OUTPUT_BE_G1_MUL_SCALAR_ONE: &[u8] = &hex!(
"1412e9c96ece3820082c8c7925c49d38b486a421b48293071aefb7a3db558fc5f7f375fcc9ab9c5ad2072b5c5982a5e005651836bd16494c9188633b33ff7c2b3d08791e765afe0c7e5c984e2ce77e38dc23367502afbe698abcca24ab0ce7e1"
);
pub const OUTPUT_LE_G1_MUL_SCALAR_ONE: &[u8] = &hex!(
"e0a582595c2b07d25a9cabc9fc75f3f7c58f55dba3b7ef1a079382b421a486b4389dc425798c2c082038ce6ec9e91214e1e70cab24cabc8a69beaf02753623dc387ee72c4e985c7e0cfe5a761e79083d2b7cff333b6388914c4916bd36186505"
);
// Test Case: G1_MUL_SCALAR_MINUS_ONE
pub const INPUT_BE_G1_MUL_SCALAR_MINUS_ONE: &[u8] = &hex!(
"1412e9c96ece3820082c8c7925c49d38b486a421b48293071aefb7a3db558fc5f7f375fcc9ab9c5ad2072b5c5982a5e005651836bd16494c9188633b33ff7c2b3d08791e765afe0c7e5c984e2ce77e38dc23367502afbe698abcca24ab0ce7e173eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000"
);
pub const INPUT_LE_G1_MUL_SCALAR_MINUS_ONE: &[u8] = &hex!(
"e0a582595c2b07d25a9cabc9fc75f3f7c58f55dba3b7ef1a079382b421a486b4389dc425798c2c082038ce6ec9e91214e1e70cab24cabc8a69beaf02753623dc387ee72c4e985c7e0cfe5a761e79083d2b7cff333b6388914c4916bd3618650500000000fffffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73"
);
pub const OUTPUT_BE_G1_MUL_SCALAR_MINUS_ONE: &[u8] = &hex!(
"1412e9c96ece3820082c8c7925c49d38b486a421b48293071aefb7a3db558fc5f7f375fcc9ab9c5ad2072b5c5982a5e0149bf9b37c699d4db993447b0f4c30ac276ed2667d2a14b2e8d43a52c9c977eb4288c989aea441962f4235db54f2c2ca"
);
pub const OUTPUT_LE_G1_MUL_SCALAR_MINUS_ONE: &[u8] = &hex!(
"e0a582595c2b07d25a9cabc9fc75f3f7c58f55dba3b7ef1a079382b421a486b4389dc425798c2c082038ce6ec9e91214cac2f254db35422f9641a4ae89c98842eb77c9c9523ad4e8b2142a7d66d26e27ac304c0f7b4493b94d9d697cb3f99b14"
);
// Test Case: G1_MUL_POINT_INFINITY
pub const INPUT_BE_G1_MUL_POINT_INFINITY: &[u8] = &hex!(
"4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001dc06f97bb256d5b81dfbce1750378a26b429fff3d802920f25fe8ca6abc9a93"
);
pub const INPUT_LE_G1_MUL_POINT_INFINITY: &[u8] = &hex!(
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000939abc6acae85ff22029803dff9f426ba2780375e1bcdf815b6d25bb976fc01d"
);
pub const OUTPUT_BE_G1_MUL_POINT_INFINITY: &[u8] = &hex!(
"400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
pub const OUTPUT_LE_G1_MUL_POINT_INFINITY: &[u8] = &hex!(
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
// Test Case: G2_MUL_RANDOM
pub const INPUT_BE_G2_MUL_RANDOM: &[u8] = &hex!(
"015f105a75b9fd4c1944366f9aa17dcb79049a43cd9d4c0980e02551d6e2473be0bb9899c73e3a4a89f52e659b11d440058600b91384cd654dcc763f47acd01dd23d3304bebfd3af69f5cc393854d2b8eba9e7a18053fceae3ffa6dbc9b0a91014dacb26b562d559987be6c9045f2a561d8943e9e6a1cee7c9b04f0cc538d424ebd8a01bdd637cdc854c7bd1c84e7a2410ab12f76f6f8426f0b71b4c87d388ca375df6ebbf92b7a16e81043aee3b4df23858609692f789e68923096c5f7f4b4e1dc06f97bb256d5b81dfbce1750378a26b429fff3d802920f25fe8ca6abc9a93"
);
pub const INPUT_LE_G2_MUL_RANDOM: &[u8] = &hex!(
"10a9b0c9dba6ffe3eafc5380a1e7a9ebb8d2543839ccf569afd3bfbe04333dd21dd0ac473f76cc4d65cd8413b900860540d4119b652ef5894a3a3ec79998bbe03b47e2d65125e080094c9dcd439a0479cb7da19a6f3644194cfdb9755a105f014e4b7f5f6c092389e689f79296605838f24d3bee3a04816ea1b792bfebf65d37ca88d3874c1bb7f026846f6ff712ab10247a4ec8d17b4c85dc7c63dd1ba0d8eb24d438c50c4fb0c9e7cea1e6e943891d562a5f04c9e67b9859d562b526cbda14939abc6acae85ff22029803dff9f426ba2780375e1bcdf815b6d25bb976fc01d"
);
pub const OUTPUT_BE_G2_MUL_RANDOM: &[u8] = &hex!(
"0a5c58c01ac82680bc94fe10ca27aefc216f2979d309d18a2b687ad604fb2251245c8f1397d56ff0640f214a7b8fb599066b52608d933fc80d1f4205b8871852bdf03afa303d840d17f01feefc21bff1265addc9a489625c94f6e116ef6361b314fb27720e9ca5b63ae96429223b776728ce32afdf7e9211a10e542b953ad4c5fa0fd07a210457db52c90c0b2c4c3bb6124c26b8af0bd30440852968b9993ff627912671a2b74d023386f3c44a6fb7a9dee4bf358135ba5e61901f75dacfd6bd"
);
pub const OUTPUT_LE_G2_MUL_RANDOM: &[u8] = &hex!(
"b36163ef16e1f6945c6289a4c9dd5a26f1bf21fcee1ff0170d843d30fa3af0bd521887b805421f0dc83f938d60526b0699b58f7b4a210f64f06fd597138f5c245122fb04d67a682b8ad109d379296f21fcae27ca10fe94bc8026c81ac0585c0abdd6cfda751f90615eba358135bfe4dea9b76f4ac4f38633024db7a271269127f63f99b96829854004d30bafb8264c12b63b4c2c0b0cc952db5704217ad00ffac5d43a952b540ea111927edfaf32ce2867773b222964e93ab6a59c0e7227fb14"
);
// Test Case: G2_MUL_SCALAR_ZERO
pub const INPUT_BE_G2_MUL_SCALAR_ZERO: &[u8] = &hex!(
"015f105a75b9fd4c1944366f9aa17dcb79049a43cd9d4c0980e02551d6e2473be0bb9899c73e3a4a89f52e659b11d440058600b91384cd654dcc763f47acd01dd23d3304bebfd3af69f5cc393854d2b8eba9e7a18053fceae3ffa6dbc9b0a91014dacb26b562d559987be6c9045f2a561d8943e9e6a1cee7c9b04f0cc538d424ebd8a01bdd637cdc854c7bd1c84e7a2410ab12f76f6f8426f0b71b4c87d388ca375df6ebbf92b7a16e81043aee3b4df23858609692f789e68923096c5f7f4b4e0000000000000000000000000000000000000000000000000000000000000000"
);
pub const INPUT_LE_G2_MUL_SCALAR_ZERO: &[u8] = &hex!(
"10a9b0c9dba6ffe3eafc5380a1e7a9ebb8d2543839ccf569afd3bfbe04333dd21dd0ac473f76cc4d65cd8413b900860540d4119b652ef5894a3a3ec79998bbe03b47e2d65125e080094c9dcd439a0479cb7da19a6f3644194cfdb9755a105f014e4b7f5f6c092389e689f79296605838f24d3bee3a04816ea1b792bfebf65d37ca88d3874c1bb7f026846f6ff712ab10247a4ec8d17b4c85dc7c63dd1ba0d8eb24d438c50c4fb0c9e7cea1e6e943891d562a5f04c9e67b9859d562b526cbda140000000000000000000000000000000000000000000000000000000000000000"
);
pub const OUTPUT_BE_G2_MUL_SCALAR_ZERO: &[u8] = &hex!(
"400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
pub const OUTPUT_LE_G2_MUL_SCALAR_ZERO: &[u8] = &hex!(
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
// Test Case: G2_MUL_SCALAR_ONE
pub const INPUT_BE_G2_MUL_SCALAR_ONE: &[u8] = &hex!(
"015f105a75b9fd4c1944366f9aa17dcb79049a43cd9d4c0980e02551d6e2473be0bb9899c73e3a4a89f52e659b11d440058600b91384cd654dcc763f47acd01dd23d3304bebfd3af69f5cc393854d2b8eba9e7a18053fceae3ffa6dbc9b0a91014dacb26b562d559987be6c9045f2a561d8943e9e6a1cee7c9b04f0cc538d424ebd8a01bdd637cdc854c7bd1c84e7a2410ab12f76f6f8426f0b71b4c87d388ca375df6ebbf92b7a16e81043aee3b4df23858609692f789e68923096c5f7f4b4e0000000000000000000000000000000000000000000000000000000000000001"
);
pub const INPUT_LE_G2_MUL_SCALAR_ONE: &[u8] = &hex!(
"10a9b0c9dba6ffe3eafc5380a1e7a9ebb8d2543839ccf569afd3bfbe04333dd21dd0ac473f76cc4d65cd8413b900860540d4119b652ef5894a3a3ec79998bbe03b47e2d65125e080094c9dcd439a0479cb7da19a6f3644194cfdb9755a105f014e4b7f5f6c092389e689f79296605838f24d3bee3a04816ea1b792bfebf65d37ca88d3874c1bb7f026846f6ff712ab10247a4ec8d17b4c85dc7c63dd1ba0d8eb24d438c50c4fb0c9e7cea1e6e943891d562a5f04c9e67b9859d562b526cbda140100000000000000000000000000000000000000000000000000000000000000"
);
pub const OUTPUT_BE_G2_MUL_SCALAR_ONE: &[u8] = &hex!(
"015f105a75b9fd4c1944366f9aa17dcb79049a43cd9d4c0980e02551d6e2473be0bb9899c73e3a4a89f52e659b11d440058600b91384cd654dcc763f47acd01dd23d3304bebfd3af69f5cc393854d2b8eba9e7a18053fceae3ffa6dbc9b0a91014dacb26b562d559987be6c9045f2a561d8943e9e6a1cee7c9b04f0cc538d424ebd8a01bdd637cdc854c7bd1c84e7a2410ab12f76f6f8426f0b71b4c87d388ca375df6ebbf92b7a16e81043aee3b4df23858609692f789e68923096c5f7f4b4e"
);
pub const OUTPUT_LE_G2_MUL_SCALAR_ONE: &[u8] = &hex!(
"10a9b0c9dba6ffe3eafc5380a1e7a9ebb8d2543839ccf569afd3bfbe04333dd21dd0ac473f76cc4d65cd8413b900860540d4119b652ef5894a3a3ec79998bbe03b47e2d65125e080094c9dcd439a0479cb7da19a6f3644194cfdb9755a105f014e4b7f5f6c092389e689f79296605838f24d3bee3a04816ea1b792bfebf65d37ca88d3874c1bb7f026846f6ff712ab10247a4ec8d17b4c85dc7c63dd1ba0d8eb24d438c50c4fb0c9e7cea1e6e943891d562a5f04c9e67b9859d562b526cbda14"
);
// Test Case: G2_MUL_SCALAR_MINUS_ONE
pub const INPUT_BE_G2_MUL_SCALAR_MINUS_ONE: &[u8] = &hex!(
"015f105a75b9fd4c1944366f9aa17dcb79049a43cd9d4c0980e02551d6e2473be0bb9899c73e3a4a89f52e659b11d440058600b91384cd654dcc763f47acd01dd23d3304bebfd3af69f5cc393854d2b8eba9e7a18053fceae3ffa6dbc9b0a91014dacb26b562d559987be6c9045f2a561d8943e9e6a1cee7c9b04f0cc538d424ebd8a01bdd637cdc854c7bd1c84e7a2410ab12f76f6f8426f0b71b4c87d388ca375df6ebbf92b7a16e81043aee3b4df23858609692f789e68923096c5f7f4b4e73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000"
);
pub const INPUT_LE_G2_MUL_SCALAR_MINUS_ONE: &[u8] = &hex!(
"10a9b0c9dba6ffe3eafc5380a1e7a9ebb8d2543839ccf569afd3bfbe04333dd21dd0ac473f76cc4d65cd8413b900860540d4119b652ef5894a3a3ec79998bbe03b47e2d65125e080094c9dcd439a0479cb7da19a6f3644194cfdb9755a105f014e4b7f5f6c092389e689f79296605838f24d3bee3a04816ea1b792bfebf65d37ca88d3874c1bb7f026846f6ff712ab10247a4ec8d17b4c85dc7c63dd1ba0d8eb24d438c50c4fb0c9e7cea1e6e943891d562a5f04c9e67b9859d562b526cbda1400000000fffffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73"
);
pub const OUTPUT_BE_G2_MUL_SCALAR_MINUS_ONE: &[u8] = &hex!(
"015f105a75b9fd4c1944366f9aa17dcb79049a43cd9d4c0980e02551d6e2473be0bb9899c73e3a4a89f52e659b11d440058600b91384cd654dcc763f47acd01dd23d3304bebfd3af69f5cc393854d2b8eba9e7a18053fceae3ffa6dbc9b0a910052646c3841d1140b29fc0ed3eec828146ee079b0ce343d79d808394317821ff32d35fe2d3f0832334b2842e37b130870955fef2ca1062735a648c69bb78240d2d19549933f25b1df8afce660875a831e6539f681e5c761930dbf693a0805f5d"
);
pub const OUTPUT_LE_G2_MUL_SCALAR_MINUS_ONE: &[u8] = &hex!(
"10a9b0c9dba6ffe3eafc5380a1e7a9ebb8d2543839ccf569afd3bfbe04333dd21dd0ac473f76cc4d65cd8413b900860540d4119b652ef5894a3a3ec79998bbe03b47e2d65125e080094c9dcd439a0479cb7da19a6f3644194cfdb9755a105f015d5f80a093f6db3019765c1e689f53e631a8750866ceaff81d5bf2339954192d0d2478bb698c645a736210caf2fe55098730b1372e84b2342383f0d3e25fd332ff2178319483809dd743e30c9b07ee468182ec3eedc09fb240111d84c3462605"
);
// Test Case: G2_MUL_POINT_INFINITY
pub const INPUT_BE_G2_MUL_POINT_INFINITY: &[u8] = &hex!(
"4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001dc06f97bb256d5b81dfbce1750378a26b429fff3d802920f25fe8ca6abc9a93"
);
pub const INPUT_LE_G2_MUL_POINT_INFINITY: &[u8] = &hex!(
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000939abc6acae85ff22029803dff9f426ba2780375e1bcdf815b6d25bb976fc01d"
);
pub const OUTPUT_BE_G2_MUL_POINT_INFINITY: &[u8] = &hex!(
"400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
pub const OUTPUT_LE_G2_MUL_POINT_INFINITY: &[u8] = &hex!(
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);

View file

@ -0,0 +1,67 @@
use hex_literal::hex;
// Test Case: PAIRING_IDENTITY
pub const INPUT_BE_PAIRING_IDENTITY: &[u8] = &hex!("");
pub const INPUT_LE_PAIRING_IDENTITY: &[u8] = &hex!("");
pub const OUTPUT_BE_PAIRING_IDENTITY: &[u8] = &hex!(
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"
);
pub const OUTPUT_LE_PAIRING_IDENTITY: &[u8] = &hex!(
"010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
// Test Case: PAIRING_ONE_PAIR
pub const INPUT_BE_PAIRING_ONE_PAIR: &[u8] = &hex!(
"03a16836f27410320f712a266c0b7f402bf93285690885ee2206bd7799244b4157f95a6d85c8cb197f44fbf30ed2cc23127c950544b239e6fd9ac0a3059290640766094c43fb932d1b6fccd5db8d3a0beb6406dc4de6e8c8d2c803b80a5017a408f9da9ae87dfab9993c849bbc7732cd204cb8b5a49e400cb3b5965fe209af33a9b922b2f9a11ba4d26babcbf60b9e560e87c5e1072c5ef3d8c864c7760e6ab558cacf9ce3657eec2ebdee49dc769749fff96767ffb95b52d4946e13d46fc7c504901991c48ecdfc555530f3d13e39d42c955171ab3cc149280b2478133e021916e8e332234baccd02251b41b6064a2b01ef6981b862d7510f13ab27fc39b0abb5477cfb35cad5213aaf342959e6d9b1201852a6f0e8df188d46791933ad1e06"
);
pub const INPUT_LE_PAIRING_ONE_PAIR: &[u8] = &hex!(
"23ccd20ef3fb447f19cbc8856d5af957414b249977bd0622ee8508698532f92b407f0b6c262a710f321074f23668a103a417500ab803c8d2c8e8e64ddc0664eb0b3a8ddbd5cc6f1b2d93fb434c09660764909205a3c09afde639b24405957c12c5c76fd4136e94d4525bb9ff6767f9ff499776dc49eebd2eec7e65e39ccfca58b56a0e76c764c8d8f35e2c07e1c5870e569e0bf6cbab6bd2a41ba1f9b222b9a933af09e25f96b5b30c409ea4b5b84c20cd3277bc9b843c99b9fa7de89adaf908061ead331979468d18dfe8f0a6521820b1d9e6592934af3a21d5ca35fb7c47b5abb039fc27ab130f51d762b88169ef012b4a06b6411b2502cdac4b2332e3e81619023e1378240b2849c13cab7151952cd4393ed1f3305555fccd8ec491199004"
);
pub const OUTPUT_BE_PAIRING_ONE_PAIR: &[u8] = &hex!(
"0e39a48076e53ac2a3b3079b131bc3b8f7f6534c3f4778488f8202c023fb24e8e57a447e36e4c5f970ea5d8285f64b290d1fe8e169dbb469e1b82b39b80ae493f5e32844d7d90fa40ee777867821d234402f272aabdde13af9f7cca11410670100a86d9ddf3c930b4c025f56ae04647d7ce21f9fc7a031624c7cdd6506d56f2c18ac4e2ad8895b44d328d2acf21d73dc0b9cf975760c3b3b5789d9be903ef967f4f79870ee1f7a88270931d716b4a478a6733e8204d8399b08d67409dea822f2132fb77cc4de3a874b61f2e7beeea2327ce6e5ac9c8cc4a3d5319990a7767aa746cb9178ed2e878200cc8b3d160af3e80f26a1926a8a56c608a7e57d5f1c783317a1fa697db1a9a8610500e78f8d165c8f945f42979a37a9005b6b053bfc088c00c34087c5e2ebaa7fb0d907b4ebde3ac3ddc082568f00c7e13539b5979851b7fcfb057c3da485a90e14ce243801c5d6170a20df8057a6213d1dbe5a9652796dffd34f2e3930d57d085d0a97a2898581ed654d27555eea2b5565f0e95d39ab0d12261f1d29a9c1316c77e782612d23fc957d7440a346288fa00e0f5ba8cf4d284ad072324077d8b660da00b94569c267138121ccfaedbf8f7a38ea3e08e001f26e0ac2b2c6dc97a7eaebcf945df9dd990f56594c311d124a00f62a8f593c306017add1d59c509a9fa10cb2e1e24d63f99af66e60b04f5a02be3fbd7baace778e8a0f5dbfe6649f8e3277cc9dc9e65d39037d60c3f7c34c18b06358ce563fcc25adb67433f00f9bc7c7c6b72cf1fbec23b224086b5299901c1de5969d25d86074"
);
pub const OUTPUT_LE_PAIRING_ONE_PAIR: &[u8] = &hex!(
"7460d8259d96e51d1c9099526b0824b223ecfbf12cb7c6c7c79b0ff03374b6ad25cc3f56ce5863b0184cc3f7c3607d03395de6c99dcc77328e9f64e6bf5d0f8a8e77ceaa7bbd3fbe025a4fb0606ef69af9634de2e1b20ca19f9a509cd5d1ad1760303c598f2af6004a121d314c59560f99ddf95d94cfebeaa797dcc6b2c20a6ef201e0083eea387a8fbfedfacc21811367c26945b900da60b6d877403272d04a284dcfa85b0f0ea08f2846a340747d95fc232d6182e7776c31c1a9291d1f26120dab395de9f065552bea5e55274d65ed818589a2970a5d087dd530392e4fd3ff6d7952965abe1d3d21a65780df200a17d6c5013824ce140ea985a43d7c05fbfcb7519897b53935e1c7008f5682c0ddc33adeebb407d9b07faaebe2c58740c3008c08fc3b056b5b00a9379a97425f948f5c168d8fe7000561a8a9b17d69faa11733781c5f7de5a708c6568a6a92a1260fe8f30a163d8bcc0082872eed7891cb46a77a76a7909931d5a3c48c9cace5e67c32a2eebee7f2614b873adec47cb72f13f222a8de0974d6089b39d804823e73a678a4b416d7310927887a1fee7098f7f467f93e90bed989573b3b0c7675f99c0bdc731df2acd228d3445b89d82a4eac182c6fd50665dd7c4c6231a0c79f1fe27c7d6404ae565f024c0b933cdf9d6da80001671014a1ccf7f93ae1ddab2a272f4034d221788677e70ea40fd9d74428e3f593e40ab8392bb8e169b4db69e1e81f0d294bf685825dea70f9c5e4367e447ae5e824fb23c002828f4878473f4c53f6f7b8c31b139b07b3a3c23ae57680a4390e"
);
// Test Case: PAIRING_TWO_PAIRS
pub const INPUT_BE_PAIRING_TWO_PAIRS: &[u8] = &hex!(
"175a43b5fe41d4c82fda24056e7a619b70d696a20f79bc741c75d061e1b08ac0f403697e210b010439db8355d0d80d7d089a02374427c924b351810e28b5e28ee154f5aac6db4946b7a028f2f8061edc9b95e08cdea0d6467866025687a64f0a15a846c4c74f9865abed2351cc5115f057f4e2e49953107c8bd47cfff311b4c39f13713d982ef2e901ccf29a80f816a20b5c9c986f714412c0ac5a2d57cd3603bd610b0a059091a3c440fd0846d0fa40aeccc507f17b26f84e081621996d9da310372e978ef56f3b48ba20d9fea571435900e6a8d6efdbb593f863f03d47aeb63859da16c3777148735992ba08e687c211c28ef231375b6b4d15fe8732e18c20d87ce93adb11f7cd6e18150ac2fa49fed1e955ab77bbb0ba91800cc2cc063044163cab96ec515f603aa1362d0742bb67091159b4ab56f31e2642e2004cffdadd5327b0d272bf12f0ac21dacc6932afd217a9953cd7717ba6a3f415025ccefaa99eaa5d5233713a5354bd5e775de6c340da25e2a91c9ca2e934a9f53f96569522171d23a93e201136ad66ea9ba535ea9a0d995fe2f669d04a90ca9fd463887478d65045aab23c76c85926ff3d9d53ac48138beb244bca9d19ae2b397e13e19bcbc846c074b214906d29a2f97950b02676c9dfecf6fa089373c7de72c1f4ccb6300fd8abfa0df3fcbb73ff032db194fac69a1bed6ead04156179b28f243556a83128e030b1222704cf3a03197321d326450a37c6e88b795a51691517481b268b8c8fd004d42cc40cb150435a4b8d78e35b089ea2f2b9c86b5ff749a63619ba3ddc"
);
pub const INPUT_LE_PAIRING_TWO_PAIRS: &[u8] = &hex!(
"7d0dd8d05583db3904010b217e6903f4c08ab0e161d0751c74bc790fa296d6709b617a6e0524da2fc8d441feb5435a170a4fa6875602667846d6a0de8ce0959bdc1e06f8f228a0b74649dbc6aaf554e18ee2b5280e8151b324c9274437029a08a216f8809af2cc01e9f22e983d71139fc3b411f3ff7cd48b7c105399e4e2f457f01551cc5123edab65984fc7c446a815a39d6d992116084ef8267bf107c5ccae40fad04608fd40c4a39190050a0b61bd0336cd572d5aacc01244716f989c5c0b443006ccc20c8091bab0bb77ab55e9d1fe49fac20a15186ecdf711db3ae97cd8208ce13287fe154d6b5b3731f28ec211c287e608ba925973487177c316da5938b6ae473df063f893b5dbefd6a8e600594371a5fed920ba483b6ff58e972e3710229556963ff5a934e9a29c1ca9e225da40c3e65d775ebd54533a7133525daa9ea9face5c0215f4a3a67b71d73c95a917d2af3269ccda21acf012bf72d2b02753dddaff4c00e242261ef356abb459110967bb42072d36a13a605f51ec96ab3c1630b6ccf4c172dec7739308faf6ecdfc97626b05079f9a2296d9014b274c046c8cb9be1137e392bae199dca4b24eb8b1348ac539d3dff2659c8763cb2aa4550d678748863d49fca904ad069f6e25f990d9aea35a59bea66ad3611203ea9231d17dc3dba1936a649f75f6bc8b9f2a29e085be3788d4b5a4350b10cc42cd404d08f8c8b261b48171569515a798be8c6370a4526d3217319033acf042722b130e02831a85635248fb279611504ad6eed1b9ac6fa94b12d03ff73bbfcf30dfaabd80f"
);
pub const OUTPUT_BE_PAIRING_TWO_PAIRS: &[u8] = &hex!(
"12b900a55ac5e082ab9c7b6e9a4181d0add318c12dfc90ca33072ecbf30086b5e9193cb3d6b86df9c3c027388f937db50e70258382006a389e1bb045df24b43b87481961f39debd37c724926845d3800589d179b0f08da2eb4db527c7d6923fa06c8ec4eb5718b82cf955c37722e2bcdd78ddc5a5f2be4287c327f9bad389e3e99f0a8dae6ca9dbe0d1ff6098d786e6013455dcf38a6ed344ee1a857c939a7afcd3c982707a9c36efcaba340b4b510c29882baff5ca7792a7d1c5fe0942401b200aaf05bb3ee4f27bde60bda9e23a0253460c2443abd60a7c7d09e742730e304c36527c7faeea54a793544a5587f261001b8c08b9a4390daa9a8c764a9d0895e34d01e4dc79c0688412f97b121a0300d285fe957496ae3bd9aa9bf14fa766ce8144f9fc4c3fb2c3e82c1ecb9098cef4516ae4cd0896b8572129e8346e96569441ff870e4aed21ad42ce9cede16a3b86609cc8cfe35e36c7f5553cc85ac26efe52420845cf352cb67a56c55d74b77ad904bb850a1b5b0bf236c37f8ac6061a8b40b4e2949507a1f2b5b1f71df93e619631b977c7f36087367c452cf0ecf081c5511ac1336b1999dd9c458c7ee9c4596e900258cd9824ce5c13be86938dc16716c37666e61598f215147f1559a4a3518f64e451685949742bc2afa786e1277577e07dda5ade21d49a256ae3511b3348a9e107b9db6690f6630a7b9954157c84775ea3518332b8306dd36b7ac9f918f755809abbc2d199aeb7a78c49643fa60f27d8156d9c67efba69556c22942724d67b34be49cbf497783e83e73adff41ea7774"
);
pub const OUTPUT_LE_PAIRING_TWO_PAIRS: &[u8] = &hex!(
"7477ea41ffad733ee8837749bf9ce44bb3674d724229c25695a6fb7ec6d956817df260fa4396c4787aeb9a192dbcab0958758f919facb736dd06832b331835ea7547c8574195b9a730660f69b69d7b109e8a34b31135ae56a2491de2ada5dd077e5777126e78fa2abc4297948516454ef618354a9a55f14751218f59616e66376c7116dc3869e83bc1e54c82d98c2500e996459ceec758c4d99d99b13613ac11551c08cf0ecf52c4677308367f7c971b6319e693df711f5b2b1f7a5049294e0bb4a86160acf8376c23bfb0b5a150b84b90ad774bd7556ca567cb52f35c842024e5ef26ac85cc53557f6ce335fe8ccc0966b8a316decee92cd41ad2aee470f81f446965e946839e1272856b89d04cae1645ef8c09b9ecc1823e2cfbc3c49f4f14e86c76fa14bfa99abde36a4957e95f280d30a021b1972f4188069cc74d1ed0345e89d0a964c7a8a9da90439a8bc0b80110267f58a54435794aa5eefac72765c304e33027749ed0c7a760bd3a44c2603425a0239eda0be6bd274feeb35bf0aa00b2012494e05f1c7d2a79a75cffba8298c210b5b440a3abfc6ec3a90727983ccdafa739c957a8e14e34eda638cf5d4513606e788d09f61f0dbe9dcae6daa8f0993e9e38ad9b7f327c28e42b5f5adc8dd7cd2b2e72375c95cf828b71b54eecc806fa23697d7c52dbb42eda080f9b179d5800385d842649727cd3eb9df3611948873bb424df45b01b9e386a00828325700eb57d938f3827c0c3f96db8d6b33c19e9b58600f3cb2e0733ca90fc2dc118d3add081419a6e7b9cab82e0c55aa500b912"
);
// Test Case: PAIRING_THREE_PAIRS
pub const INPUT_BE_PAIRING_THREE_PAIRS: &[u8] = &hex!(
"035205fc0226821e7af21ef2760c2f3f9538b9612200c5e502e10cff141938f8cf72d99f1aa4f770ea0bca10c57ae692177049bd989d92a7681e40b7be1505318be023e7b877b1a40ae9c3738058d99c69156f6a075d30ee7803226638b722fd052244350368122b5ae34e1efde626ee9e162ece751d668031c51314caab2c4eb01e58c3bec9b7abffaae5731247710103a41cf2c11bdb262b41505f3bcc78f5a8d1afb2c9ca5391a1b9895a947cd01f3f3b5c214fdc4fd978cf188d8919215a03abf112c9bd7a812d546f48d0cbeed2b6b446f360a2de1642e9892a8c35f8547de30d19036785fbd2a425bdc35d9788187182e38c97334b6416dacd3fc9110e8f59c3d14aad8bdb2fc6133a7a7c0ea0d107e254e1d1cd9e5b73dd9535ecc185139c94c3e88cbe70a9c6a711718638530a0c3a14bad3bdf2f45f6c960b57a6543fd2560d81ab2727a8715e85eb89cc8c036de17081b505a8af4bcd656868844c72bc49a956740fc60d405817579a3ce330551a86324abb61b0ef123d58f6568e0f8939d7682eb54aa24c382b9a3cf1c8cd10bb0763f386cca6e94f8aac8559eb5b34c9ba0d0287bc6ba8414d359af6aa06dde73759f2491eee944c090ec86d3c986c277e5e99f578efbfc87a10c20e7b7e8872686b13d3a5fca47e5c592fa8cf1580ada0cb4fa0e128ba53dc9b8c85b84abab9d3c3d5574830de38519af09e720f01a1ccb5830031815afb2082ac9b85065ceba1a4160b29a5f062f573219cd1755f7581f94d3137e3c755d4b9573598dda0cc1eb0f54ababa2907b7854cbaa214ea9e99d2caaf2c67a7b07d0c79bf17027b0e12b74b7d24358b010e6973402341a94616c566e428324f2141594263f7105d8b606b0863d2f8d3adad634d36f941d9cf66392f8fdadfad338bf296cb1a84ded68d28e108e98c124f127c43f1ef006c9342a18aff9b069144699209421d28432586b3ec48d8d244dad7d1496c1b38e4ffbb2a0168c8ba8c078d310f5d3903150b7c9d055ac91fb1f9708fbfbb97773d37e0fef87d00f4ed5e9a043e56b445a74d0f240bbfd096d4370d8d399603013048fb8d578df3996f0d36b6d0a2224c51ad6592b96b8f33a0689a823f306af244c474b2c157b230fdd20a22abf60f0704c6b79716d44865d0433dd92cb023115deea9d5c9e2881a6c3f3bb3dca960dd9346b5f5facfa191c652b23c60d511"
);
pub const INPUT_LE_PAIRING_THREE_PAIRS: &[u8] = &hex!(
"92e67ac510ca0bea70f7a41a9fd972cff8381914ff0ce102e5c5002261b938953f2f0c76f21ef27a1e822602fc055203fd22b73866220378ee305d076a6f15699cd9588073c3e90aa4b177b8e723e08b310515beb7401e68a7929d98bd4970170171471273e5aaffabb7c9bec3581eb04e2cabca1413c53180661d75ce2e169eee26e6fd1e4ee35a2b126803354422055a2119898d18cf78d94fdc4f215c3b3f1fd07c945a89b9a19153cac9b2afd1a8f578cc3b5f50412b26db1bc1f21ca40388975dc3bd25a4d2fb856703190de37d54f8358c2a89e94216dea260f346b4b6d2eecbd0486f542d817abdc912f1ab0385c1ec3595dd735b9ecdd1e154e207d1a00e7c7a3a13c62fdb8bad4ad1c3598f0e11c93fcdda16644b33978ce38271188e56f6583d12efb061bb4a32861a5530e33c9a571758400dc60f7456a949bc724c84686865cd4bafa805b58170e16d038ccc89eb855e71a82727ab810d56d23f54a6570b966c5ff4f2bdd3ba143a0c0a5338867111a7c6a970be8ce8c3949c13cfa82f595c7ea4fca5d3136b6872887e7b0ec2107ac8bfef78f5995e7e276c983c6dc80e094c94ee1e49f25937e7dd06aaf69a354d41a86bbc87020dbac9345beb5985ac8a4fe9a6cc86f36307bb10cdc8f13c9a2b384ca24ab52e68d739890fa2ba4c85b70729baba4af5b01ecca0dd983557b9d455c7e337314df981755f75d19c2173f562f0a5290b16a4a1eb5c06859bac8220fb5a81310083b5cca1010f729ef09a5138de304857d5c3d3b9ba4ab8858c9bdc53ba28e1a04fcba0ad8015eff1437c124f128ce908e1288dd6de841acb96f28b33addfda8f2f3966cfd941f9364d63adadd3f8d263086b608b5d10f763425941214f3228e466c51646a941234073690e018b35247d4bb7120e7b0217bf790c7db0a7672cafcad2999eea140396398d0d37d496d0bf0b240f4da745b4563e049a5eedf4007df8fee0373d7797bbbf8f70f9b11fc95a059d7c0b1503395d0f318d078cbac868012abbffe4381b6c49d1d7da44d2d848ecb3862543281d420992694491069bff8aa142936c0011d5603cb252c691a1cffaf5b54693dd60a9dcb33b3f6c1a88e2c9d5a9ee5d1123b02cd93d43d06548d41697b7c604070ff6ab220ad2fd30b257c1b274c444f26a303f829a68a0338f6bb99265ad514c22a2d0b6360d6f99f38d578dfb483001"
);
pub const OUTPUT_BE_PAIRING_THREE_PAIRS: &[u8] = &hex!(
"0e3b7891cce242f16fcf2e78d791f59207737e819746aca96a2371cffa7e4a73a7d23e72deca87ffbc0e1016d3006ef3158a4930b3d9da7421b1bb4c41e1fa6d0e95a2c83f033252e277fcc8d67fb88f0bfdcc202decd2d865f85a33207cc53215dfec6a9043eb3c25a6c148c0208d898d8c357883f8ed66a0cb70115d8142f7464bfadde1e7d6cb8bbfc416d7895cff0c998d077822fd9dce6edae91b84cc5dd7ec8accc1ed262d356f803a2fbbb2bfefd283de4b450ea61c08a867776ec54808a5ea36bc38d039d9bac15207dcd817eaa06e054a5b2ba1ec45e8ff8d320eb8c7aa0dba07854c90a5618d08af32717a02803f583c027353813f31fc27d53472c8be0044b80af0510dfdba8647cfaa1f0e0913a870ef79f02762e0f0401e31b113aa3947932f24bdd50b5909c425edda718be31158693d78fcd41e0d548bf379aa5f48c24542ed3de38dc248e30a919709d97b7d46624318005f4beeebe09cd7bc85d4d50ddb0377b2ea79d11d6ff8aa2d283d7f7cd8b93d1b15fefe5c689fb911c262e76d7641c2941b93a921ff0bde9d20093184491f01fa2683098b97a4255d0684eb5d3a673b9b2ae84984e1d0ac10526c144bfb88850392593ebabd5efe82ba62620366144e6bd9dbaddaaebd1ede0e640d1ee414b4a3fd0b1f7b9f68e400b88cde2734b2c4eb3a25ce87bcdd7af1cc8ea9a5812b7993c4cdc152cf2f7847e32671a543bd58955fb54b7edf220e168962731fd01590691fa946d2f2e820bfee8171828fc23b61c42405cf03b95fe522e66974f64566df2e7c2a259bba69"
);
pub const OUTPUT_LE_PAIRING_THREE_PAIRS: &[u8] = &hex!(
"69ba9b252a7c2edf6645f67469e622e55fb903cf0524c4613bc28f827181eebf20e8f2d246a91f699015d01f736289160e22df7e4bb55f9558bd43a57126e347782fcf52c1cdc493792b81a5a98eccf17addbc87ce253aebc4b23427de8cb800e4689f7b1f0bfda3b414e41e0d640ede1ebdaedaaddbd96b4e1466036262ba82fe5ebdba3e5992038588fb4b146c5210acd0e18449e82a9b3b673a5deb84065d25a4978b098326fa011f49843109209dde0bff21a9931b94c241766de762c211b99f685cfefe151b3db9d87c7f3d282daaf86f1dd179eab27703db0dd5d485bcd79ce0ebee4b5f00184362467d7bd90997910ae348c28de33ded4245c2485faa79f38b540d1ed4fc783d695811e38b71daed25c409590bd5bd242f934739aa13b1311e40f0e06227f079ef70a813090e1faacf4786bafd0d51f00ab84400bec87234d527fc313f815373023c583f80027a7132af088d61a5904c8507ba0daac7b80e328dffe845eca12b5b4a056ea0ea17d8dc0752c1bad939d038bc36eaa50848c56e7767a8081ca60e454bde83d2efbfb2bb2f3a806f352d26edc1cc8aecd75dcc841be9da6ece9dfd2278078d990cff5c89d716c4bf8bcbd6e7e1ddfa4b46f742815d1170cba066edf88378358c8d898d20c048c1a6253ceb43906aecdf1532c57c20335af865d8d2ec2d20ccfd0b8fb87fd6c8fc77e25232033fc8a2950e6dfae1414cbbb12174dad9b330498a15f36e00d316100ebcff87cade723ed2a7734a7efacf71236aa9ac4697817e730792f591d7782ecf6ff142e2cc91783b0e"
);
// Test Case: PAIRING_BILINEARITY_IDENTITY
pub const INPUT_BE_PAIRING_BILINEARITY_IDENTITY: &[u8] = &hex!(
"0220c395088feefaf9d5a458088ca6cdda0c925fe753b82a0ce7a4e0c37c9f03d4679c36c4981e698a5a83dabc669c74155eefab2ca2817edc8d73b1723e94d449c091e58beb3b67eb2f248bdd6213cc3bca74be11e51943addbbe09b5a0251b0dd53be8717494bd848d63f87bd77d9d9f11bcf7f1ef09760fe2d65cd865d8dfc967f5f626f7d81598f5ca73702acf6413f8353510ec47e286e09e5b20487ff6ae1783853a99c182d756992bafd6e017858ac55ff11aa67ffb629ccb4bd5500511029411be813604e705128763456003f138feb9effd2eb43effbb0b9640f0bb20df8edc39c20fa8602229e180d488d101937df03fc800fdb1ba8c22db7e004a75acb592ddbdda4d13f859da4b7deb954108041f3d5edeb61fa9102c1d21184901a645b6f42d1a6b93473b48b4e18df9d95f743032a1e73fea401b25b4f9e900742e4945602701b0aafe306b2c7e1c4a156889fb76a3b7e3d03993142de706ea56129a7d7ca0e34d30198bebd97ac2364fbeb7dee2fda3e9f44a0863e2b5a1fd0de68937ddb50291acff6cbc602667f1e9ef5a625670ec8197a222f8aa98f35455c8e4785522f1b9a1e106f6eb9667f50292ba78a0cadc176d3bdfdc0c42ec4be6299883fd4587aec277fa0b79cd1107805280b95accb49f7fc62bc446897f1216ecddbdde719df4b45f51d83306054cbd10ccf93ebc62ef570a7c8a6480fc6e6c7b6877e044da7fe95a402206a204091448ad5d4e2d2f0e33f3798160d8a2951dbb6f654466bc333fd5daa6b5a694e70edfe14cde5ef0470e91fd7571b971f4"
);
pub const INPUT_LE_PAIRING_BILINEARITY_IDENTITY: &[u8] = &hex!(
"749c66bcda835a8a691e98c4369c67d4039f7cc3e0a4e70c2ab853e75f920cdacda68c0858a4d5f9faee8f0895c320021b25a0b509bedbad4319e511be74ca3bcc1362dd8b242feb673beb8be591c049d4943e72b1738ddc7e81a22cabef5e1564cf2a7073caf59815d8f726f6f567c9dfd865d85cd6e20f7609eff1f7bc119f9d7dd77bf8638d84bd947471e83bd50d0550d54bcb9c62fb7fa61af15fc58a8517e0d6af2b9956d782c1993a858317aef67f48205b9ee086e247ec103535f8134918211d2c10a91fb6de5e3d1f04084195eb7d4bda59f8134ddabddd92b5ac754a007edb228cbab1fd00c83ff07d9301d188d480e1292260a80fc239dc8edf20bbf040960bbbff3eb42efdefb9fe38f103604563871205e7043681be11940211fda1b5e263084af4e9a3fde2deb7be4f36c27ad9eb8b19304de3a07c7d9a1256ea06e72d149339d0e3b7a376fb8968154a1c7e2c6b30feaab001276045492e7400e9f9b4251b40ea3fe7a13230745fd9f98de1b4483b47936b1a2df4b645a601127f8946c42bc67f9fb4cc5ab98052800711cd790bfa77c2ae8745fd839829e64bec420cdcdf3b6d17dccaa078ba9202f56796ebf606e1a1b9f1225578e4c85554f398aaf822a29781ec7056625aefe9f1672660bc6cffac9102b5dd3789e60df471b97175fd910e47f05ede4ce1df0ee794a6b5a6dad53f33bc6644656fbb1d95a2d8608179f3330e2f2d4e5dad48140904a20622405ae97fda44e077687b6c6efc80648a7c0a57ef62bc3ef9cc10bd4c050633d8515fb4f49d71debdddec16"
);
pub const OUTPUT_BE_PAIRING_BILINEARITY_IDENTITY: &[u8] = &hex!(
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"
);
pub const OUTPUT_LE_PAIRING_BILINEARITY_IDENTITY: &[u8] = &hex!(
"010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);

View file

@ -0,0 +1,113 @@
use hex_literal::hex;
// Test Case: G1_SUB_RANDOM
pub const INPUT_BE_G1_SUB_RANDOM: &[u8] = &hex!(
"067e43b1dda8db9311206d70cc5fcfb3e3ca20fa762bc369b02fbc2bb5e27b7784f061ace1f7b44c3ae5bc79f71cf5c611805eefce0a0a1494bae2ca0cc44748a72c574018d6eeda06a671a5b208dd00159a48a09e462ef47f04fa9e1f0282980cad836a11aca92ecde45319ccd876df106634ebcaffb75b634e8da90ef4a11cf020d62e005d6a4929b0dca0fb25126e0f5643d2897247dca779b1e08e97981dce0c23062e3c357f544ee758315fdb24e0b600fd88733b0f50e588671bd3785a"
);
pub const INPUT_LE_G1_SUB_RANDOM: &[u8] = &hex!(
"c6f51cf779bce53a4cb4f7e1ac61f084777be2b52bbc2fb069c32b76fa20cae3b3cf5fcc706d201193dba8ddb1437e069882021f9efa047ff42e469ea0489a1500dd08b2a571a606daeed61840572ca74847c40ccae2ba94140a0aceef5e80116e1225fba0dcb029496a5d002ed620f01ca1f40ea98d4e635bb7ffcaeb346610df76d8cc1953e4cd2ea9ac116a83ad0c5a78d31b6788e5500f3b7388fd00b6e024db5f3158e74e547f353c2e06230cce1d98978ee0b179a7dc477289d243560f"
);
pub const OUTPUT_BE_G1_SUB_RANDOM: &[u8] = &hex!(
"0d90837443e588a58792b5bfc5d7447e679ee732316908f335d1631027b1d36380a425658bba0ee154d27810cb73a0310af344f157c1bab357d658277b7e881fb286cbde7fcedaf087b75d918894aeee9f0075d4abf794c5ce07e151724a3fc9"
);
pub const OUTPUT_LE_G1_SUB_RANDOM: &[u8] = &hex!(
"31a073cb1078d254e10eba8b6525a48063d3b1271063d135f308693132e79e677e44d7c5bfb59287a588e5437483900dc93f4a7251e107cec594f7abd475009feeae9488915db787f0dace7fdecb86b21f887e7b2758d657b3bac157f144f30a"
);
// Test Case: G1_SUB_P_MINUS_P
pub const INPUT_BE_G1_SUB_P_MINUS_P: &[u8] = &hex!(
"067e43b1dda8db9311206d70cc5fcfb3e3ca20fa762bc369b02fbc2bb5e27b7784f061ace1f7b44c3ae5bc79f71cf5c611805eefce0a0a1494bae2ca0cc44748a72c574018d6eeda06a671a5b208dd00159a48a09e462ef47f04fa9e1f028298067e43b1dda8db9311206d70cc5fcfb3e3ca20fa762bc369b02fbc2bb5e27b7784f061ace1f7b44c3ae5bc79f71cf5c611805eefce0a0a1494bae2ca0cc44748a72c574018d6eeda06a671a5b208dd00159a48a09e462ef47f04fa9e1f028298"
);
pub const INPUT_LE_G1_SUB_P_MINUS_P: &[u8] = &hex!(
"c6f51cf779bce53a4cb4f7e1ac61f084777be2b52bbc2fb069c32b76fa20cae3b3cf5fcc706d201193dba8ddb1437e069882021f9efa047ff42e469ea0489a1500dd08b2a571a606daeed61840572ca74847c40ccae2ba94140a0aceef5e8011c6f51cf779bce53a4cb4f7e1ac61f084777be2b52bbc2fb069c32b76fa20cae3b3cf5fcc706d201193dba8ddb1437e069882021f9efa047ff42e469ea0489a1500dd08b2a571a606daeed61840572ca74847c40ccae2ba94140a0aceef5e8011"
);
pub const OUTPUT_BE_G1_SUB_P_MINUS_P: &[u8] = &hex!(
"400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
pub const OUTPUT_LE_G1_SUB_P_MINUS_P: &[u8] = &hex!(
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
// Test Case: G1_SUB_INF_MINUS_P
pub const INPUT_BE_G1_SUB_INF_MINUS_P: &[u8] = &hex!(
"400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000067e43b1dda8db9311206d70cc5fcfb3e3ca20fa762bc369b02fbc2bb5e27b7784f061ace1f7b44c3ae5bc79f71cf5c611805eefce0a0a1494bae2ca0cc44748a72c574018d6eeda06a671a5b208dd00159a48a09e462ef47f04fa9e1f028298"
);
pub const INPUT_LE_G1_SUB_INF_MINUS_P: &[u8] = &hex!(
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c6f51cf779bce53a4cb4f7e1ac61f084777be2b52bbc2fb069c32b76fa20cae3b3cf5fcc706d201193dba8ddb1437e069882021f9efa047ff42e469ea0489a1500dd08b2a571a606daeed61840572ca74847c40ccae2ba94140a0aceef5e8011"
);
pub const OUTPUT_BE_G1_SUB_INF_MINUS_P: &[u8] = &hex!(
"067e43b1dda8db9311206d70cc5fcfb3e3ca20fa762bc369b02fbc2bb5e27b7784f061ace1f7b44c3ae5bc79f71cf5c60880b2fa6b75dc85b660c4ec3687658ebd4af444daae23e5608a60fb44a819240911b75e130dd10b3afa0561e0fd2813"
);
pub const OUTPUT_LE_G1_SUB_INF_MINUS_P: &[u8] = &hex!(
"c6f51cf779bce53a4cb4f7e1ac61f084777be2b52bbc2fb069c32b76fa20cae3b3cf5fcc706d201193dba8ddb1437e061328fde06105fa3a0bd10d135eb711092419a844fb608a60e523aeda44f44abd8e658736ecc460b685dc756bfab28008"
);
// Test Case: G1_SUB_P_MINUS_INF
pub const INPUT_BE_G1_SUB_P_MINUS_INF: &[u8] = &hex!(
"067e43b1dda8db9311206d70cc5fcfb3e3ca20fa762bc369b02fbc2bb5e27b7784f061ace1f7b44c3ae5bc79f71cf5c611805eefce0a0a1494bae2ca0cc44748a72c574018d6eeda06a671a5b208dd00159a48a09e462ef47f04fa9e1f028298400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
pub const INPUT_LE_G1_SUB_P_MINUS_INF: &[u8] = &hex!(
"c6f51cf779bce53a4cb4f7e1ac61f084777be2b52bbc2fb069c32b76fa20cae3b3cf5fcc706d201193dba8ddb1437e069882021f9efa047ff42e469ea0489a1500dd08b2a571a606daeed61840572ca74847c40ccae2ba94140a0aceef5e8011000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
pub const OUTPUT_BE_G1_SUB_P_MINUS_INF: &[u8] = &hex!(
"067e43b1dda8db9311206d70cc5fcfb3e3ca20fa762bc369b02fbc2bb5e27b7784f061ace1f7b44c3ae5bc79f71cf5c611805eefce0a0a1494bae2ca0cc44748a72c574018d6eeda06a671a5b208dd00159a48a09e462ef47f04fa9e1f028298"
);
pub const OUTPUT_LE_G1_SUB_P_MINUS_INF: &[u8] = &hex!(
"c6f51cf779bce53a4cb4f7e1ac61f084777be2b52bbc2fb069c32b76fa20cae3b3cf5fcc706d201193dba8ddb1437e069882021f9efa047ff42e469ea0489a1500dd08b2a571a606daeed61840572ca74847c40ccae2ba94140a0aceef5e8011"
);
// Test Case: G2_SUB_RANDOM
pub const INPUT_BE_G2_SUB_RANDOM: &[u8] = &hex!(
"016f712aa580c21a828e3ac63df471401960c40cd337d5556dd2d3b160300f7a9bada610715ffd45c40fbbc9cfff51b00f4d18c74e8e17b137763ef87b29d548a9b105b0c59e3e0105dbbe5c242575a2ca09e7c70d486624f6f13444b92cee171701c01c3d67ec4a2e1c4043c2f3d0ba2ec98e07a68b72d765ea6cb85d873db09ad01c4fd2846015c70b49d228f16bd708cb9c02d321cbc47cac94e879746de20f0d93f114461c0a11338f8c237f6d07cadcd0610ba7775ec05ca5d7e6a010380e496559d3550573945152d88d9432ae1156f6922ae6b5fa2840f87906a775bedb6039507fea8db39a6d0552e9fe0730056cfdc41090518cfcb8ecc161c881df841c877981813c214d2bb5b43ce06c7fcf70364251b9a67836a937ee20dbacd418a56acf144482e9be4bb1119d70ae58bdb67edb7288430fa78532ac7c5e0895cbe823da908e4a965eb6216a6f78cb3b0a794ff876a5e839573c2adf62689eee44983b13ac5914ee3f31cc8a6cc30ae9514fd76b2bc5bee70f0efbcbb3cde0c3"
);
pub const INPUT_LE_G2_SUB_RANDOM: &[u8] = &hex!(
"17ee2cb94434f1f62466480dc7e709caa27525245cbedb05013e9ec5b005b1a948d5297bf83e7637b1178e4ec7184d0fb051ffcfc9bb0fc445fd5f7110a6ad9b7a0f3060b1d3d26d55d537d30cc460194071f43dc63a8e821ac280a52a716f013810a0e6d7a55cc05e77a70b61d0dcca076d7f238c8f33110a1c4614f1930d0fe26d7479e894ac7cc4cb21d3029ccb08d76bf128d2490bc7156084d24f1cd09ab03d875db86cea65d7728ba6078ec92ebad0f3c243401c2e4aec673d1cc00117d4acdb20ee37a93678a6b951423670cf7f6ce03cb4b52b4d213c818179871c84df81c861c1ecb8fc8c519010c4fd6c053007fee952056d9ab38dea7f503960dbbe75a70679f84028fab5e62a92f65611ae32948dd8525194730555d35965490ec3e0cdb3cbfb0e0fe7bec52b6bd74f51e90ac36c8acc313fee1459ac133b9844ee9e6862df2a3c5739e8a576f84f790a3bcb786f6a21b65e964a8e90da23e8cb95085e7cac3285a70f438872db7eb6bd58ae709d11b14bbee9824414cf6aa518"
);
pub const OUTPUT_BE_G2_SUB_RANDOM: &[u8] = &hex!(
"0fc0dceaf67e8da36ba22b75ab9ec384c4d6ed85628570f8a19403a3141a3188a1f424b3edcc3a16336a0004eff4f259050e951f4ed54699932b5413df64eb3dac4288c90b51a888cf2ec6d0ab90bb234d3aba93bff3090ce016e62470f672130d74ba3e9eb0c996bb0d20878c6cb2ae5ad432b8ee11e5a7c368b39ca6fb6373851990652d4613565bf7ec5dfc0e6ad40f2a3e68a2d808b49c34feb31d5f5e10f5d7a5437332babee3d5477e1d51d92b9d0c6469d3ac65d4498c956dfcb46216"
);
pub const OUTPUT_LE_G2_SUB_RANDOM: &[u8] = &hex!(
"1372f67024e616e00c09f3bf93ba3a4d23bb90abd0c62ecf88a8510bc98842ac3deb64df13542b939946d54e1f950e0559f2f4ef04006a33163accedb324f4a188311a14a30394a1f870856285edd6c484c39eab752ba26ba38d7ef6eadcc00f1662b4fc6d958c49d465acd369640c9d2bd9511d7e47d5e3beba327343a5d7f5105e5f1db3fe349cb408d8a2683e2a0fd46a0efc5decf75b5613462d659019857363fba69cb368c3a7e511eeb832d45aaeb26c8c87200dbb96c9b09e3eba740d"
);
// Test Case: G2_SUB_P_MINUS_P
pub const INPUT_BE_G2_SUB_P_MINUS_P: &[u8] = &hex!(
"016f712aa580c21a828e3ac63df471401960c40cd337d5556dd2d3b160300f7a9bada610715ffd45c40fbbc9cfff51b00f4d18c74e8e17b137763ef87b29d548a9b105b0c59e3e0105dbbe5c242575a2ca09e7c70d486624f6f13444b92cee171701c01c3d67ec4a2e1c4043c2f3d0ba2ec98e07a68b72d765ea6cb85d873db09ad01c4fd2846015c70b49d228f16bd708cb9c02d321cbc47cac94e879746de20f0d93f114461c0a11338f8c237f6d07cadcd0610ba7775ec05ca5d7e6a01038016f712aa580c21a828e3ac63df471401960c40cd337d5556dd2d3b160300f7a9bada610715ffd45c40fbbc9cfff51b00f4d18c74e8e17b137763ef87b29d548a9b105b0c59e3e0105dbbe5c242575a2ca09e7c70d486624f6f13444b92cee171701c01c3d67ec4a2e1c4043c2f3d0ba2ec98e07a68b72d765ea6cb85d873db09ad01c4fd2846015c70b49d228f16bd708cb9c02d321cbc47cac94e879746de20f0d93f114461c0a11338f8c237f6d07cadcd0610ba7775ec05ca5d7e6a01038"
);
pub const INPUT_LE_G2_SUB_P_MINUS_P: &[u8] = &hex!(
"17ee2cb94434f1f62466480dc7e709caa27525245cbedb05013e9ec5b005b1a948d5297bf83e7637b1178e4ec7184d0fb051ffcfc9bb0fc445fd5f7110a6ad9b7a0f3060b1d3d26d55d537d30cc460194071f43dc63a8e821ac280a52a716f013810a0e6d7a55cc05e77a70b61d0dcca076d7f238c8f33110a1c4614f1930d0fe26d7479e894ac7cc4cb21d3029ccb08d76bf128d2490bc7156084d24f1cd09ab03d875db86cea65d7728ba6078ec92ebad0f3c243401c2e4aec673d1cc0011717ee2cb94434f1f62466480dc7e709caa27525245cbedb05013e9ec5b005b1a948d5297bf83e7637b1178e4ec7184d0fb051ffcfc9bb0fc445fd5f7110a6ad9b7a0f3060b1d3d26d55d537d30cc460194071f43dc63a8e821ac280a52a716f013810a0e6d7a55cc05e77a70b61d0dcca076d7f238c8f33110a1c4614f1930d0fe26d7479e894ac7cc4cb21d3029ccb08d76bf128d2490bc7156084d24f1cd09ab03d875db86cea65d7728ba6078ec92ebad0f3c243401c2e4aec673d1cc00117"
);
pub const OUTPUT_BE_G2_SUB_P_MINUS_P: &[u8] = &hex!(
"400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
pub const OUTPUT_LE_G2_SUB_P_MINUS_P: &[u8] = &hex!(
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
// Test Case: G2_SUB_INF_MINUS_P
pub const INPUT_BE_G2_SUB_INF_MINUS_P: &[u8] = &hex!(
"400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016f712aa580c21a828e3ac63df471401960c40cd337d5556dd2d3b160300f7a9bada610715ffd45c40fbbc9cfff51b00f4d18c74e8e17b137763ef87b29d548a9b105b0c59e3e0105dbbe5c242575a2ca09e7c70d486624f6f13444b92cee171701c01c3d67ec4a2e1c4043c2f3d0ba2ec98e07a68b72d765ea6cb85d873db09ad01c4fd2846015c70b49d228f16bd708cb9c02d321cbc47cac94e879746de20f0d93f114461c0a11338f8c237f6d07cadcd0610ba7775ec05ca5d7e6a01038"
);
pub const INPUT_LE_G2_SUB_INF_MINUS_P: &[u8] = &hex!(
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017ee2cb94434f1f62466480dc7e709caa27525245cbedb05013e9ec5b005b1a948d5297bf83e7637b1178e4ec7184d0fb051ffcfc9bb0fc445fd5f7110a6ad9b7a0f3060b1d3d26d55d537d30cc460194071f43dc63a8e821ac280a52a716f013810a0e6d7a55cc05e77a70b61d0dcca076d7f238c8f33110a1c4614f1930d0fe26d7479e894ac7cc4cb21d3029ccb08d76bf128d2490bc7156084d24f1cd09ab03d875db86cea65d7728ba6078ec92ebad0f3c243401c2e4aec673d1cc00117"
);
pub const OUTPUT_BE_G2_SUB_INF_MINUS_P: &[u8] = &hex!(
"016f712aa580c21a828e3ac63df471401960c40cd337d5556dd2d3b160300f7a9bada610715ffd45c40fbbc9cfff51b00f4d18c74e8e17b137763ef87b29d548a9b105b0c59e3e0105dbbe5c242575a2ca09e7c70d486624f6f13444b92cee1702ff51cdfc17fa501cff67728057dc1d35adbd7d4cf99fe8014665e89929b87383dbe3aedecf9fe9f2f3b62dd70e3ed4113575e7665e1ad5ce6f12cdc9d73ef55569b793df3ef6b555fd4314d331891c53cf2f9da5ac88a0f9a25a28195f9a73"
);
pub const OUTPUT_LE_G2_SUB_INF_MINUS_P: &[u8] = &hex!(
"17ee2cb94434f1f62466480dc7e709caa27525245cbedb05013e9ec5b005b1a948d5297bf83e7637b1178e4ec7184d0fb051ffcfc9bb0fc445fd5f7110a6ad9b7a0f3060b1d3d26d55d537d30cc460194071f43dc63a8e821ac280a52a716f01739a5f19285aa2f9a088aca59d2fcf531c8931d31443fd55b5f63edf93b76955f53ed7c9cd126fced51a5e66e7753511d43e0ed72db6f3f2e99fcfdeaee3db8373b82999e8654601e89ff94c7dbdad351ddc57807267ff1c50fa17fccd51ff02"
);
// Test Case: G2_SUB_P_MINUS_INF
pub const INPUT_BE_G2_SUB_P_MINUS_INF: &[u8] = &hex!(
"016f712aa580c21a828e3ac63df471401960c40cd337d5556dd2d3b160300f7a9bada610715ffd45c40fbbc9cfff51b00f4d18c74e8e17b137763ef87b29d548a9b105b0c59e3e0105dbbe5c242575a2ca09e7c70d486624f6f13444b92cee171701c01c3d67ec4a2e1c4043c2f3d0ba2ec98e07a68b72d765ea6cb85d873db09ad01c4fd2846015c70b49d228f16bd708cb9c02d321cbc47cac94e879746de20f0d93f114461c0a11338f8c237f6d07cadcd0610ba7775ec05ca5d7e6a01038400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
pub const INPUT_LE_G2_SUB_P_MINUS_INF: &[u8] = &hex!(
"17ee2cb94434f1f62466480dc7e709caa27525245cbedb05013e9ec5b005b1a948d5297bf83e7637b1178e4ec7184d0fb051ffcfc9bb0fc445fd5f7110a6ad9b7a0f3060b1d3d26d55d537d30cc460194071f43dc63a8e821ac280a52a716f013810a0e6d7a55cc05e77a70b61d0dcca076d7f238c8f33110a1c4614f1930d0fe26d7479e894ac7cc4cb21d3029ccb08d76bf128d2490bc7156084d24f1cd09ab03d875db86cea65d7728ba6078ec92ebad0f3c243401c2e4aec673d1cc00117000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
pub const OUTPUT_BE_G2_SUB_P_MINUS_INF: &[u8] = &hex!(
"016f712aa580c21a828e3ac63df471401960c40cd337d5556dd2d3b160300f7a9bada610715ffd45c40fbbc9cfff51b00f4d18c74e8e17b137763ef87b29d548a9b105b0c59e3e0105dbbe5c242575a2ca09e7c70d486624f6f13444b92cee171701c01c3d67ec4a2e1c4043c2f3d0ba2ec98e07a68b72d765ea6cb85d873db09ad01c4fd2846015c70b49d228f16bd708cb9c02d321cbc47cac94e879746de20f0d93f114461c0a11338f8c237f6d07cadcd0610ba7775ec05ca5d7e6a01038"
);
pub const OUTPUT_LE_G2_SUB_P_MINUS_INF: &[u8] = &hex!(
"17ee2cb94434f1f62466480dc7e709caa27525245cbedb05013e9ec5b005b1a948d5297bf83e7637b1178e4ec7184d0fb051ffcfc9bb0fc445fd5f7110a6ad9b7a0f3060b1d3d26d55d537d30cc460194071f43dc63a8e821ac280a52a716f013810a0e6d7a55cc05e77a70b61d0dcca076d7f238c8f33110a1c4614f1930d0fe26d7479e894ac7cc4cb21d3029ccb08d76bf128d2490bc7156084d24f1cd09ab03d875db86cea65d7728ba6078ec92ebad0f3c243401c2e4aec673d1cc00117"
);

View file

@ -0,0 +1,82 @@
use hex_literal::hex;
// Test Case: G1_VALIDATE_RANDOM_VALID
pub const INPUT_BE_G1_VALIDATE_RANDOM_VALID: &[u8] = &hex!(
"16a3fa43c5a867c98021aa604a282d5a69b5f47c806b1b8e9e60002e901b3dcd41268da5377172172469fc7393100c270b1335d76b805e44162e4ab3ece8dc1e30a9551046701a254968cbbd2a608d5aa7293d52b8505d70cc8ce1f56782b8c2"
);
pub const INPUT_LE_G1_VALIDATE_RANDOM_VALID: &[u8] = &hex!(
"270c109373fc692417727137a58d2641cd3d1b902e00609e8e1b6b807cf4b5695a2d284a60aa2180c967a8c543faa316c2b88267f5e18ccc705d50b8523d29a75a8d602abdcb6849251a70461055a9301edce8ecb34a2e16445e806bd735130b"
);
pub const EXPECTED_G1_VALIDATE_RANDOM_VALID: bool = true;
// Test Case: G1_VALIDATE_INFINITY_VALID
pub const INPUT_BE_G1_VALIDATE_INFINITY_VALID: &[u8] = &hex!(
"400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
pub const INPUT_LE_G1_VALIDATE_INFINITY_VALID: &[u8] = &hex!(
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
pub const EXPECTED_G1_VALIDATE_INFINITY_VALID: bool = true;
// Test Case: G1_VALIDATE_GENERATOR_VALID
pub const INPUT_BE_G1_VALIDATE_GENERATOR_VALID: &[u8] = &hex!(
"17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1"
);
pub const INPUT_LE_G1_VALIDATE_GENERATOR_VALID: &[u8] = &hex!(
"bbc622db0af03afbef1a7af93fe8556c58ac1b173f3a4ea105b974974f8c68c30faca94f8c63952694d79731a7d3f117e1e7c5462923aa0ce48a88a244c73cd0edb3042ccb18db00f60ad0d595e0f5fce48a1d74ed309ea0f1a0aae381f4b308"
);
pub const EXPECTED_G1_VALIDATE_GENERATOR_VALID: bool = true;
// Test Case: G2_VALIDATE_RANDOM_VALID
pub const INPUT_BE_G2_VALIDATE_RANDOM_VALID: &[u8] = &hex!(
"004fcf735b480050313bcbbdb2f0128ddf933e4f628393216797890ca00d4eb40ddd59efb2f98d0826891747d5021c0d18a8330622b8e416ad0be0a80e679a12a633ff9a2de6fd959110fb6bf83735962583858a9cc346ca8390a6a450fbb3a70836bc990aeb530ed35fd43678af9453fd6a35b29d76d06e00bb6f0e8cf68bc8cdb24824438c2764a3688c4e5b7b82c50cb04668412b68e866eee573fd3e3dcf74dff5cefaa31ec84c655d45d8f0bdc6fd1bc720d7e00c324ecc6a2875442c71"
);
pub const INPUT_LE_G2_VALIDATE_RANDOM_VALID: &[u8] = &hex!(
"a7b3fb50a4a69083ca46c39c8a858325963537f86bfb109195fde62d9aff33a6129a670ea8e00bad16e4b8220633a8180d1c02d547178926088df9b2ef59dd0db44e0da00c899767219383624f3e93df8d12f0b2bdcb3b315000485b73cf4f00712c4475286acc4e320ce0d720c71bfdc6bdf0d8455d654cc81ea3facef5df74cf3d3efd73e5ee66e8682b416846b00cc5827b5b4e8c68a364278c432448b2cdc88bf68c0e6fbb006ed0769db2356afd5394af7836d45fd30e53eb0a99bc3608"
);
pub const EXPECTED_G2_VALIDATE_RANDOM_VALID: bool = true;
// Test Case: G2_VALIDATE_INFINITY_VALID
pub const INPUT_BE_G2_VALIDATE_INFINITY_VALID: &[u8] = &hex!(
"400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
pub const INPUT_LE_G2_VALIDATE_INFINITY_VALID: &[u8] = &hex!(
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
);
pub const EXPECTED_G2_VALIDATE_INFINITY_VALID: bool = true;
// Test Case: G1_VALIDATE_NOT_ON_CURVE_INVALID
pub const INPUT_BE_G1_VALIDATE_NOT_ON_CURVE_INVALID: &[u8] = &hex!(
"16a3fa43c5a867c98021aa604a282d5a69b5f47c806b1b8e9e60002e901b3dcd41268da5377172172469fc7393100c270b1335d76b805e44162e4ab3ece8dc1e30a9551046701a254968cbbd2a608d5aa7293d52b8505d70cc8ce1f56782b8c7"
);
pub const INPUT_LE_G1_VALIDATE_NOT_ON_CURVE_INVALID: &[u8] = &hex!(
"270c109373fc692417727137a58d2641cd3d1b902e00609e8e1b6b807cf4b5695a2d284a60aa2180c967a8c543faa316c7b88267f5e18ccc705d50b8523d29a75a8d602abdcb6849251a70461055a9301edce8ecb34a2e16445e806bd735130b"
);
pub const EXPECTED_G1_VALIDATE_NOT_ON_CURVE_INVALID: bool = false;
// Test Case: G1_VALIDATE_FIELD_X_EQ_P_INVALID
pub const INPUT_BE_G1_VALIDATE_FIELD_X_EQ_P_INVALID: &[u8] = &hex!(
"1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1"
);
pub const INPUT_LE_G1_VALIDATE_FIELD_X_EQ_P_INVALID: &[u8] = &hex!(
"abaafffffffffeb9ffff53b1feffab1e24f6b0f6a0d23067bf1285f3844b7764d7ac4b43b6a71b4b9ae67f39ea11011ae1e7c5462923aa0ce48a88a244c73cd0edb3042ccb18db00f60ad0d595e0f5fce48a1d74ed309ea0f1a0aae381f4b308"
);
pub const EXPECTED_G1_VALIDATE_FIELD_X_EQ_P_INVALID: bool = false;
// Test Case: G2_VALIDATE_NOT_ON_CURVE_INVALID
pub const INPUT_BE_G2_VALIDATE_NOT_ON_CURVE_INVALID: &[u8] = &hex!(
"004fcf735b480050313bcbbdb2f0128ddf933e4f628393216797890ca00d4eb40ddd59efb2f98d0826891747d5021c0d18a8330622b8e416ad0be0a80e679a12a633ff9a2de6fd959110fb6bf83735962583858a9cc346ca8390a6a450fbb3a70836bc990aeb530ed35fd43678af9453fd6a35b29d76d06e00bb6f0e8cf68bc8cdb24824438c2764a3688c4e5b7b82c50cb04668412b68e866eee573fd3e3dcf74dff5cefaa31ec84c655d45d8f0bdc6fd1bc720d7e00c324ecc6a2875442c76"
);
pub const INPUT_LE_G2_VALIDATE_NOT_ON_CURVE_INVALID: &[u8] = &hex!(
"a7b3fb50a4a69083ca46c39c8a858325963537f86bfb109195fde62d9aff33a6129a670ea8e00bad16e4b8220633a8180d1c02d547178926088df9b2ef59dd0db44e0da00c899767219383624f3e93df8d12f0b2bdcb3b315000485b73cf4f00762c4475286acc4e320ce0d720c71bfdc6bdf0d8455d654cc81ea3facef5df74cf3d3efd73e5ee66e8682b416846b00cc5827b5b4e8c68a364278c432448b2cdc88bf68c0e6fbb006ed0769db2356afd5394af7836d45fd30e53eb0a99bc3608"
);
pub const EXPECTED_G2_VALIDATE_NOT_ON_CURVE_INVALID: bool = false;
// Test Case: G2_VALIDATE_FIELD_X_EQ_P_INVALID
pub const INPUT_BE_G2_VALIDATE_FIELD_X_EQ_P_INVALID: &[u8] = &hex!(
"13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801"
);
pub const INPUT_LE_G2_VALIDATE_FIELD_X_EQ_P_INVALID: &[u8] = &hex!(
"abaafffffffffeb9ffff53b1feffab1e24f6b0f6a0d23067bf1285f3844b7764d7ac4b43b6a71b4b9ae67f39ea11011a7e2b045d057dace5575d941312f14c3349507fdcbb61dab51ab62099d0d06b59654f2788a0d3ac7d609f7152602be0130128b808865493e189a2ac3bccc93a922cd16051699a426da7d3bd8caa9bfdad1a352edac6cdc98c116e7d7227d5e50cbe795ff05f07a9aaa11dec5c270d373fab992e57ab927426af63a7857e283ecb998bc22bb0d2ac32cc34a72ea0c40606"
);
pub const EXPECTED_G2_VALIDATE_FIELD_X_EQ_P_INVALID: bool = false;

View file

@ -0,0 +1,173 @@
use crate::{
Version,
encoding::{Endianness, PodG1Point, PodG2Point},
};
/// Validates that a G1 point is on the curve and in the correct subgroup.
pub fn bls12_381_g1_point_validation(
_version: Version,
input: &PodG1Point,
endianness: Endianness,
) -> bool {
// to_affine performs Field, On-Curve, and Subgroup checks
input.to_affine(endianness).is_some()
}
/// Validates that a G2 point is on the curve and in the correct subgroup.
pub fn bls12_381_g2_point_validation(
_version: Version,
input: &PodG2Point,
endianness: Endianness,
) -> bool {
// to_affine performs Field, On-Curve, and Subgroup checks
input.to_affine(endianness).is_some()
}
#[cfg(test)]
mod tests {
use {
super::*,
crate::{
encoding::{swap_fq_endianness, swap_g2_c0_c1},
test_vectors::*,
},
bytemuck::pod_read_unaligned,
};
fn to_pod_g1(bytes: &[u8]) -> PodG1Point {
pod_read_unaligned(bytes)
}
fn to_pod_g2(bytes: &[u8]) -> PodG2Point {
pod_read_unaligned(bytes)
}
fn run_g1_test(test_name: &str, input_be: &[u8], expected_valid: bool, input_le: &[u8]) {
let input_be_pod = to_pod_g1(input_be);
let result_be = bls12_381_g1_point_validation(Version::V0, &input_be_pod, Endianness::BE);
assert_eq!(
result_be, expected_valid,
"G1 {test_name} BE Validation Failed. Expected {expected_valid}, got {result_be}",
);
if expected_valid {
let point = input_be_pod.to_affine(Endianness::BE).unwrap();
let bytes = point.to_uncompressed();
assert_eq!(bytes, input_be_pod.0, "G1 {test_name} BE Round Trip Failed");
}
let input_le_pod = to_pod_g1(input_le);
let result_le = bls12_381_g1_point_validation(Version::V0, &input_le_pod, Endianness::LE);
assert_eq!(
result_le, expected_valid,
"G1 {test_name} LE Validation Failed. Expected {expected_valid}, got {result_le}",
);
if expected_valid {
let point = input_le_pod.to_affine(Endianness::LE).unwrap();
let mut bytes = point.to_uncompressed(); // Returns Zcash BE
swap_fq_endianness(&mut bytes); // Convert to LE
assert_eq!(bytes, input_le_pod.0, "G1 {test_name} LE Round Trip Failed");
}
}
fn run_g2_test(test_name: &str, input_be: &[u8], expected_valid: bool, input_le: &[u8]) {
let input_be_pod = to_pod_g2(input_be);
let result_be = bls12_381_g2_point_validation(Version::V0, &input_be_pod, Endianness::BE);
assert_eq!(
result_be, expected_valid,
"G2 {test_name} BE Validation Failed. Expected {expected_valid}, got {result_be}",
);
if expected_valid {
let point = input_be_pod.to_affine(Endianness::BE).unwrap();
let bytes = point.to_uncompressed();
assert_eq!(bytes, input_be_pod.0, "G2 {test_name} BE Round Trip Failed");
}
let input_le_pod = to_pod_g2(input_le);
let result_le = bls12_381_g2_point_validation(Version::V0, &input_le_pod, Endianness::LE);
assert_eq!(
result_le, expected_valid,
"G2 {test_name} LE Validation Failed. Expected {expected_valid}, got {result_le}",
);
if expected_valid {
let point = input_le_pod.to_affine(Endianness::LE).unwrap();
let mut bytes = point.to_uncompressed(); // Returns Zcash BE (c1, c0)
swap_fq_endianness(&mut bytes); // Convert elements to LE
swap_g2_c0_c1(&mut bytes); // Convert to (c0, c1) layout
assert_eq!(bytes, input_le_pod.0, "G2 {test_name} LE Round Trip Failed");
}
}
#[test]
fn test_g1_validation_valid_points() {
run_g1_test(
"Validate: RANDOM",
INPUT_BE_G1_VALIDATE_RANDOM_VALID,
EXPECTED_G1_VALIDATE_RANDOM_VALID,
INPUT_LE_G1_VALIDATE_RANDOM_VALID,
);
run_g1_test(
"Validate: INFINITY",
INPUT_BE_G1_VALIDATE_INFINITY_VALID,
EXPECTED_G1_VALIDATE_INFINITY_VALID,
INPUT_LE_G1_VALIDATE_INFINITY_VALID,
);
run_g1_test(
"Validate: GENERATOR",
INPUT_BE_G1_VALIDATE_GENERATOR_VALID,
EXPECTED_G1_VALIDATE_GENERATOR_VALID,
INPUT_LE_G1_VALIDATE_GENERATOR_VALID,
);
}
#[test]
fn test_g1_validation_invalid_points() {
run_g1_test(
"Validate: NOT_ON_CURVE",
INPUT_BE_G1_VALIDATE_NOT_ON_CURVE_INVALID,
EXPECTED_G1_VALIDATE_NOT_ON_CURVE_INVALID,
INPUT_LE_G1_VALIDATE_NOT_ON_CURVE_INVALID,
);
run_g1_test(
"Validate: FIELD_X_EQ_P",
INPUT_BE_G1_VALIDATE_FIELD_X_EQ_P_INVALID,
EXPECTED_G1_VALIDATE_FIELD_X_EQ_P_INVALID,
INPUT_LE_G1_VALIDATE_FIELD_X_EQ_P_INVALID,
);
}
#[test]
fn test_g2_validation_valid_points() {
run_g2_test(
"Validate: RANDOM",
INPUT_BE_G2_VALIDATE_RANDOM_VALID,
EXPECTED_G2_VALIDATE_RANDOM_VALID,
INPUT_LE_G2_VALIDATE_RANDOM_VALID,
);
run_g2_test(
"Validate: INFINITY",
INPUT_BE_G2_VALIDATE_INFINITY_VALID,
EXPECTED_G2_VALIDATE_INFINITY_VALID,
INPUT_LE_G2_VALIDATE_INFINITY_VALID,
);
}
#[test]
fn test_g2_validation_invalid_points() {
run_g2_test(
"Validate: NOT_ON_CURVE",
INPUT_BE_G2_VALIDATE_NOT_ON_CURVE_INVALID,
EXPECTED_G2_VALIDATE_NOT_ON_CURVE_INVALID,
INPUT_LE_G2_VALIDATE_NOT_ON_CURVE_INVALID,
);
run_g2_test(
"Validate: FIELD_X_EQ_P",
INPUT_BE_G2_VALIDATE_FIELD_X_EQ_P_INVALID,
EXPECTED_G2_VALIDATE_FIELD_X_EQ_P_INVALID,
INPUT_LE_G2_VALIDATE_FIELD_X_EQ_P_INVALID,
);
}
}