From a37d62f602f084089a8da4b0b172c06e2ce53b9b Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 3 Sep 2014 22:26:37 +0200 Subject: [PATCH] EXTCODECOPY/SIZE. --- libethereum/ExtVM.h | 3 +++ libevm/ExtVMFace.h | 3 +++ libevm/VM.h | 20 ++++++++++++++++++++ libevmface/Instruction.cpp | 4 ++++ libevmface/Instruction.h | 2 ++ 5 files changed, 32 insertions(+) diff --git a/libethereum/ExtVM.h b/libethereum/ExtVM.h index 48099b8fc..f3d8bee50 100644 --- a/libethereum/ExtVM.h +++ b/libethereum/ExtVM.h @@ -49,6 +49,9 @@ public: /// Write a value in storage. void setStore(u256 _n, u256 _v) { m_s.setStorage(myAddress, _n, _v); if (m_ms) m_ms->altered.push_back(_n); } + /// Read address's code. + bytes const& codeAt(Address _a) { return m_s.code(_a); } + /// Create a new contract. h160 create(u256 _endowment, u256* _gas, bytesConstRef _code, OnOpFunc const& _onOp = OnOpFunc()) { diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h index 54bb86ae7..2c32c74f4 100644 --- a/libevm/ExtVMFace.h +++ b/libevm/ExtVMFace.h @@ -66,6 +66,9 @@ public: /// Read address's balance. u256 balance(Address) { return 0; } + /// Read address's code. + bytes const& codeAt(Address) { return NullBytes; } + /// Subtract amount from account's balance. void subBalance(u256) {} diff --git a/libevm/VM.h b/libevm/VM.h index b3cdc9be1..76b68a11c 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -401,6 +401,26 @@ template eth::bytesConstRef eth::VM::go(Ext& _ext, OnOpFunc const& _ memset(m_temp.data() + mf + el, 0, l - el); break; } + case Instruction::EXTCODESIZE: + require(1); + m_stack.back() = _ext.codeAt(asAddress(m_stack.back())).size(); + break; + case Instruction::EXTCODECOPY: + { + require(4); + Address a = asAddress(m_stack.back()); + m_stack.pop_back(); + unsigned mf = (unsigned)m_stack.back(); + m_stack.pop_back(); + unsigned cf = (unsigned)m_stack.back(); + m_stack.pop_back(); + unsigned l = (unsigned)m_stack.back(); + m_stack.pop_back(); + unsigned el = cf + l > _ext.codeAt(a).size() ? _ext.codeAt(a).size() < cf ? 0 : _ext.codeAt(a).size() - cf : l; + memcpy(m_temp.data() + mf, _ext.codeAt(a).data() + cf, el); + memset(m_temp.data() + mf + el, 0, l - el); + break; + } case Instruction::GASPRICE: m_stack.push_back(_ext.gasPrice); break; diff --git a/libevmface/Instruction.cpp b/libevmface/Instruction.cpp index 734dc7792..7d6fdd366 100644 --- a/libevmface/Instruction.cpp +++ b/libevmface/Instruction.cpp @@ -61,6 +61,8 @@ const std::map eth::c_instructions = { "CODESIZE", Instruction::CODESIZE }, { "CODECOPY", Instruction::CODECOPY }, { "GASPRICE", Instruction::GASPRICE }, + { "EXTCODESIZE", Instruction::EXTCODESIZE }, + { "EXTCODECOPY", Instruction::EXTCODECOPY }, { "PREVHASH", Instruction::PREVHASH }, { "COINBASE", Instruction::COINBASE }, { "TIMESTAMP", Instruction::TIMESTAMP }, @@ -186,6 +188,8 @@ static const std::map c_instructionInfo = { Instruction::CODESIZE, { "CODESIZE", 0, 0, 1 } }, { Instruction::CODECOPY, { "CODECOPY", 0, 3, 0 } }, { Instruction::GASPRICE, { "GASPRICE", 0, 0, 1 } }, + { Instruction::EXTCODESIZE, { "EXTCODESIZE", 0, 1, 1 } }, + { Instruction::EXTCODECOPY, { "EXTCODECOPY", 0, 4, 0 } }, { Instruction::PREVHASH, { "PREVHASH", 0, 0, 1 } }, { Instruction::COINBASE, { "COINBASE", 0, 0, 1 } }, { Instruction::TIMESTAMP, { "TIMESTAMP", 0, 0, 1 } }, diff --git a/libevmface/Instruction.h b/libevmface/Instruction.h index ca65d4bbe..1af42bada 100644 --- a/libevmface/Instruction.h +++ b/libevmface/Instruction.h @@ -72,6 +72,8 @@ enum class Instruction: uint8_t CODESIZE, CODECOPY, GASPRICE, + EXTCODESIZE, + EXTCODECOPY, PREVHASH = 0x40, COINBASE,