0

It seems that RPC calls for getting JSON information on blocks return "value" fields in bitcoins, not in satoshis.

This means that there is a conversion from integer to float somewhere, which is disturbing since it may introduce rounding errors (see context below).

Is there any way to get the integer satoshi amounts directly in the JSON?

Otherwise, is it completely safe to just multiply the float value by 10^8 and take the integer part?

Is there a better way to directly obtain the integer satoshi value?

Thanks!


Let me give some context.

A typical concern is that, for instance, most systems have no float of value (exactly) 0.1; they generally have a (tiny) difference.

On my machine, I obtain:

python3.6 -c 'print("%.20f"%0.1)'
0.10000000000000000555

python3.6 -c 'print(0.1+0.1+0.1==0.3)'
False

This is generally safe, but in my context this raises messy issues, so dealing only with integers is appealing.

1

1 Answer 1

1

bitcoind internally treats all amounts as an integer and only displays the value as a decimal for the RPC. Formatting for display does not introduce any floating point precision issues as it still just does integer conversion with some string formatting to make it look like a decimal. So it is perfectly safe to multiply by 100000000 to get an integer amount of satoshis.

4
  • Thank you! However, it seems to me that RPC values come from the AmountFromValue() function, that makes a conversion to double and a division. I still think that multiplying by 100000000 works, but I am curious of your claim about string formatting. May you please elaborate? Mar 29, 2021 at 5:18
  • The functions to look at are FormatMoney, ParseMoney, and AmountFromValue. None of these functions use floats or doubles. FormatMoney is how the RPC converts integer amounts to decimal amounts for display. It does integer division and modulo, then string formatting to make it look like a decimal.
    – Andrew Chow
    Mar 29, 2021 at 16:13
  • Right, I was looking at an old version of the code, with double conversions and divisions, but in modern implementations I find what you describe. Thanks! Mar 29, 2021 at 18:05
  • Let me add that, if the "value" v is stored as a float (which we should never do), taking int(v*100000000) is incorrect; one should take int(round(v*100000000)). Both give the correct value if v=0.1, but int(4.35*100000000) gives 434999999 (incorrect) whereas int(round(4.35*100000000)) gives 435000000 (correct), at least in my settings. Apr 1, 2021 at 4:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.