-
Notifications
You must be signed in to change notification settings - Fork 92
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
New utility modules for handling errors and checking types #178
Merged
Merged
Changes from 5 commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
331ceec
feat(utils): add new utility modules for errors and types
cedoor 0f2ee83
build(utils): remove declarations when using output.dir option
cedoor 309510b
refactor(utils): re-use zk-kit utility functions
cedoor 759f122
chore: update lock file
cedoor 3d6c6df
style(eddsa-poseidon): fix lint error
cedoor 30be5b8
refactor(utils): rename packing to proof-packing
cedoor 6e81e2f
docs(utils): add throws js-doc tag
cedoor 932b4c5
refactor(utils): update error messages
cedoor 2dde56a
refactor(utils): rename errors re object checks
cedoor File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Not strictly related to this PR, and I'm not sure if it's actionable, but I wanted to share some feedback about my experience with this. I think the level of flexibility on inputs here has a downside that the caller may not always be sure how the input is being interpreted, which could have an impact for compatibility.
For example, in my tests using this library, I was using a test private key borrowed from here: https://github.com/iden3/circomlibjs/blob/4f094c5be05c1f0210924a3ab204d8fd8da69f49/test/eddsa.js#L103
That key is intended to be a hex string representing 32 bytes of key to be hashed by the initial blake hash below. That's how I need to interpret it to remain consistent with existing uses of EdDSA in Zupass. However the hex digits happen to all be in the range 0-9, so it was being interpreted as a stringified bigint. This worked but was treating my string as a different key than I intended. If any of my digits had been A-F, it would've instead treated my key as a raw string of 64 bytes, rather than 32 bytes, which again would've silently worked, but been treating it as a different key. What I should have done (and will now do) is convert my string into a buffer in advance using
Buffer.from(pk, "hex")
, meaning I'll be bypassing all the type flexibility here.As I said, I'm not sure if there's a proposal here, but I suggest thinking about the tradeoff between accepting flexible input, vs. being stricter in order to make sure users are only getting the behavior they expect. Given that this function also accepts arbitrary strings (like passwords?), I think it might be best not to accept stringified bigints too, since it's impossible to know what the user's intent if the string happens to be made up of digits. This is the kind of behavior which might be difficult to maintain compatibly if the code ever changes.
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.
There's actually another related point which I think is a potential bug. If I put a "0x" before my private key, it's interpreted as hex, but ends up as a 31-byte buffer rather than a 32-byte buffer. The reason is that the hex string starts with
00
, and the conversion from string -> bigint -> buffer ends up truncating the leading zeroes. I'm not sure what you think is "correct" here, but if you intend bigints to be converted into fixed-size buffers, you should pass a size parameter 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.
Actually I discovered that the conversion issue I mentioned was only in my test code, not my intended production library, which was already calling
Buffer.from(pk, "hex")
. My point about the potential for confusion and mistakes remains, though it seems I don't have a major issue to fix on my side. I'm going to be writing more compatibility tests to rule out this kind of issue in future.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 totally agree and I'd propose the following types: arbitrary strings (yes like passwords, we should keep this as it seems the most common use-case to me),
bigint
,number
,Buffer
, or hex strings (must start with '0x'). It would be like now, but withoutbigint
strings. Ofc we'd need to add more doc.I realized
message
is a bit different here, it must be a 32-byte value, so we should check the arbitrary string length I guess.This is something we should think about now, before making this lib stable IMO. Let me know what you think.
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.
The problem here is the way
bigNumberishToBuffer
converts hexadecimal strings to buffers. It could convert it by usingBuffer.from(n, "hex")
if it's a hex string. "0x" should be removed before converting it ofc. IMO if the hex starts with zeroes it should consider them when converting to buffer. How does it sound?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.
Also, we could create separate issues for these conversations and close this PR. It looks like there are three:
privateKey
parametersize
parameter to the bigNumberish functions - ishmessage
parameterOther issues could be included in these 3. Missing anything?
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'm good with breaking things out. Quick responses to your latest thoughts:
Size parameters seem like a lot of overhead, particularly if they're usually forced to be 32. Using a type like Buffer/Uint8Array/string which has its own size seems like the cleanest way to do that, but I think bigint is actually the clearest/simplest type for most of this library since it avoids byte order issues. As discussed elsewhere, this private key is distinct because it's an input of bytes, not of a field element.
I think the question of which input encoding (Buffer, hex string, etc) for private keys is fuzzy enough that it's going to be hard to do right for all users. In Zupass, I've standardized on hex strings, and we have
toHexString
/fromHexString
helpers to convert from/to Buffers. That's mostly because that was the standard set by the EdDSATicketPCD, and I want simplicity and clarity. There are situations in which I might consider performance most important, where I might already have my bytes in a Buffer and resent the need to convert it to hex unnecessarily. But I come from lower-level languages than JavaScript, so I'm not sure how much that level of micro-optimization really matters.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.
Just to add another wrinkle to string encodings: The Zupass/PCD standard is hex strings without the 0x prefix. I think that actually makes sense when you're encoding an arbitrary-length array of bytes, because 0x to me suggests a single number. But it is part of what lead to the ambiguity which started this conversation (because my test key happened to contain only the digits 0-9).
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.
That's the point I think. In this case, we have an algorithm implementation and even if it is JS perhaps it is better to minimize conversions and type-checks in functions and prioritize performances, but also give devs an optimal experience.
Re: #188.
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.
That makes sense. If we add new utility functions to convert hex to buffer or buffer to hex we shouldn't use
0x
. In the other cases, it makes sense to use0x
as they are mostly conversions between bigints and hexadecimal.Re: #189.