feefrac_tests.cpp raw

   1  // Copyright (c) 2024-present The Bitcoin Core developers
   2  // Distributed under the MIT software license, see the accompanying
   3  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
   4  
   5  #include <util/feefrac.h>
   6  #include <random.h>
   7  
   8  #include <boost/test/unit_test.hpp>
   9  
  10  BOOST_AUTO_TEST_SUITE(feefrac_tests)
  11  
  12  BOOST_AUTO_TEST_CASE(feefrac_operators)
  13  {
  14      FeeFrac p1{1000, 100}, p2{500, 300};
  15      FeeFrac sum{1500, 400};
  16      FeeFrac diff{500, -200};
  17      FeeFrac empty{0, 0};
  18      FeeFrac zero_fee{0, 1}; // zero-fee allowed
  19  
  20      BOOST_CHECK_EQUAL(zero_fee.EvaluateFeeDown(0), 0);
  21      BOOST_CHECK_EQUAL(zero_fee.EvaluateFeeDown(1), 0);
  22      BOOST_CHECK_EQUAL(zero_fee.EvaluateFeeDown(1000000), 0);
  23      BOOST_CHECK_EQUAL(zero_fee.EvaluateFeeDown(0x7fffffff), 0);
  24      BOOST_CHECK_EQUAL(zero_fee.EvaluateFeeUp(0), 0);
  25      BOOST_CHECK_EQUAL(zero_fee.EvaluateFeeUp(1), 0);
  26      BOOST_CHECK_EQUAL(zero_fee.EvaluateFeeUp(1000000), 0);
  27      BOOST_CHECK_EQUAL(zero_fee.EvaluateFeeUp(0x7fffffff), 0);
  28  
  29      BOOST_CHECK_EQUAL(p1.EvaluateFeeDown(0), 0);
  30      BOOST_CHECK_EQUAL(p1.EvaluateFeeDown(1), 10);
  31      BOOST_CHECK_EQUAL(p1.EvaluateFeeDown(100000000), 1000000000);
  32      BOOST_CHECK_EQUAL(p1.EvaluateFeeDown(0x7fffffff), int64_t(0x7fffffff) * 10);
  33      BOOST_CHECK_EQUAL(p1.EvaluateFeeUp(0), 0);
  34      BOOST_CHECK_EQUAL(p1.EvaluateFeeUp(1), 10);
  35      BOOST_CHECK_EQUAL(p1.EvaluateFeeUp(100000000), 1000000000);
  36      BOOST_CHECK_EQUAL(p1.EvaluateFeeUp(0x7fffffff), int64_t(0x7fffffff) * 10);
  37  
  38      FeeFrac neg{-1001, 100};
  39      BOOST_CHECK_EQUAL(neg.EvaluateFeeDown(0), 0);
  40      BOOST_CHECK_EQUAL(neg.EvaluateFeeDown(1), -11);
  41      BOOST_CHECK_EQUAL(neg.EvaluateFeeDown(2), -21);
  42      BOOST_CHECK_EQUAL(neg.EvaluateFeeDown(3), -31);
  43      BOOST_CHECK_EQUAL(neg.EvaluateFeeDown(100), -1001);
  44      BOOST_CHECK_EQUAL(neg.EvaluateFeeDown(101), -1012);
  45      BOOST_CHECK_EQUAL(neg.EvaluateFeeDown(100000000), -1001000000);
  46      BOOST_CHECK_EQUAL(neg.EvaluateFeeDown(100000001), -1001000011);
  47      BOOST_CHECK_EQUAL(neg.EvaluateFeeDown(0x7fffffff), -21496311307);
  48      BOOST_CHECK_EQUAL(neg.EvaluateFeeUp(0), 0);
  49      BOOST_CHECK_EQUAL(neg.EvaluateFeeUp(1), -10);
  50      BOOST_CHECK_EQUAL(neg.EvaluateFeeUp(2), -20);
  51      BOOST_CHECK_EQUAL(neg.EvaluateFeeUp(3), -30);
  52      BOOST_CHECK_EQUAL(neg.EvaluateFeeUp(100), -1001);
  53      BOOST_CHECK_EQUAL(neg.EvaluateFeeUp(101), -1011);
  54      BOOST_CHECK_EQUAL(neg.EvaluateFeeUp(100000000), -1001000000);
  55      BOOST_CHECK_EQUAL(neg.EvaluateFeeUp(100000001), -1001000010);
  56      BOOST_CHECK_EQUAL(neg.EvaluateFeeUp(0x7fffffff), -21496311306);
  57  
  58      BOOST_CHECK(empty == FeeFrac{}); // same as no-args
  59  
  60      BOOST_CHECK(p1 == p1);
  61      BOOST_CHECK(p1 + p2 == sum);
  62      BOOST_CHECK(p1 - p2 == diff);
  63  
  64      FeeFrac p3{2000, 200};
  65      BOOST_CHECK(p1 != p3); // feefracs only equal if both fee and size are same
  66      BOOST_CHECK(p2 != p3);
  67  
  68      FeeFrac p4{3000, 300};
  69      BOOST_CHECK(p1 == p4-p3);
  70      BOOST_CHECK(p1 + p3 == p4);
  71  
  72      // Fee-rate comparison
  73      BOOST_CHECK(ByRatioNegSize{p1} > ByRatioNegSize{p2});
  74      BOOST_CHECK(ByRatioNegSize{p1} >= ByRatioNegSize{p2});
  75      BOOST_CHECK(ByRatioNegSize{p1} >= ByRatioNegSize{p4-p3});
  76      BOOST_CHECK(!(ByRatio{p1} > ByRatio{p3})); // not strictly better
  77      BOOST_CHECK(ByRatio{p1} > ByRatio{p2}); // strictly greater feerate
  78  
  79      BOOST_CHECK(ByRatioNegSize{p2} < ByRatioNegSize{p1});
  80      BOOST_CHECK(ByRatioNegSize{p2} <= ByRatioNegSize{p1});
  81      BOOST_CHECK(ByRatioNegSize{p1} <= ByRatioNegSize{p4-p3});
  82      BOOST_CHECK(!(ByRatio{p3} < ByRatio{p1})); // not strictly worse
  83      BOOST_CHECK(ByRatio{p2} < ByRatio{p1}); // strictly lower feerate
  84  
  85      // "empty" comparisons
  86      BOOST_CHECK(!(ByRatio{p1} > ByRatio{empty})); // << will always result in false
  87      BOOST_CHECK(!(ByRatio{p1} < ByRatio{empty}));
  88      BOOST_CHECK(!(ByRatio{empty} > ByRatio{empty}));
  89      BOOST_CHECK(!(ByRatio{empty} < ByRatio{empty}));
  90  
  91      // empty is always bigger than everything else
  92      BOOST_CHECK(ByRatioNegSize{empty} > ByRatioNegSize{p1});
  93      BOOST_CHECK(ByRatioNegSize{empty} > ByRatioNegSize{p2});
  94      BOOST_CHECK(ByRatioNegSize{empty} > ByRatioNegSize{p3});
  95      BOOST_CHECK(ByRatioNegSize{empty} >= ByRatioNegSize{p1});
  96      BOOST_CHECK(ByRatioNegSize{empty} >= ByRatioNegSize{p2});
  97      BOOST_CHECK(ByRatioNegSize{empty} >= ByRatioNegSize{p3});
  98  
  99      // check "max" values for comparison
 100      FeeFrac oversized_1{4611686000000, 4000000};
 101      FeeFrac oversized_2{184467440000000, 100000};
 102  
 103      BOOST_CHECK(ByRatioNegSize{oversized_1} < ByRatioNegSize{oversized_2});
 104      BOOST_CHECK(ByRatioNegSize{oversized_1} <= ByRatioNegSize{oversized_2});
 105      BOOST_CHECK(ByRatio{oversized_1} < ByRatio{oversized_2});
 106      BOOST_CHECK(ByRatioNegSize{oversized_1} != ByRatioNegSize{oversized_2});
 107  
 108      BOOST_CHECK_EQUAL(oversized_1.EvaluateFeeDown(0), 0);
 109      BOOST_CHECK_EQUAL(oversized_1.EvaluateFeeDown(1), 1152921);
 110      BOOST_CHECK_EQUAL(oversized_1.EvaluateFeeDown(2), 2305843);
 111      BOOST_CHECK_EQUAL(oversized_1.EvaluateFeeDown(1548031267), 1784758530396540);
 112      BOOST_CHECK_EQUAL(oversized_1.EvaluateFeeUp(0), 0);
 113      BOOST_CHECK_EQUAL(oversized_1.EvaluateFeeUp(1), 1152922);
 114      BOOST_CHECK_EQUAL(oversized_1.EvaluateFeeUp(2), 2305843);
 115      BOOST_CHECK_EQUAL(oversized_1.EvaluateFeeUp(1548031267), 1784758530396541);
 116  
 117      // Test cases on the threshold where FeeFrac::Evaluate start using Mul/Div.
 118      BOOST_CHECK_EQUAL(FeeFrac(0x1ffffffff, 123456789).EvaluateFeeDown(98765432), 6871947728);
 119      BOOST_CHECK_EQUAL(FeeFrac(0x200000000, 123456789).EvaluateFeeDown(98765432), 6871947729);
 120      BOOST_CHECK_EQUAL(FeeFrac(0x200000001, 123456789).EvaluateFeeDown(98765432), 6871947730);
 121      BOOST_CHECK_EQUAL(FeeFrac(0x1ffffffff, 123456789).EvaluateFeeUp(98765432), 6871947729);
 122      BOOST_CHECK_EQUAL(FeeFrac(0x200000000, 123456789).EvaluateFeeUp(98765432), 6871947730);
 123      BOOST_CHECK_EQUAL(FeeFrac(0x200000001, 123456789).EvaluateFeeUp(98765432), 6871947731);
 124  
 125      // Tests paths that use double arithmetic
 126      FeeFrac busted{(static_cast<int64_t>(INT32_MAX)) + 1, INT32_MAX};
 127      BOOST_CHECK(!(ByRatioNegSize{busted} < ByRatioNegSize{busted}));
 128  
 129      FeeFrac max_fee{2100000000000000, INT32_MAX};
 130      BOOST_CHECK(!(ByRatioNegSize{max_fee} < ByRatioNegSize{max_fee}));
 131      BOOST_CHECK(!(ByRatioNegSize{max_fee} > ByRatioNegSize{max_fee}));
 132      BOOST_CHECK(ByRatioNegSize{max_fee} <= ByRatioNegSize{max_fee});
 133      BOOST_CHECK(ByRatioNegSize{max_fee} >= ByRatioNegSize{max_fee});
 134  
 135      BOOST_CHECK_EQUAL(max_fee.EvaluateFeeDown(0), 0);
 136      BOOST_CHECK_EQUAL(max_fee.EvaluateFeeDown(1), 977888);
 137      BOOST_CHECK_EQUAL(max_fee.EvaluateFeeDown(2), 1955777);
 138      BOOST_CHECK_EQUAL(max_fee.EvaluateFeeDown(3), 2933666);
 139      BOOST_CHECK_EQUAL(max_fee.EvaluateFeeDown(1256796054), 1229006664189047);
 140      BOOST_CHECK_EQUAL(max_fee.EvaluateFeeDown(INT32_MAX), 2100000000000000);
 141      BOOST_CHECK_EQUAL(max_fee.EvaluateFeeUp(0), 0);
 142      BOOST_CHECK_EQUAL(max_fee.EvaluateFeeUp(1), 977889);
 143      BOOST_CHECK_EQUAL(max_fee.EvaluateFeeUp(2), 1955778);
 144      BOOST_CHECK_EQUAL(max_fee.EvaluateFeeUp(3), 2933667);
 145      BOOST_CHECK_EQUAL(max_fee.EvaluateFeeUp(1256796054), 1229006664189048);
 146      BOOST_CHECK_EQUAL(max_fee.EvaluateFeeUp(INT32_MAX), 2100000000000000);
 147  
 148      FeeFrac max_fee2{1, 1};
 149      BOOST_CHECK(ByRatioNegSize{max_fee} >= ByRatioNegSize{max_fee2});
 150  
 151      // Test for integer overflow issue (https://github.com/bitcoin/bitcoin/issues/32294)
 152      BOOST_CHECK_EQUAL((FeeFrac{0x7ffffffdfffffffb, 0x7ffffffd}.EvaluateFeeDown(0x7fffffff)), 0x7fffffffffffffff);
 153  }
 154  
 155  BOOST_AUTO_TEST_SUITE_END()
 156