bitcoin_cash_base/
byte_array.rs

1use crate::Integer;
2use byteorder::{LittleEndian, WriteBytesExt};
3use serde_derive::{Deserialize, Serialize};
4use std::borrow::Cow;
5use std::hash::Hash;
6use std::marker::PhantomData;
7use std::ops::Deref;
8use std::sync::Arc;
9
10#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
11pub enum Function {
12    Plain,
13    Sha1,
14    Ripemd160,
15    Sha256,
16    Hash256,
17    Hash160,
18    Num2Bin,
19    EcdsaSign,
20    SchnorrSign,
21    ToDataSig,
22    UnexpectedSplit,
23    Reverse,
24}
25
26#[derive(Clone, Debug)]
27pub struct ByteArray {
28    data: Arc<[u8]>,
29    #[cfg(not(feature = "simple-bytearray"))]
30    name: Option<Arc<Cow<'static, str>>>,
31    #[cfg(not(feature = "simple-bytearray"))]
32    function: Function,
33    #[cfg(not(feature = "simple-bytearray"))]
34    preimage: Option<Arc<[ByteArray]>>,
35}
36
37#[derive(Clone, Debug)]
38pub struct FixedByteArray<T> {
39    phantom: PhantomData<T>,
40    byte_array: ByteArray,
41}
42
43#[derive(Clone, Debug)]
44pub struct FromSliceError {
45    pub expected: usize,
46    pub actual: usize,
47}
48
49impl Function {
50    pub fn should_keep_intact(self) -> bool {
51        use Function::*;
52        match self {
53            Plain | Num2Bin | EcdsaSign | SchnorrSign | ToDataSig => false,
54            _ => true,
55        }
56    }
57}
58
59impl ByteArray {
60    pub fn debug_enabled() -> bool {
61        true
62    }
63
64    #[cfg(not(feature = "simple-bytearray"))]
65    pub fn new(name: impl Into<Cow<'static, str>>, data: impl Into<Arc<[u8]>>) -> Self {
66        ByteArray {
67            data: data.into(),
68            name: Some(Arc::new(name.into())),
69            function: Function::Plain,
70            preimage: None,
71        }
72    }
73
74    #[cfg(feature = "simple-bytearray")]
75    pub fn new(_name: impl Into<Cow<'static, str>>, data: impl Into<Arc<[u8]>>) -> Self {
76        ByteArray { data: data.into() }
77    }
78
79    #[cfg(not(feature = "simple-bytearray"))]
80    pub fn new_unnamed(data: impl Into<Arc<[u8]>>) -> Self {
81        ByteArray {
82            data: data.into(),
83            name: None,
84            function: Function::Plain,
85            preimage: None,
86        }
87    }
88
89    #[cfg(feature = "simple-bytearray")]
90    pub fn new_unnamed(data: impl Into<Arc<[u8]>>) -> Self {
91        ByteArray { data: data.into() }
92    }
93
94    #[cfg(not(feature = "simple-bytearray"))]
95    pub fn from_preimage(
96        data: Arc<[u8]>,
97        name: Option<Arc<Cow<'static, str>>>,
98        function: Function,
99        preimage: Option<Arc<[ByteArray]>>,
100    ) -> Self {
101        ByteArray {
102            data,
103            name,
104            function,
105            preimage,
106        }
107    }
108
109    #[cfg(feature = "simple-bytearray")]
110    pub fn from_preimage(
111        data: Arc<[u8]>,
112        _name: Option<Arc<Cow<'static, str>>>,
113        _function: Function,
114        _preimage: Option<Arc<[ByteArray]>>,
115    ) -> Self {
116        ByteArray { data }
117    }
118
119    #[cfg(not(feature = "simple-bytearray"))]
120    pub fn from_slice(name: impl Into<Cow<'static, str>>, slice: &[u8]) -> Self {
121        ByteArray {
122            data: slice.into(),
123            name: Some(Arc::new(name.into())),
124            function: Function::Plain,
125            preimage: None,
126        }
127    }
128
129    #[cfg(feature = "simple-bytearray")]
130    pub fn from_slice(_name: impl Into<Cow<'static, str>>, slice: &[u8]) -> Self {
131        ByteArray { data: slice.into() }
132    }
133
134    #[cfg(not(feature = "simple-bytearray"))]
135    pub fn from_slice_unnamed(slice: &[u8]) -> Self {
136        ByteArray {
137            data: slice.into(),
138            name: None,
139            function: Function::Plain,
140            preimage: None,
141        }
142    }
143
144    #[cfg(feature = "simple-bytearray")]
145    pub fn from_slice_unnamed(slice: &[u8]) -> Self {
146        ByteArray { data: slice.into() }
147    }
148
149    #[cfg(not(feature = "simple-bytearray"))]
150    pub fn function(&self) -> Function {
151        self.function
152    }
153
154    #[cfg(feature = "simple-bytearray")]
155    pub fn function(&self) -> Function {
156        Function::Plain
157    }
158
159    #[cfg(not(feature = "simple-bytearray"))]
160    pub fn preimage(&self) -> Option<&[ByteArray]> {
161        self.preimage.as_ref().map(|preimage| preimage.as_ref())
162    }
163
164    #[cfg(feature = "simple-bytearray")]
165    pub fn preimage(&self) -> Option<&[ByteArray]> {
166        None
167    }
168
169    #[cfg(not(feature = "simple-bytearray"))]
170    pub fn preimage_arc(&self) -> Option<&Arc<[ByteArray]>> {
171        self.preimage.as_ref()
172    }
173
174    #[cfg(feature = "simple-bytearray")]
175    pub fn preimage_arc(&self) -> Option<&Arc<[ByteArray]>> {
176        None
177    }
178
179    #[cfg(not(feature = "simple-bytearray"))]
180    pub fn name(&self) -> Option<&str> {
181        self.name.as_ref().map(|name| (*(*name).as_ref()).as_ref())
182    }
183
184    #[cfg(feature = "simple-bytearray")]
185    pub fn name(&self) -> Option<&str> {
186        None
187    }
188
189    #[cfg(not(feature = "simple-bytearray"))]
190    pub fn name_arc(&self) -> Option<&Arc<Cow<'static, str>>> {
191        self.name.as_ref()
192    }
193
194    #[cfg(feature = "simple-bytearray")]
195    pub fn name_arc(&self) -> Option<&Arc<Cow<'static, str>>> {
196        None
197    }
198
199    pub fn data(&self) -> &Arc<[u8]> {
200        &self.data
201    }
202
203    #[cfg(not(feature = "simple-bytearray"))]
204    pub fn concat_named_option(
205        self,
206        other: impl Into<ByteArray>,
207        name: Option<Arc<Cow<'static, str>>>,
208    ) -> ByteArray {
209        let other = other.into();
210        let mut new_data = Vec::with_capacity(self.data.len() + other.data.len());
211        new_data.extend_from_slice(&self.data);
212        new_data.extend_from_slice(&other.data);
213        if self.function == Function::Plain && other.function == Function::Plain {
214            let mut new_preimage = if self.preimage.is_some() {
215                self.preimage.unwrap().to_vec()
216            } else {
217                vec![self]
218            };
219            new_preimage.append(&mut if other.preimage.is_some() {
220                other.preimage.unwrap().to_vec()
221            } else {
222                vec![other]
223            });
224            return ByteArray {
225                data: new_data.into(),
226                name,
227                function: Function::Plain,
228                preimage: Some(new_preimage.into()),
229            };
230        }
231        ByteArray {
232            data: new_data.into(),
233            name,
234            function: Function::Plain,
235            preimage: Some(vec![self, other].into()),
236        }
237    }
238
239    #[cfg(feature = "simple-bytearray")]
240    pub fn concat_named_option(
241        self,
242        other: impl Into<ByteArray>,
243        _name: Option<Arc<Cow<'static, str>>>,
244    ) -> ByteArray {
245        let other = other.into();
246        let mut new_data = Vec::with_capacity(self.data.len() + other.data.len());
247        new_data.extend_from_slice(&self.data);
248        new_data.extend_from_slice(&other.data);
249        ByteArray {
250            data: new_data.into(),
251        }
252    }
253
254    pub fn concat(self, other: impl Into<ByteArray>) -> ByteArray {
255        self.concat_named_option(other, None)
256    }
257
258    pub fn concat_named(
259        self,
260        name: impl Into<Arc<Cow<'static, str>>>,
261        other: impl Into<ByteArray>,
262    ) -> ByteArray {
263        self.concat_named_option(other, Some(name.into()))
264    }
265
266    #[cfg(not(feature = "simple-bytearray"))]
267    pub fn split(self, at: usize) -> Result<(ByteArray, ByteArray), String> {
268        if self.data.len() < at {
269            return Err(format!(
270                "Index {} is out of bounds for array with length {}, {}.",
271                at,
272                self.data.len(),
273                hex::encode(&self.data)
274            ));
275        }
276        let mut data = self.data.to_vec();
277        let other = data.split_off(at);
278        let mut function = Function::Plain;
279        let (left_preimage, right_preimage) = match self.preimage {
280            Some(preimage) if !self.function.should_keep_intact() => {
281                let mut left_preimage = Vec::new();
282                let mut right_preimage = Vec::new();
283                let mut is_left = true;
284                let mut len = 0;
285                for part in preimage.iter().cloned() {
286                    let part_len = part.data.len();
287                    if len == at {
288                        is_left = false;
289                    }
290                    if len + part_len > at && is_left {
291                        let part_function = part.function;
292                        let (mut sub_left, mut sub_right) = part.split(at - len)?;
293                        if part_function.should_keep_intact() {
294                            sub_left.function = Function::UnexpectedSplit;
295                            sub_right.function = Function::UnexpectedSplit;
296                        }
297                        left_preimage.push(sub_left);
298                        right_preimage.push(sub_right);
299                        is_left = false;
300                    } else if is_left {
301                        left_preimage.push(part);
302                    } else {
303                        right_preimage.push(part);
304                    }
305                    len += part_len;
306                }
307                (Some(left_preimage), Some(right_preimage))
308            }
309            Some(_) => {
310                function = Function::UnexpectedSplit;
311                (None, None)
312            }
313            None => (None, None),
314        };
315        Ok((
316            ByteArray {
317                data: data.into(),
318                name: None,
319                function,
320                preimage: left_preimage.map(Into::into),
321            },
322            ByteArray {
323                data: other.into(),
324                name: None,
325                function,
326                preimage: right_preimage.map(Into::into),
327            },
328        ))
329    }
330
331    #[cfg(feature = "simple-bytearray")]
332    pub fn split(self, at: usize) -> Result<(ByteArray, ByteArray), String> {
333        if self.data.len() < at {
334            return Err(format!(
335                "Index {} is out of bounds for array with length {}, {}.",
336                at,
337                self.data.len(),
338                hex::encode(&self.data)
339            ));
340        }
341        let mut data = self.data.to_vec();
342        let other = data.split_off(at);
343        Ok((
344            ByteArray { data: data.into() },
345            ByteArray { data: other.into() },
346        ))
347    }
348
349    #[cfg(not(feature = "simple-bytearray"))]
350    pub fn apply_function(self, data: impl Into<Arc<[u8]>>, function: Function) -> ByteArray {
351        ByteArray {
352            data: data.into(),
353            name: None,
354            function,
355            preimage: Some(vec![self].into()),
356        }
357    }
358
359    #[cfg(feature = "simple-bytearray")]
360    pub fn apply_function(self, data: impl Into<Arc<[u8]>>, _function: Function) -> ByteArray {
361        ByteArray { data: data.into() }
362    }
363
364    #[cfg(not(feature = "simple-bytearray"))]
365    pub fn named(self, name: impl Into<Cow<'static, str>>) -> ByteArray {
366        ByteArray {
367            name: Some(Arc::new(name.into())),
368            ..self
369        }
370    }
371
372    #[cfg(feature = "simple-bytearray")]
373    pub fn named(self, _name: impl Into<Cow<'static, str>>) -> ByteArray {
374        ByteArray { ..self }
375    }
376
377    #[cfg(not(feature = "simple-bytearray"))]
378    pub fn named_option(self, name: Option<Arc<Cow<'static, str>>>) -> ByteArray {
379        ByteArray { name, ..self }
380    }
381
382    pub fn from_int(int: Integer, n_bytes: Integer) -> Result<Self, String> {
383        if n_bytes <= 0 {
384            return Err(format!("n_bytes={} not valid", n_bytes));
385        }
386        let max_bits = (n_bytes * 8 - 1).min(31) as u128;
387        let max_num: u128 = 1 << max_bits;
388        let max_num = (max_num - 1) as Integer;
389        let min_num = -max_num;
390        if int < min_num || int > max_num {
391            return Err(format!("int={} not valid for n_bytes={}", int, n_bytes));
392        }
393        let mut bytes = Vec::new();
394        bytes.write_i32::<LittleEndian>(int.abs()).unwrap();
395        let n_bytes = n_bytes as usize;
396        if bytes.len() < n_bytes {
397            bytes.append(&mut vec![0; n_bytes - bytes.len()]);
398        } else if bytes.len() > n_bytes {
399            bytes.drain(n_bytes..);
400        }
401        if int < 0 {
402            let len = bytes.len();
403            bytes[len - 1] |= 0x80;
404        }
405        Ok(ByteArray::from_preimage(
406            bytes.into(),
407            None,
408            Function::Num2Bin,
409            None,
410        ))
411    }
412}
413
414impl<T> FixedByteArray<T> {
415    pub fn as_byte_array(&self) -> &ByteArray {
416        &self.byte_array
417    }
418
419    pub fn into_byte_array(self) -> ByteArray {
420        self.byte_array
421    }
422
423    pub fn named(self, name: impl Into<Cow<'static, str>>) -> FixedByteArray<T> {
424        FixedByteArray {
425            phantom: PhantomData,
426            byte_array: self.byte_array.named(name),
427        }
428    }
429}
430
431impl<T> FixedByteArray<T>
432where
433    T: AsRef<[u8]>,
434{
435    pub fn new(name: impl Into<Cow<'static, str>>, data: T) -> Self {
436        FixedByteArray {
437            phantom: PhantomData,
438            byte_array: ByteArray::from_preimage(
439                data.as_ref().into(),
440                Some(Arc::new(name.into())),
441                Function::Plain,
442                None,
443            ),
444        }
445    }
446
447    pub fn new_unnamed(data: T) -> Self {
448        FixedByteArray {
449            phantom: PhantomData,
450            byte_array: ByteArray::from_preimage(data.as_ref().into(), None, Function::Plain, None),
451        }
452    }
453}
454
455impl<T> FixedByteArray<T>
456where
457    T: Default + AsRef<[u8]>,
458{
459    pub fn from_slice(
460        name: impl Into<Cow<'static, str>>,
461        slice: &[u8],
462    ) -> Result<Self, FromSliceError> {
463        let array = T::default();
464        if array.as_ref().len() != slice.len() {
465            return Err(FromSliceError {
466                expected: array.as_ref().len(),
467                actual: slice.len(),
468            });
469        }
470        Ok(FixedByteArray {
471            phantom: PhantomData,
472            byte_array: ByteArray::from_preimage(
473                slice.into(),
474                Some(Arc::new(name.into())),
475                Function::Plain,
476                None,
477            ),
478        })
479    }
480
481    pub fn from_slice_unnamed(slice: &[u8]) -> Result<Self, FromSliceError> {
482        let array = T::default();
483        if array.as_ref().len() != slice.len() {
484            return Err(FromSliceError {
485                expected: array.as_ref().len(),
486                actual: slice.len(),
487            });
488        }
489        Ok(FixedByteArray {
490            phantom: PhantomData,
491            byte_array: ByteArray::from_preimage(slice.into(), None, Function::Plain, None),
492        })
493    }
494
495    pub fn from_byte_array(byte_array: ByteArray) -> Result<Self, FromSliceError> {
496        let array = T::default();
497        if array.as_ref().len() != byte_array.len() {
498            return Err(FromSliceError {
499                expected: array.as_ref().len(),
500                actual: byte_array.len(),
501            });
502        }
503        Ok(FixedByteArray {
504            phantom: PhantomData,
505            byte_array,
506        })
507    }
508}
509
510impl Default for ByteArray {
511    fn default() -> Self {
512        ByteArray::from_slice_unnamed(&[])
513    }
514}
515
516impl From<Vec<u8>> for ByteArray {
517    fn from(vec: Vec<u8>) -> Self {
518        ByteArray::new_unnamed(vec)
519    }
520}
521
522impl From<&[u8]> for ByteArray {
523    fn from(slice: &[u8]) -> Self {
524        ByteArray::from_slice_unnamed(slice)
525    }
526}
527
528macro_rules! array_impls {
529    ($($N:literal)+) => {
530        $(
531            impl From<[u8; $N]> for ByteArray {
532                fn from(array: [u8; $N]) -> Self {
533                    ByteArray::from_slice_unnamed(array.as_ref())
534                }
535            }
536            impl From<&[u8; $N]> for ByteArray {
537                fn from(array: &[u8; $N]) -> Self {
538                    ByteArray::from_slice_unnamed(array.as_ref())
539                }
540            }
541        )+
542    }
543}
544
545array_impls! {
546     0  1  2  3  4  5  6  7  8  9
547    10 11 12 13 14 15 16 17 18 19
548    20 21 22 23 24 25 26 27 28 29
549    30 31 32
550}
551
552impl Hash for ByteArray {
553    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
554        self.data.hash(state)
555    }
556}
557
558impl Deref for ByteArray {
559    type Target = [u8];
560    fn deref(&self) -> &Self::Target {
561        &self.data
562    }
563}
564
565impl AsRef<[u8]> for ByteArray {
566    fn as_ref(&self) -> &[u8] {
567        &self.data
568    }
569}
570
571impl<I: std::slice::SliceIndex<[u8]>> std::ops::Index<I> for ByteArray {
572    type Output = I::Output;
573    fn index(&self, index: I) -> &Self::Output {
574        &self.data[index]
575    }
576}
577
578impl PartialEq for ByteArray {
579    fn eq(&self, other: &ByteArray) -> bool {
580        self.data == other.data
581    }
582}
583
584impl Eq for ByteArray {}
585
586impl<'de> serde::Deserialize<'de> for ByteArray {
587    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
588    where
589        D: serde::Deserializer<'de>,
590    {
591        Ok(ByteArray::from_slice_unnamed(
592            <&[u8] as serde::Deserialize<'de>>::deserialize(deserializer)?,
593        ))
594    }
595}
596
597impl serde::Serialize for ByteArray {
598    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
599    where
600        S: serde::Serializer,
601    {
602        self.data.serialize(serializer)
603    }
604}
605
606impl<T: Default + AsRef<[u8]>> Default for FixedByteArray<T> {
607    fn default() -> Self {
608        FixedByteArray {
609            phantom: PhantomData,
610            byte_array: ByteArray::new_unnamed(T::default().as_ref()),
611        }
612    }
613}
614
615impl<T> Hash for FixedByteArray<T> {
616    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
617        self.byte_array.hash(state)
618    }
619}
620
621impl<T> Deref for FixedByteArray<T> {
622    type Target = [u8];
623    fn deref(&self) -> &Self::Target {
624        &self.byte_array.data
625    }
626}
627
628impl<T> AsRef<[u8]> for FixedByteArray<T> {
629    fn as_ref(&self) -> &[u8] {
630        &self.byte_array.data
631    }
632}
633
634impl<T, I: std::slice::SliceIndex<[u8]>> std::ops::Index<I> for FixedByteArray<T> {
635    type Output = I::Output;
636    fn index(&self, index: I) -> &Self::Output {
637        &self.byte_array.data[index]
638    }
639}
640
641impl<T> PartialEq for FixedByteArray<T> {
642    fn eq(&self, other: &FixedByteArray<T>) -> bool {
643        self.byte_array.data == other.byte_array.data
644    }
645}
646
647impl<T> Eq for FixedByteArray<T> {}
648
649impl<'de, T> serde::Deserialize<'de> for FixedByteArray<T>
650where
651    T: serde::Deserialize<'de> + AsRef<[u8]>,
652{
653    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
654    where
655        D: serde::Deserializer<'de>,
656    {
657        Ok(FixedByteArray::new_unnamed(T::deserialize(deserializer)?))
658    }
659}
660
661impl<T> serde::Serialize for FixedByteArray<T>
662where
663    T: serde::Serialize + Default + AsMut<[u8]>,
664{
665    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
666    where
667        S: serde::Serializer,
668    {
669        let mut array = T::default();
670        array.as_mut().copy_from_slice(self.byte_array.as_ref());
671        array.serialize(serializer)
672    }
673}
674
675#[cfg(not(feature = "simple-bytearray"))]
676#[cfg(test)]
677mod tests {
678    use super::{ByteArray, Function};
679    use sha2::Digest;
680
681    #[test]
682    fn test_cat() {
683        let a = ByteArray::from_slice_unnamed(b"A");
684        let b = ByteArray::from_slice_unnamed(b"B");
685        let c = ByteArray::from_slice_unnamed(b"C");
686        let d = ByteArray::from_slice_unnamed(b"D");
687        let ab = a.concat(b);
688        {
689            assert_eq!(ab.data.as_ref(), b"AB");
690            let preimage = ab.preimage.as_ref().expect("No preimage");
691            assert_eq!(preimage[0].data.as_ref(), b"A");
692            assert_eq!(preimage[0].preimage, None);
693            assert_eq!(preimage[1].data.as_ref(), b"B");
694            assert_eq!(preimage[1].preimage, None);
695        }
696        let abcd = ab.concat(c.concat(d));
697        {
698            assert_eq!(abcd.data.as_ref(), b"ABCD");
699            let preimage = abcd.preimage.as_ref().expect("No preimage");
700            assert_eq!(preimage.len(), 4);
701            assert_eq!(preimage[0].data.as_ref(), b"A");
702            assert_eq!(preimage[0].preimage, None);
703            assert_eq!(preimage[1].data.as_ref(), b"B");
704            assert_eq!(preimage[1].preimage, None);
705            assert_eq!(preimage[2].data.as_ref(), b"C");
706            assert_eq!(preimage[2].preimage, None);
707            assert_eq!(preimage[3].data.as_ref(), b"D");
708            assert_eq!(preimage[3].preimage, None);
709        }
710    }
711
712    #[test]
713    fn test_hash() {
714        let a = ByteArray::from_slice_unnamed(b"A");
715        let b = ByteArray::from_slice_unnamed(b"B");
716        let c = ByteArray::from_slice_unnamed(b"C");
717        let cat = a.concat(b).concat(c);
718        let hash = sha2::Sha256::digest(&cat.data);
719        let hashed = cat.apply_function(hash.as_ref(), Function::Sha256);
720        let hash_preimage = hashed.preimage.as_ref().expect("No hash_preimage");
721        assert_eq!(hashed.data.as_ref(), hash.as_slice());
722        assert_eq!(hash_preimage.len(), 1);
723        assert_eq!(hash_preimage[0].data.as_ref(), b"ABC");
724        let preimage = hash_preimage[0].preimage.as_ref().expect("No preimage");
725        assert_eq!(preimage[0].data.as_ref(), b"A");
726        assert_eq!(preimage[0].preimage, None);
727        assert_eq!(preimage[1].data.as_ref(), b"B");
728        assert_eq!(preimage[1].preimage, None);
729        assert_eq!(preimage[2].data.as_ref(), b"C");
730        assert_eq!(preimage[2].preimage, None);
731    }
732
733    #[test]
734    fn test_hash_nested() {
735        let a = ByteArray::from_slice_unnamed(b"A");
736        let b = ByteArray::from_slice_unnamed(b"B");
737        let inner = a.concat(b);
738        let inner_hash = sha2::Sha256::digest(&inner.data);
739        let inner_hashed = inner.apply_function(inner_hash.as_ref(), Function::Sha256);
740        let c = ByteArray::from_slice_unnamed(b"C");
741        let d = ByteArray::from_slice_unnamed(b"D");
742        let outer = c.concat(inner_hashed).concat(d);
743        let outer_hash = sha2::Sha256::digest(&outer.data);
744        let outer_hashed = outer.apply_function(outer_hash.as_ref(), Function::Sha256);
745        assert_eq!(outer_hashed.data.as_ref(), outer_hash.as_slice());
746
747        let outer_preimage = outer_hashed.preimage.as_ref().expect("No preimage");
748
749        assert_eq!(outer_preimage.len(), 1);
750        let outer_preimage0 = &outer_preimage[0];
751        assert_eq!(
752            outer_preimage0.data.as_ref(),
753            [b"C", inner_hash.as_slice(), b"D"].concat().as_slice()
754        );
755        let outer_preimages = outer_preimage0.preimage.as_ref().expect("No preimage");
756        assert_eq!(outer_preimages.len(), 3);
757        assert_eq!(outer_preimages[0].preimage, None);
758        assert_eq!(outer_preimages[1].data.as_ref(), inner_hash.as_slice());
759        assert!(outer_preimages[1].preimage.is_some());
760        assert_eq!(outer_preimages[2].data.as_ref(), b"D");
761        assert_eq!(outer_preimages[2].preimage, None);
762
763        let inner_hash_preimage = outer_preimages[1].preimage.as_ref().expect("No preimage");
764        assert_eq!(inner_hash_preimage.len(), 1);
765        assert_eq!(inner_hash_preimage[0].data.as_ref(), b"AB");
766        let inner_preimage = inner_hash_preimage[0]
767            .preimage
768            .as_ref()
769            .expect("No preimage");
770        assert_eq!(inner_preimage[0].data.as_ref(), b"A");
771        assert_eq!(inner_preimage[0].preimage, None);
772        assert_eq!(inner_preimage[1].data.as_ref(), b"B");
773        assert_eq!(inner_preimage[1].preimage, None);
774    }
775
776    #[test]
777    fn test_split_a_b() {
778        let a = ByteArray::from_slice_unnamed(b"A");
779        let b = ByteArray::from_slice_unnamed(b"B");
780        let cat = a.concat(b);
781        let (left, right) = cat.split(1).unwrap();
782        let left_preimage = left.preimage.as_ref().expect("No preimage");
783        let right_preimage = right.preimage.as_ref().expect("No preimage");
784        assert_eq!(left.function, Function::Plain);
785        assert_eq!(left.data.as_ref(), b"A");
786        assert_eq!(left_preimage.len(), 1);
787        assert_eq!(left_preimage[0].data.as_ref(), b"A");
788        assert_eq!(right.function, Function::Plain);
789        assert_eq!(right.data.as_ref(), b"B");
790        assert_eq!(right_preimage.len(), 1);
791        assert_eq!(right_preimage[0].data.as_ref(), b"B");
792    }
793
794    #[test]
795    fn test_split_nested() {
796        let a = ByteArray::from_slice_unnamed(b"A");
797        let b = ByteArray::from_slice_unnamed(b"B");
798        let inner = a.concat(b);
799        let inner_hash = sha2::Sha256::digest(&inner.data);
800        let inner_hashed = inner.apply_function(inner_hash.as_ref(), Function::Sha256);
801        let c = ByteArray::from_slice_unnamed(b"C");
802        let d = ByteArray::from_slice_unnamed(b"D");
803        let outer = c.concat(inner_hashed.clone()).concat(d);
804
805        // test 1, split neatly at 1
806        {
807            let (left, right) = outer.clone().split(1).unwrap();
808            let left_preimage = left.preimage.as_ref().expect("No preimage");
809            let right_preimage = right.preimage.as_ref().expect("No preimage");
810            assert_eq!(left.function, Function::Plain);
811            assert_eq!(left.data.as_ref(), b"C");
812            assert_eq!(left_preimage.len(), 1);
813            assert_eq!(left_preimage[0].data.as_ref(), b"C");
814            assert_eq!(left_preimage[0].preimage, None);
815            assert_eq!(right.function, Function::Plain);
816            assert_eq!(
817                right.data.as_ref(),
818                [inner_hash.as_slice(), b"D"].concat().as_slice()
819            );
820            assert_eq!(right_preimage.len(), 2);
821            assert_eq!(right_preimage[0].function, Function::Sha256);
822            assert_eq!(right_preimage[0].data.as_ref(), inner_hash.as_slice());
823            assert_eq!(right_preimage[1].function, Function::Plain);
824            assert_eq!(right_preimage[1].data.as_ref(), b"D");
825            let right_preimage2 = right_preimage[0].preimage.as_ref().expect("No preimage");
826            assert_eq!(right_preimage2[0].function, Function::Plain);
827            assert_eq!(right_preimage2[0].data.as_ref(), b"AB");
828            let right_preimage3 = right_preimage2[0].preimage.as_ref().expect("No preimage");
829            assert_eq!(right_preimage3[0].function, Function::Plain);
830            assert_eq!(right_preimage3[0].data.as_ref(), b"A");
831            assert_eq!(right_preimage3[0].preimage, None);
832            assert_eq!(right_preimage3[1].function, Function::Plain);
833            assert_eq!(right_preimage3[1].data.as_ref(), b"B");
834            assert_eq!(right_preimage3[1].preimage, None);
835        }
836
837        // test 2, split in middle of hash
838        {
839            let (left, right) = outer.clone().split(3).unwrap();
840            let left_preimage = left.preimage.as_ref().expect("No preimage");
841            let right_preimage = right.preimage.as_ref().expect("No preimage");
842            assert_eq!(left.function, Function::Plain);
843            assert_eq!(
844                left.data.as_ref(),
845                [b"C", &inner_hash[..2]].concat().as_slice()
846            );
847            assert_eq!(left_preimage.len(), 2);
848            assert_eq!(left_preimage[0].function, Function::Plain);
849            assert_eq!(left_preimage[0].data.as_ref(), b"C");
850            assert_eq!(left_preimage[0].preimage, None);
851            assert_eq!(left_preimage[1].function, Function::UnexpectedSplit);
852            assert_eq!(left_preimage[1].data.as_ref(), &inner_hash[..2]);
853            assert_eq!(left_preimage[1].preimage, None);
854            assert_eq!(right.function, Function::Plain);
855            assert_eq!(
856                right.data.as_ref(),
857                [&inner_hash[2..], b"D"].concat().as_slice()
858            );
859            assert_eq!(right_preimage[0].data.as_ref(), &inner_hash[2..]);
860            assert_eq!(right_preimage[0].preimage, None);
861            assert_eq!(right_preimage[1].data.as_ref(), b"D");
862            assert_eq!(right_preimage[1].preimage, None);
863        }
864
865        // test 3, split neatly after hash
866        {
867            let (left, right) = outer.clone().split(33).unwrap();
868            let left_preimage = left.preimage.as_ref().expect("No preimage");
869            let right_preimage = right.preimage.as_ref().expect("No preimage");
870            assert_eq!(left.function, Function::Plain);
871            assert_eq!(
872                left.data.as_ref(),
873                [b"C", inner_hash.as_slice()].concat().as_slice()
874            );
875            assert_eq!(left_preimage.len(), 2);
876            assert_eq!(left_preimage[0].function, Function::Plain);
877            assert_eq!(left_preimage[0].data.as_ref(), b"C");
878            assert_eq!(left_preimage[0].preimage, None);
879            assert_eq!(left_preimage[1].function, Function::Sha256);
880            assert_eq!(left_preimage[1].data.as_ref(), inner_hash.as_slice());
881            assert_eq!(&left_preimage[1], &inner_hashed);
882            assert_eq!(right.function, Function::Plain);
883            assert_eq!(right.data.as_ref(), b"D");
884            assert_eq!(right_preimage[0].data.as_ref(), b"D");
885            assert_eq!(right_preimage[0].preimage, None);
886        }
887    }
888}