This is a two-patch patch against 0.3.24 (since master has a lot of churn in rpc.cpp and I don't want to do all the work merging until I know that this patch has community support).
The first commit adds RPC versioning support. As things need to be changed, older clients still need to be supported in some way. This has been done by taking a numeric token from the URL and using that to determine the version. So if the API is accessed at http://localhost:8332/ then it will use version 0. If http://localhost:8332/bitcoin.v1 then it will use version 1. And of course, http://localhost:8332/bitcoin.v2 would be version 2. For the purposes of versioning, I am declaring versions 0 and 1 identical, to avoid confusion.
The second commit does two things:
- Instead of requiring a JSON number, BTC amounts may now be sent as strings.
- If the service is accessed using version 2 or higher, BTC amounts will be returned as strings instead of numbers.
This is an important change, because not all JSON libraries store numbers in a format with 16 decimal digits of precision. I've tested, and when I set bitcoind's paytxfee setting to 10000000.00000001, Python is unable to handle this many significant digits; it represents the number as 10000000.000000009. While not off by much, it does seem to indicate that representing amounts as pure numbers in JSON data may cause some clients to have accuracy issues.
By taking the amounts directly from int64s to strings, the client is free to convert the values to whatever high-precision format it wants (like the Decimal type in Python).
However, while many languages will convert strings to numbers automatically, many will not, so this change won't be backwards-compatible; hence the new API versioning feature.
Here are the effects of this branch, using Python:
>>> bitcoindv0 = jsonrpclib.Server("http://chris:testing@localhost:8332/")
>>> bitcoindv1 = jsonrpclib.Server("http://chris:testing@localhost:8332/bitcoin.v1")
>>> bitcoindv2 = jsonrpclib.Server("http://chris:testing@localhost:8332/bitcoin.v2")
>>> bitcoindv0.getinfo()[u'balance'];
0.10000000000000001
>>> bitcoindv1.getinfo()[u'balance'];
0.10000000000000001
>>> bitcoindv2.getinfo()[u'balance'];
u'0.10000000'