-
Notifications
You must be signed in to change notification settings - Fork 12k
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
Add missing tests to ECSDA #1248
Add missing tests to ECSDA #1248
Conversation
Can you rebase from |
@nventuro updated. |
test/library/ECRecovery.test.js
Outdated
// The last two hex digits are the signature version. | ||
// The only valid values are 0, 1, 27 and 28. | ||
// eslint-disable-next-line max-len | ||
const signature = '0x331fe75a821c982f9127538858900d87d3ec1f9f737338ad67cad133fa48feff48e6fa0c18abc62e42820f05943e47af3e9fbe306ce74d64094bdf1691ee53e002'; |
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.
Why is this signature different from the others? Shouldn't just the version differ? If so, I'd abstract out the signature prefix, and add the suffix in each test.
But more importantly, why is the signature hardcoded and not generated in the test? :/
test/library/ECRecovery.test.js
Outdated
@@ -30,6 +30,33 @@ contract('ECRecovery', function ([_, anyone]) { | |||
(await this.mock.recover(TEST_MESSAGE, signature)).should.equal(signer); | |||
}); | |||
|
|||
it('recover v27', async function () { |
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.
If possible, these may read more clearly with a structure like the following one:
context with valid signature
context with v27 signature
it works
context with v28 signature
it works
context with invalid version signature
it reverts
context with invalid signature
it reverts
(the test itself should probably be abstracted into a function to avoid repetition)
@nventuro please take another look. |
test/library/ECDSA.test.js
Outdated
@@ -14,48 +14,101 @@ contract('ECDSA', function ([_, anyone]) { | |||
this.mock = await ECDSAMock.new(); |
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.
While we're at it, can you rename this to this.ecdsa
or something more descriptive?
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.
done.
const signer = '0x2cc1166f6212628a0deef2b33befb2187d35b86c'; | ||
// eslint-disable-next-line max-len | ||
const signatureWithoutVersion = '0x5d99b6f7f6d1f73d1a26497f2b1c89b24c0993913f86e9a2d02cd69887d9c94f3c880358579d811b21dd1b7fd9bb01c1d81d10e69f0384e675c32b39643be892'; | ||
context('with 00 as version value', function () { |
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.
Please add an empty line before this context
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.
done
(await this.mock.recover(TEST_MESSAGE, signature)).should.equal(signer); | ||
}); | ||
context('recover with valid signature', function () { | ||
context('with v0 signature', function () { |
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.
Shouldn't we have a case for v0 (and v1) signatures, where the version is incorrect?
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 so. We check the version first, and if it's not 0/1/27/28, we return 0. It doesn't matter if the rest of the signature makes sense or not.
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 an internal detail though 😛 I wanted to include that it
inside this context
, to make it clear that all signatures fail if the version is wrong
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.
alright. I kind-of thing that's a myth that you can (and should) keep your tests totally independent from the implementation. But I'll follow your advice here. One less magic number anyway.
test/library/ECDSA.test.js
Outdated
// Signature generated outside ganache with method web3.eth.sign(signer, message) | ||
const version = '00'; | ||
const signature = signatureWithoutVersion + version; | ||
(await this.mock.recover(TEST_MESSAGE, signature)).should.equal(signer); |
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'd create a function as follows:
async function shouldRecoverSigner() {
(await this.mock.recover(TEST_MESSAGE, this.signatureWithoutVersion + this.version)).should.equal(this.signer);
}
then have each context
assign version
and friends in a beforeEach
, and then simply do
it('works', async function () {
await shouldRecoverSigner();
});
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.
I'm slightly against this. I think the duplication here makes every test easier to read independently. shouldRecoverSigner hides how recover works, and for tests I tend to value more the expressiveness of each one than the amount of code. I find this.ecdsa.recover(TEST_MESSAGE, signature)).should.equal(signer);
nice and short.
But there are good arguments for simplifying with the function, I can make the change. Your call @nventuro.
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.
shouldRecoverSigner
will be extremely close by for in-depth analysis, so I don't agree with it hiding the internals. IMO, the tests not sharing code seems to suggest they do different things, and I have to manually compare each line to realize they are actually all the same. @frangio wtb exec decision
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've been trying to understand more about the v
value and I've learnt that it's not a version number. It's a "recovery identifier" according to the yellow paper; something related to the parameters of the ECDSA curve. So 1) we might want to change everywhere that says "version" in these tests, but 2) I have no idea how to generate the different v
values so the hardcoded signatures will have to do for now.
test/library/ECDSA.test.js
Outdated
}); | ||
context('with 00 as version value', function () { | ||
it('works', async function () { | ||
// Signature generated outside ganache with method web3.eth.sign(signer, message) |
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.
This comment seems like it should be moved above next to the declaration of signatureWithoutVersion
.
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.
Removed, thanks for catching it.
@frangio I think that research about v and refactoring everything to that new name once we understand what it is and how to get web3 to generate it should be a separate task. |
test/library/ECDSA.test.js
Outdated
@@ -9,7 +9,7 @@ require('chai') | |||
const TEST_MESSAGE = web3.sha3('OpenZeppelin'); | |||
const WRONG_MESSAGE = web3.sha3('Nope'); | |||
|
|||
contract('ECDSA', function ([_, anyone]) { | |||
contract.only('ECDSA', function ([_, anyone]) { |
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.
Oops!
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 hate this tool :)
* fix: refactor sign.js and related tests * fix: remove unused dep * fix: update package.json correctly * Add missing tests to ECRecovery * fix lint * Reorganize the tests * Reuse signature * fix static errors * Apply suggestions by @frangion and @nventuro * Remove only * More suggestions * Remove unnecessary max-len * remove only (cherry picked from commit 75c0a59)
Requires #1243.
This is one step towards #1147
🚀 Description
Complete the test coverage for ECRecover:
cases when version is 27, 28 and invalid.
npm run lint:all:fix
).