diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp
index 810fea580..918a28916 100644
--- a/alethzero/MainWin.cpp
+++ b/alethzero/MainWin.cpp
@@ -883,6 +883,7 @@ void Main::on_blocks_currentItemChanged()
s << "
Coinbase: " << pretty(info.coinbaseAddress).toHtmlEscaped().toStdString() << " " << info.coinbaseAddress;
s << "
Nonce: " << info.nonce << "";
s << "
Parent: " << info.parentHash << "";
+ s << "
Bloom: " << details.bloom << "";
s << "
Transactions: " << block[1].itemCount() << " @" << info.transactionsRoot << "";
s << "
Uncles: " << block[2].itemCount() << " @" << info.sha3Uncles << "";
s << "
Pre: " << BlockInfo(m_client->blockChain().block(info.parentHash)).stateRoot << "";
diff --git a/libethential/FixedHash.h b/libethential/FixedHash.h
index 55d8a5cc8..f792e378d 100644
--- a/libethential/FixedHash.h
+++ b/libethential/FixedHash.h
@@ -50,9 +50,15 @@ public:
/// Method to convert from a string.
enum ConstructFromStringType { FromHex, FromBinary };
+ /// Method to convert from a string.
+ enum ConstructFromHashType { AlignLeft, AlignRight };
+
/// Construct an empty hash.
FixedHash() { m_data.fill(0); }
+ /// Construct from another hash, filling with zeroes or cropping as necessary.
+ template FixedHash(FixedHash const& _h, ConstructFromHashType _t = AlignLeft) { m_data.fill(0); unsigned c = std::min(M, N); for (unsigned i = 0; i < c; ++i) m_data[_t == AlignRight ? N - 1 - i : i] = _h[_t == AlignRight ? M - 1 - i : i]; }
+
/// Convert from the corresponding arithmetic type.
FixedHash(Arith const& _arith) { toBigEndian(_arith, m_data); }
@@ -85,6 +91,9 @@ public:
FixedHash operator&(FixedHash const& _c) const { return FixedHash(*this) &= _c; }
FixedHash& operator~() { for (auto i = 0; i < N; ++i) m_data[i] = ~m_data[i]; return *this; }
+ /// @returns true if all bytes in @a _c are set in this object.
+ bool contains(FixedHash const& _c) const { return (*this & _c) == _c; }
+
/// @returns a particular byte from the hash.
byte& operator[](unsigned _i) { return m_data[_i]; }
/// @returns a particular byte from the hash.
diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp
index 8b09f5fae..004b28454 100644
--- a/libethereum/BlockChain.cpp
+++ b/libethereum/BlockChain.cpp
@@ -59,11 +59,12 @@ BlockDetails::BlockDetails(RLP const& _r)
totalDifficulty = _r[1].toInt();
parent = _r[2].toHash();
children = _r[3].toVector();
+ bloom = _r[4].isNull() ? ~h256() : _r[4].toHash();
}
bytes BlockDetails::rlp() const
{
- return rlpList(number, totalDifficulty, parent, children);
+ return rlpList(number, totalDifficulty, parent, children, bloom);
}
std::map const& eth::genesisState()
@@ -133,7 +134,7 @@ BlockChain::BlockChain(std::string _path, bool _killExisting)
if (!details(m_genesisHash))
{
// Insert details of genesis block.
- m_details[m_genesisHash] = BlockDetails(0, c_genesisDifficulty, h256(), {});
+ m_details[m_genesisHash] = BlockDetails(0, c_genesisDifficulty, h256(), {}, h256());
auto r = m_details[m_genesisHash].rlp();
m_detailsDB->Put(m_writeOptions, ldb::Slice((char const*)&m_genesisHash, 32), (ldb::Slice)eth::ref(r));
}
@@ -238,6 +239,7 @@ void 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();
s.cleanup(true);
td = pd.totalDifficulty + tdIncrease;
@@ -247,7 +249,7 @@ void BlockChain::import(bytes const& _block, OverlayDB const& _db)
// All ok - insert into DB
{
lock_guard l(m_lock);
- m_details[newHash] = BlockDetails((uint)pd.number + 1, td, bi.parentHash, {});
+ m_details[newHash] = BlockDetails((uint)pd.number + 1, td, bi.parentHash, {}, b);
m_details[bi.parentHash].children.push_back(newHash);
}
diff --git a/libethereum/BlockChain.h b/libethereum/BlockChain.h
index ffab54ddd..025181396 100644
--- a/libethereum/BlockChain.h
+++ b/libethereum/BlockChain.h
@@ -37,7 +37,7 @@ class RLPStream;
struct BlockDetails
{
BlockDetails(): number(0), totalDifficulty(0) {}
- BlockDetails(uint _n, u256 _tD, h256 _p, h256s _c): number(_n), totalDifficulty(_tD), parent(_p), children(_c) {}
+ BlockDetails(uint _n, u256 _tD, h256 _p, h256s _c, h256 _bloom): number(_n), totalDifficulty(_tD), parent(_p), children(_c), bloom(_bloom) {}
BlockDetails(RLP const& _r);
bytes rlp() const;
@@ -48,7 +48,7 @@ struct BlockDetails
u256 totalDifficulty;
h256 parent;
h256s children;
- // TODO: add trace bloom
+ h256 bloom;
};
// TODO: DB for full traces.
diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp
index 2faa4d425..f4f59530e 100644
--- a/libethereum/Client.cpp
+++ b/libethereum/Client.cpp
@@ -335,8 +335,45 @@ bytes Client::codeAt(Address _a, int _block) const
return asOf(_block).code(_a);
}
+bool TransactionFilter::matches(h256 _bloom) const
+{
+ auto have = [=](Address const& a) { return _bloom.contains(a.bloom()); };
+ if (m_from.size())
+ {
+ for (auto i: m_from)
+ if (have(i))
+ goto OK1;
+ return false;
+ }
+ OK1:
+ if (m_to.size())
+ {
+ for (auto i: m_to)
+ if (have(i))
+ goto OK2;
+ return false;
+ }
+ OK2:
+ if (m_stateAltered.size() || m_altered.size())
+ {
+ for (auto i: m_altered)
+ if (have(i))
+ goto OK3;
+ for (auto i: m_stateAltered)
+ if (have(i.first) && _bloom.contains(h256(i.second).bloom()))
+ goto OK3;
+ return false;
+ }
+ OK3:
+ return true;
+}
+
bool TransactionFilter::matches(State const& _s, unsigned _i) const
{
+ h256 b = _s.changesFromPending(_i).bloom();
+ if (!matches(b))
+ return false;
+
Transaction t = _s.pending()[_i];
if (!m_to.empty() && !m_to.count(t.receiveAddress))
return false;
@@ -388,29 +425,42 @@ PastTransactions Client::transactions(TransactionFilter const& _f) const
return ret;
}
+ unsigned skipped = 0;
+ unsigned falsePos = 0;
auto cn = m_bc.number();
auto h = m_bc.numberHash(begin);
- for (unsigned n = begin; ret.size() != m && n != end; n--, h = m_bc.details(h).parent)
+ unsigned n = begin;
+ for (; ret.size() != m && n != end; n--, h = m_bc.details(h).parent)
{
- try
- {
- State st(m_stateDB, m_bc, h);
- for (unsigned i = st.pending().size(); i-- && ret.size() != m;)
- if (_f.matches(st, i))
- {
- if (s)
- s--;
- else
- ret.insert(ret.begin(), PastTransaction(st.pending()[i], h, i, BlockInfo(m_bc.block(h)).timestamp, cn - n + 2));
- }
- }
- catch (...)
+ auto d = m_bc.details(h);
+ if (_f.matches(d.bloom))
{
- // Gaa. bad state. not good at all. bury head in sand for now.
+ try
+ {
+ State st(m_stateDB, m_bc, h);
+ unsigned os = s;
+ for (unsigned i = st.pending().size(); i-- && ret.size() != m;)
+ if (_f.matches(st, i))
+ {
+ if (s)
+ s--;
+ else
+ ret.insert(ret.begin(), PastTransaction(st.pending()[i], h, i, BlockInfo(m_bc.block(h)).timestamp, cn - n + 2));
+ }
+ if (os - s == st.pending().size())
+ falsePos++;
+ }
+ catch (...)
+ {
+ // Gaa. bad state. not good at all. bury head in sand for now.
+ }
}
+ else
+ skipped++;
if (n == end)
break;
}
+ cdebug << (begin - n) << "searched; " << skipped << "skipped; " << falsePos << "false +ves";
return ret;
}
diff --git a/libethereum/Client.h b/libethereum/Client.h
index cbfdcd6e5..6908de228 100644
--- a/libethereum/Client.h
+++ b/libethereum/Client.h
@@ -88,6 +88,7 @@ public:
int latest() const { return m_latest; }
unsigned max() const { return m_max; }
unsigned skip() const { return m_skip; }
+ bool matches(h256 _bloom) const;
bool matches(State const& _s, unsigned _i) const;
TransactionFilter from(Address _a) { m_from.insert(_a); return *this; }
diff --git a/libethereum/PeerServer.cpp b/libethereum/PeerServer.cpp
index 49d897bb4..275d9ace7 100644
--- a/libethereum/PeerServer.cpp
+++ b/libethereum/PeerServer.cpp
@@ -339,6 +339,17 @@ bool PeerServer::ensureInitialised(BlockChain& _bc, TransactionQueue& _tq)
return false;
}
+bool PeerServer::noteBlock(h256 _hash, bytesConstRef _data)
+{
+ if (!m_chain->details(_hash))
+ {
+ lock_guard l(m_incomingLock);
+ m_incomingBlocks.push_back(_data.toBytes());
+ return true;
+ }
+ return false;
+}
+
bool PeerServer::sync(BlockChain& _bc, TransactionQueue& _tq, OverlayDB& _o)
{
bool ret = ensureInitialised(_bc, _tq);
@@ -404,7 +415,7 @@ bool PeerServer::sync(BlockChain& _bc, TransactionQueue& _tq, OverlayDB& _o)
for (int accepted = 1, n = 0; accepted; ++n)
{
accepted = 0;
-
+ lock_guard l(m_incomingLock);
if (m_incomingBlocks.size())
for (auto it = prev(m_incomingBlocks.end());; --it)
{
diff --git a/libethereum/PeerServer.h b/libethereum/PeerServer.h
index ec67b8469..6e44d2ea4 100644
--- a/libethereum/PeerServer.h
+++ b/libethereum/PeerServer.h
@@ -21,6 +21,7 @@
#pragma once
+#include
#include