1use crate::*;
2use core::ops::*;
3
4impl From<SHA256Hash> for StorageKey {
5 fn from(hash: SHA256Hash) -> Self {
6 Self::ContractData {
7 contract_data_key: hash.into_inner().into(),
8 }
9 }
10}
11
12impl From<SHA256Hash> for StorageKeyContractData {
13 fn from(hash: SHA256Hash) -> Self {
14 hash.into_inner().into()
15 }
16}
17
18impl From<ContractAddress> for StorageKeyContractData {
19 fn from(addr: ContractAddress) -> Self {
20 addr.into_inner().into()
21 }
22}
23
24impl From<SHA256Hash> for ContractAddress {
25 fn from(hash: SHA256Hash) -> Self {
26 hash.into_inner().into()
27 }
28}
29
30impl BitXor for SHA256Hash {
31 type Output = Self;
32
33 fn bitxor(mut self, rhs: Self) -> Self::Output {
34 self ^= &rhs.into_inner();
35
36 self
37 }
38}
39
40impl BitXor<&Self> for SHA256Hash {
41 type Output = Self;
42
43 fn bitxor(mut self, rhs: &Self) -> Self::Output {
44 let rhs: &[u8; 32] = rhs;
45
46 self ^= rhs;
47
48 self
49 }
50}
51
52impl BitXorAssign<&[u8; 32]> for SHA256Hash {
53 fn bitxor_assign(&mut self, rhs: &[u8; 32]) {
54 bitxor_assign_bytes(&mut *self, rhs);
55 }
56}
57
58impl BitXor for StorageKeyContractData {
59 type Output = Self;
60
61 fn bitxor(mut self, rhs: Self) -> Self::Output {
62 self ^= &rhs.into_inner();
63
64 self
65 }
66}
67
68impl BitXor<&Self> for StorageKeyContractData {
69 type Output = Self;
70
71 fn bitxor(mut self, rhs: &Self) -> Self::Output {
72 let rhs: &[u8; 32] = rhs;
73
74 self ^= rhs;
75
76 self
77 }
78}
79
80impl BitXorAssign<&[u8; 32]> for StorageKeyContractData {
81 fn bitxor_assign(&mut self, rhs: &[u8; 32]) {
82 bitxor_assign_bytes(&mut *self, rhs);
83 }
84}
85
86fn bitxor_assign_bytes<const N: usize>(lhs: &mut [u8; N], rhs: &[u8; N]) {
87 let (lchunks, []) = lhs.as_chunks_mut::<4>() else {
88 unreachable!()
89 };
90 let (rchunks, []) = rhs.as_chunks::<4>() else {
91 unreachable!()
92 };
93 lchunks
94 .iter_mut()
95 .zip(rchunks.iter())
96 .for_each(|(lbytes, rbytes)| {
97 let l = u32::from_le_bytes(*lbytes);
98 let r = u32::from_le_bytes(*rbytes);
99 *lbytes = (l ^ r).to_le_bytes();
100 });
101}
102
103impl Default for Ed25519Signature {
105 fn default() -> Self {
106 Self::from([0; 64])
107 }
108}
109
110impl Default for Signature {
111 fn default() -> Self {
112 Signature::Ed25519 {
113 ed25519: Ed25519Signature::default(),
114 }
115 }
116}
117
118impl Default for StorageKey {
119 fn default() -> Self {
120 Self::ContractData {
121 contract_data_key: StorageKeyContractData::default(),
122 }
123 }
124}
125
126impl ContractAddress {
127 pub const fn zero() -> Self {
130 Self::new([0; 32])
131 }
132}
133
134macro_rules! base58_debug {
137 ($($t:ty),+ $(,)?) => {$(
138 impl core::fmt::Debug for $t {
139 fn fmt(
140 &self,
141 f: &mut core::fmt::Formatter<'_>,
142 ) -> core::fmt::Result {
143 write!(f, "{}", crate::base58::base58_encode(self))
144 }
145 }
146 )+};
147}
148
149base58_debug!(ContractAddress, SHA256Hash);
150
151macro_rules! redacted_debug {
155 ($($t:ident),+ $(,)?) => {$(
156 impl core::fmt::Debug for $t {
157 fn fmt(
158 &self,
159 f: &mut core::fmt::Formatter<'_>,
160 ) -> core::fmt::Result {
161 f.write_str(concat!(stringify!($t), "(<redacted>)"))
162 }
163 }
164 )+};
165}
166
167redacted_debug!(Ed25519SecretKey, MlDsa65SecretKey);
168
169impl ContractEntrypointID {
170 pub const fn from_u64(n: u64) -> Self {
173 Self::new(n.to_be_bytes())
174 }
175
176 pub fn into_u64(self) -> u64 {
179 u64::from_be_bytes(self.into_inner())
180 }
181}
182
183impl From<uint128_xdr> for u128 {
184 fn from(u: uint128_xdr) -> Self {
185 ((u.highbits as u128) << 64) | (u.lowbits as u128)
186 }
187}
188
189impl From<u128> for uint128_xdr {
190 fn from(n: u128) -> Self {
191 uint128_xdr {
192 lowbits: (n & 0xffff_ffff_ffff_ffff) as u64,
193 highbits: (n >> 64) as u64,
194 }
195 }
196}
197
198impl From<int128_xdr> for i128 {
199 fn from(i: int128_xdr) -> Self {
200 ((i.highbits as i128) << 64) | (i.lowbits as i128)
201 }
202}
203
204impl From<i128> for int128_xdr {
205 fn from(n: i128) -> Self {
206 int128_xdr {
207 lowbits: (n & 0xffff_ffff_ffff_ffff) as u64,
208 highbits: (n >> 64) as i64,
209 }
210 }
211}
212
213impl Default for StorageLongHash {
214 fn default() -> Self {
215 Self::new([0; 2048])
216 }
217}
218
219#[cfg(test)]
220mod xor_test {
221 use super::*;
222 use std::vec::Vec;
223
224 #[test]
225 fn sk_bit_xor() {
226 let l: Vec<u8> = (0..32).collect();
227 let l: &[u8; 32] = l.as_slice().try_into().unwrap();
228 let l: StorageKeyContractData = (*l).into();
229
230 let rv: Vec<u8> = (107..139).rev().collect();
231 let rs: &[u8; 32] = rv.as_slice().try_into().unwrap();
232 let r: StorageKeyContractData = (*rs).into();
233
234 let expected = xor_arrays(&l, &r);
235
236 let x: StorageKeyContractData = l ^ r;
237 assert_eq!(*x, expected);
238
239 #[allow(clippy::op_ref)]
241 let x: StorageKeyContractData = l ^ &r;
242 assert_eq!(*x, expected);
243
244 let mut x: StorageKeyContractData = l;
245 x ^= rs;
246 assert_eq!(*x, expected);
247 }
248
249 fn xor_arrays(a: &[u8; 32], b: &[u8; 32]) -> [u8; 32] {
250 let out: Vec<_> =
251 a.iter().zip(b.iter()).map(|(a, b)| *a ^ *b).collect();
252 let out: &[u8; 32] = out.as_slice().try_into().unwrap();
253 *out
254 }
255}