Define canonical JSON encoding for unsigned 64-bit integers #343
No reviewers
Labels
No labels
breaking change
bug
documentation
enhancement
needs discussion
needs implementation
new nut
ready
wallet-only
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
forgejo-admin/nuts!343
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "robwoodgate/json-int"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The NUTs define amounts as unsigned 64-bit integers, but the JSON wire encoding is ambiguous.
JSON has no integer type, and many clients parse JSON numbers via float-like defaults. This can cause cross-language divergence and precision loss for large values (e.g, in environments where JSON numbers use IEEE-754).
This PR defines a canonical
UInt64Jsonformat, which is backwards compatible and precision safe across runtimes.Simply:
This applies to
int/u64fields across the protocol, including amounts in Proofs, Blinded Messages, and request/response payloads.Fee fields are unchanged to keep the change minimal, but we could include all int/u64 JSON fields for consistency.
When exactly are the amounts bigger than
(2^53-1)?Just look at Minibits key amounts: https://mint.minibits.cash/Bitcoin/v1/keys
Keys
9007199254740992up to9223372036854775808are all over the safe limit (9007199254740991)Amounts in millisats (eg melt quotes, amounts in unit
msat) can go over the limit.Even if not used 99.99% of the time, the wire support must be solid.
Yeah, I agree that if amounts are listed in msats, then we need this.
@ -64,0 +68,4 @@For JSON fields, `int` / `u64` values may be encoded as a JSON integer number or a base-10 decimal string.Implementations **MUST** accept both forms.If we want to encourage a single standard (decimal string) over time, we could tweak:
We already consistently use string amounts in the
/v1/keysapi, so this would be a continuation of that precedent.I think this is too excessive. NUT-00 could state that all amounts are uint64 and we could leave the rest as is.
When you say 'uint64', do you mean non-quoted integers?
As mentioned by others, key amounts are quoted currently , but fees are non-quoted. Both of those, I think, make sense as fees can't realistically get very big
Ignore this comment. I oversimplified. See Rob's response just below
(Maybe I've missed some detail/context, but I think this will break stuff)
The CDK code currently requires the amounts (in the amount-publickey mapping in a keyset) to be quoted, i.e.
"8"not8.In this screenshot, 'key' means the 'amount' and 'value' means the mint's public key for that amount.
So basically, I don't think we can change anything about existing fields
=======
An AI helped me find this example. (Apologies if I'm wrong, and have been misled by AI)
Key amounts ARE all strings, and that is perfect. Not suggesting a change there at all.
In a perfect world, ALL u64 amounts would be represented as strings in JSON.
The issue is "amounts" (sums of key amounts), which currently transport as numeric digits, and which CAN be > 2^53-1 because a) some keys are already larger than that, and b) combinations of proofs could go over the limit in total.
Especially with millisat (or in future, nanosat) amounts.
Fee amounts can stay as numeric digits, as it would be crazy if fees went over the limit.
I have trimmed it down to essentially the NUT-00 change. LMK if you want other changes.
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.Merge
Merge the changes and update on Forgejo.Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.