diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h index 0032a1314..284745c64 100644 --- a/libdevcore/FixedHash.h +++ b/libdevcore/FixedHash.h @@ -158,6 +158,25 @@ public: return ret; } + template inline FixedHash& shiftBloom(FixedHash const& _h) { return (*this |= _h.nbloom()); } + + template inline FixedHash nbloom() const + { + static const unsigned c_bloomBytes = (M + 7) / 8; + unsigned mask = (1 << c_bloomBytes) - 1; + 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) + index = (index << 8) | *p; + index &= mask; + ret[N - 1 - index / 8] |= (1 << (index % 8)); + } + return ret; + } + /// Returns the index of the first bit set to one, or size() * 8 if no bits are set. inline unsigned firstBitSet() const { diff --git a/libdevcrypto/SHA3.cpp b/libdevcrypto/SHA3.cpp index eaabae0ff..7c2cc01a3 100644 --- a/libdevcrypto/SHA3.cpp +++ b/libdevcrypto/SHA3.cpp @@ -30,7 +30,6 @@ namespace dev { h256 EmptySHA3 = sha3(bytesConstRef()); -h256 ZeroRLPSHA3 = sha3(rlp(bytesConstRef())); std::string sha3(std::string const& _input, bool _hex) { diff --git a/libdevcrypto/SHA3.h b/libdevcrypto/SHA3.h index 5948cb3bd..fc2cfcfc3 100644 --- a/libdevcrypto/SHA3.h +++ b/libdevcrypto/SHA3.h @@ -57,7 +57,6 @@ inline h256 sha3(bytes const& _input) { return sha3(bytesConstRef((bytes*)&_inpu inline h256 sha3(std::string const& _input) { return sha3(bytesConstRef(_input)); } extern h256 EmptySHA3; -extern h256 ZeroRLPSHA3; // Other crypto convenience routines diff --git a/libdevcrypto/TrieDB.cpp b/libdevcrypto/TrieDB.cpp index 168b2fdf7..674f21aa4 100644 --- a/libdevcrypto/TrieDB.cpp +++ b/libdevcrypto/TrieDB.cpp @@ -26,6 +26,7 @@ using namespace dev; #if !ETH_LANGUAGES -const h256 dev::c_shaNull = sha3(rlp("")); +h256 const dev::c_shaNull = sha3(rlp("")); +h256 const dev::EmptyTrie = c_shaNull; #endif diff --git a/libdevcrypto/TrieDB.h b/libdevcrypto/TrieDB.h index 0ca0b9d98..b42d67aea 100644 --- a/libdevcrypto/TrieDB.h +++ b/libdevcrypto/TrieDB.h @@ -45,6 +45,7 @@ struct TrieDBChannel: public LogChannel { static const char* name() { return "- struct InvalidTrie: virtual dev::Exception {}; extern const h256 c_shaNull; +extern const h256 EmptyTrie; /** * @brief Merkle Patricia Tree "Trie": a modifed base-16 Radix tree. diff --git a/libethcore/BlockInfo.cpp b/libethcore/BlockInfo.cpp index 6e4af247f..da609d5b4 100644 --- a/libethcore/BlockInfo.cpp +++ b/libethcore/BlockInfo.cpp @@ -52,16 +52,16 @@ BlockInfo BlockInfo::fromHeader(bytesConstRef _block) h256 BlockInfo::headerHashWithoutNonce() const { RLPStream s; - fillStream(s, false); + streamRLP(s, false); return sha3(s.out()); } auto static const c_sha3EmptyList = sha3(RLPEmptyList); -void BlockInfo::fillStream(RLPStream& _s, bool _nonce) const +void BlockInfo::streamRLP(RLPStream& _s, bool _nonce) const { - _s.appendList(_nonce ? 13 : 12) - << parentHash << sha3Uncles << coinbaseAddress << stateRoot << transactionsRoot + _s.appendList(_nonce ? 15 : 14) + << parentHash << sha3Uncles << coinbaseAddress << stateRoot << transactionsRoot << receiptsRoot << logBloom << difficulty << number << minGasPrice << gasLimit << gasUsed << timestamp << extraData; if (_nonce) _s << nonce; @@ -84,14 +84,16 @@ void BlockInfo::populateFromHeader(RLP const& _header, bool _checkNonce) coinbaseAddress = _header[field = 2].toHash
(); stateRoot = _header[field = 3].toHash(); transactionsRoot = _header[field = 4].toHash(); - difficulty = _header[field = 5].toInt(); - number = _header[field = 6].toInt(); - minGasPrice = _header[field = 7].toInt(); - gasLimit = _header[field = 8].toInt(); - gasUsed = _header[field = 9].toInt(); - timestamp = _header[field = 10].toInt(); - extraData = _header[field = 11].toBytes(); - nonce = _header[field = 12].toHash(); + receiptsRoot = _header[field = 5].toHash(); + logBloom = _header[field = 6].toHash(); + difficulty = _header[field = 7].toInt(); + number = _header[field = 8].toInt(); + minGasPrice = _header[field = 9].toInt(); + gasLimit = _header[field = 10].toInt(); + gasUsed = _header[field = 11].toInt(); + timestamp = _header[field = 12].toInt(); + extraData = _header[field = 13].toBytes(); + nonce = _header[field = 14].toHash(); } catch (Exception & _e) diff --git a/libethcore/BlockInfo.h b/libethcore/BlockInfo.h index 283f11b88..18628e2ec 100644 --- a/libethcore/BlockInfo.h +++ b/libethcore/BlockInfo.h @@ -47,7 +47,7 @@ extern u256 c_genesisDifficulty; * corresponding RLP block created with createGenesisBlock(). * * The difficulty and gas-limit derivations may be calculated with the calculateDifficulty() - * and calculateGasLimit() and the object serialised to RLP with fillStream. To determine the + * and calculateGasLimit() and the object serialised to RLP with streamRLP. To determine the * header hash without the nonce (for mining), the method headerHashWithoutNonce() is provided. * * The default constructor creates an empty object, which can be tested against with the boolean @@ -62,6 +62,8 @@ public: Address coinbaseAddress; h256 stateRoot; h256 transactionsRoot; + h256 receiptsRoot; + h512 logBloom; // TODO LogBloom - get include u256 difficulty; u256 number; u256 minGasPrice; @@ -89,6 +91,8 @@ public: coinbaseAddress == _cmp.coinbaseAddress && stateRoot == _cmp.stateRoot && transactionsRoot == _cmp.transactionsRoot && + receiptsRoot == _cmp.receiptsRoot && + logBloom == _cmp.logBloom && difficulty == _cmp.difficulty && number == _cmp.number && minGasPrice == _cmp.minGasPrice && @@ -112,13 +116,14 @@ public: /// No-nonce sha3 of the header only. h256 headerHashWithoutNonce() const; - void fillStream(RLPStream& _s, bool _nonce) const; + void streamRLP(RLPStream& _s, bool _nonce) const; }; inline std::ostream& operator<<(std::ostream& _out, BlockInfo const& _bi) { _out << _bi.hash << " " << _bi.parentHash << " " << _bi.sha3Uncles << " " << _bi.coinbaseAddress << " " << _bi.stateRoot << " " << _bi.transactionsRoot << " " << - _bi.difficulty << " " << _bi.number << " " << _bi.minGasPrice << " " << _bi.gasLimit << " " << _bi.gasUsed << " " << _bi.timestamp << " " << _bi.nonce; + _bi.receiptsRoot << " " << _bi.logBloom << " " << _bi.difficulty << " " << _bi.number << " " << _bi.minGasPrice << " " << _bi.gasLimit << " " << + _bi.gasUsed << " " << _bi.timestamp << " " << _bi.nonce; return _out; } diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index b08179f9e..f63eb64cd 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -102,7 +102,8 @@ bytes BlockChain::createGenesisBlock() } block.appendList(13) - << h256() << c_shaNull << h160() << stateRoot << c_shaNull << c_genesisDifficulty << 0 << 0 << 1000000 << 0 << (unsigned)0 << string() << sha3(bytes(1, 42)); + // 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)); block.appendRaw(RLPEmptyList); block.appendRaw(RLPEmptyList); return block.out(); @@ -305,7 +306,7 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db) // Get total difficulty increase and update state, checking it. State s(bi.coinbaseAddress, _db); auto tdIncrease = s.enactOn(&_block, bi, *this); - auto b = s.bloom(); + auto b = s.oldBloom(); BlockBlooms bb; BlockTraces bt; for (unsigned i = 0; i < s.pending().size(); ++i) diff --git a/libethereum/BlockDetails.h b/libethereum/BlockDetails.h index 9cb49a21c..90bf65bdd 100644 --- a/libethereum/BlockDetails.h +++ b/libethereum/BlockDetails.h @@ -66,7 +66,7 @@ struct BlockTraces { BlockTraces() {} BlockTraces(RLP const& _r) { for (auto const& i: _r) traces.emplace_back(i.data()); } - bytes rlp() const { RLPStream s(traces.size()); for (auto const& i: traces) i.streamOut(s); return s.out(); } + bytes rlp() const { RLPStream s(traces.size()); for (auto const& i: traces) i.streamRLP(s); return s.out(); } Manifests traces; }; diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index dc36957ee..63e093b17 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -159,7 +159,7 @@ void Client::clearPending() if (!m_postMine.pending().size()) return; for (unsigned i = 0; i < m_postMine.pending().size(); ++i) - appendFromNewPending(m_postMine.bloom(i), changeds); + appendFromNewPending(m_postMine.oldBloom(i), changeds); changeds.insert(PendingChangedFilter); m_postMine = m_preMine; } diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index 840287ca9..22d538231 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -123,7 +123,11 @@ bool Executive::call(Address _receiveAddress, Address _senderAddress, u256 _valu m_ext = new ExtVM(m_s, _receiveAddress, _senderAddress, _originAddress, _value, _gasPrice, _data, &c, m_ms); } else + { m_endGas = _gas; + if (m_ext) + m_ext->sub.logs.push_back(LogEntry(_receiveAddress, {u256((u160)_senderAddress) + 1}, bytes())); + } return !m_ext; } diff --git a/libethereum/Manifest.cpp b/libethereum/Manifest.cpp index 2d1e4aa6e..9e6d2f651 100644 --- a/libethereum/Manifest.cpp +++ b/libethereum/Manifest.cpp @@ -37,10 +37,10 @@ Manifest::Manifest(bytesConstRef _r) internal.emplace_back(i.data()); } -void Manifest::streamOut(RLPStream& _s) const +void Manifest::streamRLP(RLPStream& _s) const { _s.appendList(7) << from << to << value << altered << input << output; _s.appendList(internal.size()); for (auto const& i: internal) - i.streamOut(_s); + i.streamRLP(_s); } diff --git a/libethereum/Manifest.h b/libethereum/Manifest.h index 12c40b3a9..e0e512c92 100644 --- a/libethereum/Manifest.h +++ b/libethereum/Manifest.h @@ -41,7 +41,7 @@ struct Manifest { Manifest() {} Manifest(bytesConstRef _r); - void streamOut(RLPStream& _s) const; + void streamRLP(RLPStream& _s) const; h256 bloom() const { h256 ret = from.bloom() | to.bloom(); for (auto const& i: internal) ret |= i.bloom(); for (auto const& i: altered) ret |= h256(i).bloom(); return ret; } diff --git a/libethereum/MessageFilter.cpp b/libethereum/MessageFilter.cpp index 951bfec98..fc6af1308 100644 --- a/libethereum/MessageFilter.cpp +++ b/libethereum/MessageFilter.cpp @@ -27,7 +27,7 @@ using namespace std; using namespace dev; using namespace dev::eth; -void MessageFilter::fillStream(RLPStream& _s) const +void MessageFilter::streamRLP(RLPStream& _s) const { _s.appendList(8) << m_from << m_to << m_stateAltered << m_altered << m_earliest << m_latest << m_max << m_skip; } @@ -35,7 +35,7 @@ void MessageFilter::fillStream(RLPStream& _s) const h256 MessageFilter::sha3() const { RLPStream s; - fillStream(s); + streamRLP(s); return dev::sha3(s.out()); } diff --git a/libethereum/MessageFilter.h b/libethereum/MessageFilter.h index c9fb4e51c..83cbb7237 100644 --- a/libethereum/MessageFilter.h +++ b/libethereum/MessageFilter.h @@ -39,7 +39,7 @@ class MessageFilter public: MessageFilter(int _earliest = 0, int _latest = -1, unsigned _max = 10, unsigned _skip = 0): m_earliest(_earliest), m_latest(_latest), m_max(_max), m_skip(_skip) {} - void fillStream(RLPStream& _s) const; + void streamRLP(RLPStream& _s) const; h256 sha3() const; int earliest() const { return m_earliest; } diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 7e2489f4d..5571a02e0 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -161,6 +161,7 @@ State::State(State const& _s): m_db(_s.m_db), m_state(&m_db, _s.m_state.root()), m_transactions(_s.m_transactions), + m_receipts(_s.m_receipts), m_transactionSet(_s.m_transactionSet), m_cache(_s.m_cache), m_previousBlock(_s.m_previousBlock), @@ -192,6 +193,7 @@ State& State::operator=(State const& _s) m_db = _s.m_db; m_state.open(&m_db, _s.m_state.root()); m_transactions = _s.m_transactions; + m_receipts = _s.m_receipts; m_transactionSet = _s.m_transactionSet; m_cache = _s.m_cache; m_previousBlock = _s.m_previousBlock; @@ -353,7 +355,7 @@ void State::ensureCached(std::map& _cache, Address _a, bo RLP state(stateBack); AddressState s; if (state.isNull()) - s = AddressState(0, 0, ZeroRLPSHA3, EmptySHA3); + s = AddressState(0, 0, EmptyTrie, EmptySHA3); else s = AddressState(state[0].toInt(), state[1].toInt(), state[2].toHash(), state[3].toHash()); bool ok; @@ -484,6 +486,7 @@ map State::addresses() const void State::resetCurrent() { m_transactions.clear(); + m_receipts.clear(); m_transactionSet.clear(); m_cache.clear(); m_currentBlock = BlockInfo(); @@ -547,7 +550,7 @@ h256s State::sync(TransactionQueue& _tq, bool* o_transactionQueueChanged) { uncommitToMine(); execute(i.second); - ret.push_back(m_transactions.back().changes.bloom()); + ret.push_back(m_receipts.back().changes().bloom()); _tq.noteGood(i); ++goodTxs; } @@ -713,7 +716,7 @@ void State::uncommitToMine() if (!m_transactions.size()) m_state.setRoot(m_previousBlock.stateRoot); else - m_state.setRoot(m_transactions[m_transactions.size() - 1].stateRoot); + m_state.setRoot(m_receipts[m_receipts.size() - 1].stateRoot()); m_db = m_lastTx; paranoia("Uncommited to mine", true); m_currentBlock.sha3Uncles = h256(); @@ -730,7 +733,7 @@ bool State::amIJustParanoid(BlockChain const& _bc) // Compile block: RLPStream block; block.appendList(3); - m_currentBlock.fillStream(block, true); + m_currentBlock.streamRLP(block, true); block.appendRaw(m_currentTxs); block.appendRaw(m_currentUncles); @@ -757,11 +760,20 @@ bool State::amIJustParanoid(BlockChain const& _bc) return false; } -h256 State::bloom() const +h256 State::oldBloom() const { h256 ret = m_currentBlock.coinbaseAddress.bloom(); - for (auto const& i: m_transactions) - ret |= i.changes.bloom(); + for (auto const& i: m_receipts) + ret |= i.changes().bloom(); + return ret; +} + +LogBloom State::logBloom() const +{ + LogBloom ret; + ret.shiftBloom<3>(sha3(m_currentBlock.coinbaseAddress.ref())); + for (TransactionReceipt const& i: m_receipts) + ret |= i.bloom(); return ret; } @@ -797,7 +809,7 @@ void State::commitToMine(BlockChain const& _bc) if (!knownUncles.count(u)) // ignore any uncles/mainline blocks that we know about. { BlockInfo ubi(_bc.block(u)); - ubi.fillStream(unclesData, true); + ubi.streamRLP(unclesData, true); ++unclesCount; uncleAddresses.push_back(ubi.coinbaseAddress); } @@ -805,8 +817,8 @@ void State::commitToMine(BlockChain const& _bc) } MemoryDB tm; - GenericTrieDB transactionReceipts(&tm); - transactionReceipts.init(); + GenericTrieDB receipts(&tm); + receipts.init(); RLPStream txs; txs.appendList(m_transactions.size()); @@ -816,16 +828,20 @@ void State::commitToMine(BlockChain const& _bc) RLPStream k; k << i; RLPStream v; - m_transactions[i].fillStream(v); - transactionReceipts.insert(&k.out(), &v.out()); - txs.appendRaw(v.out()); + m_receipts[i].streamRLP(v); + receipts.insert(&k.out(), &v.out()); + + RLPStream txrlp; + m_transactions[i].streamRLP(txrlp); + txs.appendRaw(txrlp.out()); } txs.swapOut(m_currentTxs); RLPStream(unclesCount).appendRaw(unclesData.out(), unclesCount).swapOut(m_currentUncles); - m_currentBlock.transactionsRoot = transactionReceipts.root(); + m_currentBlock.receiptsRoot = receipts.root(); + m_currentBlock.logBloom = logBloom(); m_currentBlock.sha3Uncles = sha3(m_currentUncles); // Apply rewards last of all. @@ -865,7 +881,7 @@ void State::completeMine() // Compile block: RLPStream ret; ret.appendList(3); - m_currentBlock.fillStream(ret, true); + m_currentBlock.streamRLP(ret, true); ret.appendRaw(m_currentTxs); ret.appendRaw(m_currentUncles); ret.swapOut(m_currentBytes); @@ -875,6 +891,7 @@ void State::completeMine() // Quickly reset the transactions. // TODO: Leave this in a better state than this limbo, or at least record that it's in limbo. m_transactions.clear(); + m_receipts.clear(); m_transactionSet.clear(); m_lastTx = m_db; } @@ -1114,7 +1131,8 @@ u256 State::execute(bytesConstRef _rlp, bytes* o_output, bool _commit) // TODO: CHECK TRIE after level DB flush to make sure exactly the same. // Add to the user-originated transactions that we've executed. - m_transactions.push_back(TransactionReceipt(e.t(), rootHash(), startGasUsed + e.gasUsed(), ms, e.logs())); + m_transactions.push_back(e.t()); + m_receipts.push_back(TransactionReceipt(rootHash(), startGasUsed + e.gasUsed(), e.logs(), ms)); m_transactionSet.insert(e.t().sha3()); return e.gasUsed(); } @@ -1185,6 +1203,12 @@ bool State::call(Address _receiveAddress, Address _codeAddress, Address _senderA return !revert; } + else + { + // non-contract call + if (o_sub) + o_sub->logs.push_back(LogEntry(_receiveAddress, {u256((u160)_senderAddress) + 1}, bytes())); + } return true; } @@ -1261,11 +1285,12 @@ State State::fromPending(unsigned _i) const if (!_i) ret.m_state.setRoot(m_previousBlock.stateRoot); else - ret.m_state.setRoot(m_transactions[_i - 1].stateRoot); + ret.m_state.setRoot(m_receipts[_i - 1].stateRoot()); while (ret.m_transactions.size() > _i) { - ret.m_transactionSet.erase(ret.m_transactions.back().transaction.sha3()); + ret.m_transactionSet.erase(ret.m_transactions.back().sha3()); ret.m_transactions.pop_back(); + ret.m_receipts.pop_back(); } return ret; } diff --git a/libethereum/State.h b/libethereum/State.h index d6087fc01..aa241fbef 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -52,26 +52,37 @@ 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; }; -struct TransactionReceipt +class TransactionReceipt { - TransactionReceipt(Transaction const& _t, h256 _root, u256 _gasUsed, Manifest const& _ms, LogEntries const& _logs): transaction(_t), stateRoot(_root), gasUsed(_gasUsed), changes(_ms), logs(_logs) {} +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; } -// Manifest const& changes() const { return 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 fillStream(RLPStream& _s) const + void streamRLP(RLPStream& _s) const { - _s.appendList(3); - transaction.fillStream(_s); - _s.append(stateRoot, false, true) << gasUsed; + _s.appendList(4) << m_stateRoot << m_gasUsed << m_bloom; + _s.appendList(m_log.size()); + for (LogEntry const& l: m_log) + l.streamRLP(_s); } - Transaction transaction; - h256 stateRoot; - u256 gasUsed; - Manifest changes; - LogEntries logs; +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; @@ -227,16 +238,25 @@ public: h256 rootHash() const { return m_state.root(); } /// Get the list of pending transactions. - Transactions pending() const { Transactions ret; for (auto const& t: m_transactions) ret.push_back(t.transaction); return ret; } + Transactions const& pending() const { return m_transactions; } + + /// Get the list of pending transactions. TODO: PoC-7: KILL + Manifest changesFromPending(unsigned _i) const { return m_receipts[_i].changes(); } + + /// Get the bloom filter of all changes happened in the block. TODO: PoC-7: KILL + h256 oldBloom() const; + + /// Get the bloom filter of a particular transaction that happened in the block. TODO: PoC-7: KILL + h256 oldBloom(unsigned _i) const { return m_receipts[_i].changes().bloom(); } /// Get the list of pending transactions. - Manifest changesFromPending(unsigned _i) const { return m_transactions[_i].changes; } + LogEntries const& log(unsigned _i) const { return m_receipts[_i].log(); } - /// Get the bloom filter of all changes happened in the block. - h256 bloom() const; + /// Get the bloom filter of all logs that happened in the block. + LogBloom logBloom() const; /// Get the bloom filter of a particular transaction that happened in the block. - h256 bloom(unsigned _i) const { return m_transactions[_i].changes.bloom(); } + LogBloom const& logBloom(unsigned _i) const { return m_receipts[_i].bloom(); } /// Get the State immediately after the given number of pending transactions have been applied. /// If (_i == 0) returns the initial state of the block. @@ -305,14 +325,15 @@ private: void refreshManifest(RLPStream* _txs = nullptr); /// @returns gas used by transactions thus far executed. - u256 gasUsed() const { return m_transactions.size() ? m_transactions.back().gasUsed : 0; } + u256 gasUsed() const { return m_receipts.size() ? m_receipts.back().gasUsed() : 0; } bool isTrieGood(bool _enforceRefs, bool _requireNoLeftOvers) const; void paranoia(std::string const& _when, bool _enforceRefs = false) const; OverlayDB m_db; ///< Our overlay for the state tree. TrieDB m_state; ///< Our state tree, as an OverlayDB DB. - std::vector m_transactions; ///< The current list of transactions that we've included in the state. + Transactions m_transactions; ///< The current list of transactions that we've included in the state. + TransactionReceipts m_receipts; ///< The corresponding list of transaction receipts. std::set m_transactionSet; ///< The set of transaction hashes that we've included in the state. OverlayDB m_lastTx; diff --git a/libethereum/Transaction.cpp b/libethereum/Transaction.cpp index b707efde3..bdc8bf34d 100644 --- a/libethereum/Transaction.cpp +++ b/libethereum/Transaction.cpp @@ -85,7 +85,7 @@ void Transaction::sign(Secret _priv) vrs = *(SignatureStruct const*)&sig; } -void Transaction::fillStream(RLPStream& _s, bool _sig) const +void Transaction::streamRLP(RLPStream& _s, bool _sig) const { _s.appendList((_sig ? 3 : 0) + 6); _s << nonce << gasPrice << gas; diff --git a/libethereum/Transaction.h b/libethereum/Transaction.h index ca73ba06a..2492e32bc 100644 --- a/libethereum/Transaction.h +++ b/libethereum/Transaction.h @@ -64,11 +64,11 @@ struct Transaction static h256 kFromMessage(h256 _msg, h256 _priv); - void fillStream(RLPStream& _s, bool _sig = true) const; - bytes rlp(bool _sig = true) const { RLPStream s; fillStream(s, _sig); return s.out(); } + void streamRLP(RLPStream& _s, bool _sig = true) const; + bytes rlp(bool _sig = true) const { RLPStream s; streamRLP(s, _sig); return s.out(); } std::string rlpString(bool _sig = true) const { return asString(rlp(_sig)); } - h256 sha3(bool _sig = true) const { RLPStream s; fillStream(s, _sig); return dev::sha3(s.out()); } - bytes sha3Bytes(bool _sig = true) const { RLPStream s; fillStream(s, _sig); return dev::sha3Bytes(s.out()); } + h256 sha3(bool _sig = true) const { RLPStream s; streamRLP(s, _sig); return dev::sha3(s.out()); } + bytes sha3Bytes(bool _sig = true) const { RLPStream s; streamRLP(s, _sig); return dev::sha3Bytes(s.out()); } private: mutable Address m_sender; diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h index 4aa3ee122..1b1ae7455 100644 --- a/libevm/ExtVMFace.h +++ b/libevm/ExtVMFace.h @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include #include @@ -34,10 +36,25 @@ namespace dev namespace eth { +using LogBloom = h512; + struct LogEntry { LogEntry() {} + LogEntry(RLP const& _r) { from = (Address)_r[0]; topics = (h256s)_r[1]; data = (bytes)_r[2]; } LogEntry(Address const& _f, h256s&& _ts, bytes&& _d): from(_f), topics(std::move(_ts)), data(std::move(_d)) {} + + void streamRLP(RLPStream& _s) const { _s.appendList(3) << from << topics << data; } + + LogBloom bloom() const + { + LogBloom ret; + ret.shiftBloom<3, 32>(sha3(from.ref())); + for (auto t: topics) + ret.shiftBloom<3, 32>(sha3(t.ref())); + return ret; + } + Address from; h256s topics; bytes data; @@ -45,6 +62,14 @@ struct LogEntry using LogEntries = std::vector; +inline LogBloom bloom(LogEntries const& _logs) +{ + LogBloom ret; + for (auto const& l: _logs) + ret |= l.bloom(); + return ret; +} + struct SubState { std::set
suicides; ///< Any accounts that have suicided. diff --git a/libevm/VM.h b/libevm/VM.h index 7e39623e1..4b17d9e73 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -703,7 +703,7 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con break; case Instruction::JUMPDEST: break; - case Instruction::LOG0: +/* case Instruction::LOG0: _ext.log({}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2])); break; case Instruction::LOG1: @@ -717,6 +717,21 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con break; case Instruction::LOG4: _ext.log({m_stack[m_stack.size() - 1], m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 3], m_stack[m_stack.size() - 4]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 5], (unsigned)m_stack[m_stack.size() - 6])); + break;*/ + case Instruction::LOG0: + _ext.log({}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2])); + break; + case Instruction::LOG1: + _ext.log({m_stack[m_stack.size() - 3]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2])); + break; + case Instruction::LOG2: + _ext.log({m_stack[m_stack.size() - 3], m_stack[m_stack.size() - 4]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2])); + break; + case Instruction::LOG3: + _ext.log({m_stack[m_stack.size() - 3], m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2])); + break; + case Instruction::LOG4: + _ext.log({m_stack[m_stack.size() - 3], m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5], m_stack[m_stack.size() - 6]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2])); break; case Instruction::CREATE: { diff --git a/liblll/Assembly.cpp b/liblll/Assembly.cpp index c26a9a98e..5b10138d1 100644 --- a/liblll/Assembly.cpp +++ b/liblll/Assembly.cpp @@ -147,7 +147,7 @@ ostream& dev::eth::operator<<(ostream& _out, AssemblyItemsConstRef _i) return _out; } -ostream& Assembly::streamOut(ostream& _out, string const& _prefix) const +ostream& Assembly::streamRLP(ostream& _out, string const& _prefix) const { _out << _prefix << ".code:" << endl; for (AssemblyItem const& i: m_items) @@ -189,7 +189,7 @@ ostream& Assembly::streamOut(ostream& _out, string const& _prefix) const for (auto const& i: m_subs) { _out << _prefix << " " << hex << (unsigned)(u256)i.first << ": " << endl; - i.second.streamOut(_out, _prefix + " "); + i.second.streamRLP(_out, _prefix + " "); } } return _out; diff --git a/liblll/Assembly.h b/liblll/Assembly.h index b7feaf4f4..8ab3062dc 100644 --- a/liblll/Assembly.h +++ b/liblll/Assembly.h @@ -104,11 +104,11 @@ public: void injectStart(AssemblyItem const& _i); - std::string out() const { std::stringstream ret; streamOut(ret); return ret.str(); } + std::string out() const { std::stringstream ret; streamRLP(ret); return ret.str(); } int deposit() const { return m_deposit; } bytes assemble() const; Assembly& optimise(bool _enable); - std::ostream& streamOut(std::ostream& _out, std::string const& _prefix = "") const; + std::ostream& streamRLP(std::ostream& _out, std::string const& _prefix = "") const; private: void donePath() { if (m_totalDeposit != INT_MAX && m_totalDeposit != m_deposit) BOOST_THROW_EXCEPTION(InvalidDeposit()); } @@ -127,7 +127,7 @@ private: inline std::ostream& operator<<(std::ostream& _out, Assembly const& _a) { - _a.streamOut(_out); + _a.streamRLP(_out); return _out; } diff --git a/libwhisper/Common.cpp b/libwhisper/Common.cpp index 11908d181..15b07e433 100644 --- a/libwhisper/Common.cpp +++ b/libwhisper/Common.cpp @@ -36,7 +36,7 @@ BuildTopic& BuildTopic::shiftBytes(bytes const& _b) h256 TopicFilter::sha3() const { RLPStream s; - fillStream(s); + streamRLP(s); return dev::sha3(s.out()); } diff --git a/libwhisper/Common.h b/libwhisper/Common.h index a85caafe1..21296e193 100644 --- a/libwhisper/Common.h +++ b/libwhisper/Common.h @@ -92,7 +92,7 @@ public: TopicFilter(TopicMasks const& _m): m_topicMasks(_m) {} TopicFilter(RLP const& _r): m_topicMasks((TopicMasks)_r) {} - void fillStream(RLPStream& _s) const { _s << m_topicMasks; } + void streamRLP(RLPStream& _s) const { _s << m_topicMasks; } h256 sha3() const; bool matches(Envelope const& _m) const; diff --git a/libwhisper/Message.h b/libwhisper/Message.h index 84214fd18..6b28073b7 100644 --- a/libwhisper/Message.h +++ b/libwhisper/Message.h @@ -55,9 +55,9 @@ public: operator bool() const { return !!m_expiry; } - void streamOut(RLPStream& _s, bool _withNonce) const { _s.appendList(_withNonce ? 5 : 4) << m_expiry << m_ttl << m_topic << m_data; if (_withNonce) _s << m_nonce; } - h256 sha3() const { RLPStream s; streamOut(s, true); return dev::sha3(s.out()); } - h256 sha3NoNonce() const { RLPStream s; streamOut(s, false); return dev::sha3(s.out()); } + void streamRLP(RLPStream& _s, bool _withNonce) const { _s.appendList(_withNonce ? 5 : 4) << m_expiry << m_ttl << m_topic << m_data; if (_withNonce) _s << m_nonce; } + h256 sha3() const { RLPStream s; streamRLP(s, true); return dev::sha3(s.out()); } + h256 sha3NoNonce() const { RLPStream s; streamRLP(s, false); return dev::sha3(s.out()); } unsigned sent() const { return m_expiry - m_ttl; } unsigned expiry() const { return m_expiry; } diff --git a/libwhisper/WhisperHost.cpp b/libwhisper/WhisperHost.cpp index 591574bf0..71030aae2 100644 --- a/libwhisper/WhisperHost.cpp +++ b/libwhisper/WhisperHost.cpp @@ -48,8 +48,8 @@ void WhisperHost::streamMessage(h256 _m, RLPStream& _s) const { UpgradeGuard ll(l); auto const& m = m_messages.at(_m); - cnote << "streamOut: " << m.expiry() << m.ttl() << m.topic() << toHex(m.data()); - m.streamOut(_s, true); + cnote << "streamRLP: " << m.expiry() << m.ttl() << m.topic() << toHex(m.data()); + m.streamRLP(_s, true); } } diff --git a/test/main.cpp b/test/main.cpp index ef009e299..3f8860d7a 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -44,7 +44,7 @@ using namespace dev::eth; BOOST_AUTO_TEST_CASE(basic_tests) { /* RLPStream s; - BlockInfo::genesis().fillStream(s, false); + BlockInfo::genesis().streamRLP(s, false); std::cout << RLP(s.out()) << std::endl; std::cout << toHex(s.out()) << std::endl; std::cout << sha3(s.out()) << std::endl;*/