1use std::default::Default;
28use std::{error, fmt};
29
30#[cfg(feature = "serde")] use serde;
31
32use blockdata::opcodes;
33use consensus::encode::{Decodable, Encodable};
34use consensus::encode::{self, Decoder, Encoder};
35use bitcoin_hashes::{hash160, sha256, Hash};
36#[cfg(feature="bitcoinconsensus")] use bitcoinconsensus;
37#[cfg(feature="bitcoinconsensus")] use std::convert;
38#[cfg(feature="bitcoinconsensus")] use bitcoin_hashes::sha256d;
39
40#[derive(Clone, Default, PartialOrd, Ord, PartialEq, Eq, Hash)]
41pub struct Script(Box<[u8]>);
43
44impl fmt::Debug for Script {
45 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
46 let mut index = 0;
47
48 f.write_str("Script(")?;
49 while index < self.0.len() {
50 let opcode = opcodes::All::from(self.0[index]);
51 index += 1;
52
53 let data_len = if let opcodes::Class::PushBytes(n) = opcode.classify() {
54 n as usize
55 } else {
56 match opcode {
57 opcodes::all::OP_PUSHDATA1 => {
58 if self.0.len() < index + 1 {
59 f.write_str("<unexpected end>")?;
60 break;
61 }
62 match read_uint(&self.0[index..], 1) {
63 Ok(n) => { index += 1; n as usize }
64 Err(_) => { f.write_str("<bad length>")?; break; }
65 }
66 }
67 opcodes::all::OP_PUSHDATA2 => {
68 if self.0.len() < index + 2 {
69 f.write_str("<unexpected end>")?;
70 break;
71 }
72 match read_uint(&self.0[index..], 2) {
73 Ok(n) => { index += 2; n as usize }
74 Err(_) => { f.write_str("<bad length>")?; break; }
75 }
76 }
77 opcodes::all::OP_PUSHDATA4 => {
78 if self.0.len() < index + 4 {
79 f.write_str("<unexpected end>")?;
80 break;
81 }
82 match read_uint(&self.0[index..], 4) {
83 Ok(n) => { index += 4; n as usize }
84 Err(_) => { f.write_str("<bad length>")?; break; }
85 }
86 }
87 _ => 0
88 }
89 };
90
91 if index > 1 { f.write_str(" ")?; }
92 if opcode == opcodes::all::OP_PUSHBYTES_0 {
94 f.write_str("OP_0")?;
95 } else {
96 write!(f, "{:?}", opcode)?;
97 }
98 if data_len > 0 {
100 f.write_str(" ")?;
101 if index + data_len <= self.0.len() {
102 for ch in &self.0[index..index + data_len] {
103 write!(f, "{:02x}", ch)?;
104 }
105 index += data_len;
106 } else {
107 f.write_str("<push past end>")?;
108 break;
109 }
110 }
111 }
112 f.write_str(")")
113 }
114}
115
116impl fmt::Display for Script {
117 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
118 fmt::Debug::fmt(self, f)
119 }
120}
121
122impl fmt::LowerHex for Script {
123 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
124 for &ch in self.0.iter() {
125 write!(f, "{:02x}", ch)?;
126 }
127 Ok(())
128 }
129}
130
131impl fmt::UpperHex for Script {
132 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
133 for &ch in self.0.iter() {
134 write!(f, "{:02X}", ch)?;
135 }
136 Ok(())
137 }
138}
139
140#[derive(PartialEq, Eq, Debug, Clone)]
141pub struct Builder(Vec<u8>);
143display_from_debug!(Builder);
144
145#[derive(PartialEq, Eq, Debug, Clone)]
149pub enum Error {
150 NonMinimalPush,
153 EarlyEndOfScript,
155 NumericOverflow,
157 #[cfg(feature="bitcoinconsensus")]
158 BitcoinConsensus(bitcoinconsensus::Error),
160 #[cfg(feature="bitcoinconsensus")]
161 UnknownSpentTransaction(sha256d::Hash),
163 #[cfg(feature="bitcoinconsensus")]
164 WrongSpentOutputIndex(usize),
166 #[cfg(feature="bitcoinconsensus")]
167 SerializationError
169}
170
171impl fmt::Display for Error {
172 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
173 f.write_str(error::Error::description(self))
174 }
175}
176
177impl error::Error for Error {
178 fn cause(&self) -> Option<&error::Error> { None }
179
180 fn description(&self) -> &'static str {
181 match *self {
182 Error::NonMinimalPush => "non-minimal datapush",
183 Error::EarlyEndOfScript => "unexpected end of script",
184 Error::NumericOverflow => "numeric overflow (number on stack larger than 4 bytes)",
185 #[cfg(feature="bitcoinconsensus")]
186 Error::BitcoinConsensus(ref _n) => "bitcoinconsensus verification failed",
187 #[cfg(feature="bitcoinconsensus")]
188 Error::UnknownSpentTransaction (ref _hash) => "unknown transaction referred in Transaction::verify()",
189 #[cfg(feature="bitcoinconsensus")]
190 Error::WrongSpentOutputIndex(ref _ix) => "unknown output index {} referred in Transaction::verify()",
191 #[cfg(feature="bitcoinconsensus")]
192 Error::SerializationError => "can not serialize the spending transaction in Transaction::verify()",
193 }
194 }
195}
196
197#[cfg(feature="bitcoinconsensus")]
198#[doc(hidden)]
199impl convert::From<bitcoinconsensus::Error> for Error {
200 fn from(err: bitcoinconsensus::Error) -> Error {
201 match err {
202 _ => Error::BitcoinConsensus(err)
203 }
204 }
205}
206fn build_scriptint(n: i64) -> Vec<u8> {
208 if n == 0 { return vec![] }
209
210 let neg = n < 0;
211
212 let mut abs = if neg { -n } else { n } as usize;
213 let mut v = vec![];
214 while abs > 0xFF {
215 v.push((abs & 0xFF) as u8);
216 abs >>= 8;
217 }
218 if abs & 0x80 != 0 {
221 v.push(abs as u8);
222 v.push(if neg { 0x80u8 } else { 0u8 });
223 }
224 else {
226 abs |= if neg { 0x80 } else { 0 };
227 v.push(abs as u8);
228 }
229 v
230}
231
232pub fn read_scriptint(v: &[u8]) -> Result<i64, Error> {
247 let len = v.len();
248 if len == 0 { return Ok(0); }
249 if len > 4 { return Err(Error::NumericOverflow); }
250
251 let (mut ret, sh) = v.iter()
252 .fold((0, 0), |(acc, sh), n| (acc + ((*n as i64) << sh), sh + 8));
253 if v[len - 1] & 0x80 != 0 {
254 ret &= (1 << (sh - 1)) - 1;
255 ret = -ret;
256 }
257 Ok(ret)
258}
259
260#[inline]
263pub fn read_scriptbool(v: &[u8]) -> bool {
264 !(v.is_empty() ||
265 ((v[v.len() - 1] == 0 || v[v.len() - 1] == 0x80) &&
266 v.iter().rev().skip(1).all(|&w| w == 0)))
267}
268
269pub fn read_uint(data: &[u8], size: usize) -> Result<usize, Error> {
271 if data.len() < size {
272 Err(Error::EarlyEndOfScript)
273 } else {
274 let mut ret = 0;
275 for (i, item) in data.iter().take(size).enumerate() {
276 ret += (*item as usize) << (i * 8);
277 }
278 Ok(ret)
279 }
280}
281
282impl Script {
283 pub fn new() -> Script { Script(vec![].into_boxed_slice()) }
285
286 pub fn len(&self) -> usize { self.0.len() }
288
289 pub fn is_empty(&self) -> bool { self.0.is_empty() }
291
292 pub fn as_bytes(&self) -> &[u8] { &*self.0 }
294
295 pub fn to_bytes(&self) -> Vec<u8> { self.0.clone().into_vec() }
297
298 pub fn into_bytes(self) -> Vec<u8> { self.0.into_vec() }
300
301 pub fn to_p2sh(&self) -> Script {
303 Builder::new().push_opcode(opcodes::all::OP_HASH160)
304 .push_slice(&hash160::Hash::hash(&self.0)[..])
305 .push_opcode(opcodes::all::OP_EQUAL)
306 .into_script()
307 }
308
309 pub fn to_v0_p2wsh(&self) -> Script {
312 Builder::new().push_int(0)
313 .push_slice(&sha256::Hash::hash(&self.0)[..])
314 .into_script()
315 }
316
317 #[inline]
319 pub fn is_p2sh(&self) -> bool {
320 self.0.len() == 23 &&
321 self.0[0] == opcodes::all::OP_HASH160.into_u8() &&
322 self.0[1] == opcodes::all::OP_PUSHBYTES_20.into_u8() &&
323 self.0[22] == opcodes::all::OP_EQUAL.into_u8()
324 }
325
326 #[inline]
328 pub fn is_p2pkh(&self) -> bool {
329 self.0.len() == 25 &&
330 self.0[0] == opcodes::all::OP_DUP.into_u8() &&
331 self.0[1] == opcodes::all::OP_HASH160.into_u8() &&
332 self.0[2] == opcodes::all::OP_PUSHBYTES_20.into_u8() &&
333 self.0[23] == opcodes::all::OP_EQUALVERIFY.into_u8() &&
334 self.0[24] == opcodes::all::OP_CHECKSIG.into_u8()
335 }
336
337 #[inline]
339 pub fn is_p2pk(&self) -> bool {
340 (self.0.len() == 67 &&
341 self.0[0] == opcodes::all::OP_PUSHBYTES_65.into_u8() &&
342 self.0[66] == opcodes::all::OP_CHECKSIG.into_u8())
343 || (self.0.len() == 35 &&
344 self.0[0] == opcodes::all::OP_PUSHBYTES_33.into_u8() &&
345 self.0[34] == opcodes::all::OP_CHECKSIG.into_u8())
346 }
347
348 #[inline]
350 pub fn is_v0_p2wsh(&self) -> bool {
351 self.0.len() == 34 &&
352 self.0[0] == opcodes::all::OP_PUSHBYTES_0.into_u8() &&
353 self.0[1] == opcodes::all::OP_PUSHBYTES_32.into_u8()
354 }
355
356 #[inline]
358 pub fn is_v0_p2wpkh(&self) -> bool {
359 self.0.len() == 22 &&
360 self.0[0] == opcodes::all::OP_PUSHBYTES_0.into_u8() &&
361 self.0[1] == opcodes::all::OP_PUSHBYTES_20.into_u8()
362 }
363
364 pub fn is_op_return (&self) -> bool {
366 !self.0.is_empty() && (opcodes::All::from(self.0[0]) == opcodes::all::OP_RETURN)
367 }
368
369 pub fn is_provably_unspendable(&self) -> bool {
371 !self.0.is_empty() && (opcodes::All::from(self.0[0]).classify() == opcodes::Class::ReturnOp ||
372 opcodes::All::from(self.0[0]).classify() == opcodes::Class::IllegalOp)
373 }
374
375 pub fn iter(&self, enforce_minimal: bool) -> Instructions {
380 Instructions {
381 data: &self.0[..],
382 enforce_minimal: enforce_minimal,
383 }
384 }
385
386 #[cfg(feature="bitcoinconsensus")]
387 pub fn verify (&self, index: usize, amount: u64, spending: &[u8]) -> Result<(), Error> {
393 Ok(bitcoinconsensus::verify (&self.0[..], amount, spending, index)?)
394 }
395}
396
397impl From<Vec<u8>> for Script {
399 fn from(v: Vec<u8>) -> Script { Script(v.into_boxed_slice()) }
400}
401
402impl_index_newtype!(Script, u8);
403
404#[derive(Debug, PartialEq, Eq, Clone)]
406pub enum Instruction<'a> {
407 PushBytes(&'a [u8]),
409 Op(opcodes::All),
411 Error(Error)
413}
414
415pub struct Instructions<'a> {
417 data: &'a [u8],
418 enforce_minimal: bool,
419}
420
421impl<'a> Iterator for Instructions<'a> {
422 type Item = Instruction<'a>;
423
424 fn next(&mut self) -> Option<Instruction<'a>> {
425 if self.data.is_empty() {
426 return None;
427 }
428
429 match opcodes::All::from(self.data[0]).classify() {
430 opcodes::Class::PushBytes(n) => {
431 let n = n as usize;
432 if self.data.len() < n + 1 {
433 self.data = &[]; return Some(Instruction::Error(Error::EarlyEndOfScript));
435 }
436 if self.enforce_minimal {
437 if n == 1 && (self.data[1] == 0x81 || (self.data[1] > 0 && self.data[1] <= 16)) {
438 self.data = &[];
439 return Some(Instruction::Error(Error::NonMinimalPush));
440 }
441 }
442 let ret = Some(Instruction::PushBytes(&self.data[1..n+1]));
443 self.data = &self.data[n + 1..];
444 ret
445 }
446 opcodes::Class::Ordinary(opcodes::Ordinary::OP_PUSHDATA1) => {
447 if self.data.len() < 2 {
448 self.data = &[];
449 return Some(Instruction::Error(Error::EarlyEndOfScript));
450 }
451 let n = match read_uint(&self.data[1..], 1) {
452 Ok(n) => n,
453 Err(e) => {
454 self.data = &[];
455 return Some(Instruction::Error(e));
456 }
457 };
458 if self.data.len() < n + 2 {
459 self.data = &[];
460 return Some(Instruction::Error(Error::EarlyEndOfScript));
461 }
462 if self.enforce_minimal && n < 76 {
463 self.data = &[];
464 return Some(Instruction::Error(Error::NonMinimalPush));
465 }
466 let ret = Some(Instruction::PushBytes(&self.data[2..n+2]));
467 self.data = &self.data[n + 2..];
468 ret
469 }
470 opcodes::Class::Ordinary(opcodes::Ordinary::OP_PUSHDATA2) => {
471 if self.data.len() < 3 {
472 self.data = &[];
473 return Some(Instruction::Error(Error::EarlyEndOfScript));
474 }
475 let n = match read_uint(&self.data[1..], 2) {
476 Ok(n) => n,
477 Err(e) => {
478 self.data = &[];
479 return Some(Instruction::Error(e));
480 }
481 };
482 if self.enforce_minimal && n < 0x100 {
483 self.data = &[];
484 return Some(Instruction::Error(Error::NonMinimalPush));
485 }
486 if self.data.len() < n + 3 {
487 self.data = &[];
488 return Some(Instruction::Error(Error::EarlyEndOfScript));
489 }
490 let ret = Some(Instruction::PushBytes(&self.data[3..n + 3]));
491 self.data = &self.data[n + 3..];
492 ret
493 }
494 opcodes::Class::Ordinary(opcodes::Ordinary::OP_PUSHDATA4) => {
495 if self.data.len() < 5 {
496 self.data = &[];
497 return Some(Instruction::Error(Error::EarlyEndOfScript));
498 }
499 let n = match read_uint(&self.data[1..], 4) {
500 Ok(n) => n,
501 Err(e) => {
502 self.data = &[];
503 return Some(Instruction::Error(e));
504 }
505 };
506 if self.enforce_minimal && n < 0x10000 {
507 self.data = &[];
508 return Some(Instruction::Error(Error::NonMinimalPush));
509 }
510 if self.data.len() < n + 5 {
511 self.data = &[];
512 return Some(Instruction::Error(Error::EarlyEndOfScript));
513 }
514 let ret = Some(Instruction::PushBytes(&self.data[5..n + 5]));
515 self.data = &self.data[n + 5..];
516 ret
517 }
518 _ => {
520 let ret = Some(Instruction::Op(opcodes::All::from(self.data[0])));
521 self.data = &self.data[1..];
522 ret
523 }
524 }
525 }
526}
527
528impl Builder {
529 pub fn new() -> Builder { Builder(vec![]) }
531
532 pub fn len(&self) -> usize { self.0.len() }
534
535 pub fn is_empty(&self) -> bool { self.0.is_empty() }
537
538 pub fn push_int(mut self, data: i64) -> Builder {
542 if data == -1 || (data >= 1 && data <= 16) {
544 self.0.push((data - 1 + opcodes::OP_TRUE.into_u8() as i64) as u8);
545 self
546 }
547 else if data == 0 {
549 self.0.push(opcodes::OP_FALSE.into_u8());
550 self
551 }
552 else { self.push_scriptint(data) }
554 }
555
556 pub fn push_scriptint(self, data: i64) -> Builder {
559 self.push_slice(&build_scriptint(data))
560 }
561
562 pub fn push_slice(mut self, data: &[u8]) -> Builder {
564 match data.len() as u64 {
566 n if n < opcodes::Ordinary::OP_PUSHDATA1 as u64 => { self.0.push(n as u8); },
567 n if n < 0x100 => {
568 self.0.push(opcodes::Ordinary::OP_PUSHDATA1.into_u8());
569 self.0.push(n as u8);
570 },
571 n if n < 0x10000 => {
572 self.0.push(opcodes::Ordinary::OP_PUSHDATA2.into_u8());
573 self.0.push((n % 0x100) as u8);
574 self.0.push((n / 0x100) as u8);
575 },
576 n if n < 0x100000000 => {
577 self.0.push(opcodes::Ordinary::OP_PUSHDATA4.into_u8());
578 self.0.push((n % 0x100) as u8);
579 self.0.push(((n / 0x100) % 0x100) as u8);
580 self.0.push(((n / 0x10000) % 0x100) as u8);
581 self.0.push((n / 0x1000000) as u8);
582 }
583 _ => panic!("tried to put a 4bn+ sized object into a script!")
584 }
585 self.0.extend(data.iter().cloned());
587 self
588 }
589
590 pub fn push_opcode(mut self, data: opcodes::All) -> Builder {
592 self.0.push(data.into_u8());
593 self
594 }
595
596 pub fn into_script(self) -> Script {
598 Script(self.0.into_boxed_slice())
599 }
600}
601
602impl Default for Builder {
604 fn default() -> Builder { Builder(vec![]) }
605}
606
607impl From<Vec<u8>> for Builder {
609 fn from(v: Vec<u8>) -> Builder { Builder(v) }
610}
611
612impl_index_newtype!(Builder, u8);
613
614#[cfg(feature = "serde")]
615impl<'de> serde::Deserialize<'de> for Script {
616 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
617 where
618 D: serde::Deserializer<'de>,
619 {
620 use std::fmt::{self, Formatter};
621
622 struct Visitor;
623 impl<'de> serde::de::Visitor<'de> for Visitor {
624 type Value = Script;
625
626 fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
627 formatter.write_str("a script")
628 }
629
630 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
631 where
632 E: serde::de::Error,
633 {
634 let v: Vec<u8> = ::hex::decode(v).map_err(E::custom)?;
635 Ok(Script::from(v))
636 }
637
638 fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
639 where
640 E: serde::de::Error,
641 {
642 self.visit_str(v)
643 }
644
645 fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
646 where
647 E: serde::de::Error,
648 {
649 self.visit_str(&v)
650 }
651 }
652
653 deserializer.deserialize_str(Visitor)
654 }
655}
656
657#[cfg(feature = "serde")]
658impl serde::Serialize for Script {
659 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
661 where
662 S: serde::Serializer,
663 {
664 serializer.serialize_str(&format!("{:x}", self))
665 }
666}
667
668impl<S: Encoder> Encodable<S> for Script {
670 #[inline]
671 fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> {
672 self.0.consensus_encode(s)
673 }
674}
675
676impl<D: Decoder> Decodable<D> for Script {
677 #[inline]
678 fn consensus_decode(d: &mut D) -> Result<Script, encode::Error> {
679 Ok(Script(Decodable::consensus_decode(d)?))
680 }
681}
682
683#[cfg(test)]
684mod test {
685 use hex::decode as hex_decode;
686
687 use super::*;
688 use super::build_scriptint;
689
690 use consensus::encode::{deserialize, serialize};
691 use blockdata::opcodes;
692
693 #[test]
694 fn script() {
695 let mut comp = vec![];
696 let mut script = Builder::new();
697 assert_eq!(&script[..], &comp[..]);
698
699 script = script.push_int(1); comp.push(81u8); assert_eq!(&script[..], &comp[..]);
701 script = script.push_int(0); comp.push(0u8); assert_eq!(&script[..], &comp[..]);
702 script = script.push_int(4); comp.push(84u8); assert_eq!(&script[..], &comp[..]);
703 script = script.push_int(-1); comp.push(79u8); assert_eq!(&script[..], &comp[..]);
704 script = script.push_scriptint(4); comp.extend([1u8, 4].iter().cloned()); assert_eq!(&script[..], &comp[..]);
706 script = script.push_int(17); comp.extend([1u8, 17].iter().cloned()); assert_eq!(&script[..], &comp[..]);
708 script = script.push_int(10000); comp.extend([2u8, 16, 39].iter().cloned()); assert_eq!(&script[..], &comp[..]);
709 script = script.push_int(10000000); comp.extend([4u8, 128, 150, 152, 0].iter().cloned()); assert_eq!(&script[..], &comp[..]);
711 script = script.push_int(-10000000); comp.extend([4u8, 128, 150, 152, 128].iter().cloned()); assert_eq!(&script[..], &comp[..]);
712
713 script = script.push_slice("NRA4VR".as_bytes()); comp.extend([6u8, 78, 82, 65, 52, 86, 82].iter().cloned()); assert_eq!(&script[..], &comp[..]);
715
716 script = script.push_opcode(opcodes::all::OP_CHECKSIG); comp.push(0xACu8); assert_eq!(&script[..], &comp[..]);
718 script = script.push_opcode(opcodes::all::OP_CHECKSIG); comp.push(0xACu8); assert_eq!(&script[..], &comp[..]);
719 }
720
721 #[test]
722 fn script_builder() {
723 let script = Builder::new().push_opcode(opcodes::all::OP_DUP)
725 .push_opcode(opcodes::all::OP_HASH160)
726 .push_slice(&hex_decode("16e1ae70ff0fa102905d4af297f6912bda6cce19").unwrap())
727 .push_opcode(opcodes::all::OP_EQUALVERIFY)
728 .push_opcode(opcodes::all::OP_CHECKSIG)
729 .into_script();
730 assert_eq!(&format!("{:x}", script), "76a91416e1ae70ff0fa102905d4af297f6912bda6cce1988ac");
731 }
732
733 #[test]
734 fn script_serialize() {
735 let hex_script = hex_decode("6c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52").unwrap();
736 let script: Result<Script, _> = deserialize(&hex_script);
737 assert!(script.is_ok());
738 assert_eq!(serialize(&script.unwrap()), hex_script);
739 }
740
741 #[test]
742 fn scriptint_round_trip() {
743 assert_eq!(build_scriptint(-1), vec![0x81]);
744 assert_eq!(build_scriptint(255), vec![255, 0]);
745 assert_eq!(build_scriptint(256), vec![0, 1]);
746 assert_eq!(build_scriptint(257), vec![1, 1]);
747 assert_eq!(build_scriptint(511), vec![255, 1]);
748 for &i in [10, 100, 255, 256, 1000, 10000, 25000, 200000, 5000000, 1000000000,
749 (1 << 31) - 1, -((1 << 31) - 1)].iter() {
750 assert_eq!(Ok(i), read_scriptint(&build_scriptint(i)));
751 assert_eq!(Ok(-i), read_scriptint(&build_scriptint(-i)));
752 }
753 assert!(read_scriptint(&build_scriptint(1 << 31)).is_err());
754 assert!(read_scriptint(&build_scriptint(-(1 << 31))).is_err());
755 }
756
757 #[test]
758 fn provably_unspendable_test() {
759 assert_eq!(hex_script!("410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac").is_provably_unspendable(), false);
761 assert_eq!(hex_script!("4104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac").is_provably_unspendable(), false);
762 assert_eq!(hex_script!("76a914ee61d57ab51b9d212335b1dba62794ac20d2bcf988ac").is_provably_unspendable(), false);
764 assert_eq!(hex_script!("6aa9149eb21980dc9d413d8eac27314938b9da920ee53e87").is_provably_unspendable(), true);
765 }
766
767 #[test]
768 fn op_return_test() {
769 assert_eq!(hex_script!("6aa9149eb21980dc9d413d8eac27314938b9da920ee53e87").is_op_return(), true);
770 assert_eq!(hex_script!("76a914ee61d57ab51b9d212335b1dba62794ac20d2bcf988ac").is_op_return(), false);
771 assert_eq!(hex_script!("").is_op_return(), false);
772 }
773
774 #[test]
775 #[cfg(all(feature = "serde", feature = "strason"))]
776 fn script_json_serialize() {
777 use strason::Json;
778
779 let original = hex_script!("827651a0698faaa9a8a7a687");
780 let json = Json::from_serialize(&original).unwrap();
781 assert_eq!(json.to_bytes(), b"\"827651a0698faaa9a8a7a687\"");
782 assert_eq!(json.string(), Some("827651a0698faaa9a8a7a687"));
783 let des = json.into_deserialize().unwrap();
784 assert_eq!(original, des);
785 }
786
787 #[test]
788 fn script_debug_display() {
789 assert_eq!(format!("{:?}", hex_script!("6363636363686868686800")),
790 "Script(OP_IF OP_IF OP_IF OP_IF OP_IF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_0)");
791 assert_eq!(format!("{}", hex_script!("6363636363686868686800")),
792 "Script(OP_IF OP_IF OP_IF OP_IF OP_IF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_0)");
793 assert_eq!(format!("{}", hex_script!("2102715e91d37d239dea832f1460e91e368115d8ca6cc23a7da966795abad9e3b699ac")),
794 "Script(OP_PUSHBYTES_33 02715e91d37d239dea832f1460e91e368115d8ca6cc23a7da966795abad9e3b699 OP_CHECKSIG)");
795 assert_eq!(format!("{}", hex_script!("0047304402202457e78cc1b7f50d0543863c27de75d07982bde8359b9e3316adec0aec165f2f02200203fd331c4e4a4a02f48cf1c291e2c0d6b2f7078a784b5b3649fca41f8794d401004cf1552103244e602b46755f24327142a0517288cebd159eccb6ccf41ea6edf1f601e9af952103bbbacc302d19d29dbfa62d23f37944ae19853cf260c745c2bea739c95328fcb721039227e83246bd51140fe93538b2301c9048be82ef2fb3c7fc5d78426ed6f609ad210229bf310c379b90033e2ecb07f77ecf9b8d59acb623ab7be25a0caed539e2e6472103703e2ed676936f10b3ce9149fa2d4a32060fb86fa9a70a4efe3f21d7ab90611921031e9b7c6022400a6bb0424bbcde14cff6c016b91ee3803926f3440abf5c146d05210334667f975f55a8455d515a2ef1c94fdfa3315f12319a14515d2a13d82831f62f57ae")),
797 "Script(OP_0 OP_PUSHBYTES_71 304402202457e78cc1b7f50d0543863c27de75d07982bde8359b9e3316adec0aec165f2f02200203fd331c4e4a4a02f48cf1c291e2c0d6b2f7078a784b5b3649fca41f8794d401 OP_0 OP_PUSHDATA1 552103244e602b46755f24327142a0517288cebd159eccb6ccf41ea6edf1f601e9af952103bbbacc302d19d29dbfa62d23f37944ae19853cf260c745c2bea739c95328fcb721039227e83246bd51140fe93538b2301c9048be82ef2fb3c7fc5d78426ed6f609ad210229bf310c379b90033e2ecb07f77ecf9b8d59acb623ab7be25a0caed539e2e6472103703e2ed676936f10b3ce9149fa2d4a32060fb86fa9a70a4efe3f21d7ab90611921031e9b7c6022400a6bb0424bbcde14cff6c016b91ee3803926f3440abf5c146d05210334667f975f55a8455d515a2ef1c94fdfa3315f12319a14515d2a13d82831f62f57ae)");
798 }
799
800 #[test]
801 fn script_p2sh_p2p2k_template() {
802 assert!(hex_script!("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").is_p2pkh());
804 assert!(!hex_script!("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").is_p2sh());
805 assert!(!hex_script!("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ad").is_p2pkh());
806 assert!(!hex_script!("").is_p2pkh());
807 assert!(hex_script!("a914acc91e6fef5c7f24e5c8b3f11a664aa8f1352ffd87").is_p2sh());
808 assert!(!hex_script!("a914acc91e6fef5c7f24e5c8b3f11a664aa8f1352ffd87").is_p2pkh());
809 assert!(!hex_script!("a314acc91e6fef5c7f24e5c8b3f11a664aa8f1352ffd87").is_p2sh());
810 }
811
812 #[test]
813 fn script_p2pk() {
814 assert!(hex_script!("21021aeaf2f8638a129a3156fbe7e5ef635226b0bafd495ff03afe2c843d7e3a4b51ac").is_p2pk());
815 assert!(hex_script!("410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac").is_p2pk());
816 }
817
818 #[test]
819 fn p2sh_p2wsh_conversion() {
820 let redeem_script = hex_script!("410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac");
823 let expected_witout = hex_script!("0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64");
824 assert!(redeem_script.to_v0_p2wsh().is_v0_p2wsh());
825 assert_eq!(redeem_script.to_v0_p2wsh(), expected_witout);
826
827 let redeem_script = hex_script!("0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8");
829 let expected_p2shout = hex_script!("a91491b24bf9f5288532960ac687abb035127b1d28a587");
830 assert!(redeem_script.to_p2sh().is_p2sh());
831 assert_eq!(redeem_script.to_p2sh(), expected_p2shout);
832
833 let redeem_script = hex_script!("410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac");
835 let expected_witout = hex_script!("0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64");
836 let expected_out = hex_script!("a914f386c2ba255cc56d20cfa6ea8b062f8b5994551887");
837 assert!(redeem_script.to_p2sh().is_p2sh());
838 assert!(redeem_script.to_p2sh().to_v0_p2wsh().is_v0_p2wsh());
839 assert_eq!(redeem_script.to_v0_p2wsh(), expected_witout);
840 assert_eq!(redeem_script.to_v0_p2wsh().to_p2sh(), expected_out);
841 }
842
843 #[test]
844 fn test_iterator() {
845 let zero = hex_script!("00");
846 let zeropush = hex_script!("0100");
847
848 let nonminimal = hex_script!("4c0169b2"); let minimal = hex_script!("0169b2"); let nonminimal_alt = hex_script!("026900b2"); let v_zero: Vec<Instruction> = zero.iter(true).collect();
853 let v_zeropush: Vec<Instruction> = zeropush.iter(true).collect();
854
855 let v_min: Vec<Instruction> = minimal.iter(true).collect();
856 let v_nonmin: Vec<Instruction> = nonminimal.iter(true).collect();
857 let v_nonmin_alt: Vec<Instruction> = nonminimal_alt.iter(true).collect();
858 let slop_v_min: Vec<Instruction> = minimal.iter(false).collect();
859 let slop_v_nonmin: Vec<Instruction> = nonminimal.iter(false).collect();
860 let slop_v_nonmin_alt: Vec<Instruction> = nonminimal_alt.iter(false).collect();
861
862 assert_eq!(
863 v_zero,
864 vec![
865 Instruction::PushBytes(&[]),
866 ]
867 );
868 assert_eq!(
869 v_zeropush,
870 vec![
871 Instruction::PushBytes(&[0]),
872 ]
873 );
874
875 assert_eq!(
876 v_min,
877 vec![
878 Instruction::PushBytes(&[105]),
879 Instruction::Op(opcodes::all::OP_NOP3),
880 ]
881 );
882
883 assert_eq!(
884 v_nonmin,
885 vec![
886 Instruction::Error(Error::NonMinimalPush),
887 ]
888 );
889
890 assert_eq!(
891 v_nonmin_alt,
892 vec![
893 Instruction::PushBytes(&[105, 0]),
894 Instruction::Op(opcodes::all::OP_NOP3),
895 ]
896 );
897
898 assert_eq!(v_min, slop_v_min);
899 assert_eq!(v_min, slop_v_nonmin);
900 assert_eq!(v_nonmin_alt, slop_v_nonmin_alt);
901 }
902
903 #[test]
904 fn script_ord() {
905 let script_1 = Builder::new().push_slice(&[1,2,3,4]).into_script();
906 let script_2 = Builder::new().push_int(10).into_script();
907 let script_3 = Builder::new().push_int(15).into_script();
908 let script_4 = Builder::new().push_opcode(opcodes::all::OP_RETURN).into_script();
909
910 assert!(script_1 < script_2);
911 assert!(script_2 < script_3);
912 assert!(script_3 < script_4);
913
914 assert!(script_1 <= script_1);
915 assert!(script_1 >= script_1);
916
917 assert!(script_4 > script_3);
918 assert!(script_3 > script_2);
919 assert!(script_2 > script_1);
920 }
921
922 #[test]
923 #[cfg(feature="bitcoinconsensus")]
924 fn test_bitcoinconsensus () {
925 let spent = Builder::from(hex_decode("0020701a8d401c84fb13e6baf169d59684e17abd9fa216c8cc5b9fc63d622ff8c58d").unwrap()).into_script();
927 let spending = hex_decode("010000000001011f97548fbbe7a0db7588a66e18d803d0089315aa7d4cc28360b6ec50ef36718a0100000000ffffffff02df1776000000000017a9146c002a686959067f4866b8fb493ad7970290ab728757d29f0000000000220020701a8d401c84fb13e6baf169d59684e17abd9fa216c8cc5b9fc63d622ff8c58d04004730440220565d170eed95ff95027a69b313758450ba84a01224e1f7f130dda46e94d13f8602207bdd20e307f062594022f12ed5017bbf4a055a06aea91c10110a0e3bb23117fc014730440220647d2dc5b15f60bc37dc42618a370b2a1490293f9e5c8464f53ec4fe1dfe067302203598773895b4b16d37485cbe21b337f4e4b650739880098c592553add7dd4355016952210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae00000000").unwrap();
928 spent.verify(0, 18393430, spending.as_slice()).unwrap();
929 }
930}
931