XRPLF / xrpl.js

A JavaScript/TypeScript API for interacting with the XRP Ledger in Node.js and the browser
https://xrpl.org/
1.2k stars 511 forks source link

Transaction signing corrupts floating point string #738

Closed professorhantzen closed 6 years ago

professorhantzen commented 7 years ago

Supply rippleAPI.sign with a JSON string for an OfferCreate transaction containing a floating point string as TakerPays. Choose a value with a large number of digits. Sometimes this creates a serialised transaction with the correct value embedded, other times the value becomes corrupted.

This has been verified by taking the serialised output from the sign function, and sending it to the websocket server at wss://s-west.ripple.com:51233 and comparing the output.

Eg, inputting the following JSON into api.sign:

TakerPays: 
   { currency: 'BTC',
     issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B',
     value: '0.01153351040117655' }

Results in a serialised transaction that rippled interprets as:

"TakerPays":
{"currency":"BTC",
"issuer":"rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
"value":"0.01153351040117655"}

vs inputting:

TakerPays: 
   { currency: 'BTC',
     issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B',
     value: '0.19999999999999991' }

Which results in:

"TakerPays":
{"currency":"BTC",
"issuer":"rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
"value":"1841616395.698057"}
--- Want to back this issue? **[Post a bounty on it!](https://www.bountysource.com/issues/39092523-transaction-signing-corrupts-floating-point-string?utm_campaign=plugin&utm_content=tracker%2F323756&utm_medium=issues&utm_source=github)** We accept bounties via [Bountysource](https://www.bountysource.com/?utm_campaign=plugin&utm_content=tracker%2F323756&utm_medium=issues&utm_source=github).
sublimator commented 7 years ago

ripple-binary-codec needs to check the significant digits is no greater than 16 probably. RippleAPI probably doesn't with the simple json schema.

sublimator commented 7 years ago

0.1999 9999 9999 9999 1

17 significant digits.

On 9 Nov 2016 11:46 p.m., "Nicholas Dudfield" ndudfield@gmail.com wrote:

ripple-binary-codec needs to check the significant digits is no greater than 16 probably. RippleAPI probably doesn't with the simple json schema.

sublimator commented 7 years ago

If I get to my pc b4 someone else fixes it I'll fix it.

professorhantzen commented 7 years ago

Thank you! What form of fix is likely? Will ripple-binary-codec return an error if the supplied value exceeds 16 significant digits, or will it round the value?

Also, a temporary workaround for inputs into the current sign function:

var floatingPointString = '0.19999999999999991';
floatingPointString = ''+(floatingPointString*1).toPrecision(16)/1;

The multiply by 1 casts the string to a number, toPrecision reduces it to 16 significant digits, dividing by 1 removes trailing zeroes. Finally, the addition to an empty string converts the number to a string.

sublimator commented 7 years ago

Earth to ripple? @clark800? Who maintains this these days?

intelliot commented 6 years ago

This should be fixed as of ripple-lib 0.17.5 and later.