-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Conversation
Codecov Report
@@ Coverage Diff @@
## develop #4062 +/- ##
===========================================
- Coverage 65.92% 65.85% -0.07%
===========================================
Files 308 308
Lines 22905 22913 +8
===========================================
- Hits 15100 15090 -10
- Misses 7805 7823 +18
|
@winsvega can you generate tests for this? |
libevm/VM.h
Outdated
@@ -104,6 +104,9 @@ class VM: public VMFace | |||
// space for code | |||
bytes m_code; | |||
|
|||
/// Space for return data. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why three /
s? (I was not looking for them but I saw them.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
///
starts a Doxygen comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe clarify that this is for the data returned from the subcall.
Because now we have m_output described as "return bytes" and m_returnedData described as "return data", this is confusing if you don't know what's it all about
libevmcore/Instruction.cpp
Outdated
@@ -204,6 +54,8 @@ static const std::map<Instruction, InstructionInfo> c_instructionInfo = | |||
{ Instruction::ADDMOD, { "ADDMOD", 0, 3, 1, false, Tier::Mid } }, | |||
{ Instruction::MULMOD, { "MULMOD", 0, 3, 1, false, Tier::Mid } }, | |||
{ Instruction::SIGNEXTEND, { "SIGNEXTEND", 0, 2, 1, false, Tier::Low } }, | |||
{ Instruction::RETURNDATASIZE,{"RETURNDATASIZE", 0, 0, 1, false, Tier::Low } }, | |||
{ Instruction::RETURNDATACOPY,{"RETURNDATACOPY", 0, 3, 0, false, Tier::Low } }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do the Tiers look different from those of CALLDATASIZE
and CALLDATACOPY
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I was so focused on setting the number of args right I forgot about the costs.
libevmcore/Instruction.cpp
Outdated
@@ -204,6 +54,8 @@ static const std::map<Instruction, InstructionInfo> c_instructionInfo = | |||
{ Instruction::ADDMOD, { "ADDMOD", 0, 3, 1, false, Tier::Mid } }, | |||
{ Instruction::MULMOD, { "MULMOD", 0, 3, 1, false, Tier::Mid } }, | |||
{ Instruction::SIGNEXTEND, { "SIGNEXTEND", 0, 2, 1, false, Tier::Low } }, | |||
{ Instruction::RETURNDATASIZE,{"RETURNDATASIZE", 0, 0, 1, false, Tier::VeryLow } }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are the prices still not right? Tier::VeryLow
is 3, but RETURNDATASIZE
should be 2, which is Tier::Base
, like CALLDATASIZE
And RETURNDATACOPY
should be Tier::VeryLow
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Of course. I'm really sorry, I must have been distracted. BTW, "side effect" is not used, but this should be addressed in #4072.
libevmcore/Instruction.cpp
Outdated
@@ -204,6 +54,8 @@ static const std::map<Instruction, InstructionInfo> c_instructionInfo = | |||
{ Instruction::ADDMOD, { "ADDMOD", 0, 3, 1, false, Tier::Mid } }, | |||
{ Instruction::MULMOD, { "MULMOD", 0, 3, 1, false, Tier::Mid } }, | |||
{ Instruction::SIGNEXTEND, { "SIGNEXTEND", 0, 2, 1, false, Tier::Low } }, | |||
{ Instruction::RETURNDATASIZE,{"RETURNDATASIZE", 0, 0, 1, false, Tier::VeryLow } }, | |||
{ Instruction::RETURNDATACOPY,{"RETURNDATACOPY", 0, 3, 0, false, Tier::Low } }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess it should have true
for side-effects like CALLDATACOPY
libevm/VMCalls.cpp
Outdated
bytesRef output; | ||
if (caseCallSetup(callParams.get(), output)) | ||
{ | ||
std::pair<bool, owning_bytes_ref> callResult = m_ext->call(*callParams); | ||
callResult.second.copyTo(output); | ||
m_returnData.assign(callResult.second.begin(), callResult.second.end()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we define m_returnData
as owning_bytes_ref
and then move here instead of copying?
(if not, using helpers like owning_bytes_ref::toBytes
probably would make this expression simpler)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not a big fun of helpers like toBytes
, usually C++ std lib should be enough. But the question is: should we keep the full memory buffer (owning_bytes_ref) or copy only the return buffer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Anyway, refactored.
bool success = false; | ||
owning_bytes_ref outputRef; | ||
std::tie(success, outputRef) = m_ext->call(*callParams); | ||
outputRef.copyTo(output); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Am I mistaken that output
is only written to but not read from? (This didn't change in this commit, but I started wondering now.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, it's the caller's memory!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Magic. The output
is actually a memory reference initialized in caseCallSetup()
. This is exactly CALL output buffer, might be of length 0 depending on CALL arguments. Here we copy the data there according to what the CALL requested.
Big thanks for reviewing this. |
I would better merge now, then fix what changed later |
ON_OP(); | ||
updateIOGas(); | ||
|
||
copyDataToMemory(&m_returnData, m_SP); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not strictly connected to this PR, but probably it would be better to have the offset + size as explicit parameters in copyDataToMemory
.
@@ -120,6 +120,9 @@ void VM::caseCreate() | |||
uint64_t initOff = (uint64_t)m_SP[1]; | |||
uint64_t initSize = (uint64_t)m_SP[2]; | |||
|
|||
// Clear the return data buffer. This will not free the memory. | |||
m_returnData.clear(); | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When the contract initialization executes REVERT
, m_returnData
has to be set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See the last sentence on this line: https://github.com/ethereum/EIPs/pull/211/files#diff-fd8c393953fe66162d8bb518d87bfb57R32
(That's something I learned while doing YP.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implemented.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to update return buffer after CREATE
Introduce RETURNDATASIZE and RETURNDATACOPY opcodes, they do nothing useful at the moment.
libevm/VMCalls.cpp
Outdated
owning_bytes_ref revertOutput; | ||
std::tie(addr, revertOutput) = m_ext->create(endowment, gas, bytesConstRef(m_mem.data() + initOff, initSize), m_onOp); | ||
m_SPP[0] = (u160)addr; | ||
m_returnData = revertOutput.toBytes(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When the creation succeeds, does this set the deployed code in the buffer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. Executive handles this. For CREATE, the VM output is only taken in case of REVERT. https://github.com/ethereum/cpp-ethereum/blob/develop/libethereum/Executive.cpp#L411.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see. I've opened the same file in the editor but I was not quite seeing it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's my role to explain the changes.
libevm/JitVM.cpp
Outdated
auto addr = env.create(value, gas, input, {}); | ||
h160 addr; | ||
owning_bytes_ref revertOutput; | ||
std::tie(addr, revertOutput) = env.create(value, gas, input, {}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
revertOutput
is not used after create
, is this correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At the moment it is. EVM-C does not support "revert output" yet so there is not option to pass this back to EVMJIT. But EVM-C v4 changes are in progress.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd use std::ignore
while this is the case.
libevmcore/Instruction.h
Outdated
@@ -47,6 +47,9 @@ enum class Instruction: uint8_t | |||
EXP, ///< exponential operation | |||
SIGNEXTEND, ///< extend length of signed integer | |||
|
|||
RETURNDATASIZE = 0x0d, ///< size of data returned from previous call | |||
RETURNDATACOPY = 0x0e, ///< copy data returned from previous call to memory |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The opcodes seem to have changed: ethereum/solidity#2275 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not in the EIP PR.
libevm/VMCalls.cpp
Outdated
if (m_ext->balance(m_ext->myAddress) >= endowment && m_ext->depth < 1024) | ||
{ | ||
*m_io_gas_p = m_io_gas; | ||
u256 createGas = *m_io_gas_p; | ||
if (!m_schedule->staticCallDepthLimit()) | ||
createGas -= createGas / 64; | ||
u256 gas = createGas; | ||
m_SPP[0] = (u160)m_ext->create(endowment, gas, bytesConstRef(m_mem.data() + initOff, initSize), m_onOp); | ||
h160 addr; | ||
owning_bytes_ref revertOutput; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe name it just output
? Because revertOutput
is kind of assuming how create
works internally and that only REVERT
can return data. Which is the case now, but could change in the furure
Looks good now, just a couple of minor comments. |
@yann300 take a look at changes in |
Ok, I will try to apply suggestions as soon as possible. |
Ready to land? |
@chriseth is changing the EIP. |
ethereum/EIPs#211