1use borsh::{BorshDeserialize, BorshSerialize};
2use wasm_bindgen::JsValue;
3use workflow_core::sendable::Sendable;
4
5pub mod int;
6pub mod uint;
7pub mod wasm;
8
9construct_uint!(Uint192, 3, BorshSerialize, BorshDeserialize);
10construct_uint!(Uint256, 4);
11construct_uint!(Uint320, 5);
12construct_uint!(Uint3072, 48);
13
14#[derive(thiserror::Error, Debug)]
15pub enum Error {
16 #[error("{0:?}")]
17 JsValue(Sendable<JsValue>),
18
19 #[error("Invalid hex string: {0}")]
20 Hex(#[from] faster_hex::Error),
21
22 #[error(transparent)]
23 TryFromSliceError(#[from] uint::TryFromSliceError),
24 #[error("Utf8 error: {0}")]
26 Utf8(#[from] std::str::Utf8Error),
27
28 #[error(transparent)]
29 WorkflowWasm(#[from] workflow_wasm::error::Error),
30
31 #[error(transparent)]
32 SerdeWasmBindgen(#[from] serde_wasm_bindgen::Error),
33
34 #[error("{0:?}")]
35 JsSys(Sendable<js_sys::Error>),
36
37 #[error("Supplied value is not compatible with this type")]
38 NotCompatible,
39
40 #[error("range error: {0:?}")]
41 Range(Sendable<js_sys::RangeError>),
42}
43
44impl From<js_sys::Error> for Error {
45 fn from(err: js_sys::Error) -> Self {
46 Error::JsSys(Sendable(err))
47 }
48}
49
50impl From<js_sys::RangeError> for Error {
51 fn from(err: js_sys::RangeError) -> Self {
52 Error::Range(Sendable(err))
53 }
54}
55
56impl From<JsValue> for Error {
57 fn from(err: JsValue) -> Self {
58 Error::JsValue(Sendable(err))
59 }
60}
61
62impl Uint256 {
63 #[inline]
64 pub fn from_compact_target_bits(bits: u32) -> Self {
65 let (mant, expt) = {
70 let unshifted_expt = bits >> 24;
71 if unshifted_expt <= 3 {
72 ((bits & 0xFFFFFF) >> (8 * (3 - unshifted_expt)), 0)
73 } else {
74 (bits & 0xFFFFFF, 8 * ((bits >> 24) - 3))
75 }
76 };
77 if mant > 0x7FFFFF {
79 Uint256::ZERO
80 } else {
81 Uint256::from_u64(u64::from(mant)) << expt
82 }
83 }
84
85 #[inline]
86 pub fn compact_target_bits(self) -> u32 {
88 let mut size = (self.bits() + 7) / 8;
89 let mut compact = if size <= 3 {
90 (self.as_u64() << (8 * (3 - size))) as u32
91 } else {
92 let bn = self >> (8 * (size - 3));
93 bn.as_u64() as u32
94 };
95
96 if (compact & 0x00800000) != 0 {
97 compact >>= 8;
98 size += 1;
99 }
100 compact | (size << 24)
101 }
102}
103
104impl From<Uint256> for Uint320 {
105 #[inline]
106 fn from(u: Uint256) -> Self {
107 let mut result = Uint320::ZERO;
108 result.0[..4].copy_from_slice(&u.0);
109 result
110 }
111}
112
113impl TryFrom<Uint320> for Uint256 {
114 type Error = crate::uint::TryFromIntError;
115
116 #[inline]
117 fn try_from(value: Uint320) -> Result<Self, Self::Error> {
118 if value.0[4] != 0 {
119 Err(crate::uint::TryFromIntError)
120 } else {
121 let mut result = Uint256::ZERO;
122 result.0.copy_from_slice(&value.0[..4]);
123 Ok(result)
124 }
125 }
126}
127
128impl TryFrom<Uint256> for Uint192 {
129 type Error = crate::uint::TryFromIntError;
130
131 #[inline]
132 fn try_from(value: Uint256) -> Result<Self, Self::Error> {
133 if value.0[3] != 0 {
134 Err(crate::uint::TryFromIntError)
135 } else {
136 let mut result = Uint192::ZERO;
137 result.0.copy_from_slice(&value.0[..3]);
138 Ok(result)
139 }
140 }
141}
142
143#[cfg(test)]
144mod tests {
145 use crate::{Uint256, Uint3072};
146
147 #[test]
148 fn test_overflow_bug() {
149 let a = Uint256::from_le_bytes([
150 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
151 255, 255,
152 ]);
153 let b = Uint256::from_le_bytes([
154 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 71, 33, 0, 0, 0, 0, 0, 0,
155 0, 32, 0, 0, 0,
156 ]);
157 let c = a.overflowing_add(b).0;
158 let expected = [254, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 71, 33, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0];
159 assert_eq!(c.to_le_bytes(), expected);
160 }
161 #[rustfmt::skip]
162 #[test]
163 fn div_rem_u3072_bug() {
164 let r = Uint3072([
165 18446744073708447899, 18446744069733351423, 18446744073709551615, 18446744073709551615,
166 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615,
167 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615,
168 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615,
169 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615,
170 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615,
171 18446744073709551615, 18446744073642442751, 18446744073709551615, 18446744073709551615,
172 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615,
173 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615,
174 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615,
175 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615,
176 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615,
177 ]);
178 let newr = Uint3072([
179 0, 3976200192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
180 0, 67108864, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
181 ]);
182 let expected = Uint3072([
183 18446744073709551614, 18446744073709551615, 18446744073709551615, 18446744073709551615,
184 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615,
185 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615,
186 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615,
187 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615,
188 18446744073709551615, 18446744073709551615, 274877906943, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
189 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
190 ]);
191 assert_eq!(r / newr, expected);
192 }
193}