diff --git a/libethereum/ExtVM.h b/libethereum/ExtVM.h index 7709f9d7f..48099b8fc 100644 --- a/libethereum/ExtVM.h +++ b/libethereum/ExtVM.h @@ -62,12 +62,12 @@ public: return ret; } - /// Create a new message call. Leave _myAddressOverride at he default to use the present address as caller. - bool call(Address _receiveAddress, u256 _txValue, bytesConstRef _txData, u256* _gas, bytesRef _out, OnOpFunc const& _onOp = OnOpFunc(), Address _myAddressOverride = Address()) + /// Create a new message call. Leave _myAddressOverride as the default to use the present address as caller. + bool call(Address _receiveAddress, u256 _txValue, bytesConstRef _txData, u256* _gas, bytesRef _out, OnOpFunc const& _onOp = OnOpFunc(), Address _myAddressOverride = Address(), Address _codeAddressOverride = Address()) { if (m_ms) m_ms->internal.resize(m_ms->internal.size() + 1); - auto ret = m_s.call(_receiveAddress, _myAddressOverride ? _myAddressOverride : myAddress, _txValue, gasPrice, _txData, _gas, _out, origin, &suicides, &posts, m_ms ? &(m_ms->internal.back()) : nullptr, _onOp, level + 1); + auto ret = m_s.call(_receiveAddress, _codeAddressOverride ? _codeAddressOverride : _receiveAddress, _myAddressOverride ? _myAddressOverride : myAddress, _txValue, gasPrice, _txData, _gas, _out, origin, &suicides, &posts, m_ms ? &(m_ms->internal.back()) : nullptr, _onOp, level + 1); if (m_ms && !m_ms->internal.back().from) m_ms->internal.pop_back(); return ret; diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 41f4a6f1b..5ef528c58 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -1037,7 +1037,7 @@ u256 State::execute(bytesConstRef _rlp, bytes* o_output, bool _commit) return e.gasUsed(); } -bool State::call(Address _receiveAddress, Address _senderAddress, u256 _value, u256 _gasPrice, bytesConstRef _data, u256* _gas, bytesRef _out, Address _originAddress, std::set
* o_suicides, PostList* o_posts, Manifest* o_ms, OnOpFunc const& _onOp, unsigned _level) +bool State::call(Address _receiveAddress, Address _codeAddress, Address _senderAddress, u256 _value, u256 _gasPrice, bytesConstRef _data, u256* _gas, bytesRef _out, Address _originAddress, std::set
* o_suicides, PostList* o_posts, Manifest* o_ms, OnOpFunc const& _onOp, unsigned _level) { if (!_originAddress) _originAddress = _senderAddress; @@ -1053,10 +1053,10 @@ bool State::call(Address _receiveAddress, Address _senderAddress, u256 _value, u o_ms->input = _data.toBytes(); } - if (addressHasCode(_receiveAddress)) + if (addressHasCode(_codeAddress)) { VM vm(*_gas); - ExtVM evm(*this, _receiveAddress, _senderAddress, _originAddress, _value, _gasPrice, _data, &code(_receiveAddress), o_ms, _level); + ExtVM evm(*this, _receiveAddress, _senderAddress, _originAddress, _value, _gasPrice, _data, &code(_codeAddress), o_ms, _level); bool revert = false; try diff --git a/libethereum/State.h b/libethereum/State.h index 879e5e741..d2aa97632 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -275,7 +275,7 @@ private: /// Execute a call. /// @a _gas points to the amount of gas to use for the call, and will lower it accordingly. /// @returns false if the call ran out of gas before completion. true otherwise. - bool call(Address _myAddress, Address _txSender, u256 _txValue, u256 _gasPrice, bytesConstRef _txData, u256* _gas, bytesRef _out, Address _originAddress = Address(), std::set
* o_suicides = nullptr, PostList* o_posts = nullptr, Manifest* o_ms = nullptr, OnOpFunc const& _onOp = OnOpFunc(), unsigned _level = 0); + bool call(Address _myAddress, Address _codeAddress, Address _txSender, u256 _txValue, u256 _gasPrice, bytesConstRef _txData, u256* _gas, bytesRef _out, Address _originAddress = Address(), std::set
* o_suicides = nullptr, PostList* o_posts = nullptr, Manifest* o_ms = nullptr, OnOpFunc const& _onOp = OnOpFunc(), unsigned _level = 0); /// Sets m_currentBlock to a clean state, (i.e. no change from m_previousBlock). void resetCurrent(); diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h index 7aa8df8e5..54bb86ae7 100644 --- a/libevm/ExtVMFace.h +++ b/libevm/ExtVMFace.h @@ -40,6 +40,8 @@ struct Post using PostList = std::list; +using OnOpFunc = std::function; + /** * @brief A null implementation of the class for specifying VM externalities. */ @@ -77,7 +79,7 @@ public: h160 create(u256, u256*, bytesConstRef, bytesConstRef) { return h160(); } /// Make a new message call. - bool call(Address, u256, bytesConstRef, u256*, bytesRef) { return false; } + bool call(Address, u256, bytesConstRef, u256*, bytesRef, OnOpFunc const&, Address, Address) { return false; } /// Post a new message call. void post(Address _to, u256 _value, bytesConstRef _data, u256 _gas) { posts.push_back(Post({myAddress, _to, _value, _data.toBytes(), _gas})); } @@ -101,6 +103,4 @@ public: std::list posts; ///< Any posts that have been made. }; -typedef std::function OnOpFunc; - } diff --git a/libevm/VM.h b/libevm/VM.h index de2d56431..b3cdc9be1 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -166,6 +166,12 @@ template eth::bytesConstRef eth::VM::go(Ext& _ext, OnOpFunc const& _ newTempSize = std::max(memNeed(m_stack[m_stack.size() - 6], m_stack[m_stack.size() - 7]), memNeed(m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5])); break; + case Instruction::CALLSTATELESS: + require(7); + runGas = c_callGas + m_stack[m_stack.size() - 1]; + newTempSize = std::max(memNeed(m_stack[m_stack.size() - 6], m_stack[m_stack.size() - 7]), memNeed(m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5])); + break; + case Instruction::POST: require(5); runGas = c_callGas + m_stack[m_stack.size() - 1]; @@ -580,12 +586,13 @@ template eth::bytesConstRef eth::VM::go(Ext& _ext, OnOpFunc const& _ break; } case Instruction::CALL: + case Instruction::CALLSTATELESS: { require(7); u256 gas = m_stack.back(); m_stack.pop_back(); - u160 receiveAddress = asAddress(m_stack.back()); + Address receiveAddress = asAddress(m_stack.back()); m_stack.pop_back(); u256 value = m_stack.back(); m_stack.pop_back(); @@ -602,7 +609,7 @@ template eth::bytesConstRef eth::VM::go(Ext& _ext, OnOpFunc const& _ if (_ext.balance(_ext.myAddress) >= value) { _ext.subBalance(value); - m_stack.push_back(_ext.call(receiveAddress, value, bytesConstRef(m_temp.data() + inOff, inSize), &gas, bytesRef(m_temp.data() + outOff, outSize), _onOp)); + m_stack.push_back(_ext.call(receiveAddress, value, bytesConstRef(m_temp.data() + inOff, inSize), &gas, bytesRef(m_temp.data() + outOff, outSize), _onOp, Address(), inst == Instruction::CALL ? receiveAddress : _ext.myAddress)); } else m_stack.push_back(0); diff --git a/libevmface/Instruction.cpp b/libevmface/Instruction.cpp index 2ef5981c0..734dc7792 100644 --- a/libevmface/Instruction.cpp +++ b/libevmface/Instruction.cpp @@ -144,6 +144,7 @@ const std::map eth::c_instructions = { "SWAP16", Instruction::SWAP16 }, { "CREATE", Instruction::CREATE }, { "CALL", Instruction::CALL }, + { "CALLSTATELESS", Instruction::CALLSTATELESS }, { "RETURN", Instruction::RETURN }, { "POST", Instruction::POST }, { "SUICIDE", Instruction::SUICIDE } @@ -268,6 +269,7 @@ static const std::map c_instructionInfo = { Instruction::SWAP16, { "SWAP16", 0, 17, 17 } }, { Instruction::CREATE, { "CREATE", 0, 3, 1 } }, { Instruction::CALL, { "CALL", 0, 7, 1 } }, + { Instruction::CALLSTATELESS, { "CALLSTATELESS",0, 7, 1 } }, { Instruction::RETURN, { "RETURN", 0, 2, 0 } }, { Instruction::POST, { "POST", 0, 5, 0 } }, { Instruction::SUICIDE, { "SUICIDE", 0, 1, 0} } diff --git a/libevmface/Instruction.h b/libevmface/Instruction.h index e1cefe7e4..ca65d4bbe 100644 --- a/libevmface/Instruction.h +++ b/libevmface/Instruction.h @@ -163,6 +163,7 @@ enum class Instruction: uint8_t CALL, RETURN, POST, + CALLSTATELESS, SUICIDE = 0xff }; diff --git a/test/vm.cpp b/test/vm.cpp index e54967a59..0647849a0 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -80,7 +80,7 @@ public: return na; } - bool call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256* _gas, bytesRef _out, OnOpFunc) + bool call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256* _gas, bytesRef _out, OnOpFunc, Address, Address) { /* if (get<0>(addresses[myAddress]) >= _value) {