From e393d0ec3b6373f8604dd41f45717c5b3b3155fe Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Fri, 4 Dec 2015 10:59:43 -0600 Subject: [PATCH] Add useful Debug/Display for Script --- src/blockdata/script.rs | 90 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 1 deletion(-) diff --git a/src/blockdata/script.rs b/src/blockdata/script.rs index f43cfb24..12ff8ff5 100644 --- a/src/blockdata/script.rs +++ b/src/blockdata/script.rs @@ -44,10 +44,88 @@ use network::serialize::{SimpleDecoder, SimpleEncoder, serialize}; use util::hash::Sha256dHash; use util::misc::script_find_and_remove; -#[derive(PartialEq, Eq, Debug)] +#[derive(PartialEq, Eq)] /// A Bitcoin script pub struct Script(Box<[u8]>); +impl fmt::Debug for Script { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut index = 0; + + try!(f.write_str("Script(")); + while index < self.0.len() { + let opcode = opcodes::All::from(self.0[index]); + + let data_len = if let opcodes::Class::PushBytes(n) = opcode.classify() { + n as usize + } else { + match opcode { + opcodes::All::OP_PUSHDATA1 => { + if self.0.len() < index + 1 { + try!(f.write_str("")); + break; + } + match read_uint(&self.0[index..], 1) { + Ok(n) => { index += 1; n as usize } + Err(_) => { try!(f.write_str("")); break; } + } + } + opcodes::All::OP_PUSHDATA2 => { + if self.0.len() < index + 2 { + try!(f.write_str("")); + break; + } + match read_uint(&self.0[index..], 2) { + Ok(n) => { index += 2; n as usize } + Err(_) => { try!(f.write_str("")); break; } + } + } + opcodes::All::OP_PUSHDATA4 => { + if self.0.len() < index + 4 { + try!(f.write_str("")); + break; + } + match read_uint(&self.0[index..], 4) { + Ok(n) => { index += 4; n as usize } + Err(_) => { try!(f.write_str("")); break; } + } + } + _ => 0 + } + }; + + if index > 0 { try!(f.write_str(" ")); } + // Write the opcode + if opcode == opcodes::All::OP_PUSHBYTES_0 { + try!(f.write_str("OP_0")); + } else { + try!(write!(f, "{:?}", opcode)); + } + index += 1; + // Write any pushdata + if data_len > 0 { + try!(f.write_str(" ")); + if index + data_len < self.0.len() { + for ch in &self.0[index..index + data_len] { + try!(write!(f, "{:02x}", ch)); + } + index += data_len; + } else { + try!(f.write_str("")); + break; + } + } + } + f.write_str(")") + } +} + +impl fmt::Display for Script { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(self, f) + } +} + impl Clone for Script { fn clone(&self) -> Script { Script(self.0.to_vec().into_boxed_slice()) @@ -3091,6 +3169,16 @@ mod test { let des = json.into_deserialize().unwrap(); assert_eq!(original, des); } + + #[test] + fn script_debug_display() { + assert_eq!(format!("{:?}", hex_script!("6363636363686868686800")), + "Script(OP_IF OP_IF OP_IF OP_IF OP_IF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_0)"); + assert_eq!(format!("{}", hex_script!("6363636363686868686800")), + "Script(OP_IF OP_IF OP_IF OP_IF OP_IF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_0)"); + assert_eq!(format!("{}", hex_script!("2102715e91d37d239dea832f1460e91e368115d8ca6cc23a7da966795abad9e3b699ac")), + "Script(OP_PUSHBYTES_33 02715e91d37d239dea832f1460e91e368115d8ca6cc23a7da966795abad9e3b699 OP_CHECKSIG)"); + } }