diff --git a/alethzero/Transact.cpp b/alethzero/Transact.cpp index 30e069fd0..4b7bea73f 100644 --- a/alethzero/Transact.cpp +++ b/alethzero/Transact.cpp @@ -369,39 +369,37 @@ Secret Transact::findSecret(u256 _totalReq) const void Transact::on_send_clicked() { - u256 totalReq = value() + fee(); - for (auto const& i: m_myKeys) - if (ethereum()->balanceAt(i.address(), 0) >= totalReq) - { - Secret s = i.secret(); - if (isCreation()) + Secret s = findSecret(value() + fee()); + if (!s) + { + QMessageBox::critical(this, "Transaction Failed", "Couldn't make transaction: no single account contains at least the required amount."); + return; + } + + if (isCreation()) + { + // If execution is a contract creation, add Natspec to + // a local Natspec LEVELDB + ethereum()->submitTransaction(s, value(), m_data, ui->gas->value(), gasPrice()); + string src = ui->data->toPlainText().toStdString(); + if (sourceIsSolidity(src)) + try { - // If execution is a contract creation, add Natspec to - // a local Natspec LEVELDB - ethereum()->submitTransaction(s, value(), m_data, ui->gas->value(), gasPrice()); - string src = ui->data->toPlainText().toStdString(); - if (sourceIsSolidity(src)) - try - { - dev::solidity::CompilerStack compiler(true); - m_data = compiler.compile(src, ui->optimize->isChecked()); - for (string const& s: compiler.getContractNames()) - { - h256 contractHash = compiler.getContractCodeHash(s); - m_natSpecDB->add(contractHash, compiler.getMetadata(s, dev::solidity::DocumentationType::NatspecUser)); - } - } - catch (...) - { - } - close(); - return; + dev::solidity::CompilerStack compiler(true); + m_data = compiler.compile(src, ui->optimize->isChecked()); + for (string const& s: compiler.getContractNames()) + { + h256 contractHash = compiler.getContractCodeHash(s); + m_natSpecDB->add(contractHash, compiler.getMetadata(s, dev::solidity::DocumentationType::NatspecUser)); + } } - else - ethereum()->submitTransaction(s, value(), m_context->fromString(ui->destination->currentText()), m_data, ui->gas->value(), gasPrice()); - return; - } - QMessageBox::critical(this, "Transaction Failed", "Couldn't make transaction: no single account contains at least the required amount."); + catch (...) + { + } + } + else + ethereum()->submitTransaction(s, value(), m_context->fromString(ui->destination->currentText()), m_data, ui->gas->value(), gasPrice()); + close(); } void Transact::on_debug_clicked() diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index fb29ffb6a..3ca06f381 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -357,11 +357,11 @@ LocalisedLogEntries Client::checkWatch(unsigned _watchId) return ret; } -void Client::appendFromNewPending(TransactionReceipt const& _receipt, h256Set& io_changed, h256 _sha3) +void Client::appendFromNewPending(TransactionReceipt const& _receipt, h256Set& io_changed, h256 _transactionHash) { Guard l(m_filterLock); for (pair& i: m_filters) - if ((unsigned)i.second.filter.latest() > m_bc.number()) + if (i.second.filter.envelops(RelativeBlock::Pending, m_bc.number() + 1)) { // acceptable number. auto m = i.second.filter.matches(_receipt); @@ -369,7 +369,7 @@ void Client::appendFromNewPending(TransactionReceipt const& _receipt, h256Set& i { // filter catches them for (LogEntry const& l: m) - i.second.changes.push_back(LocalisedLogEntry(l, m_bc.number() + 1, _sha3)); + i.second.changes.push_back(LocalisedLogEntry(l, m_bc.number() + 1, _transactionHash)); io_changed.insert(i.first); } } @@ -383,7 +383,7 @@ void Client::appendFromNewBlock(h256 const& _block, h256Set& io_changed) Guard l(m_filterLock); for (pair& i: m_filters) - if ((unsigned)i.second.filter.latest() >= d.number && (unsigned)i.second.filter.earliest() <= d.number && i.second.filter.matches(d.logBloom)) + if (i.second.filter.envelops(RelativeBlock::Latest, d.number) && i.second.filter.matches(d.logBloom)) // acceptable number & looks like block may contain a matching log entry. for (size_t j = 0; j < br.receipts.size(); j++) { @@ -391,10 +391,10 @@ void Client::appendFromNewBlock(h256 const& _block, h256Set& io_changed) auto m = i.second.filter.matches(tr); if (m.size()) { - auto sha3 = transaction(d.hash, j).sha3(); + auto transactionHash = transaction(d.hash, j).sha3(); // filter catches them for (LogEntry const& l: m) - i.second.changes.push_back(LocalisedLogEntry(l, (unsigned)d.number, sha3)); + i.second.changes.push_back(LocalisedLogEntry(l, (unsigned)d.number, transactionHash)); io_changed.insert(i.first); } } diff --git a/libethereum/LogFilter.cpp b/libethereum/LogFilter.cpp index 45716a949..a2a1aa40e 100644 --- a/libethereum/LogFilter.cpp +++ b/libethereum/LogFilter.cpp @@ -46,6 +46,33 @@ h256 LogFilter::sha3() const return dev::sha3(s.out()); } +static bool isNoLater(RelativeBlock _logBlockRelation, u256 _logBlockNumber, int _latest) +{ + if (_latest == PendingBlock) + return true; + else if (_latest == LatestBlock) + return _logBlockRelation == RelativeBlock::Latest; + else + return _logBlockNumber <= _latest; +} + +static bool isNoEarlier(RelativeBlock _logBlockRelation, u256 _logBlockNumber, int _earliest) +{ + if (_earliest == PendingBlock) + return _logBlockRelation == RelativeBlock::Pending; + else if (_earliest == LatestBlock) + return true; + else + return _logBlockNumber >= _earliest; +} + +bool LogFilter::envelops(RelativeBlock _logBlockRelation, u256 _logBlockNumber) const +{ + return + isNoLater(_logBlockRelation, _logBlockNumber, m_latest) && + isNoEarlier(_logBlockRelation, _logBlockNumber, m_earliest); +} + bool LogFilter::matches(LogBloom _bloom) const { if (m_addresses.size()) diff --git a/libethereum/LogFilter.h b/libethereum/LogFilter.h index a28bfe806..7b808a0eb 100644 --- a/libethereum/LogFilter.h +++ b/libethereum/LogFilter.h @@ -42,17 +42,27 @@ std::ostream& operator<<(std::ostream& _out, dev::eth::LogFilter const& _s); class State; +enum class RelativeBlock +{ + Latest, + Pending +}; + +static const unsigned LatestBlock = (unsigned)-2; +static const unsigned PendingBlock = (unsigned)-1; + class LogFilter { public: - LogFilter(int _earliest = 0, int _latest = -1): m_earliest(_earliest), m_latest(_latest) {} + LogFilter(unsigned _earliest = 0, unsigned _latest = PendingBlock): m_earliest(_earliest), m_latest(_latest) {} void streamRLP(RLPStream& _s) const; h256 sha3() const; - int earliest() const { return m_earliest; } - int latest() const { return m_latest; } + unsigned earliest() const { return m_earliest; } + unsigned latest() const { return m_latest; } + bool envelops(RelativeBlock _logBlockRelation, u256 _logBlockNumber) const; std::vector bloomPossibilities() const; bool matches(LogBloom _bloom) const; bool matches(State const& _s, unsigned _i) const; @@ -68,8 +78,8 @@ public: private: AddressSet m_addresses; std::array m_topics; - int m_earliest = 0; - int m_latest = -1; + unsigned m_earliest = 0; + unsigned m_latest = LatestBlock; }; } diff --git a/libweb3jsonrpc/WebThreeStubServerBase.cpp b/libweb3jsonrpc/WebThreeStubServerBase.cpp index 6424354f2..1bbd8b404 100644 --- a/libweb3jsonrpc/WebThreeStubServerBase.cpp +++ b/libweb3jsonrpc/WebThreeStubServerBase.cpp @@ -139,6 +139,18 @@ static Json::Value toJson(map const& _storage) return res; } +static unsigned jsToBlockIndex(std::string const& _js) +{ + if (_js == "latest") + return LatestBlock; + else if (_js == "earliest") + return 0; + else if (_js == "pending") + return PendingBlock; + else + return (unsigned)jsToInt(_js); +} + static dev::eth::LogFilter toLogFilter(Json::Value const& _json) // commented to avoid warning. Uncomment once in use @ PoC-7. { dev::eth::LogFilter filter; @@ -147,9 +159,9 @@ static dev::eth::LogFilter toLogFilter(Json::Value const& _json) // commented to // check only !empty. it should throw exceptions if input params are incorrect if (!_json["fromBlock"].empty()) - filter.withEarliest(jsToInt(_json["fromBlock"].asString())); + filter.withEarliest(jsToBlockIndex(_json["fromBlock"].asString())); if (!_json["toBlock"].empty()) - filter.withLatest(jsToInt(_json["toBlock"].asString())); + filter.withLatest(jsToBlockIndex(_json["toBlock"].asString())); if (!_json["address"].empty()) { if (_json["address"].isArray()) @@ -227,6 +239,7 @@ static Json::Value toJson(h256 const& _h, shh::Envelope const& _e, shh::Message return res; } +// TODO: convert to jsToBlockNumber, downstream. too. static int toBlockNumber(string const& _string) { if (_string.compare("latest") == 0)