mirror of
https://github.com/saymrwulf/pasta_curves-source.git
synced 2026-09-06 20:20:34 +00:00
commit
93df9c0cb9
9 changed files with 101 additions and 69 deletions
18
.github/workflows/ci.yml
vendored
18
.github/workflows/ci.yml
vendored
|
|
@ -16,7 +16,7 @@ jobs:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions-rs/toolchain@v1
|
- uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
toolchain: 1.51.0
|
||||||
override: true
|
override: true
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
|
|
@ -37,7 +37,7 @@ jobs:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions-rs/toolchain@v1
|
- uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
toolchain: 1.51.0
|
||||||
override: true
|
override: true
|
||||||
- name: Add target
|
- name: Add target
|
||||||
run: rustup target add ${{ matrix.target }}
|
run: rustup target add ${{ matrix.target }}
|
||||||
|
|
@ -55,7 +55,7 @@ jobs:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions-rs/toolchain@v1
|
- uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
toolchain: 1.51.0
|
||||||
override: true
|
override: true
|
||||||
# Build benchmarks to prevent bitrot
|
# Build benchmarks to prevent bitrot
|
||||||
- name: Build benchmarks
|
- name: Build benchmarks
|
||||||
|
|
@ -71,7 +71,7 @@ jobs:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions-rs/toolchain@v1
|
- uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
toolchain: 1.51.0
|
||||||
override: true
|
override: true
|
||||||
- name: cargo build
|
- name: cargo build
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
|
|
@ -85,7 +85,7 @@ jobs:
|
||||||
run: mdbook test -L target/debug/deps book/
|
run: mdbook test -L target/debug/deps book/
|
||||||
|
|
||||||
clippy:
|
clippy:
|
||||||
name: Clippy (stable)
|
name: Clippy (1.51.0)
|
||||||
timeout-minutes: 30
|
timeout-minutes: 30
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
|
@ -93,13 +93,13 @@ jobs:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions-rs/toolchain@v1
|
- uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
toolchain: 1.51.0
|
||||||
components: clippy
|
components: clippy
|
||||||
override: true
|
override: true
|
||||||
- name: Run clippy
|
- name: Run clippy
|
||||||
uses: actions-rs/clippy-check@v1
|
uses: actions-rs/clippy-check@v1
|
||||||
with:
|
with:
|
||||||
name: Clippy (stable)
|
name: Clippy (1.51.0)
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
args: --all-features --all-targets -- -D warnings
|
args: --all-features --all-targets -- -D warnings
|
||||||
|
|
||||||
|
|
@ -158,7 +158,7 @@ jobs:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions-rs/toolchain@v1
|
- uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
toolchain: 1.51.0
|
||||||
override: true
|
override: true
|
||||||
- name: cargo fetch
|
- name: cargo fetch
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
|
|
@ -181,7 +181,7 @@ jobs:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions-rs/toolchain@v1
|
- uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
toolchain: 1.51.0
|
||||||
override: true
|
override: true
|
||||||
- run: rustup component add rustfmt
|
- run: rustup component add rustfmt
|
||||||
- uses: actions-rs/cargo@v1
|
- uses: actions-rs/cargo@v1
|
||||||
|
|
|
||||||
|
|
@ -6,4 +6,6 @@ and this project adheres to Rust's notion of
|
||||||
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [0.1.0] - 2021-06-01
|
||||||
Initial release!
|
Initial release!
|
||||||
|
|
|
||||||
15
Cargo.toml
15
Cargo.toml
|
|
@ -1,7 +1,7 @@
|
||||||
[package]
|
[package]
|
||||||
name = "pasta_curves"
|
name = "pasta_curves"
|
||||||
description = "Implementation of the Pallas and Vesta (Pasta) curve cycle"
|
description = "Implementation of the Pallas and Vesta (Pasta) curve cycle"
|
||||||
version = "0.0.0"
|
version = "0.1.0"
|
||||||
authors = [
|
authors = [
|
||||||
"Sean Bowe <sean@electriccoin.co>",
|
"Sean Bowe <sean@electriccoin.co>",
|
||||||
"Ying Tong Lai <yingtong@electriccoin.co>",
|
"Ying Tong Lai <yingtong@electriccoin.co>",
|
||||||
|
|
@ -13,9 +13,7 @@ license-file = "LICENSE-BOSL"
|
||||||
repository = "https://github.com/zcash/pasta_curves"
|
repository = "https://github.com/zcash/pasta_curves"
|
||||||
documentation = "https://docs.rs/pasta_curves"
|
documentation = "https://docs.rs/pasta_curves"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
exclude = ["Contributor_Agreement"]
|
||||||
# We are not publishing this yet.
|
|
||||||
publish = false
|
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
all-features = true
|
all-features = true
|
||||||
|
|
@ -39,12 +37,13 @@ harness = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
subtle = "2.3"
|
subtle = "2.3"
|
||||||
ff = "0.9"
|
ff = "0.10"
|
||||||
group = "0.9"
|
group = "0.10"
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
blake2b_simd = "0.5"
|
blake2b_simd = "0.5"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
static_assertions = "1.1.0"
|
static_assertions = "1.1.0"
|
||||||
|
|
||||||
# Temporary workaround for https://github.com/myrrlyn/funty/issues/3
|
[features]
|
||||||
funty = "=1.1.0"
|
default = ["bits"]
|
||||||
|
bits = ["ff/bits"]
|
||||||
|
|
|
||||||
31
README.md
31
README.md
|
|
@ -1,12 +1,35 @@
|
||||||
# `pasta_curves`
|
# `pasta_curves`
|
||||||
|
|
||||||
**IMPORTANT**: This library is being actively developed and should not be used in production software.
|
This crate provides an implementation of the Pasta elliptic curve constructions,
|
||||||
|
Pallas and Vesta. More details about the Pasta curves can be found
|
||||||
|
[in this blog post](https://electriccoin.co/blog/the-pasta-curves-for-halo-2-and-beyond/).
|
||||||
|
|
||||||
## [Documentation](https://docs.rs/pasta_curves)
|
## [Documentation](https://docs.rs/pasta_curves)
|
||||||
|
|
||||||
This crate currently has a Minimum Supported Rust Version of 1.49.0. When const generics
|
## Minimum Supported Rust Version
|
||||||
are stabilized [in Rust 1.51.0](https://github.com/rust-lang/rust/pull/79135), we plan
|
|
||||||
to require that version.
|
Requires Rust **1.51** or higher.
|
||||||
|
|
||||||
|
Minimum supported Rust version can be changed in the future, but it will be done with a
|
||||||
|
minor version bump.
|
||||||
|
|
||||||
|
## Curve Descriptions
|
||||||
|
|
||||||
|
- Pallas: y<sup>2</sup> = x<sup>3</sup> + 5 over
|
||||||
|
`GF(0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001)`.
|
||||||
|
|
||||||
|
- Vesta: y<sup>2</sup> = x<sup>3</sup> + 5 over
|
||||||
|
`GF(0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001)`.
|
||||||
|
|
||||||
|
The Pasta curves form a cycle with one another: the order of each curve is exactly the
|
||||||
|
base field of the other. This property is critical to the efficiency of recursive proof
|
||||||
|
systems. They are designed to be highly 2-adic, meaning that a large power-of-two
|
||||||
|
multiplicative subgroup exists in each field. This is important for the performance of
|
||||||
|
polynomial arithmetic over their scalar fields and is essential for protocols similar
|
||||||
|
to PLONK.
|
||||||
|
|
||||||
|
These curves can be reproducibly obtained
|
||||||
|
[using a curve search utility we’ve published](https://github.com/zcash/pasta).
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|
|
||||||
1
rust-toolchain
Normal file
1
rust-toolchain
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
1.51.0
|
||||||
|
|
@ -219,8 +219,8 @@ impl<F: FieldExt> SqrtTables<F> {
|
||||||
|
|
||||||
// Now invert gtab[3].
|
// Now invert gtab[3].
|
||||||
let mut inv: Vec<u8> = vec![1; hash_mod];
|
let mut inv: Vec<u8> = vec![1; hash_mod];
|
||||||
for j in 0..256 {
|
for (j, gtab_3_j) in gtab_3.iter().enumerate() {
|
||||||
let hash = hasher.hash(>ab_3[j]);
|
let hash = hasher.hash(gtab_3_j);
|
||||||
// 1 is the last value to be assigned, so this ensures there are no collisions.
|
// 1 is the last value to be assigned, so this ensures there are no collisions.
|
||||||
assert!(inv[hash] == 1);
|
assert!(inv[hash] == 1);
|
||||||
inv[hash] = ((256 - j) & 0xFF) as u8;
|
inv[hash] = ((256 - j) & 0xFF) as u8;
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
use core::convert::TryInto;
|
use core::convert::TryInto;
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use core::ops::{Add, Mul, Neg, Sub};
|
use core::ops::{Add, Mul, Neg, Sub};
|
||||||
use ff::FieldBits;
|
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
|
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
|
||||||
|
|
||||||
|
#[cfg(feature = "bits")]
|
||||||
|
use ff::{FieldBits, PrimeFieldBits};
|
||||||
|
|
||||||
use crate::arithmetic::{adc, mac, sbb, FieldExt, Group, SqrtTables};
|
use crate::arithmetic::{adc, mac, sbb, FieldExt, Group, SqrtTables};
|
||||||
|
|
||||||
/// This represents an element of $\mathbb{F}_p$ where
|
/// This represents an element of $\mathbb{F}_p$ where
|
||||||
|
|
@ -529,15 +531,8 @@ impl ff::Field for Fp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_pointer_width = "64"))]
|
|
||||||
type ReprBits = [u32; 8];
|
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
|
||||||
type ReprBits = [u64; 4];
|
|
||||||
|
|
||||||
impl ff::PrimeField for Fp {
|
impl ff::PrimeField for Fp {
|
||||||
type Repr = [u8; 32];
|
type Repr = [u8; 32];
|
||||||
type ReprBits = ReprBits;
|
|
||||||
|
|
||||||
const NUM_BITS: u32 = 255;
|
const NUM_BITS: u32 = 255;
|
||||||
const CAPACITY: u32 = 254;
|
const CAPACITY: u32 = 254;
|
||||||
|
|
@ -551,6 +546,29 @@ impl ff::PrimeField for Fp {
|
||||||
self.to_bytes()
|
self.to_bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_odd(&self) -> bool {
|
||||||
|
self.to_bytes()[0] & 1 == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn multiplicative_generator() -> Self {
|
||||||
|
GENERATOR
|
||||||
|
}
|
||||||
|
|
||||||
|
fn root_of_unity() -> Self {
|
||||||
|
Self::ROOT_OF_UNITY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "bits", not(target_pointer_width = "64")))]
|
||||||
|
type ReprBits = [u32; 8];
|
||||||
|
|
||||||
|
#[cfg(all(feature = "bits", target_pointer_width = "64"))]
|
||||||
|
type ReprBits = [u64; 4];
|
||||||
|
|
||||||
|
#[cfg(feature = "bits")]
|
||||||
|
impl PrimeFieldBits for Fp {
|
||||||
|
type ReprBits = ReprBits;
|
||||||
|
|
||||||
fn to_le_bits(&self) -> FieldBits<Self::ReprBits> {
|
fn to_le_bits(&self) -> FieldBits<Self::ReprBits> {
|
||||||
let bytes = self.to_bytes();
|
let bytes = self.to_bytes();
|
||||||
|
|
||||||
|
|
@ -577,10 +595,6 @@ impl ff::PrimeField for Fp {
|
||||||
FieldBits::new(limbs)
|
FieldBits::new(limbs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_odd(&self) -> bool {
|
|
||||||
self.to_bytes()[0] & 1 == 1
|
|
||||||
}
|
|
||||||
|
|
||||||
fn char_le_bits() -> FieldBits<Self::ReprBits> {
|
fn char_le_bits() -> FieldBits<Self::ReprBits> {
|
||||||
#[cfg(not(target_pointer_width = "64"))]
|
#[cfg(not(target_pointer_width = "64"))]
|
||||||
{
|
{
|
||||||
|
|
@ -590,14 +604,6 @@ impl ff::PrimeField for Fp {
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
FieldBits::new(MODULUS.0)
|
FieldBits::new(MODULUS.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn multiplicative_generator() -> Self {
|
|
||||||
GENERATOR
|
|
||||||
}
|
|
||||||
|
|
||||||
fn root_of_unity() -> Self {
|
|
||||||
Self::ROOT_OF_UNITY
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
use core::convert::TryInto;
|
use core::convert::TryInto;
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use core::ops::{Add, Mul, Neg, Sub};
|
use core::ops::{Add, Mul, Neg, Sub};
|
||||||
use ff::FieldBits;
|
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
|
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
|
||||||
|
|
||||||
|
#[cfg(feature = "bits")]
|
||||||
|
use ff::{FieldBits, PrimeFieldBits};
|
||||||
|
|
||||||
use crate::arithmetic::{adc, mac, sbb, FieldExt, Group, SqrtTables};
|
use crate::arithmetic::{adc, mac, sbb, FieldExt, Group, SqrtTables};
|
||||||
|
|
||||||
/// This represents an element of $\mathbb{F}_q$ where
|
/// This represents an element of $\mathbb{F}_q$ where
|
||||||
|
|
@ -529,15 +531,8 @@ impl ff::Field for Fq {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_pointer_width = "64"))]
|
|
||||||
type ReprBits = [u32; 8];
|
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
|
||||||
type ReprBits = [u64; 4];
|
|
||||||
|
|
||||||
impl ff::PrimeField for Fq {
|
impl ff::PrimeField for Fq {
|
||||||
type Repr = [u8; 32];
|
type Repr = [u8; 32];
|
||||||
type ReprBits = ReprBits;
|
|
||||||
|
|
||||||
const NUM_BITS: u32 = 255;
|
const NUM_BITS: u32 = 255;
|
||||||
const CAPACITY: u32 = 254;
|
const CAPACITY: u32 = 254;
|
||||||
|
|
@ -551,6 +546,29 @@ impl ff::PrimeField for Fq {
|
||||||
self.to_bytes()
|
self.to_bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_odd(&self) -> bool {
|
||||||
|
self.to_bytes()[0] & 1 == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn multiplicative_generator() -> Self {
|
||||||
|
GENERATOR
|
||||||
|
}
|
||||||
|
|
||||||
|
fn root_of_unity() -> Self {
|
||||||
|
Self::ROOT_OF_UNITY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "bits", not(target_pointer_width = "64")))]
|
||||||
|
type ReprBits = [u32; 8];
|
||||||
|
|
||||||
|
#[cfg(all(feature = "bits", target_pointer_width = "64"))]
|
||||||
|
type ReprBits = [u64; 4];
|
||||||
|
|
||||||
|
#[cfg(feature = "bits")]
|
||||||
|
impl PrimeFieldBits for Fq {
|
||||||
|
type ReprBits = ReprBits;
|
||||||
|
|
||||||
fn to_le_bits(&self) -> FieldBits<Self::ReprBits> {
|
fn to_le_bits(&self) -> FieldBits<Self::ReprBits> {
|
||||||
let bytes = self.to_bytes();
|
let bytes = self.to_bytes();
|
||||||
|
|
||||||
|
|
@ -577,10 +595,6 @@ impl ff::PrimeField for Fq {
|
||||||
FieldBits::new(limbs)
|
FieldBits::new(limbs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_odd(&self) -> bool {
|
|
||||||
self.to_bytes()[0] & 1 == 1
|
|
||||||
}
|
|
||||||
|
|
||||||
fn char_le_bits() -> FieldBits<Self::ReprBits> {
|
fn char_le_bits() -> FieldBits<Self::ReprBits> {
|
||||||
#[cfg(not(target_pointer_width = "64"))]
|
#[cfg(not(target_pointer_width = "64"))]
|
||||||
{
|
{
|
||||||
|
|
@ -590,14 +604,6 @@ impl ff::PrimeField for Fq {
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
FieldBits::new(MODULUS.0)
|
FieldBits::new(MODULUS.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn multiplicative_generator() -> Self {
|
|
||||||
GENERATOR
|
|
||||||
}
|
|
||||||
|
|
||||||
fn root_of_unity() -> Self {
|
|
||||||
Self::ROOT_OF_UNITY
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,7 @@
|
||||||
|
|
||||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||||
#![allow(unknown_lints)]
|
#![allow(unknown_lints)]
|
||||||
#![allow(
|
#![allow(clippy::op_ref, clippy::same_item_push, clippy::upper_case_acronyms)]
|
||||||
clippy::op_ref,
|
|
||||||
clippy::same_item_push,
|
|
||||||
clippy::upper_case_acronyms,
|
|
||||||
clippy::unknown_clippy_lints
|
|
||||||
)]
|
|
||||||
#![deny(broken_intra_doc_links)]
|
#![deny(broken_intra_doc_links)]
|
||||||
#![deny(missing_debug_implementations)]
|
#![deny(missing_debug_implementations)]
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue