aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/miscellaneous.rst9
-rw-r--r--libevmasm/Assembly.cpp10
-rw-r--r--libevmasm/Assembly.h7
-rw-r--r--libsolidity/ast/AST.cpp1
-rw-r--r--libsolidity/codegen/Compiler.cpp4
-rw-r--r--libsolidity/codegen/CompilerContext.cpp7
-rw-r--r--libsolidity/codegen/CompilerContext.h4
-rw-r--r--libsolidity/interface/CompilerStack.cpp1
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