#elliptic-curve #fft #finite-fields #prime-field

ecfft

适用于所有素数域的椭圆曲线快速傅里叶变换

1个不稳定版本

0.1.0 2023年6月18日

#2003 in 密码学

MIT许可

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