aboutsummaryrefslogtreecommitdiffstats
path: root/libsolc
diff options
context:
space:
mode:
authorAlex Beregszaszi <alex@rtfs.hu>2017-09-16 10:50:16 +0800
committerAlex Beregszaszi <alex@rtfs.hu>2017-12-11 20:49:08 +0800
commit1734d4456189b4a313a07e7f3e24cb01f5057fc3 (patch)
tree3cbc303365f827a8c7f76cb7feb6eabfa821c9c7 /libsolc
parent27f38fb5b31b9f0c228238cf0471155498b951b7 (diff)
downloaddexon-solidity-1734d4456189b4a313a07e7f3e24cb01f5057fc3.tar.gz
dexon-solidity-1734d4456189b4a313a07e7f3e24cb01f5057fc3.tar.zst
dexon-solidity-1734d4456189b4a313a07e7f3e24cb01f5057fc3.zip
Rename jsonCompiler to libsolc
Diffstat (limited to 'libsolc')
-rw-r--r--libsolc/CMakeLists.txt9
-rw-r--r--libsolc/libsolc.cpp302
-rw-r--r--libsolc/libsolc.h42
3 files changed, 353 insertions, 0 deletions
diff --git a/libsolc/CMakeLists.txt b/libsolc/CMakeLists.txt
new file mode 100644
index 00000000..e67583dd
--- /dev/null
+++ b/libsolc/CMakeLists.txt
@@ -0,0 +1,9 @@
+if (EMSCRIPTEN)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s EXPORTED_FUNCTIONS='[\"_compileJSON\",\"_license\",\"_version\",\"_compileJSONMulti\",\"_compileJSONCallback\",\"_compileStandard\"]' -s RESERVED_FUNCTION_POINTERS=20")
+ add_executable(soljson libsolc.cpp)
+ target_link_libraries(soljson PRIVATE solidity)
+else()
+ add_library(libsolc libsolc.cpp)
+ set_target_properties(libsolc PROPERTIES OUTPUT_NAME solc)
+ target_link_libraries(libsolc PRIVATE solidity)
+endif()
diff --git a/libsolc/libsolc.cpp b/libsolc/libsolc.cpp
new file mode 100644
index 00000000..3a6e1521
--- /dev/null
+++ b/libsolc/libsolc.cpp
@@ -0,0 +1,302 @@
+/*
+ This file is part of solidity.
+
+ solidity is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ solidity is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * @author Christian <c@ethdev.com>
+ * @date 2014
+ * JSON interface for the solidity compiler to be used from Javascript.
+ */
+
+#include <libsolc/libsolc.h>
+#include <libdevcore/Common.h>
+#include <libdevcore/JSON.h>
+#include <libsolidity/interface/StandardCompiler.h>
+#include <libsolidity/interface/Version.h>
+
+#include <string>
+
+#include "license.h"
+
+using namespace std;
+using namespace dev;
+using namespace solidity;
+
+namespace
+{
+
+ReadCallback::Callback wrapReadCallback(CStyleReadFileCallback _readCallback = nullptr)
+{
+ ReadCallback::Callback readCallback;
+ if (_readCallback)
+ {
+ readCallback = [=](string const& _path)
+ {
+ char* contents_c = nullptr;
+ char* error_c = nullptr;
+ _readCallback(_path.c_str(), &contents_c, &error_c);
+ ReadCallback::Result result;
+ result.success = true;
+ if (!contents_c && !error_c)
+ {
+ result.success = false;
+ result.responseOrErrorMessage = "File not found.";
+ }
+ if (contents_c)
+ {
+ result.success = true;
+ result.responseOrErrorMessage = string(contents_c);
+ free(contents_c);
+ }
+ if (error_c)
+ {
+ result.success = false;
+ result.responseOrErrorMessage = string(error_c);
+ free(error_c);
+ }
+ return result;
+ };
+ }
+ return readCallback;
+}
+
+/// Translates a gas value as a string to a JSON number or null
+Json::Value gasToJson(Json::Value const& _value)
+{
+ if (_value.isObject())
+ {
+ Json::Value ret = Json::objectValue;
+ for (auto const& sig: _value.getMemberNames())
+ ret[sig] = gasToJson(_value[sig]);
+ return ret;
+ }
+
+ if (_value == "infinite")
+ return Json::Value(Json::nullValue);
+
+ u256 value(_value.asString());
+ if (value > std::numeric_limits<Json::LargestUInt>::max())
+ return Json::Value(Json::nullValue);
+ else
+ return Json::Value(Json::LargestUInt(value));
+}
+
+Json::Value translateGasEstimates(Json::Value const& estimates)
+{
+ Json::Value output(Json::objectValue);
+
+ if (estimates["creation"].isObject())
+ {
+ Json::Value creation(Json::arrayValue);
+ creation[0] = gasToJson(estimates["creation"]["executionCost"]);
+ creation[1] = gasToJson(estimates["creation"]["codeDepositCost"]);
+ output["creation"] = creation;
+ }
+ else
+ output["creation"] = Json::objectValue;
+ output["external"] = gasToJson(estimates.get("external", Json::objectValue));
+ output["internal"] = gasToJson(estimates.get("internal", Json::objectValue));
+
+ return output;
+}
+
+string compile(StringMap const& _sources, bool _optimize, CStyleReadFileCallback _readCallback)
+{
+ /// create new JSON input format
+ Json::Value input = Json::objectValue;
+ input["language"] = "Solidity";
+ input["sources"] = Json::objectValue;
+ for (auto const& source: _sources)
+ {
+ input["sources"][source.first] = Json::objectValue;
+ input["sources"][source.first]["content"] = source.second;
+ }
+ input["settings"] = Json::objectValue;
+ input["settings"]["optimizer"] = Json::objectValue;
+ input["settings"]["optimizer"]["enabled"] = _optimize;
+ input["settings"]["optimizer"]["runs"] = 200;
+
+ // Enable all SourceUnit-level outputs.
+ input["settings"]["outputSelection"]["*"][""][0] = "*";
+ // Enable all Contract-level outputs.
+ input["settings"]["outputSelection"]["*"]["*"][0] = "*";
+
+ 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" = {}
+ // }
+ // }
+ // }
+ Json::Value output = Json::objectValue;
+
+ if (ret.isMember("errors"))
+ {
+ output["errors"] = Json::arrayValue;
+ for (auto const& error: ret["errors"])
+ output["errors"].append(
+ !error["formattedMessage"].empty() ? error["formattedMessage"] : error["message"]
+ );
+ }
+
+ output["sourceList"] = Json::arrayValue;
+ for (auto const& source: _sources)
+ output["sourceList"].append(source.first);
+
+ if (ret.isMember("sources"))
+ {
+ output["sources"] = Json::objectValue;
+ for (auto const& sourceName: ret["sources"].getMemberNames())
+ {
+ output["sources"][sourceName] = Json::objectValue;
+ output["sources"][sourceName]["AST"] = ret["sources"][sourceName]["legacyAST"];
+ }
+ }
+
+ 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 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;
+ }
+ }
+
+ try
+ {
+ return dev::jsonCompactPrint(output);
+ }
+ catch (...)
+ {
+ return "{\"errors\":[\"Unknown error while generating JSON.\"]}";
+ }
+}
+
+string compileMulti(string const& _input, bool _optimize, CStyleReadFileCallback _readCallback = nullptr)
+{
+ Json::Reader reader;
+ Json::Value input;
+ if (!reader.parse(_input, input, false))
+ {
+ Json::Value errors(Json::arrayValue);
+ errors.append("Error parsing input JSON: " + reader.getFormattedErrorMessages());
+ Json::Value output(Json::objectValue);
+ output["errors"] = errors;
+ return dev::jsonCompactPrint(output);
+ }
+ else
+ {
+ StringMap sources;
+ Json::Value jsonSources = input["sources"];
+ if (jsonSources.isObject())
+ for (auto const& sourceName: jsonSources.getMemberNames())
+ sources[sourceName] = jsonSources[sourceName].asString();
+ return compile(sources, _optimize, _readCallback);
+ }
+}
+
+string compileSingle(string const& _input, bool _optimize)
+{
+ StringMap sources;
+ sources[""] = _input;
+ return compile(sources, _optimize, nullptr);
+}
+
+
+string compileStandardInternal(string const& _input, CStyleReadFileCallback _readCallback = nullptr)
+{
+ StandardCompiler compiler(wrapReadCallback(_readCallback));
+ return compiler.compile(_input);
+}
+
+}
+
+static string s_outputBuffer;
+
+extern "C"
+{
+extern char const* license()
+{
+ static string fullLicenseText = otherLicenses + licenseText;
+ return fullLicenseText.c_str();
+}
+extern char const* version()
+{
+ return VersionString.c_str();
+}
+extern char const* compileJSON(char const* _input, bool _optimize)
+{
+ s_outputBuffer = compileSingle(_input, _optimize);
+ return s_outputBuffer.c_str();
+}
+extern char const* compileJSONMulti(char const* _input, bool _optimize)
+{
+ s_outputBuffer = compileMulti(_input, _optimize);
+ return s_outputBuffer.c_str();
+}
+extern char const* compileJSONCallback(char const* _input, bool _optimize, CStyleReadFileCallback _readCallback)
+{
+ s_outputBuffer = compileMulti(_input, _optimize, _readCallback);
+ return s_outputBuffer.c_str();
+}
+extern char const* compileStandard(char const* _input, CStyleReadFileCallback _readCallback)
+{
+ s_outputBuffer = compileStandardInternal(_input, _readCallback);
+ return s_outputBuffer.c_str();
+}
+}
diff --git a/libsolc/libsolc.h b/libsolc/libsolc.h
new file mode 100644
index 00000000..c392ce93
--- /dev/null
+++ b/libsolc/libsolc.h
@@ -0,0 +1,42 @@
+/*
+ This file is part of solidity.
+
+ solidity is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ solidity is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * @author Christian <c@ethdev.com>
+ * @date 2014
+ * JSON interface for the solidity compiler to be used from Javascript.
+ */
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/// Callback used to retrieve additional source files. "Returns" two pointers that should be
+/// heap-allocated and are free'd by the caller.
+typedef void (*CStyleReadFileCallback)(char const* _path, char** o_contents, char** o_error);
+
+char const* license();
+char const* version();
+char const* compileJSON(char const* _input, bool _optimize);
+char const* compileJSONMulti(char const* _input, bool _optimize);
+char const* compileJSONCallback(char const* _input, bool _optimize, CStyleReadFileCallback _readCallback);
+char const* compileStandard(char const* _input, CStyleReadFileCallback _readCallback);
+
+#ifdef __cplusplus
+}
+#endif