Skip to content

Commit 61469aa

Browse files
committed
Finish opcode optimality checks
1 parent 69c118a commit 61469aa

File tree

3 files changed

+52
-276
lines changed

3 files changed

+52
-276
lines changed

src/lib.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919
//! ```rust
2020
//! #![feature(proc_macro_hygiene)]
2121
//!
22-
//! use bitcoin_script::{script, define_pushable};
22+
//! # use bitcoin_script::{script, define_pushable};
2323
//!
24-
//! define_pushable!();
24+
//! # define_pushable!();
2525
//! # let digest = 0;
2626
//! # let seller_pubkey_hash = 0;
2727
//! # let buyer_pubkey_hash = 0;
@@ -59,7 +59,8 @@
5959
//!
6060
//! ```rust
6161
//! # #![feature(proc_macro_hygiene)]
62-
//! # use bitcoin_script::script;
62+
//! # use bitcoin_script::{script, define_pushable};
63+
//! # define_pushable!();
6364
//! let script = script!(OP_CHECKSIG OP_VERIFY);
6465
//! ```
6566
//!
@@ -73,7 +74,8 @@
7374
//!
7475
//! ```rust
7576
//! # #![feature(proc_macro_hygiene)]
76-
//! # use bitcoin_script::script;
77+
//! # use bitcoin_script::{script, define_pushable};
78+
//! # define_pushable!();
7779
//! let script = script!(123 -456 999999);
7880
//! ```
7981
//!
@@ -83,7 +85,8 @@
8385
//!
8486
//! ```rust
8587
//! # #![feature(proc_macro_hygiene)]
86-
//! # use bitcoin_script::script;
88+
//! # use bitcoin_script::{script, define_pushable};
89+
//! # define_pushable!();
8790
//! let script = script!(
8891
//! 0x0102030405060708090a0b0c0d0e0f OP_HASH160
8992
//! );
@@ -105,7 +108,7 @@
105108
//! ```rust
106109
//! # #![feature(proc_macro_hygiene)]
107110
//! # use bitcoin_script::{script, define_pushable};
108-
//! define_pushable!();
111+
//! # define_pushable!();
109112
//! let bytes = vec![1, 2, 3];
110113
//!
111114
//! let script = script! {
@@ -140,7 +143,7 @@ pub fn define_pushable(_: TokenStream) -> TokenStream {
140143

141144
use bitcoin::blockdata::opcodes::{all::*, Opcode};
142145
use bitcoin::blockdata::script::Builder as BitcoinBuilder;
143-
use bitcoin::blockdata::script::{PushBytesBuf, Script};
146+
use bitcoin::blockdata::script::{PushBytesBuf, PushBytes, Script};
144147
use std::convert::TryFrom;
145148

146149
pub struct Builder(pub BitcoinBuilder);
@@ -210,8 +213,8 @@ pub fn define_pushable(_: TokenStream) -> TokenStream {
210213
self
211214
}
212215

213-
pub fn push_slice(mut self, slice: PushBytesBuf) -> Builder {
214-
self.0 = self.0.push_slice(slice);
216+
pub fn push_slice<T: AsRef<PushBytes>>(mut self, data: T) -> Builder {
217+
self.0 = self.0.push_slice(data);
215218
self
216219
}
217220

src/parse.rs

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ where
143143
{
144144
let mut escape = quote! {
145145
let mut script_var = vec![];
146+
let mut last_opcode = None;
146147
};
147148
escape.extend(std::iter::once(token.clone()));
148149

@@ -155,16 +156,41 @@ where
155156
let next_script = script !{
156157
#inner_block
157158
};
158-
if script_var.len() > 0 {
159-
if next_script.as_bytes().len() == 0 {
160-
eprintln!("Script can be optimized: Inner block of a for loop iteration is empty.");
161-
} else {
162-
// TODO this could be a data push
163-
let previous_opcode = ::bitcoin::opcodes::Opcode::from(script_var[script_var.len() - 1]);
164-
let opcode = ::bitcoin::opcodes::Opcode::from(next_script.as_bytes()[0]);
165-
pushable::check_optimality(previous_opcode, opcode);
159+
if next_script.as_bytes().len() > 0 {
160+
if let Some(previous_opcode) = last_opcode {
161+
// Check optimality for the next_script first opcode and the previous
162+
// scripts last opcode.
163+
match next_script.instructions_minimal().next() {
164+
Some(instr_result) => match instr_result {
165+
Ok(instr) => match instr {
166+
bitcoin::script::Instruction::PushBytes(push_bytes) => {
167+
if push_bytes.as_bytes() == [] {
168+
pushable::check_optimality(previous_opcode, ::bitcoin::opcodes::all::OP_PUSHBYTES_0)
169+
}
170+
},
171+
bitcoin::script::Instruction::Op(opcode) => pushable::check_optimality(previous_opcode, opcode),
172+
},
173+
Err(_) => eprintln!("Script includes non-minimal pushes."),
174+
},
175+
None => eprintln!("Script can be optimized: Inner block of a for loop iteration is empty."),
176+
};
166177
}
167-
}
178+
// Store last instruction of next_script as Opcode in last_opcode.
179+
match next_script.instructions_minimal().last() {
180+
Some(instr_result) => match instr_result {
181+
Ok(instr) => match instr {
182+
bitcoin::script::Instruction::PushBytes(push_bytes) => {
183+
if push_bytes.as_bytes() == [] {
184+
last_opcode = Some(::bitcoin::opcodes::all::OP_PUSHBYTES_0);
185+
}
186+
},
187+
bitcoin::script::Instruction::Op(new_last_opcode) => last_opcode = Some(new_last_opcode),
188+
},
189+
Err(_) => eprintln!("Script includes non-minimal pushes."),
190+
},
191+
None => (),
192+
};
193+
};
168194
script_var.extend_from_slice(next_script.as_bytes());
169195
}
170196
bitcoin::script::ScriptBuf::from(script_var)

0 commit comments

Comments
 (0)