mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Use CBOR encoding.
This commit is contained in:
parent
e0d4a3d518
commit
6a7ff039df
@ -236,20 +236,22 @@ If ``solc`` is called with the option ``--link``, all input files are interprete
|
|||||||
Contract Metadata
|
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.
|
contract metadata, that contains information about the current contract.
|
||||||
It can be used to query the compiler version, the sourcecode, the ABI
|
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 NatSpec documentation in order to more safely interact with the contract
|
||||||
and to verify its source code.
|
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
|
The compiler appends a swarm hash (32 bytes) of that file to the end of the
|
||||||
contract, so that you can retrieve the file in an authenticated way
|
bytecode (for details, see below) of each contract, so that you can retrieve
|
||||||
without having to resort to a centralized data provider.
|
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)
|
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
|
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
|
The metadata file has the following format. The example below is presented in a
|
||||||
human-readable way. Properly formatted metadata should use quotes correctly,
|
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
|
Usage for Automatic Interface Generation and NatSpec
|
||||||
----------------------------------------------------
|
----------------------------------------------------
|
||||||
|
|
||||||
The metadata is used in the following way: A component that wants to interact
|
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
|
with a contract (e.g. mist) retrieves the code of the contract, from that
|
||||||
and from that the last 32 bytes, which are interpreted as the swarm hash of
|
the swarm hash of a file which is then retrieved.
|
||||||
a file which is then retrieved.
|
|
||||||
That file is JSON-decoded into a structure like above.
|
That file is JSON-decoded into a structure like above.
|
||||||
|
|
||||||
The component can then use the abi to automatically generate a rudimentary
|
The component can then use the abi to automatically generate a rudimentary
|
||||||
|
@ -31,12 +31,12 @@ using namespace dev::solidity;
|
|||||||
void Compiler::compileContract(
|
void Compiler::compileContract(
|
||||||
ContractDefinition const& _contract,
|
ContractDefinition const& _contract,
|
||||||
std::map<const ContractDefinition*, eth::Assembly const*> const& _contracts,
|
std::map<const ContractDefinition*, eth::Assembly const*> const& _contracts,
|
||||||
h256 const& _metadataHash
|
bytes const& _metadata
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
ContractCompiler runtimeCompiler(nullptr, m_runtimeContext, m_optimize);
|
ContractCompiler runtimeCompiler(nullptr, m_runtimeContext, m_optimize);
|
||||||
runtimeCompiler.compileContract(_contract, _contracts);
|
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
|
// This might modify m_runtimeContext because it can access runtime functions at
|
||||||
// creation time.
|
// creation time.
|
||||||
|
@ -43,7 +43,7 @@ public:
|
|||||||
void compileContract(
|
void compileContract(
|
||||||
ContractDefinition const& _contract,
|
ContractDefinition const& _contract,
|
||||||
std::map<ContractDefinition const*, eth::Assembly const*> const& _contracts,
|
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
|
/// 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.
|
/// contract at runtime, but contains the full creation-time code.
|
||||||
|
@ -611,7 +611,14 @@ void CompilerStack::compileContract(
|
|||||||
shared_ptr<Compiler> compiler = make_shared<Compiler>(m_optimize, m_optimizeRuns);
|
shared_ptr<Compiler> compiler = make_shared<Compiler>(m_optimize, m_optimizeRuns);
|
||||||
Contract& compiledContract = m_contracts.at(_contract.name());
|
Contract& compiledContract = m_contracts.at(_contract.name());
|
||||||
string onChainMetadata = createOnChainMetadata(compiledContract);
|
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.compiler = compiler;
|
||||||
compiledContract.object = compiler->assembledObject();
|
compiledContract.object = compiler->assembledObject();
|
||||||
compiledContract.runtimeObject = compiler->runtimeObject();
|
compiledContract.runtimeObject = compiler->runtimeObject();
|
||||||
|
@ -75,7 +75,7 @@ eth::AssemblyItems compileContract(const string& _sourceCode)
|
|||||||
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
|
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
|
||||||
{
|
{
|
||||||
Compiler compiler;
|
Compiler compiler;
|
||||||
compiler.compileContract(*contract, map<ContractDefinition const*, Assembly const*>{}, h256());
|
compiler.compileContract(*contract, map<ContractDefinition const*, Assembly const*>{}, bytes());
|
||||||
|
|
||||||
return compiler.runtimeAssemblyItems();
|
return compiler.runtimeAssemblyItems();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user