aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2016-11-30 00:47:47 +0800
committerchriseth <c@ethdev.com>2016-12-01 23:03:59 +0800
commit6a7ff039df15be59fbb71dc3dfaad09fb0b8961f (patch)
tree01d433c964f51111800766c30f230dd4c0e680ea
parente0d4a3d518dc742d94571ef1e16b3f95765ec62f (diff)
downloaddexon-solidity-6a7ff039df15be59fbb71dc3dfaad09fb0b8961f.tar
dexon-solidity-6a7ff039df15be59fbb71dc3dfaad09fb0b8961f.tar.gz
dexon-solidity-6a7ff039df15be59fbb71dc3dfaad09fb0b8961f.tar.bz2
dexon-solidity-6a7ff039df15be59fbb71dc3dfaad09fb0b8961f.tar.lz
dexon-solidity-6a7ff039df15be59fbb71dc3dfaad09fb0b8961f.tar.xz
dexon-solidity-6a7ff039df15be59fbb71dc3dfaad09fb0b8961f.tar.zst
dexon-solidity-6a7ff039df15be59fbb71dc3dfaad09fb0b8961f.zip
Use CBOR encoding.
-rw-r--r--docs/miscellaneous.rst36
-rw-r--r--libsolidity/codegen/Compiler.cpp4
-rw-r--r--libsolidity/codegen/Compiler.h2
-rw-r--r--libsolidity/interface/CompilerStack.cpp9
-rw-r--r--test/libsolidity/Assembly.cpp2
5 files changed, 39 insertions, 14 deletions
diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst
index 3b8c5232..5b51c4a9 100644
--- a/docs/miscellaneous.rst
+++ b/docs/miscellaneous.rst
@@ -236,20 +236,22 @@ If ``solc`` is called with the option ``--link``, all input files are interprete
Contract Metadata
*****************
-The Solidity compiler automatically generates an internal json file, the
+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 sourcecode, 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 (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.
+The compiler appends a swarm hash (32 bytes) of that 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``.
+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.
+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,
@@ -319,13 +321,29 @@ Comments are of course also not permitted and used here only for explanatory pur
}
}
+
+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, you can check the end of the deployed
+bytecode 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
-and from that the last 32 bytes, which are interpreted as the swarm hash of
-a file which is then retrieved.
+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
diff --git a/libsolidity/codegen/Compiler.cpp b/libsolidity/codegen/Compiler.cpp
index b7e0cc64..44264a07 100644
--- a/libsolidity/codegen/Compiler.cpp
+++ b/libsolidity/codegen/Compiler.cpp
@@ -31,12 +31,12 @@ using namespace dev::solidity;
void Compiler::compileContract(
ContractDefinition const& _contract,
std::map<const ContractDefinition*, eth::Assembly const*> const& _contracts,
- h256 const& _metadataHash
+ bytes const& _metadata
)
{
ContractCompiler runtimeCompiler(nullptr, m_runtimeContext, m_optimize);
runtimeCompiler.compileContract(_contract, _contracts);
- m_runtimeContext.appendAuxiliaryData(_metadataHash.asBytes());
+ m_runtimeContext.appendAuxiliaryData(_metadata);
// This might modify m_runtimeContext because it can access runtime functions at
// creation time.
diff --git a/libsolidity/codegen/Compiler.h b/libsolidity/codegen/Compiler.h
index 58ef1963..eef078c1 100644
--- a/libsolidity/codegen/Compiler.h
+++ b/libsolidity/codegen/Compiler.h
@@ -43,7 +43,7 @@ public:
void compileContract(
ContractDefinition const& _contract,
std::map<ContractDefinition const*, eth::Assembly const*> const& _contracts,
- h256 const& _metadataHash
+ bytes const& _metadata
);
/// Compiles a contract that uses DELEGATECALL to call into a pre-deployed version of the given
/// contract at runtime, but contains the full creation-time code.
diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp
index 357b18bd..d79345f0 100644
--- a/libsolidity/interface/CompilerStack.cpp
+++ b/libsolidity/interface/CompilerStack.cpp
@@ -611,7 +611,14 @@ void CompilerStack::compileContract(
shared_ptr<Compiler> compiler = make_shared<Compiler>(m_optimize, m_optimizeRuns);
Contract& compiledContract = m_contracts.at(_contract.name());
string onChainMetadata = createOnChainMetadata(compiledContract);
- compiler->compileContract(_contract, _compiledContracts, dev::swarmHash(onChainMetadata));
+ bytes cborEncodedMetadata =
+ // CBOR-encoding of {"bzzr0": dev::swarmHash(onChainMetadata)}
+ bytes{0xa1, 0x65, 'b', 'z', 'z', 'r', '0', 0x58, 0x20} +
+ dev::swarmHash(onChainMetadata).asBytes();
+ solAssert(cborEncodedMetadata.size() <= 0xffff, "Metadata too large");
+ // 16-bit big endian length
+ cborEncodedMetadata += toCompactBigEndian(cborEncodedMetadata.size(), 2);
+ compiler->compileContract(_contract, _compiledContracts, cborEncodedMetadata);
compiledContract.compiler = compiler;
compiledContract.object = compiler->assembledObject();
compiledContract.runtimeObject = compiler->runtimeObject();
diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp
index 27709086..bdbe7dba 100644
--- a/test/libsolidity/Assembly.cpp
+++ b/test/libsolidity/Assembly.cpp
@@ -75,7 +75,7 @@ eth::AssemblyItems compileContract(const string& _sourceCode)
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
{
Compiler compiler;
- compiler.compileContract(*contract, map<ContractDefinition const*, Assembly const*>{}, h256());
+ compiler.compileContract(*contract, map<ContractDefinition const*, Assembly const*>{}, bytes());
return compiler.runtimeAssemblyItems();
}