Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

patch 3.2.0 #4

Open
wants to merge 11 commits into
base: v3.2.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,19 @@ sha2 = { version = "0.9", default-features = false }
bincode = "1"
criterion = "0.3.0"
hex = "0.4.2"
rand = "0.7"
# rand = "0.7"
rand = "0.8"
rand_core = { version = "0.6", default-features = false, features = ["getrandom"] }

[[bench]]
name = "dalek_benchmarks"
harness = false
required-features = ["alloc", "rand_core"]

[dependencies]
rand_core = { version = "0.5", default-features = false }
cfg-if = "1"
# rand_core = { version = "0.5", default-features = false }
rand_core = { version = "0.6.4", default-features = false, optional = true }
byteorder = { version = "^1.2.3", default-features = false, features = ["i128"] }
digest = { version = "0.9", default-features = false }
subtle = { version = "^2.2.1", default-features = false }
Expand All @@ -53,6 +58,10 @@ packed_simd = { version = "0.3.4", package = "packed_simd_2", features = ["into_
zeroize = { version = "1", default-features = false }
fiat-crypto = { version = "0.1.6", optional = true}

[target.'cfg(all(target_os = "zkvm", target_vendor = "succinct"))'.dependencies]
sp1-lib = "2.0.0"
anyhow = "1.0"

[features]
nightly = ["subtle/nightly"]
default = ["std", "u64_backend"]
Expand Down
26 changes: 21 additions & 5 deletions src/backend/serial/scalar_mul/variable_base.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
#![allow(non_snake_case)]

use traits::Identity;
use scalar::Scalar;
use edwards::EdwardsPoint;
use backend::serial::curve_models::ProjectiveNielsPoint;
use window::LookupTable;
use crate::backend::serial::curve_models::ProjectiveNielsPoint;
use crate::edwards::EdwardsPoint;
use crate::scalar::Scalar;
use crate::traits::Identity;
use crate::window::LookupTable;
use prelude::Vec;
use crate::constants::ED25519_BASEPOINT_POINT;

#[cfg(not(all(target_os = "zkvm", target_vendor = "succinct")))]
/// Perform constant-time, variable-base scalar multiplication.
pub(crate) fn mul(point: &EdwardsPoint, scalar: &Scalar) -> EdwardsPoint {
// Construct a lookup table of [P,2P,3P,4P,5P,6P,7P,8P]
Expand Down Expand Up @@ -44,3 +47,16 @@ pub(crate) fn mul(point: &EdwardsPoint, scalar: &Scalar) -> EdwardsPoint {
}
tmp1.to_extended()
}

#[cfg(all(target_os = "zkvm", target_vendor = "succinct"))]
use sp1_lib::{ed25519::Ed25519AffinePoint, utils::AffinePoint};
#[cfg(all(target_os = "zkvm", target_vendor = "succinct"))]
/// Perform constant-time, variable-base scalar multiplication.
///
/// Accelerated with SP1's EdAdd syscall.
#[allow(non_snake_case)]
pub(crate) fn mul(point: &EdwardsPoint, scalar: &Scalar) -> EdwardsPoint {
let mut ed_point: Ed25519AffinePoint = (*point).into();
ed_point.mul_assign(&sp1_lib::utils::bytes_to_words_le(scalar.as_bytes())).expect("Scalar multiplication failed");
ed_point.into()
}
27 changes: 27 additions & 0 deletions src/backend/serial/scalar_mul/vartime_double_base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ use scalar::Scalar;
use edwards::EdwardsPoint;
use backend::serial::curve_models::{ProjectiveNielsPoint, ProjectivePoint};
use window::NafLookupTable5;
use prelude::Vec;
use constants::ED25519_BASEPOINT_POINT;

#[cfg(not(all(target_os = "zkvm", target_vendor = "succinct")))]
/// Compute \\(aA + bB\\) in variable time, where \\(B\\) is the Ed25519 basepoint.
pub fn mul(a: &Scalar, A: &EdwardsPoint, b: &Scalar) -> EdwardsPoint {
let a_naf = a.non_adjacent_form(5);
Expand Down Expand Up @@ -60,3 +63,27 @@ pub fn mul(a: &Scalar, A: &EdwardsPoint, b: &Scalar) -> EdwardsPoint {

r.to_extended()
}

#[cfg(all(target_os = "zkvm", target_vendor = "succinct"))]
use sp1_lib::{ed25519::Ed25519AffinePoint, utils::AffinePoint};
#[cfg(all(target_os = "zkvm", target_vendor = "succinct"))]
/// Compute \\(aA + bB\\) in variable time, where \\(B\\) is the Ed25519 basepoint.
///
/// Accelerated with SP1's EdAdd syscall.
#[allow(non_snake_case)]
pub fn mul(a: &Scalar, A: &EdwardsPoint, b: &Scalar) -> EdwardsPoint {
let A: Ed25519AffinePoint = (*A).into();

let a_bits = a.bits_le().collect::<Vec<bool>>();
let b_bits = b.bits_le().collect::<Vec<bool>>();

// Note: The base point is the identity point.
let res = AffinePoint::multi_scalar_multiplication(
&a_bits,
A,
&b_bits,
ED25519_BASEPOINT_POINT.into(),
)
.unwrap();
res.into()
}
15 changes: 15 additions & 0 deletions src/backend/serial/u64/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,21 @@ impl ConditionallySelectable for FieldElement51 {
}

impl FieldElement51 {
pub(crate) const fn from_limbs(limbs: [u64; 5]) -> FieldElement51 {
FieldElement51(limbs)
}
/// The scalar \\( 0 \\).
pub const ZERO: FieldElement51 = FieldElement51::from_limbs([0, 0, 0, 0, 0]);
/// The scalar \\( 1 \\).
pub const ONE: FieldElement51 = FieldElement51::from_limbs([1, 0, 0, 0, 0]);
/// The scalar \\( -1 \\).
pub const MINUS_ONE: FieldElement51 = FieldElement51::from_limbs([
2251799813685228,
2251799813685247,
2251799813685247,
2251799813685247,
2251799813685247,
]);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where did this come from?

Copy link
Author

@umadayal umadayal Oct 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's from patch 4.1.3. We mostly just need ONE for the patch so I can delete ZERO and MINUS_ONE

/// Invert the sign of this field element
pub fn negate(&mut self) {
// See commentary in the Sub impl
Expand Down
68 changes: 68 additions & 0 deletions src/edwards.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,49 @@ use backend::serial::scalar_mul;
))]
use backend::vector::scalar_mul;

cfg_if::cfg_if! {
if #[cfg(all(target_os = "zkvm", target_vendor = "succinct"))] {
use sp1_lib::{ed25519::Ed25519AffinePoint, utils::AffinePoint, syscall_ed_decompress};
use core::convert::TryInto;

impl From<EdwardsPoint> for Ed25519AffinePoint {
fn from(value: EdwardsPoint) -> Self {
let mut limbs = [0u32; 16];

// Ensure that the point is normalized.
assert_eq!(value.Z, FieldElement::ONE);

// Convert the x and y coordinates to little endian u32 limbs.
for (x_limb, x_bytes) in limbs[..8]
.iter_mut()
.zip(value.X.to_bytes().chunks_exact(4))
{
*x_limb = u32::from_le_bytes(x_bytes.try_into().unwrap());
}
for (y_limb, y_bytes) in limbs[8..]
.iter_mut()
.zip(value.Y.to_bytes().chunks_exact(4))
{
*y_limb = u32::from_le_bytes(y_bytes.try_into().unwrap());
}

Self { 0: limbs }
}
}

impl From<Ed25519AffinePoint> for EdwardsPoint {
fn from(value: Ed25519AffinePoint) -> Self {
let le_bytes = value.to_le_bytes();
let x = FieldElement::from_bytes(&le_bytes[..32].try_into().unwrap());
let y = FieldElement::from_bytes(&le_bytes[32..].try_into().unwrap());
let t = &x * &y;

Self { X: x, Y: y, Z: FieldElement::ONE, T: t }
}
}
}
}

// ------------------------------------------------------------------------
// Compressed points
// ------------------------------------------------------------------------
Expand Down Expand Up @@ -186,6 +229,7 @@ impl CompressedEdwardsY {
self.0
}

#[cfg(not(all(target_os = "zkvm", target_vendor = "succinct")))]
/// Attempt to decompress to an `EdwardsPoint`.
///
/// Returns `None` if the input is not the \\(y\\)-coordinate of a
Expand All @@ -207,6 +251,30 @@ impl CompressedEdwardsY {

Some(EdwardsPoint{ X, Y, Z, T: &X * &Y })
}

#[cfg(all(target_os = "zkvm", target_vendor = "succinct"))]
/// Attempt to decompress to an `EdwardsPoint`.
///
/// Returns `None` if the input is not the \\(y\\)-coordinate of a
/// curve point.
///
/// Accelerated with SP1's EdDecompress syscall.
pub fn decompress(&self) -> Option<EdwardsPoint> {
let mut XY_bytes = [0_u8; 64];
XY_bytes[32..].copy_from_slice(self.as_bytes());
unsafe {
syscall_ed_decompress(&mut XY_bytes);
}
let X = FieldElement::from_bytes(&XY_bytes[0..32].try_into().unwrap());
let Y = FieldElement::from_bytes(&XY_bytes[32..].try_into().unwrap());
let Z = FieldElement::ONE;
return Some(EdwardsPoint {
X,
Y,
Z,
T: &X * &Y,
});
}
}

// ------------------------------------------------------------------------
Expand Down
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,9 @@ extern crate zeroize;
#[cfg(any(feature = "fiat_u64_backend", feature = "fiat_u32_backend"))]
extern crate fiat_crypto;

#[cfg(all(target_os = "zkvm", target_vendor = "succinct"))]
extern crate sp1_lib;

// Used for traits related to constant-time code.
extern crate subtle;

Expand Down
10 changes: 10 additions & 0 deletions src/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,16 @@ impl Scalar {
ret
}

/// Get the bits of the scalar, in little-endian order
pub(crate) fn bits_le(&self) -> impl DoubleEndedIterator<Item = bool> + '_ {
(0..256).map(move |i| {
// As i runs from 0..256, the bottom 3 bits index the bit, while the upper bits index
// the byte. Since self.bytes is little-endian at the byte level, this iterator is
// little-endian on the bit level
((self.bytes[i >> 3] >> (i & 7)) & 1u8) == 1
})
}

Comment on lines +824 to +833

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where did this come from?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need it for let a_bits = a.bits_le().collect::<Vec>(); in vartime_double_base.rs (from 4.1.3 patch)

/// Get the bits of the scalar.
pub(crate) fn bits(&self) -> [i8; 256] {
let mut bits = [0i8; 256];
Expand Down