diff --git a/CMakeLists.txt b/CMakeLists.txt index 01f60bbf5..912812947 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -292,12 +292,24 @@ else() set(QTQML 1) endif() +if(CRYPTOPP_ID) include_directories(${CRYPTOPP_ID}) +endif() +if(PYTHON_ID) include_directories(${PYTHON_ID}) +endif() +if(MINIUPNPC_ID) include_directories(${MINIUPNPC_ID}) +endif() +if(LEVELDB_ID) include_directories(${LEVELDB_ID}) +endif() +if(READLINE_ID) include_directories(${READLINE_ID}) -include_directories(${JSONRPC_ID}) +endif() +if(JSONRPC_ID) + include_directories(${JSONRPC_ID}) +endif() # if (NOT APPLE) # link_directories(${CRYPTOPP_LS}) diff --git a/eth/CMakeLists.txt b/eth/CMakeLists.txt index ba5f3e509..350c22f80 100644 --- a/eth/CMakeLists.txt +++ b/eth/CMakeLists.txt @@ -13,11 +13,17 @@ add_executable(${EXECUTABLE} ${SRC_LIST}) target_link_libraries(${EXECUTABLE} ethereum) target_link_libraries(${EXECUTABLE} secp256k1) target_link_libraries(${EXECUTABLE} gmp) -target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) +if(MINIUPNPC_LS) + target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) +endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LS}) +if(JSONRPC_LS) target_link_libraries(${EXECUTABLE} ${JSONRPC_LS}) +endif() +if(READLINE_LS) target_link_libraries(${EXECUTABLE} ${READLINE_LS}) +endif() if (${TARGET_PLATFORM} STREQUAL "w64") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") diff --git a/exp/CMakeLists.txt b/exp/CMakeLists.txt index e894bc716..45a30adbc 100644 --- a/exp/CMakeLists.txt +++ b/exp/CMakeLists.txt @@ -9,12 +9,12 @@ set(EXECUTABLE exp) add_executable(${EXECUTABLE} ${SRC_LIST}) target_link_libraries(${EXECUTABLE} ethereum) +target_link_libraries(${EXECUTABLE} gmp) target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LS}) +if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) +endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) -target_link_libraries(${EXECUTABLE} ${JSONRPC_LS}) -target_link_libraries(${EXECUTABLE} ${READLINE_LS}) -target_link_libraries(${EXECUTABLE} gmp) if (${TARGET_PLATFORM} STREQUAL "w64") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") diff --git a/libethcore/CMakeLists.txt b/libethcore/CMakeLists.txt index 590b1b5e3..414201614 100644 --- a/libethcore/CMakeLists.txt +++ b/libethcore/CMakeLists.txt @@ -17,9 +17,11 @@ include_directories(..) target_link_libraries(${EXECUTABLE} ethential) target_link_libraries(${EXECUTABLE} secp256k1) +target_link_libraries(${EXECUTABLE} gmp) +if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) +endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) -target_link_libraries(${EXECUTABLE} gmp) target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LS}) if(${TARGET_PLATFORM} STREQUAL "w64") diff --git a/libethereum/CMakeLists.txt b/libethereum/CMakeLists.txt index ca298814f..9b0a507aa 100644 --- a/libethereum/CMakeLists.txt +++ b/libethereum/CMakeLists.txt @@ -21,7 +21,9 @@ target_link_libraries(${EXECUTABLE} evm) target_link_libraries(${EXECUTABLE} lll) target_link_libraries(${EXECUTABLE} ethcore) target_link_libraries(${EXECUTABLE} secp256k1) +if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) +endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LS}) target_link_libraries(${EXECUTABLE} gmp) diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 98d2899f9..2a3b3f29d 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -327,8 +327,73 @@ bytes Client::codeAt(Address _a, int _block) const return asOf(_block).code(_a); } +bool TransactionFilter::matches(State const& _s, unsigned _i) const +{ + Transaction t = _s.pending()[_i]; + if (!m_to.empty() && !m_to.count(t.receiveAddress)) + return false; + if (!m_from.empty() && !m_from.count(t.sender())) + return false; + if (m_stateAltered.empty() && m_altered.empty()) + return true; + StateDiff d = _s.pendingDiff(_i); + if (!m_stateAltered.empty()) + { + for (auto const& s: m_stateAltered) + if (d.accounts.count(s.first) && d.accounts.at(s.first).storage.count(s.second)) + goto OK; + return false; + OK:; + } + if (!m_altered.empty()) + { + for (auto const& s: m_altered) + if (d.accounts.count(s)) + goto OK2; + return false; + OK2:; + } + return true; +} + Transactions Client::transactions(TransactionFilter const& _f) const { Transactions ret; + unsigned begin = numberOf(_f.latest()); + unsigned end = min(begin, numberOf(_f.earliest())); + unsigned m = _f.max(); + unsigned s = _f.skip(); + + // Handle pending transactions differently as they're not on the block chain. + if (_f.latest() == 0) + { + for (unsigned i = m_postMine.pending().size(); i--;) + if (_f.matches(m_postMine, i)) + { + if (s) + s--; + else + ret.insert(ret.begin(), m_postMine.pending()[i]); + } + // Early exit here since we can't rely on begin/end, being out of the blockchain as we are. + if (_f.earliest() == 0) + return ret; + } + + auto h = m_bc.numberHash(begin); + for (unsigned n = begin; ret.size() != m; n--, h = m_bc.details(h).parent) + { + State st(m_stateDB, m_bc, h); + for (unsigned i = st.pending().size(); i--;) + if (_f.matches(st, i)) + { + if (s) + s--; + else + ret.insert(ret.begin(), st.pending()[i]); + } + if (n == end) + break; + } return ret; } diff --git a/libethereum/Client.h b/libethereum/Client.h index 9c8bf0e9c..8316e33c4 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -77,29 +77,39 @@ private: unsigned m_protocolVersion; }; +static const int GenesisBlock = INT_MIN; + class TransactionFilter { public: - TransactionFilter(int _blockFrom = 0, int _blockTo = -1, unsigned _max = 10): m_blockFrom(_blockFrom), m_blockTo(_blockTo), m_max(_max) {} + TransactionFilter(int _earliest = GenesisBlock, int _latest = 0, unsigned _max = 10, unsigned _skip = 0): m_earliest(_earliest), m_latest(_latest), m_max(_max), m_skip(_skip) {} + + 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(State const& _s, unsigned _i) const; TransactionFilter from(Address _a) { m_from.insert(_a); return *this; } TransactionFilter to(Address _a) { m_to.insert(_a); return *this; } TransactionFilter stateAltered(Address _a, u256 _l) { m_stateAltered.insert(std::make_pair(_a, _l)); return *this; } TransactionFilter stateAltered(Address _a) { m_altered.insert(_a); return *this; } TransactionFilter withMax(unsigned _m) { m_max = _m; return *this; } + TransactionFilter withSkip(unsigned _m) { m_skip = _m; return *this; } + TransactionFilter withEarliest(int _e) { m_earliest = _e; return *this; } + TransactionFilter withLatest(int _e) { m_latest = _e; return *this; } private: std::set
m_from; std::set
m_to; std::set> m_stateAltered; std::set
m_altered; - int m_blockFrom; - int m_blockTo; + int m_earliest; + int m_latest; unsigned m_max; + unsigned m_skip; }; -static const int GenesisBlock = INT_MIN; - /** * @brief Main API hub for interfacing with Ethereum. */ diff --git a/libevm/CMakeLists.txt b/libevm/CMakeLists.txt index bf18d658e..b994204b1 100644 --- a/libevm/CMakeLists.txt +++ b/libevm/CMakeLists.txt @@ -22,7 +22,9 @@ target_link_libraries(${EXECUTABLE} evmface) target_link_libraries(${EXECUTABLE} ethential) target_link_libraries(${EXECUTABLE} secp256k1) target_link_libraries(${EXECUTABLE} gmp) +if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) +endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LS}) diff --git a/libqethereum/QEthereum.cpp b/libqethereum/QEthereum.cpp index 3b70c2019..1a39581ab 100644 --- a/libqethereum/QEthereum.cpp +++ b/libqethereum/QEthereum.cpp @@ -252,6 +252,7 @@ void QEthereum::setup(QWebFrame* _e) _e->evaluateJavaScript("eth.watch = function(a, s, f) { eth.changed.connect(f ? f : s) }"); _e->evaluateJavaScript("eth.create = function(s, v, c, g, p, f) { var v = eth.doCreate(s, v, c, g, p); if (f) f(v) }"); _e->evaluateJavaScript("eth.transact = function(s, v, t, d, g, p, f) { eth.doTransact(s, v, t, d, g, p); if (f) f() }"); + _e->evaluateJavaScript("eth.transactions = function(a) { return eval(eth.getTransactions(a)); }"); _e->evaluateJavaScript("String.prototype.pad = function(l, r) { return eth.pad(this, l, r) }"); _e->evaluateJavaScript("String.prototype.bin = function() { return eth.toBinary(this) }"); _e->evaluateJavaScript("String.prototype.unbin = function(l) { return eth.fromBinary(this) }"); @@ -384,6 +385,36 @@ double QEthereum::countAt(QString _a, int _block) const return (double)(uint64_t)client()->countAt(toAddress(_a), _block); } +QString QEthereum::getTransactions(QString _a) const +{ + eth::TransactionFilter filter; + + QJsonObject f = QJsonDocument::fromJson(_a.toUtf8()).object(); + if (f.contains("earliest")) + filter.withEarliest(f["earliest"].toInt()); + if (f.contains("latest")) + filter.withLatest(f["latest"].toInt()); + if (f.contains("max")) + filter.withMax(f["max"].toInt()); + if (f.contains("skip")) + filter.withSkip(f["skip"].toInt()); + + QJsonArray ret; + for (Transaction const& t: m_client->transactions(filter)) + { + QJsonObject v; + v["data"] = ::fromBinary(t.data); + v["gas"] = toQJS(t.gas); + v["gasPrice"] = toQJS(t.gasPrice); + v["nonce"] = toQJS(t.nonce); + v["to"] = toQJS(t.receiveAddress); + v["value"] = toQJS(t.value); + v["sender"] = toQJS(t.sender()); + ret.append(v); + } + return QString::fromUtf8(QJsonDocument(ret).toJson()); +} + bool QEthereum::isMining() const { return client()->isMining(); diff --git a/libqethereum/QEthereum.h b/libqethereum/QEthereum.h index 1a19eaffb..16489336b 100644 --- a/libqethereum/QEthereum.h +++ b/libqethereum/QEthereum.h @@ -402,6 +402,12 @@ public: Q_INVOKABLE QString/*eth::u256*/ stateAt(QString/*eth::Address*/ _a, QString/*eth::u256*/ _p, int _block) const; Q_INVOKABLE QString/*eth::u256*/ codeAt(QString/*eth::Address*/ _a, int _block) const; + /*TransactionFilter from(Address _a) { m_from.insert(_a); return *this; } + TransactionFilter to(Address _a) { m_to.insert(_a); return *this; } + TransactionFilter stateAltered(Address _a, u256 _l) { m_stateAltered.insert(std::make_pair(_a, _l)); return *this; } + TransactionFilter stateAltered(Address _a) { m_altered.insert(_a); return *this; }*/ + Q_INVOKABLE QString getTransactions(QString _attribs) const; + Q_INVOKABLE QString doCreate(QString _secret, QString _amount, QString _init, QString _gas, QString _gasPrice); Q_INVOKABLE void doTransact(QString _secret, QString _amount, QString _dest, QString _data, QString _gas, QString _gasPrice); diff --git a/neth/CMakeLists.txt b/neth/CMakeLists.txt index 6286afb5c..0e50b0cb7 100644 --- a/neth/CMakeLists.txt +++ b/neth/CMakeLists.txt @@ -15,10 +15,14 @@ add_executable(${EXECUTABLE} ${SRC_LIST}) target_link_libraries(${EXECUTABLE} ethereum) target_link_libraries(${EXECUTABLE} secp256k1) target_link_libraries(${EXECUTABLE} gmp) +if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) +endif() target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LS}) +if(JSONRPC_LS) target_link_libraries(${EXECUTABLE} ${JSONRPC_LS}) +endif() if (${TARGET_PLATFORM} STREQUAL "w64") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++")