From aa845c05591a756300bbf28f3b6c0dd57b75854f Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 11 Mar 2014 23:19:38 -0700 Subject: [PATCH] Non-compiling instruction changes. --- libethereum/Instruction.cpp | 112 ++++++++-------- libethereum/Instruction.h | 52 ++++---- libethereum/VM.h | 255 +++++------------------------------- 3 files changed, 114 insertions(+), 305 deletions(-) diff --git a/libethereum/Instruction.cpp b/libethereum/Instruction.cpp index 55371bbd6..ce20b0da3 100644 --- a/libethereum/Instruction.cpp +++ b/libethereum/Instruction.cpp @@ -41,45 +41,42 @@ const std::map eth::c_instructions = { "EXP", Instruction::EXP }, { "NEG", Instruction::NEG }, { "LT", Instruction::LT }, - { "LE", Instruction::LE }, { "GT", Instruction::GT }, - { "GE", Instruction::GE }, { "EQ", Instruction::EQ }, { "NOT", Instruction::NOT }, - { "MYADDRESS", Instruction::MYADDRESS }, - { "TXSENDER", Instruction::TXSENDER }, - { "TXVALUE", Instruction::TXVALUE }, - { "TXDATAN", Instruction::TXDATAN }, - { "TXDATA", Instruction::TXDATA }, - { "BLK_PREVHASH", Instruction::BLK_PREVHASH }, - { "BLK_COINBASE", Instruction::BLK_COINBASE }, - { "BLK_TIMESTAMP", Instruction::BLK_TIMESTAMP }, - { "BLK_NUMBER", Instruction::BLK_NUMBER }, - { "BLK_DIFFICULTY", Instruction::BLK_DIFFICULTY }, - { "BLK_NONCE", Instruction::BLK_NONCE }, - { "BASEFEE", Instruction::BASEFEE }, - { "SHA256", Instruction::SHA256 }, - { "RIPEMD160", Instruction::RIPEMD160 }, - { "ECMUL", Instruction::ECMUL }, - { "ECADD", Instruction::ECADD }, - { "ECSIGN", Instruction::ECSIGN }, - { "ECRECOVER", Instruction::ECRECOVER }, - { "ECVALID", Instruction::ECVALID }, + { "ROTATE", Instruction::ROTATE }, + { "AND", Instruction::AND }, + { "OR", Instruction::OR }, + { "XOR", Instruction::XOR }, { "SHA3", Instruction::SHA3 }, + { "ADDRESS", Instruction::ADDRESS }, + { "BALANCE", Instruction::BALANCE }, + { "ORIGIN", Instruction::ORIGIN }, + { "CALLER", Instruction::CALLER }, + { "CALLVALUE", Instruction::CALLVALUE }, + { "CALLDATA", Instruction::CALLDATA }, + { "CALLDATASIZE", Instruction::CALLDATASIZE }, + { "BASEFEE", Instruction::BASEFEE }, + { "PREVHASH", Instruction::PREVHASH }, + { "PREVNONCE", Instruction::PREVNONCE }, + { "COINBASE", Instruction::COINBASE }, + { "TIMESTAMP", Instruction::TIMESTAMP }, + { "NUMBER", Instruction::NUMBER }, + { "DIFFICULTY", Instruction::DIFFICULTY }, { "PUSH", Instruction::PUSH }, { "POP", Instruction::POP }, { "DUP", Instruction::DUP }, { "SWAP", Instruction::SWAP }, { "MLOAD", Instruction::MLOAD }, { "MSTORE", Instruction::MSTORE }, + { "MSTORE8", Instruction::MSTORE8 }, { "SLOAD", Instruction::SLOAD }, { "SSTORE", Instruction::SSTORE }, - { "JMP", Instruction::JMP }, - { "JMPI", Instruction::JMPI }, - { "IND", Instruction::IND }, - { "EXTRO", Instruction::EXTRO }, - { "BALANCE", Instruction::BALANCE }, - { "MKTX", Instruction::MKTX }, + { "JUMP", Instruction::JUMP }, + { "JUMPI", Instruction::JUMPI }, + { "PC", Instruction::PC }, + { "CALL", Instruction::CALL }, + { "RETURN", Instruction::RETURN }, { "SUICIDE", Instruction::SUICIDE } }; @@ -96,45 +93,42 @@ const std::map eth::c_instructionInfo = { Instruction::EXP, { "EXP", 0, 2, 1 } }, { Instruction::NEG, { "NEG", 0, 1, 1 } }, { Instruction::LT, { "LT", 0, 2, 1 } }, - { Instruction::LE, { "LE", 0, 2, 1 } }, { Instruction::GT, { "GT", 0, 2, 1 } }, - { Instruction::GE, { "GE", 0, 2, 1 } }, { Instruction::EQ, { "EQ", 0, 2, 1 } }, { Instruction::NOT, { "NOT", 0, 1, 1 } }, - { Instruction::MYADDRESS, { "MYADDRESS", 0, 0, 1 } }, - { Instruction::TXSENDER, { "TXSENDER", 0, 0, 1 } }, - { Instruction::TXVALUE, { "TXVALUE", 0, 0, 1 } }, - { Instruction::TXDATAN, { "TXDATAN", 0, 0, 1 } }, - { Instruction::TXDATA, { "TXDATA", 0, 1, 1 } }, - { Instruction::BLK_PREVHASH, { "BLK_PREVHASH", 0, 0, 1 } }, - { Instruction::BLK_COINBASE, { "BLK_COINBASE", 0, 0, 1 } }, - { Instruction::BLK_TIMESTAMP, { "BLK_TIMESTAMP", 0, 0, 1 } }, - { Instruction::BLK_NUMBER, { "BLK_NUMBER", 0, 0, 1 } }, - { Instruction::BLK_DIFFICULTY, { "BLK_DIFFICULTY", 0, 0, 1 } }, - { Instruction::BLK_NONCE, { "BLK_NONCE", 0, 0, 1 } }, + { Instruction::ROTATE, { "ROTATE", 0, 2, 1 } }, + { Instruction::ADD, { "ADD", 0, 2, 1 } }, + { Instruction::OR, { "OR", 0, 2, 1 } }, + { Instruction::XOR, { "XOR", 0, 2, 1 } }, + { Instruction::SHA3, { "SHA3", 0, 2, 1 } }, + { Instruction::ADDRESS, { "ADDRESS", 0, 0, 1 } }, + { Instruction::BALANCE, { "BALANCE", 0, 1, 1 } }, + { Instruction::ORIGIN, { "ORIGIN", 0, 1, 1 } }, + { Instruction::CALLER, { "CALLER", 0, 0, 1 } }, + { Instruction::CALLVALUE, { "CALLVALUE", 0, 0, 1 } }, + { Instruction::CALLDATA, { "CALLDATA", 0, 0, 1 } }, + { Instruction::CALLDATASIZE, { "CALLDATASIZE", 0, 1, 1 } }, { Instruction::BASEFEE, { "BASEFEE", 0, 0, 1 } }, - { Instruction::SHA256, { "SHA256", 0, -1, 1 } }, - { Instruction::RIPEMD160, { "RIPEMD160", 0, -1, 1 } }, - { Instruction::ECMUL, { "ECMUL", 0, 3, 2 } }, - { Instruction::ECADD, { "ECADD", 0, 4, 2 } }, - { Instruction::ECSIGN, { "ECSIGN", 0, 2, 3 } }, - { Instruction::ECRECOVER, { "ECRECOVER", 0, 4, 2 } }, - { Instruction::ECVALID, { "ECVALID", 0, 2, 1 } }, - { Instruction::SHA3, { "SHA3", 0, -1, 1 } }, + { Instruction::PREVHASH, { "PREVHASH", 0, 0, 1 } }, + { Instruction::PREVNONCE, { "PREVNONCE", 0, 0, 1 } }, + { Instruction::COINBASE, { "COINBASE", 0, 0, 1 } }, + { Instruction::TIMESTAMP, { "TIMESTAMP", 0, 0, 1 } }, + { Instruction::NUMBER, { "NUMBER", 0, 0, 1 } }, + { Instruction::DIFFICULTY, { "DIFFICULTY", 0, 0, 1 } }, { Instruction::PUSH, { "PUSH", 1, 0, 1 } }, { Instruction::POP, { "POP", 0, 1, 0 } }, { Instruction::DUP, { "DUP", 0, 1, 2 } }, { Instruction::SWAP, { "SWAP", 0, 2, 2 } }, { Instruction::MLOAD, { "MLOAD", 0, 1, 1 } }, { Instruction::MSTORE, { "MSTORE", 0, 2, 0 } }, + { Instruction::MSTORE8, { "MSTORE8", 0, 2, 0 } }, { Instruction::SLOAD, { "SLOAD", 0, 1, 1 } }, { Instruction::SSTORE, { "SSTORE", 0, 2, 0 } }, - { Instruction::JMP, { "JMP", 0, 1, 0 } }, - { Instruction::JMPI, { "JMPI", 0, 2, 0 } }, - { Instruction::IND, { "IND", 0, 0, 1 } }, - { Instruction::EXTRO, { "EXTRO", 0, 2, 1 } }, - { Instruction::BALANCE, { "BALANCE", 0, 1, 1 } }, - { Instruction::MKTX, { "MKTX", 0, -3, 0 } }, + { Instruction::JUMP, { "JUMP", 0, 1, 0 } }, + { Instruction::JUMPI, { "JUMPI", 0, 2, 0 } }, + { Instruction::PC, { "PC", 0, 0, 1 } }, + { Instruction::CALL, { "CALL", 0, 6, 1 } }, + { Instruction::RETURN, { "RETURN", 0, 2, 0 } }, { Instruction::SUICIDE, { "SUICIDE", 0, 1, 0} } }; @@ -251,7 +245,7 @@ static void appendCode(u256s& o_code, vector& o_locs, u256s _code, vec static int compileLispFragment(char const*& d, char const* e, bool _quiet, u256s& o_code, vector& o_locs) { std::map const c_arith = { { "+", Instruction::ADD }, { "-", Instruction::SUB }, { "*", Instruction::MUL }, { "/", Instruction::DIV }, { "%", Instruction::MOD } }; - std::map const c_binary = { { "<", Instruction::LT }, { "<=", Instruction::LE }, { ">", Instruction::GT }, { ">=", Instruction::GE }, { "=", Instruction::EQ }, { "!=", Instruction::NOT } }; + std::map> const c_binary = { { "<", { Instruction::LT, false } }, { "<=", { Instruction::GT, true } }, { ">", { Instruction::GT, false } }, { ">=", { Instruction::LT, true } }, { "=", { Instruction::EQ, false } }, { "!=", { Instruction::EQ, true } } }; std::map const c_unary = { { "!", Instruction::NOT } }; std::set const c_allowed = { '+', '-', '*', '/', '%', '<', '>', '=', '!' }; @@ -733,11 +727,11 @@ static int compileLispFragment(char const*& d, char const* e, bool _quiet, u256s cwarn << "Expected two arguments to binary operator" << t << "; got" << totalArgs << "."; break; } - for (auto it = codes.rbegin(); it != codes.rend(); ++it) - appendCode(o_code, o_locs, it->first, it->second); - if (it->second == Instruction::NOT) + for (auto jt = codes.rbegin(); jt != codes.rend(); ++jt) + appendCode(o_code, o_locs, jt->first, jt->second); + if (it->second.second) o_code.push_back(Instruction::EQ); - o_code.push_back((u256)it->second); + o_code.push_back((u256)it->second.first); } else { diff --git a/libethereum/Instruction.h b/libethereum/Instruction.h index dbc46db27..1dbe40781 100644 --- a/libethereum/Instruction.h +++ b/libethereum/Instruction.h @@ -42,45 +42,43 @@ enum class Instruction: uint8_t EXP, NEG, LT, - LE, GT, - GE, EQ, NOT, - MYADDRESS, ///< pushes the transaction sender - TXSENDER, ///< pushes the transaction sender - TXVALUE , ///< pushes the transaction value - TXDATAN, ///< pushes the number of data items - TXDATA, ///< pops one item and pushes data item S[-1], or zero if index out of range - BLK_PREVHASH, ///< pushes the hash of the previous block (NOT the current one since that's impossible!) - BLK_COINBASE, ///< pushes the coinbase of the current block - BLK_TIMESTAMP, ///< pushes the timestamp of the current block - BLK_NUMBER, ///< pushes the current block number - BLK_DIFFICULTY, ///< pushes the difficulty of the current block - BLK_NONCE, - BASEFEE, - SHA256 = 0x20, - RIPEMD160, - ECMUL, - ECADD, - ECSIGN, - ECRECOVER, - ECVALID, + ROTATE, + AND, + OR, + XOR, SHA3, + ADDRESS = 0x20, ///< pushes the transaction sender + BALANCE, + ORIGIN, ///< pushes the transaction sender + CALLER, ///< pushes the transaction sender + CALLVALUE, ///< pushes the transaction value + CALLDATA, ///< pushes the transaction value + CALLDATASIZE, ///< pushes the transaction value + BASEFEE, + MEMSIZE, + PREVHASH, ///< pushes the hash of the previous block (NOT the current one since that's impossible!) + PREVNONCE, + COINBASE, ///< pushes the coinbase of the current block + TIMESTAMP, ///< pushes the timestamp of the current block + NUMBER, ///< pushes the current block number + DIFFICULTY, ///< pushes the difficulty of the current block PUSH = 0x30, POP, DUP, SWAP, MLOAD, MSTORE, + MSTORE8, SLOAD, SSTORE, - JMP, - JMPI, - IND, - EXTRO, - BALANCE, - MKTX, + JUMP, + JUMPI, + PC, + CALL, + RETURN, SUICIDE = 0x3f }; diff --git a/libethereum/VM.h b/libethereum/VM.h index 8b0f120dd..24a3d3e8c 100644 --- a/libethereum/VM.h +++ b/libethereum/VM.h @@ -103,24 +103,14 @@ template void eth::VM::go(Ext& _ext, uint64_t _steps) runFee += _ext.fees.m_dataFee; break; - case Instruction::EXTRO: case Instruction::BALANCE: runFee += _ext.fees.m_extroFee; break; - case Instruction::MKTX: + case Instruction::CALL: runFee += _ext.fees.m_txFee; break; - case Instruction::SHA256: - case Instruction::RIPEMD160: - case Instruction::ECMUL: - case Instruction::ECADD: - case Instruction::ECSIGN: - case Instruction::ECRECOVER: - case Instruction::ECVALID: - runFee += _ext.fees.m_cryptoFee; - break; default: break; } @@ -196,21 +186,11 @@ template void eth::VM::go(Ext& _ext, uint64_t _steps) m_stack[m_stack.size() - 2] = m_stack.back() < m_stack[m_stack.size() - 2] ? 1 : 0; m_stack.pop_back(); break; - case Instruction::LE: - require(2); - m_stack[m_stack.size() - 2] = m_stack.back() <= m_stack[m_stack.size() - 2] ? 1 : 0; - m_stack.pop_back(); - break; case Instruction::GT: require(2); m_stack[m_stack.size() - 2] = m_stack.back() > m_stack[m_stack.size() - 2] ? 1 : 0; m_stack.pop_back(); break; - case Instruction::GE: - require(2); - m_stack[m_stack.size() - 2] = m_stack.back() >= m_stack[m_stack.size() - 2] ? 1 : 0; - m_stack.pop_back(); - break; case Instruction::EQ: require(2); m_stack[m_stack.size() - 2] = m_stack.back() == m_stack[m_stack.size() - 2] ? 1 : 0; @@ -220,50 +200,13 @@ template void eth::VM::go(Ext& _ext, uint64_t _steps) require(1); m_stack.back() = m_stack.back() ? 0 : 1; break; - case Instruction::MYADDRESS: - m_stack.push_back(fromAddress(_ext.myAddress)); - break; - case Instruction::TXSENDER: - m_stack.push_back(fromAddress(_ext.txSender)); - break; - case Instruction::TXVALUE: - m_stack.push_back(_ext.txValue); - break; - case Instruction::TXDATAN: - m_stack.push_back(_ext.txData.size()); - break; - case Instruction::TXDATA: - require(1); - m_stack.back() = m_stack.back() < _ext.txData.size() ? _ext.txData[(uint)m_stack.back()] : 0; - break; - case Instruction::BLK_PREVHASH: - m_stack.push_back(_ext.previousBlock.hash); - break; - case Instruction::BLK_COINBASE: - m_stack.push_back((u160)_ext.currentBlock.coinbaseAddress); - break; - case Instruction::BLK_TIMESTAMP: - m_stack.push_back(_ext.currentBlock.timestamp); - break; - case Instruction::BLK_NUMBER: - m_stack.push_back(_ext.currentNumber); - break; - case Instruction::BLK_DIFFICULTY: - m_stack.push_back(_ext.currentBlock.difficulty); - break; - case Instruction::BLK_NONCE: - m_stack.push_back(_ext.previousBlock.nonce); - break; - case Instruction::BASEFEE: - m_stack.push_back(_ext.fees.multiplier()); - break; - case Instruction::SHA256: + case Instruction::SHA3: { require(1); uint s = (uint)std::min(m_stack.back(), (u256)(m_stack.size() - 1) * 32); m_stack.pop_back(); - CryptoPP::SHA256 digest; + CryptoPP::SHA3_256 digest; uint i = 0; for (; s; s = (s >= 32 ? s - 32 : 0), i += 32) { @@ -276,163 +219,46 @@ template void eth::VM::go(Ext& _ext, uint64_t _steps) m_stack.push_back(fromBigEndian(final)); break; } - case Instruction::RIPEMD160: - { - require(1); - uint s = (uint)std::min(m_stack.back(), (u256)(m_stack.size() - 1) * 32); - m_stack.pop_back(); - - CryptoPP::RIPEMD160 digest; - uint i = 0; - for (; s; s = (s >= 32 ? s - 32 : 0), i += 32) - { - bytes b = toBigEndian(m_stack.back()); - digest.Update(b.data(), (int)std::min(32, s)); // b.size() == 32 - m_stack.pop_back(); - } - std::array final; - digest.TruncatedFinal(final.data(), 20); - // NOTE: this aligns to right of 256-bit container (low-order bytes). - // This won't work if they're treated as byte-arrays and thus left-aligned in a 256-bit container. - m_stack.push_back((u256)fromBigEndian(final)); + case Instruction::ADDRESS: + m_stack.push_back(fromAddress(_ext.myAddress)); break; - } - case Instruction::ECMUL: - { - // ECMUL - pops three items. - // If (S[-2],S[-1]) are a valid point in secp256k1, including both coordinates being less than P, pushes (S[-1],S[-2]) * S[-3], using (0,0) as the point at infinity. - // Otherwise, pushes (0,0). - require(3); - - bytes pub(1, 4); - pub += toBigEndian(m_stack[m_stack.size() - 2]); - pub += toBigEndian(m_stack.back()); - m_stack.pop_back(); - m_stack.pop_back(); - - bytes x = toBigEndian(m_stack.back()); - m_stack.pop_back(); - - if (secp256k1_ecdsa_pubkey_verify(pub.data(), (int)pub.size())) // TODO: Check both are less than P. - { - secp256k1_ecdsa_pubkey_tweak_mul(pub.data(), (int)pub.size(), x.data()); - m_stack.push_back(fromBigEndian(bytesConstRef(&pub).cropped(1, 32))); - m_stack.push_back(fromBigEndian(bytesConstRef(&pub).cropped(33, 32))); - } - else - { - m_stack.push_back(0); - m_stack.push_back(0); - } + case Instruction::ORIGIN: + // TODO properly + m_stack.push_back(fromAddress(_ext.txSender)); break; - } - case Instruction::ECADD: - { - // ECADD - pops four items and pushes (S[-4],S[-3]) + (S[-2],S[-1]) if both points are valid, otherwise (0,0). - require(4); - - bytes pub(1, 4); - pub += toBigEndian(m_stack[m_stack.size() - 2]); - pub += toBigEndian(m_stack.back()); - m_stack.pop_back(); - m_stack.pop_back(); - - bytes tweak(1, 4); - tweak += toBigEndian(m_stack[m_stack.size() - 2]); - tweak += toBigEndian(m_stack.back()); - m_stack.pop_back(); - m_stack.pop_back(); - - if (secp256k1_ecdsa_pubkey_verify(pub.data(),(int) pub.size()) && secp256k1_ecdsa_pubkey_verify(tweak.data(),(int) tweak.size())) - { - secp256k1_ecdsa_pubkey_tweak_add(pub.data(), (int)pub.size(), tweak.data()); - m_stack.push_back(fromBigEndian(bytesConstRef(&pub).cropped(1, 32))); - m_stack.push_back(fromBigEndian(bytesConstRef(&pub).cropped(33, 32))); - } - else - { - m_stack.push_back(0); - m_stack.push_back(0); - } + case Instruction::CALLER: + m_stack.push_back(fromAddress(_ext.txSender)); break; - } - case Instruction::ECSIGN: - { - require(2); - bytes sig(64); - int v = 0; - - u256 msg = m_stack.back(); - m_stack.pop_back(); - u256 priv = m_stack.back(); - m_stack.pop_back(); - bytes nonce = toBigEndian(Transaction::kFromMessage(msg, priv)); - - if (!secp256k1_ecdsa_sign_compact(toBigEndian(msg).data(), 64, sig.data(), toBigEndian(priv).data(), nonce.data(), &v)) - throw InvalidSignature(); - - m_stack.push_back(v + 27); - m_stack.push_back(fromBigEndian(bytesConstRef(&sig).cropped(0, 32))); - m_stack.push_back(fromBigEndian(bytesConstRef(&sig).cropped(32))); + case Instruction::CALLVALUE: + m_stack.push_back(_ext.txValue); break; - } - case Instruction::ECRECOVER: - { - require(4); - - bytes sig = toBigEndian(m_stack[m_stack.size() - 2]) + toBigEndian(m_stack.back()); - m_stack.pop_back(); - m_stack.pop_back(); - int v = (int)m_stack.back(); - m_stack.pop_back(); - bytes msg = toBigEndian(m_stack.back()); - m_stack.pop_back(); - - byte pubkey[65]; - int pubkeylen = 65; - if (secp256k1_ecdsa_recover_compact(msg.data(), (int)msg.size(), sig.data(), pubkey, &pubkeylen, 0, v - 27)) - { - m_stack.push_back(0); - m_stack.push_back(0); - } - else - { - m_stack.push_back(fromBigEndian(bytesConstRef(&pubkey[1], 32))); - m_stack.push_back(fromBigEndian(bytesConstRef(&pubkey[33], 32))); - } + case Instruction::CALLDATA: + m_stack.push_back(_ext.txData.size()); break; - } - case Instruction::ECVALID: - { - require(2); - bytes pub(1, 4); - pub += toBigEndian(m_stack[m_stack.size() - 2]); - pub += toBigEndian(m_stack.back()); - m_stack.pop_back(); - m_stack.pop_back(); - - m_stack.back() = secp256k1_ecdsa_pubkey_verify(pub.data(), (int)pub.size()) ? 1 : 0; + case Instruction::CALLDATASIZE: + m_stack.push_back(_ext.txData.size()); break; - } - case Instruction::SHA3: - { - require(1); - uint s = (uint)std::min(m_stack.back(), (u256)(m_stack.size() - 1) * 32); - m_stack.pop_back(); - - CryptoPP::SHA3_256 digest; - uint i = 0; - for (; s; s = (s >= 32 ? s - 32 : 0), i += 32) - { - bytes b = toBigEndian(m_stack.back()); - digest.Update(b.data(), (int)std::min(32, s)); // b.size() == 32 - m_stack.pop_back(); - } - std::array final; - digest.TruncatedFinal(final.data(), 32); - m_stack.push_back(fromBigEndian(final)); + case Instruction::BASEFEE: + m_stack.push_back(_ext.fees.multiplier()); + break; + case Instruction::PREVHASH: + m_stack.push_back(_ext.previousBlock.hash); + break; + case Instruction::PREVNONCE: + m_stack.push_back(_ext.previousBlock.nonce); + break; + case Instruction::COINBASE: + m_stack.push_back((u160)_ext.currentBlock.coinbaseAddress); + break; + case Instruction::TIMESTAMP: + m_stack.push_back(_ext.currentBlock.timestamp); + break; + case Instruction::NUMBER: + m_stack.push_back(_ext.currentNumber); + break; + case Instruction::DIFFICULTY: + m_stack.push_back(_ext.currentBlock.difficulty); break; - } case Instruction::PUSH: { m_stack.push_back(_ext.store(m_curPC + 1)); @@ -531,15 +357,6 @@ template void eth::VM::go(Ext& _ext, uint64_t _steps) case Instruction::IND: m_stack.push_back(m_curPC); break; - case Instruction::EXTRO: - { - require(2); - auto memoryAddress = m_stack.back(); - m_stack.pop_back(); - Address contractAddress = asAddress(m_stack.back()); - m_stack.back() = _ext.extro(contractAddress, memoryAddress); - break; - } case Instruction::BALANCE: { require(1);