Merge pull request #11026 from ethereum/resolve-keccak

Evaluate ``keccak256(a, const)``, when the value at memory location ``a`` is known at compile time and ``const <= 32``
This commit is contained in:
Harikrishnan Mulackal
2021-04-22 19:18:19 +02:00
committed by GitHub
115 changed files with 610 additions and 136 deletions
+10 -2
View File
@@ -317,7 +317,14 @@ YulOptimizerTestCommon::YulOptimizerTestCommon(
}},
{"fullSuite", [&]() {
GasMeter meter(dynamic_cast<EVMDialect const&>(*m_dialect), false, 200);
OptimiserSuite::run(*m_dialect, &meter, *m_object, true, solidity::frontend::OptimiserSettings::DefaultYulOptimiserSteps);
OptimiserSuite::run(
*m_dialect,
&meter,
*m_object,
true,
frontend::OptimiserSettings::DefaultYulOptimiserSteps,
frontend::OptimiserSettings::standard().expectedExecutionsPerDeployment
);
}},
{"stackLimitEvader", [&]() {
disambiguate();
@@ -434,6 +441,7 @@ void YulOptimizerTestCommon::updateContext()
m_context = make_unique<OptimiserStepContext>(OptimiserStepContext{
*m_dialect,
*m_nameDispenser,
m_reservedIdentifiers
m_reservedIdentifiers,
frontend::OptimiserSettings::standard().expectedExecutionsPerDeployment
});
}
@@ -0,0 +1,46 @@
// The yul code for the following contract
// contract C {
// uint256[] x;
// function f() public { x[10] = 5; }
// }
{
let _1 := 0
if eq(0x26121ff0, shr(224, calldataload(_1)))
{
if callvalue() { revert(_1, _1) }
if slt(add(calldatasize(), not(3)), _1) { revert(_1, _1) }
if iszero(lt(0x0a, sload(_1)))
{
mstore(_1, shl(224, 0x4e487b71))
mstore(4, 0x32)
revert(_1, 0x24)
}
mstore(_1, _1)
// The hash should be evaluated here
sstore(add(keccak256(_1, 0x20), 0x0a), 0x05)
}
}
// ====
// EVMVersion: >=constantinople
// ----
// step: fullSuite
//
// {
// {
// let _1 := 0
// if eq(0x26121ff0, shr(224, calldataload(_1)))
// {
// if callvalue() { revert(_1, _1) }
// if slt(add(calldatasize(), not(3)), _1) { revert(_1, _1) }
// if iszero(lt(0x0a, sload(_1)))
// {
// mstore(_1, shl(224, 0x4e487b71))
// mstore(4, 0x32)
// revert(_1, 0x24)
// }
// mstore(_1, _1)
// sstore(0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56d, 0x05)
// }
// }
// }
@@ -0,0 +1,16 @@
{
mstore(0, 10)
/// >>> int.from_bytes(web3.Web3.keccak(int.to_bytes(10, 32, byteorder='big')), byteorder='big')
/// 89717814153306320011181716697424560163256864414616650038987186496166826726056
let val := keccak256(0, 32)
sstore(0, val)
}
// ----
// step: loadResolver
//
// {
// let _1 := 10
// let _2 := 0
// mstore(_2, _1)
// sstore(_2, 89717814153306320011181716697424560163256864414616650038987186496166826726056)
// }
@@ -0,0 +1,18 @@
{
mstore(0, 30)
if calldataload(0) {
mstore(0, 20)
}
let val := keccak256(0, 32)
sstore(0, val)
}
// ----
// step: loadResolver
//
// {
// let _1 := 30
// let _2 := 0
// mstore(_2, _1)
// if calldataload(_2) { mstore(_2, 20) }
// sstore(_2, keccak256(_2, 32))
// }
@@ -0,0 +1,16 @@
{
mstore(100, 10)
mstore(132, 5)
// Won't be evaluated, even though the value is known
let val := keccak256(10, 33)
sstore(0, val)
}
// ----
// step: loadResolver
//
// {
// let _1 := 10
// mstore(100, _1)
// mstore(132, 5)
// sstore(0, keccak256(_1, 33))
// }
@@ -0,0 +1,31 @@
// import web3
// >>> asBytes = int(10).to_bytes(32, byteorder='big')
// >>> int.from_bytes(web3.Web3.keccak(asBytes[:31]), byteorder='big')
// 9948786400348073077032572701554570401043517428989726124163377057770909578447
// >>> int.from_bytes(web3.Web3.keccak(asBytes[:30]), byteorder='big')
// 110945455955148346822663466543669633859020391897956790847617069135813044810108
// >>> int.from_bytes(web3.Web3.keccak(asBytes[:1]), byteorder='big')
// 85131057757245807317576516368191972321038229705283732634690444270750521936266
// >>> int.from_bytes(web3.Web3.keccak(b''), byteorder='big')
// 89477152217924674838424037953991966239322087453347756267410168184682657981552
{
mstore(0, 10)
sstore(0, keccak256(0, 31))
sstore(1, keccak256(0, 30))
sstore(2, keccak256(0, 1))
sstore(2, keccak256(0, 0))
}
// ----
// step: loadResolver
//
// {
// let _1 := 10
// let _2 := 0
// mstore(_2, _1)
// sstore(_2, 9948786400348073077032572701554570401043517428989726124163377057770909578447)
// sstore(1, 110945455955148346822663466543669633859020391897956790847617069135813044810108)
// let _13 := 85131057757245807317576516368191972321038229705283732634690444270750521936266
// let _14 := 2
// sstore(_14, _13)
// sstore(_14, 89477152217924674838424037953991966239322087453347756267410168184682657981552)
// }
@@ -0,0 +1,22 @@
{
let converted := 14
let _1 := 50
mstore(_1, "abcdefghijklmn")
// >>> int.from_bytes(web3.Web3.keccak(text="abcdefghijklmn"), byteorder='big')
// 51246744213555520563123611275127692828770413530219146609532820042079541949502
sstore(0, keccak256(_1, converted))
sstore(0, add(mload(_1), 1))
}
// ----
// step: loadResolver
//
// {
// let _1 := 50
// let _2 := "abcdefghijklmn"
// mstore(_1, _2)
// let _3 := 51246744213555520563123611275127692828770413530219146609532820042079541949502
// let _4 := 0
// sstore(_4, _3)
// sstore(_4, add(_2, 1))
// }
@@ -0,0 +1,22 @@
// Test where the location of the memory offset is not known at compile time
// >>> import web3
// >>> asBytes = int(500).to_bytes(32, byteorder='big')
// >>> int.from_bytes(web3.Web3.keccak(asBytes), byteorder='big')
// 92647596584187651892918913434663110448935397770592030057655219009846081465370
// >>> int.from_bytes(web3.Web3.keccak(asBytes[:16]), byteorder='big')
// 110620294328144418057589324861608220015688365608948720310623173341503153578932
{
let offset := calldataload(0)
mstore(offset, 500)
sstore(0, keccak256(offset, 32))
sstore(1, keccak256(offset, 16))
}
// ----
// step: loadResolver
//
// {
// let _1 := 0
// mstore(calldataload(_1), 500)
// sstore(_1, 92647596584187651892918913434663110448935397770592030057655219009846081465370)
// sstore(1, 110620294328144418057589324861608220015688365608948720310623173341503153578932)
// }
@@ -0,0 +1,19 @@
{
sstore(0, msize())
mstore(0, 10)
// Keccak-256 should not be evaluated because of the msize.
// Even though, though the code is likely equivalent,
// we skip steps if `msize` is present
let val := keccak256(0, 32)
sstore(1, val)
}
// ----
// step: loadResolver
//
// {
// let _1 := msize()
// let _2 := 0
// sstore(_2, _1)
// mstore(_2, 10)
// sstore(1, keccak256(_2, 32))
// }