1个不稳定版本
0.1.0 | 2023年6月18日 |
---|
#2003 in 密码学
82KB
1.5K SLoC
ECFFT
此库通过实现椭圆曲线快速傅里叶变换(ECFFT)第一部分中概述的所有算法,实现了在任何有限域上快速多项式算术。
算法 | 描述 | 运行时间 |
---|---|---|
ENTER | 系数到评估(fft类似) | $\mathcal{O}(n\log^2{n})$ |
EXIT | 评估到系数(ifft类似) | $\mathcal{O}(n\log^2{n})$ |
DEGREE | 计算多项式的度数 | $\mathcal{O}(n\log{n})$ |
EXTEND | 从一个集合扩展到另一个集合的评估 | $\mathcal{O}(n\log{n})$ |
MEXTEND | 特殊单变量多项式的EXTEND | $\mathcal{O}(n\log{n})$ |
MOD | 计算多项式除法的余数 | $\mathcal{O}(n\log{n})$ |
REDC | 计算Montgomery的REDC的多项式类似物 | $\mathcal{O}(n\log{n})$ |
VANISH | 生成一个消失多项式(来自第7.1节) | $\mathcal{O}(n\log^2{n})$ |
还实现了来自ECFFT第二部分的一些相关算法
算法 | 描述 | 运行时间 |
---|---|---|
FIND_CURVE | 找到$\mathbb{F}_q$上具有$2^k$阶循环子群的曲线 | $\mathcal{O}(2^k\log{q})$ |
编译时构建FFTrees
FFTrees是ECFFT算法构建的核心数据结构。可以在编译时生成和序列化FFTrees,然后在运行时反序列化和使用。这可能是首选的,因为生成FFTrees涉及大量的计算。虽然这种方法提高了运行时间,但它将显著增加二进制文件的大小。生成一个能够评估/插值度数为$n$的多项式的FFTTree需要$\mathcal{O}(n\log^3{n})$ - 该FFTTree的空间复杂度为$\mathcal{O}(n)$。
// build.rs
use ark_serialize::CanonicalSerialize;
use ecfft::{secp256k1::Fp, FftreeField};
use std::{env, fs::File, io, path::Path};
fn main() -> io::Result<()> {
let fftree = Fp::build_fftree(1 << 16).unwrap();
let out_dir = env::var_os("OUT_DIR").unwrap();
let path = Path::new(&out_dir).join("fftree");
fftree.serialize_compressed(File::create(path)?).unwrap();
println!("cargo:rerun-if-changed=build.rs");
Ok(())
}
// src/main.rs
use ark_ff::One;
use ark_serialize::CanonicalDeserialize;
use ecfft::{ecfft::FFTree, secp256k1::Fp};
use std::sync::OnceLock;
static FFTREE: OnceLock<FFTree<Fp>> = OnceLock::new();
fn get_fftree() -> &'static FFTree<Fp> {
const BYTES: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/fftree"));
FFTREE.get_or_init(|| FFTree::deserialize_compressed(BYTES).unwrap())
}
fn main() {
let fftree = get_fftree();
// = x^65535 + x^65534 + ... + x + 1
let poly = vec![Fp::one(); 1 << 16];
let evals = fftree.enter(&poly);
let coeffs = fftree.exit(&evals);
assert_eq!(poly, coeffs);
}
参考文献
依赖项
~5MB
~90K SLoC