Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
79eccd9
Remove `Chuncker` in `README.md` (#276)
hunterfarq Apr 3, 2025
8d06b42
perf(chunk): replace Script with ScriptBuf in batch operations (#280)
manishbista28 Apr 15, 2025
f908591
Remove script_lines (#281)
Hakkush-07 Apr 17, 2025
9fe0ad2
fix print message in test of hinted check add (#283)
mukeshdroid Apr 17, 2025
1768078
chore: fix array out-of-bounds error with index validation (#278)
barajeel Apr 22, 2025
eb9f625
test: bigint limb transforms fuzz (#274)
danielntmd Apr 22, 2025
7daacb1
Fix connector_b_leaf_2_script test for proper Taproot script verifica…
VolodymyrBg Apr 28, 2025
2dd2e0e
Bump `blake3` version (and update fuzzer) (#288)
AaronFeickert Apr 29, 2025
c4843ca
WOTS data format refactor (#289)
uncomputable May 5, 2025
8d6b113
Remove unnecessary script serialization (#292)
AaronFeickert May 8, 2025
d3ee606
Add public graph accessor methods to BitVMClient (#287)
gap-editor May 8, 2025
7f7e932
Implement vulnerability fixes for bitcoin merkle tree and SPV
ozankaymak May 19, 2025
663717c
chore: cache hashing scripts (#294)
sander2 May 19, 2025
a58599b
Update risc0 to version 2.0.2, fix compilation issues
ozankaymak May 20, 2025
1660e74
Fix e2e test
ozankaymak May 20, 2025
0608a85
Cargo lock update
ozankaymak May 20, 2025
0ebe03e
Fix CI by installing risc0
ozankaymak May 21, 2025
9dda219
Fix CI: Specify rust version
ozankaymak May 21, 2025
58b809c
Updated WOTS API (#293)
uncomputable May 23, 2025
cc44324
CI: Remove risc0 installation
lucidLuckylee May 23, 2025
67e7c27
Merge branch 'chainwayxyz-fix-merkle-tree-and-spv-vuln'
lucidLuckylee May 23, 2025
b822f19
Fix/disprove script exceeds 4 m with constraints (#297)
manishbista28 Jun 3, 2025
4f04f96
Merge 'bitvm/main' into goat
KSlashh Jun 4, 2025
483f954
merge
KSlashh Jun 4, 2025
881b627
feat: more flexible disprove tx
KSlashh Jun 5, 2025
faa3b6c
chore: remove unused dep
KSlashh Jun 12, 2025
95a63b3
Merge remote-tracking branch 'goat/goat-test' into goat-v1.2
KSlashh Jun 16, 2025
a8fa866
fix: include connector_b in take_1
KSlashh Jun 20, 2025
482da42
fix: update take1 tx size
KSlashh Jul 1, 2025
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
2,192 changes: 1,499 additions & 693 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ rand_chacha = "0.3.1"
dotenv = "0.15.0"
aws-sdk-s3 = "1.40.0"
regex = "1.10.5"
blake3 = "=1.5.1"
blake3 = "1.6.1"
paste = "1.0.15"
musig2 = { version = "0.1.0", features = ["serde", "rand"] }
futures = "0.3.30"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ Below is a list of the components and their purpose.
Groth16 uses BN254 to verify proof, the script is currently around 1 GB.
Some hints are precomputed in this part, which is related to the paper "On Proving Pairings".

- [**Chunker**](bitvm/src/chunker/):
- [**Chunk**](bitvm/src/chunk/):
Splits Groth16 into chunks.
These chunks make sure two principles:

Expand Down
2 changes: 1 addition & 1 deletion bitvm/src/bigint/bits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ impl<const N_BITS: u32, const LIMB_SIZE: u32> BigIntImpl<N_BITS, LIMB_SIZE> {
}

pub fn limb_from_bytes() -> Script {
let bytes_per_limb = (LIMB_SIZE + 7) / 8;
let bytes_per_limb = LIMB_SIZE.div_ceil(8);

assert!(LIMB_SIZE > 0, "LIMB_SIZE must not be 0");
assert!(LIMB_SIZE < 33, "LIMB_SIZE must be less than 33");
Expand Down
1 change: 1 addition & 0 deletions bitvm/src/bigint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub mod mul;
pub mod std;
pub mod sub;

#[derive(Debug)]
pub struct BigIntImpl<const N_BITS: u32, const LIMB_SIZE: u32> {}

impl<const N_BITS: u32, const LIMB_SIZE: u32> BigIntImpl<N_BITS, LIMB_SIZE> {
Expand Down
84 changes: 84 additions & 0 deletions bitvm/src/bn254/fp254impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,49 @@ pub trait Fp254Impl {
(script, hints)
}

// Assumes tmul hint (1 BigInteger) at the top of stack
// and operands (a, b, c, d) at stack depths (a_depth, b_depth, c_depth, d_depth)
// Computes r = a * c + b * d (mod p)
#[allow(clippy::too_many_arguments)]
fn hinted_mul_lc2_w4(
a_depth: u32,
a: ark_bn254::Fq,
b_depth: u32,
b: ark_bn254::Fq,
c_depth: u32,
c: ark_bn254::Fq,
d_depth: u32,
d: ark_bn254::Fq,
) -> (Script, Vec<Hint>) {
assert!(a_depth > b_depth && b_depth > c_depth && c_depth > d_depth);

let mut hints = Vec::with_capacity(1);

let modulus = &Fq::modulus_as_bigint();

let x = BigInt::from_str(&a.to_string()).unwrap();
let y = BigInt::from_str(&b.to_string()).unwrap();
let z = BigInt::from_str(&c.to_string()).unwrap();
let w = BigInt::from_str(&d.to_string()).unwrap();

let q = (x * z + y * w) / modulus;

let script = script! {
for _ in 0..Self::N_LIMBS {
OP_DEPTH OP_1SUB OP_ROLL // hints
}
// { Fq::push(ark_bn254::Fq::from_str(&q.to_string()).unwrap()) }
{ Fq::roll(a_depth + 1) }
{ Fq::roll(b_depth + 2) }
{ Fq::roll(c_depth + 3) }
{ Fq::roll(d_depth + 4) }
{ Fq::tmul_lc2_w4() }
};
hints.push(Hint::BigIntegerTmulLC2(q));

(script, hints)
}

#[allow(clippy::too_many_arguments)]
fn hinted_mul_lc4(
a_depth: u32,
Expand Down Expand Up @@ -792,6 +835,47 @@ pub trait Fp254Impl {
(script, hints)
}

// Same as hinted_mul_lc2_keep_elements(), except retains operands (a, b, c, d) on stack
#[allow(clippy::too_many_arguments)]
fn hinted_mul_lc2_keep_elements_w4(
a_depth: u32,
a: ark_bn254::Fq,
b_depth: u32,
b: ark_bn254::Fq,
c_depth: u32,
c: ark_bn254::Fq,
d_depth: u32,
d: ark_bn254::Fq,
) -> (Script, Vec<Hint>) {
assert!(a_depth > b_depth && b_depth > c_depth && c_depth > d_depth);

let mut hints = Vec::with_capacity(1);

let modulus = &Fq::modulus_as_bigint();

let x = BigInt::from_str(&a.to_string()).unwrap();
let y = BigInt::from_str(&b.to_string()).unwrap();
let z = BigInt::from_str(&c.to_string()).unwrap();
let w = BigInt::from_str(&d.to_string()).unwrap();

let q = (x * z + y * w) / modulus;

let script = script! {
for _ in 0..Self::N_LIMBS {
OP_DEPTH OP_1SUB OP_ROLL // hints
}
// { Fq::push(ark_bn254::Fq::from_str(&q.to_string()).unwrap()) }
{ Fq::copy(a_depth + 1) }
{ Fq::copy(b_depth + 2) }
{ Fq::copy(c_depth + 3) }
{ Fq::copy(d_depth + 4) }
{ Fq::tmul_lc2_w4() }
};
hints.push(Hint::BigIntegerTmulLC2(q));

(script, hints)
}

// TODO: Optimize using the sqaure feature
fn hinted_square(a: ark_bn254::Fq) -> (Script, Vec<Hint>) {
let mut hints = Vec::new();
Expand Down
11 changes: 11 additions & 0 deletions bitvm/src/bn254/fq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ impl Fq {
}
}

// Wrapper over 4-bit windowed tmul that computes a linear combination of two terms
// Computes r = a * c + b * d (mod p)
// Input Stack: [hint, a, b, c, d]
// Output Stack: [r]
pub fn tmul_lc2_w4() -> Script {
script! {
{ <Fq as Fp254Mul2LCW4>::tmul() }
}
}

pub fn tmul_lc4() -> Script {
script! {
{ <Fq as Fp254Mul4LC>::tmul() }
Expand Down Expand Up @@ -408,6 +418,7 @@ macro_rules! fp_lc_mul {

fp_lc_mul!(Mul, 4, 4, [true]);
fp_lc_mul!(Mul2LC, 3, 3, [true, true]);
fp_lc_mul!(Mul2LCW4, 4, 4, [true, true]);
fp_lc_mul!(Mul4LC, 3, 3, [true, true, true, true]);

#[cfg(test)]
Expand Down
67 changes: 67 additions & 0 deletions bitvm/src/bn254/fq2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,46 @@ impl Fq2 {
(script, hints)
}

// Given Fq2 elements a and b, compute their product
// A = a0 + a1 u, B = b0 + b1 u, where $u^2$ is quadratic non-residue, for bn-254 $u^2$ = -1
// A.B = (a0.b0 + a1.b1 $u^2$) + u (a0.b1 + a1b0) = (a0.b0 - a1.b1) + u (a0.b1 + a1.b0)
// This specific version uses tmul of 4-bit window to compute each of the two terms above.
pub fn hinted_mul_w4(
mut a_depth: u32,
mut a: ark_bn254::Fq2,
mut b_depth: u32,
mut b: ark_bn254::Fq2,
) -> (Script, Vec<Hint>) {
if a_depth < b_depth {
(a_depth, b_depth) = (b_depth, a_depth);
(a, b) = (b, a);
}
assert_ne!(a_depth, b_depth);

let mut hints = Vec::with_capacity(2);

let (hinted_script1, hint1) =
Fq::hinted_mul_lc2_keep_elements_w4(3, a.c0, 2, a.c1, 1, b.c1, 0, b.c0);
let (hinted_script2, hint2) = Fq::hinted_mul_lc2_w4(3, a.c0, 2, a.c1, 1, b.c0, 0, -b.c1);

let script = script! {
{ Fq2::roll(a_depth) }
{ Fq2::roll(b_depth + 2) } // a.c0 a.c1 b.c0 b.c1
{ Fq::roll(1) } // a.c0 a.c1 b.c1 b.c0
{ hinted_script1 } // a.c0 a.c1 b.c1 b.c0 a.c0*b.c1+a.c1*b.c0
{ Fq::toaltstack() } // a.c0 a.c1 b.c1 b.c0 | a.c0*b.c1+a.c1*b.c0
{ Fq::roll(1) } // a.c0 a.c1 b.c0 b.c1 | a.c0*b.c1+a.c1*b.c0
{ Fq::neg(0) } // a.c0 a.c1 b.c0 -b.c1 | a.c0*b.c1+a.c1*b.c0
{ hinted_script2 } // a.c0*b.c0-a.c1*b.c1 | a.c0*b.c1+a.c1*b.c0
{ Fq::fromaltstack() } // a.c0*b.c0-a.c1*b.c1 a.c0*b.c1+a.c1*b.c0
};

hints.extend(hint1);
hints.extend(hint2);

(script, hints)
}

pub fn hinted_mul_by_constant(
a: ark_bn254::Fq2,
constant: &ark_bn254::Fq2,
Expand Down Expand Up @@ -496,6 +536,33 @@ mod test {
}
}

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

for _ in 0..100 {
let a = ark_bn254::Fq2::rand(&mut prng);
let b = ark_bn254::Fq2::rand(&mut prng);
let c = a.mul(&b);

let (hinted_mul, hints) = Fq2::hinted_mul_w4(2, a, 0, b);
println!("Fq2::hinted_mul_w4: {} bytes", hinted_mul.len());

let script = script! {
for hint in hints {
{ hint.push() }
}
{ Fq2::push(a) }
{ Fq2::push(b) }
{ hinted_mul.clone() }
{ Fq2::push(c) }
{ Fq2::equalverify() }
OP_TRUE
};
run(script);
}
}

#[test]
fn test_bn254_fq2_hinted_mul_by_constant() {
let mut prng: ChaCha20Rng = ChaCha20Rng::seed_from_u64(0);
Expand Down
76 changes: 36 additions & 40 deletions bitvm/src/bn254/fq6.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,58 +157,54 @@ impl Fq6 {
let (hinted_script4, hints4) = Fq2::hinted_mul(2, a.c1, 0, a.c2);
let (hinted_script5, hints5) = Fq2::hinted_square(a.c2);

let mut script = script! {};
let script_lines = [
let script = script! {
// compute s_0 = a_0 ^ 2
Fq2::copy(4),
hinted_script1,
{ Fq2::copy(4) }
{ hinted_script1 }
// compute a_0 + a_2
Fq2::roll(6),
Fq2::copy(4),
Fq2::add(2, 0),
{ Fq2::roll(6) }
{ Fq2::copy(4) }
{ Fq2::add(2, 0) }
// compute s_1 = (a_0 + a_1 + a_2) ^ 2
Fq2::copy(0),
Fq2::copy(8),
Fq2::add(2, 0),
hinted_script2,
{ Fq2::copy(0) }
{ Fq2::copy(8) }
{ Fq2::add(2, 0) }
{ hinted_script2 }
// compute s_2 = (a_0 - a_1 + a_2) ^ 2
Fq2::copy(8),
Fq2::sub(4, 0),
hinted_script3,
{ Fq2::copy(8) }
{ Fq2::sub(4, 0) }
{ hinted_script3 }
// compute s_3 = 2a_1a_2
Fq2::roll(8),
Fq2::copy(8),
hinted_script4,
Fq2::double(0),
{ Fq2::roll(8) }
{ Fq2::copy(8) }
{ hinted_script4 }
{ Fq2::double(0) }
// compute s_4 = a_2 ^ 2
Fq2::roll(8),
hinted_script5,
{ Fq2::roll(8) }
{ hinted_script5 }
// compute t_1 = (s_1 + s_2) / 2
Fq2::copy(6),
Fq2::roll(6),
Fq2::add(2, 0),
Fq2::div2(),
{ Fq2::copy(6) }
{ Fq2::roll(6) }
{ Fq2::add(2, 0) }
{ Fq2::div2() }
// at this point, we have s_0, s_1, s_3, s_4, t_1

// compute c_0 = s_0 + \beta s_3
Fq2::copy(4),
Fq6::mul_fq2_by_nonresidue(),
Fq2::copy(10),
Fq2::add(2, 0),
{ Fq2::copy(4) }
{ Fq6::mul_fq2_by_nonresidue() }
{ Fq2::copy(10) }
{ Fq2::add(2, 0) }
// compute c_1 = s_1 - s_3 - t_1 + \beta s_4
Fq2::copy(4),
Fq6::mul_fq2_by_nonresidue(),
Fq2::copy(4),
Fq2::add(10, 0),
Fq2::sub(10, 0),
Fq2::add(2, 0),
{ Fq2::copy(4) }
{ Fq6::mul_fq2_by_nonresidue() }
{ Fq2::copy(4) }
{ Fq2::add(10, 0) }
{ Fq2::sub(10, 0) }
{ Fq2::add(2, 0) }
// compute c_2 = t_1 - s_0 - s_4
Fq2::add(8, 6),
Fq2::sub(6, 0),
];
for script_line in script_lines {
script = script.push_script(script_line.compile());
}
{ Fq2::add(8, 6) }
{ Fq2::sub(6, 0) }
};

hints.extend(hints1);
hints.extend(hints2);
Expand Down
2 changes: 1 addition & 1 deletion bitvm/src/bn254/g1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -739,7 +739,7 @@ mod test {
let exec_result = execute_script(script);
assert!(exec_result.success);
println!(
"hinted_add_line: {} @ {} stack",
"hinted_check_add: {} @ {} stack",
hinted_check_add.len(),
exec_result.stats.max_nb_stack_items
);
Expand Down
2 changes: 1 addition & 1 deletion bitvm/src/bn254/g2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,7 @@ pub fn hinted_affine_add_line(
) -> (Script, Vec<Hint>) {
let mut hints = Vec::new();
let (hinted_script0, hint0) = Fq2::hinted_square(c3);
let (hinted_script1, hint1) = Fq2::hinted_mul(4, c3, 0, c3.square() - tx - qx);
let (hinted_script1, hint1) = Fq2::hinted_mul_w4(4, c3, 0, c3.square() - tx - qx);

let script = script! {
// [c3, c4, T.x, Q.x]
Expand Down
Loading
Loading