Include used events in `--hashes` output

This commit is contained in:
Marenz 2022-02-01 15:42:08 +01:00
parent 3e7c68d9b0
commit 46075d04d9
12 changed files with 47 additions and 32 deletions

View File

@ -192,7 +192,7 @@ FunctionDefinition const* ContractDefinition::receiveFunction() const
return nullptr; return nullptr;
} }
vector<EventDefinition const*> const& ContractDefinition::interfaceEvents() const vector<EventDefinition const*> const& ContractDefinition::definedInterfaceEvents() const
{ {
return m_interfaceEvents.init([&]{ return m_interfaceEvents.init([&]{
set<string> eventsSeen; set<string> eventsSeen;
@ -213,11 +213,20 @@ vector<EventDefinition const*> const& ContractDefinition::interfaceEvents() cons
interfaceEvents.push_back(e); interfaceEvents.push_back(e);
} }
} }
return interfaceEvents; return interfaceEvents;
}); });
} }
vector<EventDefinition const*> const ContractDefinition::usedInterfaceEvents() const
{
solAssert(annotation().creationCallGraph.set(), "");
return convertContainer<std::vector<EventDefinition const*>>(
(*annotation().creationCallGraph)->emittedEvents +
(*annotation().deployedCallGraph)->emittedEvents
);
}
vector<ErrorDefinition const*> ContractDefinition::interfaceErrors(bool _requireCallGraph) const vector<ErrorDefinition const*> ContractDefinition::interfaceErrors(bool _requireCallGraph) const
{ {
set<ErrorDefinition const*, CompareByID> result; set<ErrorDefinition const*, CompareByID> result;
@ -227,10 +236,9 @@ vector<ErrorDefinition const*> ContractDefinition::interfaceErrors(bool _require
if (_requireCallGraph) if (_requireCallGraph)
solAssert(annotation().creationCallGraph.set(), ""); solAssert(annotation().creationCallGraph.set(), "");
if (annotation().creationCallGraph.set()) if (annotation().creationCallGraph.set())
{ result +=
result += (*annotation().creationCallGraph)->usedErrors; (*annotation().creationCallGraph)->usedErrors +
result += (*annotation().deployedCallGraph)->usedErrors; (*annotation().deployedCallGraph)->usedErrors;
}
return convertContainer<vector<ErrorDefinition const*>>(move(result)); return convertContainer<vector<ErrorDefinition const*>>(move(result));
} }

View File

@ -519,7 +519,8 @@ public:
return ranges::subrange<decltype(b)>(b, e) | ranges::views::values; return ranges::subrange<decltype(b)>(b, e) | ranges::views::values;
} }
std::vector<EventDefinition const*> events() const { return filteredNodes<EventDefinition>(m_subNodes); } std::vector<EventDefinition const*> events() const { return filteredNodes<EventDefinition>(m_subNodes); }
std::vector<EventDefinition const*> const& interfaceEvents() const; std::vector<EventDefinition const*> const& definedInterfaceEvents() const;
std::vector<EventDefinition const*> const usedInterfaceEvents() const;
/// @returns all errors defined in this contract or any base contract /// @returns all errors defined in this contract or any base contract
/// and all errors referenced during execution. /// and all errors referenced during execution.
/// @param _requireCallGraph if false, do not fail if the call graph has not been computed yet. /// @param _requireCallGraph if false, do not fail if the call graph has not been computed yet.

View File

@ -101,7 +101,7 @@ Json::Value ABI::generate(ContractDefinition const& _contractDef)
method["stateMutability"] = stateMutabilityToString(externalFunctionType->stateMutability()); method["stateMutability"] = stateMutabilityToString(externalFunctionType->stateMutability());
abi.emplace(std::move(method)); abi.emplace(std::move(method));
} }
for (auto const& it: _contractDef.interfaceEvents()) for (auto const& it: _contractDef.definedInterfaceEvents())
{ {
Json::Value event{Json::objectValue}; Json::Value event{Json::objectValue};
event["type"] = "event"; event["type"] = "event";

View File

@ -81,6 +81,8 @@
#include <boost/algorithm/string/replace.hpp> #include <boost/algorithm/string/replace.hpp>
#include <range/v3/view/concat.hpp>
#include <utility> #include <utility>
#include <map> #include <map>
#include <limits> #include <limits>
@ -1014,31 +1016,34 @@ Json::Value const& CompilerStack::natspecDev(Contract const& _contract) const
return _contract.devDocumentation.init([&]{ return Natspec::devDocumentation(*_contract.contract); }); return _contract.devDocumentation.init([&]{ return Natspec::devDocumentation(*_contract.contract); });
} }
Json::Value CompilerStack::contractIdentifiers(string const& _contractName) const Json::Value CompilerStack::interfaceSymbols(string const& _contractName) const
{ {
if (m_stackState < AnalysisPerformed) if (m_stackState < AnalysisPerformed)
solThrow(CompilerError, "Analysis was not successful."); solThrow(CompilerError, "Analysis was not successful.");
Json::Value contractIdentifiers(Json::objectValue); Json::Value interfaceSymbols(Json::objectValue);
// Always have a methods object // Always have a methods object
contractIdentifiers["methods"] = Json::objectValue; interfaceSymbols["methods"] = Json::objectValue;
for (auto const& it: contractDefinition(_contractName).interfaceFunctions()) for (auto const& it: contractDefinition(_contractName).interfaceFunctions())
contractIdentifiers["methods"][it.second->externalSignature()] = it.first.hex(); interfaceSymbols["methods"][it.second->externalSignature()] = it.first.hex();
for (ErrorDefinition const* error: contractDefinition(_contractName).interfaceErrors()) for (ErrorDefinition const* error: contractDefinition(_contractName).interfaceErrors())
{ {
string signature = error->functionType(true)->externalSignature(); string signature = error->functionType(true)->externalSignature();
contractIdentifiers["errors"][signature] = toHex(toCompactBigEndian(selectorFromSignature32(signature), 4)); interfaceSymbols["errors"][signature] = toHex(toCompactBigEndian(selectorFromSignature32(signature), 4));
} }
for (EventDefinition const* event: contractDefinition(_contractName).interfaceEvents()) for (EventDefinition const* event: ranges::concat_view(
contractDefinition(_contractName).definedInterfaceEvents(),
contractDefinition(_contractName).usedInterfaceEvents()
))
if (!event->isAnonymous()) if (!event->isAnonymous())
{ {
string signature = event->functionType(true)->externalSignature(); string signature = event->functionType(true)->externalSignature();
contractIdentifiers["events"][signature] = toHex(u256(h256::Arith(keccak256(signature)))); interfaceSymbols["events"][signature] = toHex(u256(h256::Arith(keccak256(signature))));
} }
return contractIdentifiers; return interfaceSymbols;
} }
bytes CompilerStack::cborMetadata(string const& _contractName, bool _forIR) const bytes CompilerStack::cborMetadata(string const& _contractName, bool _forIR) const

View File

@ -328,7 +328,7 @@ public:
Json::Value const& natspecDev(std::string const& _contractName) const; Json::Value const& natspecDev(std::string const& _contractName) const;
/// @returns a JSON object with the three members ``methods``, ``events``, ``errors``. Each is a map, mapping identifiers (hashes) to function names. /// @returns a JSON object with the three members ``methods``, ``events``, ``errors``. Each is a map, mapping identifiers (hashes) to function names.
Json::Value contractIdentifiers(std::string const& _contractName) const; Json::Value interfaceSymbols(std::string const& _contractName) const;
/// @returns the Contract Metadata matching the pipeline selected using the viaIR setting. /// @returns the Contract Metadata matching the pipeline selected using the viaIR setting.
std::string const& metadata(std::string const& _contractName) const { return metadata(contract(_contractName)); } std::string const& metadata(std::string const& _contractName) const { return metadata(contract(_contractName)); }

View File

@ -78,7 +78,7 @@ Json::Value Natspec::userDocumentation(ContractDefinition const& _contractDef)
doc["methods"][it.second->externalSignature()]["notice"] = value; doc["methods"][it.second->externalSignature()]["notice"] = value;
} }
for (auto const& event: _contractDef.interfaceEvents()) for (auto const& event: _contractDef.definedInterfaceEvents())
{ {
string value = extractDoc(event->annotation().docTags, "notice"); string value = extractDoc(event->annotation().docTags, "notice");
if (!value.empty()) if (!value.empty())

View File

@ -1298,7 +1298,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "evm.legacyAssembly", wildcardMatchesExperimental)) if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "evm.legacyAssembly", wildcardMatchesExperimental))
evmData["legacyAssembly"] = compilerStack.assemblyJSON(contractName); evmData["legacyAssembly"] = compilerStack.assemblyJSON(contractName);
if (isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "evm.methodIdentifiers", wildcardMatchesExperimental)) if (isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "evm.methodIdentifiers", wildcardMatchesExperimental))
evmData["methodIdentifiers"] = compilerStack.contractIdentifiers(contractName)["methods"]; evmData["methodIdentifiers"] = compilerStack.interfaceSymbols(contractName)["methods"];
if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "evm.gasEstimates", wildcardMatchesExperimental)) if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "evm.gasEstimates", wildcardMatchesExperimental))
evmData["gasEstimates"] = compilerStack.gasEstimates(contractName); evmData["gasEstimates"] = compilerStack.gasEstimates(contractName);

View File

@ -270,23 +270,23 @@ void CommandLineInterface::handleSignatureHashes(string const& _contract)
if (!m_options.compiler.outputs.signatureHashes) if (!m_options.compiler.outputs.signatureHashes)
return; return;
Json::Value contractIdentifiers = m_compiler->contractIdentifiers(_contract); Json::Value interfaceSymbols = m_compiler->interfaceSymbols(_contract);
string out = "Function signatures:\n"; string out = "Function signatures:\n";
for (auto const& name: contractIdentifiers["methods"].getMemberNames()) for (auto const& name: interfaceSymbols["methods"].getMemberNames())
out += contractIdentifiers["methods"][name].asString() + ": " + name + "\n"; out += interfaceSymbols["methods"][name].asString() + ": " + name + "\n";
if (contractIdentifiers.isMember("errors")) if (interfaceSymbols.isMember("errors"))
{ {
out += "\nError signatures:\n"; out += "\nError signatures:\n";
for (auto const& name: contractIdentifiers["errors"].getMemberNames()) for (auto const& name: interfaceSymbols["errors"].getMemberNames())
out += contractIdentifiers["errors"][name].asString() + ": " + name + "\n"; out += interfaceSymbols["errors"][name].asString() + ": " + name + "\n";
} }
if (contractIdentifiers.isMember("events")) if (interfaceSymbols.isMember("events"))
{ {
out += "\nEvent signatures:\n"; out += "\nEvent signatures:\n";
for (auto const& name: contractIdentifiers["events"].getMemberNames()) for (auto const& name: interfaceSymbols["events"].getMemberNames())
out += contractIdentifiers["events"][name].asString() + ": " + name + "\n"; out += interfaceSymbols["events"][name].asString() + ": " + name + "\n";
} }
if (!m_options.output.dir.empty()) if (!m_options.output.dir.empty())
@ -836,7 +836,7 @@ void CommandLineInterface::handleCombinedJSON()
m_compiler->runtimeObject(contractName).functionDebugData m_compiler->runtimeObject(contractName).functionDebugData
); );
if (m_options.compiler.combinedJsonRequests->signatureHashes) if (m_options.compiler.combinedJsonRequests->signatureHashes)
contractData[g_strSignatureHashes] = m_compiler->contractIdentifiers(contractName)["methods"]; contractData[g_strSignatureHashes] = m_compiler->interfaceSymbols(contractName)["methods"];
if (m_options.compiler.combinedJsonRequests->natspecDev) if (m_options.compiler.combinedJsonRequests->natspecDev)
contractData[g_strNatspecDev] = m_compiler->natspecDev(contractName); contractData[g_strNatspecDev] = m_compiler->natspecDev(contractName);
if (m_options.compiler.combinedJsonRequests->natspecUser) if (m_options.compiler.combinedJsonRequests->natspecUser)

View File

@ -10,6 +10,7 @@ Error signatures:
Event signatures: Event signatures:
2d4dd5fe18ada5a020a9f5591539a8dc3010a5c074ba6a70e1c956659f02786a: ev(uint256) 2d4dd5fe18ada5a020a9f5591539a8dc3010a5c074ba6a70e1c956659f02786a: ev(uint256)
81f3fb02f88d32d3bb08c80c9a622ca3b3223292f131c6ad049811f9a8a606dc: libraryEvent(uint256)
======= hashes/input.sol:L ======= ======= hashes/input.sol:L =======
Function signatures: Function signatures:

View File

@ -435,7 +435,7 @@ TestCase::TestResult SemanticTest::runTest(
{ {
soltestAssert( soltestAssert(
m_allowNonExistingFunctions || m_allowNonExistingFunctions ||
m_compiler.contractIdentifiers(m_compiler.lastContractName(m_sources.mainSourceFile))["methods"].isMember(test.call().signature), m_compiler.interfaceSymbols(m_compiler.lastContractName(m_sources.mainSourceFile))["methods"].isMember(test.call().signature),
"The function " + test.call().signature + " is not known to the compiler" "The function " + test.call().signature + " is not known to the compiler"
); );

View File

@ -58,7 +58,7 @@ optional<CompilerOutput> SolidityCompilationFramework::compileContract()
else else
contractName = m_compilerInput.contractName; contractName = m_compilerInput.contractName;
evmasm::LinkerObject obj = m_compiler.object(contractName); evmasm::LinkerObject obj = m_compiler.object(contractName);
Json::Value methodIdentifiers = m_compiler.contractIdentifiers(contractName)["methods"]; Json::Value methodIdentifiers = m_compiler.interfaceSymbols(contractName)["methods"];
return CompilerOutput{obj.bytecode, methodIdentifiers}; return CompilerOutput{obj.bytecode, methodIdentifiers};
} }
} }

View File

@ -91,7 +91,7 @@ public:
/// @returns method identifiers in contract called @param _contractName. /// @returns method identifiers in contract called @param _contractName.
Json::Value methodIdentifiers(std::string const& _contractName) Json::Value methodIdentifiers(std::string const& _contractName)
{ {
return m_compiler.contractIdentifiers(_contractName)["methods"]; return m_compiler.interfaceSymbols(_contractName)["methods"];
} }
/// @returns Compilation output comprising EVM bytecode and list of /// @returns Compilation output comprising EVM bytecode and list of
/// method identifiers in contract if compilation is successful, /// method identifiers in contract if compilation is successful,