From 640f688b4508e7a728fbb1143c636ce9aa26be2f Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 7 Mar 2015 16:43:05 +0100 Subject: [PATCH 1/2] Gas pricing infrastructure and a couple of pricing mechanisms. --- eth/main.cpp | 120 +++++++++++++++++++++++++++++++++++------ libethereum/Client.cpp | 54 ++++++++++++++++--- libethereum/Client.h | 28 +++++++++- libethereum/State.cpp | 39 -------------- libethereum/State.h | 55 +++++++++---------- test/blockchain.cpp | 2 +- 6 files changed, 208 insertions(+), 90 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index a7bed4f3b..b0dac094e 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -74,6 +74,9 @@ void interactiveHelp() << " jsonstop Stops the JSON-RPC server." << endl << " connect Connects to a specific peer." << endl << " verbosity () Gets or sets verbosity level." << endl + << " setetherprice

Resets the ether price." << endl + << " setpriority

Resets the transaction priority." << endl + << " minestart Starts mining." << endl << " minestart Starts mining." << endl << " minestop Stops mining." << endl << " mineforce Forces mining, even when there are no transactions." << endl @@ -85,12 +88,12 @@ void interactiveHelp() << " send Execute a given transaction with current secret." << endl << " contract Create a new contract with current secret." << endl << " peers List the peers that are connected" << endl - << " listAccounts List the accounts on the network." << endl - << " listContracts List the contracts on the network." << endl - << " setSecret Set the secret to the hex secret key." < Set the coinbase (mining payout) address." < Export the config (.RLP) to the path provided." < Import the config (.RLP) from the path provided." < Set the secret to the hex secret key." < Set the coinbase (mining payout) address." < Export the config (.RLP) to the path provided." < Import the config (.RLP) from the path provided." < Dumps a contract to /.evm." << endl << " dumptrace Dumps a transaction trace" << endl << "to . should be one of pretty, standard, standard+." << endl << " dumpreceipt Dumps a transation receipt." << endl @@ -104,9 +107,11 @@ void help() << "Options:" << endl << " -a,--address Set the coinbase (mining payout) address to addr (default: auto)." << endl << " -b,--bootstrap Connect to the default Ethereum peerserver." << endl + << " -B,--block-fees Set the block fee profit in the reference unit e.g. ¢ (Default: 15)." << endl << " -c,--client-name Add a name to your client's version string (default: blank)." << endl << " -d,--db-path Load database from path (default: ~/.ethereum " << endl << " /Etherum or Library/Application Support/Ethereum)." << endl + << " -e,--ether-price Set the ether price in the reference unit e.g. ¢ (Default: 30.679)." << endl << " -f,--force-mining Mine even when there are no transaction to mine (Default: off)" << endl << " -h,--help Show this help message and exit." << endl << " -i,--interactive Enter interactive mode (default: non-interactive)." << endl @@ -115,11 +120,12 @@ void help() << " --json-rpc-port Specify JSON-RPC server port (implies '-j', default: 8080)." << endl #endif << " -l,--listen Listen on the given port for incoming connected (default: 30303)." << endl + << " -L,--local-networking Use peers whose addresses are local." << endl << " -m,--mining Enable mining, optionally for a specified number of blocks (Default: off)" << endl << " -n,--upnp Use upnp for NAT (default: on)." << endl - << " -L,--local-networking Use peers whose addresses are local." << endl << " -o,--mode Start a full node or a peer node (Default: full)." << endl << " -p,--port Connect to remote port (default: 30303)." << endl + << " -P,--priority <0 - 100> Default % priority of a transaction (default: 50)." << endl << " -r,--remote Connect to remote host (default: none)." << endl << " -s,--secret Set the secret key for use with send command (default: auto)." << endl << " -t,--miners Number of mining threads to start (Default: " << thread::hardware_concurrency() << ")" << endl @@ -128,7 +134,7 @@ void help() << " -x,--peers Attempt to connect to given number of peers (Default: 5)." << endl << " -V,--version Show the version and exit." << endl #if ETH_EVMJIT - << " --jit Use EVM JIT (default: off)." << endl + << " --jit Use EVM JIT (default: off)." << endl #endif ; exit(0); @@ -212,6 +218,9 @@ int main(int argc, char** argv) bool structuredLogging = false; string structuredLoggingFormat = "%Y-%m-%dT%H:%M:%S"; string clientName; + TransactionPriority priority = TransactionPriority::Medium; + double etherPrice = 30.679; + double blockFees = 15.0; // Init defaults Defaults::get(); @@ -289,6 +298,48 @@ int main(int argc, char** argv) structuredLogging = true; else if ((arg == "-d" || arg == "--path" || arg == "--db-path") && i + 1 < argc) dbPath = argv[++i]; + else if ((arg == "-B" || arg == "--block-fees") && i + 1 < argc) + { + try { + blockFees = stof(argv[++i]); + } + catch (...) { + cerr << "Bad " << arg << " option: " << argv[++i] << endl; + return -1; + } + } + else if ((arg == "-e" || arg == "--ether-price") && i + 1 < argc) + { + try { + etherPrice = stof(argv[++i]); + } + catch (...) { + cerr << "Bad " << arg << " option: " << argv[++i] << endl; + return -1; + } + } + else if ((arg == "-P" || arg == "--priority") && i + 1 < argc) + { + string m = boost::to_lower_copy(string(argv[++i])); + if (m == "lowest") + priority = TransactionPriority::Lowest; + else if (m == "low") + priority = TransactionPriority::Low; + else if (m == "medium" || m == "mid" || m == "default" || m == "normal") + priority = TransactionPriority::Medium; + else if (m == "high") + priority = TransactionPriority::High; + else if (m == "highest") + priority = TransactionPriority::Highest; + else + try { + priority = (TransactionPriority)(max(0, min(100, stoi(m))) * 8 / 100); + } + catch (...) { + cerr << "Unknown " << arg << " option: " << m << endl; + return -1; + } + } else if ((arg == "-m" || arg == "--mining") && i + 1 < argc) { string m = argv[++i]; @@ -301,7 +352,7 @@ int main(int argc, char** argv) mining = stoi(m); } catch (...) { - cerr << "Unknown -m/--mining option: " << m << endl; + cerr << "Unknown " << arg << " option: " << m << endl; return -1; } } @@ -373,10 +424,12 @@ int main(int argc, char** argv) miners ); web3.setIdealPeerCount(peers); + std::shared_ptr gasPricer = make_shared(u256(double(ether / 1000) / etherPrice), u256(blockFees * 1000)); eth::Client* c = mode == NodeMode::Full ? web3.ethereum() : nullptr; StructuredLogger::starting(clientImplString, dev::Version); if (c) { + c->setGasPricer(gasPricer); c->setForceMining(forceMining); c->setAddress(coinbase); } @@ -435,6 +488,7 @@ int main(int argc, char** argv) istringstream iss(l); string cmd; iss >> cmd; + boost::to_lower(cmd); if (cmd == "netstart") { iss >> netPrefs.listenPort; @@ -466,6 +520,42 @@ int main(int argc, char** argv) iss >> enable; c->setForceMining(isTrue(enable)); } + else if (c && cmd == "setblockfees") + { + iss >> blockFees; + gasPricer->setRefBlockFees(u256(blockFees * 1000)); + cout << "Block fees: " << blockFees << endl; + } + else if (c && cmd == "setetherprice") + { + iss >> etherPrice; + gasPricer->setRefPrice(u256(double(ether / 1000) / etherPrice)); + cout << "ether Price: " << etherPrice << endl; + } + else if (c && cmd == "setpriority") + { + string m; + iss >> m; + boost::to_lower(m); + if (m == "lowest") + priority = TransactionPriority::Lowest; + else if (m == "low") + priority = TransactionPriority::Low; + else if (m == "medium" || m == "mid" || m == "default" || m == "normal") + priority = TransactionPriority::Medium; + else if (m == "high") + priority = TransactionPriority::High; + else if (m == "highest") + priority = TransactionPriority::Highest; + else + try { + priority = (TransactionPriority)(max(0, min(100, stoi(m))) * 8 / 100); + } + catch (...) { + cerr << "Unknown priority: " << m << endl; + } + cout << "Priority: " << (int)priority << "/8" << endl; + } else if (cmd == "verbosity") { if (iss.peek() != -1) @@ -582,7 +672,7 @@ int main(int argc, char** argv) else cwarn << "Require parameters: transact ADDRESS AMOUNT GASPRICE GAS SECRET DATA"; } - else if (c && cmd == "listContracts") + else if (c && cmd == "listcontracts") { auto acs =c->addresses(); string ss; @@ -593,7 +683,7 @@ int main(int argc, char** argv) cout << ss << endl; } } - else if (c && cmd == "listAccounts") + else if (c && cmd == "listaccounts") { auto acs =c->addresses(); string ss; @@ -809,7 +899,7 @@ int main(int argc, char** argv) } } } - else if (cmd == "setSecret") + else if (cmd == "setsecret") { if (iss.peek() != -1) { @@ -820,7 +910,7 @@ int main(int argc, char** argv) else cwarn << "Require parameter: setSecret HEXSECRETKEY"; } - else if (cmd == "setAddress") + else if (cmd == "setaddress") { if (iss.peek() != -1) { @@ -848,7 +938,7 @@ int main(int argc, char** argv) else cwarn << "Require parameter: setAddress HEXADDRESS"; } - else if (cmd == "exportConfig") + else if (cmd == "exportconfig") { if (iss.peek() != -1) { @@ -861,7 +951,7 @@ int main(int argc, char** argv) else cwarn << "Require parameter: exportConfig PATH"; } - else if (cmd == "importConfig") + else if (cmd == "importconfig") { if (iss.peek() != -1) { diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 05e1b86af..4572e29b8 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -60,16 +60,58 @@ void VersionChecker::setOk() } } +void BasicGasPricer::update(BlockChain const& _bc) +{ + unsigned c = 0; + h256 p = _bc.currentHash(); + m_gasPerBlock = _bc.info(p).gasLimit; + + map dist; + unsigned total; + while (c < 1000 && p) + { + BlockInfo bi = _bc.info(p); + if (bi.transactionsRoot != EmptyTrie) + { + auto bb = _bc.block(p); + RLP r(bb); + BlockReceipts brs(_bc.receipts(bi.hash)); + for (unsigned i = 0; i < r[1].size(); ++i) + { + auto gu = brs.receipts[i].gasUsed(); + dist[Transaction(r[1][i].data(), CheckSignature::None).gasPrice()] += (unsigned)brs.receipts[i].gasUsed(); + total += (unsigned)gu; + } + } + p = bi.parentHash; + ++c; + } + if (total > 0) + { + unsigned t = 0; + unsigned q = 1; + m_octiles[0] = dist.begin()->first; + for (auto const& i: dist) + { + for (; t <= total * q / 8 && t + i.second > total * q / 8; ++q) + m_octiles[q] = i.first; + if (q > 7) + break; + } + m_octiles[8] = dist.rbegin()->first; + } +} + Client::Client(p2p::Host* _extNet, std::string const& _dbPath, bool _forceClean, u256 _networkId, int _miners): Worker("eth"), m_vc(_dbPath), m_bc(_dbPath, !m_vc.ok() || _forceClean), - m_gp(u256("60000000000000")), + m_gp(new TrivialGasPricer), m_stateDB(State::openDB(_dbPath, !m_vc.ok() || _forceClean)), m_preMine(Address(), m_stateDB), m_postMine(Address(), m_stateDB) { - m_gp.updateQuartiles(m_bc); + m_gp->update(m_bc); m_host = _extNet->registerCapability(new EthereumHost(m_bc, m_tq, m_bq, _networkId)); @@ -85,16 +127,16 @@ Client::Client(p2p::Host* _extNet, std::string const& _dbPath, bool _forceClean, startWorking(); } -Client::Client(p2p::Host* _extNet, u256 weiPerCent, std::string const& _dbPath, bool _forceClean, u256 _networkId, int _miners): +Client::Client(p2p::Host* _extNet, std::shared_ptr _gp, std::string const& _dbPath, bool _forceClean, u256 _networkId, int _miners): Worker("eth"), m_vc(_dbPath), m_bc(_dbPath, !m_vc.ok() || _forceClean), - m_gp(weiPerCent), + m_gp(_gp), m_stateDB(State::openDB(_dbPath, !m_vc.ok() || _forceClean)), m_preMine(Address(), m_stateDB), m_postMine(Address(), m_stateDB) { - m_gp.updateQuartiles(m_bc); + m_gp->update(m_bc); m_host = _extNet->registerCapability(new EthereumHost(m_bc, m_tq, m_bq, _networkId)); @@ -620,7 +662,7 @@ void Client::doWork() // returns h256s as blooms, once for each transaction. cwork << "postSTATE <== TQ"; - TransactionReceipts newPendingReceipts = m_postMine.sync(m_bc, m_tq, m_gp); + TransactionReceipts newPendingReceipts = m_postMine.sync(m_bc, m_tq, *m_gp); if (newPendingReceipts.size()) { for (size_t i = 0; i < newPendingReceipts.size(); i++) diff --git a/libethereum/Client.h b/libethereum/Client.h index 677c70977..5bfaf8051 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -160,6 +160,27 @@ private: State m_state; }; +class BasicGasPricer: public GasPricer +{ +public: + explicit BasicGasPricer(u256 _weiPerRef, u256 _refsPerBlock): m_weiPerRef(_weiPerRef), m_refsPerBlock(_refsPerBlock) {} + + void setRefPrice(u256 _weiPerRef) { m_weiPerRef = _weiPerRef; } + void setRefBlockFees(u256 _refsPerBlock) { m_refsPerBlock = _refsPerBlock; } + +protected: + u256 ask(State const&) const override { return m_weiPerRef * m_refsPerBlock / m_gasPerBlock; } + u256 bid(TransactionPriority _p = TransactionPriority::Medium) const override { return m_octiles[(int)_p] > 0 ? m_octiles[(int)_p] : (m_weiPerRef * m_refsPerBlock / m_gasPerBlock); } + + void update(BlockChain const& _bc) override; + +private: + u256 m_weiPerRef; + u256 m_refsPerBlock; + u256 m_gasPerBlock = 1000000; + std::array m_octiles; +}; + /** * @brief Main API hub for interfacing with Ethereum. */ @@ -179,7 +200,7 @@ public: explicit Client( p2p::Host* _host, - u256 _weiPerCent, + std::shared_ptr _gpForAdoption, // pass it in with new. std::string const& _dbPath = std::string(), bool _forceClean = false, u256 _networkId = 0, @@ -189,6 +210,9 @@ public: /// Destructor. virtual ~Client(); + /// Resets the gas pricer to some other object. + void setGasPricer(std::shared_ptr _gp) { m_gp = _gp; } + /// Submits the given message-call transaction. virtual void transact(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo); @@ -361,7 +385,7 @@ private: CanonBlockChain m_bc; ///< Maintains block database. TransactionQueue m_tq; ///< Maintains a list of incoming transactions not yet in a block on the blockchain. BlockQueue m_bq; ///< Maintains a list of incoming blocks not yet on the blockchain (to be imported). - GasPricer m_gp; ///< The gas pricer. + std::shared_ptr m_gp; ///< The gas pricer. mutable SharedMutex x_stateDB; ///< Lock on the state DB, effectively a lock on m_postMine. OverlayDB m_stateDB; ///< Acts as the central point for the state database, so multiple States can share it. diff --git a/libethereum/State.cpp b/libethereum/State.cpp index e405f5cb8..d1e430dbe 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -464,45 +464,6 @@ TransactionReceipts State::sync(BlockChain const& _bc, TransactionQueue& _tq, Ga return ret; } -void GasPricer::updateQuartiles(BlockChain const& _bc) -{ - unsigned c = 0; - h256 p = _bc.currentHash(); - - map dist; - unsigned total; - while (c < 1000 && p) - { - BlockInfo bi = _bc.info(p); - if (bi.transactionsRoot != EmptyTrie) - { - auto bb = _bc.block(p); - RLP r(bb); - BlockReceipts brs(_bc.receipts(bi.hash)); - for (unsigned i = 0; i < r[1].size(); ++i) - { - auto gu = brs.receipts[i].gasUsed(); - dist[Transaction(r[1][i].data(), CheckSignature::None).gasPrice()] += (unsigned)brs.receipts[i].gasUsed(); - total += (unsigned)gu; - } - } - p = bi.parentHash; - ++c; - } - if (total > 0) - { - unsigned t = 0; - unsigned q = 1; - for (auto const& i: dist) - { - for (; t <= total * q / 4 && t + i.second > total * q / 4; ++q) - m_quartiles[q - 1] = i.first; - if (q > 3) - break; - } - } -} - u256 State::enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce) { // m_currentBlock is assumed to be prepopulated and reset. diff --git a/libethereum/State.h b/libethereum/State.h index 49e353b1e..78ec85f38 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -47,6 +47,7 @@ namespace eth { class BlockChain; +class State; struct StateChat: public LogChannel { static const char* name() { return "-S-"; } static const int verbosity = 4; }; struct StateTrace: public LogChannel { static const char* name() { return "=S="; } static const int verbosity = 7; }; @@ -55,7 +56,32 @@ struct StateSafeExceptions: public LogChannel { static const char* name() { retu enum class BaseState { Empty, CanonGenesis }; -class GasPricer; +enum class TransactionPriority +{ + Lowest = 0, + Low = 2, + Medium = 4, + High = 6, + Highest = 8 +}; + +class GasPricer +{ +public: + GasPricer() {} + + virtual u256 ask(State const&) const = 0; + virtual u256 bid(TransactionPriority _p = TransactionPriority::Medium) const = 0; + + virtual void update(BlockChain const&) {} +}; + +class TrivialGasPricer: public GasPricer +{ +protected: + u256 ask(State const&) const override { return 10 * szabo; } + u256 bid(TransactionPriority = TransactionPriority::Medium) const override { return 10 * szabo; } +}; /** * @brief Model of the current state of the ledger. @@ -153,6 +179,7 @@ public: /// Like sync but only operate on _tq, killing the invalid/old ones. bool cull(TransactionQueue& _tq) const; + /// Returns the last few block hashes of the current chain. LastHashes getLastHashes(BlockChain const& _bc, unsigned _n) const; /// Execute a given transaction. @@ -370,32 +397,6 @@ void commit(std::map const& _cache, DB& _db, SecureTrieDB m_quartiles; -}; - } } diff --git a/test/blockchain.cpp b/test/blockchain.cpp index ccbc84956..0e1128ef9 100644 --- a/test/blockchain.cpp +++ b/test/blockchain.cpp @@ -87,7 +87,7 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) // get txs TransactionQueue txs; - GasPricer gp(10000); + TrivialGasPricer gp; BOOST_REQUIRE(blObj.count("transactions")); for (auto const& txObj: blObj["transactions"].get_array()) { From 289fe2d58b3945a7b44ebf1aef693c799708bae1 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 7 Mar 2015 19:22:15 +0100 Subject: [PATCH 2/2] Fast lookups in filter. --- alethzero/MainWin.cpp | 228 ++++++++++++++---------------------------- eth/main.cpp | 3 + libethereum/Client.h | 1 - 3 files changed, 79 insertions(+), 153 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index e786b12ed..88b9103cb 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -372,28 +372,6 @@ void Main::load(QString _s) { QString contents = QString::fromStdString(dev::asString(dev::contents(_s.toStdString()))); ui->webView->page()->runJavaScript(contents); - /* - QFile fin(_s); - if (!fin.open(QFile::ReadOnly)) - return; - QString line; - while (!fin.atEnd()) - { - QString l = QString::fromUtf8(fin.readLine()); - line.append(l); - if (line.count('"') % 2) - { - line.chop(1); - } - else if (line.endsWith("\\\n")) - line.chop(2); - else - { - ui->webView->page()->currentFrame()->evaluateJavaScript(line); - //eval(line); - line.clear(); - } - }*/ } void Main::on_newTransaction_triggered() @@ -472,37 +450,17 @@ static Public stringToPublic(QString const& _a) return Public(); } -//static Address g_newNameReg; - QString Main::pretty(dev::Address _a) const { -/* static map s_memos; - - if (!s_memos.count(_a)) - {*/ -// if (!g_newNameReg) - auto g_newNameReg = getNameReg(); - - if (g_newNameReg) - { - QString s = QString::fromStdString(toString(abiOut(ethereum()->call(g_newNameReg, abiIn("nameOf(address)", _a))))); -// s_memos[_a] = s; - if (s.size()) - return s; - } -/* } - else - if (s_memos[_a].size()) - return s_memos[_a];*/ + auto g_newNameReg = getNameReg(); + if (g_newNameReg) + { + QString s = QString::fromStdString(toString(abiOut(ethereum()->call(g_newNameReg, abiIn("nameOf(address)", _a))))); + if (s.size()) + return s; + } h256 n; -/* - if (h160 nameReg = (u160)ethereum()->stateAt(c_config, 0)) - n = ethereum()->stateAt(nameReg, (u160)(_a)); - - if (!n) - n = ethereum()->stateAt(m_nameReg, (u160)(_a)); -*/ return fromRaw(n); } @@ -527,41 +485,13 @@ Address Main::fromString(QString const& _n) const if (_n == "(Create Contract)") return Address(); -/* static map s_memos; - - if (!s_memos.count(_n)) - {*/ -// if (!g_newNameReg) - auto g_newNameReg = getNameReg(); - - if (g_newNameReg) - { - Address a = abiOut

(ethereum()->call(g_newNameReg, abiIn("addressOf(string32)", ::fromString(_n.toStdString())))); -// s_memos[_n] = a; - if (a) - return a; - } -/* } - else - if (s_memos[_n]) - return s_memos[_n]; - - string sn = _n.toStdString(); - if (sn.size() > 32) - sn.resize(32); - h256 n; - memcpy(n.data(), sn.data(), sn.size()); - memset(n.data() + sn.size(), 0, 32 - sn.size()); - if (_n.size()) + auto g_newNameReg = getNameReg(); + if (g_newNameReg) { - if (h160 nameReg = (u160)ethereum()->stateAt(c_config, 0)) - if (h256 a = ethereum()->stateAt(nameReg, n)) - return right160(a); - - if (h256 a = ethereum()->stateAt(m_nameReg, n)) - return right160(a); - }*/ - + Address a = abiOut
(ethereum()->call(g_newNameReg, abiIn("addressOf(string32)", ::fromString(_n.toStdString())))); + if (a) + return a; + } if (_n.size() == 40) { try @@ -595,13 +525,6 @@ QString Main::lookup(QString const& _a) const h256 n; memcpy(n.data(), sn.data(), sn.size()); -/* string sn2 = _a.toStdString(); - if (sn2.size() > 32) - sn2 = sha3(sn2, false); - h256 n2; - memcpy(n2.data(), sn2.data(), sn2.size()); -*/ - h256 ret; // TODO: fix with the new DNSreg contract // if (h160 dnsReg = (u160)ethereum()->stateAt(c_config, 4, 0)) @@ -1038,31 +961,6 @@ void Main::refreshBlockCount() ui->blockCount->setText(QString("%6 #%1 @%3 T%2 PV%4 D%5").arg(d.number).arg(toLog2(d.totalDifficulty)).arg(toLog2(diff)).arg(c_protocolVersion).arg(c_databaseVersion).arg(m_privateChain.size() ? "[" + m_privateChain + "] " : "testnet")); } -static bool blockMatch(string const& _f, BlockDetails const& _b, h256 _h, CanonBlockChain const& _bc) -{ - try - { - if (_f.size() > 1 && _f.size() < 10 && _f[0] == '#' && stoul(_f.substr(1)) == _b.number) - return true; - } - catch (...) {} - if (toHex(_h.ref()).find(_f) != string::npos) - return true; - BlockInfo bi(_bc.block(_h)); - string info = toHex(bi.stateRoot.ref()) + " " + toHex(bi.coinbaseAddress.ref()) + " " + toHex(bi.transactionsRoot.ref()) + " " + toHex(bi.sha3Uncles.ref()); - if (info.find(_f) != string::npos) - return true; - return false; -} - -static bool transactionMatch(string const& _f, Transaction const& _t) -{ - string info = toHex(_t.receiveAddress().ref()) + " " + toHex(_t.sha3().ref()) + " " + toHex(_t.sha3(eth::WithoutSignature).ref()) + " " + toHex(_t.sender().ref()); - if (info.find(_f) != string::npos) - return true; - return false; -} - void Main::on_turboMining_triggered() { ethereum()->setTurboMining(ui->turboMining->isChecked()); @@ -1072,55 +970,81 @@ void Main::refreshBlockChain() { cwatch << "refreshBlockChain()"; - QByteArray oldSelected = ui->blocks->count() ? ui->blocks->currentItem()->data(Qt::UserRole).toByteArray() : QByteArray(); - ui->blocks->clear(); + // TODO: keep the same thing highlighted. + // TODO: refactor into MVC + // TODO: use get by hash/number + // TODO: transactions, log addresses, log topics - string filter = ui->blockChainFilter->text().toLower().toStdString(); auto const& bc = ethereum()->blockChain(); - unsigned i = (ui->showAll->isChecked() || !filter.empty()) ? (unsigned)-1 : 10; - for (auto h = bc.currentHash(); bc.details(h) && i; h = bc.details(h).parent, --i) - { - auto d = bc.details(h); - auto bm = blockMatch(filter, d, h, bc); - if (bm) + QStringList filters = ui->blockChainFilter->text().toLower().split(QRegExp("\\s+"), QString::SkipEmptyParts); + + h256Set blocks; + for (QString f: filters) + if (f.size() == 64) { - QListWidgetItem* blockItem = new QListWidgetItem(QString("#%1 %2").arg(d.number).arg(h.abridged().c_str()), ui->blocks); - auto hba = QByteArray((char const*)h.data(), h.size); - blockItem->setData(Qt::UserRole, hba); - if (oldSelected == hba) - blockItem->setSelected(true); + h256 h(f.toStdString()); + if (bc.isKnown(h)) + blocks.insert(h); } + else if (f.toLongLong() <= bc.number()) + blocks.insert(bc.numberHash(u256(f.toLongLong()))); + /*else if (f.size() == 40) + { + Address h(f[0]); + if (bc.(h)) + blocks.insert(h); + }*/ + + QByteArray oldSelected = ui->blocks->count() ? ui->blocks->currentItem()->data(Qt::UserRole).toByteArray() : QByteArray(); + ui->blocks->clear(); + auto showBlock = [&](h256 const& h) { + auto d = bc.details(h); + QListWidgetItem* blockItem = new QListWidgetItem(QString("#%1 %2").arg(d.number).arg(h.abridged().c_str()), ui->blocks); + auto hba = QByteArray((char const*)h.data(), h.size); + blockItem->setData(Qt::UserRole, hba); + if (oldSelected == hba) + blockItem->setSelected(true); + int n = 0; auto b = bc.block(h); for (auto const& i: RLP(b)[1]) { Transaction t(i.data(), CheckSignature::Sender); - if (bm || transactionMatch(filter, t)) - { - QString s = t.receiveAddress() ? - QString(" %2 %5> %3: %1 [%4]") - .arg(formatBalance(t.value()).c_str()) - .arg(render(t.safeSender())) - .arg(render(t.receiveAddress())) - .arg((unsigned)t.nonce()) - .arg(ethereum()->codeAt(t.receiveAddress()).size() ? '*' : '-') : - QString(" %2 +> %3: %1 [%4]") - .arg(formatBalance(t.value()).c_str()) - .arg(render(t.safeSender())) - .arg(render(right160(sha3(rlpList(t.safeSender(), t.nonce()))))) - .arg((unsigned)t.nonce()); - QListWidgetItem* txItem = new QListWidgetItem(s, ui->blocks); - auto hba = QByteArray((char const*)h.data(), h.size); - txItem->setData(Qt::UserRole, hba); - txItem->setData(Qt::UserRole + 1, n); - if (oldSelected == hba) - txItem->setSelected(true); - } + QString s = t.receiveAddress() ? + QString(" %2 %5> %3: %1 [%4]") + .arg(formatBalance(t.value()).c_str()) + .arg(render(t.safeSender())) + .arg(render(t.receiveAddress())) + .arg((unsigned)t.nonce()) + .arg(ethereum()->codeAt(t.receiveAddress()).size() ? '*' : '-') : + QString(" %2 +> %3: %1 [%4]") + .arg(formatBalance(t.value()).c_str()) + .arg(render(t.safeSender())) + .arg(render(right160(sha3(rlpList(t.safeSender(), t.nonce()))))) + .arg((unsigned)t.nonce()); + QListWidgetItem* txItem = new QListWidgetItem(s, ui->blocks); + auto hba = QByteArray((char const*)h.data(), h.size); + txItem->setData(Qt::UserRole, hba); + txItem->setData(Qt::UserRole + 1, n); + if (oldSelected == hba) + txItem->setSelected(true); n++; } - if (h == bc.genesisHash()) - break; + }; + + if (filters.empty()) + { + unsigned i = ui->showAll->isChecked() ? (unsigned)-1 : 10; + for (auto h = bc.currentHash(); bc.details(h) && i; h = bc.details(h).parent, --i) + { + showBlock(h); + if (h == bc.genesisHash()) + break; + } } + else + for (auto const& h: blocks) + showBlock(h); if (!ui->blocks->currentItem()) ui->blocks->setCurrentRow(0); diff --git a/eth/main.cpp b/eth/main.cpp index b0dac094e..3b97c561d 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -626,6 +626,9 @@ int main(int argc, char** argv) iss >> hexAddr >> amount >> gasPrice >> gas >> sechex >> sdata; + if (!gasPrice) + gasPrice = gasPricer->bid(priority); + cnote << "Data:"; cnote << sdata; bytes data = dev::eth::parseData(sdata); diff --git a/libethereum/Client.h b/libethereum/Client.h index 5bfaf8051..9cbfd7989 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -168,7 +168,6 @@ public: void setRefPrice(u256 _weiPerRef) { m_weiPerRef = _weiPerRef; } void setRefBlockFees(u256 _refsPerBlock) { m_refsPerBlock = _refsPerBlock; } -protected: u256 ask(State const&) const override { return m_weiPerRef * m_refsPerBlock / m_gasPerBlock; } u256 bid(TransactionPriority _p = TransactionPriority::Medium) const override { return m_octiles[(int)_p] > 0 ? m_octiles[(int)_p] : (m_weiPerRef * m_refsPerBlock / m_gasPerBlock); }