mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Metadata stamp.
This commit is contained in:
		
							parent
							
								
									55a719a79c
								
							
						
					
					
						commit
						5789eaa78d
					
				| @ -38,13 +38,14 @@ h256 swarmHashSimple(bytesConstRef _data, size_t _size) | ||||
| 	return keccak256(toLittleEndian(_size) + _data.toBytes()); | ||||
| } | ||||
| 
 | ||||
| h256 swarmHashIntermediate(bytes const& _input, size_t _offset, size_t _length) | ||||
| h256 swarmHashIntermediate(string const& _input, size_t _offset, size_t _length) | ||||
| { | ||||
| 	bytesConstRef ref; | ||||
| 	bytes innerNodes; | ||||
| 	if (_length <= 0x1000) | ||||
| 		return swarmHashSimple(bytesConstRef(_input.data() + _offset, _length), _length); | ||||
| 		ref = bytesConstRef(_input).cropped(_offset, _length); | ||||
| 	else | ||||
| 	{ | ||||
| 		bytes innerNodes; | ||||
| 		size_t maxRepresentedSize = 0x1000; | ||||
| 		while (maxRepresentedSize * (0x1000 / 32) < _length) | ||||
| 			maxRepresentedSize *= (0x1000 / 32); | ||||
| @ -53,11 +54,12 @@ h256 swarmHashIntermediate(bytes const& _input, size_t _offset, size_t _length) | ||||
| 			size_t size = std::min(maxRepresentedSize, _length - i); | ||||
| 			innerNodes += swarmHashIntermediate(_input, _offset + i, size).asBytes(); | ||||
| 		} | ||||
| 		return swarmHashSimple(bytesConstRef(&innerNodes), _length); | ||||
| 		ref = bytesConstRef(&innerNodes); | ||||
| 	} | ||||
| 	return swarmHashSimple(ref, _length); | ||||
| } | ||||
| 
 | ||||
| h256 dev::swarmHash(bytes const& _input) | ||||
| h256 dev::swarmHash(string const& _input) | ||||
| { | ||||
| 	return swarmHashIntermediate(_input, 0, _input.size()); | ||||
| } | ||||
|  | ||||
| @ -20,12 +20,13 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include <libdevcore/FixedHash.h> | ||||
| #include <libdevcore/Common.h> | ||||
| 
 | ||||
| #include <string> | ||||
| 
 | ||||
| namespace dev | ||||
| { | ||||
| 
 | ||||
| /// Compute the "swarm hash" of @a _data
 | ||||
| h256 swarmHash(bytes const& _data); | ||||
| h256 swarmHash(std::string const& _data); | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -63,6 +63,14 @@ SourceUnitAnnotation& SourceUnit::annotation() const | ||||
| 	return static_cast<SourceUnitAnnotation&>(*m_annotation); | ||||
| } | ||||
| 
 | ||||
| string Declaration::sourceUnitName() const | ||||
| { | ||||
| 	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; | ||||
| 	return dynamic_cast<SourceUnit const&>(*scope).annotation().path; | ||||
| } | ||||
| 
 | ||||
| ImportAnnotation& ImportDirective::annotation() const | ||||
| { | ||||
| 	if (!m_annotation) | ||||
|  | ||||
| @ -158,6 +158,10 @@ public: | ||||
| 	ASTNode const* scope() const { return m_scope; } | ||||
| 	void setScope(ASTNode const* _scope) { m_scope = _scope; } | ||||
| 
 | ||||
| 	/// @returns the source name this declaration is present in.
 | ||||
| 	/// Can be combined with annotation().canonicalName to form a globally unique name.
 | ||||
| 	std::string sourceUnitName() const; | ||||
| 
 | ||||
| 	virtual bool isLValue() const { return false; } | ||||
| 	virtual bool isPartOfExternalInterface() const { return false; } | ||||
| 
 | ||||
|  | ||||
| @ -30,7 +30,8 @@ using namespace dev::solidity; | ||||
| 
 | ||||
| void Compiler::compileContract( | ||||
| 	ContractDefinition const& _contract, | ||||
| 	std::map<const ContractDefinition*, eth::Assembly const*> const& _contracts | ||||
| 	std::map<const ContractDefinition*, eth::Assembly const*> const& _contracts, | ||||
| 	h256 const& _metadataHash | ||||
| ) | ||||
| { | ||||
| 	ContractCompiler runtimeCompiler(nullptr, m_runtimeContext, m_optimize); | ||||
| @ -43,11 +44,8 @@ void Compiler::compileContract( | ||||
| 
 | ||||
| 	m_context.optimise(m_optimize, m_optimizeRuns); | ||||
| 
 | ||||
| 	if (_contract.isLibrary()) | ||||
| 	{ | ||||
| 		solAssert(m_runtimeSub != size_t(-1), ""); | ||||
| 		m_context.injectVersionStampIntoSub(m_runtimeSub); | ||||
| 	} | ||||
| 	solAssert(m_runtimeSub != size_t(-1), ""); | ||||
| 	m_context.injectMetadataHashIntoSub(m_runtimeSub, _metadataHash); | ||||
| } | ||||
| 
 | ||||
| void Compiler::compileClone( | ||||
|  | ||||
| @ -42,7 +42,8 @@ public: | ||||
| 
 | ||||
| 	void compileContract( | ||||
| 		ContractDefinition const& _contract, | ||||
| 		std::map<ContractDefinition const*, eth::Assembly const*> const& _contracts | ||||
| 		std::map<ContractDefinition const*, eth::Assembly const*> const& _contracts, | ||||
| 		h256 const& _metadataHash | ||||
| 	); | ||||
| 	/// 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.
 | ||||
|  | ||||
| @ -227,6 +227,13 @@ 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 | ||||
|  | ||||
| @ -155,6 +155,9 @@ 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); | ||||
| 
 | ||||
| 	void optimise(bool _fullOptimsation, unsigned _runs = 200) { m_asm->optimise(_fullOptimsation, true, _runs); } | ||||
| 
 | ||||
| 	/// @returns the runtime context if in creation mode and runtime context is set, nullptr otherwise.
 | ||||
|  | ||||
| @ -38,7 +38,10 @@ | ||||
| #include <libsolidity/formal/Why3Translator.h> | ||||
| 
 | ||||
| #include <libevmasm/Exceptions.h> | ||||
| #include <libdevcore/SHA3.h> | ||||
| 
 | ||||
| #include <libdevcore/SwarmHash.h> | ||||
| 
 | ||||
| #include <json/json.h> | ||||
| 
 | ||||
| #include <boost/algorithm/string.hpp> | ||||
| #include <boost/filesystem.hpp> | ||||
| @ -79,6 +82,8 @@ void CompilerStack::reset(bool _keepSources) | ||||
| 	{ | ||||
| 		m_sources.clear(); | ||||
| 	} | ||||
| 	m_optimize = false; | ||||
| 	m_optimizeRuns = 200; | ||||
| 	m_globalContext.reset(); | ||||
| 	m_sourceOrder.clear(); | ||||
| 	m_contracts.clear(); | ||||
| @ -217,17 +222,22 @@ vector<string> CompilerStack::contractNames() const | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| bool CompilerStack::compile(bool _optimize, unsigned _runs) | ||||
| bool CompilerStack::compile(bool _optimize, unsigned _runs, map<string, h160> const& _libraries) | ||||
| { | ||||
| 	if (!m_parseSuccessful) | ||||
| 		if (!parse()) | ||||
| 			return false; | ||||
| 
 | ||||
| 	m_optimize = _optimize; | ||||
| 	m_optimizeRuns = _runs; | ||||
| 	m_libraries = _libraries; | ||||
| 
 | ||||
| 	map<ContractDefinition const*, eth::Assembly const*> compiledContracts; | ||||
| 	for (Source const* source: m_sourceOrder) | ||||
| 		for (ASTPointer<ASTNode> const& node: source->ast->nodes()) | ||||
| 			if (auto contract = dynamic_cast<ContractDefinition const*>(node.get())) | ||||
| 				compileContract(_optimize, _runs, *contract, compiledContracts); | ||||
| 				compileContract(*contract, compiledContracts); | ||||
| 	this->link(); | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| @ -236,13 +246,13 @@ bool CompilerStack::compile(string const& _sourceCode, bool _optimize) | ||||
| 	return parse(_sourceCode) && compile(_optimize); | ||||
| } | ||||
| 
 | ||||
| void CompilerStack::link(const std::map<string, h160>& _libraries) | ||||
| void CompilerStack::link() | ||||
| { | ||||
| 	for (auto& contract: m_contracts) | ||||
| 	{ | ||||
| 		contract.second.object.link(_libraries); | ||||
| 		contract.second.runtimeObject.link(_libraries); | ||||
| 		contract.second.cloneObject.link(_libraries); | ||||
| 		contract.second.object.link(m_libraries); | ||||
| 		contract.second.runtimeObject.link(m_libraries); | ||||
| 		contract.second.cloneObject.link(m_libraries); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| @ -352,24 +362,31 @@ Json::Value const& CompilerStack::interface(string const& _contractName) const | ||||
| } | ||||
| 
 | ||||
| Json::Value const& CompilerStack::metadata(string const& _contractName, DocumentationType _type) const | ||||
| { | ||||
| 	if (!m_parseSuccessful) | ||||
| 		BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful.")); | ||||
| 
 | ||||
| 	return metadata(contract(_contractName), _type); | ||||
| } | ||||
| 
 | ||||
| Json::Value const& CompilerStack::metadata(Contract const& _contract, DocumentationType _type) const | ||||
| { | ||||
| 	if (!m_parseSuccessful) | ||||
| 		BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful.")); | ||||
| 
 | ||||
| 	std::unique_ptr<Json::Value const>* doc; | ||||
| 	Contract const& currentContract = contract(_contractName); | ||||
| 
 | ||||
| 	// checks wheather we already have the documentation
 | ||||
| 	switch (_type) | ||||
| 	{ | ||||
| 	case DocumentationType::NatspecUser: | ||||
| 		doc = ¤tContract.userDocumentation; | ||||
| 		doc = &_contract.userDocumentation; | ||||
| 		break; | ||||
| 	case DocumentationType::NatspecDev: | ||||
| 		doc = ¤tContract.devDocumentation; | ||||
| 		doc = &_contract.devDocumentation; | ||||
| 		break; | ||||
| 	case DocumentationType::ABIInterface: | ||||
| 		doc = ¤tContract.interface; | ||||
| 		doc = &_contract.interface; | ||||
| 		break; | ||||
| 	default: | ||||
| 		BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Illegal documentation type.")); | ||||
| @ -377,11 +394,19 @@ Json::Value const& CompilerStack::metadata(string const& _contractName, Document | ||||
| 
 | ||||
| 	// caches the result
 | ||||
| 	if (!*doc) | ||||
| 		doc->reset(new Json::Value(InterfaceHandler::documentation(*currentContract.contract, _type))); | ||||
| 		doc->reset(new Json::Value(InterfaceHandler::documentation(*_contract.contract, _type))); | ||||
| 
 | ||||
| 	return *(*doc); | ||||
| } | ||||
| 
 | ||||
| string const& CompilerStack::onChainMetadata(string const& _contractName) const | ||||
| { | ||||
| 	if (!m_parseSuccessful) | ||||
| 		BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful.")); | ||||
| 
 | ||||
| 	return contract(_contractName).onChainMetadata; | ||||
| } | ||||
| 
 | ||||
| Scanner const& CompilerStack::scanner(string const& _sourceName) const | ||||
| { | ||||
| 	return *source(_sourceName).scanner; | ||||
| @ -572,8 +597,6 @@ string CompilerStack::absolutePath(string const& _path, string const& _reference | ||||
| } | ||||
| 
 | ||||
| void CompilerStack::compileContract( | ||||
| 	bool _optimize, | ||||
| 	unsigned _runs, | ||||
| 	ContractDefinition const& _contract, | ||||
| 	map<ContractDefinition const*, eth::Assembly const*>& _compiledContracts | ||||
| ) | ||||
| @ -581,19 +604,21 @@ void CompilerStack::compileContract( | ||||
| 	if (_compiledContracts.count(&_contract) || !_contract.annotation().isFullyImplemented) | ||||
| 		return; | ||||
| 	for (auto const* dependency: _contract.annotation().contractDependencies) | ||||
| 		compileContract(_optimize, _runs, *dependency, _compiledContracts); | ||||
| 		compileContract(*dependency, _compiledContracts); | ||||
| 
 | ||||
| 	shared_ptr<Compiler> compiler = make_shared<Compiler>(_optimize, _runs); | ||||
| 	compiler->compileContract(_contract, _compiledContracts); | ||||
| 	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)); | ||||
| 	compiledContract.compiler = compiler; | ||||
| 	compiledContract.object = compiler->assembledObject(); | ||||
| 	compiledContract.runtimeObject = compiler->runtimeObject(); | ||||
| 	compiledContract.onChainMetadata = onChainMetadata; | ||||
| 	_compiledContracts[compiledContract.contract] = &compiler->assembly(); | ||||
| 
 | ||||
| 	try | ||||
| 	{ | ||||
| 		Compiler cloneCompiler(_optimize, _runs); | ||||
| 		Compiler cloneCompiler(m_optimize, m_optimizeRuns); | ||||
| 		cloneCompiler.compileClone(_contract, _compiledContracts); | ||||
| 		compiledContract.cloneObject = cloneCompiler.assembledObject(); | ||||
| 	} | ||||
| @ -637,6 +662,43 @@ CompilerStack::Source const& CompilerStack::source(string const& _sourceName) co | ||||
| 	return it->second; | ||||
| } | ||||
| 
 | ||||
| string CompilerStack::createOnChainMetadata(Contract const& _contract) const | ||||
| { | ||||
| 	Json::Value meta; | ||||
| 	meta["version"] = 1; | ||||
| 	meta["language"] = "Solidity"; | ||||
| 	meta["compiler"]["version"] = VersionString; | ||||
| 	meta["compilationTarget"] = | ||||
| 		_contract.contract->sourceUnitName() + | ||||
| 		":" + | ||||
| 		_contract.contract->annotation().canonicalName; | ||||
| 
 | ||||
| 	for (auto const& s: m_sources) | ||||
| 	{ | ||||
| 		solAssert(s.second.scanner, "Scanner not available"); | ||||
| 		meta["sources"][s.first]["swarm"] = | ||||
| 			"0x" + toHex(dev::swarmHash(s.second.scanner->source()).asBytes()); | ||||
| 	} | ||||
| 	meta["settings"]["optimizer"]["enabled"] = m_optimize; | ||||
| 	meta["settings"]["optimizer"]["runs"] = m_optimizeRuns; | ||||
| 
 | ||||
| 	set<string> remappings; | ||||
| 	for (auto const& r: m_remappings) | ||||
| 		remappings.insert(r.context + ":" + r.prefix + "=" + r.target); | ||||
| 	for (auto const& r: remappings) | ||||
| 		meta["settings"]["remappings"].append(r); | ||||
| 
 | ||||
| 	for (auto const& library: m_libraries) | ||||
| 		meta["settings"]["libraries"][library.first] = "0x" + toHex(library.second.asBytes()); | ||||
| 
 | ||||
| 	meta["output"]["abi"] = metadata(_contract, DocumentationType::ABIInterface); | ||||
| 	meta["output"]["natspec"] = metadata(_contract, DocumentationType::NatspecUser); | ||||
| 
 | ||||
| 	Json::FastWriter writer; | ||||
| 	writer.omitEndingLineFeed(); | ||||
| 	return writer.write(meta); | ||||
| } | ||||
| 
 | ||||
| string CompilerStack::computeSourceMapping(eth::AssemblyItems const& _items) const | ||||
| { | ||||
| 	string ret; | ||||
|  | ||||
| @ -113,14 +113,15 @@ public: | ||||
| 
 | ||||
| 	/// Compiles the source units that were previously added and parsed.
 | ||||
| 	/// @returns false on error.
 | ||||
| 	bool compile(bool _optimize = false, unsigned _runs = 200); | ||||
| 	bool compile( | ||||
| 		bool _optimize = false, | ||||
| 		unsigned _runs = 200, | ||||
| 		std::map<std::string, h160> const& _libraries = std::map<std::string, h160>{} | ||||
| 	); | ||||
| 	/// Parses and compiles the given source code.
 | ||||
| 	/// @returns false on error.
 | ||||
| 	bool compile(std::string const& _sourceCode, bool _optimize = false); | ||||
| 
 | ||||
| 	/// Inserts the given addresses into the linker objects of all compiled contracts.
 | ||||
| 	void link(std::map<std::string, h160> const& _libraries); | ||||
| 
 | ||||
| 	/// Tries to translate all source files into a language suitable for formal analysis.
 | ||||
| 	/// @param _errors list to store errors - defaults to the internal error list.
 | ||||
| 	/// @returns false on error.
 | ||||
| @ -170,6 +171,7 @@ public: | ||||
| 	/// @param type The type of the documentation to get.
 | ||||
| 	/// Can be one of 4 types defined at @c DocumentationType
 | ||||
| 	Json::Value const& metadata(std::string const& _contractName, DocumentationType _type) const; | ||||
| 	std::string const& onChainMetadata(std::string const& _contractName) const; | ||||
| 
 | ||||
| 	/// @returns the previously used scanner, useful for counting lines during error reporting.
 | ||||
| 	Scanner const& scanner(std::string const& _sourceName = "") const; | ||||
| @ -213,6 +215,7 @@ private: | ||||
| 		eth::LinkerObject object; | ||||
| 		eth::LinkerObject runtimeObject; | ||||
| 		eth::LinkerObject cloneObject; | ||||
| 		std::string onChainMetadata; ///< The metadata json that will be hashed into the chain.
 | ||||
| 		mutable std::unique_ptr<Json::Value const> interface; | ||||
| 		mutable std::unique_ptr<Json::Value const> userDocumentation; | ||||
| 		mutable std::unique_ptr<Json::Value const> devDocumentation; | ||||
| @ -233,16 +236,18 @@ private: | ||||
| 	std::string absolutePath(std::string const& _path, std::string const& _reference) const; | ||||
| 	/// Compile a single contract and put the result in @a _compiledContracts.
 | ||||
| 	void compileContract( | ||||
| 		bool _optimize, | ||||
| 		unsigned _runs, | ||||
| 		ContractDefinition const& _contract, | ||||
| 		std::map<ContractDefinition const*, eth::Assembly const*>& _compiledContracts | ||||
| 	); | ||||
| 
 | ||||
| 	void link(); | ||||
| 
 | ||||
| 	Contract const& contract(std::string const& _contractName = "") const; | ||||
| 	Source const& source(std::string const& _sourceName = "") const; | ||||
| 
 | ||||
| 	std::string createOnChainMetadata(Contract const& _contract) const; | ||||
| 	std::string computeSourceMapping(eth::AssemblyItems const& _items) const; | ||||
| 	Json::Value const& metadata(Contract const&, DocumentationType _type) const; | ||||
| 
 | ||||
| 	struct Remapping | ||||
| 	{ | ||||
| @ -252,6 +257,9 @@ private: | ||||
| 	}; | ||||
| 
 | ||||
| 	ReadFileCallback m_readFile; | ||||
| 	bool m_optimize = false; | ||||
| 	size_t m_optimizeRuns = 200; | ||||
| 	std::map<std::string, h160> m_libraries; | ||||
| 	/// list of path prefix remappings, e.g. mylibrary: github.com/ethereum = /usr/local/ethereum
 | ||||
| 	/// "context:prefix=target"
 | ||||
| 	std::vector<Remapping> m_remappings; | ||||
|  | ||||
| @ -80,6 +80,8 @@ public: | ||||
| 
 | ||||
| 	void reset() { m_position = 0; } | ||||
| 
 | ||||
| 	std::string const& source() const { return m_source; } | ||||
| 
 | ||||
| 	///@{
 | ||||
| 	///@name Error printing helper functions
 | ||||
| 	/// Functions that help pretty-printing parse errors
 | ||||
| @ -102,6 +104,8 @@ public: | ||||
| 
 | ||||
| 	explicit Scanner(CharStream const& _source = CharStream(), std::string const& _sourceName = "") { reset(_source, _sourceName); } | ||||
| 
 | ||||
| 	std::string source() const { return m_source.source(); } | ||||
| 
 | ||||
| 	/// Resets the scanner as if newly constructed with _source and _sourceName as input.
 | ||||
| 	void reset(CharStream const& _source, std::string const& _sourceName); | ||||
| 	/// Resets scanner to the start of input.
 | ||||
|  | ||||
| @ -78,6 +78,7 @@ static string const g_argCloneBinaryStr = "clone-bin"; | ||||
| static string const g_argOpcodesStr = "opcodes"; | ||||
| static string const g_argNatspecDevStr = "devdoc"; | ||||
| static string const g_argNatspecUserStr = "userdoc"; | ||||
| static string const g_argMetadata = "metadata"; | ||||
| static string const g_argAddStandard = "add-std"; | ||||
| static string const g_stdinFileName = "<stdin>"; | ||||
| 
 | ||||
| @ -91,6 +92,7 @@ static set<string> const g_combinedJsonArgs{ | ||||
| 	"opcodes", | ||||
| 	"abi", | ||||
| 	"interface", | ||||
| 	"metadata", | ||||
| 	"asm", | ||||
| 	"ast", | ||||
| 	"userdoc", | ||||
| @ -117,6 +119,7 @@ static bool needsHumanTargetedStdout(po::variables_map const& _args) | ||||
| 	for (string const& arg: { | ||||
| 		g_argAbiStr, | ||||
| 		g_argSignatureHashes, | ||||
| 		g_argMetadata, | ||||
| 		g_argNatspecUserStr, | ||||
| 		g_argAstJson, | ||||
| 		g_argNatspecDevStr, | ||||
| @ -202,6 +205,18 @@ void CommandLineInterface::handleSignatureHashes(string const& _contract) | ||||
| 		cout << "Function signatures: " << endl << out; | ||||
| } | ||||
| 
 | ||||
| void CommandLineInterface::handleOnChainMetadata(string const& _contract) | ||||
| { | ||||
| 	if (!m_args.count(g_argMetadata)) | ||||
| 		return; | ||||
| 
 | ||||
| 	string data = m_compiler->onChainMetadata(_contract); | ||||
| 	if (m_args.count("output-dir")) | ||||
| 		createFile(_contract + ".meta", data); | ||||
| 	else | ||||
| 		cout << "Metadata: " << endl << data << endl; | ||||
| } | ||||
| 
 | ||||
| void CommandLineInterface::handleMeta(DocumentationType _type, string const& _contract) | ||||
| { | ||||
| 	std::string argName; | ||||
| @ -467,6 +482,7 @@ Allowed options)", | ||||
| 		(g_argSignatureHashes.c_str(), "Function signature hashes of the contracts.") | ||||
| 		(g_argNatspecUserStr.c_str(), "Natspec user documentation of all contracts.") | ||||
| 		(g_argNatspecDevStr.c_str(), "Natspec developer documentation of all contracts.") | ||||
| 		(g_argMetadata.c_str(), "Combined metadata JSON whose swarm hash is stored on-chain.") | ||||
| 		("formal", "Translated source suitable for formal analysis."); | ||||
| 	desc.add(outputComponents); | ||||
| 
 | ||||
| @ -581,9 +597,7 @@ bool CommandLineInterface::processInput() | ||||
| 		// TODO: Perhaps we should not compile unless requested
 | ||||
| 		bool optimize = m_args.count("optimize") > 0; | ||||
| 		unsigned runs = m_args["optimize-runs"].as<unsigned>(); | ||||
| 		bool successful = m_compiler->compile(optimize, runs); | ||||
| 		if (successful) | ||||
| 			m_compiler->link(m_libraries); | ||||
| 		bool successful = m_compiler->compile(optimize, runs, m_libraries); | ||||
| 
 | ||||
| 		if (successful && m_args.count("formal")) | ||||
| 			if (!m_compiler->prepareFormalAnalysis()) | ||||
| @ -659,6 +673,8 @@ void CommandLineInterface::handleCombinedJSON() | ||||
| 		Json::Value contractData(Json::objectValue); | ||||
| 		if (requests.count("abi")) | ||||
| 			contractData["abi"] = dev::jsonCompactPrint(m_compiler->interface(contractName)); | ||||
| 		if (requests.count("metadata")) | ||||
| 			contractData["metadata"] = m_compiler->onChainMetadata(contractName); | ||||
| 		if (requests.count("bin")) | ||||
| 			contractData["bin"] = m_compiler->object(contractName).toHex(); | ||||
| 		if (requests.count("bin-runtime")) | ||||
| @ -918,6 +934,7 @@ void CommandLineInterface::outputCompilationResults() | ||||
| 
 | ||||
| 		handleBytecode(contract); | ||||
| 		handleSignatureHashes(contract); | ||||
| 		handleOnChainMetadata(contract); | ||||
| 		handleMeta(DocumentationType::ABIInterface, contract); | ||||
| 		handleMeta(DocumentationType::NatspecDev, contract); | ||||
| 		handleMeta(DocumentationType::NatspecUser, contract); | ||||
|  | ||||
| @ -63,6 +63,7 @@ private: | ||||
| 	void handleOpcode(std::string const& _contract); | ||||
| 	void handleBytecode(std::string const& _contract); | ||||
| 	void handleSignatureHashes(std::string const& _contract); | ||||
| 	void handleOnChainMetadata(std::string const& _contract); | ||||
| 	void handleMeta(DocumentationType _type, std::string const& _contract); | ||||
| 	void handleGasEstimation(std::string const& _contract); | ||||
| 	void handleFormal(); | ||||
|  | ||||
| @ -218,6 +218,7 @@ string compile(StringMap const& _sources, bool _optimize, CStyleReadFileCallback | ||||
| 				contractData["bytecode"] = compiler.object(contractName).toHex(); | ||||
| 				contractData["runtimeBytecode"] = compiler.runtimeObject(contractName).toHex(); | ||||
| 				contractData["opcodes"] = solidity::disassemble(compiler.object(contractName).bytecode); | ||||
| 				contractData["metadata"] = compiler.onChainMetadata(contractName); | ||||
| 				contractData["functionHashes"] = functionHashes(compiler.contractDefinition(contractName)); | ||||
| 				contractData["gasEstimates"] = estimateGas(compiler, contractName); | ||||
| 				auto sourceMap = compiler.sourceMapping(contractName); | ||||
|  | ||||
| @ -31,24 +31,24 @@ namespace test | ||||
| 
 | ||||
| BOOST_AUTO_TEST_SUITE(SwarmHash) | ||||
| 
 | ||||
| string swarmHashHex(bytes const& _input) | ||||
| string swarmHashHex(string const& _input) | ||||
| { | ||||
| 	return toHex(swarmHash(_input).asBytes()); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(test_zeros) | ||||
| { | ||||
| 	BOOST_CHECK_EQUAL(swarmHashHex(bytes()), string("011b4d03dd8c01f1049143cf9c4c817e4b167f1d1b83e5c6f0f10d89ba1e7bce")); | ||||
| 	BOOST_CHECK_EQUAL(swarmHashHex(bytes(0x1000 - 1, 0)), string("32f0faabc4265ac238cd945087133ce3d7e9bb2e536053a812b5373c54043adb")); | ||||
| 	BOOST_CHECK_EQUAL(swarmHashHex(bytes(0x1000, 0)), string("411dd45de7246e94589ff5888362c41e85bd3e582a92d0fda8f0e90b76439bec")); | ||||
| 	BOOST_CHECK_EQUAL(swarmHashHex(bytes(0x1000 + 1, 0)), string("69754a0098432bbc2e84fe1205276870748a61a065ab6ef44d6a2e7b13ce044d")); | ||||
| 	BOOST_CHECK_EQUAL(swarmHashHex(bytes(0x2000 - 1, 0)), string("69ad3c581043404f775ffa8d6f1b25ad4a9ee812971190e90209c0966116a321")); | ||||
| 	BOOST_CHECK_EQUAL(swarmHashHex(bytes(0x2000, 0)), string("f00222373ff82d0a178dc6271c78953e9c88f74130a52d401f5ec51475f63c43")); | ||||
| 	BOOST_CHECK_EQUAL(swarmHashHex(bytes(0x2000 + 1, 0)), string("86d6773e79e02fd8145ee1aedba89ace0c15f2566db1249654000039a9a134bf")); | ||||
| 	BOOST_CHECK_EQUAL(swarmHashHex(bytes(0x80000, 0)), string("cc0854fe2c6b98e920d5c14b1a88e6d4223e55b8f78883f60939aa2485e361bf")); | ||||
| 	BOOST_CHECK_EQUAL(swarmHashHex(bytes(0x80020, 0)), string("ee9ffca246e70d3704740ba4df450fa6988d14a1c2439c7e734c7a77a4eb6fd3")); | ||||
| 	BOOST_CHECK_EQUAL(swarmHashHex(bytes(0x800020, 0)), string("78b90b20c90559fb904535181a7c28929ea2f30a2329dbc25232de579709f12f")); | ||||
| 	BOOST_CHECK_EQUAL(swarmHashHex(bytes(2095104, 0)), string("a9958184589fc11b4027a4c233e777ebe2e99c66f96b74aef2a0638a94dd5439")); | ||||
| 	BOOST_CHECK_EQUAL(swarmHashHex(string()), string("011b4d03dd8c01f1049143cf9c4c817e4b167f1d1b83e5c6f0f10d89ba1e7bce")); | ||||
| 	BOOST_CHECK_EQUAL(swarmHashHex(string(0x1000 - 1, 0)), string("32f0faabc4265ac238cd945087133ce3d7e9bb2e536053a812b5373c54043adb")); | ||||
| 	BOOST_CHECK_EQUAL(swarmHashHex(string(0x1000, 0)), string("411dd45de7246e94589ff5888362c41e85bd3e582a92d0fda8f0e90b76439bec")); | ||||
| 	BOOST_CHECK_EQUAL(swarmHashHex(string(0x1000 + 1, 0)), string("69754a0098432bbc2e84fe1205276870748a61a065ab6ef44d6a2e7b13ce044d")); | ||||
| 	BOOST_CHECK_EQUAL(swarmHashHex(string(0x2000 - 1, 0)), string("69ad3c581043404f775ffa8d6f1b25ad4a9ee812971190e90209c0966116a321")); | ||||
| 	BOOST_CHECK_EQUAL(swarmHashHex(string(0x2000, 0)), string("f00222373ff82d0a178dc6271c78953e9c88f74130a52d401f5ec51475f63c43")); | ||||
| 	BOOST_CHECK_EQUAL(swarmHashHex(string(0x2000 + 1, 0)), string("86d6773e79e02fd8145ee1aedba89ace0c15f2566db1249654000039a9a134bf")); | ||||
| 	BOOST_CHECK_EQUAL(swarmHashHex(string(0x80000, 0)), string("cc0854fe2c6b98e920d5c14b1a88e6d4223e55b8f78883f60939aa2485e361bf")); | ||||
| 	BOOST_CHECK_EQUAL(swarmHashHex(string(0x80020, 0)), string("ee9ffca246e70d3704740ba4df450fa6988d14a1c2439c7e734c7a77a4eb6fd3")); | ||||
| 	BOOST_CHECK_EQUAL(swarmHashHex(string(0x800020, 0)), string("78b90b20c90559fb904535181a7c28929ea2f30a2329dbc25232de579709f12f")); | ||||
| 	BOOST_CHECK_EQUAL(swarmHashHex(string(2095104, 0)), string("a9958184589fc11b4027a4c233e777ebe2e99c66f96b74aef2a0638a94dd5439")); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_SUITE_END() | ||||
|  | ||||
| @ -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*>{}); | ||||
| 			compiler.compileContract(*contract, map<ContractDefinition const*, Assembly const*>{}, h256()); | ||||
| 
 | ||||
| 			return compiler.runtimeAssemblyItems(); | ||||
| 		} | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user