Browse Source

Merge pull request #1037 from chriseth/sol_bytesCalldataToMemory

Copying calldata directly to memory.
cl-refactor
Gav Wood 10 years ago
parent
commit
de06db7e73
  1. 63
      libsolidity/CompilerUtils.cpp
  2. 15
      test/SolidityEndToEndTest.cpp

63
libsolidity/CompilerUtils.cpp

@ -76,35 +76,44 @@ void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBound
if (_type.getCategory() == Type::Category::ByteArray) if (_type.getCategory() == Type::Category::ByteArray)
{ {
auto const& type = dynamic_cast<ByteArrayType const&>(_type); auto const& type = dynamic_cast<ByteArrayType const&>(_type);
solAssert(type.getLocation() == ByteArrayType::Location::Storage, "Non-storage byte arrays not yet implemented.");
m_context << eth::Instruction::DUP1 << eth::Instruction::SLOAD; if (type.getLocation() == ByteArrayType::Location::CallData)
// stack here: memory_offset storage_offset length_bytes {
// jump to end if length is zero m_context << eth::Instruction::CALLDATASIZE << u256(0) << eth::Instruction::DUP3
m_context << eth::Instruction::DUP1 << eth::Instruction::ISZERO; << eth::Instruction::CALLDATACOPY
eth::AssemblyItem loopEnd = m_context.newTag(); << eth::Instruction::CALLDATASIZE << eth::Instruction::ADD;
m_context.appendConditionalJumpTo(loopEnd); }
// compute memory end offset else
m_context << eth::Instruction::DUP3 << eth::Instruction::ADD << eth::Instruction::SWAP2; {
// actual array data is stored at SHA3(storage_offset) solAssert(type.getLocation() == ByteArrayType::Location::Storage, "Memory byte arrays not yet implemented.");
m_context << eth::Instruction::SWAP1; m_context << eth::Instruction::DUP1 << eth::Instruction::SLOAD;
CompilerUtils(m_context).computeHashStatic(); // stack here: memory_offset storage_offset length_bytes
m_context << eth::Instruction::SWAP1; // jump to end if length is zero
m_context << eth::Instruction::DUP1 << eth::Instruction::ISZERO;
eth::AssemblyItem loopEnd = m_context.newTag();
m_context.appendConditionalJumpTo(loopEnd);
// compute memory end offset
m_context << eth::Instruction::DUP3 << eth::Instruction::ADD << eth::Instruction::SWAP2;
// actual array data is stored at SHA3(storage_offset)
m_context << eth::Instruction::SWAP1;
CompilerUtils(m_context).computeHashStatic();
m_context << eth::Instruction::SWAP1;
// stack here: memory_end_offset storage_data_offset memory_offset // stack here: memory_end_offset storage_data_offset memory_offset
eth::AssemblyItem loopStart = m_context.newTag(); eth::AssemblyItem loopStart = m_context.newTag();
m_context << loopStart m_context << loopStart
// load and store // load and store
<< eth::Instruction::DUP2 << eth::Instruction::SLOAD << eth::Instruction::DUP2 << eth::Instruction::SLOAD
<< eth::Instruction::DUP2 << eth::Instruction::MSTORE << eth::Instruction::DUP2 << eth::Instruction::MSTORE
// increment storage_data_offset by 1 // increment storage_data_offset by 1
<< eth::Instruction::SWAP1 << u256(1) << eth::Instruction::ADD << eth::Instruction::SWAP1 << u256(1) << eth::Instruction::ADD
// increment memory offset by 32 // increment memory offset by 32
<< eth::Instruction::SWAP1 << u256(32) << eth::Instruction::ADD << eth::Instruction::SWAP1 << u256(32) << eth::Instruction::ADD
// check for loop condition // check for loop condition
<< eth::Instruction::DUP1 << eth::Instruction::DUP4 << eth::Instruction::GT; << eth::Instruction::DUP1 << eth::Instruction::DUP4 << eth::Instruction::GT;
m_context.appendConditionalJumpTo(loopStart); m_context.appendConditionalJumpTo(loopStart);
m_context << loopEnd << eth::Instruction::POP << eth::Instruction::POP; m_context << loopEnd << eth::Instruction::POP << eth::Instruction::POP;
}
} }
else else
{ {

15
test/SolidityEndToEndTest.cpp

@ -2273,6 +2273,21 @@ BOOST_AUTO_TEST_CASE(store_bytes)
BOOST_CHECK(callContractFunction("save()", "abcdefg") == encodeArgs(24)); BOOST_CHECK(callContractFunction("save()", "abcdefg") == encodeArgs(24));
} }
BOOST_AUTO_TEST_CASE(bytes_from_calldata_to_memory)
{
char const* sourceCode = R"(
contract C {
function() returns (hash) {
return sha3("abc", msg.data);
}
}
)";
compileAndRun(sourceCode);
bytes calldata = bytes(61, 0x22) + bytes(12, 0x12);
sendMessage(calldata, false);
BOOST_CHECK(m_output == encodeArgs(dev::sha3(bytes{'a', 'b', 'c'} + calldata)));
}
BOOST_AUTO_TEST_CASE(call_forward_bytes) BOOST_AUTO_TEST_CASE(call_forward_bytes)
{ {
char const* sourceCode = R"( char const* sourceCode = R"(

Loading…
Cancel
Save