mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
[ewasm] Overhaul memory handling in EwasmInterpreter
Introduce writeMemory and read/writeBytes32/Address helpers. Fix read/writeU128/U256 to be little-endian. Update each instruction to follow the specification.
This commit is contained in:
parent
9b353103b4
commit
62028c90f0
@ -6,7 +6,7 @@
|
|||||||
// Trace:
|
// Trace:
|
||||||
// Memory dump:
|
// Memory dump:
|
||||||
// 0: 0000000000000000000000000000000000000000000000000000000000000001
|
// 0: 0000000000000000000000000000000000000000000000000000000000000001
|
||||||
// 20: 0000000000000000000000000000000000000000000000000000000022222222
|
// 20: 0000000000000000000000000000000022222222000000000000000000000000
|
||||||
// Storage dump:
|
// Storage dump:
|
||||||
// 0000000000000000000000000000000000000000000000000000000000000000: 0000000000000000000000000000000000000000000000000000000022222222
|
// 0000000000000000000000000000000000000000000000000000000000000000: 0000000000000000000000000000000022222222000000000000000000000000
|
||||||
// 0000000000000000000000000000000000000000000000000000000000000001: 0000000000000000000000000000000000000000000000000000000022222222
|
// 0000000000000000000000000000000000000000000000000000000000000001: 0000000000000000000000000000000022222222000000000000000000000000
|
||||||
|
@ -4,6 +4,6 @@
|
|||||||
// ----
|
// ----
|
||||||
// Trace:
|
// Trace:
|
||||||
// Memory dump:
|
// Memory dump:
|
||||||
// 20: 0000000000000000000000005555555500000000000000000000000000000000
|
// 20: 5555555500000000000000000000000000000000000000000000000000000000
|
||||||
// Storage dump:
|
// Storage dump:
|
||||||
// 0000000000000000000000000000000000000000000000000000000000000000: 0000000000000000000000005555555500000000000000000000000000000000
|
// 0000000000000000000000000000000000000000000000000000000000000000: 5555555500000000000000000000000000000000000000000000000000000000
|
||||||
|
@ -4,6 +4,6 @@
|
|||||||
// ----
|
// ----
|
||||||
// Trace:
|
// Trace:
|
||||||
// Memory dump:
|
// Memory dump:
|
||||||
// 20: 0000000000000000000000000000000000000000000000000000000009999999
|
// 20: 9999990900000000000000000000000000000000000000000000000000000000
|
||||||
// Storage dump:
|
// Storage dump:
|
||||||
// 0000000000000000000000000000000000000000000000000000000000000000: 0000000000000000000000000000000000000000000000000000000009999999
|
// 0000000000000000000000000000000000000000000000000000000000000000: 9999990900000000000000000000000000000000000000000000000000000000
|
||||||
|
@ -4,6 +4,6 @@
|
|||||||
// ----
|
// ----
|
||||||
// Trace:
|
// Trace:
|
||||||
// Memory dump:
|
// Memory dump:
|
||||||
// 20: 000000000000000000000000000000000000000000000000000000000000077b
|
// 20: 0000000000000000000000000000000000000000000000000000000000000dd6
|
||||||
// Storage dump:
|
// Storage dump:
|
||||||
// 0000000000000000000000000000000000000000000000000000000000000000: 000000000000000000000000000000000000000000000000000000000000077b
|
// 0000000000000000000000000000000000000000000000000000000000000000: 0000000000000000000000000000000000000000000000000000000000000dd6
|
||||||
|
@ -4,6 +4,6 @@
|
|||||||
// ----
|
// ----
|
||||||
// Trace:
|
// Trace:
|
||||||
// Memory dump:
|
// Memory dump:
|
||||||
// 20: 0000000000000000000000006666666600000000000000000000000000000000
|
// 20: 6666666600000000000000000000000000000000000000000000000000000000
|
||||||
// Storage dump:
|
// Storage dump:
|
||||||
// 0000000000000000000000000000000000000000000000000000000000000000: 0000000000000000000000006666666600000000000000000000000000000000
|
// 0000000000000000000000000000000000000000000000000000000000000000: 6666666600000000000000000000000000000000000000000000000000000000
|
||||||
|
@ -35,6 +35,7 @@ using namespace solidity;
|
|||||||
using namespace solidity::yul;
|
using namespace solidity::yul;
|
||||||
using namespace solidity::yul::test;
|
using namespace solidity::yul::test;
|
||||||
|
|
||||||
|
using solidity::util::h160;
|
||||||
using solidity::util::h256;
|
using solidity::util::h256;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
@ -309,7 +310,7 @@ u256 EwasmBuiltinInterpreter::evalEthBuiltin(string const& _fun, vector<uint64_t
|
|||||||
return 1;
|
return 1;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
writeU256(arg[1], 0xaaaaaaaa + u256(arg[0] - m_state.blockNumber - 256));
|
writeBytes32(arg[1], h256(0xaaaaaaaa + u256(arg[0] - m_state.blockNumber - 256)));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -356,17 +357,16 @@ u256 EwasmBuiltinInterpreter::evalEthBuiltin(string const& _fun, vector<uint64_t
|
|||||||
}
|
}
|
||||||
else if (_fun == "storageStore")
|
else if (_fun == "storageStore")
|
||||||
{
|
{
|
||||||
m_state.storage[h256(readU256(arg[0]))] = readU256((arg[1]));
|
m_state.storage[readBytes32(arg[0])] = readBytes32(arg[1]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (_fun == "storageLoad")
|
else if (_fun == "storageLoad")
|
||||||
{
|
{
|
||||||
writeU256(arg[1], m_state.storage[h256(readU256(arg[0]))]);
|
writeBytes32(arg[1], m_state.storage[readBytes32(arg[0])]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (_fun == "getCaller")
|
else if (_fun == "getCaller")
|
||||||
{
|
{
|
||||||
// TODO should this only write 20 bytes?
|
|
||||||
writeAddress(arg[0], m_state.caller);
|
writeAddress(arg[0], m_state.caller);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -415,8 +415,8 @@ u256 EwasmBuiltinInterpreter::evalEthBuiltin(string const& _fun, vector<uint64_t
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (_fun == "getExternalCodeSize")
|
else if (_fun == "getExternalCodeSize")
|
||||||
// Generate "random" code length. Make sure it fits the page size.
|
// Generate "random" code length.
|
||||||
return u256(keccak256(h256(readAddress(arg[0])))) & 0xfff;
|
return uint32_t(u256(keccak256(h256(readAddress(arg[0])))) & 0xfff);
|
||||||
else if (_fun == "getGasLeft")
|
else if (_fun == "getGasLeft")
|
||||||
return 0x99;
|
return 0x99;
|
||||||
else if (_fun == "getBlockGasLimit")
|
else if (_fun == "getBlockGasLimit")
|
||||||
@ -523,6 +523,12 @@ uint32_t EwasmBuiltinInterpreter::readMemoryHalfWord(uint64_t _offset)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EwasmBuiltinInterpreter::writeMemory(uint64_t _offset, bytes const& _value)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < _value.size(); i++)
|
||||||
|
m_state.memory[_offset + i] = _value[i];
|
||||||
|
}
|
||||||
|
|
||||||
void EwasmBuiltinInterpreter::writeMemoryWord(uint64_t _offset, uint64_t _value)
|
void EwasmBuiltinInterpreter::writeMemoryWord(uint64_t _offset, uint64_t _value)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < 8; i++)
|
for (size_t i = 0; i < 8; i++)
|
||||||
@ -545,7 +551,7 @@ void EwasmBuiltinInterpreter::writeU256(uint64_t _offset, u256 _value, size_t _c
|
|||||||
accessMemory(_offset, _croppedTo);
|
accessMemory(_offset, _croppedTo);
|
||||||
for (size_t i = 0; i < _croppedTo; i++)
|
for (size_t i = 0; i < _croppedTo; i++)
|
||||||
{
|
{
|
||||||
m_state.memory[_offset + _croppedTo - 1 - i] = uint8_t(_value & 0xff);
|
m_state.memory[_offset + i] = uint8_t(_value & 0xff);
|
||||||
_value >>= 8;
|
_value >>= 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -553,9 +559,9 @@ void EwasmBuiltinInterpreter::writeU256(uint64_t _offset, u256 _value, size_t _c
|
|||||||
u256 EwasmBuiltinInterpreter::readU256(uint64_t _offset, size_t _croppedTo)
|
u256 EwasmBuiltinInterpreter::readU256(uint64_t _offset, size_t _croppedTo)
|
||||||
{
|
{
|
||||||
accessMemory(_offset, _croppedTo);
|
accessMemory(_offset, _croppedTo);
|
||||||
u256 value;
|
u256 value{0};
|
||||||
for (size_t i = 0; i < _croppedTo; i++)
|
for (size_t i = 0; i < _croppedTo; i++)
|
||||||
value = (value << 8) | m_state.memory[_offset + i];
|
value = (value << 8) | m_state.memory[_offset + _croppedTo - 1 - i];
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include <libyul/AsmDataForward.h>
|
#include <libyul/AsmDataForward.h>
|
||||||
|
|
||||||
#include <libsolutil/CommonData.h>
|
#include <libsolutil/CommonData.h>
|
||||||
|
#include <libsolutil/FixedHash.h>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -61,6 +62,8 @@ struct InterpreterState;
|
|||||||
*
|
*
|
||||||
* The main focus is that the generated execution trace is the same for equivalent executions
|
* The main focus is that the generated execution trace is the same for equivalent executions
|
||||||
* and likely to be different for non-equivalent executions.
|
* and likely to be different for non-equivalent executions.
|
||||||
|
*
|
||||||
|
* The type names are following the Ewasm specification (https://github.com/ewasm/design/blob/master/eth_interface.md).
|
||||||
*/
|
*/
|
||||||
class EwasmBuiltinInterpreter
|
class EwasmBuiltinInterpreter
|
||||||
{
|
{
|
||||||
@ -99,6 +102,9 @@ private:
|
|||||||
/// @returns the memory contents (4 bytes) at the provided address (little-endian).
|
/// @returns the memory contents (4 bytes) at the provided address (little-endian).
|
||||||
/// Does not adjust msize, use @a accessMemory for that
|
/// Does not adjust msize, use @a accessMemory for that
|
||||||
uint32_t readMemoryHalfWord(uint64_t _offset);
|
uint32_t readMemoryHalfWord(uint64_t _offset);
|
||||||
|
/// Writes bytes to memory.
|
||||||
|
/// Does not adjust msize, use @a accessMemory for that
|
||||||
|
void writeMemory(uint64_t _offset, bytes const& _value);
|
||||||
/// Writes a word to memory (little-endian)
|
/// Writes a word to memory (little-endian)
|
||||||
/// Does not adjust msize, use @a accessMemory for that
|
/// Does not adjust msize, use @a accessMemory for that
|
||||||
void writeMemoryWord(uint64_t _offset, uint64_t _value);
|
void writeMemoryWord(uint64_t _offset, uint64_t _value);
|
||||||
@ -109,14 +115,18 @@ private:
|
|||||||
/// Does not adjust msize, use @a accessMemory for that
|
/// Does not adjust msize, use @a accessMemory for that
|
||||||
void writeMemoryByte(uint64_t _offset, uint8_t _value);
|
void writeMemoryByte(uint64_t _offset, uint8_t _value);
|
||||||
|
|
||||||
/// Helper for eth.* builtins. Writes to memory (big-endian) and always returns zero.
|
/// Helper for eth.* builtins. Writes to memory (little-endian) and always returns zero.
|
||||||
void writeU256(uint64_t _offset, u256 _value, size_t _croppedTo = 32);
|
void writeU256(uint64_t _offset, u256 _value, size_t _croppedTo = 32);
|
||||||
void writeU128(uint64_t _offset, u256 _value) { writeU256(_offset, std::move(_value), 16); }
|
void writeU128(uint64_t _offset, u256 _value) { writeU256(_offset, std::move(_value), 16); }
|
||||||
void writeAddress(uint64_t _offset, u256 _value) { writeU256(_offset, std::move(_value), 20); }
|
/// Helper for eth.* builtins. Writes to memory (as a byte string).
|
||||||
/// Helper for eth.* builtins. Reads from memory (big-endian) and returns the value;
|
void writeBytes32(uint64_t _offset, util::h256 _value) { accessMemory(_offset, 32); writeMemory(_offset, _value.asBytes()); }
|
||||||
|
void writeAddress(uint64_t _offset, util::h160 _value) { accessMemory(_offset, 20); writeMemory(_offset, _value.asBytes()); }
|
||||||
|
/// Helper for eth.* builtins. Reads from memory (little-endian) and returns the value.
|
||||||
u256 readU256(uint64_t _offset, size_t _croppedTo = 32);
|
u256 readU256(uint64_t _offset, size_t _croppedTo = 32);
|
||||||
u256 readU128(uint64_t _offset) { return readU256(_offset, 16); }
|
u256 readU128(uint64_t _offset) { return readU256(_offset, 16); }
|
||||||
u256 readAddress(uint64_t _offset) { return readU256(_offset, 20); }
|
/// Helper for eth.* builtins. Reads from memory (as a byte string).
|
||||||
|
util::h256 readBytes32(uint64_t _offset) { accessMemory(_offset, 32); return util::h256(readMemory(_offset, 32)); }
|
||||||
|
util::h160 readAddress(uint64_t _offset) { accessMemory(_offset, 20); return util::h160(readMemory(_offset, 20)); }
|
||||||
|
|
||||||
void logTrace(evmasm::Instruction _instruction, std::vector<u256> const& _arguments = {}, bytes const& _data = {});
|
void logTrace(evmasm::Instruction _instruction, std::vector<u256> const& _arguments = {}, bytes const& _data = {});
|
||||||
/// Appends a log to the trace representing an instruction or similar operation by string,
|
/// Appends a log to the trace representing an instruction or similar operation by string,
|
||||||
|
Loading…
Reference in New Issue
Block a user