From bb1ae30df92a201e31408120d4cd027aaa2a37b6 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Sat, 23 May 2015 08:59:40 +0200 Subject: [PATCH 01/13] add transact create --- eth/main.cpp | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/eth/main.cpp b/eth/main.cpp index 33d049843..88b9198a8 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -1032,6 +1032,67 @@ int main(int argc, char** argv) else cwarn << "Require parameters: submitTransaction ADDRESS AMOUNT GASPRICE GAS SECRET DATA"; } + else if (c && cmd == "cretract") + { + auto const& bc =c->blockChain(); + auto h = bc.currentHash(); + auto blockData = bc.block(h); + BlockInfo info(blockData); + if (iss.peek() != -1) + { + u256 amount; + u256 gasPrice; + u256 gas; + string sechex; + string sdata; + + iss >> amount >> gasPrice >> gas >> sechex >> sdata; + + if (!gasPrice) + gasPrice = gasPricer->bid(priority); + + cnote << "Data:"; + cnote << sdata; + bytes data = dev::eth::parseData(sdata); + cnote << "Bytes:"; + string sbd = asString(data); + bytes bbd = asBytes(sbd); + stringstream ssbd; + ssbd << bbd; + cnote << ssbd.str(); + int ssize = sechex.length(); + u256 minGas = (u256)Transaction::gasRequired(data, 0); + if (gas < minGas) + cwarn << "Minimum gas amount is" << minGas; + else if (ssize < 40) + { + if (ssize > 0) + cwarn << "Invalid secret length:" << ssize; + } + else + { + try + { + Secret secret = h256(fromHex(sechex)); + c->submitTransaction(secret, amount, data, gas, gasPrice); + + //Address dest = h160(fromHex(hexAddr)); + //c->submitTransaction(secret, amount, dest, data, gas, gasPrice); + } + catch (BadHexCharacter& _e) + { + cwarn << "invalid hex character, transaction rejected"; + cwarn << boost::diagnostic_information(_e); + } + catch (...) + { + cwarn << "transaction rejected"; + } + } + } + else + cwarn << "Require parameters: submitTransaction ADDRESS AMOUNT GASPRICE GAS SECRET DATA"; + } #if ETH_FATDB else if (c && cmd == "listcontracts") { From f78b6166d7a05fa6e01d6ad188456651f02e508d Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Tue, 9 Jun 2015 12:15:44 +0200 Subject: [PATCH 02/13] add eth(CLI) functionalities --- eth/main.cpp | 133 ++++++++++++++++++++++++++++++++++++++--- libdevcore/FixedHash.h | 2 +- libethereum/Client.h | 2 + 3 files changed, 129 insertions(+), 8 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index 2162776ea..66e3a7ed3 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -84,15 +84,24 @@ void interactiveHelp() << " minestop Stops mining." << endl << " mineforce Forces mining, even when there are no transactions." << endl << " block Gives the current block height." << endl + << " blockhashfromnumber Gives the block hash with the givne number." << endl + << " numberfromblockhash Gives the block number with the given hash." << endl + << " blockqueue Gives the current block queue status." << endl + << " findblock Searches for the block in the blockchain and blockqueue." << endl + << " firstunknown Gives the first unknown block from the blockqueue." << endl + << " retryunknown retries to import all unknown blocks from the blockqueue." << endl << " accounts Gives information on all owned accounts (balances, mining beneficiary and default signer)." << endl << " newaccount Creates a new account with the given name." << endl << " transact Execute a given transaction." << endl + << " txcreate Execute a given contract creation transaction." << endl << " 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 #if ETH_FATDB || !ETH_TRUE << " listaccounts List the accounts on the network." << endl << " listcontracts List the contracts on the network." << endl + << " balanceat
Gives the balance of the given account." << endl + << " codeat
Gives the code of the given account." << endl #endif << " setsigningkey Set the address with which to sign transactions." << endl << " setaddress Set the coinbase (mining payout) address." << endl @@ -961,9 +970,85 @@ int main(int argc, char** argv) cout << "Current mining beneficiary:" << endl << beneficiary << endl; cout << "Current signing account:" << endl << signingKey << endl; } + else if (c && cmd == "blockhashfromnumber") + { + if (iss.peek() != -1) + { + unsigned number; + iss >> number; + cout << " hash of block: " << c->hashFromNumber(number).hex() << endl; + } + } + else if (c && cmd == "numberfromblockhash") + { + if (iss.peek() != -1) + { + string stringHash; + iss >> stringHash; + + h256 hash = h256(fromHex(stringHash)); + cout << " number of block: " << c->numberFromHash(hash) << endl; + } + } else if (c && cmd == "block") { - cout << "Current block: " <blockChain().details().number << endl; + cout << "Current block: " << c->blockChain().details().number << endl; + } + else if (c && cmd == "blockqueue") + { + cout << "Current blockqueue status: " << endl << c->blockQueueStatus() << endl; + } + else if (c && cmd == "findblock") + { + if (iss.peek() != -1) + { + string stringHash; + iss >> stringHash; + + h256 hash = h256(fromHex(stringHash)); + + // search in blockchain + cout << "search in blockchain... " << endl; + try + { + cout << c->blockInfo(hash) << endl; + } + catch(Exception& _e) + { + cout << "block not in blockchain" << endl; + cout << boost::diagnostic_information(_e) << endl; + } + + cout << "search in blockqueue... " << endl; + + switch(c->blockQueue().blockStatus(hash)) + { + case QueueStatus::Ready: + cout << "Ready" << endl; + break; + case QueueStatus::UnknownParent: + cout << "UnknownParent" << endl; + break; + case QueueStatus::Bad: + cout << "Bad" << endl; + break; + case QueueStatus::Unknown: + cout << "Unknown" << endl; + break; + default: + cout << "invalid queueStatus" << endl; + } + } + else + cwarn << "Require parameter: findblock HASH"; + } + else if (c && cmd == "firstunknown") + { + cout << "first unknown blockhash: " << c->blockQueue().firstUnknown().hex() << endl; + } + else if (c && cmd == "retryunknown") + { + c->retryUnkonwn(); } else if (cmd == "peers") { @@ -1077,7 +1162,7 @@ int main(int argc, char** argv) else cwarn << "Require parameters: submitTransaction ADDRESS AMOUNT GASPRICE GAS SECRET DATA"; } - else if (c && cmd == "cretract") + else if (c && cmd == "txcreate") { auto const& bc =c->blockChain(); auto h = bc.currentHash(); @@ -1119,10 +1204,7 @@ int main(int argc, char** argv) try { Secret secret = h256(fromHex(sechex)); - c->submitTransaction(secret, amount, data, gas, gasPrice); - - //Address dest = h160(fromHex(hexAddr)); - //c->submitTransaction(secret, amount, dest, data, gas, gasPrice); + cout << " new contract address : " << c->submitTransaction(secret, amount, data, gas, gasPrice) << endl; } catch (BadHexCharacter& _e) { @@ -1136,7 +1218,7 @@ int main(int argc, char** argv) } } else - cwarn << "Require parameters: submitTransaction ADDRESS AMOUNT GASPRICE GAS SECRET DATA"; + cwarn << "Require parameters: submitTransaction ADDRESS AMOUNT GASPRICE GAS SECRET INIT"; } #if ETH_FATDB else if (c && cmd == "listcontracts") @@ -1161,6 +1243,43 @@ int main(int argc, char** argv) cout << ss << endl; } } + else if (c && cmd == "balanceat") + { + if (iss.peek() != -1) + { + string stringHash; + iss >> stringHash; + + Address address = h160(fromHex(stringHash)); + + cout << "balance of " << stringHash << " is: " << toString(c->balanceAt(address)) << endl; + } + } + // TODO implement << operator for std::unorderd_map +// else if (c && cmd == "storageat") +// { +// if (iss.peek() != -1) +// { +// string stringHash; +// iss >> stringHash; + +// Address address = h160(fromHex(stringHash)); + +// cout << "storage at " << stringHash << " is: " << c->storageAt(address) << endl; +// } +// } + else if (c && cmd == "codeat") + { + if (iss.peek() != -1) + { + string stringHash; + iss >> stringHash; + + Address address = h160(fromHex(stringHash)); + + cout << "code at " << stringHash << " is: " << toHex(c->codeAt(address)) << endl; + } + } #endif else if (c && cmd == "send") { diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h index 9b25837af..88bc0fe95 100644 --- a/libdevcore/FixedHash.h +++ b/libdevcore/FixedHash.h @@ -113,7 +113,7 @@ public: /// @returns an abridged version of the hash as a user-readable hex string. std::string abridged() const { return toHex(ref().cropped(0, 4)) + "\342\200\246"; } - /// @returns an abridged version of the hash as a user-readable hex string. + /// @returns the hash as a user-readable hex string. std::string hex() const { return toHex(ref()); } /// @returns a mutable byte vector_ref to the object's data. diff --git a/libethereum/Client.h b/libethereum/Client.h index 5132b5a30..90200c20b 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -156,6 +156,8 @@ public: CanonBlockChain const& blockChain() const { return m_bc; } /// Get some information on the block queue. BlockQueueStatus blockQueueStatus() const { return m_bq.status(); } + /// Get the block queue. + BlockQueue const& blockQueue() const { return m_bq; } // Mining stuff: From af9c64da917ff7b65f36faf4bfd298a0cb339b7e Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Tue, 9 Jun 2015 14:10:18 +0200 Subject: [PATCH 03/13] add queuestatus::importing --- eth/main.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/eth/main.cpp b/eth/main.cpp index 66e3a7ed3..8b3e1fa78 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -1026,6 +1026,9 @@ int main(int argc, char** argv) case QueueStatus::Ready: cout << "Ready" << endl; break; + case QueueStatus::Importing: + cout << "Importing" << endl; + break; case QueueStatus::UnknownParent: cout << "UnknownParent" << endl; break; From cf4c191a98d3950fe61daa9764cbbf09805498b0 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Thu, 11 Jun 2015 12:27:39 +0200 Subject: [PATCH 04/13] CLMiner, query only GPU devices By default now, CPU is not considered an OpenCL device. Also added a new argument --allow-opencl-cpu, that would allow OpenCL to include CPU devices if the user's openCL implementation caters for it. --- ethminer/MinerAux.h | 2 ++ libethash-cl/ethash_cl_miner.cpp | 36 ++++++++++++++++++-------- libethash-cl/ethash_cl_miner.h | 5 ++++ libethash-cl/ethash_cl_miner_kernel.cl | 4 +-- libethcore/Ethash.cpp | 5 ++++ libethcore/Ethash.h | 2 ++ 6 files changed, 40 insertions(+), 14 deletions(-) diff --git a/ethminer/MinerAux.h b/ethminer/MinerAux.h index 476c810c2..aac68f1a7 100644 --- a/ethminer/MinerAux.h +++ b/ethminer/MinerAux.h @@ -132,6 +132,8 @@ public: ProofOfWork::GPUMiner::listDevices(); exit(0); } + else if (arg == "--allow-opencl-cpu") + ProofOfWork::GPUMiner::allowCPU(); else if (arg == "--phone-home" && i + 1 < argc) { string m = argv[++i]; diff --git a/libethash-cl/ethash_cl_miner.cpp b/libethash-cl/ethash_cl_miner.cpp index 1a5eaddc3..054985a38 100644 --- a/libethash-cl/ethash_cl_miner.cpp +++ b/libethash-cl/ethash_cl_miner.cpp @@ -51,6 +51,8 @@ using namespace std; // TODO: If at any point we can use libdevcore in here then we should switch to using a LogChannel #define ETHCL_LOG(_contents) cout << "[OPENCL]:" << _contents << endl +// Types of OpenCL devices we are interested in +#define ETHCL_QUERIED_DEVICE_TYPES (CL_DEVICE_TYPE_GPU | CL_DEVICE_TYPE_ACCELERATOR) static void addDefinition(string& _source, char const* _id, unsigned _value) { @@ -82,9 +84,8 @@ string ethash_cl_miner::platform_info(unsigned _platformId, unsigned _deviceId) } // get GPU device of the selected platform - vector devices; unsigned platform_num = min(_platformId, platforms.size() - 1); - platforms[platform_num].getDevices(CL_DEVICE_TYPE_ALL, &devices); + vector devices = getDevices(platforms, _platformId); if (devices.empty()) { ETHCL_LOG("No OpenCL devices found."); @@ -99,6 +100,17 @@ string ethash_cl_miner::platform_info(unsigned _platformId, unsigned _deviceId) return "{ \"platform\": \"" + platforms[platform_num].getInfo() + "\", \"device\": \"" + device.getInfo() + "\", \"version\": \"" + device_version + "\" }"; } +std::vector ethash_cl_miner::getDevices(std::vector const& _platforms, unsigned _platformId) +{ + vector devices; + unsigned platform_num = min(_platformId, _platforms.size() - 1); + _platforms[platform_num].getDevices( + s_allowCPU ? CL_DEVICE_TYPE_ALL : ETHCL_QUERIED_DEVICE_TYPES, + &devices + ); + return devices; +} + unsigned ethash_cl_miner::getNumPlatforms() { vector platforms; @@ -116,9 +128,7 @@ unsigned ethash_cl_miner::getNumDevices(unsigned _platformId) return 0; } - vector devices; - unsigned platform_num = min(_platformId, platforms.size() - 1); - platforms[platform_num].getDevices(CL_DEVICE_TYPE_ALL, &devices); + vector devices = getDevices(platforms, _platformId); if (devices.empty()) { ETHCL_LOG("No OpenCL devices found."); @@ -152,6 +162,13 @@ bool ethash_cl_miner::configureGPU() ); } +bool ethash_cl_miner::s_allowCPU = false; + +void ethash_cl_miner::allowCPU() +{ + s_allowCPU = true; +} + bool ethash_cl_miner::searchForAllDevices(function _callback) { vector platforms; @@ -175,8 +192,7 @@ bool ethash_cl_miner::searchForAllDevices(unsigned _platformId, function= platforms.size()) return false; - vector devices; - platforms[_platformId].getDevices(CL_DEVICE_TYPE_ALL, &devices); + vector devices = getDevices(platforms, _platformId); for (cl::Device const& device: devices) if (_callback(device)) return true; @@ -204,8 +220,7 @@ void ethash_cl_miner::doForAllDevices(unsigned _platformId, function= platforms.size()) return; - vector devices; - platforms[_platformId].getDevices(CL_DEVICE_TYPE_ALL, &devices); + vector devices = getDevices(platforms, _platformId); for (cl::Device const& device: devices) _callback(device); } @@ -253,8 +268,7 @@ bool ethash_cl_miner::init( ETHCL_LOG("Using platform: " << platforms[_platformId].getInfo().c_str()); // get GPU device of the default platform - vector devices; - platforms[_platformId].getDevices(CL_DEVICE_TYPE_ALL, &devices); + vector devices = getDevices(platforms, _platformId); if (devices.empty()) { ETHCL_LOG("No OpenCL devices found."); diff --git a/libethash-cl/ethash_cl_miner.h b/libethash-cl/ethash_cl_miner.h index 4c986053a..dc3f7eca0 100644 --- a/libethash-cl/ethash_cl_miner.h +++ b/libethash-cl/ethash_cl_miner.h @@ -41,6 +41,7 @@ public: static std::string platform_info(unsigned _platformId = 0, unsigned _deviceId = 0); static void listDevices(); static bool configureGPU(); + static void allowCPU(); bool init( uint8_t const* _dag, @@ -56,6 +57,9 @@ public: void search_chunk(uint8_t const* header, uint64_t target, search_hook& hook); private: + + static std::vector getDevices(std::vector const& _platforms, unsigned _platformId); + enum { c_max_search_results = 63, c_num_buffers = 2, c_hash_batch_size = 1024, c_search_batch_size = 1024*256 }; cl::Context m_context; @@ -70,4 +74,5 @@ private: unsigned m_workgroup_size; bool m_opencl_1_1; + static bool s_allowCPU; }; diff --git a/libethash-cl/ethash_cl_miner_kernel.cl b/libethash-cl/ethash_cl_miner_kernel.cl index 8567bb164..46c94f241 100644 --- a/libethash-cl/ethash_cl_miner_kernel.cl +++ b/libethash-cl/ethash_cl_miner_kernel.cl @@ -275,8 +275,6 @@ uint inner_loop_chunks(uint4 init, uint thread_id, __local uint* share, __global return fnv_reduce(mix); } - - uint inner_loop(uint4 init, uint thread_id, __local uint* share, __global hash128_t const* g_dag, uint isolate) { uint4 mix = init; @@ -585,4 +583,4 @@ __kernel void ethash_search_chunks( uint slot = min(convert_uint(MAX_OUTPUTS), convert_uint(atomic_inc(&g_output[0]) + 1)); g_output[slot] = gid; } -} \ No newline at end of file +} diff --git a/libethcore/Ethash.cpp b/libethcore/Ethash.cpp index 9ac4474ba..09ecfe1a3 100644 --- a/libethcore/Ethash.cpp +++ b/libethcore/Ethash.cpp @@ -366,6 +366,11 @@ void Ethash::GPUMiner::pause() stopWorking(); } +void Ethash::GPUMiner::allowCPU() +{ + return ethash_cl_miner::allowCPU(); +} + std::string Ethash::GPUMiner::platformInfo() { return ethash_cl_miner::platform_info(s_platformId, s_deviceId); diff --git a/libethcore/Ethash.h b/libethcore/Ethash.h index 49a8ae006..91ca5f8fd 100644 --- a/libethcore/Ethash.h +++ b/libethcore/Ethash.h @@ -92,6 +92,7 @@ public: static void setDefaultDevice(unsigned) {} static void listDevices() {} static bool configureGPU() { return false; } + static void allowCPU() {} static void setNumInstances(unsigned _instances) { s_numInstances = std::min(_instances, std::thread::hardware_concurrency()); } protected: void kickOff() override @@ -121,6 +122,7 @@ public: static unsigned getNumDevices(); static void listDevices(); static bool configureGPU(); + static void allowCPU(); static void setDefaultPlatform(unsigned _id) { s_platformId = _id; } static void setDefaultDevice(unsigned _id) { s_deviceId = _id; } static void setNumInstances(unsigned _instances) { s_numInstances = std::min(_instances, getNumDevices()); } From 43f8d638fbe5bd3842fe8ace3656cdf8e5b12e54 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Thu, 11 Jun 2015 13:05:58 +0200 Subject: [PATCH 05/13] add transactnonce to ethcli --- eth/main.cpp | 70 ++++++++++++++++++++++++++++++++++++++ libethereum/ClientBase.cpp | 15 ++++++++ libethereum/ClientBase.h | 1 + 3 files changed, 86 insertions(+) diff --git a/eth/main.cpp b/eth/main.cpp index 8b3e1fa78..9128d9391 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -93,6 +93,7 @@ void interactiveHelp() << " accounts Gives information on all owned accounts (balances, mining beneficiary and default signer)." << endl << " newaccount Creates a new account with the given name." << endl << " transact Execute a given transaction." << endl + << " transactnonce Execute a given transaction with a specified nonce." << endl << " txcreate Execute a given contract creation transaction." << endl << " send Execute a given transaction with current secret." << endl << " contract Create a new contract with current secret." << endl @@ -1165,6 +1166,75 @@ int main(int argc, char** argv) else cwarn << "Require parameters: submitTransaction ADDRESS AMOUNT GASPRICE GAS SECRET DATA"; } + + else if (c && cmd == "transactnonce") + { + auto const& bc =c->blockChain(); + auto h = bc.currentHash(); + auto blockData = bc.block(h); + BlockInfo info(blockData); + if (iss.peek() != -1) + { + string hexAddr; + u256 amount; + u256 gasPrice; + u256 gas; + string sechex; + string sdata; + u256 nonce; + + iss >> hexAddr >> amount >> gasPrice >> gas >> sechex >> sdata >> nonce; + + if (!gasPrice) + gasPrice = gasPricer->bid(priority); + + cnote << "Data:"; + cnote << sdata; + bytes data = dev::eth::parseData(sdata); + cnote << "Bytes:"; + string sbd = asString(data); + bytes bbd = asBytes(sbd); + stringstream ssbd; + ssbd << bbd; + cnote << ssbd.str(); + int ssize = sechex.length(); + int size = hexAddr.length(); + u256 minGas = (u256)Transaction::gasRequired(data, 0); + if (size < 40) + { + if (size > 0) + cwarn << "Invalid address length:" << size; + } + else if (gas < minGas) + cwarn << "Minimum gas amount is" << minGas; + else if (ssize < 40) + { + if (ssize > 0) + cwarn << "Invalid secret length:" << ssize; + } + else + { + try + { + Secret secret = h256(fromHex(sechex)); + Address dest = h160(fromHex(hexAddr)); + c->submitTransaction(secret, amount, dest, data, gas, gasPrice, nonce); + } + catch (BadHexCharacter& _e) + { + cwarn << "invalid hex character, transaction rejected"; + cwarn << boost::diagnostic_information(_e); + } + catch (...) + { + cwarn << "transaction rejected"; + } + } + } + else + cwarn << "Require parameters: submitTransaction ADDRESS AMOUNT GASPRICE GAS SECRET DATA NONCE"; + } + else if (c && cmd == "txcreate") { auto const& bc =c->blockChain(); diff --git a/libethereum/ClientBase.cpp b/libethereum/ClientBase.cpp index 8dc666bb5..19f0fe737 100644 --- a/libethereum/ClientBase.cpp +++ b/libethereum/ClientBase.cpp @@ -45,6 +45,21 @@ State ClientBase::asOf(BlockNumber _h) const return asOf(bc().numberHash(_h)); } +void ClientBase::submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, u256 _nonce) +{ + prepareForTransaction(); + + auto a = toAddress(_secret); + u256 n = postMine().transactionsFrom(a); + cdebug << "submitTx: " << a << "postMine=" << n << "; tq=" << m_tq.maxNonce(a); + + Transaction t(_value, _gasPrice, _gas, _dest, _data, _nonce, _secret); + m_tq.import(t.rlp()); + + StructuredLogger::transactionReceived(t.sha3().abridged(), t.sender().abridged()); + cnote << "New transaction " << t << "(maxNonce for sender" << a << "is" << m_tq.maxNonce(a) << ")"; +} + void ClientBase::submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice) { prepareForTransaction(); diff --git a/libethereum/ClientBase.h b/libethereum/ClientBase.h index 2b271b1df..19bb2088d 100644 --- a/libethereum/ClientBase.h +++ b/libethereum/ClientBase.h @@ -76,6 +76,7 @@ public: virtual ~ClientBase() {} /// Submits the given message-call transaction. + virtual void submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, u256 _nonce); virtual void submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo) override; /// Submits a new contract-creation transaction. From eaee35dd0b6f94b94a2e6946696fdf9848fbc7b0 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Thu, 11 Jun 2015 12:58:28 +0200 Subject: [PATCH 06/13] Refactor in OpenCL argument passing - No need for many different functions to set each single option for the miner. First we set all options and then we execute them. This way --list-devices will give different results with --alow-opencl-cpu and without it as it should. - If the user has no GPU with sufficient memory we no longer default to CPU. It's better to throw an error and let the user remove the argument. It's easy to miss the defaulting to CPU log message. --- ethminer/MinerAux.h | 36 ++++++++++++++------------------ libethash-cl/ethash_cl_miner.cpp | 8 ++----- libethash-cl/ethash_cl_miner.h | 3 +-- libethcore/Ethash.cpp | 11 ++++------ libethcore/Ethash.h | 11 ++-------- 5 files changed, 25 insertions(+), 44 deletions(-) diff --git a/ethminer/MinerAux.h b/ethminer/MinerAux.h index aac68f1a7..2816f637a 100644 --- a/ethminer/MinerAux.h +++ b/ethminer/MinerAux.h @@ -128,12 +128,9 @@ public: throw BadArgument(); } else if (arg == "--list-devices") - { - ProofOfWork::GPUMiner::listDevices(); - exit(0); - } + shouldListDevices = true; else if (arg == "--allow-opencl-cpu") - ProofOfWork::GPUMiner::allowCPU(); + clAllowCPU = true; else if (arg == "--phone-home" && i + 1 < argc) { string m = argv[++i]; @@ -177,18 +174,7 @@ public: else if (arg == "-C" || arg == "--cpu") m_minerType = MinerType::CPU; else if (arg == "-G" || arg == "--opencl") - { - if (!ProofOfWork::GPUMiner::configureGPU()) - { - cout << "No GPU device with sufficient memory was found. Defaulting to CPU" << endl; - m_minerType = MinerType::CPU; - } - else - { - m_minerType = MinerType::GPU; - miningThreads = 1; - } - } + m_minerType = MinerType::GPU; else if (arg == "--no-precompute") { precompute = false; @@ -264,13 +250,22 @@ public: void execute() { + if (shouldListDevices) + { + ProofOfWork::GPUMiner::listDevices(); + exit(0); + } + if (m_minerType == MinerType::CPU) ProofOfWork::CPUMiner::setNumInstances(miningThreads); else if (m_minerType == MinerType::GPU) { - ProofOfWork::GPUMiner::setDefaultPlatform(openclPlatform); - ProofOfWork::GPUMiner::setDefaultDevice(openclDevice); ProofOfWork::GPUMiner::setNumInstances(miningThreads); + if (!ProofOfWork::GPUMiner::configureGPU(openclPlatform, openclDevice, clAllowCPU)) + { + cout << "No GPU device with sufficient memory was found. Can't GPU mine. Remove the -G argument" << endl; + exit(1); + } } if (mode == OperationMode::DAGInit) doInitDAG(initDAG); @@ -495,7 +490,8 @@ private: unsigned openclPlatform = 0; unsigned openclDevice = 0; unsigned miningThreads = UINT_MAX; - unsigned dagChunks = 1; + bool shouldListDevices = false; + bool clAllowCPU = false; /// DAG initialisation param. unsigned initDAG = 0; diff --git a/libethash-cl/ethash_cl_miner.cpp b/libethash-cl/ethash_cl_miner.cpp index 054985a38..db08d10c3 100644 --- a/libethash-cl/ethash_cl_miner.cpp +++ b/libethash-cl/ethash_cl_miner.cpp @@ -137,8 +137,9 @@ unsigned ethash_cl_miner::getNumDevices(unsigned _platformId) return devices.size(); } -bool ethash_cl_miner::configureGPU() +bool ethash_cl_miner::configureGPU(bool _allowCPU) { + s_allowCPU = _allowCPU; return searchForAllDevices([](cl::Device const _device) -> bool { cl_ulong result; @@ -164,11 +165,6 @@ bool ethash_cl_miner::configureGPU() bool ethash_cl_miner::s_allowCPU = false; -void ethash_cl_miner::allowCPU() -{ - s_allowCPU = true; -} - bool ethash_cl_miner::searchForAllDevices(function _callback) { vector platforms; diff --git a/libethash-cl/ethash_cl_miner.h b/libethash-cl/ethash_cl_miner.h index dc3f7eca0..44ec7eba9 100644 --- a/libethash-cl/ethash_cl_miner.h +++ b/libethash-cl/ethash_cl_miner.h @@ -40,8 +40,7 @@ public: static unsigned getNumDevices(unsigned _platformId = 0); static std::string platform_info(unsigned _platformId = 0, unsigned _deviceId = 0); static void listDevices(); - static bool configureGPU(); - static void allowCPU(); + static bool configureGPU(bool _allowCPU); bool init( uint8_t const* _dag, diff --git a/libethcore/Ethash.cpp b/libethcore/Ethash.cpp index 09ecfe1a3..20ba539d1 100644 --- a/libethcore/Ethash.cpp +++ b/libethcore/Ethash.cpp @@ -366,11 +366,6 @@ void Ethash::GPUMiner::pause() stopWorking(); } -void Ethash::GPUMiner::allowCPU() -{ - return ethash_cl_miner::allowCPU(); -} - std::string Ethash::GPUMiner::platformInfo() { return ethash_cl_miner::platform_info(s_platformId, s_deviceId); @@ -386,9 +381,11 @@ void Ethash::GPUMiner::listDevices() return ethash_cl_miner::listDevices(); } -bool Ethash::GPUMiner::configureGPU() +bool Ethash::GPUMiner::configureGPU(unsigned _platformId, unsigned _deviceId, bool _allowCPU) { - return ethash_cl_miner::configureGPU(); + s_platformId = _platformId; + s_deviceId = _deviceId; + return ethash_cl_miner::configureGPU(_allowCPU); } #endif diff --git a/libethcore/Ethash.h b/libethcore/Ethash.h index 91ca5f8fd..ee4c7d008 100644 --- a/libethcore/Ethash.h +++ b/libethcore/Ethash.h @@ -87,12 +87,8 @@ public: static unsigned instances() { return s_numInstances > 0 ? s_numInstances : std::thread::hardware_concurrency(); } static std::string platformInfo(); - static void setDefaultPlatform(unsigned) {} - static void setDagChunks(unsigned) {} - static void setDefaultDevice(unsigned) {} static void listDevices() {} - static bool configureGPU() { return false; } - static void allowCPU() {} + static bool configureGPU(unsigned, unsigned, bool) { return false; } static void setNumInstances(unsigned _instances) { s_numInstances = std::min(_instances, std::thread::hardware_concurrency()); } protected: void kickOff() override @@ -121,10 +117,7 @@ public: static std::string platformInfo(); static unsigned getNumDevices(); static void listDevices(); - static bool configureGPU(); - static void allowCPU(); - static void setDefaultPlatform(unsigned _id) { s_platformId = _id; } - static void setDefaultDevice(unsigned _id) { s_deviceId = _id; } + static bool configureGPU(unsigned _platformId, unsigned _deviceId, bool _allowCPU); static void setNumInstances(unsigned _instances) { s_numInstances = std::min(_instances, getNumDevices()); } protected: From 474705ba8089986056b98958865dacb202a586d2 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Thu, 11 Jun 2015 13:26:05 +0200 Subject: [PATCH 07/13] Styling changes --- ethminer/MinerAux.h | 72 +++++++++++++------------- libethash-cl/ethash_cl_miner_kernel.cl | 2 + 2 files changed, 38 insertions(+), 36 deletions(-) diff --git a/ethminer/MinerAux.h b/ethminer/MinerAux.h index 2816f637a..65311b019 100644 --- a/ethminer/MinerAux.h +++ b/ethminer/MinerAux.h @@ -97,11 +97,11 @@ public: if ((arg == "-F" || arg == "--farm") && i + 1 < argc) { mode = OperationMode::Farm; - farmURL = argv[++i]; + m_farmURL = argv[++i]; } else if (arg == "--farm-recheck" && i + 1 < argc) try { - farmRecheckPeriod = stol(argv[++i]); + m_farmRecheckPeriod = stol(argv[++i]); } catch (...) { @@ -110,7 +110,7 @@ public: } else if (arg == "--opencl-platform" && i + 1 < argc) try { - openclPlatform = stol(argv[++i]); + m_openclPlatform = stol(argv[++i]); } catch (...) { @@ -119,8 +119,8 @@ public: } else if (arg == "--opencl-device" && i + 1 < argc) try { - openclDevice = stol(argv[++i]); - miningThreads = 1; + m_openclDevice = stol(argv[++i]); + m_miningThreads = 1; } catch (...) { @@ -128,16 +128,16 @@ public: throw BadArgument(); } else if (arg == "--list-devices") - shouldListDevices = true; + m_shouldListDevices = true; else if (arg == "--allow-opencl-cpu") - clAllowCPU = true; + m_clAllowCPU = true; else if (arg == "--phone-home" && i + 1 < argc) { string m = argv[++i]; if (isTrue(m)) - phoneHome = true; + m_phoneHome = true; else if (isFalse(m)) - phoneHome = false; + m_phoneHome = false; else { cerr << "Bad " << arg << " option: " << m << endl; @@ -146,7 +146,7 @@ public: } else if (arg == "--benchmark-warmup" && i + 1 < argc) try { - benchmarkWarmup = stol(argv[++i]); + m_benchmarkWarmup = stol(argv[++i]); } catch (...) { @@ -155,7 +155,7 @@ public: } else if (arg == "--benchmark-trial" && i + 1 < argc) try { - benchmarkTrial = stol(argv[++i]); + m_benchmarkTrial = stol(argv[++i]); } catch (...) { @@ -164,7 +164,7 @@ public: } else if (arg == "--benchmark-trials" && i + 1 < argc) try { - benchmarkTrials = stol(argv[++i]); + m_benchmarkTrials = stol(argv[++i]); } catch (...) { @@ -177,7 +177,7 @@ public: m_minerType = MinerType::GPU; else if (arg == "--no-precompute") { - precompute = false; + m_precompute = false; } else if ((arg == "-D" || arg == "--create-dag") && i + 1 < argc) { @@ -185,7 +185,7 @@ public: mode = OperationMode::DAGInit; try { - initDAG = stol(m); + m_initDAG = stol(m); } catch (...) { @@ -235,7 +235,7 @@ public: else if ((arg == "-t" || arg == "--mining-threads") && i + 1 < argc) { try { - miningThreads = stol(argv[++i]); + m_miningThreads = stol(argv[++i]); } catch (...) { @@ -250,29 +250,29 @@ public: void execute() { - if (shouldListDevices) + if (m_shouldListDevices) { ProofOfWork::GPUMiner::listDevices(); exit(0); } if (m_minerType == MinerType::CPU) - ProofOfWork::CPUMiner::setNumInstances(miningThreads); + ProofOfWork::CPUMiner::setNumInstances(m_miningThreads); else if (m_minerType == MinerType::GPU) { - ProofOfWork::GPUMiner::setNumInstances(miningThreads); - if (!ProofOfWork::GPUMiner::configureGPU(openclPlatform, openclDevice, clAllowCPU)) + ProofOfWork::GPUMiner::setNumInstances(m_miningThreads); + if (!ProofOfWork::GPUMiner::configureGPU(m_openclPlatform, m_openclDevice, m_clAllowCPU)) { cout << "No GPU device with sufficient memory was found. Can't GPU mine. Remove the -G argument" << endl; exit(1); } } if (mode == OperationMode::DAGInit) - doInitDAG(initDAG); + doInitDAG(m_initDAG); else if (mode == OperationMode::Benchmark) - doBenchmark(m_minerType, phoneHome, benchmarkWarmup, benchmarkTrial, benchmarkTrials); + doBenchmark(m_minerType, m_phoneHome, m_benchmarkWarmup, m_benchmarkTrial, m_benchmarkTrials); else if (mode == OperationMode::Farm) - doFarm(m_minerType, farmURL, farmRecheckPeriod); + doFarm(m_minerType, m_farmURL, m_farmRecheckPeriod); } static void streamHelp(ostream& _out) @@ -438,7 +438,7 @@ private: cnote << "Grabbing DAG for" << newSeedHash; if (!(dag = EthashAux::full(newSeedHash, true, [&](unsigned _pc){ cout << "\rCreating DAG. " << _pc << "% done..." << flush; return 0; }))) BOOST_THROW_EXCEPTION(DAGCreationFailure()); - if (precompute) + if (m_precompute) EthashAux::computeFull(sha3(newSeedHash), true); if (hh != current.headerHash) { @@ -487,23 +487,23 @@ private: /// Mining options MinerType m_minerType = MinerType::CPU; - unsigned openclPlatform = 0; - unsigned openclDevice = 0; - unsigned miningThreads = UINT_MAX; - bool shouldListDevices = false; - bool clAllowCPU = false; + unsigned m_openclPlatform = 0; + unsigned m_openclDevice = 0; + unsigned m_miningThreads = UINT_MAX; + bool m_shouldListDevices = false; + bool m_clAllowCPU = false; /// DAG initialisation param. - unsigned initDAG = 0; + unsigned m_initDAG = 0; /// Benchmarking params - bool phoneHome = true; - unsigned benchmarkWarmup = 3; - unsigned benchmarkTrial = 3; - unsigned benchmarkTrials = 5; + bool m_phoneHome = true; + unsigned m_benchmarkWarmup = 3; + unsigned m_benchmarkTrial = 3; + unsigned m_benchmarkTrials = 5; /// Farm params - string farmURL = "http://127.0.0.1:8545"; - unsigned farmRecheckPeriod = 500; - bool precompute = true; + string m_farmURL = "http://127.0.0.1:8545"; + unsigned m_farmRecheckPeriod = 500; + bool m_precompute = true; }; diff --git a/libethash-cl/ethash_cl_miner_kernel.cl b/libethash-cl/ethash_cl_miner_kernel.cl index 46c94f241..2143435ed 100644 --- a/libethash-cl/ethash_cl_miner_kernel.cl +++ b/libethash-cl/ethash_cl_miner_kernel.cl @@ -275,6 +275,8 @@ uint inner_loop_chunks(uint4 init, uint thread_id, __local uint* share, __global return fnv_reduce(mix); } + + uint inner_loop(uint4 init, uint thread_id, __local uint* share, __global hash128_t const* g_dag, uint isolate) { uint4 mix = init; From 7604f4c22476185f62e51e80faac22ee18a21321 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Thu, 11 Jun 2015 15:17:25 +0200 Subject: [PATCH 08/13] Smarter and more flexible GPU memory check - Added new option --cl-extragpumem with which you can let the OpenCL miner know how much GPU memory you believe your system would need for miscellaneous stuff like Windowing system rendering e.t.c. The default is 350 MB. - Added new option --curent-block with which you can let the miner know the current block during the configuration phase and as such help him provide a much more accurate calculation of how much GPU memory is required. - Added help(documentation) for some arguments that did not have one --- ethminer/MinerAux.h | 20 +++++++++++++++++++- libethash-cl/ethash_cl_miner.cpp | 17 +++++++++++------ libethash-cl/ethash_cl_miner.h | 7 ++++++- libethcore/Ethash.cpp | 10 ++++++++-- libethcore/Ethash.h | 10 ++++++++-- libethcore/EthashAux.cpp | 5 +++++ libethcore/EthashAux.h | 1 + 7 files changed, 58 insertions(+), 12 deletions(-) diff --git a/ethminer/MinerAux.h b/ethminer/MinerAux.h index 65311b019..f49fbd70d 100644 --- a/ethminer/MinerAux.h +++ b/ethminer/MinerAux.h @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -131,6 +132,8 @@ public: m_shouldListDevices = true; else if (arg == "--allow-opencl-cpu") m_clAllowCPU = true; + else if (arg == "--cl-extragpu-mem" && i + 1 < argc) + m_extraGPUMemory = 1000000 * stol(argv[++i]); else if (arg == "--phone-home" && i + 1 < argc) { string m = argv[++i]; @@ -175,6 +178,8 @@ public: m_minerType = MinerType::CPU; else if (arg == "-G" || arg == "--opencl") m_minerType = MinerType::GPU; + else if (arg == "--current-block" && i + 1 < argc) + m_currentBlock = stol(argv[++i]); else if (arg == "--no-precompute") { m_precompute = false; @@ -261,7 +266,13 @@ public: else if (m_minerType == MinerType::GPU) { ProofOfWork::GPUMiner::setNumInstances(m_miningThreads); - if (!ProofOfWork::GPUMiner::configureGPU(m_openclPlatform, m_openclDevice, m_clAllowCPU)) + if (!ProofOfWork::GPUMiner::configureGPU( + m_openclPlatform, + m_openclDevice, + m_clAllowCPU, + m_extraGPUMemory, + m_currentBlock + )) { cout << "No GPU device with sufficient memory was found. Can't GPU mine. Remove the -G argument" << endl; exit(1); @@ -303,6 +314,10 @@ public: << " --opencl-platform When mining using -G/--opencl use OpenCL platform n (default: 0)." << endl << " --opencl-device When mining using -G/--opencl use OpenCL device n (default: 0)." << endl << " -t, --mining-threads Limit number of CPU/GPU miners to n (default: use everything available on selected platform)" << endl + << " --allow-opencl-cpu Allows CPU to be considered as an OpenCL device if the OpenCL platform supports it." << endl + << " --list-devices List the detected OpenCL devices and exit." < m_currentBlock; + // default value is 350MB of GPU memory for other stuff (windows system rendering, e.t.c.) + unsigned m_extraGPUMemory = 350000000; /// DAG initialisation param. unsigned m_initDAG = 0; diff --git a/libethash-cl/ethash_cl_miner.cpp b/libethash-cl/ethash_cl_miner.cpp index db08d10c3..5f36393c6 100644 --- a/libethash-cl/ethash_cl_miner.cpp +++ b/libethash-cl/ethash_cl_miner.cpp @@ -32,11 +32,11 @@ #include #include #include +#include #include "ethash_cl_miner.h" #include "ethash_cl_miner_kernel.h" #define ETHASH_BYTES 32 -#define ETHASH_CL_MINIMUM_MEMORY 2000000000 // workaround lame platforms #if !CL_VERSION_1_2 @@ -137,14 +137,18 @@ unsigned ethash_cl_miner::getNumDevices(unsigned _platformId) return devices.size(); } -bool ethash_cl_miner::configureGPU(bool _allowCPU) +bool ethash_cl_miner::configureGPU(bool _allowCPU, unsigned _extraGPUMemory, boost::optional _currentBlock) { s_allowCPU = _allowCPU; - return searchForAllDevices([](cl::Device const _device) -> bool + s_extraRequiredGPUMem = _extraGPUMemory; + // by default let's only consider the DAG of the first epoch + uint64_t dagSize = _currentBlock ? ethash_get_datasize(*_currentBlock) : 1073739904U; + uint64_t requiredSize = dagSize + _extraGPUMemory; + return searchForAllDevices([&requiredSize](cl::Device const _device) -> bool { cl_ulong result; _device.getInfo(CL_DEVICE_GLOBAL_MEM_SIZE, &result); - if (result >= ETHASH_CL_MINIMUM_MEMORY) + if (result >= requiredSize) { ETHCL_LOG( "Found suitable OpenCL device [" << _device.getInfo() @@ -156,7 +160,7 @@ bool ethash_cl_miner::configureGPU(bool _allowCPU) ETHCL_LOG( "OpenCL device " << _device.getInfo() << " has insufficient GPU memory." << result << - " bytes of memory found < " << ETHASH_CL_MINIMUM_MEMORY << " bytes of memory required" + " bytes of memory found < " << requiredSize << " bytes of memory required" ); return false; } @@ -164,6 +168,7 @@ bool ethash_cl_miner::configureGPU(bool _allowCPU) } bool ethash_cl_miner::s_allowCPU = false; +unsigned ethash_cl_miner::s_extraRequiredGPUMem; bool ethash_cl_miner::searchForAllDevices(function _callback) { @@ -279,7 +284,7 @@ bool ethash_cl_miner::init( // configure chunk number depending on max allocateable memory cl_ulong result; device.getInfo(CL_DEVICE_MAX_MEM_ALLOC_SIZE, &result); - if (result >= ETHASH_CL_MINIMUM_MEMORY) + if (result >= _dagSize) { m_dagChunksNum = 1; ETHCL_LOG("Using 1 big chunk. Max OpenCL allocateable memory is" << result); diff --git a/libethash-cl/ethash_cl_miner.h b/libethash-cl/ethash_cl_miner.h index 44ec7eba9..b17fdeeb4 100644 --- a/libethash-cl/ethash_cl_miner.h +++ b/libethash-cl/ethash_cl_miner.h @@ -12,6 +12,7 @@ #include "cl.hpp" #endif +#include #include #include #include @@ -40,7 +41,7 @@ public: static unsigned getNumDevices(unsigned _platformId = 0); static std::string platform_info(unsigned _platformId = 0, unsigned _deviceId = 0); static void listDevices(); - static bool configureGPU(bool _allowCPU); + static bool configureGPU(bool _allowCPU, unsigned _extraGPUMemory, boost::optional _currentBlock); bool init( uint8_t const* _dag, @@ -73,5 +74,9 @@ private: unsigned m_workgroup_size; bool m_opencl_1_1; + /// Allow CPU to appear as an OpenCL device or not. Default is false static bool s_allowCPU; + /// GPU memory required for other things, like window rendering e.t.c. + /// User can set it via the --cl-extragpu-mem argument. + static unsigned s_extraRequiredGPUMem; }; diff --git a/libethcore/Ethash.cpp b/libethcore/Ethash.cpp index 20ba539d1..8600dd51a 100644 --- a/libethcore/Ethash.cpp +++ b/libethcore/Ethash.cpp @@ -381,11 +381,17 @@ void Ethash::GPUMiner::listDevices() return ethash_cl_miner::listDevices(); } -bool Ethash::GPUMiner::configureGPU(unsigned _platformId, unsigned _deviceId, bool _allowCPU) +bool Ethash::GPUMiner::configureGPU( + unsigned _platformId, + unsigned _deviceId, + bool _allowCPU, + unsigned _extraGPUMemory, + boost::optional _currentBlock +) { s_platformId = _platformId; s_deviceId = _deviceId; - return ethash_cl_miner::configureGPU(_allowCPU); + return ethash_cl_miner::configureGPU(_allowCPU, _extraGPUMemory, _currentBlock); } #endif diff --git a/libethcore/Ethash.h b/libethcore/Ethash.h index ee4c7d008..d9584f0d4 100644 --- a/libethcore/Ethash.h +++ b/libethcore/Ethash.h @@ -88,7 +88,7 @@ public: static unsigned instances() { return s_numInstances > 0 ? s_numInstances : std::thread::hardware_concurrency(); } static std::string platformInfo(); static void listDevices() {} - static bool configureGPU(unsigned, unsigned, bool) { return false; } + static bool configureGPU(unsigned, unsigned, bool, unsigned, boost::optional) { return false; } static void setNumInstances(unsigned _instances) { s_numInstances = std::min(_instances, std::thread::hardware_concurrency()); } protected: void kickOff() override @@ -117,7 +117,13 @@ public: static std::string platformInfo(); static unsigned getNumDevices(); static void listDevices(); - static bool configureGPU(unsigned _platformId, unsigned _deviceId, bool _allowCPU); + static bool configureGPU( + unsigned _platformId, + unsigned _deviceId, + bool _allowCPU, + unsigned _extraGPUMemory, + boost::optional _currentBlock + ); static void setNumInstances(unsigned _instances) { s_numInstances = std::min(_instances, getNumDevices()); } protected: diff --git a/libethcore/EthashAux.cpp b/libethcore/EthashAux.cpp index 0c1e84ebc..51a606ff8 100644 --- a/libethcore/EthashAux.cpp +++ b/libethcore/EthashAux.cpp @@ -54,6 +54,11 @@ uint64_t EthashAux::cacheSize(BlockInfo const& _header) return ethash_get_cachesize((uint64_t)_header.number); } +uint64_t EthashAux::dataSize(uint64_t _blockNumber) +{ + return ethash_get_datasize(_blockNumber); +} + h256 EthashAux::seedHash(unsigned _number) { unsigned epoch = _number / ETHASH_EPOCH_LENGTH; diff --git a/libethcore/EthashAux.h b/libethcore/EthashAux.h index e6fed519f..47180bfd2 100644 --- a/libethcore/EthashAux.h +++ b/libethcore/EthashAux.h @@ -66,6 +66,7 @@ public: static h256 seedHash(unsigned _number); static uint64_t number(h256 const& _seedHash); static uint64_t cacheSize(BlockInfo const& _header); + static uint64_t dataSize(uint64_t _blockNumber); static LightType light(h256 const& _seedHash); From 9e9a33b7134a8565cc478b647090d87fb9fa82fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 11 Jun 2015 11:17:57 +0200 Subject: [PATCH 09/13] Set stack memory limit on OSX. --- cmake/EthCompilerSettings.cmake | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index 53535a489..d21a3d4b1 100644 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -55,6 +55,11 @@ else () message(WARNING "Your compiler is not tested, if you run into any issues, we'd welcome any patches.") endif () +# Set stack memory limits +if (APPLE) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-stack_size,1000000") +endif() + if (PROFILING AND (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang"))) set(CMAKE_CXX_FLAGS "-g ${CMAKE_CXX_FLAGS}") set(CMAKE_C_FLAGS "-g ${CMAKE_C_FLAGS}") From 1593d20e6c9d3b0d57b4d743346f4163f793ec1d Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 11 Jun 2015 22:53:21 +0900 Subject: [PATCH 10/13] Fix for FixedHash::operator~(). --- libdevcore/FixedHash.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h index 88bc0fe95..2d1822b2c 100644 --- a/libdevcore/FixedHash.h +++ b/libdevcore/FixedHash.h @@ -100,7 +100,7 @@ public: FixedHash operator|(FixedHash const& _c) const { return FixedHash(*this) |= _c; } FixedHash& operator&=(FixedHash const& _c) { for (unsigned i = 0; i < N; ++i) m_data[i] &= _c.m_data[i]; return *this; } FixedHash operator&(FixedHash const& _c) const { return FixedHash(*this) &= _c; } - FixedHash& operator~() { for (unsigned i = 0; i < N; ++i) m_data[i] = ~m_data[i]; return *this; } + FixedHash operator~() const { FixedHash ret; for (unsigned i = 0; i < N; ++i) ret[i] = ~m_data[i]; return ret; } /// @returns true if all bytes in @a _c are set in this object. bool contains(FixedHash const& _c) const { return (*this & _c) == _c; } From 237d044a73fe0b28a4b61eb676ac08300d090095 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 12 Jun 2015 00:41:28 +0900 Subject: [PATCH 11/13] Reprocess in eth -i, don't network by default. --- eth/main.cpp | 29 ++++++++++++++++++++++++++--- libethereum/State.cpp | 7 ++++++- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index 5497a2cda..a7f483966 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -108,6 +108,7 @@ void interactiveHelp() << " exportconfig Export the config (.RLP) to the path provided." << endl << " importconfig Import the config (.RLP) from the path provided." << endl << " inspect Dumps a contract to /.evm." << endl + << " reprocess Reprocess a given block." << endl << " dumptrace Dumps a transaction trace" << endl << "to . should be one of pretty, standard, standard+." << endl << " dumpreceipt Dumps a transation receipt." << endl << " exit Exits the application." << endl; @@ -806,13 +807,19 @@ int main(int argc, char** argv) cout << "Transaction Signer: " << signingKey << endl; cout << "Mining Benefactor: " << beneficiary << endl; - web3.startNetwork(); - cout << "Node ID: " << web3.enode() << endl; + + if (bootstrap || !remoteHost.empty()) + { + web3.startNetwork(); + cout << "Node ID: " << web3.enode() << endl; + } + else + cout << "Networking disabled. To start, use netstart or pass -b or a remote host." << endl; if (bootstrap) for (auto const& i: Host::pocHosts()) web3.requirePeer(i.first, i.second); - if (remoteHost.size()) + if (!remoteHost.empty()) web3.addNode(p2p::NodeId(), remoteHost + ":" + toString(remotePort)); #if ETH_JSONRPC || !ETH_TRUE @@ -1403,6 +1410,22 @@ int main(int argc, char** argv) cout << "Hex: " << toHex(rb) << endl; cout << r << endl; } + else if (c && cmd == "reprocess") + { + string block; + iss >> block; + h256 blockHash; + try + { + if (block.size() == 64 || block.size() == 66) + blockHash = h256(block); + else + blockHash = c->blockChain().numberHash(stoi(block)); + c->state(blockHash); + } + catch (...) + {} + } else if (c && cmd == "dumptrace") { unsigned block; diff --git a/libethereum/State.cpp b/libethereum/State.cpp index c80863d2f..a4b784b6f 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -141,7 +141,12 @@ State::State(OverlayDB const& _db, BlockChain const& _bc, h256 _h, ImportRequire // 2. Enact the block's transactions onto this state. m_ourAddress = bi.coinbaseAddress; - enact(BlockChain::verifyBlock(b), _bc, _ir); + boost::timer t; + auto vb = BlockChain::verifyBlock(b); + cnote << "verifyBlock:" << t.elapsed(); + t.restart(); + enact(vb, _bc, _ir); + cnote << "enact:" << t.elapsed(); } else { From cb133837c4f27df8c9e86652358da16ecf53a924 Mon Sep 17 00:00:00 2001 From: Dimitry Date: Thu, 11 Jun 2015 18:53:29 +0300 Subject: [PATCH 12/13] expectOut fill section to vmTests --- test/TestHelper.cpp | 2 ++ test/libevm/vm.cpp | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index 873ea21e2..733ccb6d0 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -352,6 +352,8 @@ void ImportTest::exportTest(bytes const& _output, State const& _statePost) BOOST_CHECK_MESSAGE((m_TestObject["out"].get_str() == m_TestObject["expectOut"].get_str()), warning); else BOOST_WARN_MESSAGE((m_TestObject["out"].get_str() == m_TestObject["expectOut"].get_str()), warning); + + m_TestObject.erase(m_TestObject.find("expectOut")); } // export logs diff --git a/test/libevm/vm.cpp b/test/libevm/vm.cpp index ec66837e1..5bbab2e1c 100644 --- a/test/libevm/vm.cpp +++ b/test/libevm/vm.cpp @@ -388,6 +388,19 @@ void doVMTests(json_spirit::mValue& v, bool _fillin) o["callcreates"] = fev.exportCallCreates(); o["out"] = output.size() > 4096 ? "#" + toString(output.size()) : toHex(output, 2, HexPrefix::Add); + + // compare expected output with post output + if (o.count("expectOut") > 0) + { + std::string warning = "Check State: Error! Unexpected output: " + o["out"].get_str() + " Expected: " + o["expectOut"].get_str(); + if (Options::get().checkState) + BOOST_CHECK_MESSAGE((o["out"].get_str() == o["expectOut"].get_str()), warning); + else + BOOST_WARN_MESSAGE((o["out"].get_str() == o["expectOut"].get_str()), warning); + + o.erase(o.find("expectOut")); + } + o["gas"] = toCompactHex(fev.gas, HexPrefix::Add, 1); o["logs"] = exportLog(fev.sub.logs); } From 566b2b635447cc3313817eb8482ae04af2a99eb7 Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 11 Jun 2015 18:41:31 +0200 Subject: [PATCH 13/13] resync after downloading unknown new block --- libethereum/EthereumHost.cpp | 36 +++++++++++++++++++++++++++++------- libethereum/EthereumHost.h | 2 ++ libp2p/Host.cpp | 19 ++++++++++++------- libp2p/Host.h | 1 + 4 files changed, 44 insertions(+), 14 deletions(-) diff --git a/libethereum/EthereumHost.cpp b/libethereum/EthereumHost.cpp index 33f95695b..4609fddb6 100644 --- a/libethereum/EthereumHost.cpp +++ b/libethereum/EthereumHost.cpp @@ -81,6 +81,7 @@ void EthereumHost::reset() m_hashMan.reset(m_chain.number() + 1); m_needSyncBlocks = true; m_needSyncHashes = true; + m_syncingNewHashes = false; m_syncingLatestHash = h256(); m_syncingTotalDifficulty = 0; m_latestBlockSent = h256(); @@ -88,6 +89,14 @@ void EthereumHost::reset() m_hashes.clear(); } +void EthereumHost::resetSyncTo(h256 const& _h) +{ + m_needSyncHashes = true; + m_needSyncBlocks = true; + m_syncingLatestHash = _h; + m_syncingNewHashes = false; +} + void EthereumHost::doWork() { bool netChange = ensureInitialised(); @@ -366,8 +375,13 @@ void EthereumHost::onPeerHashes(EthereumPeer* _peer, h256s const& _hashes, bool } if (_complete) { + clog(NetMessageSummary) << "Start new blocks download..."; m_needSyncBlocks = true; - continueSync(); + m_syncingNewHashes = true; + m_man.resetToChain(m_hashes); + m_hashes.clear(); + m_hashMan.reset(m_chain.number() + 1); + continueSync(_peer); } else if (syncByNumber && m_hashMan.isComplete()) { @@ -425,6 +439,7 @@ void EthereumHost::onPeerBlocks(EthereumPeer* _peer, RLP const& _r) unsigned unknown = 0; unsigned got = 0; unsigned repeated = 0; + h256 lastUnknown; for (unsigned i = 0; i < itemCount; ++i) { @@ -453,6 +468,7 @@ void EthereumHost::onPeerBlocks(EthereumPeer* _peer, RLP const& _r) break; case ImportResult::UnknownParent: + lastUnknown = h; unknown++; break; @@ -467,6 +483,13 @@ void EthereumHost::onPeerBlocks(EthereumPeer* _peer, RLP const& _r) } clog(NetMessageSummary) << dec << success << "imported OK," << unknown << "with unknown parents," << future << "with future timestamps," << got << " already known," << repeated << " repeats received."; + + if (m_syncingNewHashes && unknown > 0) + { + _peer->m_latestHash = lastUnknown; + resetSyncTo(lastUnknown); + } + continueSync(_peer); } @@ -486,7 +509,7 @@ void EthereumHost::onPeerNewHashes(EthereumPeer* _peer, h256s const& _hashes) void EthereumHost::onPeerNewBlock(EthereumPeer* _peer, RLP const& _r) { RecursiveGuard l(x_sync); - if (isSyncing_UNSAFE() || _peer->isConversing()) + if ((isSyncing_UNSAFE() || _peer->isConversing()) && !m_syncingNewHashes) { clog(NetMessageSummary) << "Ignoring new blocks since we're already downloading."; return; @@ -526,9 +549,7 @@ void EthereumHost::onPeerNewBlock(EthereumPeer* _peer, RLP const& _r) clog(NetMessageSummary) << "Received block with no known parent. Resyncing..."; _peer->m_latestHash = h; _peer->m_totalDifficulty = difficulty; - m_needSyncHashes = true; - m_needSyncBlocks = true; - m_syncingLatestHash = h; + resetSyncTo(h);; sync = true; } } @@ -646,7 +667,7 @@ void EthereumHost::continueSync(EthereumPeer* _peer) { _peer->requestHashes(m_syncingLatestHash); m_syncingV61 = false; - m_estimatedHashes = _peer->m_expectedHashes; + m_estimatedHashes = _peer->m_expectedHashes - (_peer->m_protocolVersion == protocolVersion() ? 0 : c_chainReorgSize); } else _peer->setIdle(); @@ -658,6 +679,7 @@ void EthereumHost::continueSync(EthereumPeer* _peer) { // Done our chain-get. m_needSyncBlocks = false; + m_syncingNewHashes = false; clog(NetNote) << "Chain download complete."; // 1/100th for each useful block hash. _peer->addRating(m_man.chainSize() / 100); //TODO: what about other peers? @@ -742,6 +764,6 @@ HashChainStatus EthereumHost::status() RecursiveGuard l(x_sync); if (m_syncingV61) return HashChainStatus { static_cast(m_hashMan.chainSize()), static_cast(m_hashMan.gotCount()), false }; - return HashChainStatus { m_estimatedHashes > 0 ? m_estimatedHashes - c_chainReorgSize : 0, static_cast(m_hashes.size()), m_estimatedHashes > 0 }; + return HashChainStatus { m_estimatedHashes > 0 ? m_estimatedHashes : 0, static_cast(m_hashes.size()), m_estimatedHashes > 0 }; } diff --git a/libethereum/EthereumHost.h b/libethereum/EthereumHost.h index 17684fea1..392e234f3 100644 --- a/libethereum/EthereumHost.h +++ b/libethereum/EthereumHost.h @@ -97,6 +97,7 @@ private: void foreachPeerPtr(std::function)> const& _f) const; void foreachPeer(std::function const& _f) const; bool isSyncing_UNSAFE() const; + void resetSyncTo(h256 const& _h); /// Sync with the BlockChain. It might contain one of our mined blocks, we might have new candidates from the network. void doWork(); @@ -151,6 +152,7 @@ private: bool m_needSyncBlocks = true; ///< Indicates if we still need to download some blocks h256 m_syncingLatestHash; ///< Latest block's hash, as of the current sync. u256 m_syncingTotalDifficulty; ///< Latest block's total difficulty, as of the current sync. + bool m_syncingNewHashes = false; ///< True if currently downloading hashes received with NewHashes h256s m_hashes; ///< List of hashes with unknown block numbers. Used for PV60 chain downloading and catching up to a particular unknown unsigned m_estimatedHashes = 0; ///< Number of estimated hashes for the last peer over PV60. Used for status reporting only. bool m_syncingV61 = false; ///< True if recent activity was over pv61+. Used for status reporting only. diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index f4cceebf2..628b59767 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -61,17 +61,22 @@ ReputationManager::ReputationManager() void ReputationManager::noteRude(Session const& _s, std::string const& _sub) { - m_nodes[make_pair(_s.id(), _s.info().clientVersion)].subs[_sub].isRude = true; + DEV_WRITE_GUARDED(x_nodes) + m_nodes[make_pair(_s.id(), _s.info().clientVersion)].subs[_sub].isRude = true; } bool ReputationManager::isRude(Session const& _s, std::string const& _sub) const { - auto nit = m_nodes.find(make_pair(_s.id(), _s.info().clientVersion)); - if (nit == m_nodes.end()) - return false; - auto sit = nit->second.subs.find(_sub); - bool ret = sit == nit->second.subs.end() ? false : sit->second.isRude; - return _sub.empty() ? ret : (ret || isRude(_s)); + DEV_READ_GUARDED(x_nodes) + { + auto nit = m_nodes.find(make_pair(_s.id(), _s.info().clientVersion)); + if (nit == m_nodes.end()) + return false; + auto sit = nit->second.subs.find(_sub); + bool ret = sit == nit->second.subs.end() ? false : sit->second.isRude; + return _sub.empty() ? ret : (ret || isRude(_s)); + } + return false; } Host::Host(std::string const& _clientVersion, NetworkPreferences const& _n, bytesConstRef _restoreNetwork): diff --git a/libp2p/Host.h b/libp2p/Host.h index 132dd379a..b32c495cb 100644 --- a/libp2p/Host.h +++ b/libp2p/Host.h @@ -99,6 +99,7 @@ public: private: std::unordered_map, Reputation> m_nodes; ///< Nodes that were impolite while syncing. We avoid syncing from these if possible. + SharedMutex mutable x_nodes; }; /**