Merge pull request #8052 from ethereum/yul-interp

Fix implementation of getCodeSize in Ewasm
This commit is contained in:
chriseth 2019-12-18 16:55:26 +01:00 committed by GitHub
commit f9a76f8c9b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 47 additions and 22 deletions

View File

@ -401,8 +401,7 @@ function calldatacopy(x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4) {
// Needed? // Needed?
function codesize() -> z1, z2, z3, z4 { function codesize() -> z1, z2, z3, z4 {
eth.getCodeSize(0) z4 := eth.getCodeSize()
z1, z2, z3, z4 := mload_internal(0)
} }
function codecopy(x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4) { function codecopy(x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4) {
eth.codeCopy( eth.codeCopy(

View File

@ -120,7 +120,7 @@ void WasmDialect::addEthereumExternals()
{"getCaller", {i32ptr}, {}}, {"getCaller", {i32ptr}, {}},
{"getCallValue", {i32ptr}, {}}, {"getCallValue", {i32ptr}, {}},
{"codeCopy", {i32ptr, i32, i32}, {}}, {"codeCopy", {i32ptr, i32, i32}, {}},
{"getCodeSize", {i32ptr}, {}}, {"getCodeSize", {}, {i32}},
{"getBlockCoinbase", {i32ptr}, {}}, {"getBlockCoinbase", {i32ptr}, {}},
{"create", {i32ptr, i32ptr, i32, i32ptr}, {i32}}, {"create", {i32ptr, i32ptr, i32, i32ptr}, {i32}},
{"getBlockDifficulty", {i32ptr}, {}}, {"getBlockDifficulty", {i32ptr}, {}},

View File

@ -7,6 +7,5 @@
// Trace: // Trace:
// INVALID() // INVALID()
// Memory dump: // Memory dump:
// 0: 0000000000000000000000000000000000000000000000000000000000000014
// 40: 636f6465636f6465636f6465636f6465636f6465000000000000000000000000 // 40: 636f6465636f6465636f6465636f6465636f6465000000000000000000000000
// Storage dump: // Storage dump:

View File

@ -9,6 +9,5 @@
// Trace: // Trace:
// INVALID() // INVALID()
// Memory dump: // Memory dump:
// 0: 0000000000000000000000000000000000000000000000000000000000000014
// 80: 636f6465636f6465636f6465636f6465636f6465000000000000000000000000 // 80: 636f6465636f6465636f6465636f6465636f6465000000000000000000000000
// Storage dump: // Storage dump:

View File

@ -139,18 +139,27 @@ u256 EWasmBuiltinInterpreter::evalBuiltin(YulString _fun, vector<u256> const& _a
return readMemoryWord(arg[0]); return readMemoryWord(arg[0]);
} }
else if (_fun == "eth.getAddress"_yulstring) else if (_fun == "eth.getAddress"_yulstring)
return writeAddress(arg[0], m_state.address); {
writeAddress(arg[0], m_state.address);
return 0;
}
else if (_fun == "eth.getExternalBalance"_yulstring) else if (_fun == "eth.getExternalBalance"_yulstring)
{
// TODO this does not read the address, but is consistent with // TODO this does not read the address, but is consistent with
// EVM interpreter implementation. // EVM interpreter implementation.
// If we take the address into account, this needs to use readAddress. // If we take the address into account, this needs to use readAddress.
return writeU128(arg[0], m_state.balance); writeU128(arg[0], m_state.balance);
return 0;
}
else if (_fun == "eth.getBlockHash"_yulstring) else if (_fun == "eth.getBlockHash"_yulstring)
{ {
if (arg[0] >= m_state.blockNumber || arg[0] + 256 < m_state.blockNumber) if (arg[0] >= m_state.blockNumber || arg[0] + 256 < m_state.blockNumber)
return 1; return 1;
else else
return writeU256(arg[1], 0xaaaaaaaa + u256(arg[0] - m_state.blockNumber - 256)); {
writeU256(arg[1], 0xaaaaaaaa + u256(arg[0] - m_state.blockNumber - 256));
return 0;
}
} }
else if (_fun == "eth.call"_yulstring) else if (_fun == "eth.call"_yulstring)
{ {
@ -199,12 +208,21 @@ u256 EWasmBuiltinInterpreter::evalBuiltin(YulString _fun, vector<u256> const& _a
return 0; return 0;
} }
else if (_fun == "eth.storageLoad"_yulstring) else if (_fun == "eth.storageLoad"_yulstring)
return writeU256(arg[1], m_state.storage[h256(readU256(arg[0]))]); {
writeU256(arg[1], m_state.storage[h256(readU256(arg[0]))]);
return 0;
}
else if (_fun == "eth.getCaller"_yulstring) else if (_fun == "eth.getCaller"_yulstring)
{
// TODO should this only write 20 bytes? // TODO should this only write 20 bytes?
return writeAddress(arg[0], m_state.caller); writeAddress(arg[0], m_state.caller);
return 0;
}
else if (_fun == "eth.getCallValue"_yulstring) else if (_fun == "eth.getCallValue"_yulstring)
return writeU128(arg[0], m_state.callvalue); {
writeU128(arg[0], m_state.callvalue);
return 0;
}
else if (_fun == "eth.codeCopy"_yulstring) else if (_fun == "eth.codeCopy"_yulstring)
{ {
if (accessMemory(arg[0], arg[2])) if (accessMemory(arg[0], arg[2]))
@ -215,9 +233,12 @@ u256 EWasmBuiltinInterpreter::evalBuiltin(YulString _fun, vector<u256> const& _a
return 0; return 0;
} }
else if (_fun == "eth.getCodeSize"_yulstring) else if (_fun == "eth.getCodeSize"_yulstring)
return writeU256(arg[0], m_state.code.size()); return m_state.code.size();
else if (_fun == "eth.getBlockCoinbase"_yulstring) else if (_fun == "eth.getBlockCoinbase"_yulstring)
return writeAddress(arg[0], m_state.coinbase); {
writeAddress(arg[0], m_state.coinbase);
return 0;
}
else if (_fun == "eth.create"_yulstring) else if (_fun == "eth.create"_yulstring)
{ {
// TODO access memory // TODO access memory
@ -226,7 +247,10 @@ u256 EWasmBuiltinInterpreter::evalBuiltin(YulString _fun, vector<u256> const& _a
return 0xcccccc + arg[1]; return 0xcccccc + arg[1];
} }
else if (_fun == "eth.getBlockDifficulty"_yulstring) else if (_fun == "eth.getBlockDifficulty"_yulstring)
return writeU256(arg[0], m_state.difficulty); {
writeU256(arg[0], m_state.difficulty);
return 0;
}
else if (_fun == "eth.externalCodeCopy"_yulstring) else if (_fun == "eth.externalCodeCopy"_yulstring)
{ {
// TODO use readAddress to read address. // TODO use readAddress to read address.
@ -245,7 +269,10 @@ u256 EWasmBuiltinInterpreter::evalBuiltin(YulString _fun, vector<u256> const& _a
else if (_fun == "eth.getBlockGasLimit"_yulstring) else if (_fun == "eth.getBlockGasLimit"_yulstring)
return uint64_t(m_state.gaslimit); return uint64_t(m_state.gaslimit);
else if (_fun == "eth.getTxGasPrice"_yulstring) else if (_fun == "eth.getTxGasPrice"_yulstring)
return writeU128(arg[0], m_state.gasprice); {
writeU128(arg[0], m_state.gasprice);
return 0;
}
else if (_fun == "eth.log"_yulstring) else if (_fun == "eth.log"_yulstring)
{ {
uint64_t numberOfTopics = arg[2]; uint64_t numberOfTopics = arg[2];
@ -257,7 +284,10 @@ u256 EWasmBuiltinInterpreter::evalBuiltin(YulString _fun, vector<u256> const& _a
else if (_fun == "eth.getBlockNumber"_yulstring) else if (_fun == "eth.getBlockNumber"_yulstring)
return m_state.blockNumber; return m_state.blockNumber;
else if (_fun == "eth.getTxOrigin"_yulstring) else if (_fun == "eth.getTxOrigin"_yulstring)
return writeAddress(arg[0], m_state.origin); {
writeAddress(arg[0], m_state.origin);
return 0;
}
else if (_fun == "eth.finish"_yulstring) else if (_fun == "eth.finish"_yulstring)
{ {
bytes data; bytes data;
@ -338,7 +368,7 @@ void EWasmBuiltinInterpreter::writeMemoryWord(uint64_t _offset, uint64_t _value)
m_state.memory[_offset + i] = uint8_t((_value >> (i * 8)) & 0xff); m_state.memory[_offset + i] = uint8_t((_value >> (i * 8)) & 0xff);
} }
u256 EWasmBuiltinInterpreter::writeU256(uint64_t _offset, u256 _value, size_t _croppedTo) void EWasmBuiltinInterpreter::writeU256(uint64_t _offset, u256 _value, size_t _croppedTo)
{ {
accessMemory(_offset, _croppedTo); accessMemory(_offset, _croppedTo);
for (size_t i = 0; i < _croppedTo; i++) for (size_t i = 0; i < _croppedTo; i++)
@ -346,8 +376,6 @@ u256 EWasmBuiltinInterpreter::writeU256(uint64_t _offset, u256 _value, size_t _c
m_state.memory[_offset + _croppedTo - 1 - i] = uint8_t(_value & 0xff); m_state.memory[_offset + _croppedTo - 1 - i] = uint8_t(_value & 0xff);
_value >>= 8; _value >>= 8;
} }
return {};
} }
u256 EWasmBuiltinInterpreter::readU256(uint64_t _offset, size_t _croppedTo) u256 EWasmBuiltinInterpreter::readU256(uint64_t _offset, size_t _croppedTo)

View File

@ -88,9 +88,9 @@ private:
void writeMemoryWord(uint64_t _offset, uint64_t _value); void writeMemoryWord(uint64_t _offset, uint64_t _value);
/// Helper for eth.* builtins. Writes to memory (big-endian) and always returns zero. /// Helper for eth.* builtins. Writes to memory (big-endian) and always returns zero.
dev::u256 writeU256(uint64_t _offset, dev::u256 _value, size_t _croppedTo = 32); void writeU256(uint64_t _offset, dev::u256 _value, size_t _croppedTo = 32);
dev::u256 writeU128(uint64_t _offset, dev::u256 _value) { return writeU256(_offset, std::move(_value), 16); } void writeU128(uint64_t _offset, dev::u256 _value) { writeU256(_offset, std::move(_value), 16); }
dev::u256 writeAddress(uint64_t _offset, dev::u256 _value) { return writeU256(_offset, std::move(_value), 20); } void writeAddress(uint64_t _offset, dev::u256 _value) { writeU256(_offset, std::move(_value), 20); }
/// Helper for eth.* builtins. Reads from memory (big-endian) and returns the value; /// Helper for eth.* builtins. Reads from memory (big-endian) and returns the value;
dev::u256 readU256(uint64_t _offset, size_t _croppedTo = 32); dev::u256 readU256(uint64_t _offset, size_t _croppedTo = 32);
dev::u256 readU128(uint64_t _offset) { return readU256(_offset, 16); } dev::u256 readU128(uint64_t _offset) { return readU256(_offset, 16); }