avalanche_types/txs/
raw.rs

1use std::{
2    cmp::Ordering,
3    hash::{Hash, Hasher},
4};
5
6use crate::hash;
7use serde::{self, Deserialize, Serialize};
8
9/// Represents raw transaction bytes.
10/// ref. <https://pkg.go.dev/github.com/ava-labs/avalanchego/snow/engine/avalanche/vertex#SortHashOf>
11/// ref. <https://docs.rs/zerocopy/latest/zerocopy/trait.AsBytes.html#safety>
12#[derive(Debug, Clone, Deserialize, Serialize, Eq)]
13#[repr(transparent)]
14#[derive(Default)]
15pub struct Data(Vec<u8>);
16
17impl Data {
18    pub fn from_slice(d: &[u8]) -> Self {
19        Data(Vec::from(d))
20    }
21}
22
23impl AsRef<[u8]> for Data {
24    fn as_ref(&self) -> &[u8] {
25        &self.0
26    }
27}
28
29impl Ord for Data {
30    fn cmp(&self, other: &Data) -> Ordering {
31        let h1 = hash::sha256(&self.0);
32        let h2 = hash::sha256(&other.0);
33        h1.cmp(&(h2))
34    }
35}
36
37impl PartialOrd for Data {
38    fn partial_cmp(&self, other: &Data) -> Option<Ordering> {
39        Some(self.cmp(other))
40    }
41}
42
43impl PartialEq for Data {
44    fn eq(&self, other: &Data) -> bool {
45        self.cmp(other) == Ordering::Equal
46    }
47}
48
49/// ref. <https://rust-lang.github.io/rust-clippy/master/index.html#derive_hash_xor_eq>
50impl Hash for Data {
51    fn hash<H: Hasher>(&self, state: &mut H) {
52        self.0.hash(state);
53    }
54}
55
56/// Represents a slice of raw transaction bytes, to be sorted
57/// in the order of SHA256 hash digests.
58#[derive(Eq)]
59pub struct DataSlice(Vec<Data>);
60
61impl DataSlice {
62    pub fn new(txs: &[Data]) -> Self {
63        DataSlice(Vec::from(txs))
64    }
65}
66
67impl Ord for DataSlice {
68    fn cmp(&self, other: &DataSlice) -> Ordering {
69        self.0.cmp(&other.0)
70    }
71}
72
73impl PartialOrd for DataSlice {
74    fn partial_cmp(&self, other: &DataSlice) -> Option<Ordering> {
75        Some(self.cmp(other))
76    }
77}
78
79impl PartialEq for DataSlice {
80    fn eq(&self, other: &DataSlice) -> bool {
81        self.cmp(other) == Ordering::Equal
82    }
83}
84
85/// RUST_LOG=debug cargo test --package avalanche-types --lib -- txs::raw::test_sort --exact --show-output
86#[test]
87fn test_sort() {
88    let d1 = <Vec<u8>>::from([0x01, 0x00, 0x00, 0x00]);
89    let d2 = <Vec<u8>>::from([0x01, 0x00, 0x00, 0x00]);
90    assert!(d1 == d2);
91
92    let d1 = <Vec<u8>>::from([0x01, 0x00, 0x00, 0x00]);
93    let d2 = <Vec<u8>>::from([0x01, 0x00, 0x00, 0x00, 0x00]);
94    assert!(d1 < d2);
95
96    let d1 = Data(<Vec<u8>>::from([0x01, 0x00, 0x00, 0x00]));
97    let d2 = Data(<Vec<u8>>::from([0x01, 0x00, 0x00, 0x00, 0x00]));
98    assert!(d1 < d2);
99
100    let d1 = Data(<Vec<u8>>::from([0x99, 0x00, 0x00, 0x00]));
101    let d2 = Data(<Vec<u8>>::from([0x99, 0x00, 0x00, 0x00, 0x00]));
102    assert!(d1 < d2);
103
104    let d1 = Data(<Vec<u8>>::from([0x99, 0x00, 0x00]));
105    let d2 = Data(<Vec<u8>>::from([0x99, 0x00, 0x01]));
106    assert!(d1 < d2);
107
108    let d1 = Data(<Vec<u8>>::from([0x99, 0x01, 0x01]));
109    let d2 = Data(<Vec<u8>>::from([0x99, 0x20, 0x01]));
110    assert!(d1 > d2);
111
112    let d1 = Data(<Vec<u8>>::from([0x01]));
113    let d2 = Data(<Vec<u8>>::from([0x02]));
114    let d3 = Data(<Vec<u8>>::from([0x03]));
115    assert!(d1 < d2);
116    assert!(d2 > d3);
117    assert!(d1 > d3);
118
119    let mut ds1 = DataSlice(vec![
120        Data(<Vec<u8>>::from([0x01])),
121        Data(<Vec<u8>>::from([0x02])),
122        Data(<Vec<u8>>::from([0x03])),
123    ]);
124    ds1.0.sort();
125    let ds2 = DataSlice(vec![
126        Data(<Vec<u8>>::from([0x03])),
127        Data(<Vec<u8>>::from([0x01])),
128        Data(<Vec<u8>>::from([0x02])),
129    ]);
130    assert!(ds1 == ds2);
131
132    let mut ds1 = vec![
133        Data(<Vec<u8>>::from([0x01])),
134        Data(<Vec<u8>>::from([0x02])),
135        Data(<Vec<u8>>::from([0x03])),
136    ];
137    ds1.sort();
138    let ds2 = vec![
139        Data(<Vec<u8>>::from([0x03])),
140        Data(<Vec<u8>>::from([0x01])),
141        Data(<Vec<u8>>::from([0x02])),
142    ];
143    assert!(ds1 == ds2);
144
145    let mut ds1 = vec![
146        <Vec<u8>>::from([0x01]),
147        <Vec<u8>>::from([0x02]),
148        <Vec<u8>>::from([0x03]),
149    ];
150    ds1.sort_by(|a, b| (Data::from_slice(a.as_ref())).cmp(&Data::from_slice(b.as_ref())));
151    let ds2 = vec![
152        <Vec<u8>>::from([0x03]),
153        <Vec<u8>>::from([0x01]),
154        <Vec<u8>>::from([0x02]),
155    ];
156    assert!(ds1 == ds2);
157}