Skip to content

Commit

Permalink
implement fallback from built-in scrypt to scryptsy/scrypt packages
Browse files Browse the repository at this point in the history
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 #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.
  • Loading branch information
michaelsbradleyjr committed Jul 17, 2019
1 parent 02a251d commit 5ec0eac
Showing 1 changed file with 47 additions and 9 deletions.
56 changes: 47 additions & 9 deletions packages/web3-eth-accounts/src/crypto/Scrypt.js
Expand Up @@ -5,26 +5,64 @@ let scrypt;
const isNode = Object.prototype.toString.call(typeof process !== 'undefined' ? process : 0) === '[object process]';
if (isNode) {
const NODE_MIN_VER_WITH_BUILTIN_SCRYPT = '10.5.0';
const NODE_MIN_VER_INCOMPAT_SCRYPT_PKG = '12.0.0';
const semver = require('semver');
const useNodeBuiltin = isNode && semver.Range('>=' + NODE_MIN_VER_WITH_BUILTIN_SCRYPT).test(process.version);

const tryScryptPackage = (function() {
let scryptPackage;
return function() {
if (scryptPackage !== undefined) {
return scryptPackage;
}
try {
scryptPackage = require('scrypt');
} catch (error) {
if (/was compiled against a different/.test(error.message)) {
throw error;
}
scryptPackage = null;
}
return scryptPackage;
};
})();

const canImprove = function(nodeVer) {
return `can improve web3's peformance when running Node.js versions older than ${nodeVer} by installing the (deprecated) scrypt package in your project`;
};

if (useNodeBuiltin) {
const crypto = require('crypto');
let fallbackCount = 0;
scrypt = function(key, salt, N, r, p, dkLength) {
return crypto.scryptSync(key, salt, dkLength, {N, r, p});
try {
return crypto.scryptSync(key, salt, dkLength, {N, r, p});
} catch (error) {
if (/scrypt:memory limit exceeded/.test(error.message)) {
const scryptPackage = tryScryptPackage();
if (scryptPackage) {
return scryptPackage.hashSync(key, {N: N, r: r, p: p}, dkLength, salt);
}
fallbackCount += 1;
console.warn(
'\u001B[33m%s\u001B[0m',
`Memory limit exceeded for Node's built-in crypto.scrypt, falling back to scryptsy (times: ${fallbackCount}), if this happens frequently you ${canImprove(
NODE_MIN_VER_INCOMPAT_SCRYPT_PKG
)}`
);
return scryptsy(key, salt, N, r, p, dkLength);
}
throw error;
}
};
} else {
let scryptPackage;
try {
scryptPackage = require('scrypt');
const scryptPackage = tryScryptPackage();
if (scryptPackage) {
scrypt = function(key, salt, N, r, p, dkLength) {
return scryptPackage.hashSync(key, {N, r, p}, dkLength, salt);
};
} catch (error) {
console.warn(
'\u001B[33m%s\u001B[0m',
`You can improve web3's peformance when running Node.js versions older than ${NODE_MIN_VER_WITH_BUILTIN_SCRYPT} by installing the (deprecated) scrypt package in your project`
);
} else {
console.warn('\u001B[33m%s\u001B[0m', `You ${canImprove(NODE_MIN_VER_WITH_BUILTIN_SCRYPT)}`);
}
}
}
Expand Down

0 comments on commit 5ec0eac

Please sign in to comment.