@@ -105,7 +105,7 @@ impl ScriptBuf {
105
105
}
106
106
107
107
/// 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 ( ) ) ; }
109
109
110
110
/// Adds instructions to push some arbitrary data onto the stack.
111
111
pub fn push_slice < T : AsRef < PushBytes > > ( & mut self , data : T ) {
@@ -153,33 +153,42 @@ impl ScriptBuf {
153
153
}
154
154
155
155
impl 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
+
156
164
/// Pushes the slice without reserving
157
165
pub ( crate ) fn push_slice_no_opt ( & mut self , data : & PushBytes ) {
166
+ let mut this = self . as_byte_vec ( ) ;
158
167
// Start with a PUSH opcode
159
168
match data. len ( ) . to_u64 ( ) {
160
169
n if n < opcodes:: Ordinary :: OP_PUSHDATA1 as u64 => {
161
- self . 0 . push ( n as u8 ) ;
170
+ this . push ( n as u8 ) ;
162
171
}
163
172
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 ) ;
166
175
}
167
176
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 ) ;
171
180
}
172
181
// `PushBytes` enforces len < 0x100000000
173
182
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 ) ;
179
188
}
180
189
}
181
190
// Then push the raw bytes
182
- self . 0 . extend_from_slice ( data. as_bytes ( ) ) ;
191
+ this . extend_from_slice ( data. as_bytes ( ) ) ;
183
192
}
184
193
185
194
/// Computes the sum of `len` and the length of an appropriate push opcode.
@@ -200,7 +209,7 @@ impl ScriptBuf {
200
209
pub ( crate ) fn push_verify ( & mut self , last_opcode : Option < Opcode > ) {
201
210
match opcode_to_verify ( last_opcode) {
202
211
Some ( opcode) => {
203
- self . 0 . pop ( ) ;
212
+ self . as_byte_vec ( ) . pop ( ) ;
204
213
self . push_opcode ( opcode) ;
205
214
}
206
215
None => self . push_opcode ( OP_VERIFY ) ,
@@ -254,3 +263,31 @@ impl<'a> Extend<Instruction<'a>> for ScriptBuf {
254
263
}
255
264
}
256
265
}
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