swarm-game / swarm

Resource gathering + programming game
Other
841 stars 52 forks source link

Web interface truncates 64-bit integers #645

Open byorgey opened 2 years ago

byorgey commented 2 years ago

While looking at the debugging output dumped via the web interface, it kind of seemed like all the entity hashes ended with two or more zeros. Not yet sure whether this is really a bug or what's going on, but putting this issue here as a placeholder to remind me to look into it more.

byorgey commented 2 years ago

I investigated a little bit today and it seems like the hashes are being output incorrectly in the web interface. For example, when I load the entity map and ask for the hash of the clock entity in ghci, I get 5249364704666728555. However, when I go to localhost:5357/robots/, the clock stored in the base robot is listed as having hash 5249364704666728000.

byorgey commented 2 years ago

Seems like a problem with JavaScript using a mantissa of only 2^53, resulting in 64-bit integer values being truncated. See e.g. https://stackoverflow.com/a/34989371 . Perhaps we need to modify our JSON instances to read and write 64-bit integers as string values.

To be clear, it seems like there is nothing wrong with the ToJSON instances per se. 64-bit integers get turned via the ToJSON Int instance into a Number (from the scientific package) which can represent arbitrary-precision numbers via a mantissa and exponent. But at some point along the way I guess the resulting number gets processed by JavaScript and loses precision.

xsebek commented 2 years ago

@byorgey using strings sounds good to me, we can serialize and parse hex strings so that the output is more readable.

As a side note, I hope that JavaScript never comes close to our Haskell code and stays confined to the VSCode plugin. :laughing:

I would be very interested as to what exactly processed the numbers wrong - whether it is our fault or Aeson's. :thinking:

byorgey commented 2 years ago

I would be very interested as to what exactly processed the numbers wrong - whether it is our fault or Aeson's.

I am curious too, but I haven't figured it out so far.

λ> :m +Data.Aeson
λ> toJSON (maxBound :: Int)
Number 9.223372036854775807e18
λ> encode (maxBound :: Int)
"9223372036854775807"

all looks OK. It seems like Swarm.Web is just doing some normal servant stuff to serve robots as JSON. I tried looking in the servant source to see what it's doing. It seems like it should go through the MimeRender JSON a instance, but that just calls encode from aeson, which works fine. Somewhere the number is getting turned into a Double and losing precision, but I can't figure out where.

byorgey commented 7 months ago

Looked into this briefly today, and I think we now only store entity names in robot inventories, so I'm not sure it's possible to see entity hashes in the web UI any more. (It probably should be though.)