Bitcoin Forum
June 19, 2024, 08:52:28 AM *
News: Voting for pizza day contest
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: Is Bitcoin's JSON-RPC interface safe? Or proper handling of money.  (Read 2603 times)
21st-century (OP)
Newbie
*
Offline Offline

Activity: 12
Merit: 0


View Profile
April 25, 2014, 04:47:07 AM
 #1

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.
DocJeff
Newbie
*
Offline Offline

Activity: 28
Merit: 0


View Profile
April 25, 2014, 09:00:25 AM
 #2

What language are you developing in?

Give this a look:
http://deron.meranda.us/python/comparing_json_modules/numbers
DocJeff
Newbie
*
Offline Offline

Activity: 28
Merit: 0


View Profile
April 25, 2014, 09:05:28 AM
 #3

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.
21st-century (OP)
Newbie
*
Offline Offline

Activity: 12
Merit: 0


View Profile
April 28, 2014, 03:21:31 AM
 #4

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.
jonald_fyookball
Legendary
*
Offline Offline

Activity: 1302
Merit: 1004


Core dev leaves me neg feedback #abuse #political


View Profile
April 28, 2014, 04:18:45 AM
 #5

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.

maaku
Legendary
*
expert
Offline Offline

Activity: 905
Merit: 1011


View Profile
April 28, 2014, 04:50:53 AM
 #6

Double has 53 bits position which is more than enough to encode all monetary values in bitcoin.

I'm an independent developer working on bitcoin-core, making my living off community donations.
If you like my work, please consider donating yourself: 13snZ4ZyCzaL7358SmgvHGC9AxskqumNxP
Foxpup
Legendary
*
Offline Offline

Activity: 4396
Merit: 3062


Vile Vixen and Miss Bitcointalk 2021-2023


View Profile
April 28, 2014, 05:55:29 AM
 #7

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.

Will pretend to do unspeakable things (while actually eating a taco) for bitcoins: 1K6d1EviQKX3SVKjPYmJGyWBb1avbmCFM4
I am not on the scammers' paradise known as Telegram! Do not believe anyone claiming to be me off-forum without a signed message from the above address! Accept no excuses and make no exceptions!
maaku
Legendary
*
expert
Offline Offline

Activity: 905
Merit: 1011


View Profile
April 28, 2014, 05:43:19 PM
 #8

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

I'm an independent developer working on bitcoin-core, making my living off community donations.
If you like my work, please consider donating yourself: 13snZ4ZyCzaL7358SmgvHGC9AxskqumNxP
Schleicher
Hero Member
*****
Offline Offline

Activity: 675
Merit: 513



View Profile
April 28, 2014, 09:05:09 PM
 #9

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';

maaku
Legendary
*
expert
Offline Offline

Activity: 905
Merit: 1011


View Profile
April 29, 2014, 06:31:14 AM
 #10

Try rounding to 8 decimal digits of precision, like you would with bitcoin.

I'm an independent developer working on bitcoin-core, making my living off community donations.
If you like my work, please consider donating yourself: 13snZ4ZyCzaL7358SmgvHGC9AxskqumNxP
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!