brk_structs/structs/
addressbytes.rs

1use std::fmt;
2
3use bitcoin::{
4    Address, Network, ScriptBuf,
5    hex::{Case, DisplayHex},
6    opcodes,
7    script::Builder,
8};
9use brk_error::Error;
10use derive_deref::{Deref, DerefMut};
11use serde::{Serialize, Serializer};
12use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
13
14use super::OutputType;
15
16#[derive(Debug, PartialEq, Eq)]
17pub enum AddressBytes {
18    P2PK65(P2PK65Bytes),
19    P2PK33(P2PK33Bytes),
20    P2PKH(P2PKHBytes),
21    P2SH(P2SHBytes),
22    P2WPKH(P2WPKHBytes),
23    P2WSH(P2WSHBytes),
24    P2TR(P2TRBytes),
25    P2A(P2ABytes),
26}
27
28impl fmt::Display for AddressBytes {
29    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30        f.write_str(&match self {
31            AddressBytes::P2PK65(bytes) => bytes.to_string(),
32            AddressBytes::P2PK33(bytes) => bytes.to_string(),
33            AddressBytes::P2PKH(bytes) => bytes.to_string(),
34            AddressBytes::P2SH(bytes) => bytes.to_string(),
35            AddressBytes::P2WPKH(bytes) => bytes.to_string(),
36            AddressBytes::P2WSH(bytes) => bytes.to_string(),
37            AddressBytes::P2TR(bytes) => bytes.to_string(),
38            AddressBytes::P2A(bytes) => bytes.to_string(),
39        })
40    }
41}
42
43impl AddressBytes {
44    pub fn as_slice(&self) -> &[u8] {
45        match self {
46            AddressBytes::P2PK65(bytes) => &bytes[..],
47            AddressBytes::P2PK33(bytes) => &bytes[..],
48            AddressBytes::P2PKH(bytes) => &bytes[..],
49            AddressBytes::P2SH(bytes) => &bytes[..],
50            AddressBytes::P2WPKH(bytes) => &bytes[..],
51            AddressBytes::P2WSH(bytes) => &bytes[..],
52            AddressBytes::P2TR(bytes) => &bytes[..],
53            AddressBytes::P2A(bytes) => &bytes[..],
54        }
55    }
56}
57
58impl From<&Address> for AddressBytes {
59    fn from(value: &Address) -> Self {
60        Self::try_from((&value.script_pubkey(), OutputType::from(value))).unwrap()
61    }
62}
63
64impl TryFrom<(&ScriptBuf, OutputType)> for AddressBytes {
65    type Error = Error;
66    fn try_from(tuple: (&ScriptBuf, OutputType)) -> Result<Self, Self::Error> {
67        let (script, outputtype) = tuple;
68
69        match outputtype {
70            OutputType::P2PK65 => {
71                let bytes = script.as_bytes();
72                let bytes = match bytes.len() {
73                    67 => &bytes[1..66],
74                    _ => {
75                        dbg!(bytes);
76                        return Err(Error::WrongLength);
77                    }
78                };
79                Ok(Self::P2PK65(P2PK65Bytes(U8x65::from(bytes))))
80            }
81            OutputType::P2PK33 => {
82                let bytes = script.as_bytes();
83                let bytes = match bytes.len() {
84                    35 => &bytes[1..34],
85                    _ => {
86                        dbg!(bytes);
87                        return Err(Error::WrongLength);
88                    }
89                };
90                Ok(Self::P2PK33(P2PK33Bytes(U8x33::from(bytes))))
91            }
92            OutputType::P2PKH => {
93                let bytes = &script.as_bytes()[3..23];
94                Ok(Self::P2PKH(P2PKHBytes(U8x20::from(bytes))))
95            }
96            OutputType::P2SH => {
97                let bytes = &script.as_bytes()[2..22];
98                Ok(Self::P2SH(P2SHBytes(U8x20::from(bytes))))
99            }
100            OutputType::P2WPKH => {
101                let bytes = &script.as_bytes()[2..];
102                Ok(Self::P2WPKH(P2WPKHBytes(U8x20::from(bytes))))
103            }
104            OutputType::P2WSH => {
105                let bytes = &script.as_bytes()[2..];
106                Ok(Self::P2WSH(P2WSHBytes(U8x32::from(bytes))))
107            }
108            OutputType::P2TR => {
109                let bytes = &script.as_bytes()[2..];
110                Ok(Self::P2TR(P2TRBytes(U8x32::from(bytes))))
111            }
112            OutputType::P2A => {
113                let bytes = &script.as_bytes()[2..];
114                Ok(Self::P2A(P2ABytes(U8x2::from(bytes))))
115            }
116            OutputType::P2MS => Err(Error::WrongAddressType),
117            OutputType::Unknown => Err(Error::WrongAddressType),
118            OutputType::Empty => Err(Error::WrongAddressType),
119            OutputType::OpReturn => Err(Error::WrongAddressType),
120            _ => unreachable!(),
121        }
122    }
123}
124
125#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
126pub struct P2PK65Bytes(U8x65);
127
128impl fmt::Display for P2PK65Bytes {
129    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
130        write!(f, "{}", self.to_hex_string(Case::Lower))
131    }
132}
133
134impl Serialize for P2PK65Bytes {
135    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
136    where
137        S: Serializer,
138    {
139        serializer.collect_str(&self.to_string())
140    }
141}
142
143impl From<P2PK65Bytes> for AddressBytes {
144    fn from(value: P2PK65Bytes) -> Self {
145        Self::P2PK65(value)
146    }
147}
148
149#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
150pub struct P2PK33Bytes(U8x33);
151
152impl fmt::Display for P2PK33Bytes {
153    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
154        write!(f, "{}", self.to_hex_string(Case::Lower))
155    }
156}
157
158impl Serialize for P2PK33Bytes {
159    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
160    where
161        S: Serializer,
162    {
163        serializer.collect_str(&self.to_string())
164    }
165}
166
167impl From<P2PK33Bytes> for AddressBytes {
168    fn from(value: P2PK33Bytes) -> Self {
169        Self::P2PK33(value)
170    }
171}
172
173#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
174pub struct P2PKHBytes(U8x20);
175
176impl fmt::Display for P2PKHBytes {
177    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
178        let script = Builder::new()
179            .push_opcode(opcodes::all::OP_DUP)
180            .push_opcode(opcodes::all::OP_HASH160)
181            .push_slice(*self.0)
182            .push_opcode(opcodes::all::OP_EQUALVERIFY)
183            .push_opcode(opcodes::all::OP_CHECKSIG)
184            .into_script();
185        let address = Address::from_script(&script, Network::Bitcoin).unwrap();
186        write!(f, "{address}")
187    }
188}
189
190impl Serialize for P2PKHBytes {
191    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
192    where
193        S: Serializer,
194    {
195        serializer.collect_str(&self.to_string())
196    }
197}
198
199impl From<P2PKHBytes> for AddressBytes {
200    fn from(value: P2PKHBytes) -> Self {
201        Self::P2PKH(value)
202    }
203}
204
205#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
206pub struct P2SHBytes(U8x20);
207
208impl fmt::Display for P2SHBytes {
209    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
210        let script = Builder::new()
211            .push_opcode(opcodes::all::OP_HASH160)
212            .push_slice(*self.0)
213            .push_opcode(opcodes::all::OP_EQUAL)
214            .into_script();
215        let address = Address::from_script(&script, Network::Bitcoin).unwrap();
216        write!(f, "{address}")
217    }
218}
219
220impl Serialize for P2SHBytes {
221    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
222    where
223        S: Serializer,
224    {
225        serializer.collect_str(&self.to_string())
226    }
227}
228
229impl From<P2SHBytes> for AddressBytes {
230    fn from(value: P2SHBytes) -> Self {
231        Self::P2SH(value)
232    }
233}
234
235#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
236pub struct P2WPKHBytes(U8x20);
237
238impl fmt::Display for P2WPKHBytes {
239    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
240        let script = Builder::new().push_int(0).push_slice(*self.0).into_script();
241        let address = Address::from_script(&script, Network::Bitcoin).unwrap();
242        write!(f, "{address}")
243    }
244}
245
246impl Serialize for P2WPKHBytes {
247    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
248    where
249        S: Serializer,
250    {
251        serializer.collect_str(&self.to_string())
252    }
253}
254
255impl From<P2WPKHBytes> for AddressBytes {
256    fn from(value: P2WPKHBytes) -> Self {
257        Self::P2WPKH(value)
258    }
259}
260
261#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
262pub struct P2WSHBytes(U8x32);
263
264impl fmt::Display for P2WSHBytes {
265    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
266        let script = Builder::new().push_int(0).push_slice(*self.0).into_script();
267        let address = Address::from_script(&script, Network::Bitcoin).unwrap();
268        write!(f, "{address}")
269    }
270}
271
272impl Serialize for P2WSHBytes {
273    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
274    where
275        S: Serializer,
276    {
277        serializer.collect_str(&self.to_string())
278    }
279}
280
281impl From<P2WSHBytes> for AddressBytes {
282    fn from(value: P2WSHBytes) -> Self {
283        Self::P2WSH(value)
284    }
285}
286
287#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
288pub struct P2TRBytes(U8x32);
289
290impl fmt::Display for P2TRBytes {
291    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
292        let script = Builder::new().push_int(1).push_slice(*self.0).into_script();
293        let address = Address::from_script(&script, Network::Bitcoin).unwrap();
294        write!(f, "{address}")
295    }
296}
297
298impl Serialize for P2TRBytes {
299    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
300    where
301        S: Serializer,
302    {
303        serializer.collect_str(&self.to_string())
304    }
305}
306
307impl From<P2TRBytes> for AddressBytes {
308    fn from(value: P2TRBytes) -> Self {
309        Self::P2TR(value)
310    }
311}
312
313#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
314pub struct P2ABytes(U8x2);
315
316impl fmt::Display for P2ABytes {
317    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
318        let script = Builder::new().push_int(1).push_slice(*self.0).into_script();
319        let address = Address::from_script(&script, Network::Bitcoin).unwrap();
320        write!(f, "{address}")
321    }
322}
323
324impl Serialize for P2ABytes {
325    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
326    where
327        S: Serializer,
328    {
329        serializer.collect_str(&self.to_string())
330    }
331}
332
333impl From<P2ABytes> for AddressBytes {
334    fn from(value: P2ABytes) -> Self {
335        Self::P2A(value)
336    }
337}
338
339#[derive(
340    Debug,
341    Clone,
342    Deref,
343    DerefMut,
344    PartialEq,
345    Eq,
346    Immutable,
347    IntoBytes,
348    KnownLayout,
349    FromBytes,
350    Serialize,
351)]
352pub struct U8x2([u8; 2]);
353impl From<&[u8]> for U8x2 {
354    fn from(slice: &[u8]) -> Self {
355        let mut arr = [0; 2];
356        arr.copy_from_slice(slice);
357        Self(arr)
358    }
359}
360
361#[derive(
362    Debug,
363    Clone,
364    Deref,
365    DerefMut,
366    PartialEq,
367    Eq,
368    Immutable,
369    IntoBytes,
370    KnownLayout,
371    FromBytes,
372    Serialize,
373)]
374pub struct U8x20([u8; 20]);
375impl From<&[u8]> for U8x20 {
376    fn from(slice: &[u8]) -> Self {
377        let mut arr = [0; 20];
378        arr.copy_from_slice(slice);
379        Self(arr)
380    }
381}
382
383#[derive(
384    Debug,
385    Clone,
386    Deref,
387    DerefMut,
388    PartialEq,
389    Eq,
390    Immutable,
391    IntoBytes,
392    KnownLayout,
393    FromBytes,
394    Serialize,
395)]
396pub struct U8x32([u8; 32]);
397impl From<&[u8]> for U8x32 {
398    fn from(slice: &[u8]) -> Self {
399        let mut arr = [0; 32];
400        arr.copy_from_slice(slice);
401        Self(arr)
402    }
403}
404
405#[derive(
406    Debug,
407    Clone,
408    Deref,
409    DerefMut,
410    PartialEq,
411    Eq,
412    Immutable,
413    IntoBytes,
414    KnownLayout,
415    FromBytes,
416    Serialize,
417)]
418pub struct U8x33(#[serde(with = "serde_bytes")] [u8; 33]);
419impl From<&[u8]> for U8x33 {
420    fn from(slice: &[u8]) -> Self {
421        let mut arr = [0; 33];
422        arr.copy_from_slice(slice);
423        Self(arr)
424    }
425}
426
427#[derive(
428    Debug,
429    Clone,
430    Deref,
431    DerefMut,
432    PartialEq,
433    Eq,
434    Immutable,
435    IntoBytes,
436    KnownLayout,
437    FromBytes,
438    Serialize,
439)]
440pub struct U8x64(#[serde(with = "serde_bytes")] [u8; 64]);
441impl From<&[u8]> for U8x64 {
442    fn from(slice: &[u8]) -> Self {
443        let mut arr = [0; 64];
444        arr.copy_from_slice(slice);
445        Self(arr)
446    }
447}
448
449#[derive(
450    Debug,
451    Clone,
452    Deref,
453    DerefMut,
454    PartialEq,
455    Eq,
456    Immutable,
457    IntoBytes,
458    KnownLayout,
459    FromBytes,
460    Serialize,
461)]
462pub struct U8x65(#[serde(with = "serde_bytes")] [u8; 65]);
463impl From<&[u8]> for U8x65 {
464    fn from(slice: &[u8]) -> Self {
465        let mut arr = [0; 65];
466        arr.copy_from_slice(slice);
467        Self(arr)
468    }
469}