Merge pull request #10951 from ethereum/metadataFormatFlag

Metadata format flag
This commit is contained in:
Đorđe Mijović 2021-02-12 11:26:54 +01:00 committed by GitHub
commit b385b41fa0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 120 additions and 74 deletions

View File

@ -1580,6 +1580,9 @@ private:
bytes CompilerStack::createCBORMetadata(Contract const& _contract) const
{
if (m_metadataFormat == MetadataFormat::NoMetadata)
return bytes{};
bool const experimentalMode = !onlySafeExperimentalFeaturesActivated(
_contract.contract->sourceUnit().annotation().experimentalFeatures
);
@ -1597,10 +1600,16 @@ bytes CompilerStack::createCBORMetadata(Contract const& _contract) const
if (experimentalMode || m_viaIR)
encoder.pushBool("experimental", true);
if (m_release)
if (m_metadataFormat == MetadataFormat::WithReleaseVersionTag)
encoder.pushBytes("solc", VersionCompactBytes);
else
{
solAssert(
m_metadataFormat == MetadataFormat::WithPrereleaseVersionTag,
"Invalid metadata format."
);
encoder.pushString("solc", VersionStringStrict);
}
return encoder.serialise();
}

View File

@ -98,6 +98,12 @@ public:
CompilationSuccessful
};
enum class MetadataFormat {
WithReleaseVersionTag,
WithPrereleaseVersionTag,
NoMetadata
};
enum class MetadataHash {
IPFS,
Bzzr1,
@ -336,8 +342,10 @@ public:
/// @returns a JSON representing the estimated gas usage for contract creation, internal and external functions
Json::Value gasEstimates(std::string const& _contractName) const;
/// Overwrites the release/prerelease flag. Should only be used for testing.
void overwriteReleaseFlag(bool release) { m_release = release; }
/// Changes the format of the metadata appended at the end of the bytecode.
/// This is mostly a workaround to avoid bytecode and gas differences between compiler builds
/// caused by differences in metadata. Should only be used for testing.
void setMetadataFormat(MetadataFormat _metadataFormat) { m_metadataFormat = _metadataFormat; }
private:
/// The state per source unit. Filled gradually during parsing.
struct Source
@ -496,7 +504,7 @@ private:
/// Whether or not there has been an error during processing.
/// If this is true, the stack will refuse to generate code.
bool m_hasError = false;
bool m_release = VersionIsRelease;
MetadataFormat m_metadataFormat = VersionIsRelease ? MetadataFormat::WithReleaseVersionTag : MetadataFormat::WithPrereleaseVersionTag;
};
}

View File

@ -91,7 +91,7 @@ BOOST_AUTO_TEST_CASE(string_storage)
}
}
)";
m_compiler.overwriteReleaseFlag(true);
m_compiler.setMetadataFormat(CompilerStack::MetadataFormat::NoMetadata);
compileAndRun(sourceCode);
auto evmVersion = solidity::test::CommonOptions::get().evmVersion();
@ -101,7 +101,7 @@ BOOST_AUTO_TEST_CASE(string_storage)
if (CommonOptions::get().useABIEncoderV1)
CHECK_DEPLOY_GAS(133045, 129731, evmVersion);
else
CHECK_DEPLOY_GAS(155553, 132103, evmVersion);
CHECK_DEPLOY_GAS(144679, 121229, evmVersion);
}
// This is only correct on >=Constantinople.
else if (!CommonOptions::get().useABIEncoderV1)
@ -110,22 +110,22 @@ BOOST_AUTO_TEST_CASE(string_storage)
{
// Costs with 0 are cases which cannot be triggered in tests.
if (evmVersion < EVMVersion::istanbul())
CHECK_DEPLOY_GAS(0, 120189, evmVersion);
CHECK_DEPLOY_GAS(0, 109241, evmVersion);
else
CHECK_DEPLOY_GAS(0, 108541, evmVersion);
CHECK_DEPLOY_GAS(0, 97697, evmVersion);
}
else
{
if (evmVersion < EVMVersion::istanbul())
CHECK_DEPLOY_GAS(149567, 123969, evmVersion);
CHECK_DEPLOY_GAS(138693, 123969, evmVersion);
else
CHECK_DEPLOY_GAS(134123, 110969, evmVersion);
CHECK_DEPLOY_GAS(123301, 110969, evmVersion);
}
}
else if (evmVersion < EVMVersion::istanbul())
CHECK_DEPLOY_GAS(125829, 118559, evmVersion);
else
CHECK_DEPLOY_GAS(114077, 107067, evmVersion);
CHECK_DEPLOY_GAS(114077, 96461, evmVersion);
if (evmVersion >= EVMVersion::byzantium())
{

View File

@ -106,7 +106,7 @@ TestCase::TestResult GasTest::run(ostream& _stream, string const& _linePrefix, b
// Prerelease CBOR metadata varies in size due to changing version numbers and build dates.
// This leads to volatile creation cost estimates. Therefore we force the compiler to
// release mode for testing gas estimates.
compiler().overwriteReleaseFlag(true);
compiler().setMetadataFormat(CompilerStack::MetadataFormat::NoMetadata);
OptimiserSettings settings = m_optimise ? OptimiserSettings::standard() : OptimiserSettings::minimal();
if (m_optimiseYul)
{

View File

@ -37,14 +37,19 @@ namespace solidity::frontend::test
namespace
{
map<string, string> requireParsedCBORMetadata(bytes const& _bytecode)
map<string, string> requireParsedCBORMetadata(bytes const& _bytecode, CompilerStack::MetadataFormat _metadataFormat)
{
bytes cborMetadata = solidity::test::onlyMetadata(_bytecode);
if (_metadataFormat != CompilerStack::MetadataFormat::NoMetadata)
{
BOOST_REQUIRE(!cborMetadata.empty());
std::optional<map<string, string>> tmp = solidity::test::parseCBORMetadata(cborMetadata);
BOOST_REQUIRE(tmp);
return *tmp;
}
BOOST_REQUIRE(cborMetadata.empty());
return {};
}
optional<string> compileAndCheckLicenseMetadata(string const& _contractName, char const* _sourceCode)
{
@ -83,7 +88,11 @@ BOOST_AUTO_TEST_CASE(metadata_stamp)
function g(function(uint) external returns (uint) x) public {}
}
)";
for (auto release: std::set<bool>{true, VersionIsRelease})
for (auto metadataFormat: std::set<CompilerStack::MetadataFormat>{
CompilerStack::MetadataFormat::NoMetadata,
CompilerStack::MetadataFormat::WithReleaseVersionTag,
CompilerStack::MetadataFormat::WithPrereleaseVersionTag
})
for (auto metadataHash: set<CompilerStack::MetadataHash>{
CompilerStack::MetadataHash::IPFS,
CompilerStack::MetadataHash::Bzzr1,
@ -91,7 +100,7 @@ BOOST_AUTO_TEST_CASE(metadata_stamp)
})
{
CompilerStack compilerStack;
compilerStack.overwriteReleaseFlag(release);
compilerStack.setMetadataFormat(metadataFormat);
compilerStack.setSources({{"", std::string(sourceCode)}});
compilerStack.setEVMVersion(solidity::test::CommonOptions::get().evmVersion());
compilerStack.setOptimiserSettings(solidity::test::CommonOptions::get().optimize);
@ -101,9 +110,9 @@ BOOST_AUTO_TEST_CASE(metadata_stamp)
std::string const& metadata = compilerStack.metadata("test");
BOOST_CHECK(solidity::test::isValidMetadata(metadata));
auto const cborMetadata = requireParsedCBORMetadata(bytecode);
auto const cborMetadata = requireParsedCBORMetadata(bytecode, metadataFormat);
if (metadataHash == CompilerStack::MetadataHash::None)
BOOST_CHECK(cborMetadata.size() == 1);
BOOST_CHECK(cborMetadata.size() == (metadataFormat == CompilerStack::MetadataFormat::NoMetadata ? 0 : 1));
else
{
bytes hash;
@ -121,18 +130,26 @@ BOOST_AUTO_TEST_CASE(metadata_stamp)
hashMethod = "bzzr1";
}
if (metadataFormat != CompilerStack::MetadataFormat::NoMetadata)
{
BOOST_CHECK(cborMetadata.size() == 2);
BOOST_CHECK(cborMetadata.count(hashMethod) == 1);
BOOST_CHECK(cborMetadata.at(hashMethod) == util::toHex(hash));
}
}
if (metadataFormat == CompilerStack::MetadataFormat::NoMetadata)
BOOST_CHECK(cborMetadata.count("solc") == 0);
else
{
BOOST_CHECK(cborMetadata.count("solc") == 1);
if (release)
if (metadataFormat == CompilerStack::MetadataFormat::WithReleaseVersionTag)
BOOST_CHECK(cborMetadata.at("solc") == util::toHex(VersionCompactBytes));
else
BOOST_CHECK(cborMetadata.at("solc") == VersionStringStrict);
}
}
}
BOOST_AUTO_TEST_CASE(metadata_stamp_experimental)
{
@ -144,7 +161,11 @@ BOOST_AUTO_TEST_CASE(metadata_stamp_experimental)
function g(function(uint) external returns (uint) x) public {}
}
)";
for (auto release: set<bool>{true, VersionIsRelease})
for (auto metadataFormat: std::set<CompilerStack::MetadataFormat>{
CompilerStack::MetadataFormat::NoMetadata,
CompilerStack::MetadataFormat::WithReleaseVersionTag,
CompilerStack::MetadataFormat::WithPrereleaseVersionTag
})
for (auto metadataHash: set<CompilerStack::MetadataHash>{
CompilerStack::MetadataHash::IPFS,
CompilerStack::MetadataHash::Bzzr1,
@ -152,7 +173,7 @@ BOOST_AUTO_TEST_CASE(metadata_stamp_experimental)
})
{
CompilerStack compilerStack;
compilerStack.overwriteReleaseFlag(release);
compilerStack.setMetadataFormat(metadataFormat);
compilerStack.setSources({{"", std::string(sourceCode)}});
compilerStack.setEVMVersion(solidity::test::CommonOptions::get().evmVersion());
compilerStack.setOptimiserSettings(solidity::test::CommonOptions::get().optimize);
@ -162,9 +183,9 @@ BOOST_AUTO_TEST_CASE(metadata_stamp_experimental)
std::string const& metadata = compilerStack.metadata("test");
BOOST_CHECK(solidity::test::isValidMetadata(metadata));
auto const cborMetadata = requireParsedCBORMetadata(bytecode);
auto const cborMetadata = requireParsedCBORMetadata(bytecode, metadataFormat);
if (metadataHash == CompilerStack::MetadataHash::None)
BOOST_CHECK(cborMetadata.size() == 2);
BOOST_CHECK(cborMetadata.size() == (metadataFormat == CompilerStack::MetadataFormat::NoMetadata ? 0 : 2));
else
{
bytes hash;
@ -182,13 +203,20 @@ BOOST_AUTO_TEST_CASE(metadata_stamp_experimental)
hashMethod = "bzzr1";
}
if (metadataFormat != CompilerStack::MetadataFormat::NoMetadata)
{
BOOST_CHECK(cborMetadata.size() == 3);
BOOST_CHECK(cborMetadata.count(hashMethod) == 1);
BOOST_CHECK(cborMetadata.at(hashMethod) == util::toHex(hash));
}
}
if (metadataFormat == CompilerStack::MetadataFormat::NoMetadata)
BOOST_CHECK(cborMetadata.count("solc") == 0);
else
{
BOOST_CHECK(cborMetadata.count("solc") == 1);
if (release)
if (metadataFormat == CompilerStack::MetadataFormat::WithReleaseVersionTag)
BOOST_CHECK(cborMetadata.at("solc") == util::toHex(VersionCompactBytes));
else
BOOST_CHECK(cborMetadata.at("solc") == VersionStringStrict);
@ -196,6 +224,7 @@ BOOST_AUTO_TEST_CASE(metadata_stamp_experimental)
BOOST_CHECK(cborMetadata.at("experimental") == "true");
}
}
}
BOOST_AUTO_TEST_CASE(metadata_relevant_sources)
{

View File

@ -14,9 +14,9 @@ contract C {
}
// ----
// creation:
// codeDepositCost: 1181400
// executionCost: 1227
// totalCost: 1182627
// codeDepositCost: 1170600
// executionCost: 1214
// totalCost: 1171814
// external:
// a(): 1130
// b(uint256): infinite

View File

@ -17,9 +17,9 @@ contract C {
// optimize-yul: true
// ----
// creation:
// codeDepositCost: 583400
// executionCost: 619
// totalCost: 584019
// codeDepositCost: 572600
// executionCost: 606
// totalCost: 573206
// external:
// a(): 985
// b(uint256): 2052

View File

@ -13,8 +13,8 @@ contract C {
}
// ----
// creation:
// codeDepositCost: 398400
// executionCost: 436
// totalCost: 398836
// codeDepositCost: 387600
// executionCost: 424
// totalCost: 388024
// external:
// f(): 428

View File

@ -24,9 +24,9 @@ contract Large {
}
// ----
// creation:
// codeDepositCost: 913400
// executionCost: 948
// totalCost: 914348
// codeDepositCost: 902600
// executionCost: 942
// totalCost: 903542
// external:
// a(): 1175
// b(uint256): infinite

View File

@ -27,9 +27,9 @@ contract Large {
// optimize-runs: 2
// ----
// creation:
// codeDepositCost: 267000
// executionCost: 306
// totalCost: 267306
// codeDepositCost: 256200
// executionCost: 300
// totalCost: 256500
// external:
// a(): 983
// b(uint256): 2337

View File

@ -11,9 +11,9 @@ contract Medium {
}
// ----
// creation:
// codeDepositCost: 360400
// executionCost: 399
// totalCost: 360799
// codeDepositCost: 349600
// executionCost: 386
// totalCost: 349986
// external:
// a(): 1152
// b(uint256): infinite

View File

@ -14,9 +14,9 @@ contract Medium {
// optimize-runs: 2
// ----
// creation:
// codeDepositCost: 157400
// executionCost: 202
// totalCost: 157602
// codeDepositCost: 146600
// executionCost: 190
// totalCost: 146790
// external:
// a(): 983
// b(uint256): 2095

View File

@ -6,9 +6,9 @@ contract Small {
}
// ----
// creation:
// codeDepositCost: 123600
// executionCost: 171
// totalCost: 123771
// codeDepositCost: 112800
// executionCost: 159
// totalCost: 112959
// external:
// fallback: 129
// a(): 1107

View File

@ -9,9 +9,9 @@ contract Small {
// optimize-runs: 2
// ----
// creation:
// codeDepositCost: 72600
// executionCost: 123
// totalCost: 72723
// codeDepositCost: 61800
// executionCost: 111
// totalCost: 61911
// external:
// fallback: 118
// a(): 961

View File

@ -19,9 +19,9 @@ contract C {
// optimize-yul: false
// ----
// creation:
// codeDepositCost: 119800
// executionCost: 165
// totalCost: 119965
// codeDepositCost: 109000
// executionCost: 159
// totalCost: 109159
// external:
// exp_neg_one(uint256): 2259
// exp_one(uint256): infinite

View File

@ -19,9 +19,9 @@ contract C {
// optimize-yul: true
// ----
// creation:
// codeDepositCost: 47800
// executionCost: 99
// totalCost: 47899
// codeDepositCost: 37000
// executionCost: 87
// totalCost: 37087
// external:
// exp_neg_one(uint256): 1917
// exp_one(uint256): 1870