mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #8841 from ethereum/sol_yul_ripemd160_ecrecover
[Sol - Yul] Add support for ripemd160 & ecrecover.
This commit is contained in:
commit
7ef114db9a
@ -952,14 +952,6 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
|||||||
"))\n";
|
"))\n";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FunctionType::Kind::ECRecover:
|
|
||||||
case FunctionType::Kind::SHA256:
|
|
||||||
case FunctionType::Kind::RIPEMD160:
|
|
||||||
{
|
|
||||||
solAssert(!_functionCall.annotation().tryCall, "");
|
|
||||||
appendExternalFunctionCall(_functionCall, arguments);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case FunctionType::Kind::ArrayPop:
|
case FunctionType::Kind::ArrayPop:
|
||||||
{
|
{
|
||||||
auto const& memberAccessExpression = dynamic_cast<MemberAccess const&>(_functionCall.expression()).expression();
|
auto const& memberAccessExpression = dynamic_cast<MemberAccess const&>(_functionCall.expression()).expression();
|
||||||
@ -1153,6 +1145,69 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case FunctionType::Kind::ECRecover:
|
||||||
|
case FunctionType::Kind::RIPEMD160:
|
||||||
|
case FunctionType::Kind::SHA256:
|
||||||
|
{
|
||||||
|
solAssert(!_functionCall.annotation().tryCall, "");
|
||||||
|
solAssert(!functionType->valueSet(), "");
|
||||||
|
solAssert(!functionType->gasSet(), "");
|
||||||
|
solAssert(!functionType->bound(), "");
|
||||||
|
|
||||||
|
static map<FunctionType::Kind, std::tuple<u160, size_t>> precompiles = {
|
||||||
|
{FunctionType::Kind::ECRecover, std::make_tuple(1, 0)},
|
||||||
|
{FunctionType::Kind::SHA256, std::make_tuple(2, 0)},
|
||||||
|
{FunctionType::Kind::RIPEMD160, std::make_tuple(3, 12)},
|
||||||
|
};
|
||||||
|
auto [ address, offset ] = precompiles[functionType->kind()];
|
||||||
|
TypePointers argumentTypes;
|
||||||
|
vector<string> argumentStrings;
|
||||||
|
for (auto const& arg: arguments)
|
||||||
|
{
|
||||||
|
argumentTypes.emplace_back(&type(*arg));
|
||||||
|
argumentStrings += IRVariable(*arg).stackSlots();
|
||||||
|
}
|
||||||
|
Whiskers templ(R"(
|
||||||
|
let <pos> := <allocateTemporary>()
|
||||||
|
let <end> := <encodeArgs>(<pos> <argumentString>)
|
||||||
|
<?isECRecover>
|
||||||
|
mstore(0, 0)
|
||||||
|
</isECRecover>
|
||||||
|
let <success> := <call>(<gas>, <address> <?isCall>, 0</isCall>, <pos>, sub(<end>, <pos>), 0, 32)
|
||||||
|
if iszero(<success>) { <forwardingRevert>() }
|
||||||
|
let <retVars> := <shl>(mload(0))
|
||||||
|
)");
|
||||||
|
templ("call", m_context.evmVersion().hasStaticCall() ? "staticcall" : "call");
|
||||||
|
templ("isCall", !m_context.evmVersion().hasStaticCall());
|
||||||
|
templ("shl", m_utils.shiftLeftFunction(offset * 8));
|
||||||
|
templ("allocateTemporary", m_utils.allocationTemporaryMemoryFunction());
|
||||||
|
templ("pos", m_context.newYulVariable());
|
||||||
|
templ("end", m_context.newYulVariable());
|
||||||
|
templ("isECRecover", FunctionType::Kind::ECRecover == functionType->kind());
|
||||||
|
if (FunctionType::Kind::ECRecover == functionType->kind())
|
||||||
|
templ("encodeArgs", m_context.abiFunctions().tupleEncoder(argumentTypes, parameterTypes));
|
||||||
|
else
|
||||||
|
templ("encodeArgs", m_context.abiFunctions().tupleEncoderPacked(argumentTypes, parameterTypes));
|
||||||
|
templ("argumentString", joinHumanReadablePrefixed(argumentStrings));
|
||||||
|
templ("address", toString(address));
|
||||||
|
templ("success", m_context.newYulVariable());
|
||||||
|
templ("retVars", IRVariable(_functionCall).commaSeparatedList());
|
||||||
|
templ("forwardingRevert", m_utils.forwardingRevertFunction());
|
||||||
|
if (m_context.evmVersion().canOverchargeGasForCall())
|
||||||
|
// Send all gas (requires tangerine whistle EVM)
|
||||||
|
templ("gas", "gas()");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// @todo The value 10 is not exact and this could be fine-tuned,
|
||||||
|
// but this has worked for years in the old code generator.
|
||||||
|
u256 gasNeededByCaller = evmasm::GasCosts::callGas(m_context.evmVersion()) + 10 + evmasm::GasCosts::callNewAccountGas;
|
||||||
|
templ("gas", "sub(gas(), " + formatNumber(gasNeededByCaller) + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
m_code << templ.render();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
solUnimplemented("FunctionKind " + toString(static_cast<int>(functionType->kind())) + " not yet implemented");
|
solUnimplemented("FunctionKind " + toString(static_cast<int>(functionType->kind())) + " not yet implemented");
|
||||||
}
|
}
|
||||||
|
@ -4,5 +4,7 @@ contract C {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
// ----
|
// ----
|
||||||
// f() -> 0x9c1185a5c5e9fc54612808977ee8f548b2258d31000000000000000000000000
|
// f() -> 0x9c1185a5c5e9fc54612808977ee8f548b2258d31000000000000000000000000
|
||||||
|
@ -3,5 +3,7 @@ contract C {
|
|||||||
return sha256("");
|
return sha256("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
// ----
|
// ----
|
||||||
// f() -> 0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
|
// f() -> 0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
|
||||||
|
@ -3,6 +3,8 @@ contract test {
|
|||||||
return ecrecover(h, v, r, s);
|
return ecrecover(h, v, r, s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
// ----
|
// ----
|
||||||
// a(bytes32,uint8,bytes32,bytes32):
|
// a(bytes32,uint8,bytes32,bytes32):
|
||||||
// 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c,
|
// 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c,
|
||||||
|
@ -4,6 +4,8 @@ contract test {
|
|||||||
return ecrecover(h, v, r, s);
|
return ecrecover(h, v, r, s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
// ----
|
// ----
|
||||||
// a(bytes32,uint8,bytes32,bytes32):
|
// a(bytes32,uint8,bytes32,bytes32):
|
||||||
// 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c,
|
// 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c,
|
||||||
|
@ -6,5 +6,7 @@ contract C {
|
|||||||
return ecrecover(bytes32(uint(-1)), 1, bytes32(uint(2)), bytes32(uint(3)));
|
return ecrecover(bytes32(uint(-1)), 1, bytes32(uint(2)), bytes32(uint(3)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
// ----
|
// ----
|
||||||
// f() -> 0
|
// f() -> 0
|
||||||
|
@ -11,5 +11,7 @@ contract C {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
// ----
|
// ----
|
||||||
// f() -> 0
|
// f() -> 0
|
||||||
|
@ -16,5 +16,7 @@ contract C {
|
|||||||
return ecrecover(hash, v, r, s);
|
return ecrecover(hash, v, r, s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
// ----
|
// ----
|
||||||
// f() -> 0
|
// f() -> 0
|
||||||
|
Loading…
Reference in New Issue
Block a user