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

View File

@ -98,6 +98,12 @@ public:
CompilationSuccessful CompilationSuccessful
}; };
enum class MetadataFormat {
WithReleaseVersionTag,
WithPrereleaseVersionTag,
NoMetadata
};
enum class MetadataHash { enum class MetadataHash {
IPFS, IPFS,
Bzzr1, Bzzr1,
@ -336,8 +342,10 @@ public:
/// @returns a JSON representing the estimated gas usage for contract creation, internal and external functions /// @returns a JSON representing the estimated gas usage for contract creation, internal and external functions
Json::Value gasEstimates(std::string const& _contractName) const; Json::Value gasEstimates(std::string const& _contractName) const;
/// Overwrites the release/prerelease flag. Should only be used for testing. /// Changes the format of the metadata appended at the end of the bytecode.
void overwriteReleaseFlag(bool release) { m_release = release; } /// 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: private:
/// The state per source unit. Filled gradually during parsing. /// The state per source unit. Filled gradually during parsing.
struct Source struct Source
@ -496,7 +504,7 @@ private:
/// Whether or not there has been an error during processing. /// Whether or not there has been an error during processing.
/// If this is true, the stack will refuse to generate code. /// If this is true, the stack will refuse to generate code.
bool m_hasError = false; 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); compileAndRun(sourceCode);
auto evmVersion = solidity::test::CommonOptions::get().evmVersion(); auto evmVersion = solidity::test::CommonOptions::get().evmVersion();
@ -101,7 +101,7 @@ BOOST_AUTO_TEST_CASE(string_storage)
if (CommonOptions::get().useABIEncoderV1) if (CommonOptions::get().useABIEncoderV1)
CHECK_DEPLOY_GAS(133045, 129731, evmVersion); CHECK_DEPLOY_GAS(133045, 129731, evmVersion);
else else
CHECK_DEPLOY_GAS(155553, 132103, evmVersion); CHECK_DEPLOY_GAS(144679, 121229, evmVersion);
} }
// This is only correct on >=Constantinople. // This is only correct on >=Constantinople.
else if (!CommonOptions::get().useABIEncoderV1) 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. // Costs with 0 are cases which cannot be triggered in tests.
if (evmVersion < EVMVersion::istanbul()) if (evmVersion < EVMVersion::istanbul())
CHECK_DEPLOY_GAS(0, 120189, evmVersion); CHECK_DEPLOY_GAS(0, 109241, evmVersion);
else else
CHECK_DEPLOY_GAS(0, 108541, evmVersion); CHECK_DEPLOY_GAS(0, 97697, evmVersion);
} }
else else
{ {
if (evmVersion < EVMVersion::istanbul()) if (evmVersion < EVMVersion::istanbul())
CHECK_DEPLOY_GAS(149567, 123969, evmVersion); CHECK_DEPLOY_GAS(138693, 123969, evmVersion);
else else
CHECK_DEPLOY_GAS(134123, 110969, evmVersion); CHECK_DEPLOY_GAS(123301, 110969, evmVersion);
} }
} }
else if (evmVersion < EVMVersion::istanbul()) else if (evmVersion < EVMVersion::istanbul())
CHECK_DEPLOY_GAS(125829, 118559, evmVersion); CHECK_DEPLOY_GAS(125829, 118559, evmVersion);
else else
CHECK_DEPLOY_GAS(114077, 107067, evmVersion); CHECK_DEPLOY_GAS(114077, 96461, evmVersion);
if (evmVersion >= EVMVersion::byzantium()) 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. // 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 // This leads to volatile creation cost estimates. Therefore we force the compiler to
// release mode for testing gas estimates. // release mode for testing gas estimates.
compiler().overwriteReleaseFlag(true); compiler().setMetadataFormat(CompilerStack::MetadataFormat::NoMetadata);
OptimiserSettings settings = m_optimise ? OptimiserSettings::standard() : OptimiserSettings::minimal(); OptimiserSettings settings = m_optimise ? OptimiserSettings::standard() : OptimiserSettings::minimal();
if (m_optimiseYul) if (m_optimiseYul)
{ {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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