Skip to content

Commit 8d06b42

Browse files
perf(chunk): replace Script with ScriptBuf in batch operations (BitVM#280)
1 parent 79eccd9 commit 8d06b42

File tree

6 files changed

+93
-106
lines changed

6 files changed

+93
-106
lines changed

bitvm/src/chunk/api.rs

Lines changed: 40 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use crate::signatures::wots_api::{wots256, wots_hash};
1111
use crate::treepp::*;
1212
use ark_bn254::Bn254;
1313
use ark_ec::bn::Bn;
14+
use bitcoin::ScriptBuf;
1415

1516
use super::api_runtime_utils::{
1617
execute_script_from_assertion, get_pubkeys, get_signature_from_assertion,
@@ -175,7 +176,7 @@ pub mod type_conversion_utils {
175176
// Step 1
176177
// The function takes public parameters (here verifying key) and generates partial script
177178
// partial script is essentially disprove script minus the bitcommitment locking script
178-
pub fn api_generate_partial_script(vk: &ark_groth16::VerifyingKey<Bn254>) -> Vec<Script> {
179+
pub fn api_generate_partial_script(vk: &ark_groth16::VerifyingKey<Bn254>) -> Vec<ScriptBuf> {
179180
generate_partial_script(vk)
180181
}
181182

@@ -184,8 +185,8 @@ pub fn api_generate_partial_script(vk: &ark_groth16::VerifyingKey<Bn254>) -> Vec
184185
// it generates the complete disprove scripts
185186
pub fn api_generate_full_tapscripts(
186187
inpubkeys: PublicKeys,
187-
ops_scripts_per_link: &[Script],
188-
) -> Vec<Script> {
188+
ops_scripts_per_link: &[ScriptBuf],
189+
) -> Vec<ScriptBuf> {
189190
println!("api_generate_full_tapscripts; append_bitcom_locking_script_to_partial_scripts");
190191
let taps_per_link =
191192
append_bitcom_locking_script_to_partial_scripts(inpubkeys, ops_scripts_per_link.to_vec());
@@ -244,14 +245,12 @@ pub fn generate_signatures(
244245
let pubkeys = get_pubkeys(secrets);
245246

246247
println!("generate_signatures; partial_scripts_from_segments");
247-
let partial_scripts: Vec<Script> = partial_scripts_from_segments(&segments)
248-
.into_iter()
249-
.collect();
250-
let partial_scripts: [Script; NUM_TAPS] = partial_scripts.try_into().unwrap();
248+
let partial_scripts: Vec<ScriptBuf> = partial_scripts_from_segments(&segments);
249+
let partial_scripts: [ScriptBuf; NUM_TAPS] = partial_scripts.try_into().unwrap();
251250
println!("generate_signatures; append_bitcom_locking_script_to_partial_scripts");
252251
let disprove_scripts =
253252
append_bitcom_locking_script_to_partial_scripts(pubkeys, partial_scripts.to_vec());
254-
let disprove_scripts: [Script; NUM_TAPS] = disprove_scripts.try_into().unwrap();
253+
let disprove_scripts: [ScriptBuf; NUM_TAPS] = disprove_scripts.try_into().unwrap();
255254

256255
println!("generate_signatures; execute_script_from_signature");
257256
let exec_res = execute_script_from_signature(&segments, sigs.clone(), &disprove_scripts);
@@ -278,7 +277,7 @@ pub fn validate_assertions(
278277
vk: &ark_groth16::VerifyingKey<Bn254>,
279278
signed_asserts: Signatures,
280279
_inpubkeys: PublicKeys,
281-
disprove_scripts: &[Script; NUM_TAPS],
280+
disprove_scripts: &[ScriptBuf; NUM_TAPS],
282281
) -> Option<(usize, Script)> {
283282
println!("validate_assertions; get_assertions_from_signature");
284283
let asserts = get_assertions_from_signature(signed_asserts.clone());
@@ -327,14 +326,14 @@ pub fn generate_signatures_for_any_proof(
327326
let pubkeys = get_pubkeys(secrets);
328327

329328
println!("generate_signatures; partial_scripts_from_segments");
330-
let partial_scripts: Vec<Script> = partial_scripts_from_segments(&segments)
329+
let partial_scripts: Vec<ScriptBuf> = partial_scripts_from_segments(&segments)
331330
.into_iter()
332331
.collect();
333-
let partial_scripts: [Script; NUM_TAPS] = partial_scripts.try_into().unwrap();
332+
let partial_scripts: [ScriptBuf; NUM_TAPS] = partial_scripts.try_into().unwrap();
334333
println!("generate_signatures; append_bitcom_locking_script_to_partial_scripts");
335334
let disprove_scripts =
336335
append_bitcom_locking_script_to_partial_scripts(pubkeys, partial_scripts.to_vec());
337-
let disprove_scripts: [Script; NUM_TAPS] = disprove_scripts.try_into().unwrap();
336+
let disprove_scripts: [ScriptBuf; NUM_TAPS] = disprove_scripts.try_into().unwrap();
338337

339338
println!("generate_signatures; execute_script_from_signature");
340339
let exec_res = execute_script_from_signature(&segments, sigs.clone(), &disprove_scripts);
@@ -359,11 +358,10 @@ mod test {
359358
use crate::chunk::wrap_hasher::BLAKE3_HASH_LENGTH;
360359
use crate::chunk::wrap_wots::{byte_array_to_wots256_sig, byte_array_to_wots_hash_sig};
361360
use crate::signatures::wots_api::{wots256, wots_hash};
362-
use crate::treepp::Script;
363361
use ark_bn254::Bn254;
364362
use ark_ff::UniformRand;
365363
use ark_serialize::CanonicalDeserialize;
366-
use bitcoin_script::script;
364+
use bitcoin::ScriptBuf;
367365
use rand::{Rng, SeedableRng};
368366
use rand_chacha::ChaCha20Rng;
369367
use test_utils::{
@@ -393,7 +391,6 @@ mod test {
393391
use crate::chunk::api::NUM_PUBS;
394392
use crate::chunk::api::NUM_U256;
395393
use crate::chunk::wrap_hasher::BLAKE3_HASH_LENGTH;
396-
use crate::treepp::*;
397394
use bitcoin::ScriptBuf;
398395
use std::collections::HashMap;
399396
use std::error::Error;
@@ -424,40 +421,41 @@ mod test {
424421
Ok(map)
425422
}
426423

427-
pub fn write_scripts_to_file(sig_cache: HashMap<u32, Vec<Script>>, file: &str) {
424+
pub fn write_scripts_to_file(sig_cache: HashMap<u32, Vec<ScriptBuf>>, file: &str) {
428425
let mut buf: HashMap<u32, Vec<Vec<u8>>> = HashMap::new();
429426
for (k, v) in sig_cache {
430-
let vs = v.into_iter().map(|x| x.compile().to_bytes()).collect();
427+
let vs = v.into_iter().map(|x| x.to_bytes()).collect();
431428
buf.insert(k, vs);
432429
}
433430
write_map_to_file(&buf, file).unwrap();
434431
}
435432

436-
pub fn write_scripts_to_separate_files(sig_cache: HashMap<u32, Vec<Script>>, file: &str) {
433+
pub fn write_scripts_to_separate_files(
434+
sig_cache: HashMap<u32, Vec<ScriptBuf>>,
435+
file: &str,
436+
) {
437437
let mut buf: HashMap<u32, Vec<Vec<u8>>> = HashMap::new();
438438
std::fs::create_dir_all("bridge_data/chunker_data")
439439
.expect("Failed to create directory structure");
440440

441441
for (k, v) in sig_cache {
442442
let file = format!("bridge_data/chunker_data/{file}_{k}.json");
443-
let vs = v.into_iter().map(|x| x.compile().to_bytes()).collect();
443+
let vs = v.into_iter().map(|x| x.to_bytes()).collect();
444444
buf.insert(k, vs);
445445
write_map_to_file(&buf, &file).unwrap();
446446
buf.clear();
447447
}
448448
}
449449

450-
pub fn read_scripts_from_file(file: &str) -> HashMap<u32, Vec<Script>> {
451-
let mut scr: HashMap<u32, Vec<Script>> = HashMap::new();
450+
pub fn read_scripts_from_file(file: &str) -> HashMap<u32, Vec<ScriptBuf>> {
451+
let mut scr: HashMap<u32, Vec<ScriptBuf>> = HashMap::new();
452452
let f = read_map_from_file(file).unwrap();
453453
for (k, v) in f {
454-
let vs: Vec<Script> = v
454+
let vs: Vec<ScriptBuf> = v
455455
.into_iter()
456456
.map(|x| {
457-
let sc = script! {};
458457
let bf = ScriptBuf::from_bytes(x);
459-
460-
sc.push_script(bf)
458+
bf
461459
})
462460
.collect();
463461
scr.insert(k, vs);
@@ -603,17 +601,17 @@ mod test {
603601
let mut proof_asserts = get_assertions_from_signature(proof_sigs);
604602
corrupt_at_random_index(&mut proof_asserts);
605603
let corrupt_signed_asserts = get_signature_from_assertion(proof_asserts, secrets);
606-
let disprove_scripts: [Script; NUM_TAPS] = disprove_scripts.try_into().unwrap();
604+
let disprove_scripts: [ScriptBuf; NUM_TAPS] = disprove_scripts.try_into().unwrap();
607605

608606
let invalid_tap =
609607
validate_assertions(&vk, corrupt_signed_asserts, pubkeys, &disprove_scripts);
610608
assert!(invalid_tap.is_some());
611609
let (index, hint_script) = invalid_tap.unwrap();
612610
println!("STEP 4 EXECUTING DISPROVE SCRIPT at index {}", index);
613-
let scr = script! {
614-
{hint_script.clone()}
615-
{disprove_scripts[index].clone()}
616-
};
611+
612+
let scr = hint_script
613+
.clone()
614+
.push_script(disprove_scripts[index].clone());
617615
let res = execute_script(scr);
618616
if res.final_stack.len() > 1 {
619617
println!("Stack ");
@@ -749,10 +747,9 @@ mod test {
749747
assert!(invalid_tap.is_some());
750748
let (index, hint_script) = invalid_tap.unwrap();
751749
println!("STEP 4 EXECUTING DISPROVE SCRIPT at index {}", index);
752-
let scr = script! {
753-
{hint_script.clone()}
754-
{disprove_scripts[index].clone()}
755-
};
750+
let scr = hint_script
751+
.clone()
752+
.push_script(disprove_scripts[index].clone());
756753
let res = execute_script(scr);
757754
if res.final_stack.len() > 1 {
758755
println!("Stack ");
@@ -916,11 +913,11 @@ mod test {
916913
}
917914
println!("done");
918915

919-
let ops_scripts: [Script; NUM_TAPS] = op_scripts.try_into().unwrap(); //compile_verifier(mock_vk);
916+
let ops_scripts: [ScriptBuf; NUM_TAPS] = op_scripts.try_into().unwrap(); //compile_verifier(mock_vk);
920917

921918
let tapscripts = api_generate_full_tapscripts(mock_pubs, &ops_scripts);
922919
assert_eq!(tapscripts.len(), NUM_TAPS);
923-
let tapscripts: [Script; NUM_TAPS] = tapscripts.try_into().unwrap();
920+
let tapscripts: [ScriptBuf; NUM_TAPS] = tapscripts.try_into().unwrap();
924921
println!(
925922
"tapscript.lens: {:?}",
926923
tapscripts.clone().map(|script| script.len())
@@ -1167,7 +1164,7 @@ mod test {
11671164
op_scripts.push(tap_node);
11681165
}
11691166
println!("done");
1170-
let ops_scripts: [Script; NUM_TAPS] = op_scripts.try_into().unwrap();
1167+
let ops_scripts: [ScriptBuf; NUM_TAPS] = op_scripts.try_into().unwrap();
11711168

11721169
let secrets = (0..NUM_PUBS + NUM_U256 + NUM_HASH)
11731170
.map(|idx| format!("{MOCK_SECRET}{:04x}", idx))
@@ -1266,7 +1263,7 @@ mod test {
12661263
op_scripts.push(tap_node);
12671264
}
12681265
println!("done");
1269-
let ops_scripts: [Script; NUM_TAPS] = op_scripts.try_into().unwrap();
1266+
let ops_scripts: [ScriptBuf; NUM_TAPS] = op_scripts.try_into().unwrap();
12701267

12711268
let secrets = (0..NUM_PUBS + NUM_U256 + NUM_HASH)
12721269
.map(|idx| format!("{MOCK_SECRET}{:04x}", idx))
@@ -1322,17 +1319,16 @@ mod test {
13221319
if fault.is_some() {
13231320
let (index, hint_script) = fault.unwrap();
13241321
println!("taproot index {:?}", index);
1325-
let scr = script! {
1326-
{hint_script.clone()}
1327-
{verifier_scripts[index].clone()}
1328-
};
1322+
let scr = hint_script
1323+
.clone()
1324+
.push_script(verifier_scripts[index].clone());
13291325
let res = execute_script(scr);
13301326
for i in 0..res.final_stack.len() {
13311327
println!("{i:} {:?}", res.final_stack.get(i));
13321328
}
1333-
let mut disprove_map: HashMap<u32, Vec<Script>> = HashMap::new();
1329+
let mut disprove_map: HashMap<u32, Vec<ScriptBuf>> = HashMap::new();
13341330
let disprove_f = &format!("bridge_data/chunker_data/disprove_{index}.json");
1335-
disprove_map.insert(index as u32, vec![hint_script]);
1331+
disprove_map.insert(index as u32, vec![hint_script.compile()]);
13361332
write_scripts_to_file(disprove_map, disprove_f);
13371333
assert!(res.success);
13381334
}

bitvm/src/chunk/api_compiletime_utils.rs

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use ark_bn254::Bn254;
1212
use ark_ec::bn::BnConfig;
1313
use ark_ec::{AffineRepr, CurveGroup};
1414
use ark_ff::Field;
15+
use bitcoin::ScriptBuf;
1516
use bitcoin_script::script;
1617
use num_bigint::BigUint;
1718
use std::hash::{DefaultHasher, Hash, Hasher};
@@ -38,9 +39,7 @@ pub(crate) struct Vkey {
3839
pub(crate) vky0: ark_bn254::G1Affine,
3940
}
4041

41-
pub(crate) fn generate_partial_script(
42-
vk: &ark_groth16::VerifyingKey<Bn254>,
43-
) -> Vec<bitcoin_script::Script> {
42+
pub(crate) fn generate_partial_script(vk: &ark_groth16::VerifyingKey<Bn254>) -> Vec<ScriptBuf> {
4443
println!("generate_partial_script");
4544
assert!(vk.gamma_abc_g1.len() == NUM_PUBS + 1);
4645

@@ -68,10 +67,9 @@ pub(crate) fn generate_partial_script(
6867
println!("generate_partial_script; generate_segments_using_mock_proof");
6968
let segments = generate_segments_using_mock_proof(vk, false);
7069
println!("generate_partial_script; partial_scripts_from_segments");
71-
let op_scripts: Vec<Script> = partial_scripts_from_segments(&segments)
72-
.into_iter()
73-
.collect();
70+
let op_scripts: Vec<ScriptBuf> = partial_scripts_from_segments(&segments);
7471
assert_eq!(op_scripts.len(), NUM_TAPS);
72+
7573
op_scripts
7674
}
7775

@@ -80,8 +78,8 @@ pub(crate) fn generate_partial_script(
8078
// we do not need values at the input or outputs of tapscript
8179
pub(crate) fn append_bitcom_locking_script_to_partial_scripts(
8280
inpubkeys: PublicKeys,
83-
ops_scripts: Vec<bitcoin_script::Script>,
84-
) -> Vec<bitcoin_script::Script> {
81+
ops_scripts: Vec<ScriptBuf>,
82+
) -> Vec<ScriptBuf> {
8583
println!("append_bitcom_locking_script_to_partial_scripts; generage_segments_using_mock_vk_and_mock_proof");
8684
// mock_vk can be used because generating locking_script doesn't depend upon values or partial scripts; it's only a function of pubkey and ordering of input/outputs
8785
let mock_segments = generate_segments_using_mock_vk_and_mock_proof();
@@ -93,17 +91,14 @@ pub(crate) fn append_bitcom_locking_script_to_partial_scripts(
9391
.filter(|f| !f.is_empty())
9492
.collect();
9593
assert_eq!(ops_scripts.len(), bitcom_scripts.len());
96-
let res: Vec<treepp::Script> = ops_scripts
94+
let res: Vec<ScriptBuf> = ops_scripts
9795
.into_iter()
9896
.zip(bitcom_scripts)
9997
.map(|(op_scr, bit_scr)| {
100-
script! {
101-
{bit_scr}
102-
{op_scr}
103-
}
98+
let joint_scr = bit_scr.push_script(op_scr);
99+
joint_scr.compile()
104100
})
105101
.collect();
106-
107102
res
108103
}
109104

@@ -195,7 +190,7 @@ pub(crate) fn generate_segments_using_mock_vk_and_mock_proof() -> Vec<Segment> {
195190
generate_segments_using_mock_proof(mock_vk, true)
196191
}
197192

198-
pub(crate) fn partial_scripts_from_segments(segments: &[Segment]) -> Vec<treepp::Script> {
193+
pub(crate) fn partial_scripts_from_segments(segments: &[Segment]) -> Vec<ScriptBuf> {
199194
fn serialize_element_types(elems: &[ElementType]) -> String {
200195
// 1. Convert each variant to its string representation.
201196
let joined = elems
@@ -213,7 +208,7 @@ pub(crate) fn partial_scripts_from_segments(segments: &[Segment]) -> Vec<treepp:
213208
format!("{}|{}", joined, unique_hash)
214209
}
215210

216-
let mut op_scripts: Vec<treepp::Script> = vec![];
211+
let mut op_scripts: Vec<ScriptBuf> = vec![];
217212

218213
// cache hashing script as it is repititive
219214
let mut hashing_script_cache: HashMap<String, Script> = HashMap::new();
@@ -259,10 +254,13 @@ pub(crate) fn partial_scripts_from_segments(segments: &[Segment]) -> Vec<treepp:
259254
let elem_types_str = serialize_element_types(&elem_types_to_hash);
260255
let hash_scr = hashing_script_cache.get(&elem_types_str).unwrap();
261256

262-
op_scripts.push(script! {
263-
{op_scr}
264-
{hash_scr.clone()}
265-
});
257+
op_scripts.push(
258+
script! {
259+
{script!().push_script(op_scr)}
260+
{hash_scr.clone()}
261+
}
262+
.compile(),
263+
);
266264
}
267265
}
268266
op_scripts

0 commit comments

Comments
 (0)