stacks_core/
uint.rs

1use std::{
2	cmp::Ordering,
3	fmt, io,
4	mem::transmute,
5	ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Not, Shl, Shr, Sub},
6};
7
8use serde::{Deserialize, Serialize};
9
10use crate::{
11	codec::Codec,
12	crypto::{
13		sha256::{DoubleSha256Hasher, SHA256_LENGTH},
14		Hashing,
15	},
16	StacksError, StacksResult,
17};
18
19/// A structure that represents large integers and provides basic arithmetic.
20/// It accepts a const generic `N` which controls the number of u64s used to
21/// represent the number.
22#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Copy)]
23#[serde(try_from = "Vec<u64>")]
24#[serde(into = "Vec<u64>")]
25#[repr(C)]
26pub struct Uint<const N: usize>([u64; N]);
27
28impl<const N: usize> Uint<N> {
29	/// The maximum value that can be represented by this type
30	pub const MAX: Self = Self([0xffffffffffffffff; N]);
31	/// The minimum value that can be represented by this type
32	pub const MIN: Self = Self([0; N]);
33
34	/// Build a Uint from a u64 array
35	pub fn from_u64_array(data: [u64; N]) -> Self {
36		Self(data)
37	}
38
39	/// Conversion to u32
40	pub fn low_u32(&self) -> u32 {
41		self.0[0] as u32
42	}
43
44	/// Conversion to u64
45	pub fn low_u64(&self) -> u64 {
46		self.0[0]
47	}
48
49	/// Return the least number of bits needed to represent the number
50	pub fn bits(&self) -> usize {
51		for i in 1..N {
52			if self.0[N - i] > 0 {
53				return (0x40 * (N - i + 1))
54					- self.0[N - i].leading_zeros() as usize;
55			}
56		}
57
58		0x40 - self.0[0].leading_zeros() as usize
59	}
60
61	/// Multiply by a u32
62	pub fn mul_u32(self, other: u32) -> Self {
63		let mut carry = [0u64; N];
64		let mut ret = [0u64; N];
65
66		for i in 0..N {
67			let not_last_word = i < N - 1;
68			let upper = other as u64 * (self.0[i] >> 32);
69			let lower = other as u64 * (self.0[i] & 0xFFFFFFFF);
70
71			if not_last_word {
72				carry[i + 1] += upper >> 32;
73			}
74
75			let (sum, overflow) = lower.overflowing_add(upper << 32);
76			ret[i] = sum;
77
78			if overflow && not_last_word {
79				carry[i + 1] += 1;
80			}
81		}
82
83		Self(ret) + Self(carry)
84	}
85
86	/// To litte-endian byte array
87	pub fn to_le_bytes(&self) -> Vec<u8> {
88		let mut buffer = vec![0; N * 8];
89
90		self.0
91			.iter()
92			.flat_map(|part| part.to_le_bytes())
93			.enumerate()
94			.for_each(|(i, byte)| buffer[i] = byte);
95
96		buffer
97	}
98
99	/// To big-endian byte array
100	pub fn to_be_bytes(&self) -> Vec<u8> {
101		let mut ret = vec![0; N * 8];
102
103		for i in 0..N {
104			let word_end = N * 8 - (i * 8);
105			let word_start = word_end - 8;
106
107			ret[word_start..word_end].copy_from_slice(&self.0[i].to_be_bytes());
108		}
109
110		ret
111	}
112
113	/// Build from a little-endian hex string (padding expected)
114	pub fn from_le_bytes(bytes: impl AsRef<[u8]>) -> StacksResult<Self> {
115		let bytes = bytes.as_ref();
116
117		if bytes.len() % 8 != 0 {
118			return Err(StacksError::InvalidUintBytes(bytes.len()));
119		}
120
121		if bytes.len() / 8 != N {
122			return Err(StacksError::InvalidUintBytes(bytes.len()));
123		}
124
125		let mut ret = [0u64; N];
126		for i in 0..(bytes.len() / 8) {
127			let mut next_bytes = [0u8; 8];
128			next_bytes.copy_from_slice(&bytes[8 * i..(8 * (i + 1))]);
129
130			let next = u64::from_le_bytes(next_bytes);
131
132			ret[i] = next;
133		}
134
135		Ok(Self(ret))
136	}
137
138	/// Build from a big-endian hex string (padding expected)
139	pub fn from_be_bytes(bytes: impl AsRef<[u8]>) -> StacksResult<Self> {
140		let bytes = bytes.as_ref();
141
142		if bytes.len() % 8 != 0 {
143			return Err(StacksError::InvalidUintBytes(bytes.len()));
144		}
145
146		if bytes.len() / 8 != N {
147			return Err(StacksError::InvalidUintBytes(bytes.len()));
148		}
149
150		let mut ret = [0u64; N];
151		for i in 0..(bytes.len() / 8) {
152			let mut next_bytes = [0u8; 8];
153			next_bytes.copy_from_slice(&bytes[8 * i..(8 * (i + 1))]);
154
155			let next = u64::from_be_bytes(next_bytes);
156
157			ret[(bytes.len() / 8) - 1 - i] = next;
158		}
159
160		Ok(Self(ret))
161	}
162
163	/// Convert to a little-endian hex string
164	pub fn to_le_hex(&self) -> String {
165		hex::encode(self.to_le_bytes())
166	}
167
168	/// Convert to a big-endian hex string
169	pub fn to_be_hex(&self) -> String {
170		hex::encode(self.to_be_bytes())
171	}
172
173	/// Build from a little-endian hex string
174	pub fn from_le_hex(data: impl AsRef<str>) -> StacksResult<Self> {
175		Self::from_le_bytes(hex::decode(data.as_ref())?)
176	}
177
178	/// Build from a big-endian hex string
179	pub fn from_be_hex(data: impl AsRef<str>) -> StacksResult<Self> {
180		Self::from_be_bytes(hex::decode(data.as_ref())?)
181	}
182
183	/// Wrapping add by one operation
184	pub fn increment(&mut self) {
185		let &mut Uint(ref mut arr) = self;
186
187		for item in arr.iter_mut().take(N) {
188			*item = item.wrapping_add(1);
189
190			if *item != 0 {
191				break;
192			}
193		}
194	}
195
196	/// Create a new Uint from the provided Uint
197	pub fn from_uint<const M: usize>(source: impl AsRef<Uint<M>>) -> Self {
198		assert!(M < N, "Cannot convert larger Uint to smaller");
199
200		let source = source.as_ref();
201		let mut dest = [0u64; N];
202
203		dest[..M].copy_from_slice(&source.0[..M]);
204
205		Uint(dest)
206	}
207
208	/// Create a new Uint from the provided Uint, truncating if necessary
209	pub fn from_uint_lossy<const M: usize>(
210		source: impl AsRef<Uint<M>>,
211	) -> Self {
212		let source = source.as_ref();
213		let mut dest = [0u64; N];
214		let bytes_shared = M.min(N);
215
216		dest[..bytes_shared].copy_from_slice(&source.0[..bytes_shared]);
217
218		Uint(dest)
219	}
220
221	/// Convert to a smaller Uint
222	pub fn to_uint<const M: usize>(&self) -> Uint<M> {
223		assert!(M >= N, "Cannot convert larger Uint to smaller");
224
225		let mut dest = [0u64; M];
226
227		dest[..M].copy_from_slice(&self.0[..M]);
228
229		Uint(dest)
230	}
231
232	/// Convert to a smaller Uint, truncating if necessary
233	pub fn to_uint_lossy<const M: usize>(&self) -> Uint<M> {
234		let mut dest = [0u64; M];
235		let bytes_shared = M.min(N);
236
237		dest[..bytes_shared].copy_from_slice(&self.0[..bytes_shared]);
238
239		Uint(dest)
240	}
241
242	fn one() -> Self {
243		let mut ret = [0; N];
244		ret[0] = 1;
245
246		Uint(ret)
247	}
248}
249
250impl<const N: usize> Add<Uint<N>> for Uint<N> {
251	type Output = Self;
252
253	fn add(self, other: Self) -> Self {
254		let Self(ref me) = self;
255		let Self(ref you) = other;
256
257		let mut ret = [0u64; N];
258		let mut carry = [0u64; N];
259		let mut b_carry = false;
260
261		for i in 0..N {
262			ret[i] = me[i].wrapping_add(you[i]);
263			if i < N - 1 && ret[i] < me[i] {
264				carry[i + 1] = 1;
265				b_carry = true;
266			}
267		}
268
269		if b_carry {
270			Self(ret) + Self(carry)
271		} else {
272			Self(ret)
273		}
274	}
275}
276
277impl<const N: usize> Sub<Uint<N>> for Uint<N> {
278	type Output = Self;
279
280	fn sub(self, other: Self) -> Self {
281		self + !other + Self::one()
282	}
283}
284
285impl<const N: usize> Mul<Uint<N>> for Uint<N> {
286	type Output = Self;
287
288	fn mul(self, other: Self) -> Self {
289		let mut me = Self::MIN;
290
291		for i in 0..(2 * N) {
292			let to_mul = (other >> (32 * i)).low_u32();
293			me = me + (self.mul_u32(to_mul) << (32 * i));
294		}
295		me
296	}
297}
298
299impl<const N: usize> Div<Uint<N>> for Uint<N> {
300	type Output = Self;
301
302	fn div(self, other: Self) -> Self {
303		let mut sub_copy = self;
304		let mut shift_copy = other;
305		let mut ret = [0u64; N];
306
307		let my_bits = self.bits();
308		let your_bits = other.bits();
309
310		// Check for division by 0
311		assert!(your_bits != 0);
312
313		// Early return in case we are dividing by a larger number than us
314		if my_bits < your_bits {
315			return Self(ret);
316		}
317
318		// Bitwise long division
319		let mut shift = my_bits - your_bits;
320		shift_copy = shift_copy << shift;
321
322		loop {
323			if sub_copy >= shift_copy {
324				ret[shift / 64] |= 1 << (shift % 64);
325				sub_copy = sub_copy - shift_copy;
326			}
327			shift_copy = shift_copy >> 1;
328
329			if shift == 0 {
330				break;
331			}
332
333			shift -= 1;
334		}
335
336		Self(ret)
337	}
338}
339
340impl<const N: usize> Ord for Uint<N> {
341	fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
342		// manually implement comparison to get little-endian ordering
343		// (we need this for our numeric types; non-numeric ones shouldn't
344		// be ordered anyway except to put them in BTrees or whatever, and
345		// they don't care how we order as long as we're consisistent).
346		for i in 0..N {
347			if self.0[N - 1 - i] < other.0[N - 1 - i] {
348				return Ordering::Less;
349			}
350
351			if self.0[N - 1 - i] > other.0[N - 1 - i] {
352				return Ordering::Greater;
353			}
354		}
355
356		Ordering::Equal
357	}
358}
359
360impl<const N: usize> PartialOrd for Uint<N> {
361	fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
362		Some(self.cmp(other))
363	}
364}
365
366impl<const N: usize> Default for Uint<N> {
367	fn default() -> Self {
368		Self::MIN
369	}
370}
371
372impl<const N: usize> BitAnd<Uint<N>> for Uint<N> {
373	type Output = Uint<N>;
374
375	fn bitand(self, other: Uint<N>) -> Self {
376		let Uint(ref arr1) = self;
377		let Uint(ref arr2) = other;
378
379		let mut ret = [0u64; N];
380		for i in 0..N {
381			ret[i] = arr1[i] & arr2[i];
382		}
383
384		Uint(ret)
385	}
386}
387
388impl<const N: usize> BitXor<Uint<N>> for Uint<N> {
389	type Output = Uint<N>;
390
391	fn bitxor(self, other: Uint<N>) -> Self {
392		let Uint(ref arr1) = self;
393		let Uint(ref arr2) = other;
394
395		let mut ret = [0u64; N];
396		for i in 0..N {
397			ret[i] = arr1[i] ^ arr2[i];
398		}
399
400		Uint(ret)
401	}
402}
403
404impl<const N: usize> BitOr<Uint<N>> for Uint<N> {
405	type Output = Uint<N>;
406
407	fn bitor(self, other: Uint<N>) -> Self {
408		let Uint(ref arr1) = self;
409		let Uint(ref arr2) = other;
410
411		let mut ret = [0u64; N];
412		for i in 0..N {
413			ret[i] = arr1[i] | arr2[i];
414		}
415
416		Uint(ret)
417	}
418}
419
420impl<const N: usize> Not for Uint<N> {
421	type Output = Uint<N>;
422
423	fn not(self) -> Self {
424		let Uint(ref arr) = self;
425
426		let mut ret = [0u64; N];
427		for i in 0..N {
428			ret[i] = !arr[i];
429		}
430
431		Uint(ret)
432	}
433}
434
435impl<const N: usize> Shl<usize> for Uint<N> {
436	type Output = Uint<N>;
437
438	fn shl(self, shift: usize) -> Self {
439		let Uint(ref original) = self;
440		let word_shift = shift / 64;
441		let bit_shift = shift % 64;
442
443		let mut ret = [0u64; N];
444		for i in 0..N {
445			// Shift
446			if bit_shift < 64 && i + word_shift < N {
447				ret[i + word_shift] += original[i] << bit_shift;
448			}
449
450			// Carry
451			if bit_shift > 0 && i + word_shift + 1 < N {
452				ret[i + word_shift + 1] += original[i] >> (64 - bit_shift);
453			}
454		}
455
456		Uint(ret)
457	}
458}
459
460impl<const N: usize> Shr<usize> for Uint<N> {
461	type Output = Uint<N>;
462
463	fn shr(self, shift: usize) -> Self {
464		let Uint(ref original) = self;
465		let word_shift = shift / 64;
466		let bit_shift = shift % 64;
467
468		let mut ret = [0u64; N];
469		for i in word_shift..N {
470			// Shift
471			ret[i - word_shift] += original[i] >> bit_shift;
472
473			// Carry
474			if bit_shift > 0 && i < N - 1 {
475				ret[i - word_shift] += original[i + 1] << (64 - bit_shift);
476			}
477		}
478
479		Uint(ret)
480	}
481}
482
483impl<const N: usize> AsRef<Uint<N>> for Uint<N> {
484	fn as_ref(&self) -> &Uint<N> {
485		self
486	}
487}
488
489impl<const N: usize> fmt::Debug for Uint<N> {
490	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
491		let Uint(data) = self;
492
493		write!(f, "0x")?;
494
495		for ch in data.iter().rev() {
496			write!(f, "{:016x}", ch)?;
497		}
498
499		Ok(())
500	}
501}
502
503impl<const N: usize> fmt::Display for Uint<N> {
504	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
505		<dyn fmt::Debug>::fmt(self, f)
506	}
507}
508
509impl<const N: usize> From<u8> for Uint<N> {
510	fn from(value: u8) -> Self {
511		(value as u64).into()
512	}
513}
514
515impl<const N: usize> From<u16> for Uint<N> {
516	fn from(value: u16) -> Self {
517		(value as u64).into()
518	}
519}
520
521impl<const N: usize> From<u32> for Uint<N> {
522	fn from(value: u32) -> Self {
523		(value as u64).into()
524	}
525}
526
527impl<const N: usize> From<u64> for Uint<N> {
528	fn from(value: u64) -> Self {
529		let mut ret = [0; N];
530		ret[0] = value;
531
532		Self(ret)
533	}
534}
535
536impl<const N: usize> From<u128> for Uint<N> {
537	fn from(value: u128) -> Self {
538		let mut ret = [0u64; N];
539
540		ret[0] = value as u64;
541		ret[1] = (value >> 64) as u64;
542
543		Self(ret)
544	}
545}
546
547impl<const N: usize> Codec for Uint<N> {
548	fn codec_serialize<W: io::Write>(&self, dest: &mut W) -> io::Result<()> {
549		dest.write_all(&self.to_be_bytes())
550	}
551
552	fn codec_deserialize<R: io::Read>(data: &mut R) -> io::Result<Self>
553	where
554		Self: Sized,
555	{
556		let mut buffer = vec![0u8; N * 8];
557		data.read_exact(&mut buffer)?;
558
559		Self::from_be_bytes(buffer).map_err(|_| {
560			io::Error::new(
561				io::ErrorKind::InvalidData,
562				"Could not deserialize Uint",
563			)
564		})
565	}
566}
567
568impl From<DoubleSha256Hasher> for Uint256 {
569	fn from(value: DoubleSha256Hasher) -> Self {
570		let buffer: [u8; SHA256_LENGTH] = value.as_bytes().try_into().unwrap();
571
572		let mut ret: [u64; 4] = unsafe { transmute(buffer) };
573		for x in ret.iter_mut() {
574			*x = x.to_le();
575		}
576
577		Uint256::from_u64_array(ret)
578	}
579}
580
581// From conversion is fallible for this type
582#[allow(clippy::from_over_into)]
583impl<const N: usize> Into<Vec<u64>> for Uint<N> {
584	fn into(self) -> Vec<u64> {
585		self.0.to_vec()
586	}
587}
588
589impl<const N: usize> TryFrom<Vec<u64>> for Uint<N> {
590	type Error = StacksError;
591
592	fn try_from(value: Vec<u64>) -> Result<Self, Self::Error> {
593		Ok(Self(value.as_slice().try_into()?))
594	}
595}
596
597/// A 256-bit unsigned integer
598pub type Uint256 = Uint<4>;
599/// A 512-bit unsigned integer
600pub type Uint512 = Uint<8>;
601
602#[cfg(test)]
603mod tests {
604	use super::*;
605
606	impl<const N: usize> Uint<N> {
607		fn bit(&self, index: usize) -> bool {
608			let Uint(arr) = self;
609
610			arr[index / 64] & (1 << (index % 64)) != 0
611		}
612
613		fn bit_slice(&self, start: usize, end: usize) -> Self {
614			(*self >> start).mask(end - start)
615		}
616
617		fn mask(&self, n: usize) -> Self {
618			let Uint(arr) = self;
619
620			let mut ret = [0; N];
621			for i in 0..N {
622				if n >= 0x40 * (i + 1) {
623					ret[i] = arr[i];
624				} else {
625					ret[i] = arr[i] & ((1 << (n - 0x40 * i)) - 1);
626					break;
627				}
628			}
629
630			Uint(ret)
631		}
632	}
633
634	#[test]
635	fn should_convert_from_u32() {
636		assert_eq!(Uint256::from(1337u32), Uint256::from(1337u64));
637	}
638
639	#[test]
640	pub fn uint256_bits_test() {
641		assert_eq!(Uint256::from(255u64).bits(), 8);
642		assert_eq!(Uint256::from(256u64).bits(), 9);
643		assert_eq!(Uint256::from(300u64).bits(), 9);
644		assert_eq!(Uint256::from(60000u64).bits(), 16);
645		assert_eq!(Uint256::from(70000u64).bits(), 17);
646
647		// Try to read the following lines out loud quickly
648		let mut shl = Uint256::from(70000u64);
649		shl = shl << 100;
650		assert_eq!(shl.bits(), 117);
651		shl = shl << 100;
652		assert_eq!(shl.bits(), 217);
653		shl = shl << 100;
654		assert_eq!(shl.bits(), 0);
655
656		// Bit set check
657		assert!(!Uint256::from(10u64).bit(0));
658		assert!(Uint256::from(10u64).bit(1));
659		assert!(!Uint256::from(10u64).bit(2));
660		assert!(Uint256::from(10u64).bit(3));
661		assert!(!Uint256::from(10u64).bit(4));
662	}
663
664	#[test]
665	pub fn uint256_display_test() {
666		assert_eq!(
667            format!("{}", Uint256::from(0xDEADBEEFu64)),
668            "0x00000000000000000000000000000000000000000000000000000000deadbeef"
669        );
670		assert_eq!(
671            format!("{}", Uint256::from(u64::MAX)),
672            "0x000000000000000000000000000000000000000000000000ffffffffffffffff"
673        );
674
675		let max_val = Uint256::from_u64_array([
676			0xFFFFFFFFFFFFFFFF,
677			0xFFFFFFFFFFFFFFFF,
678			0xFFFFFFFFFFFFFFFF,
679			0xFFFFFFFFFFFFFFFF,
680		]);
681
682		assert_eq!(
683            format!("{}", max_val),
684            "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
685        );
686	}
687
688	#[test]
689	pub fn uint256_comp_test() {
690		let small = Uint256::from_u64_array([10u64, 0, 0, 0]);
691		let big = Uint256::from_u64_array([
692			0x8C8C3EE70C644118u64,
693			0x0209E7378231E632,
694			0,
695			0,
696		]);
697		let bigger = Uint256::from_u64_array([
698			0x9C8C3EE70C644118u64,
699			0x0209E7378231E632,
700			0,
701			0,
702		]);
703		let biggest = Uint256::from_u64_array([
704			0x5C8C3EE70C644118u64,
705			0x0209E7378231E632,
706			0,
707			1,
708		]);
709
710		dbg!(&bigger, &biggest);
711
712		assert!(small < big);
713		assert!(big < bigger);
714		assert!(bigger < biggest);
715		assert!(bigger <= biggest);
716		assert!(biggest <= biggest);
717		assert!(bigger >= big);
718		assert!(bigger >= small);
719		assert!(small <= small);
720	}
721
722	#[test]
723	pub fn uint256_arithmetic_test() {
724		let init = Uint256::from(0xDEADBEEFDEADBEEFu64);
725		let copy = init;
726
727		let add = init + copy;
728		assert_eq!(
729			add,
730			Uint256::from_u64_array([0xBD5B7DDFBD5B7DDEu64, 1, 0, 0])
731		);
732		// Bitshifts
733		let shl = add << 88;
734		assert_eq!(
735			shl,
736			Uint256::from_u64_array([0u64, 0xDFBD5B7DDE000000, 0x1BD5B7D, 0])
737		);
738		let shr = shl >> 40;
739		assert_eq!(
740			shr,
741			Uint256::from_u64_array([
742				0x7DDE000000000000u64,
743				0x0001BD5B7DDFBD5B,
744				0,
745				0
746			])
747		);
748		// Increment
749		let mut incr = shr;
750		incr.increment();
751		assert_eq!(
752			incr,
753			Uint256::from_u64_array([
754				0x7DDE000000000001u64,
755				0x0001BD5B7DDFBD5B,
756				0,
757				0
758			])
759		);
760		// Subtraction
761		let sub = incr - init;
762		assert_eq!(
763			sub,
764			Uint256::from_u64_array([
765				0x9F30411021524112u64,
766				0x0001BD5B7DDFBD5A,
767				0,
768				0
769			])
770		);
771		// Multiplication
772		let mult = sub.mul_u32(300);
773		assert_eq!(
774			mult,
775			Uint256::from_u64_array([
776				0x8C8C3EE70C644118u64,
777				0x0209E7378231E632,
778				0,
779				0
780			])
781		);
782		// Division
783		assert_eq!(
784			Uint256::from(105u64) / Uint256::from(5u64),
785			Uint256::from(21u64)
786		);
787		let div = mult / Uint256::from(300u64);
788
789		dbg!(mult, Uint256::from(300u64), div);
790
791		assert_eq!(
792			div,
793			Uint256::from_u64_array([
794				0x9F30411021524112u64,
795				0x0001BD5B7DDFBD5A,
796				0,
797				0
798			])
799		);
800		// TODO: bit inversion
801	}
802
803	#[test]
804	pub fn mul_u32_test() {
805		let u64_val = Uint256::from(0xDEADBEEFDEADBEEFu64);
806
807		let u96_res = u64_val.mul_u32(0xFFFFFFFF);
808		let u128_res = u96_res.mul_u32(0xFFFFFFFF);
809		let u160_res = u128_res.mul_u32(0xFFFFFFFF);
810		let u192_res = u160_res.mul_u32(0xFFFFFFFF);
811		let u224_res = u192_res.mul_u32(0xFFFFFFFF);
812		let u256_res = u224_res.mul_u32(0xFFFFFFFF);
813
814		assert_eq!(
815			u96_res,
816			Uint256::from_u64_array([0xffffffff21524111u64, 0xDEADBEEE, 0, 0])
817		);
818		assert_eq!(
819			u128_res,
820			Uint256::from_u64_array([
821				0x21524111DEADBEEFu64,
822				0xDEADBEEE21524110,
823				0,
824				0
825			])
826		);
827		assert_eq!(
828			u160_res,
829			Uint256::from_u64_array([
830				0xBD5B7DDD21524111u64,
831				0x42A4822200000001,
832				0xDEADBEED,
833				0
834			])
835		);
836		assert_eq!(
837			u192_res,
838			Uint256::from_u64_array([
839				0x63F6C333DEADBEEFu64,
840				0xBD5B7DDFBD5B7DDB,
841				0xDEADBEEC63F6C334,
842				0
843			])
844		);
845		assert_eq!(
846			u224_res,
847			Uint256::from_u64_array([
848				0x7AB6FBBB21524111u64,
849				0xFFFFFFFBA69B4558,
850				0x854904485964BAAA,
851				0xDEADBEEB
852			])
853		);
854		assert_eq!(
855			u256_res,
856			Uint256::from_u64_array([
857				0xA69B4555DEADBEEFu64,
858				0xA69B455CD41BB662,
859				0xD41BB662A69B4550,
860				0xDEADBEEAA69B455C
861			])
862		);
863	}
864
865	#[test]
866	pub fn multiplication_test() {
867		let u64_val = Uint256::from(0xDEADBEEFDEADBEEFu64);
868
869		let u128_res = u64_val * u64_val;
870
871		assert_eq!(
872			u128_res,
873			Uint256::from_u64_array([
874				0x048D1354216DA321u64,
875				0xC1B1CD13A4D13D46,
876				0,
877				0
878			])
879		);
880
881		let u256_res = u128_res * u128_res;
882
883		assert_eq!(
884			u256_res,
885			Uint256::from_u64_array([
886				0xF4E166AAD40D0A41u64,
887				0xF5CF7F3618C2C886u64,
888				0x4AFCFF6F0375C608u64,
889				0x928D92B4D7F5DF33u64
890			])
891		);
892	}
893
894	#[test]
895	pub fn uint256_bitslice_test() {
896		let init = Uint256::from(0xDEADBEEFDEADBEEFu64);
897		let add = init + (init << 64);
898		assert_eq!(add.bit_slice(64, 128), init);
899		assert_eq!(add.mask(64), init);
900	}
901
902	#[test]
903	pub fn uint256_extreme_bitshift_test() {
904		// Shifting a u64 by 64 bits gives an undefined value, so make sure that
905		// we're doing the Right Thing here
906		let init = Uint256::from(0xDEADBEEFDEADBEEFu64);
907
908		assert_eq!(
909			init << 64,
910			Uint256::from_u64_array([0, 0xDEADBEEFDEADBEEF, 0, 0])
911		);
912		let add = (init << 64) + init;
913		assert_eq!(
914			add,
915			Uint256::from_u64_array([
916				0xDEADBEEFDEADBEEF,
917				0xDEADBEEFDEADBEEF,
918				0,
919				0
920			])
921		);
922		assert_eq!(
923			add >> 0,
924			Uint256::from_u64_array([
925				0xDEADBEEFDEADBEEF,
926				0xDEADBEEFDEADBEEF,
927				0,
928				0
929			])
930		);
931		assert_eq!(
932			add << 0,
933			Uint256::from_u64_array([
934				0xDEADBEEFDEADBEEF,
935				0xDEADBEEFDEADBEEF,
936				0,
937				0
938			])
939		);
940		assert_eq!(
941			add >> 64,
942			Uint256::from_u64_array([0xDEADBEEFDEADBEEF, 0, 0, 0])
943		);
944		assert_eq!(
945			add << 64,
946			Uint256::from_u64_array([
947				0,
948				0xDEADBEEFDEADBEEF,
949				0xDEADBEEFDEADBEEF,
950				0
951			])
952		);
953	}
954
955	#[test]
956	pub fn hex_codec() {
957		let init = Uint256::from(0xDEADBEEFDEADBEEFu64) << 64
958			| Uint256::from(0x0102030405060708u64);
959
960		// little-endian representation
961		let hex_init =
962			"0807060504030201efbeaddeefbeadde00000000000000000000000000000000";
963		assert_eq!(
964			Uint256::from_le_bytes(hex::decode(hex_init).unwrap()).unwrap(),
965			init
966		);
967		assert_eq!(hex::encode(init.to_le_bytes()), hex_init);
968		assert_eq!(Uint256::from_le_bytes(init.to_le_bytes()).unwrap(), init);
969
970		// big-endian representation
971		let hex_init =
972			"00000000000000000000000000000000deadbeefdeadbeef0102030405060708";
973		assert_eq!(
974			Uint256::from_be_bytes(hex::decode(hex_init).unwrap()).unwrap(),
975			init
976		);
977		assert_eq!(hex::encode(init.to_be_bytes()), hex_init);
978		assert_eq!(Uint256::from_be_bytes(init.to_be_bytes()).unwrap(), init);
979	}
980
981	#[test]
982	pub fn uint_increment_test() {
983		let mut value = Uint256::from_u64_array([0xffffffffffffffff, 0, 0, 0]);
984		value.increment();
985		assert_eq!(value, Uint256::from_u64_array([0, 1, 0, 0]));
986
987		value = Uint256::from_u64_array([
988			0xffffffffffffffff,
989			0xffffffffffffffff,
990			0,
991			0,
992		]);
993		value.increment();
994		assert_eq!(value, Uint256::from_u64_array([0, 0, 1, 0]));
995
996		value = Uint256::from_u64_array([
997			0xffffffffffffffff,
998			0xffffffffffffffff,
999			0xffffffffffffffff,
1000			0,
1001		]);
1002		value.increment();
1003		assert_eq!(value, Uint256::from_u64_array([0, 0, 0, 1]));
1004
1005		value = Uint256::from_u64_array([
1006			0xffffffffffffffff,
1007			0xffffffffffffffff,
1008			0xffffffffffffffff,
1009			0xffffffffffffffff,
1010		]);
1011		value.increment();
1012		assert_eq!(value, Uint256::from_u64_array([0, 0, 0, 0]));
1013	}
1014}