/* 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 Common.h * @author Gav Wood * @date 2014 * * Ethereum-specific data structures & algorithms. */ #pragma once #include #include #include #include #include namespace dev { namespace eth { /// Current protocol version. extern const unsigned c_protocolVersion; /// Current minor protocol version. extern const unsigned c_minorProtocolVersion; /// Current database version. extern const unsigned c_databaseVersion; /// The network id. enum class Network { Olympic = 0, Frontier = 1, Turbo = 2 }; extern Network c_network; Network resetNetwork(Network _n); /// User-friendly string representation of the amount _b in wei. std::string formatBalance(bigint const& _b); /// An Ethereum address: 20 bytes. /// @NOTE This is not endian-specific; it's just a bunch of bytes. using Address = h160; DEV_SIMPLE_EXCEPTION(InvalidAddress); /// Convert the given string into an address. Address toAddress(std::string const& _s); /// Get information concerning the currency denominations. std::vector> const& units(); /// The log bloom's size (2048-bit). using LogBloom = h2048; /// Many log blooms. using LogBlooms = std::vector; template inline u256 exp10() { return exp10() * u256(10); } template <> inline u256 exp10<0>() { return u256(1); } // The various denominations; here for ease of use where needed within code. static const u256 ether = exp10<18>(); static const u256 finney = exp10<15>(); static const u256 szabo = exp10<12>(); static const u256 shannon = exp10<9>(); static const u256 wei = exp10<0>(); using Nonce = h64; using BlockNumber = unsigned; static const BlockNumber LatestBlock = (BlockNumber)-2; static const BlockNumber PendingBlock = (BlockNumber)-1; static const h256 LatestBlockHash = h256(2); static const h256 EarliestBlockHash = h256(1); static const h256 PendingBlockHash = h256(0); enum class RelativeBlock: BlockNumber { Latest = LatestBlock, Pending = PendingBlock }; class Transaction; struct ImportRoute { h256s deadBlocks; h256s liveBlocks; std::vector goodTranactions; }; enum class ImportResult { Success = 0, UnknownParent, FutureTimeKnown, FutureTimeUnknown, AlreadyInChain, AlreadyKnown, Malformed, OverbidGasPrice, BadChain }; struct ImportRequirements { using value = unsigned; enum { ValidSeal = 1, ///< Validate seal UncleBasic = 4, ///< Check the basic structure of the uncles. TransactionBasic = 8, ///< Check the basic structure of the transactions. UncleSeals = 16, ///< Check the basic structure of the uncles. TransactionSignatures = 32, ///< Check the basic structure of the transactions. Parent = 64, ///< Check parent block header. UncleParent = 128, ///< Check uncle parent block header. CheckUncles = UncleBasic | UncleSeals, ///< Check uncle seals. CheckTransactions = TransactionBasic | TransactionSignatures, ///< Check transaction signatures. OutOfOrderChecks = ValidSeal | CheckUncles | CheckTransactions, ///< Do all checks that can be done independently of prior blocks having been imported. InOrderChecks = Parent | UncleParent, ///< Do all checks that cannot be done independently of prior blocks having been imported. Everything = ValidSeal | CheckUncles | CheckTransactions | Parent | UncleParent, None = 0 }; }; /// Super-duper signal mechanism. TODO: replace with somthing a bit heavier weight. template class Signal { public: using Callback = std::function; class HandlerAux { friend class Signal; public: ~HandlerAux() { if (m_s) m_s->m_fire.erase(m_i); } void reset() { m_s = nullptr; } void fire(Args const&... _args) { m_h(_args...); } private: HandlerAux(unsigned _i, Signal* _s, Callback const& _h): m_i(_i), m_s(_s), m_h(_h) {} unsigned m_i = 0; Signal* m_s = nullptr; Callback m_h; }; ~Signal() { for (auto const& h : m_fire) if (auto l = h.second.lock()) l->reset(); } std::shared_ptr add(Callback const& _h) { auto n = m_fire.empty() ? 0 : (m_fire.rbegin()->first + 1); auto h = std::shared_ptr(new HandlerAux(n, this, _h)); m_fire[n] = h; return h; } void operator()(Args const&... _args) { for (auto const& f: valuesOf(m_fire)) if (auto h = f.lock()) h->fire(_args...); } private: std::map> m_fire; }; template using Handler = std::shared_ptr::HandlerAux>; struct TransactionSkeleton { bool creation = false; Address from; Address to; u256 value; bytes data; u256 nonce = UndefinedU256; u256 gas = UndefinedU256; u256 gasPrice = UndefinedU256; }; void badBlock(bytesConstRef _header, std::string const& _err); inline void badBlock(bytes const& _header, std::string const& _err) { badBlock(&_header, _err); } // TODO: move back into a mining subsystem and have it be accessible from Sealant only via a dynamic_cast. /** * @brief Describes the progress of a mining operation. */ struct WorkingProgress { // MiningProgress& operator+=(MiningProgress const& _mp) { hashes += _mp.hashes; ms = std::max(ms, _mp.ms); return *this; } uint64_t hashes = 0; ///< Total number of hashes computed. uint64_t ms = 0; ///< Total number of milliseconds of mining thus far. uint64_t rate() const { return ms == 0 ? 0 : hashes * 1000 / ms; } }; /// Import transaction policy enum class IfDropped { Ignore, ///< Don't import transaction that was previously dropped. Retry ///< Import transaction even if it was dropped before. }; } }