diff options
author | fanquake <fanquake@gmail.com> | 2024-03-05 11:00:54 +0000 |
---|---|---|
committer | fanquake <fanquake@gmail.com> | 2024-03-05 11:16:59 +0000 |
commit | 2b260eadf7960290328e13dbdb029fd506105ca4 (patch) | |
tree | 8e49a306d3999e04bd6180411faa10268984ae07 /test | |
parent | 98005b6a17907c4f7bdcf802ee96c274492f902a (diff) | |
parent | e67ab174c9c04bba7a10724b7e694dd57f732177 (diff) |
Merge bitcoin/bitcoin#29502: test: modify weight estimate in functional tests
e67ab174c9c04bba7a10724b7e694dd57f732177 test: fix flaky wallet_send functional test (Max Edwards)
3c49e6967050cfc367b3c826c9eac86a48528af5 test: fix weight estimates in functional tests (Max Edwards)
Pull request description:
Fixes: https://github.com/bitcoin/bitcoin/issues/25164
The wallet_send functional test has been flaky due to a slightly overestimated weight calculation. This PR makes the weight calculation more accurate, although occasionally, due to how ECDSA signatures can be different lengths it might slightly over estimate. The assertion in the test can handle this slight variation and so should continue passing.
Update:
Because the signature can be shorter that is used in the weight estimation or the final transaction the estimate could be both slightly smaller or slightly larger.
ACKs for top commit:
achow101:
ACK e67ab174c9c04bba7a10724b7e694dd57f732177
S3RK:
Code review ACK e67ab174c9c04bba7a10724b7e694dd57f732177
Tree-SHA512: 3bf73b355309dce860fa1520afb8461e94268e4bcf0e92a8273c279b41b058c44472cf59daafa15a515529b50bd665b5d498bbe4d934f2315dbe810a05bc73f9
Diffstat (limited to 'test')
-rwxr-xr-x | test/functional/rpc_psbt.py | 13 | ||||
-rwxr-xr-x | test/functional/wallet_send.py | 21 |
2 files changed, 24 insertions, 10 deletions
diff --git a/test/functional/rpc_psbt.py b/test/functional/rpc_psbt.py index 1fd938d18a..016aa3ba11 100755 --- a/test/functional/rpc_psbt.py +++ b/test/functional/rpc_psbt.py @@ -753,11 +753,16 @@ class PSBTTest(BitcoinTestFramework): break psbt_in = dec["inputs"][input_idx] # Calculate the input weight - # (prevout + sequence + length of scriptSig + scriptsig + 1 byte buffer) * WITNESS_SCALE_FACTOR + num scriptWitness stack items + (length of stack item + stack item) * N stack items + 1 byte buffer + # (prevout + sequence + length of scriptSig + scriptsig) * WITNESS_SCALE_FACTOR + len of num scriptWitness stack items + (length of stack item + stack item) * N stack items + # Note that occasionally this weight estimate may be slightly larger or smaller than the real weight + # as sometimes ECDSA signatures are one byte shorter than expected with a probability of 1/128 len_scriptsig = len(psbt_in["final_scriptSig"]["hex"]) // 2 if "final_scriptSig" in psbt_in else 0 - len_scriptsig += len(ser_compact_size(len_scriptsig)) + 1 - len_scriptwitness = (sum([(len(x) // 2) + len(ser_compact_size(len(x) // 2)) for x in psbt_in["final_scriptwitness"]]) + len(psbt_in["final_scriptwitness"]) + 1) if "final_scriptwitness" in psbt_in else 0 - input_weight = ((40 + len_scriptsig) * WITNESS_SCALE_FACTOR) + len_scriptwitness + len_scriptsig += len(ser_compact_size(len_scriptsig)) + len_scriptwitness = (sum([(len(x) // 2) + len(ser_compact_size(len(x) // 2)) for x in psbt_in["final_scriptwitness"]]) + len(ser_compact_size(len(psbt_in["final_scriptwitness"])))) if "final_scriptwitness" in psbt_in else 0 + len_prevout_txid = 32 + len_prevout_index = 4 + len_sequence = 4 + input_weight = ((len_prevout_txid + len_prevout_index + len_sequence + len_scriptsig) * WITNESS_SCALE_FACTOR) + len_scriptwitness low_input_weight = input_weight // 2 high_input_weight = input_weight * 2 diff --git a/test/functional/wallet_send.py b/test/functional/wallet_send.py index 6ce2a56bfc..580a9d2b22 100755 --- a/test/functional/wallet_send.py +++ b/test/functional/wallet_send.py @@ -543,11 +543,16 @@ class WalletSendTest(BitcoinTestFramework): break psbt_in = dec["inputs"][input_idx] # Calculate the input weight - # (prevout + sequence + length of scriptSig + scriptsig + 1 byte buffer) * WITNESS_SCALE_FACTOR + num scriptWitness stack items + (length of stack item + stack item) * N stack items + 1 byte buffer + # (prevout + sequence + length of scriptSig + scriptsig) * WITNESS_SCALE_FACTOR + len of num scriptWitness stack items + (length of stack item + stack item) * N stack items + # Note that occasionally this weight estimate may be slightly larger or smaller than the real weight + # as sometimes ECDSA signatures are one byte shorter than expected with a probability of 1/128 len_scriptsig = len(psbt_in["final_scriptSig"]["hex"]) // 2 if "final_scriptSig" in psbt_in else 0 - len_scriptsig += len(ser_compact_size(len_scriptsig)) + 1 - len_scriptwitness = (sum([(len(x) // 2) + len(ser_compact_size(len(x) // 2)) for x in psbt_in["final_scriptwitness"]]) + len(psbt_in["final_scriptwitness"]) + 1) if "final_scriptwitness" in psbt_in else 0 - input_weight = ((40 + len_scriptsig) * WITNESS_SCALE_FACTOR) + len_scriptwitness + len_scriptsig += len(ser_compact_size(len_scriptsig)) + len_scriptwitness = (sum([(len(x) // 2) + len(ser_compact_size(len(x) // 2)) for x in psbt_in["final_scriptwitness"]]) + len(ser_compact_size(len(psbt_in["final_scriptwitness"])))) if "final_scriptwitness" in psbt_in else 0 + len_prevout_txid = 32 + len_prevout_index = 4 + len_sequence = 4 + input_weight = ((len_prevout_txid + len_prevout_index + len_sequence + len_scriptsig) * WITNESS_SCALE_FACTOR) + len_scriptwitness # Input weight error conditions assert_raises_rpc_error( @@ -558,6 +563,7 @@ class WalletSendTest(BitcoinTestFramework): options={"inputs": [ext_utxo], "input_weights": [{"txid": ext_utxo["txid"], "vout": ext_utxo["vout"], "weight": 1000}]} ) + target_fee_rate_sat_vb = 10 # Funding should also work when input weights are provided res = self.test_send( from_wallet=ext_wallet, @@ -567,14 +573,17 @@ class WalletSendTest(BitcoinTestFramework): add_inputs=True, psbt=True, include_watching=True, - fee_rate=10 + fee_rate=target_fee_rate_sat_vb ) signed = ext_wallet.walletprocesspsbt(res["psbt"]) signed = ext_fund.walletprocesspsbt(res["psbt"]) assert signed["complete"] testres = self.nodes[0].testmempoolaccept([signed["hex"]])[0] assert_equal(testres["allowed"], True) - assert_fee_amount(testres["fees"]["base"], testres["vsize"], Decimal(0.0001)) + actual_fee_rate_sat_vb = Decimal(testres["fees"]["base"]) * Decimal(1e8) / Decimal(testres["vsize"]) + # Due to ECDSA signatures not always being the same length, the actual fee rate may be slightly different + # but rounded to nearest integer, it should be the same as the target fee rate + assert_equal(round(actual_fee_rate_sat_vb), target_fee_rate_sat_vb) if __name__ == '__main__': WalletSendTest().main() |