Author

Topic: Is Bitcoin's JSON-RPC interface safe? Or proper handling of money. (Read 2604 times)

legendary
Activity: 905
Merit: 1012
Try rounding to 8 decimal digits of precision, like you would with bitcoin.
hero member
Activity: 675
Merit: 514
Why are we using floats for delicate financial operations?
Why not? Double precision is guaranteed to represent everything from 0.00000001 to 67,108,863.99999999 with no loss of precision. Try it and see.
Well, and then there's this:
Code:
0.100000000000000010000
0.200000000000000010000
0.299999999999999990000
0.400000000000000020000
That's the output of this little C++ example:
Code:
std::cout.precision(40);
std::cout << 0.1 << '\n';
std::cout << 0.2 << '\n';
std::cout << 0.3 << '\n';
std::cout << 0.4 << '\n';
legendary
Activity: 905
Merit: 1012
Fun fact: JavaScript has MAX_INT equal to 2^53 - 1, for exactly this reason. These days it's all JIT compiled, but back in the early days of JavaScript interpreters, double-precision floating point was used for *everything*. And it worked, precisely and exactly. At least so long as you didn't exceed that range or divide on an intel CPU Wink
legendary
Activity: 4522
Merit: 3183
Vile Vixen and Miss Bitcointalk 2021-2023
Why are we using floats for delicate financial operations?
Why not? Double precision is guaranteed to represent everything from 0.00000001 to 67,108,863.99999999 with no loss of precision. Try it and see.
legendary
Activity: 905
Merit: 1012
Double has 53 bits position which is more than enough to encode all monetary values in bitcoin.
legendary
Activity: 1302
Merit: 1008
Core dev leaves me neg feedback #abuse #political
JSON uses e as part of number formatting, and probably the python code is doing nothing special.  Why do you suspect a problem? 

Follow docjeff's suggestion:  use a non rounded amount as see what happens.
newbie
Activity: 12
Merit: 0
Thanks for the reply Doc. I'm unpolitely bumping this thread again for additional information. I think it's an extremely important topic and would like confirmation from someone in the know that there isn't any truncation, rounding, loss of precision, or other weird errors / inaccuracy when using Python + python-bitcoinrpc + bitcoind.
newbie
Activity: 28
Merit: 0
Side note, 2e-05 expands to 2*10^(-5), which comes out to .00002
What you really need to do is ensure non-uniform decimals (e.g. .0010335) comes out appropriately.
newbie
Activity: 28
Merit: 0
newbie
Activity: 12
Merit: 0
Quite a few program are out there that use Bitcoin's RPC interface to send vast amounts of money. As far as I can tell, this involves POSTing a JSON object over HTTP to Bitcoind and receiving JSON in return. The problem I've noticed is due to the fact that we're using JSON's double-precision floating point format (and also floats in the client) instead of encoding the number as a string or in a 64 bit integer like Bitcoin does.

For example, let's say I want to send 0.00002 to "address".
Using Jeff Garzik's Python library I code something like this:
Quote
x.sendtoaddress("address", 0.00002)

Notice first that the library seems to only accept floating point numbers. Why is that? Why are we using floats for delicate financial operations?

The above code produces this:
Quote
Send -> {"method": "sendtoaddress", "params": ["address", 2e-05], "id": 1, "version": "1.1"}

Now notice the Python float has been converted to its equivalent exponential E notation, which is valid in JSON. But it still doesn't change the fact that we aren't talking precision here, or are we? Can anyone explain why this is safe to do? For example, are there any situations where either Bitcoin or the JSON-RPC Python client doesn't receive the actual amount of coins due to rounding / floating point conversion errors? Is this a precise why to handle money?

It seems a shame to even be having this discussion given that Satoshi himself was aware of this problem which is precisely (pun somewhat intended) why he used integers. I have no clue why we're talking about floating point, rounding, and truncation when the reference implementation is internally perfect. It just seems to me that the interfaces to talk to Bitcoin isn't, unless someone can explain to me why this is safe. The Wiki for proper money also mentions that rounding is required. Is proper rounding done by python-bitcoinrpc? These issues aren't discussed any where. The Wiki also goes on to say that "You, or the JSON library you are using, should convert amounts to either a fixed-point Decimal representation (with 8 digits after the decimal point) or ideally a 64-bit integer representation." Yeah, no kidding. Now any sample code to actually do that or is it currently impossible with JSON double-precision types?

Quote
def JSONtoAmount(value):
    return long(round(value * 1e8))
def AmountToJSON(amount):
    return float(amount / 1e8)
Context?


If any of these questions seem stupid then I apologize. But people are always complaining about incompetent developers and poorly secure software and Bitcoin doesn't even have proper documentation for something as important as precise handling of money. Which, fair enough, it's still a new project. But I'm starting to think that only the core developers have any clue how any of this works and it's very hard to learn when the only proper documentation is literally a 10,000 line+ C++ project.

Thanks for reading.
Jump to: