-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow integer revision
in TypedData.Domain
#449
Conversation
- Convert `revision` from `TypedData.Revision` to `JsonPrimitive` - Add `resolvedRevision` val that parses `TypedData.Revision` from both strings and integers - Use `resolvedRevision` instead of `revision` where applicable
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #449 +/- ##
==========================================
- Coverage 71.12% 69.26% -1.86%
==========================================
Files 75 75
Lines 3338 3254 -84
Branches 367 361 -6
==========================================
- Hits 2374 2254 -120
- Misses 798 845 +47
+ Partials 166 155 -11 ☔ View full report in Codecov by Sentry. |
Even though this change is not breaking for typed data where |
@Transient | ||
val resolvedRevision = revision?.let { | ||
// Allow both string and integer values for revision | ||
lenientJson.decodeFromJsonElement<Revision>(it) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if usage of isLenient
is necessary here. kotlinx.serialization
properly understands and maps enum Revision
value by the provided serial name. Then "1"
and 1
will both be correctly interpreted as Revision.V1
, without the need of lenient mode.
Then instead of lenientJson.decodeFromJsonElement<Revision>(it)
we can use
Json.decodeFromJsonElement<Revision>(it)
and get rid of companion object with private val lenientJson
.
Just want to make clear, whether adopting a lenient mode is needed, because based on the lenient json spec
Removes JSON specification restriction (RFC-4627) and makes parser more liberal to the malformed input.
@THenry14 wdyt?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
properly understands and maps enum Revision value by the provided serial name.
As far as I remember, it doesn't. But maybe decodeFromJsonElement
is indeed able to handle that without lenient mode. In that case, it may be unnecessary as you suggest.
Removes JSON specification restriction (RFC-4627) and makes parser more liberal to the malformed input.
The intention behind lenient mode here was:
In lenient mode quoted boolean literals, and unquoted string literals are allowed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, decodeFromJsonElement
is able to handle that. Let's remove lenientJson
then, as we discussed offline.
… into chore/448-typed-data-int-revision
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@@ -548,7 +548,7 @@ internal class TypedDataTest { | |||
"name": "DomainV1", | |||
"version": "1", | |||
"chainId": "2137", | |||
"revision": "1" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we have a test with "1" as well? I suppose it may still be possible to have such response, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct, considering "1"
may occur in response, then these tests should be also added.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think "1"
is possible in revision 1 per the starknet-io/SNIPs#79
Besides, this case is covered by revision 0 typed data tests anyway, so probably we don't need any additional tests
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so it is possible to get a shortstring, but this is atm limited to revision 0 right? so either way we need some test that have the revision as string, although if the snip is to be believed this should only occur for rev 0.
Note: The value of the field
revision
is the integer1
eventhough the type of the field isshortstring
I find this a bit confusing :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but this is atm limited to revision 0 right?
Well yeah, but also:
- revision (optional): the revision of the specification to be used. If the value is omitted it will default to
0
.
- Revision
0
: Represents the de facto spec before this SNIP was published. The purpose is to help with backwards compatibility. It’s not recommended to use it.
We can add the test just for the sake of it, but we're testing something very unlikey
I find this a bit confusing :D
It is, but apparently handling shortstrings as ints or vice versa is a typical thing for typed data as I previously discovered trying to introduce some additional type checks which resulted in tests failing for existing examples
Co-authored-by: Maksim Zdobnikau <43750648+DelevoXDG@users.noreply.github.com>
Co-authored-by: Maksim Zdobnikau <43750648+DelevoXDG@users.noreply.github.com>
val domainTypeV1 = "StarknetDomain" to listOf( | ||
TypedData.StandardType("name", "shortstring"), | ||
TypedData.StandardType("version", "shortstring"), | ||
TypedData.StandardType("chainId", "shortstring"), | ||
TypedData.StandardType("revision", "shortstring"), | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can domain types from InvalidTypesTest
to avoid duplication here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can't - domainTypeV1
used in InvalidTypesTest
is accessible only in its scope, therefore it cannot be accessed in in domain v1 object with string revision
test.
It's possible to create domainTypeV1
field directly in TypedDataTest
, but I don't think its a good solution. Wdyt? @DelevoXDG
val domainObjectV1WithStringRevision = """ | ||
{ | ||
"name": "DomainV1", | ||
"version": "1", | ||
"chainId": "2137", | ||
"revision": "1" | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, let's make it domain v0 with revision. Because technically only v0 domain can have a string revision
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Describe your changes
TypedData.Domain
can now be decoded from the following json, whererevision
is an integer:domain v0 object with string revision
inTypedDataTest
Linked issues
Closes #448
Breaking changes
TypedData.Domain.Revision
is now of typeJsonPrimitive?
instead ofTypedData.Revision?
. UseTypedData.Domain.resolvedRevision
to access revision asTypedData.Revision