elements_miniscript/miniscript/
lex.rs1use std::fmt;
10
11use elements::{opcodes, script};
12
13use super::Error;
14use crate::util::{build_scriptint, slice_to_u32_le};
15#[derive(Debug, Clone, PartialEq, Eq)]
17#[allow(missing_docs)]
18pub enum Token<'s> {
19 BoolAnd,
20 BoolOr,
21 Add,
22 Sub,
23 Equal,
24 NumEqual,
25 CheckSig,
26 CheckSigFromStack,
27 CheckSigAdd,
28 CheckSigFromStackVerify,
29 CheckMultiSig,
30 CheckSequenceVerify,
31 CheckLockTimeVerify,
32 FromAltStack,
33 ToAltStack,
34 Left,
35 Cat,
36 CodeSep,
37 Over,
38 Pick,
39 Depth,
40 Drop,
41 Dup,
42 If,
43 IfDup,
44 NotIf,
45 Else,
46 EndIf,
47 ZeroNotEqual,
48 Size,
49 Swap,
50 Verify,
51 Ripemd160,
52 Hash160,
53 Sha256,
54 Hash256,
55 Num(u32),
56 Hash20(&'s [u8]),
57 Bytes8(&'s [u8]),
58 Bytes32(&'s [u8]),
59 Bytes33(&'s [u8]),
60 Bytes65(&'s [u8]),
61 Push(Vec<u8>), PickPush4(u32), PickPush32([u8; 32]), PickPush(Vec<u8>), InpValue,
66 OutValue,
67 InpIssue,
68 Leq64,
69 Le64,
70 Geq64,
71 Ge64,
72 Neg64,
73 Div64,
74 Mul64,
75 Sub64,
76 Add64,
77 Nip,
78 And,
79 Or,
80 Xor,
81 Invert,
82 CurrInp,
83 InpAsset,
84 OutAsset,
85 OutSpk,
86 InpSpk,
87 NumNeg1,
88 ScriptNumToLe64,
89 Le64ToScriptNum,
90 Dup2,
91}
92
93impl<'s> fmt::Display for Token<'s> {
94 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95 match self {
96 Token::Num(n) => write!(f, "#{}", n),
97 Token::Hash20(b) | Token::Bytes33(b) | Token::Bytes32(b) | Token::Bytes65(b) => {
98 for ch in &b[..] {
99 write!(f, "{:02x}", *ch)?;
100 }
101 Ok(())
102 }
103 x => write!(f, "{:?}", x),
104 }
105 }
106}
107
108#[derive(Debug, Clone)]
109pub struct TokenIter<'s>(Vec<Token<'s>>);
115
116impl<'s> TokenIter<'s> {
117 pub fn new(v: Vec<Token<'s>>) -> TokenIter<'s> {
119 TokenIter(v)
120 }
121
122 pub fn peek(&self) -> Option<&'s Token<'_>> {
124 self.0.last()
125 }
126
127 pub fn peek_slice(&self, n: usize) -> Option<&[Token<'_>]> {
129 if n <= self.len() {
130 Some(self.0[self.len() - n..].as_ref())
131 } else {
132 None
133 }
134 }
135
136 pub fn advance(&mut self, n: usize) -> Option<()> {
139 if n <= self.len() {
140 for _ in 0..n {
141 self.next();
142 }
143 Some(())
144 } else {
145 None
146 }
147 }
148
149 pub fn un_next(&mut self, tok: Token<'s>) {
152 self.0.push(tok)
153 }
154
155 pub fn len(&self) -> usize {
157 self.0.len()
158 }
159
160 pub fn is_empty(&self) -> bool {
162 self.0.is_empty()
163 }
164
165 pub fn as_inner_mut(&mut self) -> &mut Vec<Token<'s>> {
167 &mut self.0
168 }
169}
170
171impl<'s> Iterator for TokenIter<'s> {
172 type Item = Token<'s>;
173
174 fn next(&mut self) -> Option<Token<'s>> {
175 self.0.pop()
176 }
177}
178
179pub fn lex(script: &script::Script) -> Result<Vec<Token<'_>>, Error> {
181 let mut ret = Vec::with_capacity(script.len());
182
183 fn process_candidate_push(ret: &mut [Token<'_>]) {
184 let ret_len = ret.len();
185
186 if ret_len < 2 || ret[ret_len - 1] != Token::Swap {
187 return;
188 }
189 let token = match &ret[ret_len - 2] {
190 Token::Hash20(x) => Token::Push(x.to_vec()),
191 Token::Bytes32(x) | Token::Bytes33(x) | Token::Bytes65(x) => Token::Push(x.to_vec()),
192 Token::Num(k) => Token::Push(build_scriptint(i64::from(*k))),
193 _x => return, };
195 ret[ret_len - 2] = token;
196 }
197
198 for ins in script.instructions_minimal() {
199 match ins.map_err(Error::Script)? {
200 script::Instruction::Op(opcodes::all::OP_BOOLAND) => {
201 ret.push(Token::BoolAnd);
202 }
203 script::Instruction::Op(opcodes::all::OP_BOOLOR) => {
204 ret.push(Token::BoolOr);
205 }
206 script::Instruction::Op(opcodes::all::OP_EQUAL) => {
207 ret.push(Token::Equal);
208 }
209 script::Instruction::Op(opcodes::all::OP_EQUALVERIFY) => {
210 ret.push(Token::Equal);
211 ret.push(Token::Verify);
212 }
213 script::Instruction::Op(opcodes::all::OP_NUMEQUAL) => {
214 ret.push(Token::NumEqual);
215 }
216 script::Instruction::Op(opcodes::all::OP_NUMEQUALVERIFY) => {
217 ret.push(Token::NumEqual);
218 ret.push(Token::Verify);
219 }
220 script::Instruction::Op(opcodes::all::OP_CHECKSIG) => {
221 ret.push(Token::CheckSig);
222 }
223 script::Instruction::Op(opcodes::all::OP_CHECKSIGFROMSTACK) => {
224 ret.push(Token::CheckSigFromStack);
225 }
226 script::Instruction::Op(opcodes::all::OP_CHECKSIGFROMSTACKVERIFY) => {
227 ret.push(Token::CheckSigFromStackVerify);
228 }
229 script::Instruction::Op(opcodes::all::OP_CHECKSIGVERIFY) => {
230 ret.push(Token::CheckSig);
231 ret.push(Token::Verify);
232 }
233 script::Instruction::Op(opcodes::all::OP_CHECKSIGADD) => {
234 ret.push(Token::CheckSigAdd);
235 }
236 script::Instruction::Op(opcodes::all::OP_INSPECTINPUTVALUE) => {
237 ret.push(Token::InpValue);
238 }
239 script::Instruction::Op(opcodes::all::OP_INSPECTOUTPUTVALUE) => {
240 ret.push(Token::OutValue);
241 }
242 script::Instruction::Op(opcodes::all::OP_INSPECTINPUTASSET) => {
243 ret.push(Token::InpAsset);
244 }
245 script::Instruction::Op(opcodes::all::OP_INSPECTOUTPUTASSET) => {
246 ret.push(Token::OutAsset);
247 }
248 script::Instruction::Op(opcodes::all::OP_INSPECTINPUTSCRIPTPUBKEY) => {
249 ret.push(Token::InpSpk);
250 }
251 script::Instruction::Op(opcodes::all::OP_INSPECTOUTPUTSCRIPTPUBKEY) => {
252 ret.push(Token::OutSpk);
253 }
254 script::Instruction::Op(opcodes::all::OP_INSPECTINPUTISSUANCE) => {
255 ret.push(Token::InpIssue);
256 }
257 script::Instruction::Op(opcodes::all::OP_PUSHCURRENTINPUTINDEX) => {
258 ret.push(Token::CurrInp);
259 }
260 script::Instruction::Op(opcodes::all::OP_ADD64) => {
261 ret.push(Token::Add64);
262 }
263 script::Instruction::Op(opcodes::all::OP_SUB64) => {
264 ret.push(Token::Sub64);
265 }
266 script::Instruction::Op(opcodes::all::OP_MUL64) => {
267 ret.push(Token::Mul64);
268 }
269 script::Instruction::Op(opcodes::all::OP_DIV64) => {
270 ret.push(Token::Div64);
271 }
272 script::Instruction::Op(opcodes::all::OP_NEG64) => {
273 ret.push(Token::Neg64);
274 }
275 script::Instruction::Op(opcodes::all::OP_GREATERTHAN64) => {
276 ret.push(Token::Ge64);
277 }
278 script::Instruction::Op(opcodes::all::OP_GREATERTHANOREQUAL64) => {
279 ret.push(Token::Geq64);
280 }
281 script::Instruction::Op(opcodes::all::OP_LESSTHAN64) => {
282 ret.push(Token::Le64);
283 }
284 script::Instruction::Op(opcodes::all::OP_LESSTHANOREQUAL64) => {
285 ret.push(Token::Leq64);
286 }
287 script::Instruction::Op(opcodes::all::OP_AND) => {
288 ret.push(Token::And);
289 }
290 script::Instruction::Op(opcodes::all::OP_OR) => {
291 ret.push(Token::Or);
292 }
293 script::Instruction::Op(opcodes::all::OP_XOR) => {
294 ret.push(Token::Xor);
295 }
296 script::Instruction::Op(opcodes::all::OP_INVERT) => {
297 ret.push(Token::Invert);
298 }
299 script::Instruction::Op(opcodes::all::OP_SCRIPTNUMTOLE64) => {
300 ret.push(Token::ScriptNumToLe64);
301 }
302 script::Instruction::Op(opcodes::all::OP_LE64TOSCRIPTNUM) => {
303 ret.push(Token::Le64ToScriptNum);
304 }
305 script::Instruction::Op(opcodes::all::OP_CHECKMULTISIG) => {
306 ret.push(Token::CheckMultiSig);
307 }
308 script::Instruction::Op(opcodes::all::OP_CHECKMULTISIGVERIFY) => {
309 ret.push(Token::CheckMultiSig);
310 ret.push(Token::Verify);
311 }
312 script::Instruction::Op(op) if op == opcodes::all::OP_CSV => {
313 ret.push(Token::CheckSequenceVerify);
314 }
315 script::Instruction::Op(op) if op == opcodes::all::OP_CLTV => {
316 ret.push(Token::CheckLockTimeVerify);
317 }
318 script::Instruction::Op(opcodes::all::OP_FROMALTSTACK) => {
319 ret.push(Token::FromAltStack);
320 }
321 script::Instruction::Op(opcodes::all::OP_TOALTSTACK) => {
322 ret.push(Token::ToAltStack);
323 }
324 script::Instruction::Op(opcodes::all::OP_LEFT) => {
325 ret.push(Token::Left);
326 }
327 script::Instruction::Op(opcodes::all::OP_2DUP) => {
328 ret.push(Token::Dup2);
329 }
330 script::Instruction::Op(opcodes::all::OP_CAT) => {
331 process_candidate_push(&mut ret);
332 ret.push(Token::Cat);
333 }
334 script::Instruction::Op(opcodes::all::OP_CODESEPARATOR) => {
335 ret.push(Token::CodeSep);
336 }
337 script::Instruction::Op(opcodes::all::OP_OVER) => {
338 ret.push(Token::Over);
339 }
340 script::Instruction::Op(opcodes::all::OP_NIP) => {
341 ret.push(Token::Nip);
342 }
343 script::Instruction::Op(opcodes::all::OP_PICK) => {
344 ret.push(Token::Pick);
345 }
346 script::Instruction::Op(opcodes::all::OP_DROP) => {
347 ret.push(Token::Drop);
348 }
349 script::Instruction::Op(opcodes::all::OP_DEPTH) => {
350 ret.push(Token::Depth);
351 }
352 script::Instruction::Op(opcodes::all::OP_DUP) => {
353 ret.push(Token::Dup);
354 }
355 script::Instruction::Op(opcodes::all::OP_ADD) => {
356 ret.push(Token::Add);
357 }
358 script::Instruction::Op(opcodes::all::OP_SUB) => {
359 ret.push(Token::Sub);
360 }
361 script::Instruction::Op(opcodes::all::OP_IF) => {
362 ret.push(Token::If);
363 }
364 script::Instruction::Op(opcodes::all::OP_IFDUP) => {
365 ret.push(Token::IfDup);
366 }
367 script::Instruction::Op(opcodes::all::OP_NOTIF) => {
368 ret.push(Token::NotIf);
369 }
370 script::Instruction::Op(opcodes::all::OP_ELSE) => {
371 ret.push(Token::Else);
372 }
373 script::Instruction::Op(opcodes::all::OP_ENDIF) => {
374 ret.push(Token::EndIf);
375 }
376 script::Instruction::Op(opcodes::all::OP_0NOTEQUAL) => {
377 ret.push(Token::ZeroNotEqual);
378 }
379 script::Instruction::Op(opcodes::all::OP_SIZE) => {
380 ret.push(Token::Size);
381 }
382 script::Instruction::Op(opcodes::all::OP_SWAP) => {
383 ret.push(Token::Swap);
384 }
385 script::Instruction::Op(opcodes::all::OP_VERIFY) => {
386 match ret.last() {
387 Some(op @ &Token::Equal)
388 | Some(op @ &Token::CheckSig)
389 | Some(op @ &Token::CheckMultiSig) => {
390 return Err(Error::NonMinimalVerify(format!("{:?}", op)))
391 }
392 _ => {}
393 }
394 ret.push(Token::Verify);
395 }
396 script::Instruction::Op(opcodes::all::OP_RIPEMD160) => {
397 ret.push(Token::Ripemd160);
398 }
399 script::Instruction::Op(opcodes::all::OP_HASH160) => {
400 ret.push(Token::Hash160);
401 }
402 script::Instruction::Op(opcodes::all::OP_SHA256) => {
403 ret.push(Token::Sha256);
404 }
405 script::Instruction::Op(opcodes::all::OP_HASH256) => {
406 ret.push(Token::Hash256);
407 }
408 script::Instruction::PushBytes(bytes) => {
409 if ret.last() == Some(&Token::Pick) {
415 ret.pop().unwrap();
416 match bytes.len() {
417 4 => ret.push(Token::PickPush4(slice_to_u32_le(bytes))),
420 32 => {
421 let mut x = [0u8; 32];
422 x.copy_from_slice(bytes);
423 ret.push(Token::PickPush32(x));
424 }
425 _ => return Err(Error::InvalidPush(bytes.to_owned())),
428 }
429 } else {
430 match bytes.len() {
435 8 => ret.push(Token::Bytes8(bytes)),
436 20 => ret.push(Token::Hash20(bytes)),
437 32 => ret.push(Token::Bytes32(bytes)),
438 33 => ret.push(Token::Bytes33(bytes)),
439 65 => ret.push(Token::Bytes65(bytes)),
440 _ => {
441 match script::read_scriptint(bytes) {
442 Ok(v) if v >= 0 => {
443 if &script::Builder::new().push_int(v).into_script()[1..]
445 != bytes
446 {
447 return Err(Error::InvalidPush(bytes.to_owned()));
448 }
449 ret.push(Token::Num(v as u32));
450 }
451 _ => ret.push(Token::Push(bytes.to_owned())),
452 }
453 }
454 }
455 }
456 }
457 script::Instruction::Op(opcodes::all::OP_PUSHNUM_NEG1) => {
458 ret.push(Token::NumNeg1);
459 }
460 script::Instruction::Op(opcodes::all::OP_PUSHBYTES_0) => {
461 ret.push(Token::Num(0));
462 }
463 script::Instruction::Op(opcodes::all::OP_PUSHNUM_1) => {
464 ret.push(Token::Num(1));
465 }
466 script::Instruction::Op(opcodes::all::OP_PUSHNUM_2) => {
467 ret.push(Token::Num(2));
468 }
469 script::Instruction::Op(opcodes::all::OP_PUSHNUM_3) => {
470 ret.push(Token::Num(3));
471 }
472 script::Instruction::Op(opcodes::all::OP_PUSHNUM_4) => {
473 ret.push(Token::Num(4));
474 }
475 script::Instruction::Op(opcodes::all::OP_PUSHNUM_5) => {
476 ret.push(Token::Num(5));
477 }
478 script::Instruction::Op(opcodes::all::OP_PUSHNUM_6) => {
479 ret.push(Token::Num(6));
480 }
481 script::Instruction::Op(opcodes::all::OP_PUSHNUM_7) => {
482 ret.push(Token::Num(7));
483 }
484 script::Instruction::Op(opcodes::all::OP_PUSHNUM_8) => {
485 ret.push(Token::Num(8));
486 }
487 script::Instruction::Op(opcodes::all::OP_PUSHNUM_9) => {
488 ret.push(Token::Num(9));
489 }
490 script::Instruction::Op(opcodes::all::OP_PUSHNUM_10) => {
491 ret.push(Token::Num(10));
492 }
493 script::Instruction::Op(opcodes::all::OP_PUSHNUM_11) => {
494 ret.push(Token::Num(11));
495 }
496 script::Instruction::Op(opcodes::all::OP_PUSHNUM_12) => {
497 ret.push(Token::Num(12));
498 }
499 script::Instruction::Op(opcodes::all::OP_PUSHNUM_13) => {
500 ret.push(Token::Num(13));
501 }
502 script::Instruction::Op(opcodes::all::OP_PUSHNUM_14) => {
503 ret.push(Token::Num(14));
504 }
505 script::Instruction::Op(opcodes::all::OP_PUSHNUM_15) => {
506 ret.push(Token::Num(15));
507 }
508 script::Instruction::Op(opcodes::all::OP_PUSHNUM_16) => {
509 ret.push(Token::Num(16));
510 }
511 script::Instruction::Op(op) => return Err(Error::InvalidOpcode(op)),
512 };
513 }
514 Ok(ret)
515}