From ea6cf619fd0789dc848402a5c17eee6c4d32d708 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 24 Apr 2017 16:15:36 +0100 Subject: Rewrite jsonCompiler using StandardCompiler --- solc/jsonCompiler.cpp | 209 +++++++++++++++++++++----------------------------- 1 file changed, 89 insertions(+), 120 deletions(-) (limited to 'solc') diff --git a/solc/jsonCompiler.cpp b/solc/jsonCompiler.cpp index 5165f984..1d31ea30 100644 --- a/solc/jsonCompiler.cpp +++ b/solc/jsonCompiler.cpp @@ -21,24 +21,9 @@ */ #include -#include -#include -#include #include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include #include #include "license.h" @@ -109,9 +94,8 @@ Json::Value gasToJson(Json::Value const& _value) return Json::Value(Json::LargestUInt(value)); } -Json::Value estimateGas(CompilerStack const& _compiler, string const& _contract) +Json::Value translateGasEstimates(Json::Value const& estimates) { - Json::Value estimates = _compiler.gasEstimates(_contract); Json::Value output(Json::objectValue); if (estimates["creation"].isObject()) @@ -131,121 +115,106 @@ Json::Value estimateGas(CompilerStack const& _compiler, string const& _contract) string compile(StringMap const& _sources, bool _optimize, CStyleReadFileCallback _readCallback) { - Json::Value output(Json::objectValue); - Json::Value errors(Json::arrayValue); - CompilerStack compiler(wrapReadCallback(_readCallback)); - auto scannerFromSourceName = [&](string const& _sourceName) -> solidity::Scanner const& { return compiler.scanner(_sourceName); }; - bool success = false; - try - { - compiler.addSources(_sources); - bool succ = compiler.compile(_optimize); - for (auto const& error: compiler.errors()) - { - auto err = dynamic_pointer_cast(error); - errors.append(SourceReferenceFormatter::formatExceptionInformation( - *error, - (err->type() == Error::Type::Warning) ? "Warning" : "Error", - scannerFromSourceName - )); - } - success = succ; // keep success false on exception - } - catch (Error const& error) - { - errors.append(SourceReferenceFormatter::formatExceptionInformation(error, error.typeName(), scannerFromSourceName)); - } - catch (CompilerError const& exception) - { - errors.append(SourceReferenceFormatter::formatExceptionInformation(exception, "Compiler error (" + exception.lineInfo() + ")", scannerFromSourceName)); - } - catch (InternalCompilerError const& exception) - { - errors.append(SourceReferenceFormatter::formatExceptionInformation(exception, "Internal compiler error (" + exception.lineInfo() + ")", scannerFromSourceName)); - } - catch (UnimplementedFeatureError const& exception) - { - errors.append(SourceReferenceFormatter::formatExceptionInformation(exception, "Unimplemented feature (" + exception.lineInfo() + ")", scannerFromSourceName)); - } - catch (Exception const& exception) + /// create new JSON input format + Json::Value input = Json::objectValue; + input["language"] = "Solidity"; + input["sources"] = Json::objectValue; + for (auto const& source: _sources) { - errors.append("Exception during compilation: " + boost::diagnostic_information(exception)); + input["sources"][source.first] = Json::objectValue; + input["sources"][source.first]["content"] = source.second; } - catch (...) + input["settings"] = Json::objectValue; + input["settings"]["optimizer"] = Json::objectValue; + input["settings"]["optimizer"]["enabled"] = _optimize; + input["settings"]["optimizer"]["runs"] = 200; + + StandardCompiler compiler(wrapReadCallback(_readCallback)); + Json::Value ret = compiler.compile(input); + + /// transform JSON to match the old format + // { + // "errors": [ "Error 1", "Error 2" ], + // "sourceList": [ "sourcename1", "sourcename2" ], + // "sources": { + // "sourcename1": { + // "AST": {} + // } + // }, + // "contracts": { + // "Contract1": { + // "interface": "[...abi...]", + // "bytecode": "ff0011...", + // "runtimeBytecode": "ff0011", + // "opcodes": "PUSH 1 POP STOP", + // "metadata": "{...metadata...}", + // "functionHashes": { + // "test(uint256)": "11ff2233" + // }, + // "gasEstimates": { + // "creation": [ 224, 42000 ], + // "external": { + // "11ff2233": null, + // "3322ff11": 1234 + // }, + // "internal": { + // } + // }, + // "srcmap" = "0:1:2", + // "srcmapRuntime" = "0:1:2", + // "assembly" = {} + // } + // }, + // "formal": { + // "errors": [ "Error 1" ], + // "why3": "why3 source" + // } + // } + Json::Value output = Json::objectValue; + + if (ret.isMember("errors")) { - errors.append("Unknown exception during compilation."); + output["errors"] = Json::arrayValue; + for (auto const& error: ret["errors"]) + output["errors"].append( + !error["formattedMessage"].empty() ? error["formattedMessage"] : error["message"] + ); } - if (errors.size() > 0) - output["errors"] = errors; + output["sourceList"] = Json::arrayValue; + for (auto const& source: _sources) + output["sourceList"].append(source.first); - if (success) + if (ret.isMember("sources")) { - try + output["sources"] = Json::objectValue; + for (auto const& sourceName: ret["sources"].getMemberNames()) { - output["contracts"] = Json::Value(Json::objectValue); - for (string const& contractName: compiler.contractNames()) - { - Json::Value contractData(Json::objectValue); - contractData["interface"] = dev::jsonCompactPrint(compiler.contractABI(contractName)); - contractData["bytecode"] = compiler.object(contractName).toHex(); - contractData["runtimeBytecode"] = compiler.runtimeObject(contractName).toHex(); - contractData["opcodes"] = solidity::disassemble(compiler.object(contractName).bytecode); - contractData["metadata"] = compiler.onChainMetadata(contractName); - contractData["functionHashes"] = compiler.methodIdentifiers(contractName); - contractData["gasEstimates"] = estimateGas(compiler, contractName); - auto sourceMap = compiler.sourceMapping(contractName); - contractData["srcmap"] = sourceMap ? *sourceMap : ""; - auto runtimeSourceMap = compiler.runtimeSourceMapping(contractName); - contractData["srcmapRuntime"] = runtimeSourceMap ? *runtimeSourceMap : ""; - ostringstream unused; - contractData["assembly"] = compiler.streamAssembly(unused, contractName, _sources, true); - output["contracts"][contractName] = contractData; - } - } - catch (...) - { - output["errors"].append("Unknown exception while generating contract data output."); + output["sources"][sourceName] = Json::objectValue; + output["sources"][sourceName]["AST"] = ret["sources"][sourceName]["legacyAST"]; } + } - try - { - // Do not taint the internal error list - ErrorList formalErrors; - ErrorReporter errorReporter(formalErrors); - if (compiler.prepareFormalAnalysis(&errorReporter)) - output["formal"]["why3"] = compiler.formalTranslation(); - if (!errorReporter.errors().empty()) + if (ret.isMember("contracts")) + { + output["contracts"] = Json::objectValue; + for (auto const& sourceName: ret["contracts"].getMemberNames()) + for (auto const& contractName: ret["contracts"][sourceName].getMemberNames()) { - Json::Value errors(Json::arrayValue); - for (auto const& error: errorReporter.errors()) - errors.append(SourceReferenceFormatter::formatExceptionInformation( - *error, - (error->type() == Error::Type::Warning) ? "Warning" : "Error", - scannerFromSourceName - )); - output["formal"]["errors"] = errors; + Json::Value contractInput = ret["contracts"][sourceName][contractName]; + Json::Value contractOutput = Json::objectValue; + contractOutput["interface"] = dev::jsonCompactPrint(contractInput["abi"]); + contractOutput["metadata"] = contractInput["metadata"]; + contractOutput["functionHashes"] = contractInput["evm"]["methodIdentifiers"]; + contractOutput["gasEstimates"] = translateGasEstimates(contractInput["evm"]["gasEstimates"]); + contractOutput["assembly"] = contractInput["evm"]["legacyAssembly"]; + contractOutput["bytecode"] = contractInput["evm"]["bytecode"]["object"]; + contractOutput["opcodes"] = contractInput["evm"]["bytecode"]["opcodes"]; + contractOutput["srcmap"] = contractInput["evm"]["bytecode"]["sourceMap"]; + contractOutput["runtimeBytecode"] = contractInput["evm"]["deployedBytecode"]["object"]; + contractOutput["srcmapRuntime"] = contractInput["evm"]["deployedBytecode"]["sourceMap"]; + output["contracts"][sourceName + ":" + contractName] = contractOutput; } - } - catch (...) - { - output["errors"].append("Unknown exception while generating formal method output."); - } - - try - { - // Indices into this array are used to abbreviate source names in source locations. - output["sourceList"] = Json::Value(Json::arrayValue); - for (auto const& source: compiler.sourceNames()) - output["sourceList"].append(source); - output["sources"] = Json::Value(Json::objectValue); - for (auto const& source: compiler.sourceNames()) - output["sources"][source]["AST"] = ASTJsonConverter(true, compiler.sourceIndices()).toJson(compiler.ast(source)); - } - catch (...) - { - output["errors"].append("Unknown exception while generating source name output."); - } } try -- cgit