diff options
Diffstat (limited to 'libsolidity/interface')
-rw-r--r-- | libsolidity/interface/StandardCompiler.cpp | 49 |
1 files changed, 45 insertions, 4 deletions
diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 6a8417de..2b280dd5 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -25,6 +25,7 @@ #include <libsolidity/ast/ASTJsonConverter.h> #include <libevmasm/Instruction.h> #include <libdevcore/JSON.h> +#include <libdevcore/SHA3.h> using namespace std; using namespace dev; @@ -91,6 +92,19 @@ Json::Value formatErrorWithException( return formatError(_warning, _type, _component, message, formattedMessage, location); } +/// Returns true iff @a _hash (hex with 0x prefix) is the Keccak256 hash of the binary data in @a _content. +bool hashMatchesContent(string const& _hash, string const& _content) +{ + try + { + return dev::h256(_hash) == dev::keccak256(_content); + } + catch (dev::BadHexCharacter) + { + return false; + } +} + StringMap createSourceList(Json::Value const& _input) { StringMap sources; @@ -165,8 +179,24 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input) Json::Value errors = Json::arrayValue; for (auto const& sourceName: sources.getMemberNames()) + { + string hash; + if (sources[sourceName]["keccak256"].isString()) + hash = sources[sourceName]["keccak256"].asString(); + if (sources[sourceName]["content"].isString()) - m_compilerStack.addSource(sourceName, sources[sourceName]["content"].asString()); + { + string content = sources[sourceName]["content"].asString(); + if (!hash.empty() && !hashMatchesContent(hash, content)) + errors.append(formatError( + false, + "IOError", + "general", + "Mismatch between content and supplied hash for \"" + sourceName + "\"" + )); + else + m_compilerStack.addSource(sourceName, content); + } else if (sources[sourceName]["urls"].isArray()) { if (!m_readFile) @@ -180,9 +210,19 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input) ReadFile::Result result = m_readFile(url.asString()); if (result.success) { - m_compilerStack.addSource(sourceName, result.contentsOrErrorMessage); - found = true; - break; + if (!hash.empty() && !hashMatchesContent(hash, result.contentsOrErrorMessage)) + errors.append(formatError( + false, + "IOError", + "general", + "Mismatch between content and supplied hash for \"" + sourceName + "\" at \"" + url.asString() + "\"" + )); + else + { + m_compilerStack.addSource(sourceName, result.contentsOrErrorMessage); + found = true; + break; + } } else failures.push_back("Cannot import url (\"" + url.asString() + "\"): " + result.contentsOrErrorMessage); @@ -201,6 +241,7 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input) } else return formatFatalError("JSONError", "Invalid input source specified."); + } Json::Value const& settings = _input.get("settings", Json::Value()); |