Skip to content

Improve ethdebug resources output #16043

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: ethdebug_test_schema
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 0 additions & 19 deletions libevmasm/Ethdebug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,22 +148,3 @@ Json ethdebug::program(std::string_view _name, unsigned _sourceID, Assembly cons
.instructions = programInstructions(_assembly, _linkerObject, _sourceID)
};
}

Json ethdebug::resources(std::vector<std::string> const& _sources, std::string const& _version)
{
Json sources = Json::array();
for (size_t id = 0; id < _sources.size(); ++id)
{
Json source = Json::object();
source["id"] = id;
source["path"] = _sources[id];
sources.push_back(source);
}
Json result = Json::object();
result["compilation"] = Json::object();
result["compilation"]["compiler"] = Json::object();
result["compilation"]["compiler"]["name"] = "solc";
result["compilation"]["compiler"]["version"] = _version;
result["compilation"]["sources"] = sources;
return result;
}
3 changes: 0 additions & 3 deletions libevmasm/Ethdebug.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,4 @@ namespace solidity::evmasm::ethdebug
// returns ethdebug/format/program.
Json program(std::string_view _name, unsigned _sourceID, Assembly const& _assembly, LinkerObject const& _linkerObject);

// returns ethdebug/format/info/resources
Json resources(std::vector<std::string> const& _sources, std::string const& _version);

} // namespace solidity::evmasm::ethdebug
24 changes: 24 additions & 0 deletions libevmasm/EthdebugSchema.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,23 @@ void schema::materials::to_json(Json& _json, SourceRange::Range const& _range)
_json["offset"] = _range.offset;
}

void schema::materials::to_json(Json& _json, Source const& _source)
{
_json["id"] = _source.id;
_json["path"] = _source.path;
_json["contents"] = _source.contents;
if (_source.encoding)
_json["encoding"] = *_source.encoding;
_json["language"] = _source.language;
}

void schema::materials::to_json(Json& _json, Compilation const& _compilation)
{
_json["id"] = _compilation.id;
_json["compiler"]["name"] = _compilation.compiler.name;
_json["compiler"]["version"] = _compilation.compiler.version;
_json["sources"] = _compilation.sources;
}

void schema::materials::to_json(Json& _json, SourceRange const& _sourceRange)
{
Expand All @@ -73,6 +90,13 @@ void schema::to_json(Json& _json, Program::Contract const& _contract)
_json["definition"] = _contract.definition;
}

void schema::info::to_json(Json& _json, Resources const& _resources)
{
if (_resources.compilation)
_json["compilation"] = *_resources.compilation;
}


void schema::program::to_json(Json& _json, Context::Variable const& _contextVariable)
{
auto const numProperties =
Expand Down
36 changes: 36 additions & 0 deletions libevmasm/EthdebugSchema.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,35 @@ struct SourceRange
std::optional<Range> range;
};

struct Source
{
ID id;
std::string path;
std::string contents;
std::optional<std::string> encoding;
std::string language;
};

struct Compilation
{
struct Compiler
{
std::string name;
std::string version;
};
ID id;
Compiler compiler;
std::vector<Source> sources;
};

}

namespace info
{
struct Resources
{
std::optional<materials::Compilation> compilation;
};
}

namespace program
Expand Down Expand Up @@ -155,6 +184,13 @@ void to_json(Json& _json, ID const& _id);
void to_json(Json& _json, Reference const& _source);
void to_json(Json& _json, SourceRange::Range const& _range);
void to_json(Json& _json, SourceRange const& _sourceRange);
void to_json(Json& _json, Source const& _source);
void to_json(Json& _json, Compilation const& _compilation);
}

namespace info
{
void to_json(Json& _json, Resources const& _resources);
}

namespace program
Expand Down
44 changes: 42 additions & 2 deletions libsolidity/interface/CompilerStack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
#include <libsolutil/FunctionSelector.h>

#include <libevmasm/Ethdebug.h>
#include <libevmasm/EthdebugSchema.h>

#include <boost/algorithm/string/replace.hpp>

Expand Down Expand Up @@ -1196,7 +1197,38 @@ Json CompilerStack::ethdebug() const
{
solAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful.");
solAssert(!m_contracts.empty());
return evmasm::ethdebug::resources(sourceNames(), VersionString);

std::vector<std::string> const paths = sourceNames();

std::vector<evmasm::ethdebug::schema::materials::Source> sources;
sources.reserve(paths.size());

for (auto const& sourcePath: paths)
sources.push_back(
evmasm::ethdebug::schema::materials::Source{
.id = {sourceIndices()[sourcePath]},
.path = sourcePath,
.contents = source(sourcePath).charStream->source(),
.encoding = std::nullopt,
.language = "Solidity"
}
);

std::stringstream concatenatedMetadata;
for (auto const& contract: m_contracts | ranges::views::values)
concatenatedMetadata << metadata(contract);
evmasm::ethdebug::schema::info::Resources resources {
.compilation = evmasm::ethdebug::schema::materials::Compilation {
.id = {util::toHex(util::ipfsHash(concatenatedMetadata.str()), util::HexPrefix::Add)},
.compiler = evmasm::ethdebug::schema::materials::Compilation::Compiler {
.name = "solc",
.version = VersionString
},
.sources = sources
}
};

return resources;
}

Json CompilerStack::ethdebug(std::string const& _contractName) const
Expand Down Expand Up @@ -1931,7 +1963,15 @@ bytes CompilerStack::createCBORMetadata(Contract const& _contract, bool _forIR)
_contract.contract->sourceUnit().annotation().experimentalFeatures
);

std::string meta = (_forIR == m_viaIR ? metadata(_contract) : createMetadata(_contract, _forIR));
std::string otherMeta;
std::string_view meta;
if (_forIR == m_viaIR)
meta = metadata(_contract);
else
{
otherMeta = createMetadata(_contract, _forIR);
meta = otherMeta;
}

MetadataCBOREncoder encoder;

Expand Down
30 changes: 26 additions & 4 deletions libsolidity/interface/StandardCompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,15 @@

#include <liblangutil/SourceReferenceFormatter.h>

#include <libsolutil/CommonData.h>
#include <libsolutil/IpfsHash.h>
#include <libsolutil/JSON.h>
#include <libsolutil/Keccak256.h>
#include <libsolutil/CommonData.h>

#include <boost/algorithm/string/predicate.hpp>

#include <algorithm>
#include <libevmasm/EthdebugSchema.h>
#include <optional>

using namespace solidity;
Expand Down Expand Up @@ -1637,7 +1639,7 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu
}


Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings, Json const& _rawInput)
{
solAssert(_inputsAndSettings.jsonSources.empty());

Expand Down Expand Up @@ -1787,7 +1789,27 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
output["contracts"][sourceName][contractName]["yulCFGJson"] = stack.cfgJson();

if (isEthdebugRequested(_inputsAndSettings.outputSelection))
output["ethdebug"] = evmasm::ethdebug::resources({sourceName}, VersionString);
{
std::string const id = util::toHex(ipfsHash(jsonCompactPrint(jsonCompactPrint(_rawInput) + jsonCompactPrint(_inputsAndSettings.sources))), HexPrefix::Add);
output["ethdebug"] = evmasm::ethdebug::schema::info::Resources {
.compilation = evmasm::ethdebug::schema::materials::Compilation {
.id = {id},
.compiler = evmasm::ethdebug::schema::materials::Compilation::Compiler{
.name = "solc",
.version = VersionString
},
.sources = {
evmasm::ethdebug::schema::materials::Source {
.id = evmasm::ethdebug::schema::materials::ID{std::uint64_t{0}},
.path = sourceName,
.contents = sourceContents,
.encoding = std::nullopt,
.language = "Yul"
}
}
}
};
}

return output;
}
Expand All @@ -1805,7 +1827,7 @@ Json StandardCompiler::compile(Json const& _input) noexcept
if (settings.language == "Solidity")
return compileSolidity(std::move(settings));
else if (settings.language == "Yul")
return compileYul(std::move(settings));
return compileYul(std::move(settings), _input);
else if (settings.language == "SolidityAST")
return compileSolidity(std::move(settings));
else if (settings.language == "EVMAssembly")
Expand Down
2 changes: 1 addition & 1 deletion libsolidity/interface/StandardCompiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ class StandardCompiler
std::map<std::string, Json> parseAstFromInput(StringMap const& _sources);
Json importEVMAssembly(InputsAndSettings _inputsAndSettings);
Json compileSolidity(InputsAndSettings _inputsAndSettings);
Json compileYul(InputsAndSettings _inputsAndSettings);
Json compileYul(InputsAndSettings _inputsAndSettings, Json const& _rawInput);

ReadCallback::Callback m_readFile;

Expand Down
4 changes: 2 additions & 2 deletions libsolutil/IpfsHash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ bytes groupChunksBottomUp(Chunks _currentLevel)
}
}

bytes solidity::util::ipfsHash(std::string _data)
bytes solidity::util::ipfsHash(std::string_view _data)
{
size_t const maxChunkSize = 1024 * 256;
size_t chunkCount = _data.length() / maxChunkSize + (_data.length() % maxChunkSize > 0 ? 1 : 0);
Expand Down Expand Up @@ -196,7 +196,7 @@ bytes solidity::util::ipfsHash(std::string _data)
return groupChunksBottomUp(std::move(allChunks));
}

std::string solidity::util::ipfsHashBase58(std::string _data)
std::string solidity::util::ipfsHashBase58(std::string_view _data)
{
return base58Encode(ipfsHash(std::move(_data)));
}
5 changes: 3 additions & 2 deletions libsolutil/IpfsHash.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <libsolutil/Common.h>

#include <string>
#include <string_view>

namespace solidity::util
{
Expand All @@ -30,9 +31,9 @@ namespace solidity::util
/// As hash function it will use sha2-256.
/// The effect is that the hash should be identical to the one produced by
/// the command `ipfs add <filename>`.
bytes ipfsHash(std::string _data);
bytes ipfsHash(std::string_view _data);

/// Compute the "ipfs hash" as above, but encoded in base58 as used by ipfs / bitcoin.
std::string ipfsHashBase58(std::string _data);
std::string ipfsHashBase58(std::string_view _data);

}
2 changes: 1 addition & 1 deletion libsolutil/SwarmHash.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ h256 bzzr0Hash(std::string const& _input);
/// Compute the "bzz hash" of @a _input (the NEW binary / BMT version)
h256 bzzr1Hash(bytes const& _input);

inline h256 bzzr1Hash(std::string const& _input)
inline h256 bzzr1Hash(std::string_view const _input)
{
return bzzr1Hash(asBytes(_input));
}
Expand Down
22 changes: 20 additions & 2 deletions solc/CommandLineInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include <libyul/YulStack.h>

#include <libevmasm/Ethdebug.h>
#include <libevmasm/EthdebugSchema.h>
#include <libevmasm/Disassemble.h>

#include <liblangutil/Exceptions.h>
Expand Down Expand Up @@ -1359,8 +1360,25 @@ void CommandLineInterface::assembleYul(yul::YulStack::Language _language, yul::Y
{
sout() << "======= Debug Data (ethdebug/format/info/resources) =======" << std::endl;
sout() << util::jsonPrint(
evmasm::ethdebug::resources({{sourceUnitName}}, VersionString),
m_options.formatting.json
evmasm::ethdebug::schema::info::Resources{
.compilation = evmasm::ethdebug::schema::materials::Compilation {
.id = {""},
.compiler = evmasm::ethdebug::schema::materials::Compilation::Compiler {
.name = "solc",
.version = VersionString
},
.sources = {
evmasm::ethdebug::schema::materials::Source {
.id = evmasm::ethdebug::schema::materials::ID{std::uint64_t{0}},
.path = sourceUnitName,
.contents = yulSource,
.encoding = std::nullopt,
.language = "Yul"
}
}
}
},
m_options.formatting.json
) << std::endl;
}

Expand Down
3 changes: 3 additions & 0 deletions test/cmdlineTests/ethdebug_eof_container_osaka/output
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@
"name": "solc",
"version": "<VERSION REMOVED>"
},
"id": "0x1220a5451e57fefae301cb773787fc38d855d065067f1d80a2cf38ea4e8117f914f8",
"sources": [
{
"contents": "// SPDX-License-Identifier: GPL-2.0\npragma solidity >=0.0;\n\ncontract C {\n function f() public {}\n}\n",
"id": 0,
"language": "Solidity",
"path": "input.sol"
}
]
Expand Down
3 changes: 3 additions & 0 deletions test/cmdlineTests/ethdebug_on_abstract/output
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@
"name": "solc",
"version": "<VERSION REMOVED>"
},
"id": "0x1220f18bade7c9fe1910e3cfe817d60dd1d42d85760d009fe087c91aac1aced8ed66",
"sources": [
{
"contents": "// SPDX-License-Identifier: GPL-2.0\npragma solidity >=0.0;\n\nabstract contract C {\n function f() public virtual returns (bytes32);\n}\n",
"id": 0,
"language": "Solidity",
"path": "input.sol"
}
]
Expand Down
3 changes: 3 additions & 0 deletions test/cmdlineTests/ethdebug_on_interface/output
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@
"name": "solc",
"version": "<VERSION REMOVED>"
},
"id": "0x1220e2276c1de81ce47e074f4113acf7edc8160f0ac86ce866411800df43be570a94",
"sources": [
{
"contents": "// SPDX-License-Identifier: GPL-2.0\npragma solidity >=0.0;\n\ninterface C {\n function f() external;\n}\n",
"id": 0,
"language": "Solidity",
"path": "input.sol"
}
]
Expand Down
Loading