aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/index.rst1
-rw-r--r--docs/metadata.rst144
-rw-r--r--docs/miscellaneous.rst144
-rw-r--r--libevmasm/Assembly.cpp32
-rw-r--r--libevmasm/Assembly.h21
-rw-r--r--liblll/Compiler.cpp5
-rw-r--r--libsolidity/codegen/Compiler.h10
-rw-r--r--libsolidity/codegen/CompilerContext.h11
-rw-r--r--libsolidity/interface/AssemblyStack.cpp4
-rw-r--r--libsolidity/interface/CompilerStack.cpp18
-rw-r--r--libsolidity/interface/CompilerStack.h10
-rw-r--r--libsolidity/interface/StandardCompiler.cpp6
-rw-r--r--solc/CommandLineInterface.cpp18
13 files changed, 220 insertions, 204 deletions
diff --git a/docs/index.rst b/docs/index.rst
index 8c33fb9d..cb093bd6 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -144,6 +144,7 @@ Contents
solidity-in-depth.rst
security-considerations.rst
using-the-compiler.rst
+ metadata.rst
abi-spec.rst
style-guide.rst
common-patterns.rst
diff --git a/docs/metadata.rst b/docs/metadata.rst
new file mode 100644
index 00000000..dbde87e8
--- /dev/null
+++ b/docs/metadata.rst
@@ -0,0 +1,144 @@
+#################
+Contract Metadata
+#################
+
+.. index:: metadata, contract verification
+
+The Solidity compiler automatically generates a JSON file, the
+contract metadata, that contains information about the current contract.
+It can be used to query the compiler version, the sources used, the ABI
+and NatSpec documentation in order to more safely interact with the contract
+and to verify its source code.
+
+The compiler appends a Swarm hash of the metadata file to the end of the
+bytecode (for details, see below) of each contract, so that you can retrieve
+the file in an authenticated way without having to resort to a centralized
+data provider.
+
+Of course, you have to publish the metadata file to Swarm (or some other service)
+so that others can access it. The file can be output by using ``solc --metadata``
+and the file will be called ``ContractName_meta.json``.
+It will contain Swarm references to the source code, so you have to upload
+all source files and the metadata file.
+
+The metadata file has the following format. The example below is presented in a
+human-readable way. Properly formatted metadata should use quotes correctly,
+reduce whitespace to a minimum and sort the keys of all objects to arrive at a
+unique formatting.
+Comments are of course also not permitted and used here only for explanatory purposes.
+
+.. code-block:: none
+
+ {
+ // Required: The version of the metadata format
+ version: "1",
+ // Required: Source code language, basically selects a "sub-version"
+ // of the specification
+ language: "Solidity",
+ // Required: Details about the compiler, contents are specific
+ // to the language.
+ compiler: {
+ // Required for Solidity: Version of the compiler
+ version: "0.4.6+commit.2dabbdf0.Emscripten.clang",
+ // Optional: Hash of the compiler binary which produced this output
+ keccak256: "0x123..."
+ },
+ // Required: Compilation source files/source units, keys are file names
+ sources:
+ {
+ "myFile.sol": {
+ // Required: keccak256 hash of the source file
+ "keccak256": "0x123...",
+ // Required (unless "content" is used, see below): Sorted URL(s)
+ // to the source file, protocol is more or less arbitrary, but a
+ // Swarm URL is recommended
+ "urls": [ "bzzr://56ab..." ]
+ },
+ "mortal": {
+ // Required: keccak256 hash of the source file
+ "keccak256": "0x234...",
+ // Required (unless "url" is used): literal contents of the source file
+ "content": "contract mortal is owned { function kill() { if (msg.sender == owner) selfdestruct(owner); } }"
+ }
+ },
+ // Required: Compiler settings
+ settings:
+ {
+ // Required for Solidity: Sorted list of remappings
+ remappings: [ ":g/dir" ],
+ // Optional: Optimizer settings (enabled defaults to false)
+ optimizer: {
+ enabled: true,
+ runs: 500
+ },
+ // Required for Solidity: File and name of the contract or library this
+ // metadata is created for.
+ compilationTarget: {
+ "myFile.sol": "MyContract"
+ },
+ // Required for Solidity: Addresses for libraries used
+ libraries: {
+ "MyLib": "0x123123..."
+ }
+ },
+ // Required: Generated information about the contract.
+ output:
+ {
+ // Required: ABI definition of the contract
+ abi: [ ... ],
+ // Required: NatSpec user documentation of the contract
+ userdoc: [ ... ],
+ // Required: NatSpec developer documentation of the contract
+ devdoc: [ ... ],
+ }
+ }
+
+.. note::
+ Note the ABI definition above has no fixed order. It can change with compiler versions.
+
+.. note::
+ Since the bytecode of the resulting contract contains the metadata hash, any change to
+ the metadata will result in a change of the bytecode. Furthermore, since the metadata
+ includes a hash of all the sources used, a single whitespace change in any of the source
+ codes will result in a different metadata, and subsequently a different bytecode.
+
+Encoding of the Metadata Hash in the Bytecode
+=============================================
+
+Because we might support other ways to retrieve the metadata file in the future,
+the mapping ``{"bzzr0": <Swarm hash>}`` is stored
+`CBOR <https://tools.ietf.org/html/rfc7049>`_-encoded. Since the beginning of that
+encoding is not easy to find, its length is added in a two-byte big-endian
+encoding. The current version of the Solidity compiler thus adds the following
+to the end of the deployed bytecode::
+
+ 0xa1 0x65 'b' 'z' 'z' 'r' '0' 0x58 0x20 <32 bytes swarm hash> 0x00 0x29
+
+So in order to retrieve the data, the end of the deployed bytecode can be checked
+to match that pattern and use the Swarm hash to retrieve the file.
+
+Usage for Automatic Interface Generation and NatSpec
+====================================================
+
+The metadata is used in the following way: A component that wants to interact
+with a contract (e.g. Mist) retrieves the code of the contract, from that
+the Swarm hash of a file which is then retrieved.
+That file is JSON-decoded into a structure like above.
+
+The component can then use the ABI to automatically generate a rudimentary
+user interface for the contract.
+
+Furthermore, Mist can use the userdoc to display a confirmation message to the user
+whenever they interact with the contract.
+
+Usage for Source Code Verification
+==================================
+
+In order to verify the compilation, sources can be retrieved from Swarm
+via the link in the metadata file.
+The compiler of the correct version (which is checked to be part of the "official" compilers)
+is invoked on that input with the specified settings. The resulting
+bytecode is compared to the data of the creation transaction or ``CREATE`` opcode data.
+This automatically verifies the metadata since its hash is part of the bytecode.
+Excess data corresponds to the constructor input data, which should be decoded
+according to the interface and presented to the user.
diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst
index e9b01340..6d6c25ac 100644
--- a/docs/miscellaneous.rst
+++ b/docs/miscellaneous.rst
@@ -221,150 +221,6 @@ This means the following source mappings represent the same information:
``1:2:1;:9;2::2;;``
-*****************
-Contract Metadata
-*****************
-
-The Solidity compiler automatically generates a JSON file, the
-contract metadata, that contains information about the current contract.
-It can be used to query the compiler version, the sources used, the ABI
-and NatSpec documentation in order to more safely interact with the contract
-and to verify its source code.
-
-The compiler appends a Swarm hash of the metadata file to the end of the
-bytecode (for details, see below) of each contract, so that you can retrieve
-the file in an authenticated way without having to resort to a centralized
-data provider.
-
-Of course, you have to publish the metadata file to Swarm (or some other service)
-so that others can access it. The file can be output by using ``solc --metadata``
-and the file will be called ``ContractName_meta.json``.
-It will contain Swarm references to the source code, so you have to upload
-all source files and the metadata file.
-
-The metadata file has the following format. The example below is presented in a
-human-readable way. Properly formatted metadata should use quotes correctly,
-reduce whitespace to a minimum and sort the keys of all objects to arrive at a
-unique formatting.
-Comments are of course also not permitted and used here only for explanatory purposes.
-
-.. code-block:: none
-
- {
- // Required: The version of the metadata format
- version: "1",
- // Required: Source code language, basically selects a "sub-version"
- // of the specification
- language: "Solidity",
- // Required: Details about the compiler, contents are specific
- // to the language.
- compiler: {
- // Required for Solidity: Version of the compiler
- version: "0.4.6+commit.2dabbdf0.Emscripten.clang",
- // Optional: Hash of the compiler binary which produced this output
- keccak256: "0x123..."
- },
- // Required: Compilation source files/source units, keys are file names
- sources:
- {
- "myFile.sol": {
- // Required: keccak256 hash of the source file
- "keccak256": "0x123...",
- // Required (unless "content" is used, see below): Sorted URL(s)
- // to the source file, protocol is more or less arbitrary, but a
- // Swarm URL is recommended
- "urls": [ "bzzr://56ab..." ]
- },
- "mortal": {
- // Required: keccak256 hash of the source file
- "keccak256": "0x234...",
- // Required (unless "url" is used): literal contents of the source file
- "content": "contract mortal is owned { function kill() { if (msg.sender == owner) selfdestruct(owner); } }"
- }
- },
- // Required: Compiler settings
- settings:
- {
- // Required for Solidity: Sorted list of remappings
- remappings: [ ":g/dir" ],
- // Optional: Optimizer settings (enabled defaults to false)
- optimizer: {
- enabled: true,
- runs: 500
- },
- // Required for Solidity: File and name of the contract or library this
- // metadata is created for.
- compilationTarget: {
- "myFile.sol": "MyContract"
- },
- // Required for Solidity: Addresses for libraries used
- libraries: {
- "MyLib": "0x123123..."
- }
- },
- // Required: Generated information about the contract.
- output:
- {
- // Required: ABI definition of the contract
- abi: [ ... ],
- // Required: NatSpec user documentation of the contract
- userdoc: [ ... ],
- // Required: NatSpec developer documentation of the contract
- devdoc: [ ... ],
- }
- }
-
-.. note::
- Note the ABI definition above has no fixed order. It can change with compiler versions.
-
-.. note::
- Since the bytecode of the resulting contract contains the metadata hash, any change to
- the metadata will result in a change of the bytecode. Furthermore, since the metadata
- includes a hash of all the sources used, a single whitespace change in any of the source
- codes will result in a different metadata, and subsequently a different bytecode.
-
-Encoding of the Metadata Hash in the Bytecode
-=============================================
-
-Because we might support other ways to retrieve the metadata file in the future,
-the mapping ``{"bzzr0": <Swarm hash>}`` is stored
-`CBOR <https://tools.ietf.org/html/rfc7049>`_-encoded. Since the beginning of that
-encoding is not easy to find, its length is added in a two-byte big-endian
-encoding. The current version of the Solidity compiler thus adds the following
-to the end of the deployed bytecode::
-
- 0xa1 0x65 'b' 'z' 'z' 'r' '0' 0x58 0x20 <32 bytes swarm hash> 0x00 0x29
-
-So in order to retrieve the data, the end of the deployed bytecode can be checked
-to match that pattern and use the Swarm hash to retrieve the file.
-
-Usage for Automatic Interface Generation and NatSpec
-====================================================
-
-The metadata is used in the following way: A component that wants to interact
-with a contract (e.g. Mist) retrieves the code of the contract, from that
-the Swarm hash of a file which is then retrieved.
-That file is JSON-decoded into a structure like above.
-
-The component can then use the ABI to automatically generate a rudimentary
-user interface for the contract.
-
-Furthermore, Mist can use the userdoc to display a confirmation message to the user
-whenever they interact with the contract.
-
-Usage for Source Code Verification
-==================================
-
-In order to verify the compilation, sources can be retrieved from Swarm
-via the link in the metadata file.
-The compiler of the correct version (which is checked to be part of the "official" compilers)
-is invoked on that input with the specified settings. The resulting
-bytecode is compared to the data of the creation transaction or ``CREATE`` opcode data.
-This automatically verifies the metadata since its hash is part of the bytecode.
-Excess data corresponds to the constructor input data, which should be decoded
-according to the interface and presented to the user.
-
-
***************
Tips and Tricks
***************
diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp
index 8c1f9296..6b4bb52b 100644
--- a/libevmasm/Assembly.cpp
+++ b/libevmasm/Assembly.cpp
@@ -181,7 +181,7 @@ private:
}
-ostream& Assembly::streamAsm(ostream& _out, string const& _prefix, StringMap const& _sourceCodes) const
+void Assembly::assemblyStream(ostream& _out, string const& _prefix, StringMap const& _sourceCodes) const
{
Functionalizer f(_out, _prefix, _sourceCodes);
@@ -199,18 +199,23 @@ ostream& Assembly::streamAsm(ostream& _out, string const& _prefix, StringMap con
for (size_t i = 0; i < m_subs.size(); ++i)
{
_out << endl << _prefix << "sub_" << i << ": assembly {\n";
- m_subs[i]->streamAsm(_out, _prefix + " ", _sourceCodes);
+ m_subs[i]->assemblyStream(_out, _prefix + " ", _sourceCodes);
_out << _prefix << "}" << endl;
}
}
if (m_auxiliaryData.size() > 0)
_out << endl << _prefix << "auxdata: 0x" << toHex(m_auxiliaryData) << endl;
+}
- return _out;
+string Assembly::assemblyString(StringMap const& _sourceCodes) const
+{
+ ostringstream tmp;
+ assemblyStream(tmp, "", _sourceCodes);
+ return tmp.str();
}
-Json::Value Assembly::createJsonValue(string _name, int _begin, int _end, string _value, string _jumpType) const
+Json::Value Assembly::createJsonValue(string _name, int _begin, int _end, string _value, string _jumpType)
{
Json::Value value;
value["name"] = _name;
@@ -223,14 +228,14 @@ Json::Value Assembly::createJsonValue(string _name, int _begin, int _end, string
return value;
}
-string toStringInHex(u256 _value)
+string Assembly::toStringInHex(u256 _value)
{
std::stringstream hexStr;
hexStr << hex << _value;
return hexStr.str();
}
-Json::Value Assembly::streamAsmJson(ostream& _out, StringMap const& _sourceCodes) const
+Json::Value Assembly::assemblyJSON(StringMap const& _sourceCodes) const
{
Json::Value root;
@@ -301,29 +306,16 @@ Json::Value Assembly::streamAsmJson(ostream& _out, StringMap const& _sourceCodes
{
std::stringstream hexStr;
hexStr << hex << i;
- data[hexStr.str()] = m_subs[i]->stream(_out, "", _sourceCodes, true);
+ data[hexStr.str()] = m_subs[i]->assemblyJSON(_sourceCodes);
}
}
if (m_auxiliaryData.size() > 0)
root[".auxdata"] = toHex(m_auxiliaryData);
- _out << root;
-
return root;
}
-Json::Value Assembly::stream(ostream& _out, string const& _prefix, StringMap const& _sourceCodes, bool _inJsonFormat) const
-{
- if (_inJsonFormat)
- return streamAsmJson(_out, _sourceCodes);
- else
- {
- streamAsm(_out, _prefix, _sourceCodes);
- return Json::Value();
- }
-}
-
AssemblyItem const& Assembly::append(AssemblyItem const& _i)
{
assertThrow(m_deposit >= 0, AssemblyException, "");
diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h
index 680cb1af..cbdd71bc 100644
--- a/libevmasm/Assembly.h
+++ b/libevmasm/Assembly.h
@@ -120,11 +120,19 @@ public:
/// If @a _enable is not set, will perform some simple peephole optimizations.
Assembly& optimise(bool _enable, bool _isCreation = true, size_t _runs = 200);
- Json::Value stream(
+ /// Create a text representation of the assembly.
+ std::string assemblyString(
+ StringMap const& _sourceCodes = StringMap()
+ ) const;
+ void assemblyStream(
std::ostream& _out,
std::string const& _prefix = "",
- const StringMap &_sourceCodes = StringMap(),
- bool _inJsonFormat = false
+ StringMap const& _sourceCodes = StringMap()
+ ) const;
+
+ /// Create a JSON representation of the assembly.
+ Json::Value assemblyJSON(
+ StringMap const& _sourceCodes = StringMap()
) const;
protected:
@@ -136,9 +144,8 @@ protected:
unsigned bytesRequired(unsigned subTagSize) const;
private:
- Json::Value streamAsmJson(std::ostream& _out, StringMap const& _sourceCodes) const;
- std::ostream& streamAsm(std::ostream& _out, std::string const& _prefix, StringMap const& _sourceCodes) const;
- Json::Value createJsonValue(std::string _name, int _begin, int _end, std::string _value = std::string(), std::string _jumpType = std::string()) const;
+ static Json::Value createJsonValue(std::string _name, int _begin, int _end, std::string _value = std::string(), std::string _jumpType = std::string());
+ static std::string toStringInHex(u256 _value);
protected:
/// 0 is reserved for exception
@@ -161,7 +168,7 @@ protected:
inline std::ostream& operator<<(std::ostream& _out, Assembly const& _a)
{
- _a.stream(_out);
+ _a.assemblyStream(_out);
return _out;
}
diff --git a/liblll/Compiler.cpp b/liblll/Compiler.cpp
index 4ec11ca9..b69675aa 100644
--- a/liblll/Compiler.cpp
+++ b/liblll/Compiler.cpp
@@ -72,14 +72,13 @@ std::string dev::eth::compileLLLToAsm(std::string const& _src, bool _opt, std::v
{
CompilerState cs;
cs.populateStandard();
- stringstream ret;
auto assembly = CodeFragment::compile(_src, cs).assembly(cs);
if (_opt)
assembly = assembly.optimise(true);
- assembly.stream(ret);
+ string ret = assembly.assemblyString();
for (auto i: cs.treesToKill)
killBigints(i);
- return ret.str();
+ return ret;
}
catch (Exception const& _e)
{
diff --git a/libsolidity/codegen/Compiler.h b/libsolidity/codegen/Compiler.h
index c6ee93fb..06654486 100644
--- a/libsolidity/codegen/Compiler.h
+++ b/libsolidity/codegen/Compiler.h
@@ -60,10 +60,14 @@ public:
/// @returns Only the runtime object (without constructor).
eth::LinkerObject runtimeObject() const { return m_context.assembledRuntimeObject(m_runtimeSub); }
/// @arg _sourceCodes is the map of input files to source code strings
- /// @arg _inJsonFromat shows whether the out should be in Json format
- Json::Value streamAssembly(std::ostream& _stream, StringMap const& _sourceCodes = StringMap(), bool _inJsonFormat = false) const
+ std::string assemblyString(StringMap const& _sourceCodes = StringMap()) const
{
- return m_context.streamAssembly(_stream, _sourceCodes, _inJsonFormat);
+ return m_context.assemblyString(_sourceCodes);
+ }
+ /// @arg _sourceCodes is the map of input files to source code strings
+ Json::Value assemblyJSON(StringMap const& _sourceCodes = StringMap()) const
+ {
+ return m_context.assemblyJSON(_sourceCodes);
}
/// @returns Assembly items of the normal compiler context
eth::AssemblyItems const& assemblyItems() const { return m_context.assembly().items(); }
diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h
index 3994b010..5116585e 100644
--- a/libsolidity/codegen/CompilerContext.h
+++ b/libsolidity/codegen/CompilerContext.h
@@ -209,10 +209,15 @@ public:
eth::Assembly& nonConstAssembly() { return *m_asm; }
/// @arg _sourceCodes is the map of input files to source code strings
- /// @arg _inJsonFormat shows whether the out should be in Json format
- Json::Value streamAssembly(std::ostream& _stream, StringMap const& _sourceCodes = StringMap(), bool _inJsonFormat = false) const
+ std::string assemblyString(StringMap const& _sourceCodes = StringMap()) const
{
- return m_asm->stream(_stream, "", _sourceCodes, _inJsonFormat);
+ return m_asm->assemblyString(_sourceCodes);
+ }
+
+ /// @arg _sourceCodes is the map of input files to source code strings
+ Json::Value assemblyJSON(StringMap const& _sourceCodes = StringMap()) const
+ {
+ return m_asm->assemblyJSON(_sourceCodes);
}
eth::LinkerObject const& assembledObject() const { return m_asm->assemble(); }
diff --git a/libsolidity/interface/AssemblyStack.cpp b/libsolidity/interface/AssemblyStack.cpp
index 23524bb3..504ad92c 100644
--- a/libsolidity/interface/AssemblyStack.cpp
+++ b/libsolidity/interface/AssemblyStack.cpp
@@ -91,9 +91,7 @@ MachineAssemblyObject AssemblyStack::assemble(Machine _machine) const
eth::Assembly assembly;
assembly::CodeGenerator::assemble(*m_parserResult, *m_analysisInfo, assembly);
object.bytecode = make_shared<eth::LinkerObject>(assembly.assemble());
- ostringstream tmp;
- assembly.stream(tmp);
- object.assembly = tmp.str();
+ object.assembly = assembly.assemblyString();
return object;
}
case Machine::EVM15:
diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp
index 259694da..41bbf687 100644
--- a/libsolidity/interface/CompilerStack.cpp
+++ b/libsolidity/interface/CompilerStack.cpp
@@ -347,16 +347,24 @@ eth::LinkerObject const& CompilerStack::cloneObject(string const& _contractName)
return contract(_contractName).cloneObject;
}
-Json::Value CompilerStack::streamAssembly(ostream& _outStream, string const& _contractName, StringMap _sourceCodes, bool _inJsonFormat) const
+/// FIXME: cache this string
+string CompilerStack::assemblyString(string const& _contractName, StringMap _sourceCodes) const
{
Contract const& currentContract = contract(_contractName);
if (currentContract.compiler)
- return currentContract.compiler->streamAssembly(_outStream, _sourceCodes, _inJsonFormat);
+ return currentContract.compiler->assemblyString(_sourceCodes);
+ else
+ return string();
+}
+
+/// FIXME: cache the JSON
+Json::Value CompilerStack::assemblyJSON(string const& _contractName, StringMap _sourceCodes) const
+{
+ Contract const& currentContract = contract(_contractName);
+ if (currentContract.compiler)
+ return currentContract.compiler->assemblyJSON(_sourceCodes);
else
- {
- _outStream << "Contract not fully implemented" << endl;
return Json::Value();
- }
}
vector<string> CompilerStack::sourceNames() const
diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h
index 2756e57d..f1bbae47 100644
--- a/libsolidity/interface/CompilerStack.h
+++ b/libsolidity/interface/CompilerStack.h
@@ -190,11 +190,15 @@ public:
/// if the contract does not (yet) have bytecode.
std::string const* runtimeSourceMapping(std::string const& _contractName = "") const;
- /// Streams a verbose version of the assembly to @a _outStream.
+ /// @return a verbose text representation of the assembly.
/// @arg _sourceCodes is the map of input files to source code strings
- /// @arg _inJsonFromat shows whether the out should be in Json format
/// Prerequisite: Successful compilation.
- Json::Value streamAssembly(std::ostream& _outStream, std::string const& _contractName = "", StringMap _sourceCodes = StringMap(), bool _inJsonFormat = false) const;
+ std::string assemblyString(std::string const& _contractName = "", StringMap _sourceCodes = StringMap()) const;
+
+ /// @returns a JSON representation of the assembly.
+ /// @arg _sourceCodes is the map of input files to source code strings
+ /// Prerequisite: Successful compilation.
+ Json::Value assemblyJSON(std::string const& _contractName = "", StringMap _sourceCodes = StringMap()) const;
/// @returns a JSON representing the contract ABI.
/// Prerequisite: Successful call to parse or compile.
diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp
index be823743..b4fbbef9 100644
--- a/libsolidity/interface/StandardCompiler.cpp
+++ b/libsolidity/interface/StandardCompiler.cpp
@@ -400,10 +400,8 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
// EVM
Json::Value evmData(Json::objectValue);
// @TODO: add ir
- ostringstream tmp;
- m_compilerStack.streamAssembly(tmp, contractName, createSourceList(_input), false);
- evmData["assembly"] = tmp.str();
- evmData["legacyAssembly"] = m_compilerStack.streamAssembly(tmp, contractName, createSourceList(_input), true);
+ evmData["assembly"] = m_compilerStack.assemblyString(contractName, createSourceList(_input));
+ evmData["legacyAssembly"] = m_compilerStack.assemblyJSON(contractName, createSourceList(_input));
evmData["methodIdentifiers"] = m_compilerStack.methodIdentifiers(contractName);
evmData["gasEstimates"] = m_compilerStack.gasEstimates(contractName);
diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp
index 315f951e..e6d8776b 100644
--- a/solc/CommandLineInterface.cpp
+++ b/solc/CommandLineInterface.cpp
@@ -865,10 +865,7 @@ void CommandLineInterface::handleCombinedJSON()
if (requests.count(g_strOpcodes))
contractData[g_strOpcodes] = solidity::disassemble(m_compiler->object(contractName).bytecode);
if (requests.count(g_strAsm))
- {
- ostringstream unused;
- contractData[g_strAsm] = m_compiler->streamAssembly(unused, contractName, m_sourceCodes, true);
- }
+ contractData[g_strAsm] = m_compiler->assemblyJSON(contractName, m_sourceCodes);
if (requests.count(g_strSrcMap))
{
auto map = m_compiler->sourceMapping(contractName);
@@ -1150,16 +1147,19 @@ void CommandLineInterface::outputCompilationResults()
// do we need EVM assembly?
if (m_args.count(g_argAsm) || m_args.count(g_argAsmJson))
{
+ string ret;
+ if (m_args.count(g_argAsmJson))
+ ret = dev::jsonPrettyPrint(m_compiler->assemblyJSON(contract, m_sourceCodes));
+ else
+ ret = m_compiler->assemblyString(contract, m_sourceCodes);
+
if (m_args.count(g_argOutputDir))
{
- stringstream data;
- m_compiler->streamAssembly(data, contract, m_sourceCodes, m_args.count(g_argAsmJson));
- createFile(m_compiler->filesystemFriendlyName(contract) + (m_args.count(g_argAsmJson) ? "_evm.json" : ".evm"), data.str());
+ createFile(m_compiler->filesystemFriendlyName(contract) + (m_args.count(g_argAsmJson) ? "_evm.json" : ".evm"), ret);
}
else
{
- cout << "EVM assembly:" << endl;
- m_compiler->streamAssembly(cout, contract, m_sourceCodes, m_args.count(g_argAsmJson));
+ cout << "EVM assembly:" << endl << ret << endl;
}
}