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

Decode numbers using json.Decoder #148

Closed
wants to merge 5 commits into from

Conversation

matthew1001
Copy link
Contributor

@matthew1001 matthew1001 commented Aug 22, 2024

If the params passed in for a contract deploy include very large numbers, json.Unmarshal to an interface{} doesn't work and results in an incorrect number being passed in to the contract's constructor.

To recreate the issue, if you checkout just the UT changes from this branch and run them it will fail.

This PR switches json.Unmarshal to json.Decode.

Signed-off-by: Matthew Whitehead <[email protected]>
Signed-off-by: Matthew Whitehead <[email protected]>
Signed-off-by: Matthew Whitehead <[email protected]>
Signed-off-by: Matthew Whitehead <[email protected]>
@matthew1001 matthew1001 marked this pull request as ready for review August 22, 2024 15:19
@matthew1001 matthew1001 requested a review from a team as a code owner August 22, 2024 15:19
Copy link
Contributor

@EnriqueL8 EnriqueL8 left a comment

Choose a reason for hiding this comment

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

Looks good - just one comment on testing with FireFly Signer and understanding if not only the number is there in RLP but also the things around it like where the number starts

@@ -95,7 +96,9 @@ func (c *ethConnector) prepareDeployData(ctx context.Context, req *ffcapi.Contra
ethParams := make([]interface{}, len(req.Params))
for i, p := range req.Params {
if p != nil {
err := json.Unmarshal([]byte(*p), &ethParams[i])
decodedParam := json.NewDecoder(bytes.NewReader([]byte(*p)))
decodedParam.UseNumber()
Copy link
Contributor

Choose a reason for hiding this comment

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

From what I can read this stores the number in the string representation, have you checked that FireFly Signer supports this?

Copy link
Contributor

Choose a reason for hiding this comment

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

Just thinking of how the RLP encode code there would treat this

Copy link
Contributor

Choose a reason for hiding this comment

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

Comment on lines +99 to +101
decodedParam := json.NewDecoder(bytes.NewReader([]byte(*p)))
decodedParam.UseNumber()
err := decodedParam.Decode(&ethParams[i])
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 need to fix the issue in https://github.com/hyperledger/firefly-common/blob/main/pkg/fftypes/jsonany.go#L51 if the issue is how data gets unmarshalled

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed - and it probably needs a quick search of the code for other places where json.Unmarshal() is used as well

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Going to prove out this fix with an end-to-end contract deploy first to check that the fix is good (beyond the UTs)

Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry @matthew1001 - I'm not sure I understand why there's a concern with json.Unmarshal()

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok - I do think I now understand, but the right fix (which I think would probably include json.Unmarshal) would take time to investigate

Signed-off-by: Matthew Whitehead <[email protected]>
"outputs":[],
"type":"constructor"
}],
"params": [ 10000000000000000000000001, "some-text" ]
Copy link
Contributor

Choose a reason for hiding this comment

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

This input is broken in JSON, it's attempting to use a number that does not fit into int64

Copy link
Contributor

@peterbroadhurst peterbroadhurst left a comment

Choose a reason for hiding this comment

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

...

Copy link
Contributor

@peterbroadhurst peterbroadhurst left a comment

Choose a reason for hiding this comment

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

ok - sorry, after some misunderstanding I now understand what this PR is trying to achieve.

This PR is an enhancement to support:

  • JSON input in the params array is able to contain JSON number elements larger than fit into an int64.

One part of the fix, is that Golang provides an option on json.Decoder (not available on json.Unmarshal) to decode numbers into json.Number types (which are strings).

If that is done in this one piece of the stack, then it has implications for other places that need to be reviewed:

  • firefly
  • firefly-signer

With this done, a user choosing to generate a JSON input containing JSON number > that is possible to generate in Javascript/Java/Go serialization of numbers could be supported by the stack.

@matthew1001
Copy link
Contributor Author

Thanks for the comments @peterbroadhurst, @Chengxuan, @EnriqueL8 - I might grab some in-person time with @EnriqueL8 to discuss options & other places in the stack that will be affected. I'll circle back round on this PR once I've done that.

@matthew1001
Copy link
Contributor Author

This PR has provoked some useful discussion around large number support. After some discussions I'm closing it in lieu of:

@matthew1001 matthew1001 deleted the json-numbers branch August 27, 2024 14:34
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.

4 participants