From 5aba1ea0961017403d0b2e101c1d97b0a988e7e8 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 30 Jun 2014 11:49:52 +0200 Subject: [PATCH 1/2] Docs & consolidation of headers. --- libethcore/All.h | 12 ++++++++++++ libethential/All.h | 8 ++++++++ libethereum/All.h | 14 ++++++++++++++ libethereum/Client.h | 31 +++++++++++++++++++++++------- libethereum/ExtVM.h | 39 +++++++++++++++++++++----------------- libevm/ExtVMFace.h | 10 ++++++---- liblll/All.h | 7 +++++++ libpyserpent/pyserpent.cpp | 4 ++-- libserpent/All.h | 9 +++++++++ 9 files changed, 104 insertions(+), 30 deletions(-) create mode 100644 libethcore/All.h create mode 100644 libethential/All.h create mode 100644 libethereum/All.h create mode 100644 liblll/All.h create mode 100644 libserpent/All.h diff --git a/libethcore/All.h b/libethcore/All.h new file mode 100644 index 000000000..9cd9b72ee --- /dev/null +++ b/libethcore/All.h @@ -0,0 +1,12 @@ +#pragma once + +#include "BlockInfo.h" +#include "CommonEth.h" +#include "Dagger.h" +#include "FileSystem.h" +#include "MemoryDB.h" +#include "OverlayDB.h" +#include "SHA3.h" +#include "TrieCommon.h" +#include "TrieDB.h" +#include "UPnP.h" diff --git a/libethential/All.h b/libethential/All.h new file mode 100644 index 000000000..eac152d42 --- /dev/null +++ b/libethential/All.h @@ -0,0 +1,8 @@ +#pragma once + +#include "Common.h" +#include "CommonData.h" +#include "CommonIO.h" +#include "FixedHash.h" +#include "Log.h" +#include "RLP.h" diff --git a/libethereum/All.h b/libethereum/All.h new file mode 100644 index 000000000..adc7fedb4 --- /dev/null +++ b/libethereum/All.h @@ -0,0 +1,14 @@ +#pragma once + +#include "AddressState.h" +#include "BlockChain.h" +#include "Client.h" +#include "Defaults.h" +#include "Executive.h" +#include "ExtVM.h" +#include "PeerNetwork.h" +#include "PeerServer.h" +#include "PeerSession.h" +#include "State.h" +#include "Transaction.h" +#include "TransactionQueue.h" diff --git a/libethereum/Client.h b/libethereum/Client.h index 24a9670b8..cf5235c8c 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -77,6 +77,9 @@ private: unsigned m_protocolVersion; }; +/** + * @brief Main API hub for interfacing with Ethereum. + */ class Client { public: @@ -114,24 +117,38 @@ public: /// Calls @a _f when a transaction is mined that involves @a _dest and once per change. // void onConfirmed(Address _dest, function const& _f); - // Informational stuff: - - /// Locks/unlocks the state/blockChain/transactionQueue for access. - void lock(); - void unlock(); + // Informational stuff /// Determines whether at least one of the state/blockChain/transactionQueue has changed since the last call to changed(). bool changed() const { auto ret = m_changed; m_changed = false; return ret; } bool peekChanged() const { return m_changed; } + /// Get a map containing each of the pending transactions. + Transactions pending() const { return m_postMine.pending(); } + + // [OLD API]: + + /// Locks/unlocks the state/blockChain/transactionQueue for access. + void lock(); + void unlock(); + /// Get the object representing the current state of Ethereum. State const& state() const { return m_preMine; } /// Get the object representing the current state of Ethereum. State const& postState() const { return m_postMine; } /// Get the object representing the current canonical blockchain. BlockChain const& blockChain() const { return m_bc; } - /// Get a map containing each of the pending transactions. - Transactions pending() const { return m_postMine.pending(); } + + // [NEW API] +/* + u256 balanceAt(Address _a, unsigned _age = 1) const; + u256 countAt(Address _a, unsigned _age = 1) const; + u256 stateAt(Address _a, u256 _l, unsigned _age = 1) const; + bytes codeAt(Address _a, unsigned _age = 1) const; + + Transactions transactions(Addresses const& _from, Addresses const& _to, std::vector> const& _stateAlterations, Addresses const& _altered, unsigned _ageFrom = 0, unsigned _ageTo, unsigned _max) const; +*/ + // Misc stuff: void setClientVersion(std::string const& _name) { m_clientVersion = _name; } diff --git a/libethereum/ExtVM.h b/libethereum/ExtVM.h index 7b2c4e3db..b0edf2e4d 100644 --- a/libethereum/ExtVM.h +++ b/libethereum/ExtVM.h @@ -29,56 +29,61 @@ namespace eth { -// TODO: Document +/** + * @brief Externalality interface for the Virtual Machine providing access to world state. + */ class ExtVM: public ExtVMFace { public: + /// Full constructor. ExtVM(State& _s, Address _myAddress, Address _caller, Address _origin, u256 _value, u256 _gasPrice, bytesConstRef _data, bytesConstRef _code): ExtVMFace(_myAddress, _caller, _origin, _value, _gasPrice, _data, _code, _s.m_previousBlock, _s.m_currentBlock), m_s(_s), m_origCache(_s.m_cache) { m_s.ensureCached(_myAddress, true, true); } - u256 store(u256 _n) - { - return m_s.storage(myAddress, _n); - } - void setStore(u256 _n, u256 _v) - { - m_s.setStorage(myAddress, _n, _v); - } + /// Read storage location. + u256 store(u256 _n) { return m_s.storage(myAddress, _n); } + + /// Write a value in storage. + void setStore(u256 _n, u256 _v) { m_s.setStorage(myAddress, _n, _v); } + /// Create a new contract. h160 create(u256 _endowment, u256* _gas, bytesConstRef _code) { // Increment associated nonce for sender. m_s.noteSending(myAddress); - return m_s.create(myAddress, _endowment, gasPrice, _gas, _code, origin); } + /// Create a new message call. bool call(Address _receiveAddress, u256 _txValue, bytesConstRef _txData, u256* _gas, bytesRef _out) { return m_s.call(_receiveAddress, myAddress, _txValue, gasPrice, _txData, _gas, _out, origin); } + /// Read address's balance. u256 balance(Address _a) { return m_s.balance(_a); } + + /// Subtract amount from account's balance. void subBalance(u256 _a) { m_s.subBalance(myAddress, _a); } + + /// Determine account's TX count. u256 txCount(Address _a) { return m_s.transactionsFrom(_a); } + + /// Suicide the associated contract to the given address. void suicide(Address _a) { m_s.addBalance(_a, m_s.balance(myAddress)); m_s.m_cache[myAddress].kill(); } - void revert() - { - m_s.m_cache = m_origCache; - } + /// Revert any changes made (by any of the other calls). + void revert() { m_s.m_cache = m_origCache; } private: - State& m_s; - std::map m_origCache; - std::map* m_store; + State& m_s; ///< A reference to the base state. + std::map m_origCache; ///< The cache of the address states (i.e. the externalities) as-was prior to the execution. }; } diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h index 88817aea8..3e5a80580 100644 --- a/libevm/ExtVMFace.h +++ b/libevm/ExtVMFace.h @@ -40,7 +40,6 @@ public: /// Full constructor. ExtVMFace(Address _myAddress, Address _caller, Address _origin, u256 _value, u256 _gasPrice, bytesConstRef _data, bytesConstRef _code, BlockInfo const& _previousBlock, BlockInfo const& _currentBlock); - /// Get the code at the given location in code ROM. byte getCode(u256 _n) const { return _n < code.size() ? code[(unsigned)_n] : 0; } @@ -53,21 +52,24 @@ public: /// Read address's balance. u256 balance(Address) { return 0; } - /// Subtract amount from address's balance. + /// Subtract amount from account's balance. void subBalance(u256) {} - /// Determine address's TX count. + /// Determine account's TX count. u256 txCount(Address) { return 0; } /// Suicide the associated contract to the given address. void suicide(Address) {} - /// Create a new contract. + /// Create a new (contract) account. h160 create(u256, u256*, bytesConstRef, bytesConstRef) { return h160(); } /// Make a new message call. bool call(Address, u256, bytesConstRef, u256*, bytesRef) { return false; } + /// Revert any changes made (by any of the other calls). + void revert() {} + Address myAddress; ///< Address associated with executing code (a contract, or contract-to-be). Address caller; ///< Address which sent the message (either equal to origin or a contract). Address origin; ///< Original transactor. diff --git a/liblll/All.h b/liblll/All.h new file mode 100644 index 000000000..ec6989e66 --- /dev/null +++ b/liblll/All.h @@ -0,0 +1,7 @@ +#pragma once + +#include "Assembly.h" +#include "CodeFragment.h" +#include "Compiler.h" +#include "CompilerState.h" +#include "Parser.h" diff --git a/libpyserpent/pyserpent.cpp b/libpyserpent/pyserpent.cpp index c8f5a38b9..93d9c8917 100644 --- a/libpyserpent/pyserpent.cpp +++ b/libpyserpent/pyserpent.cpp @@ -18,8 +18,8 @@ struct VecToList for(size_t i = 0; i < vec.size(); i++) (*l).append(vec[i]); - return l->ptr(); - } + return l->ptr(); + } }; // python list to std::vector converter diff --git a/libserpent/All.h b/libserpent/All.h new file mode 100644 index 000000000..55f5ee865 --- /dev/null +++ b/libserpent/All.h @@ -0,0 +1,9 @@ +#pragma once + +#include "compiler.h" +#include "funcs.h" +#include "lllparser.h" +#include "parser.h" +#include "rewriter.h" +#include "tokenize.h" +#include "util.h" From d1802c9b79969e3c9459db7ae57bdbce4783c7be Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 1 Jul 2014 00:16:01 +0200 Subject: [PATCH 2/2] Fixed problem with alloc. --- alethzero/Main.ui | 3 ++- alethzero/MainWin.cpp | 4 ++-- libethcore/TrieDB.h | 4 +++- libethential/CMakeLists.txt | 2 +- libethereum/Client.h | 13 ++++++------- libevm/All.h | 5 +++++ liblll/Assembly.cpp | 5 +++++ liblll/Assembly.h | 2 ++ liblll/CodeFragment.cpp | 39 +++++++++++++++++++++++++++++++++++-- liblll/CodeFragment.h | 7 +++++-- liblll/Compiler.cpp | 4 ++-- liblll/CompilerState.cpp | 3 +-- liblll/CompilerState.h | 1 + sc/cmdline.cpp | 2 +- 14 files changed, 73 insertions(+), 21 deletions(-) create mode 100644 libevm/All.h diff --git a/alethzero/Main.ui b/alethzero/Main.ui index a9782f8a2..3712ca489 100644 --- a/alethzero/Main.ui +++ b/alethzero/Main.ui @@ -1288,7 +1288,8 @@ font-size: 14pt background: white; border: 0; -font-family: Monospace, Ubuntu Mono, Lucida Console, Courier New +font-family: Monospace, Ubuntu Mono, Lucida Console, Courier New; +font-size: 12pt diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index a8c024454..d06d0948e 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -118,7 +118,7 @@ Main::Main(QWidget *parent) : connect(ui->ourAccounts->model(), SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)), SLOT(ourAccountsRowsMoved())); -#if ETH_DEBUG +#if 0&Ð_DEBUG m_servers.append("192.168.0.10:30301"); #else int pocnumber = QString(eth::EthVersion).section('.', 1, 1).toInt(); @@ -985,7 +985,7 @@ void Main::on_data_textChanged() { try { - m_data = eth::asBytes(compile(src)); + m_data = compile(src); for (auto& i: errors) i = "(LLL " + i + ")"; } diff --git a/libethcore/TrieDB.h b/libethcore/TrieDB.h index 023a0dc1d..c6114b95d 100644 --- a/libethcore/TrieDB.h +++ b/libethcore/TrieDB.h @@ -42,7 +42,7 @@ extern const h256 c_shaNull; /** * @brief Merkle Patricia Tree "Trie": a modifed base-16 Radix tree. - * This version uses an LDB backend + * This version uses an database backend. * Usage: * @code * GenericTrieDB t(&myDB); @@ -153,6 +153,7 @@ public: std::string at(bytesConstRef _key) const; void insert(bytesConstRef _key, bytesConstRef _value); void remove(bytesConstRef _key); + void contains(bytesConstRef _key) { return !at(_key).empty(); } class iterator { @@ -274,6 +275,7 @@ public: std::string operator[](KeyType _k) const { return at(_k); } + bool contains(KeyType _k) const { return GenericTrieDB::contains(bytesConstRef((byte const*)&_k, sizeof(KeyType))); } std::string at(KeyType _k) const { return GenericTrieDB::at(bytesConstRef((byte const*)&_k, sizeof(KeyType))); } void insert(KeyType _k, bytesConstRef _value) { GenericTrieDB::insert(bytesConstRef((byte const*)&_k, sizeof(KeyType)), _value); } void insert(KeyType _k, bytes const& _value) { insert(_k, bytesConstRef(&_value)); } diff --git a/libethential/CMakeLists.txt b/libethential/CMakeLists.txt index c81c2c8f1..e247abcd0 100644 --- a/libethential/CMakeLists.txt +++ b/libethential/CMakeLists.txt @@ -1,4 +1,5 @@ cmake_policy(SET CMP0015 NEW) +cmake_policy(SET CMP0022 NEW) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") @@ -16,7 +17,6 @@ include_directories(..) target_link_libraries(${EXECUTABLE} ethential) target_link_libraries(${EXECUTABLE} gmp) - if(${TARGET_PLATFORM} STREQUAL "w64") include_directories(/usr/x86_64-w64-mingw32/include/cryptopp) target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) diff --git a/libethereum/Client.h b/libethereum/Client.h index cf5235c8c..8683b90f8 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -140,14 +140,13 @@ public: BlockChain const& blockChain() const { return m_bc; } // [NEW API] -/* - u256 balanceAt(Address _a, unsigned _age = 1) const; - u256 countAt(Address _a, unsigned _age = 1) const; - u256 stateAt(Address _a, u256 _l, unsigned _age = 1) const; - bytes codeAt(Address _a, unsigned _age = 1) const; - Transactions transactions(Addresses const& _from, Addresses const& _to, std::vector> const& _stateAlterations, Addresses const& _altered, unsigned _ageFrom = 0, unsigned _ageTo, unsigned _max) const; -*/ + u256 balanceAt(Address _a, int _block = -1) const; + u256 countAt(Address _a, int _block = -1) const; + u256 stateAt(Address _a, u256 _l, int _block = -1) const; + bytes codeAt(Address _a, int _block = -1) const; + Transactions transactions(Addresses const& _from, Addresses const& _to, std::vector> const& _stateAlterations, Addresses const& _altered, int _blockFrom = 0, int _blockTo = -1, unsigned _max = 10) const; + // Misc stuff: void setClientVersion(std::string const& _name) { m_clientVersion = _name; } diff --git a/libevm/All.h b/libevm/All.h new file mode 100644 index 000000000..89c451ef4 --- /dev/null +++ b/libevm/All.h @@ -0,0 +1,5 @@ +#pragma once + +#include "ExtVMFace.h" +#include "FeeStructure.h" +#include "VM.h" diff --git a/liblll/Assembly.cpp b/liblll/Assembly.cpp index 0fa125378..7016b2863 100644 --- a/liblll/Assembly.cpp +++ b/liblll/Assembly.cpp @@ -176,6 +176,11 @@ AssemblyItem const& Assembly::append(AssemblyItem const& _i) return back(); } +void Assembly::injectStart(AssemblyItem const& _i) +{ + m_items.insert(m_items.begin(), _i); +} + inline bool matches(AssemblyItemsConstRef _a, AssemblyItemsConstRef _b) { if (_a.size() != _b.size()) diff --git a/liblll/Assembly.h b/liblll/Assembly.h index 3e8a83260..9cd10a820 100644 --- a/liblll/Assembly.h +++ b/liblll/Assembly.h @@ -98,6 +98,8 @@ public: void popTo(int _deposit) { while (m_deposit > _deposit) append(Instruction::POP); } + void injectStart(AssemblyItem const& _i); + std::string out() const { std::stringstream ret; streamOut(ret); return ret.str(); } int deposit() const { return m_deposit; } bytes assemble() const; diff --git a/liblll/CodeFragment.cpp b/liblll/CodeFragment.cpp index f0aeb860c..70973aab4 100644 --- a/liblll/CodeFragment.cpp +++ b/liblll/CodeFragment.cpp @@ -19,7 +19,6 @@ * @date 2014 */ -#include "Parser.h" #include "CodeFragment.h" #include @@ -27,12 +26,30 @@ #include #include #include "CompilerState.h" +#include "Parser.h" using namespace std; using namespace eth; namespace qi = boost::spirit::qi; namespace px = boost::phoenix; namespace sp = boost::spirit; +void CodeFragment::finalise(CompilerState const& _cs) +{ + if (_cs.usedAlloc && _cs.vars.size() && !m_finalised) + { + m_finalised = true; + m_asm.injectStart(Instruction::MSTORE8); + m_asm.injectStart((u256)((_cs.vars.size() + 2) * 32) - 1); + m_asm.injectStart((u256)1); + } +} + +bytes CodeFragment::code(CompilerState const& _cs) +{ + finalise(_cs); + return m_asm.assemble(); +} + CodeFragment::CodeFragment(sp::utree const& _t, CompilerState& _s, bool _allowASM) { /* cdebug << "CodeFragment. Locals:"; @@ -317,6 +334,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) vector code; CompilerState ns = _s; ns.vars.clear(); + ns.usedAlloc = false; int c = _t.tag() ? 1 : 0; for (auto const& i: _t) if (c++) @@ -456,13 +474,30 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) m_asm.appendJump(begin); m_asm << end.tag(); } + else if (us == "ALLOC") + { + requireSize(1); + requireDeposit(0, 1); + + m_asm.append(Instruction::MEMSIZE); + m_asm.append(u256(0)); + m_asm.append(u256(1)); + m_asm.append(code[0].m_asm, 1); + m_asm.append(Instruction::MEMSIZE); + m_asm.append(Instruction::ADD); + m_asm.append(Instruction::SUB); + m_asm.append(Instruction::MSTORE8); + + _s.usedAlloc = true; + } else if (us == "LLL") { requireMinSize(2); requireMaxSize(3); requireDeposit(1, 1); - bytes const& subcode = code[0].code(); + code[0].optimise(); + bytes subcode = code[0].code(ns); m_asm.append((u256)subcode.size()); m_asm.append(Instruction::DUP); diff --git a/liblll/CodeFragment.h b/liblll/CodeFragment.h index b9d44c030..58e409125 100644 --- a/liblll/CodeFragment.h +++ b/liblll/CodeFragment.h @@ -43,18 +43,21 @@ public: static CodeFragment compile(std::string const& _src, CompilerState& _s); /// Consolidates data and compiles code. - bytes code() const { return m_asm.assemble(); } + bytes code(CompilerState const& _cs); /// Consolidates data and compiles code. - std::string assembly() const { return m_asm.out(); } + std::string assembly(CompilerState const& _cs) { finalise(_cs); return m_asm.out(); } /// Optimise the code. Best do this just before calling code() or assembly(). void optimise() { m_asm.optimise(); } private: + void finalise(CompilerState const& _cs); + template void error() const { throw T(); } void constructOperation(sp::utree const& _t, CompilerState& _s); + bool m_finalised = false; Assembly m_asm; }; diff --git a/liblll/Compiler.cpp b/liblll/Compiler.cpp index 8400ad955..0faf478d6 100644 --- a/liblll/Compiler.cpp +++ b/liblll/Compiler.cpp @@ -36,7 +36,7 @@ bytes eth::compileLLL(string const& _src, bool _opt, vector* _errors) auto f = CodeFragment::compile(_src, cs); if (_opt) f.optimise(); - bytes ret = f.code(); + bytes ret = f.code(cs); for (auto i: cs.treesToKill) killBigints(i); return ret; @@ -63,7 +63,7 @@ std::string eth::compileLLLToAsm(std::string const& _src, bool _opt, std::vector auto f = CodeFragment::compile(_src, cs); if (_opt) f.optimise(); - string ret = f.assembly(); + string ret = f.assembly(cs); for (auto i: cs.treesToKill) killBigints(i); return ret; diff --git a/liblll/CompilerState.cpp b/liblll/CompilerState.cpp index 7e990413f..7a6681909 100644 --- a/liblll/CompilerState.cpp +++ b/liblll/CompilerState.cpp @@ -52,8 +52,7 @@ void CompilerState::populateStandard() "(def 'regname (name) { [0]:name (call (- (gas) 21) namereg 0 0 32 0 0) })" "(def 'send (to value) (call (- (gas) 21) to value 0 0 0 0))" "(def 'send (gaslimit to value) (call gaslimit to value 0 0 0 0))" - "(def 'alloc (len) (asm msize 0 1 len msize add sub mstore8))" - "(def 'msg (gaslimit to value data datasize outsize) { [32]:outsize [0]:(alloc @32) (call gaslimit to value data datasize @0 @32) @0 })" + "(def 'msg (gaslimit to value data datasize outsize) { (set x outsize) (set y (alloc @32)) (call gaslimit to value data datasize @0 @32) @0 })" "(def 'msg (gaslimit to value data datasize) { (call gaslimit to value data datasize 0 32) @0 })" "(def 'msg (gaslimit to value data) { [0]:data (msg gaslimit to value 0 32) })" "(def 'msg (to value data) { [0]:data (msg 0 to value 0 32) })" diff --git a/liblll/CompilerState.h b/liblll/CompilerState.h index f8f7ce815..5dcde6147 100644 --- a/liblll/CompilerState.h +++ b/liblll/CompilerState.h @@ -48,6 +48,7 @@ struct CompilerState std::map outers; std::map, Macro> macros; std::vector treesToKill; + bool usedAlloc = false; }; } diff --git a/sc/cmdline.cpp b/sc/cmdline.cpp index 03e501ea1..e8a0a130c 100644 --- a/sc/cmdline.cpp +++ b/sc/cmdline.cpp @@ -10,7 +10,7 @@ int main(int argv, char** argc) { if (argv == 1) { std::cerr << "Must provide a command and arguments! Try parse, rewrite, compile, assemble\n"; return 0; - } + } std::string flag = ""; std::string command = argc[1]; std::string input;