Skip to content
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

Merged
merged 13 commits into from
May 15, 2024

Conversation

DelevoXDG
Copy link
Collaborator

@DelevoXDG DelevoXDG commented Mar 21, 2024

Describe your changes

  • TypedData.Domain can now be decoded from the following json, where revision is an integer:
"domain": {
    "name": "Starknet Example",
    "version": "1",
    "chainId": "SN_MAIN",
    "revision" : 1
  },
  • Add domain v0 object with string revision in TypedDataTest

Linked issues

Closes #448

Breaking changes

  • This issue contains breaking changes
  • TypedData.Domain.Revision is now of type JsonPrimitive? instead of TypedData.Revision?. Use TypedData.Domain.resolvedRevision to access revision as TypedData.Revision

- 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-commenter
Copy link

codecov-commenter commented Mar 21, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 69.26%. Comparing base (d28b008) to head (ad53b98).
Report is 4 commits behind head on main.

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.
📢 Have feedback on the report? Share it here.

@DelevoXDG
Copy link
Collaborator Author

DelevoXDG commented Mar 21, 2024

Even though this change is not breaking for typed data where revision is a string, I suppose it's best we wait for starknet-io/SNIPs#79 to be merged.

@Transient
val resolvedRevision = revision?.let {
// Allow both string and integer values for revision
lenientJson.decodeFromJsonElement<Revision>(it)
Copy link
Contributor

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?

Copy link
Collaborator Author

@DelevoXDG DelevoXDG May 6, 2024

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.

Copy link
Contributor

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.

Copy link
Contributor

@franciszekjob franciszekjob left a 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"
Copy link
Member

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?

Copy link
Contributor

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.

Copy link
Collaborator Author

@DelevoXDG DelevoXDG May 10, 2024

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

Copy link
Member

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 integer 1 eventhough the type of the field is shortstring

I find this a bit confusing :D

Copy link
Collaborator Author

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

franciszekjob and others added 3 commits May 10, 2024 11:22
Co-authored-by: Maksim Zdobnikau <43750648+DelevoXDG@users.noreply.github.com>
Co-authored-by: Maksim Zdobnikau <43750648+DelevoXDG@users.noreply.github.com>
Comment on lines 748 to 753
val domainTypeV1 = "StarknetDomain" to listOf(
TypedData.StandardType("name", "shortstring"),
TypedData.StandardType("version", "shortstring"),
TypedData.StandardType("chainId", "shortstring"),
TypedData.StandardType("revision", "shortstring"),
)
Copy link
Collaborator Author

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.

Copy link
Contributor

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

Comment on lines 740 to 746
val domainObjectV1WithStringRevision = """
{
"name": "DomainV1",
"version": "1",
"chainId": "2137",
"revision": "1"
}
Copy link
Collaborator Author

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

Copy link
Collaborator Author

@DelevoXDG DelevoXDG left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@franciszekjob franciszekjob merged commit a3c8f8e into main May 15, 2024
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

revision value in typed data revision 1 should be an integer
4 participants