1use core::num::NonZeroU64;
6use core::{fmt, ops};
7
8#[cfg(feature = "arbitrary")]
9use arbitrary::{Arbitrary, Unstructured};
10#[cfg(feature = "serde")]
11use serde::{Deserialize, Deserializer, Serialize, Serializer};
12
13use crate::parse_int::{self, PrefixedHexError, UnprefixedHexError};
14use crate::{Amount, FeeRate, NumOpResult};
15
16pub const WITNESS_SCALE_FACTOR: usize = 4;
18
19mod encapsulate {
20 #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
25 pub struct Weight(u64);
26
27 impl Weight {
28 #[inline]
30 pub const fn from_wu(wu: u64) -> Self { Self(wu) }
31
32 #[inline]
36 pub const fn to_wu(self) -> u64 { self.0 }
37 }
38}
39#[doc(inline)]
40pub use encapsulate::Weight;
41
42impl Weight {
43 pub const ZERO: Self = Self::from_wu(0);
47
48 pub const MIN: Self = Self::from_wu(u64::MIN);
52
53 pub const MAX: Self = Self::from_wu(u64::MAX);
55
56 pub const WITNESS_SCALE_FACTOR: u64 = WITNESS_SCALE_FACTOR as u64; pub const MAX_BLOCK: Self = Self::from_wu(4_000_000);
61
62 pub const MIN_TRANSACTION: Self = Self::from_wu(Self::WITNESS_SCALE_FACTOR * 60);
64
65 #[inline]
67 pub const fn from_kwu(wu: u64) -> Option<Self> {
68 match wu.checked_mul(1000) {
70 Some(wu) => Some(Self::from_wu(wu)),
71 None => None,
72 }
73 }
74
75 #[inline]
77 pub const fn from_vb(vb: u64) -> Option<Self> {
78 match vb.checked_mul(Self::WITNESS_SCALE_FACTOR) {
80 Some(wu) => Some(Self::from_wu(wu)),
81 None => None,
82 }
83 }
84
85 #[deprecated(since = "1.0.0-rc.0", note = "use `from_vb_unchecked` instead")]
91 pub const fn from_vb_unwrap(vb: u64) -> Self {
92 match vb.checked_mul(Self::WITNESS_SCALE_FACTOR) {
93 Some(weight) => Self::from_wu(weight),
94 None => panic!("checked_mul overflowed"),
95 }
96 }
97
98 #[inline]
100 pub const fn from_vb_unchecked(vb: u64) -> Self {
101 Self::from_wu(vb * Self::WITNESS_SCALE_FACTOR)
102 }
103
104 #[deprecated(since = "1.0.0-rc.1", note = "use `from_wu` instead")]
106 pub const fn from_witness_data_size(witness_size: u64) -> Self { Self::from_wu(witness_size) }
107
108 #[deprecated(since = "1.0.0-rc.1", note = "use `from_vb` or `from_vb_unchecked` instead")]
114 pub const fn from_non_witness_data_size(non_witness_size: u64) -> Self {
115 Self::from_wu(non_witness_size * Self::WITNESS_SCALE_FACTOR)
116 }
117
118 #[inline]
125 pub fn from_hex(s: &str) -> Result<Self, PrefixedHexError> {
126 let weight = parse_int::hex_u64_prefixed(s)?;
127 Ok(Self::from_wu(weight))
128 }
129
130 #[inline]
137 pub fn from_unprefixed_hex(s: &str) -> Result<Self, UnprefixedHexError> {
138 let weight = parse_int::hex_u64_unprefixed(s)?;
139 Ok(Self::from_wu(weight))
140 }
141
142 #[inline]
144 pub const fn to_kwu_floor(self) -> u64 { self.to_wu() / 1000 }
145
146 #[inline]
148 pub const fn to_kwu_ceil(self) -> u64 { self.to_wu().div_ceil(1_000) }
149
150 #[inline]
152 pub const fn to_vbytes_floor(self) -> u64 { self.to_wu() / Self::WITNESS_SCALE_FACTOR }
153
154 #[inline]
156 pub const fn to_vbytes_ceil(self) -> u64 { self.to_wu().div_ceil(Self::WITNESS_SCALE_FACTOR) }
157
158 #[inline]
162 #[must_use]
163 pub const fn checked_add(self, rhs: Self) -> Option<Self> {
164 match self.to_wu().checked_add(rhs.to_wu()) {
166 Some(wu) => Some(Self::from_wu(wu)),
167 None => None,
168 }
169 }
170
171 #[inline]
175 #[must_use]
176 pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
177 match self.to_wu().checked_sub(rhs.to_wu()) {
179 Some(wu) => Some(Self::from_wu(wu)),
180 None => None,
181 }
182 }
183
184 #[inline]
188 #[must_use]
189 pub const fn checked_mul(self, rhs: u64) -> Option<Self> {
190 match self.to_wu().checked_mul(rhs) {
192 Some(wu) => Some(Self::from_wu(wu)),
193 None => None,
194 }
195 }
196
197 #[inline]
201 #[must_use]
202 pub const fn checked_div(self, rhs: u64) -> Option<Self> {
203 match self.to_wu().checked_div(rhs) {
205 Some(wu) => Some(Self::from_wu(wu)),
206 None => None,
207 }
208 }
209
210 #[inline]
216 pub const fn mul_by_fee_rate(self, fee_rate: FeeRate) -> NumOpResult<Amount> {
217 fee_rate.mul_by_weight(self)
218 }
219}
220
221crate::internal_macros::impl_fmt_traits_for_u32_wrapper!(Weight, to_wu);
222
223impl fmt::Display for Weight {
225 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
226 if f.alternate() {
227 write!(f, "{} wu", self.to_wu())
228 } else {
229 fmt::Display::fmt(&self.to_wu(), f)
230 }
231 }
232}
233
234impl From<Weight> for u64 {
235 #[inline]
236 fn from(value: Weight) -> Self { value.to_wu() }
237}
238
239crate::internal_macros::impl_op_for_references! {
240 impl ops::Add<Weight> for Weight {
241 type Output = Weight;
242
243 fn add(self, rhs: Weight) -> Self::Output { Weight::from_wu(self.to_wu() + rhs.to_wu()) }
244 }
245 impl ops::Sub<Weight> for Weight {
246 type Output = Weight;
247
248 fn sub(self, rhs: Weight) -> Self::Output { Weight::from_wu(self.to_wu() - rhs.to_wu()) }
249 }
250
251 impl ops::Mul<u64> for Weight {
252 type Output = Weight;
253
254 fn mul(self, rhs: u64) -> Self::Output { Weight::from_wu(self.to_wu() * rhs) }
255 }
256 impl ops::Mul<Weight> for u64 {
257 type Output = Weight;
258
259 fn mul(self, rhs: Weight) -> Self::Output { Weight::from_wu(self * rhs.to_wu()) }
260 }
261 impl ops::Div<u64> for Weight {
262 type Output = Weight;
263
264 fn div(self, rhs: u64) -> Self::Output { Weight::from_wu(self.to_wu() / rhs) }
265 }
266 impl ops::Div<Weight> for Weight {
267 type Output = u64;
268
269 fn div(self, rhs: Weight) -> Self::Output { self.to_wu() / rhs.to_wu() }
270 }
271 impl ops::Rem<u64> for Weight {
272 type Output = Weight;
273
274 fn rem(self, rhs: u64) -> Self::Output { Weight::from_wu(self.to_wu() % rhs) }
275 }
276 impl ops::Rem<Weight> for Weight {
277 type Output = u64;
278
279 fn rem(self, rhs: Weight) -> Self::Output { self.to_wu() % rhs.to_wu() }
280 }
281 impl ops::Div<NonZeroU64> for Weight {
282 type Output = Weight;
283
284 fn div(self, rhs: NonZeroU64) -> Self::Output{ Self::from_wu(self.to_wu() / rhs.get()) }
285 }
286}
287crate::internal_macros::impl_add_assign!(Weight);
288crate::internal_macros::impl_sub_assign!(Weight);
289
290impl ops::MulAssign<u64> for Weight {
291 #[inline]
292 fn mul_assign(&mut self, rhs: u64) { *self = Self::from_wu(self.to_wu() * rhs); }
293}
294
295impl ops::DivAssign<u64> for Weight {
296 #[inline]
297 fn div_assign(&mut self, rhs: u64) { *self = Self::from_wu(self.to_wu() / rhs); }
298}
299
300impl ops::RemAssign<u64> for Weight {
301 #[inline]
302 fn rem_assign(&mut self, rhs: u64) { *self = Self::from_wu(self.to_wu() % rhs); }
303}
304
305impl core::iter::Sum for Weight {
306 #[inline]
307 fn sum<I>(iter: I) -> Self
308 where
309 I: Iterator<Item = Self>,
310 {
311 Self::from_wu(iter.map(Self::to_wu).sum())
312 }
313}
314
315impl<'a> core::iter::Sum<&'a Self> for Weight {
316 #[inline]
317 fn sum<I>(iter: I) -> Self
318 where
319 I: Iterator<Item = &'a Self>,
320 {
321 iter.copied().sum()
322 }
323}
324
325parse_int::impl_parse_str_from_int_infallible!(Weight, u64, from_wu);
326
327#[cfg(feature = "serde")]
328impl Serialize for Weight {
329 #[inline]
330 fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
331 where
332 S: Serializer,
333 {
334 u64::serialize(&self.to_wu(), s)
335 }
336}
337
338#[cfg(feature = "serde")]
339impl<'de> Deserialize<'de> for Weight {
340 #[inline]
341 fn deserialize<D>(d: D) -> Result<Self, D::Error>
342 where
343 D: Deserializer<'de>,
344 {
345 Ok(Self::from_wu(u64::deserialize(d)?))
346 }
347}
348
349#[cfg(feature = "arbitrary")]
350impl<'a> Arbitrary<'a> for Weight {
351 fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
352 let w = u64::arbitrary(u)?;
353 Ok(Self::from_wu(w))
354 }
355}
356
357#[cfg(test)]
358mod tests {
359 use core::num::NonZeroU64;
360
361 use super::*;
362
363 const ONE: Weight = Weight::from_wu(1);
364 const TWO: Weight = Weight::from_wu(2);
365 const FOUR: Weight = Weight::from_wu(4);
366
367 #[test]
368 fn sanity_check() {
369 assert_eq!(Weight::MIN_TRANSACTION, Weight::from_wu(240));
370 }
371
372 #[test]
373 #[allow(clippy::op_ref)]
374 fn weight_div_nonzero() {
375 let w = Weight::from_wu(100);
376 let divisor = NonZeroU64::new(4).unwrap();
377 assert_eq!(w / divisor, Weight::from_wu(25));
378 assert_eq!(&w / &divisor, Weight::from_wu(25));
380 assert_eq!(w / &divisor, Weight::from_wu(25));
381 }
382
383 #[test]
384 fn from_kwu() {
385 let got = Weight::from_kwu(1).unwrap();
386 let want = Weight::from_wu(1_000);
387 assert_eq!(got, want);
388 }
389
390 #[test]
391 fn from_kwu_overflows() { assert!(Weight::from_kwu(u64::MAX).is_none()) }
392
393 #[test]
394 fn from_vb() {
395 let got = Weight::from_vb(1).unwrap();
396 let want = Weight::from_wu(4);
397 assert_eq!(got, want);
398 }
399
400 #[test]
401 fn from_vb_overflows() {
402 assert!(Weight::from_vb(u64::MAX).is_none());
403 }
404
405 #[test]
406 fn from_vb_unchecked() {
407 let got = Weight::from_vb_unchecked(1);
408 let want = Weight::from_wu(4);
409 assert_eq!(got, want);
410 }
411
412 #[test]
413 #[cfg(debug_assertions)]
414 #[should_panic = "attempt to multiply with overflow"]
415 fn from_vb_unchecked_panic() { Weight::from_vb_unchecked(u64::MAX); }
416
417 #[test]
418 #[allow(deprecated)] #[allow(deprecated_in_future)]
420 fn from_witness_data_size() {
421 let witness_data_size = 1;
422 let got = Weight::from_witness_data_size(witness_data_size);
423 let want = Weight::from_wu(witness_data_size);
424 assert_eq!(got, want);
425 }
426
427 #[test]
428 #[allow(deprecated)] #[allow(deprecated_in_future)]
430 fn from_non_witness_data_size() {
431 let non_witness_data_size = 1;
432 let got = Weight::from_non_witness_data_size(non_witness_data_size);
433 let want = Weight::from_wu(non_witness_data_size * 4);
434 assert_eq!(got, want);
435 }
436
437 #[test]
438 #[cfg(feature = "alloc")]
439 fn try_from_string() {
440 let weight_value: alloc::string::String = "10".into();
441 let got = Weight::try_from(weight_value).unwrap();
442 let want = Weight::from_wu(10);
443 assert_eq!(got, want);
444
445 let weight_value: alloc::string::String = "0xab".into();
447 assert!(Weight::try_from(weight_value).is_err());
448 let weight_value: alloc::string::String = "10.123".into();
449 assert!(Weight::try_from(weight_value).is_err());
450 }
451
452 #[test]
453 #[cfg(feature = "alloc")]
454 fn try_from_box() {
455 let weight_value: alloc::boxed::Box<str> = "10".into();
456 let got = Weight::try_from(weight_value).unwrap();
457 let want = Weight::from_wu(10);
458 assert_eq!(got, want);
459
460 let weight_value: alloc::boxed::Box<str> = "0xab".into();
462 assert!(Weight::try_from(weight_value).is_err());
463 let weight_value: alloc::boxed::Box<str> = "10.123".into();
464 assert!(Weight::try_from(weight_value).is_err());
465 }
466
467 #[test]
468 fn to_kwu_floor() {
469 assert_eq!(Weight::from_wu(5_000).to_kwu_floor(), 5);
470 assert_eq!(Weight::from_wu(5_999).to_kwu_floor(), 5);
471 }
472
473 #[test]
474 fn to_kwu_ceil() {
475 assert_eq!(Weight::from_wu(1_000).to_kwu_ceil(), 1);
476 assert_eq!(Weight::from_wu(1_001).to_kwu_ceil(), 2);
477 assert_eq!(Weight::MAX.to_kwu_ceil(), u64::MAX / 1_000 + 1);
478 }
479
480 #[test]
481 fn to_vb_floor() {
482 assert_eq!(Weight::from_wu(8).to_vbytes_floor(), 2);
483 assert_eq!(Weight::from_wu(9).to_vbytes_floor(), 2);
484 }
485
486 #[test]
487 fn to_vb_ceil() {
488 assert_eq!(Weight::from_wu(4).to_vbytes_ceil(), 1);
489 assert_eq!(Weight::from_wu(5).to_vbytes_ceil(), 2);
490 assert_eq!(Weight::MAX.to_vbytes_ceil(), u64::MAX / Weight::WITNESS_SCALE_FACTOR + 1);
491 }
492
493 #[test]
494 fn checked_add() {
495 assert_eq!(ONE.checked_add(ONE).unwrap(), TWO);
496 }
497
498 #[test]
499 fn checked_add_overflows() { assert!(Weight::MAX.checked_add(ONE).is_none()) }
500
501 #[test]
502 fn checked_sub() {
503 assert_eq!(TWO.checked_sub(ONE).unwrap(), ONE);
504 }
505
506 #[test]
507 fn checked_sub_overflows() { assert!(Weight::ZERO.checked_sub(ONE).is_none()) }
508
509 #[test]
510 fn checked_mul() {
511 assert_eq!(TWO.checked_mul(1).unwrap(), TWO);
512 assert_eq!(TWO.checked_mul(2).unwrap(), FOUR);
513 }
514
515 #[test]
516 fn checked_mul_overflows() { assert!(Weight::MAX.checked_mul(2).is_none()) }
517
518 #[test]
519 fn checked_div() {
520 assert_eq!(FOUR.checked_div(2).unwrap(), TWO);
521 assert_eq!(TWO.checked_div(1).unwrap(), TWO);
522 }
523
524 #[test]
525 fn checked_div_overflows() { assert!(TWO.checked_div(0).is_none()) }
526
527 #[test]
528 #[allow(clippy::op_ref)]
529 fn addition() {
530 let one = Weight::from_wu(1);
531 let two = Weight::from_wu(2);
532 let three = Weight::from_wu(3);
533
534 assert!(one + two == three);
535 assert!(&one + two == three);
536 assert!(one + &two == three);
537 assert!(&one + &two == three);
538 }
539
540 #[test]
541 #[allow(clippy::op_ref)]
542 fn subtract() {
543 let ten = Weight::from_wu(10);
544 let seven = Weight::from_wu(7);
545 let three = Weight::from_wu(3);
546
547 assert_eq!(ten - seven, three);
548 assert_eq!(&ten - seven, three);
549 assert_eq!(ten - &seven, three);
550 assert_eq!(&ten - &seven, three);
551 }
552
553 #[test]
554 #[allow(clippy::op_ref)]
555 fn multiply() {
556 let two = Weight::from_wu(2);
557 let six = Weight::from_wu(6);
558
559 assert_eq!(3_u64 * two, six);
560 assert_eq!(two * 3_u64, six);
561 }
562
563 #[test]
564 fn divide() {
565 let eight = Weight::from_wu(8);
566 let four = Weight::from_wu(4);
567
568 assert_eq!(eight / four, 2_u64);
569 assert_eq!(eight / 4_u64, Weight::from_wu(2));
570 }
571
572 #[test]
573 fn add_assign() {
574 let mut f = Weight::from_wu(1);
575 f += Weight::from_wu(2);
576 assert_eq!(f, Weight::from_wu(3));
577
578 let mut f = Weight::from_wu(1);
579 f += &Weight::from_wu(2);
580 assert_eq!(f, Weight::from_wu(3));
581 }
582
583 #[test]
584 fn sub_assign() {
585 let mut f = Weight::from_wu(3);
586 f -= Weight::from_wu(2);
587 assert_eq!(f, Weight::from_wu(1));
588
589 let mut f = Weight::from_wu(3);
590 f -= &Weight::from_wu(2);
591 assert_eq!(f, Weight::from_wu(1));
592 }
593
594 #[test]
595 fn mul_assign() {
596 let mut w = Weight::from_wu(3);
597 w *= 2_u64;
598 assert_eq!(w, Weight::from_wu(6));
599 }
600
601 #[test]
602 fn div_assign() {
603 let mut w = Weight::from_wu(8);
604 w /= Weight::from_wu(4).into();
605 assert_eq!(w, Weight::from_wu(2));
606 }
607
608 #[test]
609 fn remainder() {
610 let weight10 = Weight::from_wu(10);
611 let weight3 = Weight::from_wu(3);
612
613 let remainder = weight10 % weight3;
614 assert_eq!(remainder, 1);
615
616 let remainder = weight10 % 3;
617 assert_eq!(remainder, Weight::from_wu(1));
618 }
619
620 #[test]
621 fn remainder_assign() {
622 let mut weight = Weight::from_wu(10);
623 weight %= 3;
624 assert_eq!(weight, Weight::from_wu(1));
625 }
626
627 #[test]
628 fn iter_sum() {
629 let values = [
630 Weight::from_wu(10),
631 Weight::from_wu(50),
632 Weight::from_wu(30),
633 Weight::from_wu(5),
634 Weight::from_wu(5),
635 ];
636 let got: Weight = values.into_iter().sum();
637 let want = Weight::from_wu(100);
638 assert_eq!(got, want);
639 }
640
641 #[test]
642 fn iter_sum_ref() {
643 let values = [
644 Weight::from_wu(10),
645 Weight::from_wu(50),
646 Weight::from_wu(30),
647 Weight::from_wu(5),
648 Weight::from_wu(5),
649 ];
650 let got: Weight = values.iter().sum();
651 let want = Weight::from_wu(100);
652 assert_eq!(got, want);
653 }
654
655 #[test]
656 fn iter_sum_empty() {
657 let values: [Weight; 0] = [];
658 let got: Weight = values.into_iter().sum();
659 let want = Weight::from_wu(0);
660 assert_eq!(got, want);
661 }
662}