From d1fab9d5d27a2db2546db0f610e0f6929ec4864e Mon Sep 17 00:00:00 2001 From: Martin Zumsande Date: Wed, 2 Feb 2022 17:52:05 +0100 Subject: test: Call ceildiv helper with integer It returns an incorrect result when called with a Decimal, for which the "//" operator works differently. Also drop unnecessary call to satoshi_round. --- test/functional/test_framework/util.py | 11 +++++++++-- test/functional/wallet_send.py | 9 +++++---- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py index dabde13bf1..210025104e 100644 --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -36,6 +36,7 @@ def assert_approx(v, vexp, vspan=0.00001): def assert_fee_amount(fee, tx_size, feerate_BTC_kvB): """Assert the fee is in range.""" + assert isinstance(tx_size, int) target_fee = get_fee(tx_size, feerate_BTC_kvB) if fee < target_fee: raise AssertionError("Fee of %s BTC too low! (Should be %s BTC)" % (str(fee), str(target_fee))) @@ -219,7 +220,13 @@ def str_to_b64str(string): def ceildiv(a, b): - """Divide 2 ints and round up to next int rather than round down""" + """ + Divide 2 ints and round up to next int rather than round down + Implementation requires python integers, which have a // operator that does floor division. + Other types like decimal.Decimal whose // operator truncates towards 0 will not work. + """ + assert isinstance(a, int) + assert isinstance(b, int) return -(-a // b) @@ -227,7 +234,7 @@ def get_fee(tx_size, feerate_btc_kvb): """Calculate the fee in BTC given a feerate is BTC/kvB. Reflects CFeeRate::GetFee""" feerate_sat_kvb = int(feerate_btc_kvb * Decimal(1e8)) # Fee in sat/kvb as an int to avoid float precision errors target_fee_sat = ceildiv(feerate_sat_kvb * tx_size, 1000) # Round calculated fee up to nearest sat - return satoshi_round(target_fee_sat / Decimal(1e8)) # Truncate BTC result to nearest sat + return target_fee_sat / Decimal(1e8) # Return result in BTC def satoshi_round(amount): diff --git a/test/functional/wallet_send.py b/test/functional/wallet_send.py index 843a9f52b7..86e36be8f7 100755 --- a/test/functional/wallet_send.py +++ b/test/functional/wallet_send.py @@ -16,6 +16,7 @@ from test_framework.util import ( assert_fee_amount, assert_greater_than, assert_raises_rpc_error, + count_bytes, ) from test_framework.wallet_util import bytes_to_wif @@ -320,20 +321,20 @@ class WalletSendTest(BitcoinTestFramework): res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, fee_rate=7, add_to_wallet=False) fee = self.nodes[1].decodepsbt(res["psbt"])["fee"] - assert_fee_amount(fee, Decimal(len(res["hex"]) / 2), Decimal("0.00007")) + assert_fee_amount(fee, count_bytes(res["hex"]), Decimal("0.00007")) # "unset" and None are treated the same for estimate_mode res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, fee_rate=2, estimate_mode="unset", add_to_wallet=False) fee = self.nodes[1].decodepsbt(res["psbt"])["fee"] - assert_fee_amount(fee, Decimal(len(res["hex"]) / 2), Decimal("0.00002")) + assert_fee_amount(fee, count_bytes(res["hex"]), Decimal("0.00002")) res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate=4.531, add_to_wallet=False) fee = self.nodes[1].decodepsbt(res["psbt"])["fee"] - assert_fee_amount(fee, Decimal(len(res["hex"]) / 2), Decimal("0.00004531")) + assert_fee_amount(fee, count_bytes(res["hex"]), Decimal("0.00004531")) res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate=3, add_to_wallet=False) fee = self.nodes[1].decodepsbt(res["psbt"])["fee"] - assert_fee_amount(fee, Decimal(len(res["hex"]) / 2), Decimal("0.00003")) + assert_fee_amount(fee, count_bytes(res["hex"]), Decimal("0.00003")) # Test that passing fee_rate as both an argument and an option raises. self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate=1, fee_rate=1, add_to_wallet=False, -- cgit v1.2.3