diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index ba2592491..0ea072a93 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -255,7 +255,7 @@ private: QString m_logHistory; bool m_logChanged = true; - std::unique_ptr m_server; QWebThreeConnector m_qwebConnector; + std::unique_ptr m_server; QWebThree* m_qweb = nullptr; }; diff --git a/docker/Dockerfile b/docker/Dockerfile index 1bd690cbb..c183f03b9 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -4,17 +4,30 @@ ENV DEBIAN_FRONTEND noninteractive RUN apt-get update RUN apt-get upgrade -y -RUN apt-get install -qy wget -RUN apt-get install -qy build-essential g++-4.8 automake libtool unzip git cmake -RUN apt-get install -qy libncurses5-dev libgmp-dev libgmp3-dev libboost-all-dev libleveldb-dev yasm libminiupnpc-dev -RUN apt-get install -qy qtbase5-dev qt5-default qtdeclarative5-dev libqt5webkit5-dev +# Ethereum dependencies +RUN apt-get install -qy build-essential g++-4.8 git cmake libboost-all-dev libcurl4-openssl-dev wget +RUN apt-get install -qy automake unzip libgmp-dev libtool libleveldb-dev yasm libminiupnpc-dev libreadline-dev scons -RUN mkdir /cryptopp562 -RUN cd /cryptopp562 && wget http://www.cryptopp.com/cryptopp562.zip && unzip cryptopp562.zip -RUN cd /cryptopp562 && make -j $(cat /proc/cpuinfo | grep processor | wc -l) && make install +# NCurses based GUI (not optional though for a succesful compilation, see https://github.com/ethereum/cpp-ethereum/issues/452 ) +RUN apt-get install -qy libncurses5-dev +# Qt-based GUI +# RUN apt-get install -qy qtbase5-dev qt5-default qtdeclarative5-dev libqt5webkit5-dev + +# Cryptopp +RUN git clone --depth=1 https://github.com/mmoss/cryptopp.git +RUN cd cryptopp && scons --shared --prefix=/usr + +# JSONRPC (version 0.2.1, see https://github.com/ethereum/cpp-ethereum/issues/453 ) +RUN apt-get install -qy libjsoncpp-dev libargtable2-dev +RUN git clone --depth=1 --branch=0.2.1 https://github.com/cinemast/libjson-rpc-cpp.git +RUN mkdir -p libjson-rpc-cpp/build +RUN cd libjson-rpc-cpp/build && cmake .. && make && make install + +# Build Ethereum (HEADLESS) RUN git clone --depth=1 https://github.com/ethereum/cpp-ethereum -RUN mkdir cpp-ethereum/build -RUN cd cpp-ethereum/build && cmake .. -DCMAKE_BUILD_TYPE=Release && make -j $(cat /proc/cpuinfo | grep processor | wc -l) && make install +RUN mkdir -p cpp-ethereum/build +RUN cd cpp-ethereum/build && cmake .. -DCMAKE_BUILD_TYPE=Release -DHEADLESS=1 && make -j $(cat /proc/cpuinfo | grep processor | wc -l) && make install +RUN ldconfig ENTRYPOINT ["/usr/local/bin/eth"] diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h index 41d140cad..02d199f62 100644 --- a/libdevcore/FixedHash.h +++ b/libdevcore/FixedHash.h @@ -158,21 +158,25 @@ public: return ret; } - template inline FixedHash& shiftBloom(FixedHash const& _h) { return (*this |= _h.template nbloom()); } + template inline FixedHash& shiftBloom(FixedHash const& _h) + { + return (*this |= _h.template nbloom()); + } template inline FixedHash nbloom() const { - static const unsigned c_bloomBytes = (M + 7) / 8; - unsigned mask = (1 << c_bloomBytes) - 1; + static const unsigned c_bloomBits = M * 8; + unsigned mask = c_bloomBits - 1; + unsigned bloomBytes = (dev::toLog2(c_bloomBits) + 7) / 8; FixedHash ret; byte const* p = data(); for (unsigned i = 0; i < P; ++i) { unsigned index = 0; - for (unsigned j = 0; j < c_bloomBytes; ++j, ++p) + for (unsigned j = 0; j < bloomBytes; ++j, ++p) index = (index << 8) | *p; index &= mask; - ret[N - 1 - index / 8] |= (1 << (index % 8)); + ret[M - 1 - index / 8] |= (1 << (index % 8)); } return ret; } @@ -231,6 +235,7 @@ using h520 = FixedHash<65>; using h512 = FixedHash<64>; using h256 = FixedHash<32>; using h160 = FixedHash<20>; +using h512s = std::vector; using h256s = std::vector; using h160s = std::vector; using h256Set = std::set; diff --git a/libdevcrypto/SHA3.cpp b/libdevcrypto/SHA3.cpp index 7c2cc01a3..4a0cd469e 100644 --- a/libdevcrypto/SHA3.cpp +++ b/libdevcrypto/SHA3.cpp @@ -30,6 +30,7 @@ namespace dev { h256 EmptySHA3 = sha3(bytesConstRef()); +h256 EmptyListSHA3 = sha3(RLPEmptyList); std::string sha3(std::string const& _input, bool _hex) { diff --git a/libdevcrypto/SHA3.h b/libdevcrypto/SHA3.h index fc2cfcfc3..1575ab29c 100644 --- a/libdevcrypto/SHA3.h +++ b/libdevcrypto/SHA3.h @@ -58,6 +58,8 @@ inline h256 sha3(std::string const& _input) { return sha3(bytesConstRef(_input)) extern h256 EmptySHA3; +extern h256 EmptyListSHA3; + // Other crypto convenience routines bytes aesDecrypt(bytesConstRef _cipher, std::string const& _password, unsigned _rounds = 2000, bytesConstRef _salt = bytesConstRef()); diff --git a/libethcore/BlockInfo.cpp b/libethcore/BlockInfo.cpp index d87e6f5df..44da9603c 100644 --- a/libethcore/BlockInfo.cpp +++ b/libethcore/BlockInfo.cpp @@ -56,8 +56,6 @@ h256 BlockInfo::headerHashWithoutNonce() const return sha3(s.out()); } -auto static const c_sha3EmptyList = sha3(RLPEmptyList); - void BlockInfo::streamRLP(RLPStream& _s, bool _nonce) const { _s.appendList(_nonce ? 15 : 14) diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index 710f17214..765b54627 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -103,7 +103,7 @@ bytes BlockChain::createGenesisBlock() block.appendList(15) // TODO: maybe make logbloom correct? - << h256() << EmptySHA3 << h160() << stateRoot << EmptyTrie << EmptyTrie << LogBloom() << c_genesisDifficulty << 0 << 0 << 1000000 << 0 << (unsigned)0 << string() << sha3(bytes(1, 42)); + << h256() << EmptyListSHA3 << h160() << stateRoot << EmptyTrie << EmptyTrie << LogBloom() << c_genesisDifficulty << 0 << 0 << 1000000 << 0 << (unsigned)0 << string() << sha3(bytes(1, 42)); block.appendRaw(RLPEmptyList); block.appendRaw(RLPEmptyList); return block.out(); @@ -309,10 +309,14 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db) auto b = s.oldBloom(); BlockBlooms bb; BlockTraces bt; + BlockLogBlooms blb; + BlockReceipts br; for (unsigned i = 0; i < s.pending().size(); ++i) { - bt.traces.push_back(s.changesFromPending(i)); bb.blooms.push_back(s.changesFromPending(i).bloom()); + bt.traces.push_back(s.changesFromPending(i)); + blb.blooms.push_back(s.receipt(i).bloom()); + br.receipts.push_back(s.receipt(i)); } s.cleanup(true); td = pd.totalDifficulty + tdIncrease; @@ -334,11 +338,21 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db) WriteGuard l(x_traces); m_traces[newHash] = bt; } + { + WriteGuard l(x_logBlooms); + m_logBlooms[newHash] = blb; + } + { + WriteGuard l(x_receipts); + m_receipts[newHash] = br; + } m_extrasDB->Put(m_writeOptions, toSlice(newHash), (ldb::Slice)dev::ref(m_details[newHash].rlp())); m_extrasDB->Put(m_writeOptions, toSlice(bi.parentHash), (ldb::Slice)dev::ref(m_details[bi.parentHash].rlp())); m_extrasDB->Put(m_writeOptions, toSlice(newHash, 1), (ldb::Slice)dev::ref(m_blooms[newHash].rlp())); m_extrasDB->Put(m_writeOptions, toSlice(newHash, 2), (ldb::Slice)dev::ref(m_traces[newHash].rlp())); + m_extrasDB->Put(m_writeOptions, toSlice(newHash, 3), (ldb::Slice)dev::ref(m_logBlooms[newHash].rlp())); + m_extrasDB->Put(m_writeOptions, toSlice(newHash, 4), (ldb::Slice)dev::ref(m_receipts[newHash].rlp())); m_db->Put(m_writeOptions, toSlice(newHash), (ldb::Slice)ref(_block)); #if ETH_PARANOIA diff --git a/libethereum/BlockChain.h b/libethereum/BlockChain.h index 30f5633c1..49f7b149e 100644 --- a/libethereum/BlockChain.h +++ b/libethereum/BlockChain.h @@ -105,6 +105,14 @@ public: BlockTraces traces(h256 _hash) const { return queryExtras(_hash, m_traces, x_traces, NullBlockTraces); } BlockTraces traces() const { return traces(currentHash()); } + /// Get the transactions' log blooms of a block (or the most recent mined if none given). Thread-safe. + BlockLogBlooms logBlooms(h256 _hash) const { return queryExtras(_hash, m_logBlooms, x_logBlooms, NullBlockLogBlooms); } + BlockLogBlooms logBlooms() const { return logBlooms(currentHash()); } + + /// Get the transactions' receipts of a block (or the most recent mined if none given). Thread-safe. + BlockReceipts receipts(h256 _hash) const { return queryExtras(_hash, m_receipts, x_receipts, NullBlockReceipts); } + BlockReceipts receipts() const { return receipts(currentHash()); } + /// Get a block (RLP format) for the given hash (or the most recent mined if none given). Thread-safe. bytes block(h256 _hash) const; bytes block() const { return block(currentHash()); } @@ -185,6 +193,10 @@ private: mutable BlockBloomsHash m_blooms; mutable boost::shared_mutex x_traces; mutable BlockTracesHash m_traces; + mutable boost::shared_mutex x_logBlooms; + mutable BlockLogBloomsHash m_logBlooms; + mutable boost::shared_mutex x_receipts; + mutable BlockReceiptsHash m_receipts; mutable boost::shared_mutex x_cache; mutable std::map m_cache; diff --git a/libethereum/BlockDetails.h b/libethereum/BlockDetails.h index 90bf65bdd..973e93070 100644 --- a/libethereum/BlockDetails.h +++ b/libethereum/BlockDetails.h @@ -29,6 +29,7 @@ #include #include #include "Manifest.h" +#include "TransactionReceipt.h" namespace ldb = leveldb; namespace dev @@ -71,14 +72,35 @@ struct BlockTraces Manifests traces; }; +struct BlockLogBlooms +{ + BlockLogBlooms() {} + BlockLogBlooms(RLP const& _r) { blooms = _r.toVector(); } + bytes rlp() const { RLPStream s; s << blooms; return s.out(); } + + h512s blooms; +}; + +struct BlockReceipts +{ + BlockReceipts() {} + BlockReceipts(RLP const& _r) { for (auto const& i: _r) receipts.emplace_back(i.data()); } + bytes rlp() const { RLPStream s(receipts.size()); for (TransactionReceipt const& i: receipts) i.streamRLP(s); return s.out(); } + + TransactionReceipts receipts; +}; typedef std::map BlockDetailsHash; typedef std::map BlockBloomsHash; typedef std::map BlockTracesHash; +typedef std::map BlockLogBloomsHash; +typedef std::map BlockReceiptsHash; static const BlockDetails NullBlockDetails; static const BlockBlooms NullBlockBlooms; static const BlockTraces NullBlockTraces; +static const BlockLogBlooms NullBlockLogBlooms; +static const BlockReceipts NullBlockReceipts; } } diff --git a/libethereum/ExtVM.h b/libethereum/ExtVM.h index cf80b2352..758672e49 100644 --- a/libethereum/ExtVM.h +++ b/libethereum/ExtVM.h @@ -102,7 +102,7 @@ public: private: 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. + std::map m_origCache; ///< The cache of the address states (i.e. the externalities) as-was prior to the execution. Manifest* m_ms; }; diff --git a/libethereum/State.cpp b/libethereum/State.cpp index b5a355b6b..6fc313c15 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -725,9 +725,7 @@ void State::cleanup(bool _fullCommit) m_previousBlock = m_currentBlock; } else - { m_db.rollback(); - } resetCurrent(); } diff --git a/libethereum/State.h b/libethereum/State.h index fece4601a..ef3c3a36f 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -36,6 +36,7 @@ #include "TransactionQueue.h" #include "Account.h" #include "Transaction.h" +#include "TransactionReceipt.h" #include "Executive.h" #include "AccountDiff.h" @@ -53,37 +54,6 @@ struct StateChat: public LogChannel { static const char* name() { return "-S-"; struct StateTrace: public LogChannel { static const char* name() { return "=S="; } static const int verbosity = 7; }; struct StateDetail: public LogChannel { static const char* name() { return "/S/"; } static const int verbosity = 14; }; -class TransactionReceipt -{ -public: - TransactionReceipt(h256 _root, u256 _gasUsed, LogEntries const& _log, Manifest const& _ms): m_stateRoot(_root), m_gasUsed(_gasUsed), m_bloom(eth::bloom(_log)), m_log(_log), m_changes(_ms) {} - - Manifest const& changes() const { return m_changes; } - - h256 const& stateRoot() const { return m_stateRoot; } - u256 const& gasUsed() const { return m_gasUsed; } - LogBloom const& bloom() const { return m_bloom; } - LogEntries const& log() const { return m_log; } - - void streamRLP(RLPStream& _s) const - { - _s.appendList(4) << m_stateRoot << m_gasUsed << m_bloom; - _s.appendList(m_log.size()); - for (LogEntry const& l: m_log) - l.streamRLP(_s); - } - -private: - h256 m_stateRoot; - u256 m_gasUsed; - LogBloom m_bloom; - LogEntries m_log; - - Manifest m_changes; ///< TODO: PoC-7: KILL -}; - -using TransactionReceipts = std::vector; - struct PrecompiledAddress { unsigned gas; diff --git a/libethereum/TransactionReceipt.h b/libethereum/TransactionReceipt.h new file mode 100644 index 000000000..26539c4a9 --- /dev/null +++ b/libethereum/TransactionReceipt.h @@ -0,0 +1,70 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file TransactionReceipt.h + * @author Gav Wood + * @date 2014 + */ + +#pragma once + +#include +#include +#include +#include +#include +#include "Manifest.h" + +namespace dev +{ + +namespace eth +{ + +class TransactionReceipt +{ +public: + TransactionReceipt(bytesConstRef _rlp) { RLP r(_rlp); m_stateRoot = (h256)r[0]; m_gasUsed = (u256)r[1]; m_bloom = (LogBloom)r[2]; for (auto const& i: r[3]) m_log.emplace_back(i); } + TransactionReceipt(h256 _root, u256 _gasUsed, LogEntries const& _log, Manifest const& _ms): m_stateRoot(_root), m_gasUsed(_gasUsed), m_bloom(eth::bloom(_log)), m_log(_log), m_changes(_ms) {} + + Manifest const& changes() const { return m_changes; } + + h256 const& stateRoot() const { return m_stateRoot; } + u256 const& gasUsed() const { return m_gasUsed; } + LogBloom const& bloom() const { return m_bloom; } + LogEntries const& log() const { return m_log; } + + void streamRLP(RLPStream& _s) const + { + _s.appendList(4) << m_stateRoot << m_gasUsed << m_bloom; + _s.appendList(m_log.size()); + for (LogEntry const& l: m_log) + l.streamRLP(_s); + } + +private: + h256 m_stateRoot; + u256 m_gasUsed; + LogBloom m_bloom; + LogEntries m_log; + + Manifest m_changes; ///< TODO: PoC-7: KILL +}; + +using TransactionReceipts = std::vector; + +} +} diff --git a/libevm/VM.h b/libevm/VM.h index 151643272..252628b75 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -82,7 +82,7 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con { int in = _ext.code[i] - (unsigned)Instruction::PUSH1 + 1; u256 p = 0; - for (; in--; i++) + for (i++; in--; i++) p = (p << 8) | _ext.getCode(i); if ((_ext.getCode(i) == (byte)Instruction::JUMP || _ext.getCode(i) == (byte)Instruction::JUMPI) && !(_ext.getCode(p) == (byte)Instruction::JUMP || _ext.getCode(p) == (byte)Instruction::JUMPI)) if (p >= _ext.code.size()) @@ -90,6 +90,7 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con else implicit.insert(p); else {} + i--; } for (unsigned i = 0; i < _ext.code.size(); i += instructionInfo((Instruction)_ext.getCode(i)).additional + 1) if (implicit.count(i)) diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index 020c7e420..bf8d96506 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -62,8 +62,8 @@ Host::Host(std::string const& _clientVersion, NetworkPreferences const& _n, bool m_clientVersion(_clientVersion), m_netPrefs(_n), m_ioService(new ba::io_service), - m_acceptor(*m_ioService), - m_socket(*m_ioService), + m_acceptor(new bi::tcp::acceptor(*m_ioService)), + m_socket(new bi::tcp::socket(*m_ioService)), m_key(KeyPair::create()) { populateAddresses(); @@ -91,11 +91,11 @@ void Host::start() bi::tcp::endpoint endpoint(bi::tcp::v4(), i ? 0 : m_netPrefs.listenPort); try { - m_acceptor.open(endpoint.protocol()); - m_acceptor.set_option(ba::socket_base::reuse_address(true)); - m_acceptor.bind(endpoint); - m_acceptor.listen(); - m_listenPort = i ? m_acceptor.local_endpoint().port() : m_netPrefs.listenPort; + m_acceptor->open(endpoint.protocol()); + m_acceptor->set_option(ba::socket_base::reuse_address(true)); + m_acceptor->bind(endpoint); + m_acceptor->listen(); + m_listenPort = i ? m_acceptor->local_endpoint().port() : m_netPrefs.listenPort; break; } catch (...) @@ -105,7 +105,7 @@ void Host::start() cwarn << "Couldn't start accepting connections on host. Something very wrong with network?\n" << boost::current_exception_diagnostic_information(); return; } - m_acceptor.close(); + m_acceptor->close(); continue; } } @@ -118,20 +118,24 @@ void Host::start() void Host::stop() { + // if there's no ioService, it means we've had quit() called - bomb out - we're not allowed in here. + if (!m_ioService) + return; + for (auto const& h: m_capabilities) h.second->onStopping(); stopWorking(); - if (m_acceptor.is_open()) + if (m_acceptor->is_open()) { if (m_accepting) - m_acceptor.cancel(); - m_acceptor.close(); + m_acceptor->cancel(); + m_acceptor->close(); m_accepting = false; } - if (m_socket.is_open()) - m_socket.close(); + if (m_socket->is_open()) + m_socket->close(); disconnectPeers(); if (!!m_ioService) @@ -147,6 +151,8 @@ void Host::quit() // such tasks may involve socket reads from Capabilities that maintain references // to resources we're about to free. stop(); + m_acceptor.reset(); + m_socket.reset(); m_ioService.reset(); // m_acceptor & m_socket are DANGEROUS now. } @@ -463,18 +469,18 @@ void Host::ensureAccepting() { clog(NetConnect) << "Listening on local port " << m_listenPort << " (public: " << m_public << ")"; m_accepting = true; - m_acceptor.async_accept(m_socket, [=](boost::system::error_code ec) + m_acceptor->async_accept(*m_socket, [=](boost::system::error_code ec) { if (!ec) { try { try { - clog(NetConnect) << "Accepted connection from " << m_socket.remote_endpoint(); + clog(NetConnect) << "Accepted connection from " << m_socket->remote_endpoint(); } catch (...){} - bi::address remoteAddress = m_socket.remote_endpoint().address(); + bi::address remoteAddress = m_socket->remote_endpoint().address(); // Port defaults to 0 - we let the hello tell us which port the peer listens to - auto p = std::make_shared(this, std::move(m_socket), bi::tcp::endpoint(remoteAddress, 0)); + auto p = std::make_shared(this, std::move(*m_socket), bi::tcp::endpoint(remoteAddress, 0)); p->start(); } catch (Exception const& _e) diff --git a/libp2p/Host.h b/libp2p/Host.h index 6e60b915e..7722905ab 100644 --- a/libp2p/Host.h +++ b/libp2p/Host.h @@ -214,8 +214,8 @@ private: int m_listenPort = NetworkStopped; ///< What port are we listening on? std::unique_ptr m_ioService; ///< IOService for network stuff. - bi::tcp::acceptor m_acceptor; ///< Listening acceptor. - bi::tcp::socket m_socket; ///< Listening socket. + std::unique_ptr m_acceptor; ///< Listening acceptor. + std::unique_ptr m_socket; ///< Listening socket. UPnP* m_upnp = nullptr; ///< UPnP helper. bi::tcp::endpoint m_public; ///< Our public listening endpoint. diff --git a/libsolidity/Compiler.cpp b/libsolidity/Compiler.cpp index f19dd3f7f..ba1dcfb6b 100644 --- a/libsolidity/Compiler.cpp +++ b/libsolidity/Compiler.cpp @@ -336,9 +336,11 @@ void ExpressionCompiler::appendArithmeticOperatorCode(Token::Value _operator, Ty append(eth::Instruction::MUL); break; case Token::DIV: + append(eth::Instruction::SWAP1); append(isSigned ? eth::Instruction::SDIV : eth::Instruction::DIV); break; case Token::MOD: + append(eth::Instruction::SWAP1); append(isSigned ? eth::Instruction::SMOD : eth::Instruction::MOD); break; default: diff --git a/test/solidityCompiler.cpp b/test/solidityCompiler.cpp index e08605110..e024043e4 100644 --- a/test/solidityCompiler.cpp +++ b/test/solidityCompiler.cpp @@ -193,7 +193,9 @@ BOOST_AUTO_TEST_CASE(arithmetics) byte(eth::Instruction::SWAP1), byte(eth::Instruction::SUB), byte(eth::Instruction::ADD), + byte(eth::Instruction::SWAP1), byte(eth::Instruction::MOD), + byte(eth::Instruction::SWAP1), byte(eth::Instruction::DIV), byte(eth::Instruction::MUL)}); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());