Browse Source

Solidity SHA3 can now take multiple arguments

cl-refactor
Lefteris Karapetsas 10 years ago
parent
commit
04aa0cc9ba
  1. 19
      libsolidity/AST.cpp
  2. 23
      libsolidity/ExpressionCompiler.cpp
  3. 8
      libsolidity/ExpressionCompiler.h
  4. 19
      test/SolidityEndToEndTest.cpp

19
libsolidity/AST.cpp

@ -487,14 +487,27 @@ void FunctionCall::checkTypeRequirements()
// and then ask if that is implicitly convertible to the struct represented by the // and then ask if that is implicitly convertible to the struct represented by the
// function parameters // function parameters
TypePointers const& parameterTypes = functionType->getParameterTypes(); TypePointers const& parameterTypes = functionType->getParameterTypes();
if (parameterTypes.size() != m_arguments.size()) if (functionType->getLocation() !=FunctionType::Location::SHA3 && parameterTypes.size() != m_arguments.size())
BOOST_THROW_EXCEPTION(createTypeError("Wrong argument count for function call.")); BOOST_THROW_EXCEPTION(createTypeError("Wrong argument count for function call."));
if (m_names.empty()) if (m_names.empty()) // LTODO: Totally ignoring sha3 case for named arguments for now just for the rebase to work
{ {
for (size_t i = 0; i < m_arguments.size(); ++i) for (size_t i = 0; i < m_arguments.size(); ++i)
if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[i])) {
if (functionType->getLocation() == FunctionType::Location::SHA3)
{
#if 0 // are we sure we want that? Literal constant nums can't live outside storage and so sha3(42) will fail
if (!m_arguments[i]->getType()->canLiveOutsideStorage())
BOOST_THROW_EXCEPTION(createTypeError("SHA3 called with argument that can't live outside storage"));
#endif
if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[0]))
BOOST_THROW_EXCEPTION(createTypeError(std::string("SHA3 argument ") +
boost::lexical_cast<std::string>(i) +
std::string("can't be converted to hash")));
} else if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[i]))
BOOST_THROW_EXCEPTION(createTypeError("Invalid type for argument in function call.")); BOOST_THROW_EXCEPTION(createTypeError("Invalid type for argument in function call."));
}
} }
else else
{ {

23
libsolidity/ExpressionCompiler.cpp

@ -206,7 +206,8 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
TypePointers const& parameterTypes = function.getParameterTypes(); TypePointers const& parameterTypes = function.getParameterTypes();
vector<ASTPointer<Expression const>> const& callArguments = _functionCall.getArguments(); vector<ASTPointer<Expression const>> const& callArguments = _functionCall.getArguments();
vector<ASTPointer<ASTString>> const& callArgumentNames = _functionCall.getNames(); vector<ASTPointer<ASTString>> const& callArgumentNames = _functionCall.getNames();
solAssert(callArguments.size() == parameterTypes.size(), ""); if (function.getLocation() != Location::SHA3)
solAssert(callArguments.size() == parameterTypes.size(), "");
vector<ASTPointer<Expression const>> arguments; vector<ASTPointer<Expression const>> arguments;
if (callArgumentNames.empty()) if (callArgumentNames.empty())
@ -325,9 +326,11 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
m_context << eth::Instruction::SUICIDE; m_context << eth::Instruction::SUICIDE;
break; break;
case Location::SHA3: case Location::SHA3:
appendExpressionCopyToMemory(*function.getParameterTypes().front(), *arguments.front()); {
m_context << u256(32) << u256(0) << eth::Instruction::SHA3; unsigned length = appendSameTypeArgumentsCopyToMemory(function.getParameterTypes().front(), arguments, 0);
m_context << u256(length) << u256(0) << eth::Instruction::SHA3;
break; break;
}
case Location::LOG0: case Location::LOG0:
case Location::LOG1: case Location::LOG1:
case Location::LOG2: case Location::LOG2:
@ -843,8 +846,18 @@ unsigned ExpressionCompiler::appendArgumentCopyToMemory(TypePointers const& _typ
return length; return length;
} }
unsigned ExpressionCompiler::appendTypeConversionAndMoveToMemory(Type const& _expectedType, Type const& _type, unsigned ExpressionCompiler::appendSameTypeArgumentsCopyToMemory(TypePointer const& _type,
Location const& _location, unsigned _memoryOffset) vector<ASTPointer<Expression const>> const& _arguments,
unsigned _memoryOffset)
{
unsigned length = 0;
for (unsigned i = 0; i < _arguments.size(); ++i)
length += appendExpressionCopyToMemory(*_type, *_arguments[i], _memoryOffset + length);
return length;
}
unsigned ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedType,
Expression const& _expression, unsigned _memoryOffset)
{ {
appendTypeConversion(_type, _expectedType, true); appendTypeConversion(_type, _expectedType, true);
unsigned const c_numBytes = CompilerUtils::getPaddedSize(_expectedType.getCalldataEncodedSize()); unsigned const c_numBytes = CompilerUtils::getPaddedSize(_expectedType.getCalldataEncodedSize());

8
libsolidity/ExpressionCompiler.h

@ -97,10 +97,12 @@ private:
unsigned appendArgumentCopyToMemory(TypePointers const& _types, unsigned appendArgumentCopyToMemory(TypePointers const& _types,
std::vector<ASTPointer<Expression const>> const& _arguments, std::vector<ASTPointer<Expression const>> const& _arguments,
unsigned _memoryOffset = 0); unsigned _memoryOffset = 0);
/// Appends code that copies a type to memory. /// Appends code that copies the given arguments that should all have the
/// same @a _type to memory (with optional offset).
/// @returns the number of bytes copied to memory /// @returns the number of bytes copied to memory
unsigned appendTypeConversionAndMoveToMemory(Type const& _expectedType, Type const& _type, unsigned appendSameTypeArgumentsCopyToMemory(TypePointer const& _type,
Location const& _location, unsigned _memoryOffset = 0); std::vector<ASTPointer<Expression const>> const& _arguments,
unsigned _memoryOffset = 0);
/// Appends code that evaluates a single expression and copies it to memory (with optional offset). /// Appends code that evaluates a single expression and copies it to memory (with optional offset).
/// @returns the number of bytes copied to memory /// @returns the number of bytes copied to memory
unsigned appendExpressionCopyToMemory(Type const& _expectedType, Expression const& _expression, unsigned appendExpressionCopyToMemory(Type const& _expectedType, Expression const& _expression,

19
test/SolidityEndToEndTest.cpp

@ -2095,6 +2095,25 @@ BOOST_AUTO_TEST_CASE(event_lots_of_data)
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::sha3(string("Deposit(address,hash256,uint256,bool)"))); BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::sha3(string("Deposit(address,hash256,uint256,bool)")));
} }
BOOST_AUTO_TEST_CASE(sha3_multiple_arguments)
{
char const* sourceCode = R"(
contract c {
// function foo(uint a) returns (hash d)
function foo(uint a, uint b, uint c) returns (hash d)
{
d = sha3(a, b, c);
}
})";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("foo(uint256,uint256,uint256)", 10 , 12, 13) == encodeArgs(
dev::sha3(
toBigEndian(u256(10)) +
toBigEndian(u256(12)) +
toBigEndian(u256(13)))));
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()
} }

Loading…
Cancel
Save