Skip to content

Commit 940a904

Browse files
committed
Fix: Add tmp_script in all cases
1 parent d64181f commit 940a904

File tree

3 files changed

+72
-43
lines changed

3 files changed

+72
-43
lines changed

src/chunker.rs

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
use core::panic;
22

3-
use bitcoin::{opcodes::all::{OP_ENDIF, OP_IF, OP_NOTIF}, script::Instruction, ScriptBuf};
3+
use bitcoin::{
4+
opcodes::all::{OP_ENDIF, OP_IF, OP_NOTIF},
5+
script::Instruction,
6+
ScriptBuf,
7+
};
48

59
use crate::{
610
analyzer::StackStatus,
@@ -99,9 +103,7 @@ impl Chunker {
99103
chunks.push(chunk);
100104
}
101105
for chunk in chunks.iter_mut() {
102-
// println!("chunk size: {}", chunk_size);
103106
let status = self.stack_analyze(&mut chunk.scripts);
104-
// println!("stack_analyze: {:?}", status);
105107
// ((-1 * access) as u32, (depth - access) as u32)
106108
let stack_input_size = status.deepest_stack_accessed.abs() as usize;
107109
let stack_output_size = (status.stack_changed - status.deepest_stack_accessed) as usize;
@@ -132,14 +134,13 @@ impl Chunker {
132134
return (vec![], 0);
133135
}
134136

135-
println!("[INFO] Unable to close all ifs. Undoing the added scripts to a point where num_unclosed_ifs is 0.");
136137
let mut removed_scripts = vec![];
137138
let mut removed_len = 0;
138139

139140
loop {
140141
let builder = match undo_info.call_stack.pop() {
141142
Some(builder) => builder,
142-
None => break, // the last block in the call stack
143+
None => panic!("num_unclosed_ifs != 0 but the undo_info call_stack is empty"), // the last block in the call stack
143144
};
144145
if builder.contains_flow_op() {
145146
if builder.is_script_buf() && builder.len() == 1 {
@@ -150,7 +151,7 @@ impl Chunker {
150151
break;
151152
}
152153
} else {
153-
for block in builder.blocks.iter().rev() {
154+
for block in builder.blocks {
154155
match block {
155156
Block::Call(id) => {
156157
let sub_builder = builder.script_map.get(&id).unwrap();
@@ -163,19 +164,28 @@ impl Chunker {
163164
for instruction_res in script_buf.instructions() {
164165
let instruction = instruction_res.unwrap();
165166
match instruction {
166-
Instruction::Op(OP_IF) | Instruction::Op(OP_ENDIF) | Instruction::Op(OP_NOTIF) => {
167+
Instruction::Op(OP_IF)
168+
| Instruction::Op(OP_ENDIF)
169+
| Instruction::Op(OP_NOTIF) => {
167170
undo_info.call_stack.push(Box::new(
168-
StructuredScript::new("").push_script(std::mem::take(&mut tmp_script)),
171+
StructuredScript::new("")
172+
.push_script(std::mem::take(&mut tmp_script)),
169173
));
170-
tmp_script.push_instruction_no_opt(instruction);
174+
tmp_script.push_instruction(instruction);
171175
undo_info.call_stack.push(Box::new(
172-
StructuredScript::new("").push_script(std::mem::take(&mut tmp_script)),
176+
StructuredScript::new("")
177+
.push_script(std::mem::take(&mut tmp_script)),
173178
));
174179
}
175-
_ => tmp_script.push_instruction_no_opt(instruction),
176-
180+
_ => tmp_script.push_instruction(instruction),
177181
}
178182
}
183+
if !tmp_script.is_empty() {
184+
undo_info.call_stack.push(Box::new(
185+
StructuredScript::new("")
186+
.push_script(tmp_script),
187+
));
188+
}
179189
}
180190
}
181191
}
@@ -210,9 +220,6 @@ impl Chunker {
210220
None => break, // the last block in the call stack
211221
};
212222

213-
//println!("[INFO] current chunk_len: {} -- current num_unclosed_ifs: {}", chunk_len, num_unclosed_ifs);
214-
//println!("[INFO] Popping builder with size {} and num_unclosed_ifs {} from call_stack", builder.len(), builder.num_unclosed_ifs());
215-
216223
assert!(
217224
num_unclosed_ifs + builder.num_unclosed_ifs() >= 0,
218225
"More OP_ENDIF's than OP_IF's in the script. num_unclosed_if: {:?}, builder: {:?}",
@@ -247,12 +254,16 @@ impl Chunker {
247254
} else if chunk_len + block_len > self.target_chunk_size
248255
&& (chunk_len < self.target_chunk_size - self.tolerance
249256
|| chunk_len == 0
250-
|| depth <= max_depth)
257+
|| (chunk_len < self.target_chunk_size && depth <= max_depth))
251258
{
252259
// Case 3: Current builder too large and there is no acceptable solution yet
253260
// Even if we have an acceptable solution we check if there is a better one in next depth calls
254261
// Chunk inside a call of the current builder.
255262
// Add all its calls to the call_stack.
263+
if builder.is_script_buf() {
264+
self.call_stack.push(Box::new(builder));
265+
break;
266+
}
256267
let mut contains_call = false;
257268
for block in builder.blocks.iter().rev() {
258269
match block {

tests/test.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,3 +376,22 @@ fn test_if_max_interval() {
376376
);
377377
assert_eq!(if_interval, (0, 9));
378378
}
379+
380+
#[test]
381+
fn test_is_script_buf() {
382+
let script = script! {
383+
OP_IF
384+
OP_ENDIF
385+
};
386+
assert_eq!(script.is_script_buf(), true);
387+
assert_eq!(script.contains_flow_op(), true);
388+
}
389+
390+
#[test]
391+
fn test_is_script_buf_false() {
392+
let script = script! {
393+
{ script! {OP_ADD} }
394+
};
395+
assert_eq!(script.is_script_buf(), false);
396+
assert_eq!(script.contains_flow_op(), false);
397+
}

tests/test_chunker.rs

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use bitcoin::{opcodes::all::OP_OVER, ScriptBuf};
12
use bitcoin_script::{script, Chunker};
23

34
#[test]
@@ -73,30 +74,28 @@ fn test_chunker_ifs_2() {
7374
assert_eq!(chunk_borders, vec![7, 5, 7, 5]);
7475
}
7576

76-
//#[test]
77-
//fn test_compile_to_chunks() {
78-
// let sub_script = script! {
79-
// OP_ADD
80-
// OP_ADD
81-
// };
82-
//
83-
// let script = script! {
84-
// { sub_script.clone() }
85-
// { sub_script.clone() }
86-
// { sub_script.clone() }
87-
// { sub_script.clone() }
88-
// OP_ADD
89-
// };
90-
//
91-
// println!("{:?}", script);
92-
// let (chunks, compiled_script) = script.compile_to_chunks(2, 0);
93-
// println!(
94-
// "[RESULT] compiled_script: {:?}, chunks: {:?}",
95-
// compiled_script, chunks
96-
// );
97-
// assert_eq!(chunks, vec![2, 4, 6, 8]);
98-
// assert_eq!(
99-
// compiled_script.as_bytes(),
100-
// vec![147, 147, 147, 147, 147, 147, 147, 147, 147]
101-
// );
102-
//}
77+
#[test]
78+
fn test_compile_to_chunks() {
79+
let sub_script = script! {
80+
OP_ADD
81+
OP_ADD
82+
};
83+
84+
let script = script! {
85+
{ sub_script.clone() }
86+
OP_IF
87+
OP_ROLL
88+
{ sub_script.clone() }
89+
OP_ENDIF
90+
};
91+
let (chunk_borders, chunks) = script.clone().compile_to_chunks(5, 4);
92+
println!("Chunk borders: {:?}", chunk_borders);
93+
let compiled_total_script = script.compile();
94+
let mut compiled_chunk_script = vec![];
95+
for chunk in chunks {
96+
compiled_chunk_script.extend(chunk.as_bytes());
97+
}
98+
let compiled_chunk_script = ScriptBuf::from_bytes(compiled_chunk_script);
99+
100+
assert_eq!(compiled_chunk_script, compiled_total_script);
101+
}

0 commit comments

Comments
 (0)