From 1d16e1556fc4ffe0c57c1781fc77aa3ac236f64a Mon Sep 17 00:00:00 2001
From: Gav Wood
Date: Tue, 4 Nov 2014 18:11:06 +0000
Subject: [PATCH] Ready for move to log entries in JS API.
---
libdevcore/FixedHash.h | 5 ++
libdevcrypto/Common.h | 3 +
libdevcrypto/SHA3.h | 3 +
libethereum/MessageFilter.cpp | 55 ++++++++++++++++
libethereum/MessageFilter.h | 34 ++++++++++
libethereum/State.cpp | 3 +-
libevm/ExtVMFace.h | 20 ++++--
libweb3jsonrpc/WebThreeStubServer.cpp | 71 ++++++++++++++++++---
libweb3jsonrpc/WebThreeStubServer.h | 4 +-
libweb3jsonrpc/abstractwebthreestubserver.h | 7 --
libweb3jsonrpc/spec.json | 1 -
11 files changed, 181 insertions(+), 25 deletions(-)
diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h
index 02d199f62..2353a100c 100644
--- a/libdevcore/FixedHash.h
+++ b/libdevcore/FixedHash.h
@@ -163,6 +163,11 @@ public:
return (*this |= _h.template nbloom
());
}
+ template inline bool containsBloom(FixedHash const& _h)
+ {
+ return contains(_h.template nbloom());
+ }
+
template inline FixedHash nbloom() const
{
static const unsigned c_bloomBits = M * 8;
diff --git a/libdevcrypto/Common.h b/libdevcrypto/Common.h
index 7f2a8192e..4b4d34d87 100644
--- a/libdevcrypto/Common.h
+++ b/libdevcrypto/Common.h
@@ -50,6 +50,9 @@ using Address = h160;
/// A vector of Ethereum addresses.
using Addresses = h160s;
+/// A vector of Ethereum addresses.
+using AddressSet = std::set;
+
/// A vector of secrets.
using Secrets = h256s;
diff --git a/libdevcrypto/SHA3.h b/libdevcrypto/SHA3.h
index 1575ab29c..7aa4db246 100644
--- a/libdevcrypto/SHA3.h
+++ b/libdevcrypto/SHA3.h
@@ -56,6 +56,9 @@ inline h256 sha3(bytes const& _input) { return sha3(bytesConstRef((bytes*)&_inpu
/// Calculate SHA3-256 hash of the given input (presented as a binary-filled string), returning as a 256-bit hash.
inline h256 sha3(std::string const& _input) { return sha3(bytesConstRef(_input)); }
+/// Calculate SHA3-256 hash of the given input (presented as a FixedHash), returns a 256-bit hash.
+template inline h256 sha3(FixedHash const& _input) { return sha3(_input.ref()); }
+
extern h256 EmptySHA3;
extern h256 EmptyListSHA3;
diff --git a/libethereum/MessageFilter.cpp b/libethereum/MessageFilter.cpp
index fc6af1308..88f1a24f9 100644
--- a/libethereum/MessageFilter.cpp
+++ b/libethereum/MessageFilter.cpp
@@ -149,3 +149,58 @@ bool MessageFilter::matches(Manifest const& _m, vector _p, Address _o,
return ret;
}
+
+
+
+void LogFilter::streamRLP(RLPStream& _s) const
+{
+ _s.appendList(6) << m_addresses << m_topics << m_earliest << m_latest << m_max << m_skip;
+}
+
+h256 LogFilter::sha3() const
+{
+ RLPStream s;
+ streamRLP(s);
+ return dev::sha3(s.out());
+}
+
+bool LogFilter::matches(LogBloom _bloom) const
+{
+ if (m_addresses.size())
+ {
+ for (auto i: m_addresses)
+ if (_bloom.containsBloom<3>(dev::sha3(i)))
+ goto OK1;
+ return false;
+ }
+ OK1:
+ if (m_topics.size())
+ {
+ for (auto i: m_topics)
+ if (_bloom.containsBloom<3>(dev::sha3(i)))
+ goto OK2;
+ return false;
+ }
+ OK2:
+ return true;
+}
+
+bool LogFilter::matches(State const& _s, unsigned _i) const
+{
+ return matches(_s.receipt(_i)).size() > 0;
+}
+
+LogEntries LogFilter::matches(TransactionReceipt const& _m) const
+{
+ LogEntries ret;
+ for (LogEntry const& e: _m.log())
+ {
+ if (!m_addresses.empty() && !m_addresses.count(e.address))
+ continue;
+ for (auto const& t: m_topics)
+ if (!e.topics.count(t))
+ continue;
+ ret.push_back(e);
+ }
+ return ret;
+}
diff --git a/libethereum/MessageFilter.h b/libethereum/MessageFilter.h
index 83cbb7237..5602d7a17 100644
--- a/libethereum/MessageFilter.h
+++ b/libethereum/MessageFilter.h
@@ -25,6 +25,7 @@
#include
#include
#include "PastMessage.h"
+#include "TransactionReceipt.h"
namespace dev
{
@@ -72,5 +73,38 @@ private:
unsigned m_skip;
};
+class LogFilter
+{
+public:
+ LogFilter(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 streamRLP(RLPStream& _s) const;
+ h256 sha3() const;
+
+ int earliest() const { return m_earliest; }
+ int latest() const { return m_latest; }
+ unsigned max() const { return m_max; }
+ unsigned skip() const { return m_skip; }
+ bool matches(LogBloom _bloom) const;
+ bool matches(State const& _s, unsigned _i) const;
+ LogEntries matches(TransactionReceipt const& _r) const;
+
+ LogFilter address(Address _a) { m_addresses.insert(_a); return *this; }
+ LogFilter from(Address _a) { return topic(u256((u160)_a) + 1); }
+ LogFilter topic(h256 const& _t) { m_topics.insert(_t); return *this; }
+ LogFilter withMax(unsigned _m) { m_max = _m; return *this; }
+ LogFilter withSkip(unsigned _m) { m_skip = _m; return *this; }
+ LogFilter withEarliest(int _e) { m_earliest = _e; return *this; }
+ LogFilter withLatest(int _e) { m_latest = _e; return *this; }
+
+private:
+ AddressSet m_addresses;
+ h256Set m_topics;
+ int m_earliest = 0;
+ int m_latest = -1;
+ unsigned m_max;
+ unsigned m_skip;
+};
+
}
}
diff --git a/libethereum/State.cpp b/libethereum/State.cpp
index 51f5901c5..cd1a7f541 100644
--- a/libethereum/State.cpp
+++ b/libethereum/State.cpp
@@ -791,7 +791,8 @@ h256 State::oldBloom() const
LogBloom State::logBloom() const
{
LogBloom ret;
- ret.shiftBloom<3>(sha3(m_currentBlock.coinbaseAddress.ref()));
+ auto sa = sha3(m_currentBlock.coinbaseAddress.ref());
+ ret.shiftBloom<3>(sa);
for (TransactionReceipt const& i: m_receipts)
ret |= i.bloom();
return ret;
diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h
index 1b1ae7455..9f662087c 100644
--- a/libevm/ExtVMFace.h
+++ b/libevm/ExtVMFace.h
@@ -36,27 +36,35 @@ namespace dev
namespace eth
{
+template inline std::set toSet(std::vector const& _ts)
+{
+ std::set ret;
+ for (auto const& t: _ts)
+ ret.insert(t);
+ return ret;
+}
+
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)) {}
+ LogEntry(RLP const& _r) { address = (Address)_r[0]; topics = (h256Set)_r[1]; data = (bytes)_r[2]; }
+ LogEntry(Address const& _address, h256s const& _ts, bytes&& _d): address(_address), topics(toSet(_ts)), data(std::move(_d)) {}
- void streamRLP(RLPStream& _s) const { _s.appendList(3) << from << topics << data; }
+ void streamRLP(RLPStream& _s) const { _s.appendList(3) << address << topics << data; }
LogBloom bloom() const
{
LogBloom ret;
- ret.shiftBloom<3, 32>(sha3(from.ref()));
+ ret.shiftBloom<3, 32>(sha3(address.ref()));
for (auto t: topics)
ret.shiftBloom<3, 32>(sha3(t.ref()));
return ret;
}
- Address from;
- h256s topics;
+ Address address;
+ h256Set topics;
bytes data;
};
diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp
index e7eb62e04..4ac048ee9 100644
--- a/libweb3jsonrpc/WebThreeStubServer.cpp
+++ b/libweb3jsonrpc/WebThreeStubServer.cpp
@@ -97,6 +97,24 @@ static Json::Value toJson(dev::eth::Transaction const& _t)
return res;
}
+static Json::Value toJson(dev::eth::LogEntry const& _e)
+{
+ Json::Value res;
+ res["data"] = jsFromBinary(_e.data);
+ res["address"] = toJS(_e.address);
+ for (auto const& t: _e.topics)
+ res["topics"].append(toJS(t));
+ return res;
+}
+
+static Json::Value toJson(dev::eth::LogEntries const& _es)
+{
+ Json::Value res;
+ for (dev::eth::LogEntry const& e: _es)
+ res.append(toJson(e));
+ return res;
+}
+
static dev::eth::MessageFilter toMessageFilter(Json::Value const& _json)
{
dev::eth::MessageFilter filter;
@@ -123,9 +141,9 @@ static dev::eth::MessageFilter toMessageFilter(Json::Value const& _json)
{
if (_json["to"].isArray())
for (auto i : _json["to"])
- filter.from(jsToAddress(i.asString()));
+ filter.to(jsToAddress(i.asString()));
else
- filter.from(jsToAddress(_json["to"].asString()));
+ filter.to(jsToAddress(_json["to"].asString()));
}
if (!_json["altered"].empty())
{
@@ -143,6 +161,48 @@ static dev::eth::MessageFilter toMessageFilter(Json::Value const& _json)
return filter;
}
+static dev::eth::LogFilter toLogFilter(Json::Value const& _json)
+{
+ dev::eth::LogFilter filter;
+ if (!_json.isObject() || _json.empty())
+ return filter;
+
+ if (!_json["earliest"].empty())
+ filter.withEarliest(_json["earliest"].asInt());
+ if (!_json["latest"].empty())
+ filter.withLatest(_json["lastest"].asInt());
+ if (!_json["max"].empty())
+ filter.withMax(_json["max"].asInt());
+ if (!_json["skip"].empty())
+ filter.withSkip(_json["skip"].asInt());
+ if (!_json["from"].empty())
+ {
+ if (_json["from"].isArray())
+ for (auto i : _json["from"])
+ filter.from(jsToAddress(i.asString()));
+ else
+ filter.from(jsToAddress(_json["from"].asString()));
+ }
+ if (!_json["address"].empty())
+ {
+ if (_json["address"].isArray())
+ for (auto i : _json["address"])
+ filter.address(jsToAddress(i.asString()));
+ else
+ filter.from(jsToAddress(_json["address"].asString()));
+ }
+ if (!_json["topics"].empty())
+ {
+ if (_json["topics"].isArray())
+ for (auto i: _json["topics"])
+ if (i.isString())
+ filter.topic(jsToU256(i.asString()));
+ else if(_json["topics"].isString())
+ filter.topic(jsToU256(_json["topics"].asString()));
+ }
+ return filter;
+}
+
static shh::Message toMessage(Json::Value const& _json)
{
shh::Message ret;
@@ -252,13 +312,6 @@ std::shared_ptr WebThreeStubServer::face() const
return m_web3.whisper();
}
-std::string WebThreeStubServer::account()
-{
- if (!m_accounts.empty())
- return toJS(m_accounts.begin()->first);
- return "";
-}
-
Json::Value WebThreeStubServer::accounts()
{
Json::Value ret(Json::arrayValue);
diff --git a/libweb3jsonrpc/WebThreeStubServer.h b/libweb3jsonrpc/WebThreeStubServer.h
index b18faf95a..33163b75e 100644
--- a/libweb3jsonrpc/WebThreeStubServer.h
+++ b/libweb3jsonrpc/WebThreeStubServer.h
@@ -56,13 +56,14 @@ class Interface;
* @brief JSON-RPC api implementation
* @todo filters should work on unsigned instead of int
* unsigned are not supported in json-rpc-cpp and there are bugs with double in json-rpc-cpp version 0.2.1
+ * @todo split these up according to subprotocol (eth, shh, db, p2p, web3) and make it /very/ clear about how to add other subprotocols.
+ * @todo modularise everything so additional subprotocols don't need to change this file.
*/
class WebThreeStubServer: public AbstractWebThreeStubServer
{
public:
WebThreeStubServer(jsonrpc::AbstractServerConnector* _conn, dev::WebThreeDirect& _web3, std::vector const& _accounts);
- virtual std::string account();
virtual Json::Value accounts();
virtual std::string addToGroup(std::string const& _group, std::string const& _who);
virtual std::string balanceAt(std::string const& _address);
@@ -109,6 +110,7 @@ public:
void setAccounts(std::vector const& _accounts);
void setIdentities(std::vector const& _ids);
std::map const& ids() const { return m_ids; }
+
private:
dev::eth::Interface* client() const;
std::shared_ptr face() const;
diff --git a/libweb3jsonrpc/abstractwebthreestubserver.h b/libweb3jsonrpc/abstractwebthreestubserver.h
index ac6893933..66b9ff77d 100644
--- a/libweb3jsonrpc/abstractwebthreestubserver.h
+++ b/libweb3jsonrpc/abstractwebthreestubserver.h
@@ -13,7 +13,6 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer(conn)
{
- this->bindAndAddMethod(new jsonrpc::Procedure("account", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::accountI);
this->bindAndAddMethod(new jsonrpc::Procedure("accounts", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, NULL), &AbstractWebThreeStubServer::accountsI);
this->bindAndAddMethod(new jsonrpc::Procedure("addToGroup", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::addToGroupI);
this->bindAndAddMethod(new jsonrpc::Procedure("balanceAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::balanceAtI);
@@ -59,11 +58,6 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServeraccount();
- }
-
inline virtual void accountsI(const Json::Value& request, Json::Value& response)
{
response = this->accounts();
@@ -275,7 +269,6 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer