diff --git a/Dispatcher.cpp b/Dispatcher.cpp index e080f45..32dcec2 100644 --- a/Dispatcher.cpp +++ b/Dispatcher.cpp @@ -73,30 +73,41 @@ static std::string toHex(const uint8_t * const s, const size_t len) { return r; } -static void printResult(cl_ulong4 seed, cl_ulong round, result r, cl_uchar score, const std::chrono::time_point & timeStart, const Mode & mode) { - // Time delta - const auto seconds = std::chrono::duration_cast(std::chrono::steady_clock::now() - timeStart).count(); - - // Format private key +static std::string formatPrivateKey(cl_ulong4 seed, cl_ulong round, uint foundId) { cl_ulong carry = 0; cl_ulong4 seedRes; seedRes.s[0] = seed.s[0] + round; carry = seedRes.s[0] < round; seedRes.s[1] = seed.s[1] + carry; carry = !seedRes.s[1]; seedRes.s[2] = seed.s[2] + carry; carry = !seedRes.s[2]; - seedRes.s[3] = seed.s[3] + carry + r.foundId; + seedRes.s[3] = seed.s[3] + carry + foundId; std::ostringstream ss; ss << std::hex << std::setfill('0'); ss << std::setw(16) << seedRes.s[3] << std::setw(16) << seedRes.s[2] << std::setw(16) << seedRes.s[1] << std::setw(16) << seedRes.s[0]; - const std::string strPrivate = ss.str(); + + return ss.str(); +} + +static void printResult(cl_ulong4 seed, cl_ulong round, result r, cl_uchar score, const std::chrono::time_point & timeStart, const Mode & mode) { + // Time delta + const auto seconds = std::chrono::duration_cast(std::chrono::steady_clock::now() - timeStart).count(); + + // Format private key + const std::string strPrivate = formatPrivateKey(seed, round, r.foundId); // Format public key const std::string strPublic = toHex(r.foundHash, 20); // Print const std::string strVT100ClearLine = "\33[2K\r"; - std::cout << strVT100ClearLine << " Time: " << std::setw(5) << seconds << "s Score: " << std::setw(2) << (int) score << " Private: 0x" << strPrivate << ' '; + std::cout << strVT100ClearLine << " Time: " << std::setw(5) << seconds << "s"; + + if (mode.name != "exact") { + std::cout << " Score: " << std::setw(2) << (int) score; + } + + std::cout << " Private: 0x" << strPrivate << ' '; std::cout << mode.transformName(); std::cout << ": 0x" << strPublic << std::endl; @@ -140,8 +151,9 @@ cl_command_queue Dispatcher::Device::createQueue(cl_context & clContext, cl_devi } cl_kernel Dispatcher::Device::createKernel(cl_program & clProgram, const std::string s) { - cl_kernel ret = clCreateKernel(clProgram, s.c_str(), NULL); - return ret == NULL ? throw std::runtime_error("failed to create kernel \"" + s + "\"") : ret; + cl_int errorCode; + cl_kernel ret = clCreateKernel(clProgram, s.c_str(), &errorCode); + return ret == NULL ? throw std::runtime_error("failed to create kernel \"" + s + "\"" + ", code: " + toString(errorCode)) : ret; } cl_ulong4 Dispatcher::Device::createSeed() { @@ -192,7 +204,8 @@ Dispatcher::Device::Device(Dispatcher & parent, cl_context & clContext, cl_progr m_round(0), m_speed(PROFANITY_SPEEDSAMPLES), m_sizeInitialized(0), - m_eventFinished(NULL) + m_eventFinished(NULL), + m_lastCursorIndex(1) { } @@ -235,6 +248,21 @@ void Dispatcher::run() { const auto timeInitialization = std::chrono::duration_cast(std::chrono::steady_clock::now() - timeStart).count(); std::cout << "Initialization time: " << timeInitialization << " seconds" << std::endl; + if (m_mode.name == "exact" || m_mode.name == "matching") { + auto mask = toHex(m_mode.data1, 20); // FF0... + auto pattern = toHex(m_mode.data2, 20); // AE53424... + + for (size_t i = 0; i < mask.size(); i++) { + if (mask[i] == '0') { + pattern[i] = '_'; + } + } + + std::cout << "Hex string mask: " << pattern << std::endl; + } + + std::cout << std::endl; + m_quit = false; m_countRunning = m_vDevices.size(); @@ -353,7 +381,7 @@ void Dispatcher::initContinue(Device & d) { // the commands are not required to begin execution until the queue is flushed. In standard usage, blocking enqueue calls serve this role by implicitly // flushing the queue. Since blocking calls are not permitted in callbacks, those callbacks that enqueue commands on a command queue should either call // clFlush on the queue before returning or arrange for clFlush to be called later on another thread. - clFlush(d.m_clQueue); + clFlush(d.m_clQueue); std::lock_guard lock(m_mutex); d.m_sizeInitialized += sizeRun; @@ -425,7 +453,7 @@ void Dispatcher::dispatch(Device & d) { // We're actually not allowed to call clFinish here because this function is ultimately asynchronously called by OpenCL. // However, this happens to work on my computer and it's not really intended for release, just something to aid me in // optimizations. - clFinish(d.m_clQueue); + clFinish(d.m_clQueue); std::cout << "Timing: profanity_inverse = " << getKernelExecutionTimeMicros(eventInverse) << "us, profanity_iterate = " << getKernelExecutionTimeMicros(eventIterate) << "us" << std::endl; #endif @@ -433,7 +461,55 @@ void Dispatcher::dispatch(Device & d) { OpenCLException::throwIfError("failed to set custom callback", res); } + +void Dispatcher::handleExactResult(Device & d) { + uint cursorLocation = d.m_memResult[0].found; + uint currentCursorIndex = (cursorLocation % PROFANITY_MAX_SCORE) + 1; + + // 3 cases: + + // d.m_lastCursorIndex = currentCursorIndex -> no new results + if (currentCursorIndex == d.m_lastCursorIndex) { + return; + } + + std::vector range; + + if (currentCursorIndex > d.m_lastCursorIndex) { + // d.m_lastCursorIndex > currentCursorIndex -> new results, read from last to current + for (size_t resultIndex = d.m_lastCursorIndex; resultIndex < currentCursorIndex; ++resultIndex) { + range.push_back(resultIndex); + } + } else { + // d.m_lastCursorIndex < currentCursorIndex -> buffer rollover: + + // read from last to PROFANITY_MAX_SCORE + for (size_t resultIndex = d.m_lastCursorIndex; resultIndex < PROFANITY_MAX_SCORE; ++resultIndex) { + range.push_back(resultIndex); + } + + // read from 0 to currentCursorIndex + for (size_t resultIndex = 0; resultIndex < currentCursorIndex; ++resultIndex) { + range.push_back(resultIndex); + } + } + + std::lock_guard lock(m_mutex); + + for (auto resultIndex : range) { + printResult(d.m_clSeed, d.m_round, d.m_memResult[resultIndex], 0, timeStart, m_mode); + } + + d.m_lastCursorIndex = currentCursorIndex; +} + void Dispatcher::handleResult(Device & d) { + if (m_mode.name == "exact") { + handleExactResult(d); + + return; + } + for (auto i = PROFANITY_MAX_SCORE; i > m_clScoreMax; --i) { result & r = d.m_memResult[i]; diff --git a/Dispatcher.hpp b/Dispatcher.hpp index 6992613..a72e715 100644 --- a/Dispatcher.hpp +++ b/Dispatcher.hpp @@ -77,6 +77,8 @@ class Dispatcher { // Initialization size_t m_sizeInitialized; cl_event m_eventFinished; + + size_t m_lastCursorIndex; }; public: @@ -96,6 +98,7 @@ class Dispatcher { void enqueueKernelDevice(Device & d, cl_kernel & clKernel, size_t worksizeGlobal, cl_event * pEvent); void handleResult(Device & d); + void handleExactResult(Device & d); void randomizeSeed(Device & d); void onEvent(cl_event event, cl_int status, Device & d); diff --git a/Mode.cpp b/Mode.cpp index 20757a6..9949fc1 100644 --- a/Mode.cpp +++ b/Mode.cpp @@ -37,6 +37,20 @@ static std::string::size_type hexValue(char c) { return ret; } +// +// Pattern: +// 1337________________________________C0DE +// 10000______________________________00001 +// +// | # | Chr | iHi | iLo | mHi | mLo | d1[i] | d2[i] | +// |-----------|------|------|------|------|-------|-------| +// | 0 | d d | 13 | 13 | 0xF0 | 0x0F | 0xFF | 0xDD | +// | 1 | 0 b | 0 | 11 | 0xF0 | 0x0F | 0xFF | 0x0B | +// | 2 | b _ | 11 | npos | 0xF0 | 0x00 | 0xF0 | 0x00 | +// | 3-9 | _ _ | npos | npos | 0x00 | 0x00 | 0x00 | 0x00 | +// | 10 | d d | 13 | 13 | 0xF0 | 0x0F | 0xFF | 0xDD | +// | 11 | 0 b | 0 | 11 | 0xF0 | 0x0F | 0xFF | 0x0B | + Mode Mode::matching(const std::string strHex) { Mode r; r.name = "matching"; @@ -46,7 +60,7 @@ Mode Mode::matching(const std::string strHex) { std::fill( r.data2, r.data2 + sizeof(r.data2), cl_uchar(0) ); auto index = 0; - + for( size_t i = 0; i < strHex.size(); i += 2 ) { const auto indexHi = hexValueNoException(strHex[i]); const auto indexLo = i + 1 < strHex.size() ? hexValueNoException(strHex[i+1]) : std::string::npos; @@ -66,6 +80,16 @@ Mode Mode::matching(const std::string strHex) { return r; } +Mode Mode::exact(const std::string strHex) { + Mode r = matching(strHex); + + r.name = "exact"; + r.kernel = "profanity_exact_match"; + + return r; +} + + Mode Mode::leading(const char charLeading) { Mode r; diff --git a/Mode.hpp b/Mode.hpp index ed6538a..508fecb 100644 --- a/Mode.hpp +++ b/Mode.hpp @@ -21,6 +21,7 @@ class Mode { public: static Mode matching(const std::string strHex); + static Mode exact(const std::string strHex); static Mode range(const cl_uchar min, const cl_uchar max); static Mode leading(const char charLeading); static Mode leadingRange(const cl_uchar min, const cl_uchar max); diff --git a/README.md b/README.md index 62c44b1..c923f11 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,8 @@ usage: ./profanity2 [OPTIONS] Modes with arguments: --leading Score on hashes leading with given hex character. - --matching Score on hashes matching given hex string. + --matching Score on hashes matching given hex string. + -e, --exact Score on all hashes exactly matching given mask. Advanced modes: --contract Instead of account address, score the contract @@ -88,8 +89,9 @@ usage: ./profanity2 [OPTIONS] Examples: ./profanity2 --leading f -z HEX_PUBLIC_KEY_128_CHARS_LONG - ./profanity2 --matching dead -z HEX_PUBLIC_KEY_128_CHARS_LONG - ./profanity2 --matching badXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXbad -z HEX_PUBLIC_KEY_128_CHARS_LONG + ./profanity2 --matching beef -z HEX_PUBLIC_KEY_128_CHARS_LONG + ./profanity2 --matching 1337________________________________C0DE -z HEX_PUBLIC_KEY_128_CHARS_LONG + ./profanity2 --exact 1337________________________________C0DE -z HEX_PUBLIC_KEY_128_CHARS_LONG ./profanity2 --leading-range -m 0 -M 1 -z HEX_PUBLIC_KEY_128_CHARS_LONG ./profanity2 --leading-range -m 10 -M 12 -z HEX_PUBLIC_KEY_128_CHARS_LONG ./profanity2 --range -m 0 -M 1 -z HEX_PUBLIC_KEY_128_CHARS_LONG diff --git a/help.hpp b/help.hpp index b963e23..5a75acd 100644 --- a/help.hpp +++ b/help.hpp @@ -21,7 +21,8 @@ usage: ./profanity2 [OPTIONS] Modes with arguments: --leading Score on hashes leading with given hex character. - --matching Score on hashes matching given hex string. + --matching Score on hashes matching given hex string. + -e, --exact Score on all hashes exactly matching given mask. Advanced modes: --contract Instead of account address, score the contract @@ -49,12 +50,14 @@ usage: ./profanity2 [OPTIONS] Examples: ./profanity2 --leading f -z HEX_PUBLIC_KEY_128_CHARS_LONG - ./profanity2 --matching dead -z HEX_PUBLIC_KEY_128_CHARS_LONG - ./profanity2 --matching badXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXbad -z HEX_PUBLIC_KEY_128_CHARS_LONG + ./profanity2 --matching beef -z HEX_PUBLIC_KEY_128_CHARS_LONG + ./profanity2 --matching 1337________________________________C0DE -z HEX_PUBLIC_KEY_128_CHARS_LONG + ./profanity2 --exact 1337________________________________C0DE -z HEX_PUBLIC_KEY_128_CHARS_LONG ./profanity2 --leading-range -m 0 -M 1 -z HEX_PUBLIC_KEY_128_CHARS_LONG ./profanity2 --leading-range -m 10 -M 12 -z HEX_PUBLIC_KEY_128_CHARS_LONG ./profanity2 --range -m 0 -M 1 -z HEX_PUBLIC_KEY_128_CHARS_LONG ./profanity2 --contract --leading 0 -z HEX_PUBLIC_KEY_128_CHARS_LONG + ./profanity2 --contract --zero-bytes -z HEX_PUBLIC_KEY_128_CHARS_LONG About: profanity2 is a vanity address generator for Ethereum that utilizes diff --git a/profanity.cl b/profanity.cl index 75abd70..0d410ce 100644 --- a/profanity.cl +++ b/profanity.cl @@ -5,7 +5,7 @@ * * Terminology * =========== - * + * * * Cutting corners * =============== @@ -16,7 +16,7 @@ * doing it right is too severe. In the future I'll introduce a periodic check * after N amount of cycles that verifies the integrity of all the points to * make sure that even very unlikely event are at some point rectified. - * + * * Currently, if any of the points in the kernels experiences the unlikely event * of an error then that point is forever garbage and your runtime-performance * will in practice be (i*I-N) / (i*I). i and I here refers to the values given @@ -331,7 +331,7 @@ void mp_mod_mul(mp_number * const r, const mp_number * const X, const mp_number *r = Z; } -// Modular inversion of a number. +// Modular inversion of a number. void mp_mod_inverse(mp_number * const r) { mp_number A = { { 1 } }; mp_number C = { { 0 } }; @@ -474,7 +474,7 @@ __kernel void profanity_init(__global const point * const precomp, __global mp_n mp_mod_sub_gx(&tmp1, &p.x); mp_mod_inverse(&tmp1); - mp_mod_sub_gy(&tmp2, &p.y); + mp_mod_sub_gy(&tmp2, &p.y); mp_mod_mul(&tmp1, &tmp1, &tmp2); // Jump to next point (precomp[0] is the generator point G) @@ -494,7 +494,7 @@ __kernel void profanity_init(__global const point * const precomp, __global mp_n // This kernel calculates several modular inversions at once with just one inverse. // It's an implementation of Algorithm 2.11 from Modern Computer Arithmetic: -// https://members.loria.fr/PZimmermann/mca/pub226.html +// https://members.loria.fr/PZimmermann/mca/pub226.html // // My RX 480 is very sensitive to changes in the second loop and sometimes I have // to make seemingly non-functional changes to the code to make the compiler @@ -563,7 +563,7 @@ __kernel void profanity_inverse(__global const mp_number * const pDeltaX, __glob // Then we have: // d = x - G_x <=> x = d + G_x // x' = λ² - G_x - x <=> x_r = λ² - G_x - d - G_x = λ² - 2G_x - d -// +// // d' = x' - G_x = λ² - 2G_x - d - G_x = λ² - 3G_x - d // // So we see that the new delta d' can be calculated with the same @@ -585,9 +585,9 @@ __kernel void profanity_inverse(__global const mp_number * const pDeltaX, __glob // But we aren't done yet! Let's expand the expression for the next // lambda, λ'. We have: // λ' = (y' - G_y) / d' -// = (-λ * d' - G_y - G_y) / d' -// = (-λ * d' - 2*G_y) / d' -// = -λ - 2*G_y / d' +// = (-λ * d' - G_y - G_y) / d' +// = (-λ * d' - 2*G_y) / d' +// = -λ - 2*G_y / d' // // So the next lambda value can be calculated from the old one. This in // and of itself is not so interesting but the fact that the term -2 * G_y @@ -602,7 +602,7 @@ __kernel void profanity_inverse(__global const mp_number * const pDeltaX, __glob // but it's still a net gain. To additionally decrease memory access // overhead I never any longer store the Y coordinate. Instead I // calculate it at the end directly from the lambda and deltaX. -// +// // In addition to this some algebraic re-ordering has been done to move // constants into the same argument to a new function mp_mod_sub_const // in hopes that using constant storage instead of private storage @@ -693,7 +693,7 @@ void profanity_result_update(const size_t id, __global const uchar * const hash, __kernel void profanity_transform_contract(__global mp_number * const pInverse) { const size_t id = get_global_id(0); - __global const uchar * const hash = pInverse[id].d; + __global const uchar * const hash = (__global const uchar * const)pInverse[id].d; ethhash h; for (int i = 0; i < 50; ++i) { @@ -719,15 +719,45 @@ __kernel void profanity_transform_contract(__global mp_number * const pInverse) __kernel void profanity_score_benchmark(__global mp_number * const pInverse, __global result * const pResult, __constant const uchar * const data1, __constant const uchar * const data2, const uchar scoreMax) { const size_t id = get_global_id(0); - __global const uchar * const hash = pInverse[id].d; + __global const uchar * const hash = (__global const uchar * const)pInverse[id].d; int score = 0; profanity_result_update(id, hash, pResult, score, scoreMax); } +// Returns all exact matches of the mask back to host +__kernel void profanity_exact_match(__global mp_number * const pInverse, __global result * const pResult, __constant const uchar * const data1, __constant const uchar * const data2, const uchar scoreMax) { + const size_t id = get_global_id(0); + __global const uchar * const hash = (__global const uchar * const)pInverse[id].d; + + uint match = 1; + + // Check if the hash matches the mask exactly + for (int i = 0; i < 20; ++i) { + if (data1[i] > 0 && (hash[i] & data1[i]) != data2[i]) { + match = 0; + break; + } + } + + if (match > 0) { + // Using pResult as circular buffer, where [0] is write cursor position and + // PROFANITY_MAX_SCORE is the buffer size. + uint newIndex = atomic_inc(&pResult[0].found); + uint slot = (newIndex % PROFANITY_MAX_SCORE) + 1; // +1 because slot 0 is the write cursor + + pResult[slot].foundId = id; + + // Copy the hash + for (int i = 0; i < 20; ++i) { + pResult[slot].foundHash[i] = hash[i]; + } + } +} + __kernel void profanity_score_matching(__global mp_number * const pInverse, __global result * const pResult, __constant const uchar * const data1, __constant const uchar * const data2, const uchar scoreMax) { const size_t id = get_global_id(0); - __global const uchar * const hash = pInverse[id].d; + __global const uchar * const hash = (__global const uchar * const)pInverse[id].d; int score = 0; for (int i = 0; i < 20; ++i) { @@ -741,7 +771,7 @@ __kernel void profanity_score_matching(__global mp_number * const pInverse, __gl __kernel void profanity_score_leading(__global mp_number * const pInverse, __global result * const pResult, __constant const uchar * const data1, __constant const uchar * const data2, const uchar scoreMax) { const size_t id = get_global_id(0); - __global const uchar * const hash = pInverse[id].d; + __global const uchar * const hash = (__global const uchar * const)pInverse[id].d; int score = 0; for (int i = 0; i < 20; ++i) { @@ -765,7 +795,7 @@ __kernel void profanity_score_leading(__global mp_number * const pInverse, __glo __kernel void profanity_score_range(__global mp_number * const pInverse, __global result * const pResult, __constant const uchar * const data1, __constant const uchar * const data2, const uchar scoreMax) { const size_t id = get_global_id(0); - __global const uchar * const hash = pInverse[id].d; + __global const uchar * const hash = (__global const uchar * const)pInverse[id].d; int score = 0; for (int i = 0; i < 20; ++i) { @@ -786,7 +816,7 @@ __kernel void profanity_score_range(__global mp_number * const pInverse, __globa __kernel void profanity_score_zerobytes(__global mp_number * const pInverse, __global result * const pResult, __constant const uchar * const data1, __constant const uchar * const data2, const uchar scoreMax) { const size_t id = get_global_id(0); - __global const uchar * const hash = pInverse[id].d; + __global const uchar * const hash = (__global const uchar * const)pInverse[id].d; int score = 0; for (int i = 0; i < 20; ++i) { @@ -800,7 +830,7 @@ __kernel void profanity_score_zerobytes(__global mp_number * const pInverse, __g __kernel void profanity_score_leadingrange(__global mp_number * const pInverse, __global result * const pResult, __constant const uchar * const data1, __constant const uchar * const data2, const uchar scoreMax) { const size_t id = get_global_id(0); - __global const uchar * const hash = pInverse[id].d; + __global const uchar * const hash = (__global const uchar * const)pInverse[id].d; int score = 0; for (int i = 0; i < 20; ++i) { @@ -827,7 +857,7 @@ __kernel void profanity_score_leadingrange(__global mp_number * const pInverse, __kernel void profanity_score_mirror(__global mp_number * const pInverse, __global result * const pResult, __constant const uchar * const data1, __constant const uchar * const data2, const uchar scoreMax) { const size_t id = get_global_id(0); - __global const uchar * const hash = pInverse[id].d; + __global const uchar * const hash = (__global const uchar * const)pInverse[id].d; int score = 0; for (int i = 0; i < 10; ++i) { @@ -855,7 +885,7 @@ __kernel void profanity_score_mirror(__global mp_number * const pInverse, __glob __kernel void profanity_score_doubles(__global mp_number * const pInverse, __global result * const pResult, __constant const uchar * const data1, __constant const uchar * const data2, const uchar scoreMax) { const size_t id = get_global_id(0); - __global const uchar * const hash = pInverse[id].d; + __global const uchar * const hash = (__global const uchar * const)pInverse[id].d; int score = 0; for (int i = 0; i < 20; ++i) { diff --git a/profanity.cpp b/profanity.cpp index a5b0e1d..7e1888e 100644 --- a/profanity.cpp +++ b/profanity.cpp @@ -156,6 +156,7 @@ int main(int argc, char * * argv) { bool bModeNumbers = false; std::string strModeLeading; std::string strModeMatching; + std::string strModeExact; std::string strPublicKey; bool bModeLeadingRange = false; bool bModeRange = false; @@ -193,6 +194,7 @@ int main(int argc, char * * argv) { argp.addSwitch('c', "contract", bMineContract); argp.addSwitch('z', "publicKey", strPublicKey); argp.addSwitch('b', "zero-bytes", bModeZeroBytes); + argp.addSwitch('e', "exact", strModeExact); if (!argp.parse()) { std::cout << "error: bad arguments, try again :<" << std::endl; @@ -217,6 +219,8 @@ int main(int argc, char * * argv) { mode = Mode::leading(strModeLeading.front()); } else if (!strModeMatching.empty()) { mode = Mode::matching(strModeMatching); + } else if (!strModeExact.empty()) { + mode = Mode::exact(strModeExact); } else if (bModeLeadingRange) { mode = Mode::leadingRange(rangeMin, rangeMax); } else if (bModeRange) { @@ -231,7 +235,7 @@ int main(int argc, char * * argv) { std::cout << g_strHelp << std::endl; return 0; } - + if (strPublicKey.length() == 0) { std::cout << "error: this tool requires your public key to derive it's private key security" << std::endl; return 1; @@ -242,6 +246,8 @@ int main(int argc, char * * argv) { return 1; } + std::cout << "Public key: " << strPublicKey << std::endl; + std::cout << "Mode: " << mode.name << std::endl; if (bMineContract) { @@ -249,7 +255,9 @@ int main(int argc, char * * argv) { } else { mode.target = ADDRESS; } - std::cout << "Target: " << mode.transformName() << std:: endl; + + std::cout << "Target: " << mode.transformName() << std::endl; + std::cout << std::endl; std::vector vFoundDevices = getAllDevices(); std::vector vDevices; @@ -334,19 +342,22 @@ int main(int argc, char * * argv) { // Build the program std::cout << " Building program..." << std::flush; const std::string strBuildOptions = "-D PROFANITY_INVERSE_SIZE=" + toString(inverseSize) + " -D PROFANITY_MAX_SCORE=" + toString(PROFANITY_MAX_SCORE); - if (printResult(clBuildProgram(clProgram, vDevices.size(), vDevices.data(), strBuildOptions.c_str(), NULL, NULL))) { + auto res = printResult(clBuildProgram(clProgram, vDevices.size(), vDevices.data(), strBuildOptions.c_str(), NULL, NULL)); + #ifdef PROFANITY_DEBUG - std::cout << std::endl; - std::cout << "build log:" << std::endl; + std::cout << std::endl; + std::cout << "build log:" << std::endl; - size_t sizeLog; - clGetProgramBuildInfo(clProgram, vDevices[0], CL_PROGRAM_BUILD_LOG, 0, NULL, &sizeLog); - char * const szLog = new char[sizeLog]; - clGetProgramBuildInfo(clProgram, vDevices[0], CL_PROGRAM_BUILD_LOG, sizeLog, szLog, NULL); + size_t sizeLog; + clGetProgramBuildInfo(clProgram, vDevices[0], CL_PROGRAM_BUILD_LOG, 0, NULL, &sizeLog); + char * const szLog = new char[sizeLog]; + clGetProgramBuildInfo(clProgram, vDevices[0], CL_PROGRAM_BUILD_LOG, sizeLog, szLog, NULL); - std::cout << szLog << std::endl; - delete[] szLog; + std::cout << szLog << std::endl; + delete[] szLog; #endif + + if (res) { return 1; } @@ -379,4 +390,3 @@ int main(int argc, char * * argv) { return 1; } -