SatSale/SatSale

Off by one millisatoshi, payment never completes (LN)

Opened this issue · 3 comments

Had situation today - LN invoice (CLN) was generated for 58999msat, but SatSale does not know anything about millisatoshis, so it rounded up everything to 0.00000059 BTC (59000msat). Invoice got paid correctly, but SatSale still thinks it wasn't paid because 58999 < 59000.

Fast workaround would be to always round down BTC amounts, so it would be 0.00000058 BTC here (don't think anybody currently cares about +/- 1 sat).

In loger term IMO SatSale should internally everywhere use msat integers instead of BTC floats. There are similar one off problems possible with float, as it is by definition approximation not exact value.

Ok, no, SatSale actually calculated 0.00000059 BTC before generating CLN invoice. Problem is here:

# Multiplying by 10^8 to convert to satoshi units
msats_amount = int(float(btc_amount) * 10 ** (3 + 8))

Because:

>>> int(float(0.00000059) * 10 ** (3 + 8))
58999

Same bug would be hit with LND, which uses sat instead of msat, here too:

>>> int(float(0.00000059) * 10 ** 8)
58

Would it be worth changing these calculations to use the ceil() function in the math library. I believe this would ensure that any number always rolls over to the next integer ensuring no odd rounding errors.

>>> from math import ceil
>>> ceil(float(0.00000059) * 10 ** 8)
59

I chose to use ceil() instead of round() just to ensure there were no round down edge cases.
I'm not sure if this would fix the problem exactly but I can't think of any cases where it would cause additional problems.