Skip to content

Commit

Permalink
Merge pull request #22 from Bitcoin-Wildlife-Sanctuary/constraints-fe…
Browse files Browse the repository at this point in the history
…ature-continued

added coset_vanishing() to constraints and add() to circlepointsecure
  • Loading branch information
victorkstarkware authored May 30, 2024
2 parents 77ece54 + 79a6a21 commit a47cc4b
Show file tree
Hide file tree
Showing 3 changed files with 272 additions and 65 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ This repository includes Bitcoin script implementations of various cryptographic
- **CirclePoint over QM31**
* implementation of double of a circle point over QM31.
* implementation of drawing a random point on the circle over QM31, which is useful for OODS.
* implementation of addition of a circle point over QM31.
- **Constraints on the circle curve over QM31**
* implementation of `coset_vanishing()` and `pair_vanishing()`.
- **Fiat-Shamir Transcript**
* aka "channel", which is the name used in Starkware's [stwo](https://github.com/starkware-libs/stwo) library.
* absorbing commitments and QM31 elements through `OP_CAT + OP_SHA256`.
Expand Down Expand Up @@ -51,6 +54,15 @@ These performance numbers are obtained from `cargo test -- --nocapture` over com
- **CirclePoint over QM31**
* CirclePointSecure.double_x() = 13505 bytes
* CirclePointSecure.get_random_point() = 40546 bytes
* CirclePointSecure.add() = 40542 bytes
* CirclePointSecure.add_x_only() = 26791 bytes
- **Constraints on the circle curve over QM31**
* Constraints.pair_vanishing() = 26932 bytes
* Constraints.coset_vanishing(log_size=5) = 80827 bytes
* Constraints.coset_vanishing(log_size=6) = 94332 bytes
* Constraints.coset_vanishing(log_size=7) = 107837 bytes
* Constraints.coset_vanishing(log_size=8) = 121342 bytes
* Constraints.coset_vanishing(log_size=9) = 134847 bytes
- **Fiat-Shamir Transcript**
* Channel.absorb_commitment = 2 bytes
* Channel.absorb_qm31() = 9 bytes
Expand Down
132 changes: 129 additions & 3 deletions src/circle_secure/bitcoin_script.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use crate::treepp::*;
use num_traits::One;
use rust_bitcoin_m31::{
m31_add_n31, m31_sub, push_m31_one, push_n31_one, push_qm31_one, qm31_double, qm31_dup,
qm31_equalverify, qm31_from_bottom, qm31_mul, qm31_neg, qm31_roll, qm31_rot, qm31_square,
qm31_sub, qm31_swap,
m31_add_n31, m31_sub, push_m31_one, push_n31_one, push_qm31_one, qm31_add, qm31_copy,
qm31_double, qm31_dup, qm31_equalverify, qm31_from_bottom, qm31_fromaltstack, qm31_mul,
qm31_neg, qm31_roll, qm31_rot, qm31_square, qm31_sub, qm31_swap, qm31_toaltstack,
};
use std::ops::{Add, Mul, Neg};
use stwo_prover::core::fields::qm31::QM31;
Expand All @@ -15,6 +15,57 @@ use crate::channel::ChannelGadget;
pub struct CirclePointSecureGadget;

impl CirclePointSecureGadget {
/// Only computes the x component of addition between points
pub fn add_x_only() -> Script {
script! {
{ qm31_roll(3) }
{ qm31_roll(2) }
qm31_mul
{ qm31_roll(1) }
{ qm31_roll(2) }
qm31_mul
qm31_sub
}
}

/// Add two points.
pub fn add() -> Script {
script! {
{ qm31_copy(3) }
{ qm31_copy(2) }
qm31_mul
{ qm31_copy(3) }
{ qm31_copy(2) }
qm31_mul
{ qm31_roll(5)}
{ qm31_roll(5)}
qm31_add
{ qm31_roll(4)}
{ qm31_roll(4)}
qm31_add
qm31_mul
qm31_toaltstack
{ qm31_copy(1) }
{ qm31_copy(1) }
qm31_add
qm31_fromaltstack
qm31_swap
qm31_sub
qm31_toaltstack
qm31_sub
qm31_fromaltstack
}
}

/// Fail the execution if the two points are not equal.
pub fn equalverify() -> Script {
script! {
{ qm31_roll(2) }
qm31_equalverify
qm31_equalverify
}
}

/// Double a point.
/// Rationale: cos(2*theta) = 2*cos(theta)^2-1
///
Expand Down Expand Up @@ -106,6 +157,7 @@ impl CirclePointSecureGadget {
mod test {
use num_traits::One;
use std::ops::{Add, Mul, Neg};
use stwo_prover::core::circle::CirclePoint;

use crate::treepp::*;
use rand::{Rng, RngCore, SeedableRng};
Expand All @@ -120,6 +172,80 @@ mod test {
circle_secure::bitcoin_script::CirclePointSecureGadget,
};

#[test]
fn test_add() {
let mut prng = ChaCha20Rng::seed_from_u64(0);

let add_script = CirclePointSecureGadget::add();
println!("CirclePointSecure.add() = {} bytes", add_script.len());

let add_x_script = CirclePointSecureGadget::add_x_only();
println!(
"CirclePointSecure.add_x_only() = {} bytes",
add_x_script.len()
);

for _ in 0..100 {
let a = CirclePoint {
x: QM31::from_m31(
M31::reduce(prng.next_u64()),
M31::reduce(prng.next_u64()),
M31::reduce(prng.next_u64()),
M31::reduce(prng.next_u64()),
),
y: QM31::from_m31(
M31::reduce(prng.next_u64()),
M31::reduce(prng.next_u64()),
M31::reduce(prng.next_u64()),
M31::reduce(prng.next_u64()),
),
};

let b = CirclePoint {
x: QM31::from_m31(
M31::reduce(prng.next_u64()),
M31::reduce(prng.next_u64()),
M31::reduce(prng.next_u64()),
M31::reduce(prng.next_u64()),
),
y: QM31::from_m31(
M31::reduce(prng.next_u64()),
M31::reduce(prng.next_u64()),
M31::reduce(prng.next_u64()),
M31::reduce(prng.next_u64()),
),
};
let c = a + b;

let script = script! {
{ a.x }
{ a.y }
{ b.x }
{ b.y }
{ add_script.clone() }
{ c.x }
{ c.y }
{ CirclePointSecureGadget::equalverify() }
OP_TRUE
};
let exec_result = execute_script(script);
assert!(exec_result.success);

let script = script! {
{ a.x }
{ a.y }
{ b.x }
{ b.y }
{ add_x_script.clone() }
{ c.x }
qm31_equalverify
OP_TRUE
};
let exec_result = execute_script(script);
assert!(exec_result.success);
}
}

#[test]
fn test_double_x() {
let double_x_script = CirclePointSecureGadget::double_x();
Expand Down
Loading

0 comments on commit a47cc4b

Please sign in to comment.