Skip to main content

bitcoin_primitives/script/
push_bytes.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! Contains `PushBytes` & co
4
5use core::borrow::{Borrow, BorrowMut};
6use core::convert::Infallible;
7use core::ops::{Deref, DerefMut};
8
9#[rustfmt::skip]                // Keep public re-exports separate.
10#[doc(inline)]
11// This is not the usual re-export, `primitive` here is a code audit thing.
12pub use self::primitive::{PushBytes, PushBytesBuf};
13
14/// This module only contains required operations so that outside functions wouldn't accidentally
15/// break invariants. Therefore auditing this module should be sufficient.
16mod primitive {
17    use alloc::borrow::ToOwned;
18    use alloc::vec::Vec;
19    use core::ops::{
20        Bound, Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo,
21        RangeToInclusive,
22    };
23
24    use super::PushBytesError;
25
26    #[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))]
27    fn check_limit(_: usize) -> Result<(), PushBytesError> { Ok(()) }
28
29    #[cfg(not(any(target_pointer_width = "16", target_pointer_width = "32")))]
30    fn check_limit(len: usize) -> Result<(), PushBytesError> {
31        if len < 0x1_0000_0000 {
32            Ok(())
33        } else {
34            Err(PushBytesError { len })
35        }
36    }
37
38    // Defined in `REPO_DIR/include/newtype.rs`.
39    crate::transparent_newtype! {
40        /// Byte slices that can be in Bitcoin script.
41        ///
42        /// The encoding of Bitcoin script restricts data pushes to be less than 2^32 bytes long.
43        /// This type represents slices that are guaranteed to be within the limit so they can be put in
44        /// the script safely.
45        #[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
46        pub struct PushBytes([u8]);
47
48        impl PushBytes {
49            /// Constructs a new `&PushBytes` without checking the length.
50            ///
51            /// The caller is responsible for checking that the length is less than the 2^32.
52            fn from_slice_unchecked(bytes: &_) -> &Self;
53
54            /// Constructs a new `&mut PushBytes` without checking the length.
55            ///
56            /// The caller is responsible for checking that the length is less than the 2^32.
57            fn from_mut_slice_unchecked(bytes: &mut _) -> &mut Self;
58        }
59    }
60
61    impl PushBytes {
62        /// Constructs an empty `&PushBytes`.
63        pub fn empty() -> &'static Self { Self::from_slice_unchecked(&[]) }
64
65        /// Returns the underlying bytes.
66        pub fn as_bytes(&self) -> &[u8] { &self.0 }
67
68        /// Returns the underlying mutable bytes.
69        pub fn as_mut_bytes(&mut self) -> &mut [u8] { &mut self.0 }
70    }
71
72    macro_rules! delegate_index {
73        ($($type:ty),* $(,)?) => {
74            $(
75                impl Index<$type> for PushBytes {
76                    type Output = Self;
77
78                    #[inline]
79                    #[track_caller]
80                    fn index(&self, index: $type) -> &Self::Output {
81                        Self::from_slice_unchecked(&self.0[index])
82                    }
83                }
84
85                impl IndexMut<$type> for PushBytes {
86                    #[inline]
87                    #[track_caller]
88                    fn index_mut(&mut self, index: $type) -> &mut Self::Output {
89                        Self::from_mut_slice_unchecked(&mut self.0[index])
90                    }
91                }
92            )*
93        }
94    }
95
96    delegate_index!(
97        Range<usize>,
98        RangeFrom<usize>,
99        RangeTo<usize>,
100        RangeFull,
101        RangeInclusive<usize>,
102        RangeToInclusive<usize>,
103        (Bound<usize>, Bound<usize>)
104    );
105
106    impl Index<usize> for PushBytes {
107        type Output = u8;
108
109        #[inline]
110        #[track_caller]
111        fn index(&self, index: usize) -> &Self::Output { &self.0[index] }
112    }
113
114    impl IndexMut<usize> for PushBytes {
115        #[inline]
116        #[track_caller]
117        fn index_mut(&mut self, index: usize) -> &mut Self::Output { &mut self.0[index] }
118    }
119
120    impl<'a> TryFrom<&'a [u8]> for &'a PushBytes {
121        type Error = PushBytesError;
122
123        fn try_from(bytes: &'a [u8]) -> Result<Self, Self::Error> {
124            check_limit(bytes.len())?;
125            Ok(PushBytes::from_slice_unchecked(bytes))
126        }
127    }
128
129    impl<'a> TryFrom<&'a mut [u8]> for &'a mut PushBytes {
130        type Error = PushBytesError;
131
132        fn try_from(bytes: &'a mut [u8]) -> Result<Self, Self::Error> {
133            check_limit(bytes.len())?;
134            Ok(PushBytes::from_mut_slice_unchecked(bytes))
135        }
136    }
137
138    macro_rules! from_array {
139        ($($len:literal),* $(,)?) => {
140            $(
141                impl<'a> From<&'a [u8; $len]> for &'a PushBytes {
142                    fn from(bytes: &'a [u8; $len]) -> Self {
143                        // Check that the macro wasn't called with a wrong number.
144                        const _: () = [(); 1][($len >= 0x100000000u64) as usize];
145                        PushBytes::from_slice_unchecked(bytes)
146                    }
147                }
148
149                impl<'a> From<&'a mut [u8; $len]> for &'a mut PushBytes {
150                    fn from(bytes: &'a mut [u8; $len]) -> Self {
151                        // Macro check already above, no need to duplicate.
152                        // We know the size of array statically and we checked macro input.
153                        PushBytes::from_mut_slice_unchecked(bytes)
154                    }
155                }
156
157                impl AsRef<PushBytes> for [u8; $len] {
158                    fn as_ref(&self) -> &PushBytes {
159                        self.into()
160                    }
161                }
162
163                impl AsMut<PushBytes> for [u8; $len] {
164                    fn as_mut(&mut self) -> &mut PushBytes {
165                        self.into()
166                    }
167                }
168
169                impl From<[u8; $len]> for PushBytesBuf {
170                    fn from(bytes: [u8; $len]) -> Self {
171                        PushBytesBuf(Vec::from(&bytes))
172                    }
173                }
174
175                impl<'a> From<&'a [u8; $len]> for PushBytesBuf {
176                    fn from(bytes: &'a [u8; $len]) -> Self {
177                        PushBytesBuf(Vec::from(bytes))
178                    }
179                }
180            )*
181        }
182    }
183
184    // Sizes up to 76 to support all pubkey and signature sizes
185    from_array! {
186        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
187        25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
188        48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
189        71, 72, 73, 74, 75, 76
190    }
191
192    /// Owned, growable counterpart to `PushBytes`.
193    #[derive(Default, Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
194    pub struct PushBytesBuf(Vec<u8>);
195
196    impl PushBytesBuf {
197        /// Constructs an empty `PushBytesBuf`.
198        #[inline]
199        pub const fn new() -> Self { Self(Vec::new()) }
200
201        /// Constructs an empty `PushBytesBuf` with reserved capacity.
202        pub fn with_capacity(capacity: usize) -> Self { Self(Vec::with_capacity(capacity)) }
203
204        /// Reserve capacity for `additional_capacity` bytes.
205        pub fn reserve(&mut self, additional_capacity: usize) {
206            self.0.reserve(additional_capacity);
207        }
208
209        /// Try pushing a single byte.
210        ///
211        /// # Errors
212        ///
213        /// This method fails if `self` would exceed the limit.
214        #[allow(deprecated)]
215        pub fn push(&mut self, byte: u8) -> Result<(), PushBytesError> {
216            // This is OK on 32 bit archs since vec has its own check and this check is pointless.
217            check_limit(self.0.len().saturating_add(1))?;
218            self.0.push(byte);
219            Ok(())
220        }
221
222        /// Try appending a slice to `PushBytesBuf`
223        ///
224        /// # Errors
225        ///
226        /// This method fails if `self` would exceed the limit.
227        pub fn extend_from_slice(&mut self, bytes: &[u8]) -> Result<(), PushBytesError> {
228            let len = self.0.len().saturating_add(bytes.len());
229            check_limit(len)?;
230            self.0.extend_from_slice(bytes);
231            Ok(())
232        }
233
234        /// Remove the last byte from buffer if any.
235        pub fn pop(&mut self) -> Option<u8> { self.0.pop() }
236
237        /// Remove the byte at `index` and return it.
238        ///
239        /// # Panics
240        ///
241        /// This method panics if `index` is out of bounds.
242        #[track_caller]
243        pub fn remove(&mut self, index: usize) -> u8 { self.0.remove(index) }
244
245        /// Remove all bytes from buffer without affecting capacity.
246        pub fn clear(&mut self) { self.0.clear() }
247
248        /// Remove bytes from buffer past `len`.
249        pub fn truncate(&mut self, len: usize) { self.0.truncate(len) }
250
251        /// Extracts `PushBytes` slice
252        pub fn as_push_bytes(&self) -> &PushBytes {
253            // length guaranteed by our invariant
254            PushBytes::from_slice_unchecked(&self.0)
255        }
256
257        /// Extracts mutable `PushBytes` slice
258        pub fn as_mut_push_bytes(&mut self) -> &mut PushBytes {
259            // length guaranteed by our invariant
260            PushBytes::from_mut_slice_unchecked(&mut self.0)
261        }
262
263        /// Accesses inner `Vec` - provided for `super` to impl other methods.
264        pub(super) fn inner(&self) -> &Vec<u8> { &self.0 }
265    }
266
267    impl From<PushBytesBuf> for Vec<u8> {
268        fn from(value: PushBytesBuf) -> Self { value.0 }
269    }
270
271    impl TryFrom<Vec<u8>> for PushBytesBuf {
272        type Error = PushBytesError;
273
274        fn try_from(vec: Vec<u8>) -> Result<Self, Self::Error> {
275            // check len
276            let _: &PushBytes = vec.as_slice().try_into()?;
277            Ok(Self(vec))
278        }
279    }
280
281    impl ToOwned for PushBytes {
282        type Owned = PushBytesBuf;
283
284        fn to_owned(&self) -> Self::Owned { PushBytesBuf(self.0.to_owned()) }
285    }
286}
287
288impl PushBytes {
289    /// Returns the number of bytes in buffer.
290    pub fn len(&self) -> usize { self.as_bytes().len() }
291
292    /// Returns true if the buffer contains zero bytes.
293    pub fn is_empty(&self) -> bool { self.as_bytes().is_empty() }
294}
295
296impl PushBytesBuf {
297    /// Returns the number of bytes in buffer.
298    pub fn len(&self) -> usize { self.inner().len() }
299
300    /// Returns the number of bytes the buffer can contain without reallocating.
301    pub fn capacity(&self) -> usize { self.inner().capacity() }
302
303    /// Returns true if the buffer contains zero bytes.
304    pub fn is_empty(&self) -> bool { self.inner().is_empty() }
305}
306
307impl AsRef<[u8]> for PushBytes {
308    fn as_ref(&self) -> &[u8] { self.as_bytes() }
309}
310
311impl AsMut<[u8]> for PushBytes {
312    fn as_mut(&mut self) -> &mut [u8] { self.as_mut_bytes() }
313}
314
315impl Deref for PushBytesBuf {
316    type Target = PushBytes;
317
318    fn deref(&self) -> &Self::Target { self.as_push_bytes() }
319}
320
321impl DerefMut for PushBytesBuf {
322    fn deref_mut(&mut self) -> &mut Self::Target { self.as_mut_push_bytes() }
323}
324
325impl AsRef<Self> for PushBytes {
326    fn as_ref(&self) -> &Self { self }
327}
328
329impl AsMut<Self> for PushBytes {
330    fn as_mut(&mut self) -> &mut Self { self }
331}
332
333impl AsRef<PushBytes> for PushBytesBuf {
334    fn as_ref(&self) -> &PushBytes { self.as_push_bytes() }
335}
336
337impl AsMut<PushBytes> for PushBytesBuf {
338    fn as_mut(&mut self) -> &mut PushBytes { self.as_mut_push_bytes() }
339}
340
341impl Borrow<PushBytes> for PushBytesBuf {
342    fn borrow(&self) -> &PushBytes { self.as_push_bytes() }
343}
344
345impl BorrowMut<PushBytes> for PushBytesBuf {
346    fn borrow_mut(&mut self) -> &mut PushBytes { self.as_mut_push_bytes() }
347}
348
349crate::impl_asref_push_bytes! {
350    hashes::ripemd160::Hash,
351    hashes::hash160::Hash,
352    hashes::sha1::Hash,
353    hashes::sha256::Hash,
354    hashes::sha256d::Hash,
355}
356
357/// Reports information about failed conversion into `PushBytes`.
358///
359/// This should not be needed by general public, except as an additional bound on `TryFrom` when
360/// converting to `WitnessProgram`.
361pub trait PushBytesErrorReport {
362    /// How many bytes the input had.
363    fn input_len(&self) -> usize;
364}
365
366impl PushBytesErrorReport for core::convert::Infallible {
367    #[inline]
368    fn input_len(&self) -> usize { match *self {} }
369}
370
371#[doc(no_inline)]
372pub use error::PushBytesError;
373
374#[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))]
375mod error {
376    use core::fmt;
377
378    /// Error returned on attempt to create too large `PushBytes`.
379    #[allow(unused)]
380    #[derive(Debug, Clone, PartialEq, Eq)]
381    pub struct PushBytesError {
382        pub(super) never: core::convert::Infallible,
383    }
384
385    impl super::PushBytesErrorReport for PushBytesError {
386        #[inline]
387        fn input_len(&self) -> usize { match self.never {} }
388    }
389
390    impl fmt::Display for PushBytesError {
391        fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result { match self.never {} }
392    }
393}
394
395// we have 64 bits in mind, but even for esoteric sizes, this code is correct, since it's the
396// conservative one that checks for errors
397#[cfg(not(any(target_pointer_width = "16", target_pointer_width = "32")))]
398mod error {
399    use core::fmt;
400
401    /// Error returned on attempt to create too large `PushBytes`.
402    #[derive(Debug, Clone, PartialEq, Eq)]
403    pub struct PushBytesError {
404        /// How long the input was.
405        pub(super) len: usize,
406    }
407
408    impl super::PushBytesErrorReport for PushBytesError {
409        #[inline]
410        fn input_len(&self) -> usize { self.len }
411    }
412
413    impl fmt::Display for PushBytesError {
414        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
415            write!(
416                f,
417                "attempt to prepare {} bytes to be pushed into script but the limit is 2^32-1",
418                self.len
419            )
420        }
421    }
422}
423
424impl From<Infallible> for PushBytesError {
425    fn from(never: Infallible) -> Self { match never {} }
426}
427
428#[cfg(feature = "std")]
429impl std::error::Error for PushBytesError {
430    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
431        #[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))]
432        let Self { never: _ } = self;
433        #[cfg(not(any(target_pointer_width = "16", target_pointer_width = "32")))]
434        let Self { len: _ } = self;
435        None
436    }
437}
438
439#[cfg(test)]
440mod tests {
441    use alloc::vec;
442
443    use super::*;
444
445    #[test]
446    fn push_bytes_empty_inits() {
447        let pb = PushBytes::empty();
448        assert!(pb.is_empty());
449        assert_eq!(pb.len(), 0);
450        assert_eq!(pb.as_bytes(), &[0u8; 0]);
451
452        let pb = PushBytesBuf::new();
453        assert!(pb.is_empty());
454        assert_eq!(pb.len(), 0);
455        assert_eq!(pb.as_bytes(), &[0u8; 0]);
456
457        let pb = PushBytesBuf::default();
458        assert!(pb.is_empty());
459        assert_eq!(pb.len(), 0);
460        assert_eq!(pb.as_bytes(), &[0u8; 0]);
461    }
462
463    #[test]
464    fn push_bytes_try_from_slice() {
465        let data = [0x01, 0x02, 0x03];
466        let pb = <&PushBytes>::try_from(data.as_slice()).unwrap();
467        assert_eq!(pb.as_bytes(), &data);
468        assert_eq!(pb.len(), 3);
469        assert!(!pb.is_empty());
470    }
471
472    #[test]
473    #[cfg(target_pointer_width = "64")]
474    #[cfg_attr(miri, ignore)]
475    fn push_bytes_check_limit_boundary() {
476        // The limit is len < 2^32; a slice of exactly 2^32 bytes must be rejected.
477        // It's insane to allocate that much memory for a test case, so we have to fake
478        // it with unsafe pointer antics.
479        // Safety: try_from only reads bytes.len(), it never accesses the pointed-to data.
480        let ptr = core::ptr::NonNull::<u8>::dangling().as_ptr();
481        let too_long: &[u8] = unsafe { core::slice::from_raw_parts(ptr, 0x1_0000_0000) };
482        assert!(<&PushBytes>::try_from(too_long).is_err());
483    }
484
485    #[test]
486    fn push_bytes_from_array() {
487        let data = [0xde, 0xad, 0xbe, 0xef];
488        let pb: &PushBytes = (&data).into();
489        assert_eq!(pb.as_bytes(), &data);
490    }
491
492    #[test]
493    fn push_bytes_asref_array() {
494        let data = [0x01, 0x02];
495        let pb: &PushBytes = data.as_ref();
496        assert_eq!(pb.as_bytes(), &data);
497    }
498
499    #[test]
500    fn push_bytes_index() {
501        let data = [0x01, 0x02, 0x03];
502        let pb: &PushBytes = (&data).into();
503        assert_eq!(pb[0], 0x01);
504        assert_eq!(pb[2], 0x03);
505        let slice = &pb[1..];
506        assert_eq!(slice.as_bytes(), &[0x02, 0x03]);
507    }
508
509    #[test]
510    fn push_bytes_as_mut_bytes() {
511        let mut data = [0x01, 0x02, 0x03];
512        let pb: &mut PushBytes = (&mut data).into();
513        pb.as_mut_bytes()[0] = 0xff;
514        assert_eq!(data, [0xff, 0x02, 0x03]);
515    }
516
517    #[test]
518    fn push_bytes_buf_with_capacity() {
519        let buf = PushBytesBuf::with_capacity(16);
520        assert!(buf.is_empty());
521        assert!(buf.capacity() >= 16);
522    }
523
524    #[test]
525    fn push_bytes_buf_push_and_pop() {
526        let mut buf = PushBytesBuf::new();
527        buf.push(0x01).unwrap();
528        buf.push(0x02).unwrap();
529        assert_eq!(buf.len(), 2);
530        assert!(!buf.is_empty());
531        assert_eq!(buf.pop(), Some(0x02));
532        assert_eq!(buf.pop(), Some(0x01));
533        assert_eq!(buf.pop(), None);
534        assert!(buf.is_empty());
535    }
536
537    #[test]
538    fn push_bytes_buf_reserve() {
539        let mut buf = PushBytesBuf::new();
540        assert_eq!(buf.capacity(), 0);
541        buf.reserve(32);
542        assert!(buf.capacity() >= 32);
543    }
544
545    #[test]
546    fn push_bytes_buf_extend_from_slice() {
547        let mut buf = PushBytesBuf::new();
548        buf.extend_from_slice(&[0x01, 0x02, 0x03]).unwrap();
549        assert_eq!(buf.as_bytes(), &[0x01, 0x02, 0x03]);
550    }
551
552    #[test]
553    fn push_bytes_buf_clear() {
554        let mut buf = PushBytesBuf::new();
555        buf.extend_from_slice(&[0x01, 0x02]).unwrap();
556        buf.clear();
557        assert!(buf.is_empty());
558    }
559
560    #[test]
561    fn push_bytes_buf_truncate() {
562        let mut buf = PushBytesBuf::new();
563        buf.extend_from_slice(&[0x01, 0x02, 0x03, 0x04]).unwrap();
564        buf.truncate(2);
565        assert_eq!(buf.as_bytes(), &[0x01, 0x02]);
566    }
567
568    #[test]
569    fn push_bytes_buf_remove() {
570        let mut buf = PushBytesBuf::new();
571        buf.extend_from_slice(&[0x01, 0x02, 0x03]).unwrap();
572        let removed = buf.remove(1);
573        assert_eq!(removed, 0x02);
574        assert_eq!(buf.as_bytes(), &[0x01, 0x03]);
575    }
576
577    #[test]
578    fn push_bytes_buf_from_array() {
579        let buf = PushBytesBuf::from([0x01, 0x02, 0x03]);
580        assert_eq!(buf.as_bytes(), &[0x01, 0x02, 0x03]);
581    }
582
583    #[test]
584    fn push_bytes_buf_try_from_vec() {
585        let vec = vec![0x01, 0x02, 0x03];
586        let buf = PushBytesBuf::try_from(vec.clone()).unwrap();
587        assert_eq!(buf.as_bytes(), &vec[..]);
588    }
589
590    #[test]
591    fn push_bytes_buf_into_vec() {
592        let buf = PushBytesBuf::from([0x01, 0x02]);
593        let vec: alloc::vec::Vec<u8> = buf.into();
594        assert_eq!(vec, [0x01, 0x02]);
595    }
596
597    #[test]
598    fn push_bytes_buf_as_push_bytes() {
599        let buf = PushBytesBuf::from([0xab, 0xcd]);
600        let pb: &PushBytes = buf.as_push_bytes();
601        assert_eq!(pb.as_bytes(), &[0xab, 0xcd]);
602    }
603
604    #[test]
605    fn push_bytes_buf_deref() {
606        let buf = PushBytesBuf::from([0x01, 0x02]);
607        let pb: &PushBytes = &buf;
608        assert_eq!(pb.as_bytes(), buf.as_bytes());
609    }
610
611    #[test]
612    fn push_bytes_buf_to_owned() {
613        use alloc::borrow::ToOwned;
614        let data = [0x01, 0x02, 0x03];
615        let pb: &PushBytes = (&data).into();
616        let owned: PushBytesBuf = pb.to_owned();
617        assert_eq!(owned.as_bytes(), pb.as_bytes());
618    }
619}