@@ -105,7 +105,7 @@ impl ScriptBuf {
105105 }
106106
107107 /// Adds a single opcode to the script.
108- pub fn push_opcode ( & mut self , data : Opcode ) { self . 0 . push ( data. to_u8 ( ) ) ; }
108+ pub fn push_opcode ( & mut self , data : Opcode ) { self . as_byte_vec ( ) . push ( data. to_u8 ( ) ) ; }
109109
110110 /// Adds instructions to push some arbitrary data onto the stack.
111111 pub fn push_slice < T : AsRef < PushBytes > > ( & mut self , data : T ) {
@@ -153,33 +153,42 @@ impl ScriptBuf {
153153}
154154
155155impl ScriptBuf {
156+ /// Pretends to convert `&mut ScriptBuf` to `&mut Vec<u8>` so that it can be modified.
157+ ///
158+ /// Note: if the returned value leaks the original `ScriptBuf` will become empty.
159+ pub ( crate ) fn as_byte_vec ( & mut self ) -> ScriptBufAsVec < ' _ > {
160+ let vec = core:: mem:: take ( self ) . into_bytes ( ) ;
161+ ScriptBufAsVec ( self , vec)
162+ }
163+
156164 /// Pushes the slice without reserving
157165 pub ( crate ) fn push_slice_no_opt ( & mut self , data : & PushBytes ) {
166+ let mut this = self . as_byte_vec ( ) ;
158167 // Start with a PUSH opcode
159168 match data. len ( ) . to_u64 ( ) {
160169 n if n < opcodes:: Ordinary :: OP_PUSHDATA1 as u64 => {
161- self . 0 . push ( n as u8 ) ;
170+ this . push ( n as u8 ) ;
162171 }
163172 n if n < 0x100 => {
164- self . 0 . push ( opcodes:: Ordinary :: OP_PUSHDATA1 . to_u8 ( ) ) ;
165- self . 0 . push ( n as u8 ) ;
173+ this . push ( opcodes:: Ordinary :: OP_PUSHDATA1 . to_u8 ( ) ) ;
174+ this . push ( n as u8 ) ;
166175 }
167176 n if n < 0x10000 => {
168- self . 0 . push ( opcodes:: Ordinary :: OP_PUSHDATA2 . to_u8 ( ) ) ;
169- self . 0 . push ( ( n % 0x100 ) as u8 ) ;
170- self . 0 . push ( ( n / 0x100 ) as u8 ) ;
177+ this . push ( opcodes:: Ordinary :: OP_PUSHDATA2 . to_u8 ( ) ) ;
178+ this . push ( ( n % 0x100 ) as u8 ) ;
179+ this . push ( ( n / 0x100 ) as u8 ) ;
171180 }
172181 // `PushBytes` enforces len < 0x100000000
173182 n => {
174- self . 0 . push ( opcodes:: Ordinary :: OP_PUSHDATA4 . to_u8 ( ) ) ;
175- self . 0 . push ( ( n % 0x100 ) as u8 ) ;
176- self . 0 . push ( ( ( n / 0x100 ) % 0x100 ) as u8 ) ;
177- self . 0 . push ( ( ( n / 0x10000 ) % 0x100 ) as u8 ) ;
178- self . 0 . push ( ( n / 0x1000000 ) as u8 ) ;
183+ this . push ( opcodes:: Ordinary :: OP_PUSHDATA4 . to_u8 ( ) ) ;
184+ this . push ( ( n % 0x100 ) as u8 ) ;
185+ this . push ( ( ( n / 0x100 ) % 0x100 ) as u8 ) ;
186+ this . push ( ( ( n / 0x10000 ) % 0x100 ) as u8 ) ;
187+ this . push ( ( n / 0x1000000 ) as u8 ) ;
179188 }
180189 }
181190 // Then push the raw bytes
182- self . 0 . extend_from_slice ( data. as_bytes ( ) ) ;
191+ this . extend_from_slice ( data. as_bytes ( ) ) ;
183192 }
184193
185194 /// Computes the sum of `len` and the length of an appropriate push opcode.
@@ -200,7 +209,7 @@ impl ScriptBuf {
200209 pub ( crate ) fn push_verify ( & mut self , last_opcode : Option < Opcode > ) {
201210 match opcode_to_verify ( last_opcode) {
202211 Some ( opcode) => {
203- self . 0 . pop ( ) ;
212+ self . as_byte_vec ( ) . pop ( ) ;
204213 self . push_opcode ( opcode) ;
205214 }
206215 None => self . push_opcode ( OP_VERIFY ) ,
@@ -254,3 +263,31 @@ impl<'a> Extend<Instruction<'a>> for ScriptBuf {
254263 }
255264 }
256265}
266+
267+ /// Pretends that this is a mutable reference to [`ScriptBuf`]'s internal buffer.
268+ ///
269+ /// In reality the backing `Vec<u8>` is swapped with an empty one and this is holding both the
270+ /// reference and the vec. The vec is put back when this drops so it also covers paics. (But not
271+ /// leaks, which is OK since we never leak.)
272+ pub ( crate ) struct ScriptBufAsVec < ' a > ( & ' a mut ScriptBuf , Vec < u8 > ) ;
273+
274+ impl < ' a > core:: ops:: Deref for ScriptBufAsVec < ' a > {
275+ type Target = Vec < u8 > ;
276+
277+ fn deref ( & self ) -> & Self :: Target {
278+ & self . 1
279+ }
280+ }
281+
282+ impl < ' a > core:: ops:: DerefMut for ScriptBufAsVec < ' a > {
283+ fn deref_mut ( & mut self ) -> & mut Self :: Target {
284+ & mut self . 1
285+ }
286+ }
287+
288+ impl < ' a > Drop for ScriptBufAsVec < ' a > {
289+ fn drop ( & mut self ) {
290+ let vec = core:: mem:: take ( & mut self . 1 ) ;
291+ * ( self . 0 ) = ScriptBuf :: from_bytes ( vec) ;
292+ }
293+ }
0 commit comments