From 971b6854418e540e9341837d9d826680894f97b7 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 24 Jun 2015 23:07:05 +0200 Subject: [PATCH 01/17] blockchain isKnown block / transaction --- libethereum/BlockChain.h | 3 +++ libethereum/ClientBase.cpp | 16 ++++++++++++++++ libethereum/ClientBase.h | 4 ++++ libethereum/Interface.h | 3 +++ libweb3jsonrpc/WebThreeStubServerBase.cpp | 14 ++++++++++---- libweb3jsonrpc/WebThreeStubServerBase.h | 4 ++-- libweb3jsonrpc/abstractwebthreestubserver.h | 8 ++++---- libweb3jsonrpc/spec.json | 4 ++-- test/libweb3jsonrpc/webthreestubclient.h | 12 ++++++------ 9 files changed, 50 insertions(+), 18 deletions(-) diff --git a/libethereum/BlockChain.h b/libethereum/BlockChain.h index 421eb3ac2..906608d35 100644 --- a/libethereum/BlockChain.h +++ b/libethereum/BlockChain.h @@ -178,6 +178,9 @@ public: std::vector withBlockBloom(LogBloom const& _b, unsigned _earliest, unsigned _latest) const; std::vector withBlockBloom(LogBloom const& _b, unsigned _earliest, unsigned _latest, unsigned _topLevel, unsigned _index) const; + /// Returns true if transaction is known. Thread-safe + bool isKnownTransaction(h256 const& _transactionHash) const { TransactionAddress ta = queryExtras(_transactionHash, m_transactionAddresses, x_transactionAddresses, NullTransactionAddress); return !!ta; } + /// Get a transaction from its hash. Thread-safe. bytes transaction(h256 const& _transactionHash) const { TransactionAddress ta = queryExtras(_transactionHash, m_transactionAddresses, x_transactionAddresses, NullTransactionAddress); if (!ta) return bytes(); return transaction(ta.blockHash, ta.index); } std::pair transactionLocation(h256 const& _transactionHash) const { TransactionAddress ta = queryExtras(_transactionHash, m_transactionAddresses, x_transactionAddresses, NullTransactionAddress); if (!ta) return std::pair(h256(), 0); return std::make_pair(ta.blockHash, ta.index); } diff --git a/libethereum/ClientBase.cpp b/libethereum/ClientBase.cpp index 2ac413a6a..6489f939d 100644 --- a/libethereum/ClientBase.cpp +++ b/libethereum/ClientBase.cpp @@ -480,3 +480,19 @@ int ClientBase::compareBlockHashes(h256 _h1, h256 _h2) const } return -1; } + +bool ClientBase::isKnown(h256 _hash) const +{ + return bc().isKnown(_hash); +} + +bool ClientBase::isKnown(BlockNumber _block) const +{ + return bc().numberHash(_block) != h256(); +} + +bool ClientBase::isKnownTransaction(h256 _transactionHash) const +{ + return bc().isKnownTransaction(_transactionHash); +} + diff --git a/libethereum/ClientBase.h b/libethereum/ClientBase.h index ebcc48c18..aac10ae60 100644 --- a/libethereum/ClientBase.h +++ b/libethereum/ClientBase.h @@ -149,6 +149,10 @@ public: /// Get the coinbase address virtual Address address() const override; + virtual bool isKnown(h256 _hash) const override; + virtual bool isKnown(BlockNumber _block) const override; + virtual bool isKnownTransaction(h256 _transactionHash) const override; + /// TODO: consider moving it to a separate interface virtual void startMining() override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("ClientBase::startMining")); } diff --git a/libethereum/Interface.h b/libethereum/Interface.h index f631fb43e..204ce7dec 100644 --- a/libethereum/Interface.h +++ b/libethereum/Interface.h @@ -133,12 +133,15 @@ public: // [BLOCK QUERY API] + virtual bool isKnownTransaction(h256 _transactionHash) const = 0; virtual Transaction transaction(h256 _transactionHash) const = 0; virtual std::pair transactionLocation(h256 const& _transactionHash) const = 0; virtual h256 hashFromNumber(BlockNumber _number) const = 0; virtual BlockNumber numberFromHash(h256 _blockHash) const = 0; virtual int compareBlockHashes(h256 _h1, h256 _h2) const = 0; + virtual bool isKnown(BlockNumber _block) const = 0; + virtual bool isKnown(h256 _hash) const = 0; virtual BlockInfo blockInfo(h256 _hash) const = 0; virtual BlockDetails blockDetails(h256 _hash) const = 0; virtual Transaction transaction(h256 _blockHash, unsigned _i) const = 0; diff --git a/libweb3jsonrpc/WebThreeStubServerBase.cpp b/libweb3jsonrpc/WebThreeStubServerBase.cpp index 99c7e3425..dd979ee32 100644 --- a/libweb3jsonrpc/WebThreeStubServerBase.cpp +++ b/libweb3jsonrpc/WebThreeStubServerBase.cpp @@ -186,11 +186,14 @@ string WebThreeStubServerBase::eth_getBlockTransactionCountByNumber(string const } } -string WebThreeStubServerBase::eth_getUncleCountByBlockHash(string const& _blockHash) +Json::Value WebThreeStubServerBase::eth_getUncleCountByBlockHash(string const& _blockHash) { try { - return toJS(client()->uncleCount(jsToFixed<32>(_blockHash))); + h256 blockHash = jsToFixed<32>(_blockHash); + if (!client()->isKnown(blockHash)) + return Json::Value(Json::nullValue); + return toJS(client()->uncleCount(blockHash)); } catch (...) { @@ -198,11 +201,14 @@ string WebThreeStubServerBase::eth_getUncleCountByBlockHash(string const& _block } } -string WebThreeStubServerBase::eth_getUncleCountByBlockNumber(string const& _blockNumber) +Json::Value WebThreeStubServerBase::eth_getUncleCountByBlockNumber(string const& _blockNumber) { try { - return toJS(client()->uncleCount(jsToBlockNumber(_blockNumber))); + BlockNumber blockNumber = jsToBlockNumber(_blockNumber); + if (!client()->isKnown(blockNumber)) + return Json::Value(Json::nullValue); + return toJS(client()->uncleCount(blockNumber)); } catch (...) { diff --git a/libweb3jsonrpc/WebThreeStubServerBase.h b/libweb3jsonrpc/WebThreeStubServerBase.h index d3e16d0f4..8e3de4c17 100644 --- a/libweb3jsonrpc/WebThreeStubServerBase.h +++ b/libweb3jsonrpc/WebThreeStubServerBase.h @@ -108,8 +108,8 @@ public: virtual std::string eth_getTransactionCount(std::string const& _address, std::string const& _blockNumber); virtual std::string eth_getBlockTransactionCountByHash(std::string const& _blockHash); virtual std::string eth_getBlockTransactionCountByNumber(std::string const& _blockNumber); - virtual std::string eth_getUncleCountByBlockHash(std::string const& _blockHash); - virtual std::string eth_getUncleCountByBlockNumber(std::string const& _blockNumber); + virtual Json::Value eth_getUncleCountByBlockHash(std::string const& _blockHash); + virtual Json::Value eth_getUncleCountByBlockNumber(std::string const& _blockNumber); virtual std::string eth_getCode(std::string const& _address, std::string const& _blockNumber); virtual std::string eth_sendTransaction(Json::Value const& _json); virtual std::string eth_call(Json::Value const& _json, std::string const& _blockNumber); diff --git a/libweb3jsonrpc/abstractwebthreestubserver.h b/libweb3jsonrpc/abstractwebthreestubserver.h index 82864a61a..20a248985 100644 --- a/libweb3jsonrpc/abstractwebthreestubserver.h +++ b/libweb3jsonrpc/abstractwebthreestubserver.h @@ -29,8 +29,8 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServerbindAndAddMethod(jsonrpc::Procedure("eth_getTransactionCount", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_getTransactionCountI); this->bindAndAddMethod(jsonrpc::Procedure("eth_getBlockTransactionCountByHash", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_getBlockTransactionCountByHashI); this->bindAndAddMethod(jsonrpc::Procedure("eth_getBlockTransactionCountByNumber", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_getBlockTransactionCountByNumberI); - this->bindAndAddMethod(jsonrpc::Procedure("eth_getUncleCountByBlockHash", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_getUncleCountByBlockHashI); - this->bindAndAddMethod(jsonrpc::Procedure("eth_getUncleCountByBlockNumber", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_getUncleCountByBlockNumberI); + this->bindAndAddMethod(jsonrpc::Procedure("eth_getUncleCountByBlockHash", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_getUncleCountByBlockHashI); + this->bindAndAddMethod(jsonrpc::Procedure("eth_getUncleCountByBlockNumber", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_getUncleCountByBlockNumberI); this->bindAndAddMethod(jsonrpc::Procedure("eth_getCode", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_getCodeI); this->bindAndAddMethod(jsonrpc::Procedure("eth_sendTransaction", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::eth_sendTransactionI); this->bindAndAddMethod(jsonrpc::Procedure("eth_call", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_OBJECT,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_callI); @@ -478,8 +478,8 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServerCallMethod("eth_getUncleCountByBlockHash",p); - if (result.isString()) - return result.asString(); + if (result.isObject()) + return result; else throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - std::string eth_getUncleCountByBlockNumber(const std::string& param1) throw (jsonrpc::JsonRpcException) + Json::Value eth_getUncleCountByBlockNumber(const std::string& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); Json::Value result = this->CallMethod("eth_getUncleCountByBlockNumber",p); - if (result.isString()) - return result.asString(); + if (result.isObject()) + return result; else throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } From 45cb07bccfc2c192b4a012aa64398e9251b67f1b Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 24 Jun 2015 23:25:13 +0200 Subject: [PATCH 02/17] getBlockBy** and getBlockTransactionCountBy** return null if block is not found --- libethereum/ClientBase.cpp | 9 +++++-- libweb3jsonrpc/WebThreeStubServerBase.cpp | 26 +++++++++++++++++---- libweb3jsonrpc/WebThreeStubServerBase.h | 4 ++-- libweb3jsonrpc/abstractwebthreestubserver.h | 8 +++---- libweb3jsonrpc/spec.json | 4 ++-- test/libweb3jsonrpc/webthreestubclient.h | 12 +++++----- 6 files changed, 42 insertions(+), 21 deletions(-) diff --git a/libethereum/ClientBase.cpp b/libethereum/ClientBase.cpp index 6489f939d..3d4411505 100644 --- a/libethereum/ClientBase.cpp +++ b/libethereum/ClientBase.cpp @@ -483,12 +483,17 @@ int ClientBase::compareBlockHashes(h256 _h1, h256 _h2) const bool ClientBase::isKnown(h256 _hash) const { - return bc().isKnown(_hash); + return _hash == PendingBlockHash || + _hash == LatestBlockHash || + _hash == EarliestBlockHash || + bc().isKnown(_hash); } bool ClientBase::isKnown(BlockNumber _block) const { - return bc().numberHash(_block) != h256(); + return _block == PendingBlock || + _block == LatestBlock || + bc().numberHash(_block) != h256(); } bool ClientBase::isKnownTransaction(h256 _transactionHash) const diff --git a/libweb3jsonrpc/WebThreeStubServerBase.cpp b/libweb3jsonrpc/WebThreeStubServerBase.cpp index dd979ee32..c63c22693 100644 --- a/libweb3jsonrpc/WebThreeStubServerBase.cpp +++ b/libweb3jsonrpc/WebThreeStubServerBase.cpp @@ -162,11 +162,15 @@ string WebThreeStubServerBase::eth_getTransactionCount(string const& _address, s } } -string WebThreeStubServerBase::eth_getBlockTransactionCountByHash(string const& _blockHash) +Json::Value WebThreeStubServerBase::eth_getBlockTransactionCountByHash(string const& _blockHash) { try { - return toJS(client()->transactionCount(jsToFixed<32>(_blockHash))); + h256 blockHash = jsToFixed<32>(_blockHash); + if (!client()->isKnown(blockHash)) + return Json::Value(Json::nullValue); + + return toJS(client()->transactionCount(blockHash)); } catch (...) { @@ -174,10 +178,14 @@ string WebThreeStubServerBase::eth_getBlockTransactionCountByHash(string const& } } -string WebThreeStubServerBase::eth_getBlockTransactionCountByNumber(string const& _blockNumber) +Json::Value WebThreeStubServerBase::eth_getBlockTransactionCountByNumber(string const& _blockNumber) { try { + BlockNumber blockNumber = jsToBlockNumber(_blockNumber); + if (!client()->isKnown(blockNumber)) + return Json::Value(Json::nullValue); + return toJS(client()->transactionCount(jsToBlockNumber(_blockNumber))); } catch (...) @@ -193,6 +201,7 @@ Json::Value WebThreeStubServerBase::eth_getUncleCountByBlockHash(string const& _ h256 blockHash = jsToFixed<32>(_blockHash); if (!client()->isKnown(blockHash)) return Json::Value(Json::nullValue); + return toJS(client()->uncleCount(blockHash)); } catch (...) @@ -208,6 +217,7 @@ Json::Value WebThreeStubServerBase::eth_getUncleCountByBlockNumber(string const& BlockNumber blockNumber = jsToBlockNumber(_blockNumber); if (!client()->isKnown(blockNumber)) return Json::Value(Json::nullValue); + return toJS(client()->uncleCount(blockNumber)); } catch (...) @@ -336,7 +346,10 @@ Json::Value WebThreeStubServerBase::eth_getBlockByHash(string const& _blockHash, { try { - auto h = jsToFixed<32>(_blockHash); + h256 h = jsToFixed<32>(_blockHash); + if (!client()->isKnown(h)) + return Json::Value(Json::nullValue); + if (_includeTransactions) return toJson(client()->blockInfo(h), client()->blockDetails(h), client()->uncleHashes(h), client()->transactions(h)); else @@ -352,7 +365,10 @@ Json::Value WebThreeStubServerBase::eth_getBlockByNumber(string const& _blockNum { try { - auto h = jsToBlockNumber(_blockNumber); + BlockNumber h = jsToBlockNumber(_blockNumber); + if (!client()->isKnown(h)) + return Json::Value(Json::nullValue); + if (_includeTransactions) return toJson(client()->blockInfo(h), client()->blockDetails(h), client()->uncleHashes(h), client()->transactions(h)); else diff --git a/libweb3jsonrpc/WebThreeStubServerBase.h b/libweb3jsonrpc/WebThreeStubServerBase.h index 8e3de4c17..94fbd1acb 100644 --- a/libweb3jsonrpc/WebThreeStubServerBase.h +++ b/libweb3jsonrpc/WebThreeStubServerBase.h @@ -106,8 +106,8 @@ public: virtual std::string eth_getBalance(std::string const& _address, std::string const& _blockNumber); virtual std::string eth_getStorageAt(std::string const& _address, std::string const& _position, std::string const& _blockNumber); virtual std::string eth_getTransactionCount(std::string const& _address, std::string const& _blockNumber); - virtual std::string eth_getBlockTransactionCountByHash(std::string const& _blockHash); - virtual std::string eth_getBlockTransactionCountByNumber(std::string const& _blockNumber); + virtual Json::Value eth_getBlockTransactionCountByHash(std::string const& _blockHash); + virtual Json::Value eth_getBlockTransactionCountByNumber(std::string const& _blockNumber); virtual Json::Value eth_getUncleCountByBlockHash(std::string const& _blockHash); virtual Json::Value eth_getUncleCountByBlockNumber(std::string const& _blockNumber); virtual std::string eth_getCode(std::string const& _address, std::string const& _blockNumber); diff --git a/libweb3jsonrpc/abstractwebthreestubserver.h b/libweb3jsonrpc/abstractwebthreestubserver.h index 20a248985..6d0db7394 100644 --- a/libweb3jsonrpc/abstractwebthreestubserver.h +++ b/libweb3jsonrpc/abstractwebthreestubserver.h @@ -27,8 +27,8 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServerbindAndAddMethod(jsonrpc::Procedure("eth_getBalance", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_getBalanceI); this->bindAndAddMethod(jsonrpc::Procedure("eth_getStorageAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING,"param3",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_getStorageAtI); this->bindAndAddMethod(jsonrpc::Procedure("eth_getTransactionCount", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_getTransactionCountI); - this->bindAndAddMethod(jsonrpc::Procedure("eth_getBlockTransactionCountByHash", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_getBlockTransactionCountByHashI); - this->bindAndAddMethod(jsonrpc::Procedure("eth_getBlockTransactionCountByNumber", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_getBlockTransactionCountByNumberI); + this->bindAndAddMethod(jsonrpc::Procedure("eth_getBlockTransactionCountByHash", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_getBlockTransactionCountByHashI); + this->bindAndAddMethod(jsonrpc::Procedure("eth_getBlockTransactionCountByNumber", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_getBlockTransactionCountByNumberI); this->bindAndAddMethod(jsonrpc::Procedure("eth_getUncleCountByBlockHash", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_getUncleCountByBlockHashI); this->bindAndAddMethod(jsonrpc::Procedure("eth_getUncleCountByBlockNumber", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_getUncleCountByBlockNumberI); this->bindAndAddMethod(jsonrpc::Procedure("eth_getCode", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_getCodeI); @@ -476,8 +476,8 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServerCallMethod("eth_getBlockTransactionCountByHash",p); - if (result.isString()) - return result.asString(); + if (result.isObject()) + return result; else throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - std::string eth_getBlockTransactionCountByNumber(const std::string& param1) throw (jsonrpc::JsonRpcException) + Json::Value eth_getBlockTransactionCountByNumber(const std::string& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); Json::Value result = this->CallMethod("eth_getBlockTransactionCountByNumber",p); - if (result.isString()) - return result.asString(); + if (result.isObject()) + return result; else throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } From 107701727dd1f9c518fa365875515511004d7862 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Thu, 25 Jun 2015 09:51:22 +0200 Subject: [PATCH 03/17] fixed getting transaction by blockNumber and index --- libethereum/Interface.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libethereum/Interface.h b/libethereum/Interface.h index 204ce7dec..1073b45ff 100644 --- a/libethereum/Interface.h +++ b/libethereum/Interface.h @@ -154,7 +154,7 @@ public: BlockInfo blockInfo(BlockNumber _block) const { return blockInfo(hashFromNumber(_block)); } BlockDetails blockDetails(BlockNumber _block) const { return blockDetails(hashFromNumber(_block)); } - Transaction transaction(BlockNumber _block, unsigned _i) const { if (_block == PendingBlock) { auto p = pending(); return _i < p.size() ? p[_i] : Transaction(); } return transaction(hashFromNumber(_block)); } + Transaction transaction(BlockNumber _block, unsigned _i) const { auto p = transactions(_block); return _i < p.size() ? p[_i] : Transaction(); } unsigned transactionCount(BlockNumber _block) const { if (_block == PendingBlock) { auto p = pending(); return p.size(); } return transactionCount(hashFromNumber(_block)); } Transactions transactions(BlockNumber _block) const { if (_block == PendingBlock) return pending(); return transactions(hashFromNumber(_block)); } TransactionHashes transactionHashes(BlockNumber _block) const { if (_block == PendingBlock) return pendingHashes(); return transactionHashes(hashFromNumber(_block)); } From 560f93be76a9669dbbd4db2082125c53bda4b939 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Thu, 25 Jun 2015 10:08:01 +0200 Subject: [PATCH 04/17] fixed eth_getTransactionByHash when transactionHash is unknown --- libweb3jsonrpc/WebThreeStubServerBase.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libweb3jsonrpc/WebThreeStubServerBase.cpp b/libweb3jsonrpc/WebThreeStubServerBase.cpp index c63c22693..cc0e80eab 100644 --- a/libweb3jsonrpc/WebThreeStubServerBase.cpp +++ b/libweb3jsonrpc/WebThreeStubServerBase.cpp @@ -385,6 +385,9 @@ Json::Value WebThreeStubServerBase::eth_getTransactionByHash(string const& _tran try { h256 h = jsToFixed<32>(_transactionHash); + if (!client()->isKnownTransaction(h)) + return Json::Value(Json::nullValue); + auto l = client()->transactionLocation(h); return toJson(client()->transaction(h), l, client()->numberFromHash(l.first)); } From 5613e2197409254c10e7166b41cb63c8276e39c6 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Thu, 25 Jun 2015 11:19:16 +0200 Subject: [PATCH 05/17] fixed encoding unformatted data in eth_getStorageAt --- libweb3jsonrpc/WebThreeStubServerBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libweb3jsonrpc/WebThreeStubServerBase.cpp b/libweb3jsonrpc/WebThreeStubServerBase.cpp index cc0e80eab..3683c01ca 100644 --- a/libweb3jsonrpc/WebThreeStubServerBase.cpp +++ b/libweb3jsonrpc/WebThreeStubServerBase.cpp @@ -142,7 +142,7 @@ string WebThreeStubServerBase::eth_getStorageAt(string const& _address, string c { try { - return toJS(client()->stateAt(jsToAddress(_address), jsToU256(_position), jsToBlockNumber(_blockNumber))); + return toJS(toCompactBigEndian(client()->stateAt(jsToAddress(_address), jsToU256(_position), jsToBlockNumber(_blockNumber)), 1)); } catch (...) { From 34b2767a59d74e08e8d73f59591eb375732c214b Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 1 Jul 2015 14:06:01 +0200 Subject: [PATCH 06/17] isKnown const& --- libethereum/ClientBase.cpp | 4 ++-- libethereum/ClientBase.h | 4 ++-- libethereum/Interface.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libethereum/ClientBase.cpp b/libethereum/ClientBase.cpp index 3d4411505..d6d259380 100644 --- a/libethereum/ClientBase.cpp +++ b/libethereum/ClientBase.cpp @@ -481,7 +481,7 @@ int ClientBase::compareBlockHashes(h256 _h1, h256 _h2) const return -1; } -bool ClientBase::isKnown(h256 _hash) const +bool ClientBase::isKnown(h256 const& _hash) const { return _hash == PendingBlockHash || _hash == LatestBlockHash || @@ -496,7 +496,7 @@ bool ClientBase::isKnown(BlockNumber _block) const bc().numberHash(_block) != h256(); } -bool ClientBase::isKnownTransaction(h256 _transactionHash) const +bool ClientBase::isKnownTransaction(h256 const& _transactionHash) const { return bc().isKnownTransaction(_transactionHash); } diff --git a/libethereum/ClientBase.h b/libethereum/ClientBase.h index aac10ae60..d2d22a08f 100644 --- a/libethereum/ClientBase.h +++ b/libethereum/ClientBase.h @@ -149,9 +149,9 @@ public: /// Get the coinbase address virtual Address address() const override; - virtual bool isKnown(h256 _hash) const override; + virtual bool isKnown(h256 const& _hash) const override; virtual bool isKnown(BlockNumber _block) const override; - virtual bool isKnownTransaction(h256 _transactionHash) const override; + virtual bool isKnownTransaction(h256 const& _transactionHash) const override; /// TODO: consider moving it to a separate interface diff --git a/libethereum/Interface.h b/libethereum/Interface.h index 1073b45ff..f24f1b5c3 100644 --- a/libethereum/Interface.h +++ b/libethereum/Interface.h @@ -133,7 +133,7 @@ public: // [BLOCK QUERY API] - virtual bool isKnownTransaction(h256 _transactionHash) const = 0; + virtual bool isKnownTransaction(h256 const& _transactionHash) const = 0; virtual Transaction transaction(h256 _transactionHash) const = 0; virtual std::pair transactionLocation(h256 const& _transactionHash) const = 0; virtual h256 hashFromNumber(BlockNumber _number) const = 0; @@ -141,7 +141,7 @@ public: virtual int compareBlockHashes(h256 _h1, h256 _h2) const = 0; virtual bool isKnown(BlockNumber _block) const = 0; - virtual bool isKnown(h256 _hash) const = 0; + virtual bool isKnown(h256 const& _hash) const = 0; virtual BlockInfo blockInfo(h256 _hash) const = 0; virtual BlockDetails blockDetails(h256 _hash) const = 0; virtual Transaction transaction(h256 _blockHash, unsigned _i) const = 0; From 485a9105233bfcee019a8f43cf33275819005317 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 1 Jul 2015 13:53:53 +0200 Subject: [PATCH 07/17] Documentation and tests for RangeMask. --- libdevcore/RangeMask.h | 146 ++++++++++++++++++++------------- libethereum/BlockChainSync.h | 1 - libethereum/EthereumHost.h | 1 - libethereum/EthereumPeer.h | 1 - libp2p/Host.h | 1 - libp2p/Session.h | 1 - test/libdevcore/RangeMask.cpp | 148 ++++++++++++++++++++++++++++++++++ 7 files changed, 239 insertions(+), 60 deletions(-) create mode 100644 test/libdevcore/RangeMask.cpp diff --git a/libdevcore/RangeMask.h b/libdevcore/RangeMask.h index 7c402fc98..d87b81a3a 100644 --- a/libdevcore/RangeMask.h +++ b/libdevcore/RangeMask.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -35,6 +36,12 @@ class RLPStream; using UnsignedRange = std::pair; using UnsignedRanges = std::vector; +/** + * Set of elements of a certain "ground range" representable by unions of ranges inside this + * ground range. + * Ranges are given as pairs (begin, end), denoting the interval [begin, end), i.e. end is excluded. + * Supports set-theoretic operators, size and iteration. + */ template class RangeMask { @@ -44,14 +51,19 @@ public: using Range = std::pair; using Ranges = std::vector; + /// Constructs an empty range mask with empty ground range. RangeMask(): m_all(0, 0) {} + /// Constructs an empty range mask with ground range [_begin, _end). RangeMask(T _begin, T _end): m_all(_begin, _end) {} + /// Constructs an empty range mask with ground range _c. RangeMask(Range const& _c): m_all(_c) {} + /// @returns the union with the range mask _m, taking also the union of the ground ranges. RangeMask unionedWith(RangeMask const& _m) const { return operator+(_m); } RangeMask operator+(RangeMask const& _m) const { return RangeMask(*this) += _m; } - RangeMask lowest(T _items) const + /// @returns a new range mask containing the smallest _items elements (not ranges). + RangeMask lowest(decltype(T{} - T{}) _items) const { RangeMask ret(m_all); for (auto i = m_ranges.begin(); i != m_ranges.end() && _items; ++i) @@ -59,8 +71,10 @@ public: return ret; } + /// @returns the complement of the range mask relative to the ground range. RangeMask operator~() const { return inverted(); } + /// @returns a copy of this range mask representing the complement relative to the ground range. RangeMask inverted() const { RangeMask ret(m_all); @@ -76,6 +90,8 @@ public: return ret; } + /// Changes the range mask to its complement relative to the ground range and returns a + /// reference to itself. RangeMask& invert() { return *this = inverted(); } template RangeMask operator-(S const& _m) const { auto ret = *this; return ret -= _m; } @@ -92,61 +108,13 @@ public: return *this; } RangeMask& operator+=(Range const& _m) { return unionWith(_m); } - RangeMask& unionWith(Range const& _m) - { - for (auto i = _m.first; i < _m.second;) - { - assert(i >= m_all.first); - assert(i < m_all.second); - // for each number, we find the element equal or next lower. this, if any, must contain the value. - auto uit = m_ranges.upper_bound(i); - auto it = uit == m_ranges.begin() ? m_ranges.end() : std::prev(uit); - if (it == m_ranges.end() || it->second < i) - // lower range is too low to merge. - // if the next higher range is too high. - if (uit == m_ranges.end() || uit->first > _m.second) - { - // just create a new range - m_ranges[i] = _m.second; - break; - } - else - { - if (uit->first == i) - // move i to end of range - i = uit->second; - else - { - // merge with the next higher range - // move i to end of range - i = m_ranges[i] = uit->second; - i = uit->second; - m_ranges.erase(uit); - } - } - else if (it->second == i) - { - // if the next higher range is too high. - if (uit == m_ranges.end() || uit->first > _m.second) - { - // merge with the next lower range - m_ranges[it->first] = _m.second; - break; - } - else - { - // merge with both next lower & next higher. - i = m_ranges[it->first] = uit->second; - m_ranges.erase(uit); - } - } - else - i = it->second; - } - return *this; - } + /// Modifies this range mask to also include the range _m, which has to be a subset of + /// the ground range. + RangeMask& unionWith(Range const& _m); + /// Adds the single element _i to the range mask. RangeMask& operator+=(T _m) { return unionWith(_m); } + /// Adds the single element _i to the range mask. RangeMask& unionWith(T _i) { return operator+=(Range(_i, _i + 1)); @@ -181,10 +149,12 @@ public: m_all = std::make_pair(0, 0); } + /// @returns the ground range. std::pair const& all() const { return m_all; } + /// Extends the ground range to include _i. void extendAll(T _i) { m_all = std::make_pair(std::min(m_all.first, _i), std::max(m_all.second, _i + 1)); } - class const_iterator + class const_iterator: public std::iterator { friend class RangeMask; @@ -208,6 +178,8 @@ public: const_iterator begin() const { return const_iterator(*this, false); } const_iterator end() const { return const_iterator(*this, true); } + /// @returns the smallest element in the range mask that is larger than _t or the end of the + /// base range if such an element does not exist. T next(T _t) const { _t++; @@ -219,6 +191,7 @@ public: return uit == m_ranges.end() ? m_all.second : uit->first; } + /// @returns the number of elements (not ranges) in the range mask. size_t size() const { size_t c = 0; @@ -228,7 +201,9 @@ public: } private: + /// The ground range. UnsignedRange m_all; + /// Mapping begin -> end containing the ranges. std::map m_ranges; }; @@ -241,4 +216,65 @@ template inline std::ostream& operator<<(std::ostream& _out, RangeMask return _out; } +template +RangeMask& RangeMask::unionWith(RangeMask::Range const& _m) +{ + for (auto i = _m.first; i < _m.second;) + { + assert(i >= m_all.first); + assert(i < m_all.second); + // For each number, we find the element equal or next lower. this, if any, must contain the value. + // First range that starts after i. + auto rangeAfter = m_ranges.upper_bound(i); + // Range before rangeAfter or "end" if the rangeAfter is the first ever... + auto it = rangeAfter == m_ranges.begin() ? m_ranges.end() : std::prev(rangeAfter); + if (it == m_ranges.end() || it->second < i) + { + // i is either before the first range or between two ranges (with some distance + // so that we cannot merge it onto "it"). + // lower range is too low to merge. + // if the next higher range is too high. + if (rangeAfter == m_ranges.end() || rangeAfter->first > _m.second) + { + // just create a new range + m_ranges[i] = _m.second; + break; + } + else + { + if (rangeAfter->first == i) + // move i to end of range + i = rangeAfter->second; + else + { + // merge with the next higher range + // move i to end of range + i = m_ranges[i] = rangeAfter->second; + m_ranges.erase(rangeAfter); + } + } + } + else if (it->second == i) + { + // The range before i ends with i. + // if the next higher range is too high. + if (rangeAfter == m_ranges.end() || rangeAfter->first > _m.second) + { + // merge with the next lower range + m_ranges[it->first] = _m.second; + break; + } + else + { + // merge with both next lower & next higher. + i = m_ranges[it->first] = rangeAfter->second; + m_ranges.erase(rangeAfter); + } + } + else + i = it->second; + } + return *this; +} + } diff --git a/libethereum/BlockChainSync.h b/libethereum/BlockChainSync.h index 449dd49d1..793b05b5b 100644 --- a/libethereum/BlockChainSync.h +++ b/libethereum/BlockChainSync.h @@ -24,7 +24,6 @@ #include #include -#include #include #include #include "CommonNet.h" diff --git a/libethereum/EthereumHost.h b/libethereum/EthereumHost.h index 182c3d4cd..a4b9d0006 100644 --- a/libethereum/EthereumHost.h +++ b/libethereum/EthereumHost.h @@ -31,7 +31,6 @@ #include #include -#include #include #include #include "CommonNet.h" diff --git a/libethereum/EthereumPeer.h b/libethereum/EthereumPeer.h index d506ffb3f..e8842c8af 100644 --- a/libethereum/EthereumPeer.h +++ b/libethereum/EthereumPeer.h @@ -31,7 +31,6 @@ #include #include -#include #include #include #include "CommonNet.h" diff --git a/libp2p/Host.h b/libp2p/Host.h index 9523d0cca..b7ebb3951 100644 --- a/libp2p/Host.h +++ b/libp2p/Host.h @@ -33,7 +33,6 @@ #include #include -#include #include #include #include "NodeTable.h" diff --git a/libp2p/Session.h b/libp2p/Session.h index 0a55b2653..8d8c3ea1e 100644 --- a/libp2p/Session.h +++ b/libp2p/Session.h @@ -31,7 +31,6 @@ #include #include -#include #include #include "RLPXFrameCoder.h" #include "RLPXSocket.h" diff --git a/test/libdevcore/RangeMask.cpp b/test/libdevcore/RangeMask.cpp new file mode 100644 index 000000000..05f58963a --- /dev/null +++ b/test/libdevcore/RangeMask.cpp @@ -0,0 +1,148 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file RangeMask.cpp + * @author Christian + * @date 2015 + */ + +#include +#include "../TestHelper.h" + +using namespace std; +using namespace dev; + +namespace dev +{ +namespace test +{ + +BOOST_AUTO_TEST_SUITE(RangeMaskTest) + +BOOST_AUTO_TEST_CASE(constructor) +{ + using RM = RangeMask; + using Range = pair; + for (RM r: {RM(), RM(1, 10), RM(Range(2, 10))}) + { + BOOST_CHECK(r.empty()); + BOOST_CHECK(!r.contains(0)); + BOOST_CHECK(!r.contains(1)); + BOOST_CHECK_EQUAL(0, r.size()); + } + BOOST_CHECK(RM().full()); + BOOST_CHECK(!RM(1, 10).full()); + BOOST_CHECK(!RM(Range(2, 10)).full()); +} + +BOOST_AUTO_TEST_CASE(simple_unions) +{ + using RM = RangeMask; + using Range = pair; + RM m(Range(0, 2000)); + m.unionWith(Range(1, 2)); + BOOST_CHECK_EQUAL(m.size(), 1); + m.unionWith(Range(50, 250)); + BOOST_CHECK_EQUAL(m.size(), 201); + m.unionWith(Range(10, 16)); + BOOST_CHECK_EQUAL(m.size(), 207); + BOOST_CHECK(m.contains(1)); + BOOST_CHECK(m.contains(11)); + BOOST_CHECK(m.contains(51)); + BOOST_CHECK(m.contains(200)); + BOOST_CHECK(!m.contains(2)); + BOOST_CHECK(!m.contains(7)); + BOOST_CHECK(!m.contains(17)); + BOOST_CHECK(!m.contains(258)); +} + +BOOST_AUTO_TEST_CASE(empty_union) +{ + using RM = RangeMask; + using Range = pair; + RM m(Range(0, 2000)); + m.unionWith(Range(3, 6)); + BOOST_CHECK_EQUAL(m.size(), 3); + m.unionWith(Range(50, 50)); + BOOST_CHECK_EQUAL(m.size(), 3); + m.unionWith(Range(0, 0)); + BOOST_CHECK_EQUAL(m.size(), 3); + m.unionWith(Range(1, 1)); + BOOST_CHECK_EQUAL(m.size(), 3); + m.unionWith(Range(2, 2)); + BOOST_CHECK_EQUAL(m.size(), 3); + m.unionWith(Range(3, 3)); + BOOST_CHECK_EQUAL(m.size(), 3); +} + +BOOST_AUTO_TEST_CASE(overlapping_unions) +{ + using RM = RangeMask; + using Range = pair; + RM m(Range(0, 2000)); + m.unionWith(Range(10, 20)); + BOOST_CHECK_EQUAL(10, m.size()); + m.unionWith(Range(30, 40)); + BOOST_CHECK_EQUAL(20, m.size()); + m.unionWith(Range(15, 30)); + BOOST_CHECK_EQUAL(40 - 10, m.size()); + m.unionWith(Range(50, 60)); + m.unionWith(Range(45, 55)); + // [40, 45) still missing here + BOOST_CHECK_EQUAL(60 - 10 - 5, m.size()); + m.unionWith(Range(15, 56)); + BOOST_CHECK_EQUAL(60 - 10, m.size()); + m.unionWith(Range(15, 65)); + BOOST_CHECK_EQUAL(65 - 10, m.size()); + m.unionWith(Range(5, 70)); + BOOST_CHECK_EQUAL(70 - 5, m.size()); +} + +BOOST_AUTO_TEST_CASE(complement) +{ + using RM = RangeMask; + using Range = pair; + RM m(Range(0, 2000)); + m.unionWith(7).unionWith(9); + m = ~m; + m.unionWith(7).unionWith(9); + m = ~m; + BOOST_CHECK(m.empty()); + + m += Range(0, 10); + m += Range(1000, 2000); + m.invert(); + BOOST_CHECK_EQUAL(m.size(), 1000 - 10); +} + +BOOST_AUTO_TEST_CASE(iterator) +{ + using RM = RangeMask; + using Range = pair; + RM m(Range(0, 2000)); + m.unionWith(Range(7, 9)); + m.unionWith(11); + m.unionWith(Range(200, 205)); + + vector elements; + copy(m.begin(), m.end(), back_inserter(elements)); + BOOST_CHECK(elements == (vector{7, 8, 11, 200, 201, 202, 203, 204})); +} + +BOOST_AUTO_TEST_SUITE_END() + +} +} From 447ba77006138cfd04a3ff99bc75fe41778fe494 Mon Sep 17 00:00:00 2001 From: Vlad Gluhovsky Date: Wed, 1 Jul 2015 11:24:09 +0200 Subject: [PATCH 08/17] initial rating introduction --- libwhisper/WhisperHost.cpp | 28 +++++++++++++++++++--------- libwhisper/WhisperPeer.cpp | 10 +++++++++- libwhisper/WhisperPeer.h | 2 +- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/libwhisper/WhisperHost.cpp b/libwhisper/WhisperHost.cpp index 150d5cd63..9d97816f2 100644 --- a/libwhisper/WhisperHost.cpp +++ b/libwhisper/WhisperHost.cpp @@ -66,21 +66,31 @@ void WhisperHost::inject(Envelope const& _m, WhisperPeer* _p) m_expiryQueue.insert(make_pair(_m.expiry(), h)); } - DEV_GUARDED(m_filterLock) - { - for (auto const& f: m_filters) - if (f.second.filter.matches(_m)) - for (auto& i: m_watches) - if (i.second.id == f.first) - i.second.changes.push_back(h); - } + int rating = 1; // rating is based upon: 1. installed watch; 2. proof of work + + //if (bloomfilter.check) + //{ + // rating *= 10; + if (_p) // originated externally + DEV_GUARDED(m_filterLock) + { + for (auto const& f: m_filters) + if (f.second.filter.matches(_m)) + for (auto& i: m_watches) + if (i.second.id == f.first) + { + i.second.changes.push_back(h); + rating *= 10; + } + } + //} // TODO p2p: capability-based rating for (auto i: peerSessions()) { auto w = i.first->cap().get(); if (w == _p) - w->addRating(1); + w->addRating(rating); else w->noteNewMessage(h, _m); } diff --git a/libwhisper/WhisperPeer.cpp b/libwhisper/WhisperPeer.cpp index d749aa26e..feae5b72c 100644 --- a/libwhisper/WhisperPeer.cpp +++ b/libwhisper/WhisperPeer.cpp @@ -114,8 +114,16 @@ void WhisperPeer::sendMessages() void WhisperPeer::noteNewMessage(h256 _h, Envelope const& _m) { + unsigned rate = rating(_m); Guard l(x_unseen); - m_unseen.insert(make_pair(rating(_m), _h)); + m_unseen.insert(make_pair(rate, _h)); +} + +unsigned WhisperPeer::rating(Envelope const&) const +{ + // rated by: 1. installed watch; 2. proof of work + + return 0; } void WhisperPeer::sendTopicsOfInterest(TopicBloomFilterHash const& _bloom) diff --git a/libwhisper/WhisperPeer.h b/libwhisper/WhisperPeer.h index 48f984013..313cec28d 100644 --- a/libwhisper/WhisperPeer.h +++ b/libwhisper/WhisperPeer.h @@ -62,7 +62,7 @@ public: private: virtual bool interpret(unsigned _id, RLP const&) override; void sendMessages(); - unsigned rating(Envelope const&) const { return 0; } // TODO + unsigned rating(Envelope const&) const; void noteNewMessage(h256 _h, Envelope const& _m); void setBloom(TopicBloomFilterHash const& _b) { dev::Guard g(x_bloom); m_bloom = _b; } From ed858347118e867a90891ee02d824a3f680de9a5 Mon Sep 17 00:00:00 2001 From: Vlad Gluhovsky Date: Wed, 1 Jul 2015 20:11:30 +0200 Subject: [PATCH 09/17] Message rating for peers introduced --- libwhisper/BloomFilter.h | 6 ++---- libwhisper/Common.cpp | 2 +- libwhisper/Common.h | 7 ++++--- libwhisper/Message.cpp | 9 +++++++++ libwhisper/Message.h | 2 ++ libwhisper/WhisperHost.cpp | 4 +++- libwhisper/WhisperHost.h | 2 +- libwhisper/WhisperPeer.cpp | 41 +++++++++++++++++++++++--------------- libwhisper/WhisperPeer.h | 4 ++-- 9 files changed, 49 insertions(+), 28 deletions(-) diff --git a/libwhisper/BloomFilter.h b/libwhisper/BloomFilter.h index a624be157..7b5d179c6 100644 --- a/libwhisper/BloomFilter.h +++ b/libwhisper/BloomFilter.h @@ -42,14 +42,12 @@ public: void addRaw(FixedHash const& _h); void removeRaw(FixedHash const& _h); bool containsRaw(FixedHash const& _h) const { return this->contains(_h); } - - enum { BitsPerBloom = 3 }; private: void init() { for (unsigned i = 0; i < CounterSize; ++i) m_refCounter[i] = 0; } static bool isBitSet(FixedHash const& _h, unsigned _index); - enum { CounterSize = 8 * TopicBloomFilterBase::size }; + static const unsigned CounterSize = N * 8; std::array m_refCounter; }; @@ -91,7 +89,7 @@ bool TopicBloomFilterBase::isBitSet(FixedHash const& _h, unsigned _index) return (_h[iByte] & c_powerOfTwoBitMmask[iBit]) != 0; } -using TopicBloomFilter = TopicBloomFilterBase; +using TopicBloomFilter = TopicBloomFilterBase; } } diff --git a/libwhisper/Common.cpp b/libwhisper/Common.cpp index 748180647..7c7a9801b 100644 --- a/libwhisper/Common.cpp +++ b/libwhisper/Common.cpp @@ -100,7 +100,7 @@ TopicBloomFilterHash TopicFilter::exportBloom() const TopicBloomFilterHash ret; for (TopicMask const& t: m_topicMasks) for (auto const& i: t) - ret |= i.first.template bloomPart(); + ret |= i.first.template bloomPart(); return ret; } diff --git a/libwhisper/Common.h b/libwhisper/Common.h index d5d926291..277ce0902 100644 --- a/libwhisper/Common.h +++ b/libwhisper/Common.h @@ -58,8 +58,9 @@ enum WhisperPacket PacketCount }; -static const int c_topicBloomFilterSize = 64; -static const int c_whisperProtocolVersion = 3; +static const unsigned TopicBloomFilterSize = 64; +static const unsigned BitsPerBloom = 3; +static const unsigned WhisperProtocolVersion = 3; using AbridgedTopic = FixedHash<4>; using Topic = h256; @@ -67,7 +68,7 @@ using Topic = h256; using AbridgedTopics = std::vector; using Topics = h256s; -using TopicBloomFilterHash = FixedHash; +using TopicBloomFilterHash = FixedHash; AbridgedTopic abridge(Topic const& _topic); AbridgedTopics abridge(Topics const& _topics); diff --git a/libwhisper/Message.cpp b/libwhisper/Message.cpp index 50020b783..0b235b984 100644 --- a/libwhisper/Message.cpp +++ b/libwhisper/Message.cpp @@ -181,3 +181,12 @@ void Envelope::proveWork(unsigned _ms) } } } + +bool Envelope::matchesBloomFilter(TopicBloomFilterHash const& f) const +{ + for (AbridgedTopic t: m_topic) + if (f.contains(t.template bloomPart())) + return true; + + return false; +} diff --git a/libwhisper/Message.h b/libwhisper/Message.h index 3529054e0..ae61f210a 100644 --- a/libwhisper/Message.h +++ b/libwhisper/Message.h @@ -80,6 +80,8 @@ public: unsigned workProved() const; void proveWork(unsigned _ms); + bool matchesBloomFilter(TopicBloomFilterHash const& f) const; + private: Envelope(unsigned _exp, unsigned _ttl, AbridgedTopics const& _topic): m_expiry(_exp), m_ttl(_ttl), m_topic(_topic) {} diff --git a/libwhisper/WhisperHost.cpp b/libwhisper/WhisperHost.cpp index 9d97816f2..9ee772ba5 100644 --- a/libwhisper/WhisperHost.cpp +++ b/libwhisper/WhisperHost.cpp @@ -51,6 +51,8 @@ void WhisperHost::streamMessage(h256 _m, RLPStream& _s) const void WhisperHost::inject(Envelope const& _m, WhisperPeer* _p) { + // this function processes messages originated both by local host (_p == null), and by remote peers (_p != null) + cnote << this << ": inject: " << _m.expiry() << _m.ttl() << _m.topic() << toHex(_m.data()); if (_m.expiry() <= (unsigned)time(0)) @@ -66,7 +68,7 @@ void WhisperHost::inject(Envelope const& _m, WhisperPeer* _p) m_expiryQueue.insert(make_pair(_m.expiry(), h)); } - int rating = 1; // rating is based upon: 1. installed watch; 2. proof of work + int rating = 1; // rating for local host is based upon: 1. installed watch; 2. proof of work //if (bloomfilter.check) //{ diff --git a/libwhisper/WhisperHost.h b/libwhisper/WhisperHost.h index a6de09c38..fc1bcb557 100644 --- a/libwhisper/WhisperHost.h +++ b/libwhisper/WhisperHost.h @@ -50,7 +50,7 @@ class WhisperHost: public HostCapability, public Interface, public public: WhisperHost(); virtual ~WhisperHost(); - unsigned protocolVersion() const { return c_whisperProtocolVersion; } + unsigned protocolVersion() const { return WhisperProtocolVersion; } /// remove old messages void cleanup(); std::map all() const { dev::ReadGuard l(x_messages); return m_messages; } diff --git a/libwhisper/WhisperPeer.cpp b/libwhisper/WhisperPeer.cpp index feae5b72c..13df87ea3 100644 --- a/libwhisper/WhisperPeer.cpp +++ b/libwhisper/WhisperPeer.cpp @@ -91,19 +91,17 @@ void WhisperPeer::sendMessages() if (m_advertiseTopicsOfInterest) sendTopicsOfInterest(host()->bloom()); + multimap available; + DEV_GUARDED(x_unseen) + m_unseen.swap(available); + RLPStream amalg; - unsigned msgCount = 0; - { - Guard l(x_unseen); - msgCount = m_unseen.size(); - while (m_unseen.size()) - { - auto p = *m_unseen.begin(); - m_unseen.erase(m_unseen.begin()); - host()->streamMessage(p.second, amalg); - } - } - + + // send the highest rated messages first + for (auto i = available.rbegin(); i != available.rend(); ++i) + host()->streamMessage(i->second, amalg); + + unsigned msgCount = available.size(); if (msgCount) { RLPStream s; @@ -114,16 +112,27 @@ void WhisperPeer::sendMessages() void WhisperPeer::noteNewMessage(h256 _h, Envelope const& _m) { - unsigned rate = rating(_m); + unsigned rate = ratingForPeer(_m); Guard l(x_unseen); m_unseen.insert(make_pair(rate, _h)); } -unsigned WhisperPeer::rating(Envelope const&) const +unsigned WhisperPeer::ratingForPeer(Envelope const& e) const { - // rated by: 1. installed watch; 2. proof of work + // we try to estimate, how valuable this nessage will be for the remote peer, + // according to the following criteria: + // 1. bloom filter + // 2. proof of work - return 0; + static const unsigned BloomFilterMatchReward = 256; // vlad todo: move to common.h + unsigned rating = 0; + + DEV_GUARDED(x_bloom) + if (e.matchesBloomFilter(m_bloom)) + rating += BloomFilterMatchReward; + + rating += e.sha3().firstBitSet(); // proof of work assessment + return rating; } void WhisperPeer::sendTopicsOfInterest(TopicBloomFilterHash const& _bloom) diff --git a/libwhisper/WhisperPeer.h b/libwhisper/WhisperPeer.h index 313cec28d..4d093d259 100644 --- a/libwhisper/WhisperPeer.h +++ b/libwhisper/WhisperPeer.h @@ -53,7 +53,7 @@ public: virtual ~WhisperPeer(); WhisperHost* host() const; static std::string name() { return "shh"; } - static u256 version() { return c_whisperProtocolVersion; } + static u256 version() { return WhisperProtocolVersion; } static unsigned messageCount() { return PacketCount; } TopicBloomFilterHash bloom() const { dev::Guard g(x_bloom); return m_bloom; } void sendTopicsOfInterest(TopicBloomFilterHash const& _bloom); ///< sends our bloom filter to remote peer @@ -62,7 +62,7 @@ public: private: virtual bool interpret(unsigned _id, RLP const&) override; void sendMessages(); - unsigned rating(Envelope const&) const; + unsigned ratingForPeer(Envelope const& e) const; void noteNewMessage(h256 _h, Envelope const& _m); void setBloom(TopicBloomFilterHash const& _b) { dev::Guard g(x_bloom); m_bloom = _b; } From 16eab6d8820c1d6b6056a7ca8f38d33a7bcd776e Mon Sep 17 00:00:00 2001 From: Vlad Gluhovsky Date: Wed, 1 Jul 2015 20:21:35 +0200 Subject: [PATCH 10/17] cleanup --- libwhisper/BloomFilter.cpp | 28 ---------------------------- libwhisper/WhisperPeer.cpp | 2 +- 2 files changed, 1 insertion(+), 29 deletions(-) delete mode 100644 libwhisper/BloomFilter.cpp diff --git a/libwhisper/BloomFilter.cpp b/libwhisper/BloomFilter.cpp deleted file mode 100644 index 554274011..000000000 --- a/libwhisper/BloomFilter.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* -This file is part of cpp-ethereum. - -cpp-ethereum is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -cpp-ethereum is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with cpp-ethereum. If not, see . -*/ -/** @file BloomFilter.cpp -* @author Vladislav Gluhovsky -* @date June 2015 -*/ - -#include "BloomFilter.h" - -using namespace std; -using namespace dev; -using namespace dev::shh; - - diff --git a/libwhisper/WhisperPeer.cpp b/libwhisper/WhisperPeer.cpp index 13df87ea3..393c3749c 100644 --- a/libwhisper/WhisperPeer.cpp +++ b/libwhisper/WhisperPeer.cpp @@ -131,7 +131,7 @@ unsigned WhisperPeer::ratingForPeer(Envelope const& e) const if (e.matchesBloomFilter(m_bloom)) rating += BloomFilterMatchReward; - rating += e.sha3().firstBitSet(); // proof of work assessment + rating += e.sha3().firstBitSet(); return rating; } From c5ffcad47b21fd8008ecc552208abeb123ca751c Mon Sep 17 00:00:00 2001 From: Vlad Gluhovsky Date: Wed, 1 Jul 2015 20:49:18 +0200 Subject: [PATCH 11/17] build fix --- libp2p/Session.cpp | 2 +- test/libwhisper/bloomFilter.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libp2p/Session.cpp b/libp2p/Session.cpp index 6827a27d9..6a8c98071 100644 --- a/libp2p/Session.cpp +++ b/libp2p/Session.cpp @@ -382,7 +382,7 @@ void Session::doRead() } catch (std::exception const& _e) { - clog(NetWarn) << "Exception decoding frame header RLP:" << bytesConstRef(m_data.data(), h128::size).cropped(3); + clog(NetWarn) << _e.what() << "Exception decoding frame header RLP:" << bytesConstRef(m_data.data(), h128::size).cropped(3); drop(BadProtocol); return; } diff --git a/test/libwhisper/bloomFilter.cpp b/test/libwhisper/bloomFilter.cpp index 299fd3f5b..197a7258d 100644 --- a/test/libwhisper/bloomFilter.cpp +++ b/test/libwhisper/bloomFilter.cpp @@ -28,7 +28,7 @@ using namespace dev; using namespace dev::shh; using TopicBloomFilterShort = TopicBloomFilterBase<4>; -using TopicBloomFilterTest = TopicBloomFilterBase; +using TopicBloomFilterTest = TopicBloomFilterBase; void testAddNonExisting(TopicBloomFilterShort& _f, AbridgedTopic const& _h) { @@ -61,7 +61,7 @@ void testRemoveExistingBloom(TopicBloomFilterShort& _f, AbridgedTopic const& _h) double calculateExpected(TopicBloomFilterTest const& f, int n) { int const m = f.size * 8; // number of bits in the bloom - int const k = f.BitsPerBloom; // number of hash functions (e.g. bits set to 1 in every bloom) + int const k = BitsPerBloom; // number of hash functions (e.g. bits set to 1 in every bloom) double singleBitSet = 1.0 / m; // probability of any bit being set after inserting a single bit double singleBitNotSet = (1.0 - singleBitSet); @@ -256,7 +256,7 @@ void updateDistribution(FixedHash const& _h, array= TopicBloomFilterTest::BitsPerBloom) + if (++bits >= BitsPerBloom) return; } } @@ -274,7 +274,7 @@ BOOST_AUTO_TEST_CASE(distributionRate) for (unsigned i = 0; i < 22000; ++i) { x = sha3(x); - FixedHash h = x.template bloomPart(); + FixedHash h = x.template bloomPart(); updateDistribution(h, distribution); } From 4ce9fe8ed07d5fd4416782ba9c2925d72527b6f4 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 2 Jul 2015 11:29:31 +0200 Subject: [PATCH 12/17] Windwos fix. --- libdevcore/RangeMask.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdevcore/RangeMask.h b/libdevcore/RangeMask.h index d87b81a3a..eccc8305d 100644 --- a/libdevcore/RangeMask.h +++ b/libdevcore/RangeMask.h @@ -217,7 +217,7 @@ template inline std::ostream& operator<<(std::ostream& _out, RangeMask } template -RangeMask& RangeMask::unionWith(RangeMask::Range const& _m) +RangeMask& RangeMask::unionWith(typename RangeMask::Range const& _m) { for (auto i = _m.first; i < _m.second;) { From 784fed9a322c915c8e9f445fffdb41cb4ba27b18 Mon Sep 17 00:00:00 2001 From: Vlad Gluhovsky Date: Thu, 2 Jul 2015 14:32:16 +0200 Subject: [PATCH 13/17] minor update --- libp2p/Session.cpp | 2 +- libwhisper/WhisperHost.cpp | 26 ++++++++++---------------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/libp2p/Session.cpp b/libp2p/Session.cpp index 6a8c98071..08c411ca0 100644 --- a/libp2p/Session.cpp +++ b/libp2p/Session.cpp @@ -382,7 +382,7 @@ void Session::doRead() } catch (std::exception const& _e) { - clog(NetWarn) << _e.what() << "Exception decoding frame header RLP:" << bytesConstRef(m_data.data(), h128::size).cropped(3); + clog(NetWarn) << "Exception decoding frame header RLP:" << _e.what() << bytesConstRef(m_data.data(), h128::size).cropped(3); drop(BadProtocol); return; } diff --git a/libwhisper/WhisperHost.cpp b/libwhisper/WhisperHost.cpp index 9ee772ba5..f9ff33658 100644 --- a/libwhisper/WhisperHost.cpp +++ b/libwhisper/WhisperHost.cpp @@ -70,22 +70,16 @@ void WhisperHost::inject(Envelope const& _m, WhisperPeer* _p) int rating = 1; // rating for local host is based upon: 1. installed watch; 2. proof of work - //if (bloomfilter.check) - //{ - // rating *= 10; - if (_p) // originated externally - DEV_GUARDED(m_filterLock) - { - for (auto const& f: m_filters) - if (f.second.filter.matches(_m)) - for (auto& i: m_watches) - if (i.second.id == f.first) - { - i.second.changes.push_back(h); - rating *= 10; - } - } - //} + if (_p) // incoming message from remote peer + DEV_GUARDED(m_filterLock) + for (auto const& f: m_filters) + if (f.second.filter.matches(_m)) + for (auto& i: m_watches) + if (i.second.id == f.first) + { + i.second.changes.push_back(h); + rating += 10; // subject to review + } // TODO p2p: capability-based rating for (auto i: peerSessions()) From e5d32849ddd934a5ed61ced4ac8b2b9dd40cf6f1 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Thu, 2 Jul 2015 15:17:20 +0200 Subject: [PATCH 14/17] add transactionQueue tests --- test/libethereum/transactionqueue.cpp | 58 +++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 test/libethereum/transactionqueue.cpp diff --git a/test/libethereum/transactionqueue.cpp b/test/libethereum/transactionqueue.cpp new file mode 100644 index 000000000..b7071d640 --- /dev/null +++ b/test/libethereum/transactionqueue.cpp @@ -0,0 +1,58 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file transaction.cpp + * @author Christoph Jentzsch + * @date 2015 + * Transaaction test functions. + */ + +#include +#include "../TestHelper.h" + +using namespace std; +using namespace dev; +using namespace dev::eth; + +BOOST_AUTO_TEST_SUITE(TransactionQueue) + +BOOST_AUTO_TEST_CASE(maxNonce) +{ + + dev::eth::TransactionQueue txq; + + // from a94f5374fce5edbc8e2a8697c15331677e6ebf0b + Transaction tx0(0, 10 * szabo, 25000, Address("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"), bytes(), 0, Secret("0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8") ); + Transaction tx0_1(1, 10 * szabo, 25000, Address("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"), bytes(), 0, Secret("0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8") ); + Transaction tx1(0, 10 * szabo, 25000, Address("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"), bytes(), 1, Secret("0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8") ); + Transaction tx2(0, 10 * szabo, 25000, Address("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"), bytes(), 2, Secret("0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8") ); + Transaction tx9(0, 10 * szabo, 25000, Address("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"), bytes(), 9, Secret("0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8") ); + + txq.import(tx0); + BOOST_CHECK_EQUAL(1, (unsigned)txq.maxNonce(Address("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"))); + txq.import(tx0); + BOOST_CHECK_EQUAL(1, (unsigned)txq.maxNonce(Address("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"))); + txq.import(tx0_1); + BOOST_CHECK_EQUAL(1, (unsigned)txq.maxNonce(Address("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"))); + txq.import(tx1); + BOOST_CHECK_EQUAL(2, (unsigned)txq.maxNonce(Address("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"))); + txq.import(tx9); + BOOST_CHECK_EQUAL(10, (unsigned)txq.maxNonce(Address("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"))); + txq.import(tx2); + BOOST_CHECK_EQUAL(10, (unsigned)txq.maxNonce(Address("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"))); +} + +BOOST_AUTO_TEST_SUITE_END() From fdc40a05bf80e3225149cd89d1e6b727cfe317ea Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Thu, 2 Jul 2015 17:29:01 +0200 Subject: [PATCH 15/17] BlockQueue::import() spams only under specific verbosity I am getting the thread id even with verbosity = 0 which can make it really difficult to debug anything else if I am not interested in said thread's ID --- libethereum/BlockQueue.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libethereum/BlockQueue.cpp b/libethereum/BlockQueue.cpp index e5ff5fa8d..3a5138ca3 100644 --- a/libethereum/BlockQueue.cpp +++ b/libethereum/BlockQueue.cpp @@ -184,7 +184,7 @@ void BlockQueue::drainVerified_WITH_BOTH_LOCKS() ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc, bool _isOurs) { - cdebug << std::this_thread::get_id(); + clog(BlockQueueTraceChannel) << std::this_thread::get_id(); // Check if we already know this block. h256 h = BlockInfo::headerHash(_block); From 2a9b906cc3f9d66ba231a04786c7d6142a06948c Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 2 Jul 2015 22:59:37 +0200 Subject: [PATCH 16/17] removed incorrect invariant checks (subject to race contition) --- libethereum/BlockChainSync.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/libethereum/BlockChainSync.cpp b/libethereum/BlockChainSync.cpp index 63ac620ce..04bb44d0b 100644 --- a/libethereum/BlockChainSync.cpp +++ b/libethereum/BlockChainSync.cpp @@ -791,10 +791,6 @@ bool PV60Sync::invariants() const return false; if (m_state == SyncState::Hashes) { - bool hashes = false; - host().foreachPeer([&](std::shared_ptr _p) { if (_p->m_asking == Asking::Hashes) hashes = true; return !hashes; }); - if (!hashes) - return false; if (!m_syncingLatestHash) return false; if (m_syncingNeededBlocks.empty() != (!m_syncingLastReceivedHash)) @@ -802,10 +798,6 @@ bool PV60Sync::invariants() const } if (m_state == SyncState::Blocks || m_state == SyncState::NewBlocks) { - bool blocks = false; - host().foreachPeer([&](std::shared_ptr _p) { if (_p->m_asking == Asking::Blocks) blocks = true; return !blocks; }); - if (!blocks) - return false; if (downloadMan().isComplete()) return false; } From 07045622075b600ce9994335cd8eff3425861241 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Fri, 3 Jul 2015 00:01:12 +0200 Subject: [PATCH 17/17] style --- test/libethereum/transactionqueue.cpp | 34 ++++++++++++++++----------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/test/libethereum/transactionqueue.cpp b/test/libethereum/transactionqueue.cpp index b7071d640..ab85350a5 100644 --- a/test/libethereum/transactionqueue.cpp +++ b/test/libethereum/transactionqueue.cpp @@ -14,10 +14,10 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file transaction.cpp - * @author Christoph Jentzsch +/** @file transactionqueue.cpp + * @author Christoph Jentzsch * @date 2015 - * Transaaction test functions. + * TransactionQueue test functions. */ #include @@ -35,24 +35,30 @@ BOOST_AUTO_TEST_CASE(maxNonce) dev::eth::TransactionQueue txq; // from a94f5374fce5edbc8e2a8697c15331677e6ebf0b - Transaction tx0(0, 10 * szabo, 25000, Address("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"), bytes(), 0, Secret("0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8") ); - Transaction tx0_1(1, 10 * szabo, 25000, Address("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"), bytes(), 0, Secret("0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8") ); - Transaction tx1(0, 10 * szabo, 25000, Address("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"), bytes(), 1, Secret("0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8") ); - Transaction tx2(0, 10 * szabo, 25000, Address("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"), bytes(), 2, Secret("0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8") ); - Transaction tx9(0, 10 * szabo, 25000, Address("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"), bytes(), 9, Secret("0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8") ); + const u256 gasCost = 10 * szabo; + const u256 gas = 25000; + Address dest = Address("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"); + Address to = Address("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"); + Secret sec = Secret("0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8"); + Transaction tx0(0, gasCost, gas, dest, bytes(), 0, sec ); + Transaction tx0_1(1, gasCost, gas, dest, bytes(), 0, sec ); + Transaction tx1(0, gasCost, gas, dest, bytes(), 1, sec ); + Transaction tx2(0, gasCost, gas, dest, bytes(), 2, sec ); + Transaction tx9(0, gasCost, gas, dest, bytes(), 9, sec ); txq.import(tx0); - BOOST_CHECK_EQUAL(1, (unsigned)txq.maxNonce(Address("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"))); + BOOST_CHECK(1 == txq.maxNonce(to)); txq.import(tx0); - BOOST_CHECK_EQUAL(1, (unsigned)txq.maxNonce(Address("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"))); + BOOST_CHECK(1 == txq.maxNonce(to)); txq.import(tx0_1); - BOOST_CHECK_EQUAL(1, (unsigned)txq.maxNonce(Address("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"))); + BOOST_CHECK(1 == txq.maxNonce(to)); txq.import(tx1); - BOOST_CHECK_EQUAL(2, (unsigned)txq.maxNonce(Address("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"))); + BOOST_CHECK(2 == txq.maxNonce(to)); txq.import(tx9); - BOOST_CHECK_EQUAL(10, (unsigned)txq.maxNonce(Address("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"))); + BOOST_CHECK(10 == txq.maxNonce(to)); txq.import(tx2); - BOOST_CHECK_EQUAL(10, (unsigned)txq.maxNonce(Address("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"))); + BOOST_CHECK(10 == txq.maxNonce(to)); + } BOOST_AUTO_TEST_SUITE_END()