-
Notifications
You must be signed in to change notification settings - Fork 38.7k
Add and use satToBtc and btcToSat util functions
#31356
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. Code Coverage & BenchmarksFor details see: https://corecheck.dev/bitcoin/bitcoin/pulls/31356. ReviewsSee the guideline for information on the review process. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
2dff8fa to
8ef6811
Compare
|
🚧 At least one of the CI tasks failed. HintsTry to run the tests locally, according to the documentation. However, a CI failure may still
Leave a comment here, if you need help tracking down a confusing failure. |
8ef6811 to
632766a
Compare
|
Concept -0, it seems like a huge change to factor out what is just a multiply/division. imo this only makes sense if the intent is to add extra validity checks to the functions. Could at least make sure that the return value from |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so something like
def satToBtc(sat_value: int) -> Decimal:
return Decimal(sat_value) / COIN
def btcToSat(btc_value: Decimal) -> int:
return int(btc_value * COIN)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I think this might be better. I've updated the PR.
632766a to
42c0623
Compare
|
🚧 At least one of the CI tasks failed. HintsTry to run the tests locally, according to the documentation. However, a CI failure may still
Leave a comment here, if you need help tracking down a confusing failure. |
32a5b18 to
8aaa4ad
Compare
maflcko
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of repeating the diff in the pull request description (if someone was interested in the changes in detail, they could just look at the diff themselves), it would be better to mention the benefits/goals and how they are expected to be achieved for new code written after this was merged.
Possibly there is a case to have feerate conversion helpers, or a class to hold feerates. However, any "global" change here would need a solid motivation and long-term upside.
test/functional/feature_block.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure about this. I think writing 10 * COIN with the meaning of "10 bitcoins" is self-explanatory and couldn't be clearer. btcToSat(10) just seems like an extra step and extra complexity without a benefit?
Also, the "new" style isn't enforced, so you'll end up with both styles being used in the future, increasing the confusing further.
Finally, I had the impression that python code is using snake_case, so btcToSat would be confusing in that regard as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While 10 * COIN seems self-explanatory, I find the util function usage in the following diff more readable and easier on the eyes. Instead of having to process 3 things in one go, namely int conversion, sum() with an argument that's being calculated, multiplication with COIN, I have to process only one function call with the said argument.
- input_amount = int(sum([utxo['value'] for utxo in utxos_to_spend]) * COIN)
+ input_amount = btcToSat(sum([utxo['value'] for utxo in utxos_to_spend]))Introduce utility functions `satToBtc` and `btcToSat` to simplify and standardize conversions between satoshis and bitcoins in functional tests
8aaa4ad to
a15e9ae
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for picking this up! Left few suggestions.
Can the PR be split into 2 commits for each util function that will make it easier to process piece by piece?
| def satToBtc(sat_value: int) -> Decimal: | ||
| return Decimal(sat_value) / COIN | ||
|
|
||
|
|
||
| def btcToSat(btc_value: Decimal) -> int: | ||
| return int(btc_value * COIN) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see that COIN is defined in this file but not sure if this is the right file to put these functions in, maybe util.py?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for using camelCase in the issue description, snake_case is preferred in functional tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is definitely the wrong file, I couldn't even find this change
| tx_val = 0.001 | ||
| tx.vout = [CTxOut(int(Decimal(tx_val) * COIN), CScript([OP_RETURN] + [OP_FALSE] * 30))] | ||
| tx.vout = [CTxOut(btcToSat(Decimal(tx_val)), CScript([OP_RETURN] + [OP_FALSE] * 30))] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this utility function can become more useful if it accepts float too, thereby getting rid of explicit conversion while calling?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Python float to decimal conversion via string: https://stackoverflow.com/questions/316238/python-float-to-decimal-conversion#comment107437133_316253
| def branch(prevout, initial_value, max_txs, tree_width=5, fee=0.00001 * COIN, _total_txs=None): | ||
| def branch(prevout, initial_value, max_txs, tree_width=5, fee=None, _total_txs=None): | ||
| if fee is None: | ||
| fee = btcToSat(0.00001) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- def branch(prevout, initial_value, max_txs, tree_width=5, fee=0.00001 * COIN, _total_txs=None):
+ def branch(prevout, initial_value, max_txs, tree_width=5, fee=btcToSat(0.00001), _total_txs=None):Seems to work.
test/functional/feature_block.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While 10 * COIN seems self-explanatory, I find the util function usage in the following diff more readable and easier on the eyes. Instead of having to process 3 things in one go, namely int conversion, sum() with an argument that's being calculated, multiplication with COIN, I have to process only one function call with the said argument.
- input_amount = int(sum([utxo['value'] for utxo in utxos_to_spend]) * COIN)
+ input_amount = btcToSat(sum([utxo['value'] for utxo in utxos_to_spend]))| value += btcToSat(utxos[j]["value"]) | ||
| # Overestimate the size of the tx - signatures should be less than 120 bytes, and leave 50 for the output | ||
| tx_size = len(tx.serialize().hex())//2 + 120*num_inputs + 50 | ||
| tx.vout.append(CTxOut(int(value - self.relayfee * tx_size * COIN / 1000), SCRIPT_W0_SH_OP_TRUE)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Possibly there is a case to have feerate conversion helpers, or a class to hold feerates.
Agree, a fee rate conversion helper here would make reading this far easier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This conversion was not intuitive to me in the first glance: #30079 (comment)
| tx2_val = '20.99' | ||
| tx2.vout = [CTxOut(int(Decimal(tx2_val) * COIN), CScript([OP_RETURN] + [OP_FALSE] * 30))] | ||
| tx2.vout = [CTxOut(btcToSat(Decimal(tx2_val)), CScript([OP_RETURN] + [OP_FALSE] * 30))] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe accepting a string with internal string to decimal checking and conversion would also make it more flexible? The explicit Decimal conversion could be removed here then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An alternative idea would be to add a btcStringToSat function, instead of overloading btcToSat on type, as this makes type checking harder.
| fee_delta_b = satToBtc(Decimal(9999)) | ||
| fee_delta_c_1 = satToBtc(Decimal(-1234)) | ||
| fee_delta_c_2 = satToBtc(Decimal(8888)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't satToBtc accept an int?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, passing sats as a decimal should never be necessary.
|
🐙 This pull request conflicts with the target branch and needs rebase. |
|
Closing, given the author has said in #31345 that someone else can take it over. |
Introduce utility functions
satToBtcandbtcToSatto simplify and standardize conversions between satoshis and bitcoins in functional tests#closes #31345
This PR implements the solution proposed in the issue. The goal is to simplify conversions between satoshis and bitcoins in the functional tests by using utility functions. For example, code like
fee_rate=Decimal(feerate * 1000) / COINcould becomefee_rate=satToBtc(feerate * 1000)in the proposed solution.An additional benefit of satToBtc() is that it ensures the use of Decimal.
This issue was briefly mentioned in this discussion, where the conversion
Decimal(value) / COINwas noted to be repetitive.While some may prefer to continue using the
/ COINand* COINconversions, I don’t have a strong preference either way. I’d like to hear your opinions and, if needed, implement the approach that works best.