Values discrepancies

+4 votes

We are running Multichain 1.0.7

Is there a reason for an asset having different "balances" depending on the place were we are retrieving the information.

Using the Multichain explorer for a given address the asset BCH displays different values between raw unit and balance.

ASSET NAMEASSET REFERENCETRANSACTIONSRAW UNITSBALANCE
BCH 22786-266-701559999900000051371829999900000.05137062

Using Multichain-cli and the API I get the following values for the same address / asset.

{
    "1bK4krhKKFFQeFNxaA91yD11kWpt3KbDLdHoX2" : [
        {
            "name" : "BCH",
            "assetref" : "22786-266-7015",
            "qty" : 9999900000.05137253
        }
    ],
    "total" : [
        {
            "name" : "BCH",
            "assetref" : "22786-266-7015",
            "qty" : 9999900000.05137253
        }
    ]
}

 

The issue command was the following:

  • issue 1bK4krhKKFFQeFNxaA91yD11kWpt3KbDLdHoX2 '{"name":"BCH","open":true}' 10000000000 0.00000001 0

 

asked Jan 10 by jgodinho

1 Answer

0 votes

You are coming up here against the limitations of JSON's accuracy in representing floating point numbers. The best solution is to have a lower number of raw units, probably by making the asset divisible into units of 0.00001 instead of 0.00000001. If that's not an option, you should use raw quantities throughout your application, although note that these are not available in all APIs.

answered Jan 10 by MultiChain
We made tests in the past regarding the precision with the REST API. Our findings were that we could go to 8 decimals places.

I made another test and the balance on the destination address presents different values on Multichain Explorer and multichain-cli only for the destination address. If there is a precision issue with JSON shouldn't the source address balance display the same behaviour ?

The balance on the destination address after the transaction is only correct for the raw units displayed in the Multichain Explorer.

The test was the following
**********************************************************************************************************************************************

Balances Before:

{"method":"getmultibalances","params":["1W1Ky9BKsgibPnHMthi656uK4zuN7pGBXZAEru","BCH"],"id":"45510015-1547164350","chain_name":"sandboxChain"}

{
    "1W1Ky9BKsgibPnHMthi656uK4zuN7pGBXZAEru" : [
        {
            "name" : "BCH",
            "assetref" : "22786-266-7015",
            "qty" : 99999.94862818
        }
    ],
    "total" : [
        {
            "name" : "BCH",
            "assetref" : "22786-266-7015",
            "qty" : 99999.94862818
        }
    ]
}

BCH    22786-266-7015    4    9999994862818    99999.94862818 (Multichain Explorer)

{"method":"getmultibalances","params":["1bK4krhKKFFQeFNxaA91yD11kWpt3KbDLdHoX2","BCH"],"id":"80696522-1547164403","chain_name":"sandboxChain"}

{
    "1bK4krhKKFFQeFNxaA91yD11kWpt3KbDLdHoX2" : [
        {
            "name" : "BCH",
            "assetref" : "22786-266-7015",
            "qty" : 9999900000.05137253
        }
    ],
    "total" : [
        {
            "name" : "BCH",
            "assetref" : "22786-266-7015",
            "qty" : 9999900000.05137253
        }
    ]
}

BCH    22786-266-7015    5    999990000005137182    9999900000.05137062 (Multichain Explorer)

----------------------------------------------------------------------------------------------------------------------------------------------
Send Asset:

createrawsendfrom 1W1Ky9BKsgibPnHMthi656uK4zuN7pGBXZAEru '{"1bK4krhKKFFQeFNxaA91yD11kWpt3KbDLdHoX2":{"BCH":0.01712394}}'
signrawtransaction....
sendrawtransaction....

----------------------------------------------------------------------------------------------------------------------------------------------
After:

{"method":"getmultibalances","params":["1W1Ky9BKsgibPnHMthi656uK4zuN7pGBXZAEru","BCH"],"id":"11434046-1547164700","chain_name":"sandboxChain"}

{
    "1W1Ky9BKsgibPnHMthi656uK4zuN7pGBXZAEru" : [
        {
            "name" : "BCH",
            "assetref" : "22786-266-7015",
            "qty" : 99999.93150424
        }
    ],
    "total" : [
        {
            "name" : "BCH",
            "assetref" : "22786-266-7015",
            "qty" : 99999.93150424
        }
    ]
}

BCH    22786-266-7015    5    9999993150424    99999.93150424 (Multichain Explorer)

{"method":"getmultibalances","params":["1bK4krhKKFFQeFNxaA91yD11kWpt3KbDLdHoX2","BCH"],"id":"77530532-1547165061","chain_name":"sandboxChain"}

{
    "1bK4krhKKFFQeFNxaA91yD11kWpt3KbDLdHoX2" : [
        {
            "name" : "BCH",
            "assetref" : "22786-266-7015",
            "qty" : 9999900000.06849480
        }
    ],
    "total" : [
        {
            "name" : "BCH",
            "assetref" : "22786-266-7015",
            "qty" : 9999900000.06849480
        }
    ]
}

BCH    22786-266-7015    6    999990000006849576    9999900000.06849480 (Multichain Explorer)


9999900000,05137253 + 0,01712394 = 9999900000,06849647 (Multichain-cli)
9999900000,05137182 + 0,01712394 = 9999900000,06849576 (Multichain Explorer Raw Units)
9999900000,05137062 + 0,01712394 = 9999900000,06849456 (Multichain Explorer Balance)
The accuracy of floating point numbers in JSON is not based on decimal places, but based on significant digits. So the number of decimal places of accuracy will depend on how many digits there are before the decimal place.

For many purposes the MultiChain Explorer reads raw data from transactions, which is why it's more accurate than the JSON-RPC API.
Just focusing on the balances reported by Multichain explorer...we experience discrepancies between the raw units and balance values.

 - BCH    22786-266-7015    9    999990000008639547 9999900000.08639526
 - The asset quantity multiple = 100000000

If we take the raw units 999990000008639547 / 100000000 = 9999900000,08639547

Shouldn't this value be the same as the balance (9999900000.08639526)?
We checked the Multichain Explorer source code and on the util.py file and with a small change of code in line 1086 you can solve this issue:

 #v = float(rawqty) / float(multiple)
 v = decimal.Decimal(rawqty) / decimal.Decimal(multiple)

JSON is just a data exchange format in plain text....the precision issues in on the language used to do the parsing.
...