-
Notifications
You must be signed in to change notification settings - Fork 5k
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
Node >= v8.0.0 support for web3 1.0 #2938
Conversation
I'm attempting to swap WIP branch that would be merged back into this PR's branch: The tests that are skipped ( |
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.
Imo this can wait until 1.0 has been released.
|
4098ba3
to
8ef305e
Compare
The test suite has been fully revised to use the Also, a bug was fixed that prevented web3 accounts from being decrypted if the user provides their own |
I introduced an additional fallback behavior and console warning in the case that Node's built-in scrypt experiences memory exhaustion, as was happening in the test suite with the static tests. A large |
217965e
to
1510c53
Compare
This commit introduces an additional fallback behavior and console warning in the case that Node's built-in scrypt experiences memory exhaustion, as was discovered in the 1.x test suite with the static tests (see web3#2938). A large `n` parameter is the culprit, but that's not the case when using the 3rd party (deprecated) scrypt package. The `scryptsy` package can handle a large `n`, but performance does suffer considerably.
1510c53
to
ede0b5a
Compare
Previously, if a `salt` option was supplied as a string it would be passed to `pbkdf2Sync`/`scrypt` as a string, but during decryption it was always converted to a Buffer instance such that supplying a `salt` option as a string resulted in output that could not be decrypted. This commit fixes the bug, and also makes encrypted output match up with the output of other wallet libraries, e.g. `ethers`, whenever the equivalent encryption options are used consistently across libraries. See the following `web3.js` PRs: [#2950][2950] and [#2938][2938] [2950]: web3/web3.js#2950 [2938]: web3/web3.js#2938
See also: ethereumjs/ethereumjs-wallet#95. |
See also: ethereumjs/ethereumjs-wallet#91 (comment). |
Helps with web3#2913
ede0b5a
to
d7adf70
Compare
I've rebased this PR against |
// increase the test timeout | ||
this.timeout(6000); | ||
// disable the test timeout | ||
this.timeout(0); |
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 should be removed not set to 0.
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.
Setting to 0
is the way to say "no timeout" in mocha: https://mochajs.org/#suite-level.
Some of the static tests have large n
values: https://github.com/michaelsbradleyjr/web3.js/blob/d7adf702f815537376e7b8adb8fbdacfece17435/test/eth.accounts.encrypt-decrypt.js#L32.
In the case that Node.js falls back to scryptsy
, which will be the case in CI for Node <10.5.0
(since no scrypt
) and also >=10.5.0
because of maxmem errors with large n
(until PR #28799 makes it into releases of 10.x/12.x), then those tests will be prone to timeouts (scryptsy
is much, much slower for large n
). So for these particular tests, it makes sense to disable the timeout.
@@ -77,7 +77,7 @@ | |||
"coveralls": "^3.0.4", | |||
"crypto-js": "^3.1.9-1", | |||
"del": "^4.1.1", | |||
"ethereumjs-wallet": "^0.6.3", | |||
"ethers": "4.0.33", |
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.
Putting quite some trust into the devs of ether.js
. Also why is this version pinned here? The pinning should happen via yarn.lock
or package-lock.json
files. I think ^4.0.33
would be more appropriate.
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.
It's just a devDep, used to test that web3's wallet matches up with an independent implementation. ethereumjs-wallet
was serving that purpose but it also depends on scrypt.js
so npm i
in the repo still resulted in scrypt
package being installed and compiled.
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.
As for pinning vs. ^
, I've been bitten so many times by 3rd party patch bumps that violate semver (i.e. have breaking changes) and/or bugs that I spec exact version deps without thinking about it. However, using ^
would be more consistent with what's spec'd for the other devDeps.
@@ -307,7 +307,7 @@ Accounts.prototype.decrypt = function (v3Keystore, password, nonStrict) { | |||
kdfparams = json.crypto.kdfparams; | |||
|
|||
// FIXME: support progress reporting callback |
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.
What about this "FIXME" comment? Is it still valid?
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 it can be removed since there's not much point in trying to make use of the progress callback of scryptsy
and Node's built-in doesn't have such a thing.
@@ -351,13 +351,13 @@ Accounts.prototype.encrypt = function (privateKey, password, options) { | |||
if (kdf === 'pbkdf2') { | |||
kdfparams.c = options.c || 262144; | |||
kdfparams.prf = 'hmac-sha256'; | |||
derivedKey = cryp.pbkdf2Sync(Buffer.from(password), salt, kdfparams.c, kdfparams.dklen, 'sha256'); | |||
derivedKey = cryp.pbkdf2Sync(Buffer.from(password), Buffer.from(kdfparams.salt, 'hex'), kdfparams.c, kdfparams.dklen, 'sha256'); |
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.
Quite confusing that we are not using salt
any more but kdfparams.salt
all of a sudden. When I read the code above it should be the same, but still confusing.
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.
See above:
var kdfparams = {
dklen: options.dklen || 32,
salt: salt.toString('hex')
};
That code was already there and normalized the salt
whether it was a string or buffer. The problem was we weren't using the normalized value and it resulted in encrypted output that couldn't be decrypted. ethereumjs-wallet
has the same bug and I made a PR to fix it (still open).
if (isNode) { | ||
var NODE_MIN_VER_WITH_BUILTIN_SCRYPT = '10.5.0'; | ||
var NODE_MIN_VER_INCOMPAT_SCRYPT_PKG = '12.0.0'; | ||
var semver = require('semver'); |
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 is quite painful in webpack I fear... One can have webpack and node (e.g. lambda functions).
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.
Can you explain a bit more? If this broke something in a node FaaS context, I will be glad to work on a fix.
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 am just not sure whether or not webpack correctly supports this dynamic require. Needs to be tested.
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.
It doesn't. Webpack fails at dynamic require at [email protected]. Any idea how to workaround 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've seen the warning too, but it didn't cause my build to fail, and my build worked as expected. Are you sure you actually got a failed build?
In any case, the web3-eth-accounts
module should be refactored to make use of "browser"
in package.json
instead of using runtime isNode
detection. I'll work on that very soon.
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.
As I said in my previous comment, this should be refactored. But in the meantime I don't think the warning will result in broken builds. Here's what I tried:
$ cd ~/temp
$ npx create-react-app foo
$ cd foo && yarn add web3
After that I edited src/App.js
to import Web3 from 'web3'
and I set window.Web3 = Web3
. Then:
$ yarn start
Once the dev server was available at localhost:3000 I was able to use window.Web3
without any problems, though I did see the webpack warning in the console output of yarn start
.
I checked that I could use web3.eth.accounts
to create/encrypt/decrypt — worked as expected, so while the webpack warning isn't nice, it doesn't seem to prevent browser builds (w/ webpack) from working.
I'm not 100% sure about webpack builds targeting Node.js; but shouldn't be a problem because such builds couldn't pack up the scrypt
package in any case (it's a compiled C++ thing).
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.
Hey @michaelsbradleyjr you are absolutely right. I had other issue and critical dependency
got me triggered. Thanks for detailed answer and check. Really appreciated.
Lots of love that this feature got merged. ❤️ |
Helps with #2913.
This PR is presently incomplete because it was necessary to disable two test scripts after removingethereumjs-wallet
as a development dependency, since that package has the Node 12 incompatiblescrypt
package as a transitive dependency.Gaining support for Node versions from 8 to 12 inclusive seems like a very good thing, so maybe there is another testing strategy that can be used to restore the test files without needing to installethereumjs-wallet
?