Skip to content

Instantly share code, notes, and snippets.

@mickys
Created October 17, 2017 04:22
Show Gist options
  • Save mickys/941416a857fb29f289aadf475ad2ffe3 to your computer and use it in GitHub Desktop.
Save mickys/941416a857fb29f289aadf475ad2ffe3 to your computer and use it in GitHub Desktop.
// --- ADD THIS ---
var fs = require('fs');
var exec = require('sync-exec');
// --- ADD THIS ---
var translate = require('./translate.js');
var linker = require('./linker.js');
var requireFromString = require('require-from-string');
var https = require('https');
var MemoryStream = require('memorystream');
function setupMethods (soljson) {
var compileJSON = soljson.cwrap('compileJSON', 'string', ['string', 'number']);
var compileJSONMulti = null;
if ('_compileJSONMulti' in soljson) {
compileJSONMulti = soljson.cwrap('compileJSONMulti', 'string', ['string', 'number']);
}
var compileJSONCallback = null;
var compileStandard = null;
if (('_compileJSONCallback' in soljson) || ('_compileStandard' in soljson)) {
var copyString = function (str, ptr) {
var buffer = soljson._malloc(str.length + 1);
soljson.writeStringToMemory(str, buffer);
soljson.setValue(ptr, buffer, '*');
};
var wrapCallback = function (callback) {
return function (path, contents, error) {
var result = callback(soljson.Pointer_stringify(path));
if (typeof result.contents === 'string') {
copyString(result.contents, contents);
}
if (typeof result.error === 'string') {
copyString(result.error, error);
}
};
};
// This calls compile() with args || cb
var runWithReadCallback = function (readCallback, compile, args) {
if (readCallback === undefined) {
readCallback = function (path) {
return {
error: 'File import callback not supported'
};
};
}
var cb = soljson.Runtime.addFunction(wrapCallback(readCallback));
var output;
try {
args.push(cb);
// output = compile.apply(undefined, args);
// --- ADD THIS ---
output = compileUsingBinary(args[0]);
// --- ADD THIS ---
} catch (e) {
soljson.Runtime.removeFunction(cb);
throw e;
}
soljson.Runtime.removeFunction(cb);
return output;
};
var compileInternal = soljson.cwrap('compileJSONCallback', 'string', ['string', 'number', 'number']);
compileJSONCallback = function (input, optimize, readCallback) {
return runWithReadCallback(readCallback, compileInternal, [ input, optimize ]);
};
if ('_compileStandard' in soljson) {
var compileStandardInternal = soljson.cwrap('compileStandard', 'string', ['string', 'number']);
compileStandard = function (input, readCallback) {
return runWithReadCallback(readCallback, compileStandardInternal, [ input ]);
};
}
}
// --- ADD THIS ---
var compileUsingBinary = function (input) {
var filename = '/tmp/truffle-solc-bin.json';
fs.writeFileSync(filename, input);
return exec(`solc --standard-json < ${filename}`).stdout;
}
// --- ADD THIS ---
var compile = function (input, optimise, readCallback) {
var result = '';
if (readCallback !== undefined && compileJSONCallback !== null) {
result = compileJSONCallback(JSON.stringify(input), optimise, readCallback);
} else if (typeof input !== 'string' && compileJSONMulti !== null) {
result = compileJSONMulti(JSON.stringify(input), optimise);
} else {
result = compileJSON(input, optimise);
}
return JSON.parse(result);
};
// Expects a Standard JSON I/O but supports old compilers
var compileStandardWrapper = function (input, readCallback) {
if (compileStandard !== null) {
return compileStandard(input, readCallback);
}
function formatFatalError (message) {
return JSON.stringify({
errors: [
{
'type': 'SOLCError',
'component': 'solcjs',
'severity': 'error',
'message': message,
'formattedMessage': 'Error' + message
}
]
});
}
input = JSON.parse(input);
if (input['language'] !== 'Solidity') {
return formatFatalError('Only Solidity sources are supported');
}
if (input['sources'] == null) {
return formatFatalError('No input specified');
}
// Bail out early
if ((input['sources'].length > 1) && (compileJSONMulti === null)) {
return formatFatalError('Multiple sources provided, but compiler only supports single input');
}
function isOptimizerEnabled (input) {
return input['settings'] && input['settings']['optimizer'] && input['settings']['optimizer']['enabled'];
}
function translateSources (input) {
var sources = {};
for (var source in input['sources']) {
if (input['sources'][source]['content'] !== null) {
sources[source] = input['sources'][source]['content'];
} else {
// force failure
return null;
}
}
return sources;
}
function translateOutput (output) {
output = translate.translateJsonCompilerOutput(JSON.parse(output));
if (output == null) {
return formatFatalError('Failed to process output');
}
return JSON.stringify(output);
}
var sources = translateSources(input);
if (sources === null) {
return formatFatalError('Failed to process sources');
}
// Try to wrap around old versions
if (compileJSONCallback !== null) {
return translateOutput(compileJSONCallback(JSON.stringify({ 'sources': sources }), isOptimizerEnabled(input), readCallback));
}
if (compileJSONMulti !== null) {
return translateOutput(compileJSONMulti(JSON.stringify({ 'sources': sources }), isOptimizerEnabled(input)));
}
// Try our luck with an ancient compiler
return translateOutput(compileJSON(sources[0], isOptimizerEnabled(input)));
};
var version = soljson.cwrap('version', 'string', []);
var license = function () {
// return undefined
};
if ('_license' in soljson) {
license = soljson.cwrap('license', 'string', []);
}
return {
version: version,
license: license,
compile: compile,
compileStandard: compileStandard,
compileStandardWrapper: compileStandardWrapper,
linkBytecode: linker.linkBytecode,
supportsMulti: compileJSONMulti !== null,
supportsImportCallback: compileJSONCallback !== null,
supportsStandard: compileStandard !== null,
// Loads the compiler of the given version from the github repository
// instead of from the local filesystem.
loadRemoteVersion: function (versionString, cb) {
var mem = new MemoryStream(null, {readable: false});
var url = 'https://ethereum.github.io/solc-bin/bin/soljson-' + versionString + '.js';
https.get(url, function (response) {
if (response.statusCode !== 200) {
cb(new Error('Error retrieving binary: ' + response.statusMessage));
} else {
response.pipe(mem);
response.on('end', function () {
cb(null, setupMethods(requireFromString(mem.toString(), 'soljson-' + versionString + '.js')));
});
}
}).on('error', function (error) {
cb(error);
});
},
// Use this if you want to add wrapper functions around the pure module.
setupMethods: setupMethods
};
}
module.exports = setupMethods;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment