diff options
-rw-r--r-- | docs/miscellaneous.rst | 9 | ||||
-rw-r--r-- | libevmasm/Assembly.cpp | 10 | ||||
-rw-r--r-- | libevmasm/Assembly.h | 7 | ||||
-rw-r--r-- | libsolidity/ast/AST.cpp | 1 | ||||
-rw-r--r-- | libsolidity/codegen/Compiler.cpp | 4 | ||||
-rw-r--r-- | libsolidity/codegen/CompilerContext.cpp | 7 | ||||
-rw-r--r-- | libsolidity/codegen/CompilerContext.h | 4 | ||||
-rw-r--r-- | libsolidity/interface/CompilerStack.cpp | 1 |
8 files changed, 20 insertions, 23 deletions
diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst index a09f297a..1f94c387 100644 --- a/docs/miscellaneous.rst +++ b/docs/miscellaneous.rst @@ -242,14 +242,10 @@ It can be used to query the compiler version, the sourcecode, the ABI and NatSpec documentation in order to more safely interact with the contract and to verify its source code. -The compiler inserts a swarm hash of that file into the bytecode of each +The compiler appends a swarm hash (32 bytes) of that file to the end of the bytecode of each contract, so that you can retrieve the file in an authenticated way without having to resort to a centralized data provider. -Specifically, the runtime code for a contract always starts with -``push32 <metadata hash> pop``, so you can take a look at the 32 bytes starting at -the second byte of the code of a contract. - 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``. It will contain swarm references to the source code, so you have to upload @@ -326,8 +322,7 @@ 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 -and from that the first 33 bytes. If the first byte decodes into a PUSH32 -instruction, the other 32 bytes are interpreted as the swarm hash of +and from that the last 32 bytes, which are interpreted as the swarm hash of a file which is then retrieved. That file is JSON-decoded into a structure like above. diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index b040917d..fab63840 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -432,7 +432,7 @@ LinkerObject const& Assembly::assemble() const unsigned bytesPerTag = dev::bytesRequired(bytesRequiredForCode); byte tagPush = (byte)Instruction::PUSH1 - 1 + bytesPerTag; - unsigned bytesRequiredIncludingData = bytesRequiredForCode + 1; + unsigned bytesRequiredIncludingData = bytesRequiredForCode + 1 + m_auxiliaryData.size(); for (auto const& sub: m_subs) bytesRequiredIncludingData += sub->assemble().bytecode.size(); @@ -525,8 +525,9 @@ LinkerObject const& Assembly::assemble() const } } - if (!dataRef.empty() && !subRef.empty()) - ret.bytecode.push_back(0); + // Append a STOP just to be sure. + ret.bytecode.push_back(0); + for (size_t i = 0; i < m_subs.size(); ++i) { auto references = subRef.equal_range(i); @@ -568,6 +569,9 @@ LinkerObject const& Assembly::assemble() const } ret.bytecode += dataItem.second; } + + ret.bytecode += m_auxiliaryData; + for (unsigned pos: sizeRef) { bytesRef r(ret.bytecode.data() + pos, bytesPerDataRef); diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index a5fd4d51..9e7f9f7b 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -71,6 +71,9 @@ public: AssemblyItem appendJumpI(AssemblyItem const& _tag) { auto ret = append(_tag.pushTag()); append(solidity::Instruction::JUMPI); return ret; } AssemblyItem errorTag() { return AssemblyItem(PushTag, 0); } + /// Appends @a _data literally to the very end of the bytecode. + void appendAuxiliaryDataToEnd(bytes const& _data) { m_auxiliaryData += _data; } + template <class T> Assembly& operator<<(T const& _d) { append(_d); return *this; } AssemblyItems const& items() const { return m_items; } AssemblyItem const& back() const { return m_items.back(); } @@ -125,10 +128,12 @@ private: Json::Value createJsonValue(std::string _name, int _begin, int _end, std::string _value = std::string(), std::string _jumpType = std::string()) const; protected: - // 0 is reserved for exception + /// 0 is reserved for exception unsigned m_usedTags = 1; AssemblyItems m_items; std::map<h256, bytes> m_data; + /// Data that is appended to the very end of the contract. + bytes m_auxiliaryData; std::vector<std::shared_ptr<Assembly>> m_subs; std::map<h256, std::string> m_strings; std::map<h256, std::string> m_libraries; ///< Identifiers of libraries to be linked. diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index f8eb7108..3cd1dfbe 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -65,6 +65,7 @@ SourceUnitAnnotation& SourceUnit::annotation() const string Declaration::sourceUnitName() const { + solAssert(!!m_scope, ""); ASTNode const* scope = m_scope; while (dynamic_cast<Declaration const*>(scope) && dynamic_cast<Declaration const*>(scope)->m_scope) scope = dynamic_cast<Declaration const*>(scope)->m_scope; diff --git a/libsolidity/codegen/Compiler.cpp b/libsolidity/codegen/Compiler.cpp index 168e9462..b7e0cc64 100644 --- a/libsolidity/codegen/Compiler.cpp +++ b/libsolidity/codegen/Compiler.cpp @@ -36,6 +36,7 @@ void Compiler::compileContract( { ContractCompiler runtimeCompiler(nullptr, m_runtimeContext, m_optimize); runtimeCompiler.compileContract(_contract, _contracts); + m_runtimeContext.appendAuxiliaryData(_metadataHash.asBytes()); // This might modify m_runtimeContext because it can access runtime functions at // creation time. @@ -43,9 +44,6 @@ void Compiler::compileContract( m_runtimeSub = creationCompiler.compileConstructor(_contract, _contracts); m_context.optimise(m_optimize, m_optimizeRuns); - - solAssert(m_runtimeSub != size_t(-1), ""); - m_context.injectMetadataHashIntoSub(m_runtimeSub, _metadataHash); } void Compiler::compileClone( diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 9b921e9d..b99b0548 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -227,13 +227,6 @@ void CompilerContext::injectVersionStampIntoSub(size_t _subIndex) sub.injectStart(fromBigEndian<u256>(binaryVersion())); } -void CompilerContext::injectMetadataHashIntoSub(size_t _subIndex, h256 const& _metadataHash) -{ - eth::Assembly& sub = m_asm->sub(_subIndex); - sub.injectStart(Instruction::POP); - sub.injectStart(u256(_metadataHash)); -} - FunctionDefinition const& CompilerContext::resolveVirtualFunction( FunctionDefinition const& _function, vector<ContractDefinition const*>::const_iterator _searchStart diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h index c8a35f93..8fdb3e03 100644 --- a/libsolidity/codegen/CompilerContext.h +++ b/libsolidity/codegen/CompilerContext.h @@ -155,8 +155,8 @@ public: /// Prepends "PUSH <compiler version number> POP" void injectVersionStampIntoSub(size_t _subIndex); - /// Prepends "PUSH <metadata hash> POP" - void injectMetadataHashIntoSub(size_t _subIndex, h256 const& _metadataHash); + /// Appends arbitrary data to the end of the bytecode. + void appendAuxiliaryData(bytes const& _data) { m_asm->appendAuxiliaryDataToEnd(_data); } void optimise(bool _fullOptimsation, unsigned _runs = 200) { m_asm->optimise(_fullOptimsation, true, _runs); } diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index e77836ef..357b18bd 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -375,6 +375,7 @@ Json::Value const& CompilerStack::metadata(Contract const& _contract, Documentat if (!m_parseSuccessful) BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful.")); + solAssert(_contract.contract, ""); std::unique_ptr<Json::Value const>* doc; // checks wheather we already have the documentation |