dpp/identity/
core_script.rs1use bincode::de::{BorrowDecoder, Decoder};
2use bincode::enc::Encoder;
3use bincode::error::{DecodeError, EncodeError};
4use bincode::{BorrowDecode, Decode, Encode};
5use dashcore::blockdata::opcodes;
6use std::fmt;
7use std::ops::Deref;
8
9use dashcore::{ScriptBuf as DashcoreScript, ScriptBuf};
10use platform_value::string_encoding::{self, Encoding};
11use rand::rngs::StdRng;
12use rand::Rng;
13
14use serde::de::Visitor;
15use serde::{Deserialize, Serialize};
16
17use crate::ProtocolError;
18use bincode::de::read::Reader;
19
20#[derive(Clone, Debug, Eq, PartialEq, Default)]
21pub struct CoreScript(DashcoreScript);
22
23impl CoreScript {
24 pub fn new(script: DashcoreScript) -> Self {
25 CoreScript(script)
26 }
27
28 pub fn to_string(&self, encoding: Encoding) -> String {
29 string_encoding::encode(&self.0.to_bytes(), encoding)
30 }
31
32 pub fn from_string(encoded_value: &str, encoding: Encoding) -> Result<Self, ProtocolError> {
33 let vec = string_encoding::decode(encoded_value, encoding)?;
34
35 Ok(Self(vec.into()))
36 }
37
38 pub fn from_bytes(bytes: Vec<u8>) -> Self {
39 Self(bytes.into())
40 }
41
42 pub fn new_p2pkh(key_hash: [u8; 20]) -> Self {
43 let mut bytes: Vec<u8> = vec![
44 opcodes::all::OP_DUP.to_u8(),
45 opcodes::all::OP_HASH160.to_u8(),
46 opcodes::all::OP_PUSHBYTES_20.to_u8(),
47 ];
48 bytes.extend_from_slice(&key_hash);
49 bytes.push(opcodes::all::OP_EQUALVERIFY.to_u8());
50 bytes.push(opcodes::all::OP_CHECKSIG.to_u8());
51 Self::from_bytes(bytes)
52 }
53
54 pub fn new_p2sh(script_hash: [u8; 20]) -> Self {
55 let mut bytes = vec![
56 opcodes::all::OP_HASH160.to_u8(),
57 opcodes::all::OP_PUSHBYTES_20.to_u8(),
58 ];
59 bytes.extend_from_slice(&script_hash);
60 bytes.push(opcodes::all::OP_EQUAL.to_u8());
61 Self::from_bytes(bytes)
62 }
63
64 pub fn random_p2sh(rng: &mut StdRng) -> Self {
65 Self::new_p2sh(rng.gen())
66 }
67
68 pub fn random_p2pkh(rng: &mut StdRng) -> Self {
69 Self::new_p2pkh(rng.gen())
70 }
71}
72
73impl From<Vec<u8>> for CoreScript {
74 fn from(value: Vec<u8>) -> Self {
75 CoreScript::from_bytes(value)
76 }
77}
78
79impl Deref for CoreScript {
80 type Target = DashcoreScript;
81
82 fn deref(&self) -> &Self::Target {
83 &self.0
84 }
85}
86
87impl Encode for CoreScript {
89 fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
90 self.0.as_bytes().encode(encoder)
91 }
92}
93
94impl<C> Decode<C> for CoreScript {
96 fn decode<D: Decoder<Context = C>>(decoder: &mut D) -> Result<Self, DecodeError> {
97 let bytes = Vec::<u8>::decode(decoder)?;
98 Ok(CoreScript(ScriptBuf(bytes)))
100 }
101}
102
103impl<'de, C> BorrowDecode<'de, C> for CoreScript {
104 fn borrow_decode<D: BorrowDecoder<'de, Context = C>>(
105 decoder: &mut D,
106 ) -> Result<Self, DecodeError> {
107 let mut bytes = Vec::new();
109 loop {
110 let buf_len = 1024; let mut buf = vec![0; buf_len];
112
113 match decoder.reader().read(&mut buf) {
114 Ok(()) => {
115 let read_bytes = buf.iter().position(|&x| x == 0).unwrap_or(buf.len());
116 bytes.extend_from_slice(&buf[..read_bytes]);
117 if read_bytes < buf_len {
118 break;
119 }
120 }
121 Err(DecodeError::Io { inner, additional })
122 if inner.kind() == std::io::ErrorKind::UnexpectedEof =>
123 {
124 if additional > 0 {
125 return Err(DecodeError::Io { inner, additional });
126 } else {
127 break;
128 }
129 }
130 Err(e) => return Err(e),
131 }
132 }
133
134 let dash_core_script = DashcoreScript(bytes);
136
137 Ok(CoreScript(dash_core_script))
139 }
140}
141
142impl Serialize for CoreScript {
143 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
144 where
145 S: serde::Serializer,
146 {
147 if serializer.is_human_readable() {
148 serializer.serialize_str(&self.to_string(Encoding::Base64))
149 } else {
150 serializer.serialize_bytes(self.as_bytes())
151 }
152 }
153}
154
155impl<'de> Deserialize<'de> for CoreScript {
156 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
157 where
158 D: serde::Deserializer<'de>,
159 {
160 if deserializer.is_human_readable() {
161 let data: String = Deserialize::deserialize(deserializer)?;
162
163 Self::from_string(&data, Encoding::Base64).map_err(|e| {
164 serde::de::Error::custom(format!(
165 "expected to be able to deserialize core script from string: {}",
166 e
167 ))
168 })
169 } else {
170 struct BytesVisitor;
171
172 impl Visitor<'_> for BytesVisitor {
173 type Value = CoreScript;
174
175 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
176 formatter.write_str("a byte array")
177 }
178
179 fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
180 where
181 E: serde::de::Error,
182 {
183 Ok(CoreScript::from_bytes(v.to_vec()))
184 }
185 }
186
187 deserializer.deserialize_bytes(BytesVisitor)
188 }
189 }
190}
191
192impl std::fmt::Display for CoreScript {
193 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
194 write!(f, "{}", self.to_string(Encoding::Base64))
195 }
196}