├── ArgParser.hpp ├── CLMemory.hpp ├── Dispatcher.cpp ├── Dispatcher.hpp ├── Makefile ├── ModeFactory.cpp ├── ModeFactory.hpp ├── README.md ├── Speed.cpp ├── Speed.hpp ├── eradicate2.cl ├── eradicate2.cpp ├── help.hpp ├── hexadecimal.cpp ├── hexadecimal.hpp ├── keccak.cl ├── lexical_cast.hpp ├── sha3.cpp ├── sha3.hpp └── types.hpp /ArgParser.hpp: -------------------------------------------------------------------------------- 1 | #ifndef HPP_ARGPARSER 2 | #define HPP_ARGPARSER 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "lexical_cast.hpp" 9 | 10 | class ArgParser { 11 | private: 12 | class IArgument { 13 | public: 14 | virtual ~IArgument() {} 15 | virtual void parse(const std::string & s) = 0; 16 | }; 17 | 18 | template 19 | class Argument : public IArgument { 20 | public: 21 | Argument(T & t) : m_t(t) {} 22 | ~Argument() {} 23 | 24 | void parse(const std::string & s) { 25 | m_t = lexical_cast::read(s); 26 | } 27 | 28 | private: 29 | T & m_t; 30 | }; 31 | 32 | template 33 | class MultiArgument : public IArgument { 34 | public: 35 | MultiArgument(std::vector & t) : m_t(t) {} 36 | MultiArgument() {} 37 | 38 | void parse(const std::string & s) { 39 | m_t.push_back(lexical_cast::read(s)); 40 | } 41 | 42 | private: 43 | std::vector & m_t; 44 | }; 45 | 46 | public: 47 | ArgParser(int argc, char * * argv) { 48 | for (int i = 1; i < argc; ++i) { 49 | m_args.push_back(argv[i]); 50 | } 51 | } 52 | 53 | ~ArgParser() { 54 | for (auto & i : m_mapArgs) { 55 | delete i.second.second; // :) 56 | } 57 | } 58 | 59 | template 60 | void addSwitch(const char switchShort, const std::string switchLong, T & t) { 61 | const std::string strShort = std::string("-") + switchShort; 62 | const std::string strLong = std::string("--") + switchLong; 63 | 64 | // :) 65 | IArgument * const pArgShort = new Argument(t); 66 | IArgument * const pArgLong = new Argument(t); 67 | m_mapArgs[strShort] = std::pair(std::is_same::value, pArgShort); 68 | m_mapArgs[strLong] = std::pair(std::is_same::value, pArgLong); 69 | } 70 | 71 | template 72 | void addMultiSwitch(const char switchShort, const std::string switchLong, std::vector & t) { 73 | const std::string strShort = std::string("-") + switchShort; 74 | const std::string strLong = std::string("--") + switchLong; 75 | 76 | // :) 77 | IArgument * const pArgShort = new MultiArgument(t); 78 | IArgument * const pArgLong = new MultiArgument(t); 79 | m_mapArgs[strShort] = std::pair(false, pArgShort); 80 | m_mapArgs[strLong] = std::pair(false, pArgLong); 81 | } 82 | 83 | bool parse() const { 84 | try { 85 | std::vector::size_type i = 0; 86 | 87 | while (i < m_args.size()) { 88 | auto p = m_mapArgs.at(m_args[i]); 89 | const std::string s = p.first ? "1" : m_args.at(i + 1); 90 | 91 | p.second->parse(s); 92 | i += (p.first ? 1 : 2); 93 | } 94 | } 95 | catch (std::out_of_range & e) { 96 | return false; 97 | } 98 | 99 | return true; 100 | } 101 | 102 | private: 103 | std::vector m_args; 104 | std::map> m_mapArgs; 105 | }; 106 | 107 | #endif /* HPP_ARGPARSER */ -------------------------------------------------------------------------------- /CLMemory.hpp: -------------------------------------------------------------------------------- 1 | #ifndef HPP_CLMEMORY 2 | #define HPP_CLMEMORY 3 | 4 | #include "lexical_cast.hpp" 5 | 6 | template class CLMemory { 7 | public: 8 | CLMemory(cl_context & clContext, cl_command_queue & clQueue, const cl_mem_flags flags, const size_t size, T * const pData) 9 | : m_clQueue(clQueue), m_bFree(false), m_size(size), m_pData(pData) { 10 | m_clMem = clCreateBuffer(clContext, flags, m_size, NULL, NULL); 11 | } 12 | 13 | CLMemory(cl_context & clContext, cl_command_queue & clQueue, const cl_mem_flags flags, const size_t count, const bool noAllocation = false) 14 | : m_clQueue(clQueue), m_bFree(true), m_size(sizeof(T) * count), m_pData(noAllocation ? NULL : new T[count]) { 15 | m_clMem = clCreateBuffer(clContext, flags, m_size, NULL, NULL); 16 | } 17 | 18 | ~CLMemory() { 19 | if(m_bFree) { 20 | delete [] m_pData; 21 | } 22 | } 23 | 24 | static void setKernelArg(cl_kernel & clKernel, const cl_uint arg_index, const T & t) { 25 | const cl_int ret = clSetKernelArg(clKernel, arg_index, sizeof(T), (void *) &t); 26 | if (ret != CL_SUCCESS) { 27 | throw std::runtime_error("clSetKernelArg failed - " + lexical_cast::write(arg_index) + " - " + lexical_cast::write(ret)); 28 | } 29 | } 30 | 31 | void setKernelArg(cl_kernel & clKernel, const cl_uint arg_index) const { 32 | const cl_int ret = clSetKernelArg(clKernel, arg_index, sizeof(cl_mem), (void *) &m_clMem ); 33 | if( ret != CL_SUCCESS ) { 34 | throw std::runtime_error("clSetKernelArg failed - " + lexical_cast::write(arg_index) + " - " + lexical_cast::write(ret)); 35 | } 36 | } 37 | 38 | void read(const bool bBlock, cl_event * pEvent = NULL) const { 39 | const cl_bool block = bBlock ? CL_TRUE : CL_FALSE; 40 | auto res = clEnqueueReadBuffer(m_clQueue, m_clMem, block, 0, m_size, m_pData, 0, NULL, pEvent); 41 | if(res != CL_SUCCESS) { 42 | throw std::runtime_error("clEnqueueReadBuffer failed - " + lexical_cast::write(res)); 43 | } 44 | } 45 | 46 | void write(const bool bBlock) const { 47 | const cl_bool block = bBlock ? CL_TRUE : CL_FALSE; 48 | auto res = clEnqueueWriteBuffer(m_clQueue, m_clMem, block, 0, m_size, m_pData, 0, NULL, NULL); 49 | if( res != CL_SUCCESS ) { 50 | throw std::runtime_error("clEnqueueWriteBuffer failed - " + lexical_cast::write(res)); 51 | } 52 | } 53 | 54 | T * const & data() const { 55 | return m_pData; 56 | } 57 | 58 | T & operator[] (int x) const { 59 | return m_pData[x]; 60 | } 61 | 62 | T * operator->() const { 63 | return m_pData; 64 | } 65 | 66 | T & operator*() const { 67 | return *m_pData; 68 | } 69 | 70 | const size_t & size() const { 71 | return m_size; 72 | } 73 | 74 | private: 75 | const cl_command_queue m_clQueue; 76 | const bool m_bFree; 77 | const size_t m_size; 78 | 79 | T * const m_pData; 80 | cl_mem m_clMem; 81 | }; 82 | 83 | #endif /* HPP_CLMEMORY */ -------------------------------------------------------------------------------- /Dispatcher.cpp: -------------------------------------------------------------------------------- 1 | #include "Dispatcher.hpp" 2 | 3 | // Includes 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "hexadecimal.hpp" 13 | 14 | static void printResult(const result r, const cl_uchar score, const std::chrono::time_point & timeStart) { 15 | // Time delta 16 | const auto seconds = std::chrono::duration_cast(std::chrono::steady_clock::now() - timeStart).count(); 17 | 18 | // Format address 19 | const std::string strSalt = toHex(r.salt, 32); 20 | const std::string strPublic = toHex(r.hash, 20); 21 | 22 | // Print 23 | const std::string strVT100ClearLine = "\33[2K\r"; 24 | std::cout << strVT100ClearLine << " Time: " << std::setw(5) << seconds << "s Score: " << std::setw(2) << (int) score << " Salt: 0x" << strSalt << " Address: 0x" << strPublic << std::endl; 25 | } 26 | 27 | Dispatcher::OpenCLException::OpenCLException(const std::string s, const cl_int res) : 28 | std::runtime_error( s + " (res = " + lexical_cast::write(res) + ")"), 29 | m_res(res) 30 | { 31 | 32 | } 33 | 34 | void Dispatcher::OpenCLException::OpenCLException::throwIfError(const std::string s, const cl_int res) { 35 | if (res != CL_SUCCESS) { 36 | throw OpenCLException(s, res); 37 | } 38 | } 39 | 40 | cl_command_queue Dispatcher::Device::createQueue(cl_context & clContext, cl_device_id & clDeviceId) { 41 | // nVidia CUDA Toolkit 10.1 only supports OpenCL 1.2 so we revert back to older functions for compatability 42 | #ifdef ERADICATE2_DEBUG 43 | cl_command_queue_properties p = CL_QUEUE_PROFILING_ENABLE; 44 | #else 45 | cl_command_queue_properties p = 0; 46 | #endif 47 | 48 | #ifdef CL_VERSION_2_0 49 | const cl_command_queue ret = clCreateCommandQueueWithProperties(clContext, clDeviceId, &p, NULL); 50 | #else 51 | const cl_command_queue ret = clCreateCommandQueue(clContext, clDeviceId, p, NULL); 52 | #endif 53 | return ret == NULL ? throw std::runtime_error("failed to create command queue") : ret; 54 | } 55 | 56 | cl_kernel Dispatcher::Device::createKernel(cl_program & clProgram, const std::string s) { 57 | cl_kernel ret = clCreateKernel(clProgram, s.c_str(), NULL); 58 | return ret == NULL ? throw std::runtime_error("failed to create kernel \"" + s + "\"") : ret; 59 | } 60 | 61 | Dispatcher::Device::Device(Dispatcher & parent, cl_context & clContext, cl_program & clProgram, cl_device_id clDeviceId, const size_t worksizeLocal, const size_t size, const size_t index) : 62 | m_parent(parent), 63 | m_index(index), 64 | m_clDeviceId(clDeviceId), 65 | m_worksizeLocal(worksizeLocal), 66 | m_clScoreMax(0), 67 | m_clQueue(createQueue(clContext, clDeviceId) ), 68 | m_kernelIterate(createKernel(clProgram, "eradicate2_iterate")), 69 | m_memResult(clContext, m_clQueue, CL_MEM_READ_WRITE, ERADICATE2_MAX_SCORE + 1), 70 | m_memMode(clContext, m_clQueue, CL_MEM_READ_ONLY | CL_MEM_HOST_WRITE_ONLY, 1), 71 | m_round(0) 72 | { 73 | 74 | } 75 | 76 | Dispatcher::Device::~Device() { 77 | 78 | } 79 | 80 | Dispatcher::Dispatcher(cl_context & clContext, cl_program & clProgram, const size_t worksizeMax, const size_t size) 81 | : m_clContext(clContext), m_clProgram(clProgram), m_worksizeMax(worksizeMax), m_size(size), m_clScoreMax(0), m_eventFinished(NULL), m_countPrint(0) { 82 | 83 | } 84 | 85 | Dispatcher::~Dispatcher() { 86 | 87 | } 88 | 89 | void Dispatcher::addDevice(cl_device_id clDeviceId, const size_t worksizeLocal, const size_t index) { 90 | Device * pDevice = new Device(*this, m_clContext, m_clProgram, clDeviceId, worksizeLocal, m_size, index); 91 | m_vDevices.push_back(pDevice); 92 | } 93 | 94 | void Dispatcher::run(const mode & mode) { 95 | m_eventFinished = clCreateUserEvent(m_clContext, NULL); 96 | timeStart = std::chrono::steady_clock::now(); 97 | 98 | for (auto it = m_vDevices.begin(); it != m_vDevices.end(); ++it) { 99 | Device & d = **it; 100 | d.m_round = 0; 101 | 102 | for (size_t i = 0; i < ERADICATE2_MAX_SCORE + 1; ++i) { 103 | d.m_memResult[i].found = 0; 104 | } 105 | 106 | // Copy data 107 | *d.m_memMode = mode; 108 | d.m_memMode.write(true); 109 | d.m_memResult.write(true); 110 | 111 | // Kernel arguments - eradicate2_iterate 112 | d.m_memResult.setKernelArg(d.m_kernelIterate, 0); 113 | d.m_memMode.setKernelArg(d.m_kernelIterate, 1); 114 | CLMemory::setKernelArg(d.m_kernelIterate, 2, d.m_clScoreMax); // Updated in handleResult() 115 | CLMemory::setKernelArg(d.m_kernelIterate, 3, d.m_index); 116 | // Round information updated in deviceDispatch() 117 | } 118 | 119 | m_quit = false; 120 | m_countRunning = m_vDevices.size(); 121 | 122 | std::cout << "Running..." << std::endl; 123 | std::cout << std::endl; 124 | 125 | // Start asynchronous dispatch loop on all devices 126 | for (auto it = m_vDevices.begin(); it != m_vDevices.end(); ++it) { 127 | deviceDispatch(*(*it)); 128 | } 129 | 130 | // Wait for finish event 131 | clWaitForEvents(1, &m_eventFinished); 132 | clReleaseEvent(m_eventFinished); 133 | m_eventFinished = NULL; 134 | } 135 | 136 | void Dispatcher::enqueueKernel(cl_command_queue & clQueue, cl_kernel & clKernel, size_t worksizeGlobal, const size_t worksizeLocal, cl_event * pEvent = NULL) { 137 | const size_t worksizeMax = m_worksizeMax; 138 | size_t worksizeOffset = 0; 139 | while (worksizeGlobal) { 140 | const size_t worksizeRun = std::min(worksizeGlobal, worksizeMax); 141 | const size_t * const pWorksizeLocal = (worksizeLocal == 0 ? NULL : &worksizeLocal); 142 | const auto res = clEnqueueNDRangeKernel(clQueue, clKernel, 1, &worksizeOffset, &worksizeRun, pWorksizeLocal, 0, NULL, pEvent); 143 | OpenCLException::throwIfError("kernel queueing failed", res); 144 | 145 | worksizeGlobal -= worksizeRun; 146 | worksizeOffset += worksizeRun; 147 | } 148 | } 149 | 150 | void Dispatcher::enqueueKernelDevice(Device & d, cl_kernel & clKernel, size_t worksizeGlobal, cl_event * pEvent = NULL) { 151 | try { 152 | enqueueKernel(d.m_clQueue, clKernel, worksizeGlobal, d.m_worksizeLocal, pEvent); 153 | } catch ( OpenCLException & e ) { 154 | // If local work size is invalid, abandon it and let implementation decide 155 | if ((e.m_res == CL_INVALID_WORK_GROUP_SIZE || e.m_res == CL_INVALID_WORK_ITEM_SIZE) && d.m_worksizeLocal != 0) { 156 | std::cout << std::endl << "warning: local work size abandoned on GPU" << d.m_index << std::endl; 157 | d.m_worksizeLocal = 0; 158 | enqueueKernel(d.m_clQueue, clKernel, worksizeGlobal, d.m_worksizeLocal, pEvent); 159 | } 160 | else { 161 | throw; 162 | } 163 | } 164 | } 165 | 166 | void Dispatcher::deviceDispatch(Device & d) { 167 | // Check result 168 | for (auto i = ERADICATE2_MAX_SCORE; i > m_clScoreMax; --i) { 169 | result & r = d.m_memResult[i]; 170 | 171 | if (r.found > 0 && i >= d.m_clScoreMax) { 172 | d.m_clScoreMax = i; 173 | CLMemory::setKernelArg(d.m_kernelIterate, 2, d.m_clScoreMax); 174 | 175 | std::lock_guard lock(m_mutex); 176 | if (i >= m_clScoreMax) { 177 | m_clScoreMax = i; 178 | 179 | // TODO: Add quit condition 180 | 181 | printResult(r, i, timeStart); 182 | } 183 | 184 | break; 185 | } 186 | } 187 | 188 | d.m_parent.m_speed.update(d.m_parent.m_size, d.m_index); 189 | 190 | if (m_quit) { 191 | std::lock_guard lock(m_mutex); 192 | if (--m_countRunning == 0) { 193 | clSetUserEventStatus(m_eventFinished, CL_COMPLETE); 194 | } 195 | } else { 196 | cl_event event; 197 | d.m_memResult.read(false, &event); 198 | 199 | CLMemory::setKernelArg(d.m_kernelIterate, 4, ++d.m_round); // Round information updated in deviceDispatch() 200 | enqueueKernelDevice(d, d.m_kernelIterate, m_size); 201 | clFlush(d.m_clQueue); 202 | 203 | const auto res = clSetEventCallback(event, CL_COMPLETE, staticCallback, &d); 204 | OpenCLException::throwIfError("failed to set custom callback", res); 205 | } 206 | } 207 | 208 | void CL_CALLBACK Dispatcher::staticCallback(cl_event event, cl_int event_command_exec_status, void * user_data) { 209 | if (event_command_exec_status != CL_COMPLETE) { 210 | throw std::runtime_error("Dispatcher::onEvent - Got bad status" + lexical_cast::write(event_command_exec_status)); 211 | } 212 | 213 | Device * const pDevice = static_cast(user_data); 214 | pDevice->m_parent.deviceDispatch(*pDevice); 215 | clReleaseEvent(event); 216 | } 217 | -------------------------------------------------------------------------------- /Dispatcher.hpp: -------------------------------------------------------------------------------- 1 | #ifndef HPP_DISPATCHER 2 | #define HPP_DISPATCHER 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #if defined(__APPLE__) || defined(__MACOSX) 11 | #include 12 | #define clCreateCommandQueueWithProperties clCreateCommandQueue 13 | #else 14 | #include 15 | #endif 16 | 17 | #include "CLMemory.hpp" 18 | #include "Speed.hpp" 19 | #include "types.hpp" 20 | 21 | #define ERADICATE2_SPEEDSAMPLES 20 22 | #define ERADICATE2_MAX_SCORE 40 23 | 24 | class Dispatcher { 25 | private: 26 | class OpenCLException : public std::runtime_error { 27 | public: 28 | OpenCLException(const std::string s, const cl_int res); 29 | 30 | static void throwIfError(const std::string s, const cl_int res); 31 | 32 | const cl_int m_res; 33 | }; 34 | 35 | struct Device { 36 | static cl_command_queue createQueue(cl_context & clContext, cl_device_id & clDeviceId); 37 | static cl_kernel createKernel(cl_program & clProgram, const std::string s); 38 | 39 | Device(Dispatcher & parent, cl_context & clContext, cl_program & clProgram, cl_device_id clDeviceId, const size_t worksizeLocal, const size_t size, const size_t index); 40 | ~Device(); 41 | 42 | Dispatcher & m_parent; 43 | const size_t m_index; 44 | 45 | cl_device_id m_clDeviceId; 46 | size_t m_worksizeLocal; 47 | cl_uchar m_clScoreMax; 48 | cl_command_queue m_clQueue; 49 | 50 | cl_kernel m_kernelIterate; 51 | 52 | CLMemory m_memResult; 53 | CLMemory m_memMode; 54 | 55 | cl_uint m_round; 56 | }; 57 | 58 | public: 59 | Dispatcher(cl_context & clContext, cl_program & clProgram, const size_t worksizeMax, const size_t size); 60 | ~Dispatcher(); 61 | 62 | void addDevice(cl_device_id clDeviceId, const size_t worksizeLocal, const size_t index); 63 | void run(const mode & mode); 64 | 65 | private: 66 | void deviceDispatch(Device & d); 67 | 68 | void enqueueKernel(cl_command_queue & clQueue, cl_kernel & clKernel, size_t worksizeGlobal, const size_t worksizeLocal, cl_event * pEvent); 69 | void enqueueKernelDevice(Device & d, cl_kernel & clKernel, size_t worksizeGlobal, cl_event * pEvent); 70 | 71 | void printSpeed(); 72 | 73 | private: 74 | static void CL_CALLBACK staticCallback(cl_event event, cl_int event_command_exec_status, void * user_data); 75 | 76 | static std::string formatSpeed(double s); 77 | 78 | private: /* Instance variables */ 79 | cl_context & m_clContext; 80 | cl_program & m_clProgram; 81 | const size_t m_worksizeMax; 82 | const size_t m_size; 83 | cl_uchar m_clScoreMax; 84 | std::vector m_vDevices; 85 | 86 | cl_event m_eventFinished; 87 | 88 | // Run information 89 | std::mutex m_mutex; 90 | std::chrono::time_point timeStart; 91 | Speed m_speed; 92 | unsigned int m_countPrint; 93 | unsigned int m_countRunning; 94 | bool m_quit; 95 | }; 96 | 97 | #endif /* HPP_DISPATCHER */ 98 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC=g++ 2 | CDEFINES= 3 | SOURCES=Dispatcher.cpp eradicate2.cpp hexadecimal.cpp ModeFactory.cpp Speed.cpp sha3.cpp 4 | OBJECTS=$(SOURCES:.cpp=.o) 5 | EXECUTABLE=ERADICATE2.x64 6 | 7 | UNAME_S := $(shell uname -s) 8 | ifeq ($(UNAME_S),Darwin) 9 | LDFLAGS=-framework OpenCL 10 | CFLAGS=-c -std=c++11 -Wall -mmmx -O2 11 | else 12 | LDFLAGS=-s -lOpenCL -mcmodel=large 13 | CFLAGS=-c -std=c++11 -Wall -mmmx -O2 -mcmodel=large 14 | endif 15 | 16 | all: $(SOURCES) $(EXECUTABLE) 17 | 18 | $(EXECUTABLE): $(OBJECTS) 19 | $(CC) $(OBJECTS) $(LDFLAGS) -o $@ 20 | 21 | .cpp.o: 22 | $(CC) $(CFLAGS) $(CDEFINES) $< -o $@ 23 | 24 | clean: 25 | rm -rf *.o 26 | 27 | -------------------------------------------------------------------------------- /ModeFactory.cpp: -------------------------------------------------------------------------------- 1 | #include "ModeFactory.hpp" 2 | 3 | #include "hexadecimal.hpp" 4 | 5 | mode ModeFactory::benchmark() { 6 | mode r; 7 | r.function = ModeFunction::Benchmark; 8 | return r; 9 | } 10 | 11 | mode ModeFactory::zerobytes() { 12 | mode r; 13 | r.function = ModeFunction::ZeroBytes; 14 | return r; 15 | } 16 | 17 | mode ModeFactory::zeros() { 18 | return range(0, 0); 19 | } 20 | 21 | mode ModeFactory::matching(const std::string strHex) { 22 | mode r; 23 | r.function = ModeFunction::Matching; 24 | 25 | std::fill( r.data1, r.data1 + sizeof(r.data1), cl_uchar(0) ); 26 | std::fill( r.data2, r.data2 + sizeof(r.data2), cl_uchar(0) ); 27 | 28 | auto index = 0; 29 | 30 | for( size_t i = 0; i < strHex.size(); i += 2 ) { 31 | const auto indexHi = hexValueNoException(strHex[i]); 32 | const auto indexLo = i + 1 < strHex.size() ? hexValueNoException(strHex[i+1]) : std::string::npos; 33 | 34 | const auto valHi = (indexHi == std::string::npos) ? 0 : indexHi << 4; 35 | const auto valLo = (indexLo == std::string::npos) ? 0 : indexLo; 36 | 37 | const auto maskHi = (indexHi == std::string::npos) ? 0 : 0xF << 4; 38 | const auto maskLo = (indexLo == std::string::npos) ? 0 : 0xF; 39 | 40 | r.data1[index] = maskHi | maskLo; 41 | r.data2[index] = valHi | valLo; 42 | 43 | ++index; 44 | } 45 | 46 | return r; 47 | } 48 | 49 | mode ModeFactory::leading(const char charLeading) { 50 | mode r; 51 | r.function = ModeFunction::Leading; 52 | r.data1[0] = static_cast(hexValue(charLeading)); 53 | return r; 54 | } 55 | 56 | mode ModeFactory::range(const cl_uchar min, const cl_uchar max) { 57 | mode r; 58 | r.function = ModeFunction::Range; 59 | r.data1[0] = min; 60 | r.data2[0] = max; 61 | return r; 62 | } 63 | 64 | mode ModeFactory::letters() { 65 | return range(10, 15); 66 | } 67 | 68 | mode ModeFactory::numbers() { 69 | return range(0, 9); 70 | } 71 | 72 | mode ModeFactory::leadingRange(const cl_uchar min, const cl_uchar max) { 73 | mode r; 74 | r.function = ModeFunction::LeadingRange; 75 | r.data1[0] = min; 76 | r.data2[0] = max; 77 | return r; 78 | } 79 | 80 | mode ModeFactory::mirror() { 81 | mode r; 82 | r.function = ModeFunction::Mirror; 83 | return r; 84 | } 85 | 86 | mode ModeFactory::doubles() { 87 | mode r; 88 | r.function = ModeFunction::Doubles; 89 | return r; 90 | } 91 | -------------------------------------------------------------------------------- /ModeFactory.hpp: -------------------------------------------------------------------------------- 1 | #ifndef HPP_MODEFACTORY 2 | #define HPP_MODEFACTORY 3 | 4 | #include 5 | #include "types.hpp" 6 | 7 | class ModeFactory { 8 | private: 9 | ModeFactory(); 10 | ModeFactory(ModeFactory & o); 11 | ~ModeFactory(); 12 | 13 | public: 14 | static mode matching(const std::string strHex); 15 | static mode range(const cl_uchar min, const cl_uchar max); 16 | static mode leading(const char charLeading); 17 | static mode leadingRange(const cl_uchar min, const cl_uchar max); 18 | static mode mirror(); 19 | 20 | static mode benchmark(); 21 | static mode zerobytes(); 22 | static mode zeros(); 23 | static mode letters(); 24 | static mode numbers(); 25 | static mode doubles(); 26 | }; 27 | 28 | #endif /* HPP_MODEFACTORY */ 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ERADICATE2 2 | ``` 3 | usage: ./ERADICATE2 [OPTIONS] 4 | 5 | Input: 6 | -A, --address Target address 7 | -I, --init-code Init code 8 | -i, --init-code-file Read init code from this file 9 | 10 | The init code should be expressed as a hexadecimal string having the 11 | prefix 0x both when expressed on the command line with -I and in the 12 | file pointed to by -i if used. Any whitespace will be trimmed. If no 13 | init code is specified it defaults to an empty string. 14 | 15 | Basic modes: 16 | --benchmark Run without any scoring, a benchmark. 17 | --zeros Score on zeros anywhere in hash. 18 | --letters Score on letters anywhere in hash. 19 | --numbers Score on numbers anywhere in hash. 20 | --mirror Score on mirroring from center. 21 | --leading-doubles Score on hashes leading with hexadecimal pairs 22 | 23 | Modes with arguments: 24 | --leading Score on hashes leading with given hex character. 25 | --matching Score on hashes matching given hex string. 26 | 27 | Advanced modes: 28 | --leading-range Scores on hashes leading with characters within 29 | given range. 30 | --range Scores on hashes having characters within given 31 | range anywhere. 32 | 33 | Range: 34 | -m, --min <0-15> Set range minimum (inclusive), 0 is '0' 15 is 'f'. 35 | -M, --max <0-15> Set range maximum (inclusive), 0 is '0' 15 is 'f'. 36 | 37 | Device control: 38 | -s, --skip Skip device given by index. 39 | -n, --no-cache Don't load cached pre-compiled version of kernel. 40 | 41 | Tweaking: 42 | -w, --work Set OpenCL local work size. [default = 64] 43 | -W, --work-max Set OpenCL maximum work size. [default = -i * -I] 44 | -S, --size Set number of salts tried per loop. 45 | [default = 16777216] 46 | 47 | Examples: 48 | ./ERADICATE2 -A 0x00000000000000000000000000000000deadbeef -I 0x00 --leading 0 49 | ./ERADICATE2 -A 0x00000000000000000000000000000000deadbeef -I 0x00 --zeros 50 | 51 | About: 52 | ERADICATE2 is a vanity address generator for CREATE2 addresses that 53 | utilizes computing power from GPUs using OpenCL. 54 | 55 | Author: Johan Gustafsson 56 | Beer donations: 0x000dead000ae1c8e8ac27103e4ff65f42a4e9203 57 | ``` 58 | -------------------------------------------------------------------------------- /Speed.cpp: -------------------------------------------------------------------------------- 1 | #include "Speed.hpp" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | static std::string formatSpeed(double f) { 10 | const std::string S = " KMGT"; 11 | 12 | unsigned int index = 0; 13 | while (f > 1000.0f && index < S.size()) { 14 | f /= 1000.0f; 15 | ++index; 16 | } 17 | 18 | std::ostringstream ss; 19 | ss << std::fixed << std::setprecision(3) << (double)f << " " << S[index] << "H/s"; 20 | return ss.str(); 21 | } 22 | 23 | Speed::Speed(const unsigned int intervalPrintMs, const unsigned int intervalSampleMs) : 24 | m_intervalPrintMs(intervalPrintMs), 25 | m_intervalSampleMs(intervalSampleMs), 26 | m_lastPrint(0) { 27 | } 28 | 29 | Speed::~Speed() { 30 | } 31 | 32 | void Speed::update(const unsigned int numPoints, const unsigned int indexDevice) { 33 | std::lock_guard lockGuard(m_mutex); 34 | 35 | const auto ns = std::chrono::steady_clock::now().time_since_epoch().count(); 36 | const bool bPrint = ((ns - m_lastPrint) / 1000000) > m_intervalPrintMs; 37 | 38 | updateList(numPoints, ns, m_lSamples); 39 | updateList(numPoints, ns, m_mDeviceSamples[indexDevice]); 40 | 41 | if (bPrint) { 42 | m_lastPrint = ns; 43 | this->print(); 44 | } 45 | } 46 | 47 | double Speed::getSpeed() const { 48 | return this->getSpeed(m_lSamples); 49 | } 50 | 51 | double Speed::getSpeed(const unsigned int indexDevice) const { 52 | return m_mDeviceSamples.count(indexDevice) == 0 ? 0 : this->getSpeed(m_mDeviceSamples.at(indexDevice)); 53 | } 54 | 55 | double Speed::getSpeed(const sampleList & l) const { 56 | std::lock_guard lockGuard(m_mutex); 57 | if (l.size() == 0) { 58 | return 0.0; 59 | } 60 | 61 | auto lambda = [&](double a, samplePair b) { return a + static_cast(b.second); }; 62 | 63 | const double timeDelta = static_cast(l.back().first - l.front().first); 64 | const double numPointsSum = std::accumulate(l.begin(), l.end(), 0.0, lambda); 65 | 66 | return timeDelta == 0.0 ? 0.0 : numPointsSum / (timeDelta / 1000000000.0); 67 | } 68 | 69 | void Speed::updateList(const unsigned int & numPoints, const long long & ns, sampleList & l) { 70 | l.push_back(samplePair(ns, numPoints)); 71 | 72 | // Pop old samples until time difference between first and last element is less than or equal to m_sampleSeconds 73 | // We don't need to check size of m_lSamples since it's always >= 1 at this point 74 | while (l.size() > 2 && (l.back().first - l.front().first) / 1000000 > m_intervalSampleMs) { 75 | l.pop_front(); 76 | } 77 | } 78 | 79 | void Speed::print() const { 80 | const std::string strVT100ClearLine = "\33[2K\r"; 81 | std::cout << strVT100ClearLine << "Speed: " << formatSpeed(this->getSpeed()); 82 | 83 | // std::map is sorted by key so we'll always have the devices in numerical order 84 | for (auto it = m_mDeviceSamples.begin(); it != m_mDeviceSamples.end(); ++it) { 85 | std::cout << " GPU" << it->first << ": " << formatSpeed(this->getSpeed(it->second)); 86 | } 87 | 88 | std::cout << "\r" << std::flush; 89 | } 90 | -------------------------------------------------------------------------------- /Speed.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _HPP_SPEED 2 | #define _HPP_SPEED 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class Speed { 10 | public: 11 | typedef std::pair samplePair; 12 | typedef std::list sampleList; 13 | 14 | public: 15 | Speed(const unsigned int intervalPrintMs = 500, const unsigned int intervalSampleMs = 10000); 16 | ~Speed(); 17 | 18 | void update(const unsigned int numPoints, const unsigned int indexDevice); 19 | void print() const; 20 | 21 | double getSpeed() const; 22 | double getSpeed(const unsigned int indexDevice) const; 23 | 24 | private: 25 | double getSpeed(const sampleList & l) const; 26 | void updateList(const unsigned int & numPoints, const long long & ns, sampleList & l); 27 | 28 | private: 29 | const unsigned int m_intervalPrintMs; 30 | const unsigned int m_intervalSampleMs; 31 | 32 | long long m_lastPrint; 33 | mutable std::recursive_mutex m_mutex; 34 | sampleList m_lSamples; 35 | std::map m_mDeviceSamples; 36 | }; 37 | 38 | #endif /* _HPP_SPEED */ -------------------------------------------------------------------------------- /eradicate2.cl: -------------------------------------------------------------------------------- 1 | enum ModeFunction { 2 | Benchmark, ZeroBytes, Matching, Leading, Range, Mirror, Doubles, LeadingRange 3 | }; 4 | 5 | typedef struct { 6 | enum ModeFunction function; 7 | uchar data1[20]; 8 | uchar data2[20]; 9 | } mode; 10 | 11 | typedef struct __attribute__((packed)) { 12 | uchar salt[32]; 13 | uchar hash[20]; 14 | uint found; 15 | } result; 16 | 17 | __kernel void eradicate2_iterate(__global result * const pResult, __global const mode * const pMode, const uchar scoreMax, const uint deviceIndex, const uint round); 18 | void eradicate2_result_update(const uchar * const hash, __global result * const pResult, const uchar score, const uchar scoreMax, const uint deviceIndex, const uint round); 19 | void eradicate2_score_leading(const uchar * const hash, __global result * const pResult, __global const mode * const pMode, const uchar scoreMax, const uint deviceIndex, const uint round); 20 | void eradicate2_score_benchmark(const uchar * const hash, __global result * const pResult, __global const mode * const pMode, const uchar scoreMax, const uint deviceIndex, const uint round); 21 | void eradicate2_score_zerobytes(const uchar * const hash, __global result * const pResult, __global const mode * const pMode, const uchar scoreMax, const uint deviceIndex, const uint round); 22 | void eradicate2_score_matching(const uchar * const hash, __global result * const pResult, __global const mode * const pMode, const uchar scoreMax, const uint deviceIndex, const uint round); 23 | void eradicate2_score_range(const uchar * const hash, __global result * const pResult, __global const mode * const pMode, const uchar scoreMax, const uint deviceIndex, const uint round); 24 | void eradicate2_score_leadingrange(const uchar * const hash, __global result * const pResult, __global const mode * const pMode, const uchar scoreMax, const uint deviceIndex, const uint round); 25 | void eradicate2_score_mirror(const uchar * const hash, __global result * const pResult, __global const mode * const pMode, const uchar scoreMax, const uint deviceIndex, const uint round); 26 | void eradicate2_score_doubles(const uchar * const hash, __global result * const pResult, __global const mode * const pMode, const uchar scoreMax, const uint deviceIndex, const uint round); 27 | 28 | __kernel void eradicate2_iterate(__global result * const pResult, __global const mode * const pMode, const uchar scoreMax, const uint deviceIndex, const uint round) { 29 | ethhash h = { .q = { ERADICATE2_INITHASH } }; 30 | 31 | // Salt have index h.b[21:52] inclusive, which covers WORDS with index h.d[6:12] inclusive (they represent h.b[24:51] inclusive) 32 | // We use three out of those six words to generate a unique salt value for each device, thread and round. We ignore any overflows 33 | // and assume that there'll never be more than 2**32 devices, threads or rounds. Worst case scenario with default settings 34 | // of 16777216 = 2**24 threads means the assumption fails after a device has tried 2**32 * 2**24 = 2**56 salts, enough to match 35 | // 14 characters in the address! A GTX 1070 with speed of ~700*10**6 combinations per second would hit this target after ~3 years. 36 | h.d[6] += deviceIndex; 37 | h.d[7] += get_global_id(0); 38 | h.d[8] += round; 39 | 40 | // Hash 41 | sha3_keccakf(&h); 42 | 43 | /* enum class ModeFunction { 44 | * Benchmark, ZeroBytes, Matching, Leading, Range, Mirror, Doubles, LeadingRange 45 | * }; 46 | */ 47 | switch (pMode->function) { 48 | case Benchmark: 49 | eradicate2_score_benchmark(h.b + 12, pResult, pMode, scoreMax, deviceIndex, round); 50 | break; 51 | 52 | case ZeroBytes: 53 | eradicate2_score_zerobytes(h.b + 12, pResult, pMode, scoreMax, deviceIndex, round); 54 | break; 55 | 56 | case Matching: 57 | eradicate2_score_matching(h.b + 12, pResult, pMode, scoreMax, deviceIndex, round); 58 | break; 59 | 60 | case Leading: 61 | eradicate2_score_leading(h.b + 12, pResult, pMode, scoreMax, deviceIndex, round); 62 | break; 63 | 64 | case Range: 65 | eradicate2_score_range(h.b + 12, pResult, pMode, scoreMax, deviceIndex, round); 66 | break; 67 | 68 | case Mirror: 69 | eradicate2_score_mirror(h.b + 12, pResult, pMode, scoreMax, deviceIndex, round); 70 | break; 71 | 72 | case Doubles: 73 | eradicate2_score_doubles(h.b + 12, pResult, pMode, scoreMax, deviceIndex, round); 74 | break; 75 | 76 | case LeadingRange: 77 | eradicate2_score_leadingrange(h.b + 12, pResult, pMode, scoreMax, deviceIndex, round); 78 | break; 79 | } 80 | } 81 | 82 | void eradicate2_result_update(const uchar * const H, __global result * const pResult, const uchar score, const uchar scoreMax, const uint deviceIndex, const uint round) { 83 | if (score && score > scoreMax) { 84 | const uchar hasResult = atomic_inc(&pResult[score].found); // NOTE: If "too many" results are found it'll wrap around to 0 again and overwrite last result. Only relevant if global worksize exceeds MAX(uint). 85 | 86 | // Save only one result for each score, the first. 87 | if (hasResult == 0) { 88 | // Reconstruct state with hash and extract salt 89 | ethhash h = { .q = { ERADICATE2_INITHASH } }; 90 | h.d[6] += deviceIndex; 91 | h.d[7] += get_global_id(0); 92 | h.d[8] += round; 93 | 94 | ethhash be; 95 | 96 | for (int i = 0; i < 32; ++i) { 97 | pResult[score].salt[i] = h.b[i + 21]; 98 | } 99 | 100 | for (int i = 0; i < 20; ++i) { 101 | pResult[score].hash[i] = H[i]; 102 | } 103 | } 104 | } 105 | } 106 | 107 | void eradicate2_score_leading(const uchar * const hash, __global result * const pResult, __global const mode * const pMode, const uchar scoreMax, const uint deviceIndex, const uint round) { 108 | int score = 0; 109 | 110 | for (int i = 0; i < 20; ++i) { 111 | if ((hash[i] & 0xF0) >> 4 == pMode->data1[0]) { 112 | ++score; 113 | } else { 114 | break; 115 | } 116 | 117 | if ((hash[i] & 0x0F) == pMode->data1[0]) { 118 | ++score; 119 | } else { 120 | break; 121 | } 122 | } 123 | 124 | eradicate2_result_update(hash, pResult, score, scoreMax, deviceIndex, round); 125 | } 126 | 127 | void eradicate2_score_benchmark(const uchar * const hash, __global result * const pResult, __global const mode * const pMode, const uchar scoreMax, const uint deviceIndex, const uint round) { 128 | const size_t id = get_global_id(0); 129 | int score = 0; 130 | 131 | eradicate2_result_update(hash, pResult, score, scoreMax, deviceIndex, round); 132 | } 133 | 134 | void eradicate2_score_zerobytes(const uchar * const hash, __global result * const pResult, __global const mode * const pMode, const uchar scoreMax, const uint deviceIndex, const uint round) { 135 | const size_t id = get_global_id(0); 136 | int score = 0; 137 | 138 | for (int i = 0; i < 20; ++i) { 139 | score += !hash[i]; 140 | } 141 | 142 | eradicate2_result_update(hash, pResult, score, scoreMax, deviceIndex, round); 143 | } 144 | 145 | void eradicate2_score_matching(const uchar * const hash, __global result * const pResult, __global const mode * const pMode, const uchar scoreMax, const uint deviceIndex, const uint round) { 146 | const size_t id = get_global_id(0); 147 | int score = 0; 148 | 149 | for (int i = 0; i < 20; ++i) { 150 | if (pMode->data1[i] > 0 && (hash[i] & pMode->data1[i]) == pMode->data2[i]) { 151 | ++score; 152 | } 153 | } 154 | 155 | eradicate2_result_update(hash, pResult, score, scoreMax, deviceIndex, round); 156 | } 157 | 158 | void eradicate2_score_range(const uchar * const hash, __global result * const pResult, __global const mode * const pMode, const uchar scoreMax, const uint deviceIndex, const uint round) { 159 | const size_t id = get_global_id(0); 160 | int score = 0; 161 | 162 | for (int i = 0; i < 20; ++i) { 163 | const uchar first = (hash[i] & 0xF0) >> 4; 164 | const uchar second = (hash[i] & 0x0F); 165 | 166 | if (first >= pMode->data1[0] && first <= pMode->data2[0]) { 167 | ++score; 168 | } 169 | 170 | if (second >= pMode->data1[0] && second <= pMode->data2[0]) { 171 | ++score; 172 | } 173 | } 174 | 175 | eradicate2_result_update(hash, pResult, score, scoreMax, deviceIndex, round); 176 | } 177 | 178 | void eradicate2_score_leadingrange(const uchar * const hash, __global result * const pResult, __global const mode * const pMode, const uchar scoreMax, const uint deviceIndex, const uint round) { 179 | const size_t id = get_global_id(0); 180 | int score = 0; 181 | 182 | for (int i = 0; i < 20; ++i) { 183 | const uchar first = (hash[i] & 0xF0) >> 4; 184 | const uchar second = (hash[i] & 0x0F); 185 | 186 | if (first >= pMode->data1[0] && first <= pMode->data2[0]) { 187 | ++score; 188 | } 189 | else { 190 | break; 191 | } 192 | 193 | if (second >= pMode->data1[0] && second <= pMode->data2[0]) { 194 | ++score; 195 | } 196 | else { 197 | break; 198 | } 199 | } 200 | 201 | eradicate2_result_update(hash, pResult, score, scoreMax, deviceIndex, round); 202 | } 203 | 204 | void eradicate2_score_mirror(const uchar * const hash, __global result * const pResult, __global const mode * const pMode, const uchar scoreMax, const uint deviceIndex, const uint round) { 205 | const size_t id = get_global_id(0); 206 | int score = 0; 207 | 208 | for (int i = 0; i < 10; ++i) { 209 | const uchar leftLeft = (hash[9 - i] & 0xF0) >> 4; 210 | const uchar leftRight = (hash[9 - i] & 0x0F); 211 | 212 | const uchar rightLeft = (hash[10 + i] & 0xF0) >> 4; 213 | const uchar rightRight = (hash[10 + i] & 0x0F); 214 | 215 | if (leftRight != rightLeft) { 216 | break; 217 | } 218 | 219 | ++score; 220 | 221 | if (leftLeft != rightRight) { 222 | break; 223 | } 224 | 225 | ++score; 226 | } 227 | 228 | eradicate2_result_update(hash, pResult, score, scoreMax, deviceIndex, round); 229 | } 230 | 231 | void eradicate2_score_doubles(const uchar * const hash, __global result * const pResult, __global const mode * const pMode, const uchar scoreMax, const uint deviceIndex, const uint round) { 232 | const size_t id = get_global_id(0); 233 | int score = 0; 234 | 235 | for (int i = 0; i < 20; ++i) { 236 | if ((hash[i] == 0x00) || (hash[i] == 0x11) || (hash[i] == 0x22) || (hash[i] == 0x33) || (hash[i] == 0x44) || (hash[i] == 0x55) || (hash[i] == 0x66) || (hash[i] == 0x77) || (hash[i] == 0x88) || (hash[i] == 0x99) || (hash[i] == 0xAA) || (hash[i] == 0xBB) || (hash[i] == 0xCC) || (hash[i] == 0xDD) || (hash[i] == 0xEE) || (hash[i] == 0xFF)) { 237 | ++score; 238 | } 239 | else { 240 | break; 241 | } 242 | } 243 | 244 | eradicate2_result_update(hash, pResult, score, scoreMax, deviceIndex, round); 245 | } 246 | -------------------------------------------------------------------------------- /eradicate2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #if defined(__APPLE__) || defined(__MACOSX) 14 | #include 15 | #else 16 | #include 17 | #endif 18 | 19 | #include "hexadecimal.hpp" 20 | #include "Dispatcher.hpp" 21 | #include "ArgParser.hpp" 22 | #include "ModeFactory.hpp" 23 | #include "types.hpp" 24 | #include "help.hpp" 25 | #include "sha3.hpp" 26 | 27 | std::string readFile(const char * const szFilename) 28 | { 29 | std::ifstream in(szFilename, std::ios::in | std::ios::binary); 30 | std::ostringstream contents; 31 | contents << in.rdbuf(); 32 | return contents.str(); 33 | } 34 | 35 | std::vector getAllDevices(cl_device_type deviceType = CL_DEVICE_TYPE_GPU) 36 | { 37 | std::vector vDevices; 38 | 39 | cl_uint platformIdCount = 0; 40 | clGetPlatformIDs (0, NULL, &platformIdCount); 41 | 42 | std::vector platformIds (platformIdCount); 43 | clGetPlatformIDs (platformIdCount, platformIds.data (), NULL); 44 | 45 | for( auto it = platformIds.cbegin(); it != platformIds.cend(); ++it ) { 46 | cl_uint countDevice; 47 | clGetDeviceIDs(*it, deviceType, 0, NULL, &countDevice); 48 | 49 | std::vector deviceIds(countDevice); 50 | clGetDeviceIDs(*it, deviceType, countDevice, deviceIds.data(), &countDevice); 51 | 52 | std::copy( deviceIds.begin(), deviceIds.end(), std::back_inserter(vDevices) ); 53 | } 54 | 55 | return vDevices; 56 | } 57 | 58 | template 59 | T clGetWrapper(U function, V param, W param2) { 60 | T t; 61 | function(param, param2, sizeof(t), &t, NULL); 62 | return t; 63 | } 64 | 65 | template 66 | std::string clGetWrapperString(U function, V param, W param2) { 67 | size_t len; 68 | function(param, param2, 0, NULL, &len); 69 | char * const szString = new char[len]; 70 | function(param, param2, len, szString, NULL); 71 | std::string r(szString); 72 | delete[] szString; 73 | return r; 74 | } 75 | 76 | template 77 | std::vector clGetWrapperVector(U function, V param, W param2) { 78 | size_t len; 79 | function(param, param2, 0, NULL, &len); 80 | len /= sizeof(T); 81 | std::vector v; 82 | if (len > 0) { 83 | T * pArray = new T[len]; 84 | function(param, param2, len * sizeof(T), pArray, NULL); 85 | for (size_t i = 0; i < len; ++i) { 86 | v.push_back(pArray[i]); 87 | } 88 | delete[] pArray; 89 | } 90 | return v; 91 | } 92 | 93 | std::vector getBinaries(cl_program & clProgram) { 94 | std::vector vReturn; 95 | auto vSizes = clGetWrapperVector(clGetProgramInfo, clProgram, CL_PROGRAM_BINARY_SIZES); 96 | if (!vSizes.empty()) { 97 | unsigned char * * pBuffers = new unsigned char *[vSizes.size()]; 98 | for (size_t i = 0; i < vSizes.size(); ++i) { 99 | pBuffers[i] = new unsigned char[vSizes[i]]; 100 | } 101 | 102 | clGetProgramInfo(clProgram, CL_PROGRAM_BINARIES, vSizes.size() * sizeof(unsigned char *), pBuffers, NULL); 103 | for (size_t i = 0; i < vSizes.size(); ++i) { 104 | std::string strData(reinterpret_cast(pBuffers[i]), vSizes[i]); 105 | vReturn.push_back(strData); 106 | delete[] pBuffers[i]; 107 | } 108 | 109 | delete[] pBuffers; 110 | } 111 | 112 | return vReturn; 113 | } 114 | 115 | template bool printResult(const T & t, const cl_int & err) { 116 | std::cout << ((t == NULL) ? lexical_cast::write(err) : "OK") << std::endl; 117 | return t == NULL; 118 | } 119 | 120 | bool printResult(const cl_int err) { 121 | std::cout << ((err != CL_SUCCESS) ? lexical_cast::write(err) : "OK") << std::endl; 122 | return err != CL_SUCCESS; 123 | } 124 | 125 | std::string keccakDigest(const std::string data) { 126 | char digest[32]; 127 | sha3(data.c_str(), data.size(), digest, 32); 128 | return std::string(digest, 32); 129 | } 130 | 131 | void trim(std::string & s) { 132 | const auto iLeft = s.find_first_not_of(" \t\r\n"); 133 | if (iLeft != std::string::npos) { 134 | s.erase(0, iLeft); 135 | } 136 | 137 | const auto iRight = s.find_last_not_of(" \t\r\n"); 138 | if (iRight != std::string::npos) { 139 | const auto count = s.length() - iRight - 1; 140 | s.erase(iRight + 1, count); 141 | } 142 | } 143 | 144 | std::string makePreprocessorInitHashExpression(const std::string & strAddressBinary, const std::string & strInitCodeDigest) { 145 | std::random_device rd; 146 | std::mt19937_64 eng(rd()); 147 | std::uniform_int_distribution distr; // C++ requires integer type: "C2338 note : char, signed char, unsigned char, int8_t, and uint8_t are not allowed" 148 | ethhash h = { 0 }; 149 | 150 | h.b[0] = 0xff; 151 | for (int i = 0; i < 20; ++i) { 152 | h.b[i + 1] = strAddressBinary[i]; 153 | } 154 | 155 | for (int i = 0; i < 32; ++i) { 156 | h.b[i + 21] = distr(eng); 157 | } 158 | 159 | for (int i = 0; i < 32; ++i) { 160 | h.b[i + 53] = strInitCodeDigest[i]; 161 | } 162 | 163 | h.b[85] ^= 0x01; 164 | 165 | std::ostringstream oss; 166 | oss << std::hex; 167 | for (int i = 0; i < 25; ++i) { 168 | oss << "0x" << h.q[i]; 169 | if (i + 1 != 25) { 170 | oss << ","; 171 | } 172 | } 173 | 174 | return oss.str(); 175 | } 176 | 177 | int main(int argc, char * * argv) { 178 | try { 179 | ArgParser argp(argc, argv); 180 | bool bHelp = false; 181 | bool bModeBenchmark = false; 182 | bool bModeZeroBytes = false; 183 | bool bModeZeros = false; 184 | bool bModeLetters = false; 185 | bool bModeNumbers = false; 186 | std::string strModeLeading; 187 | std::string strModeMatching; 188 | bool bModeLeadingRange = false; 189 | bool bModeRange = false; 190 | bool bModeMirror = false; 191 | bool bModeDoubles = false; 192 | int rangeMin = 0; 193 | int rangeMax = 0; 194 | std::vector vDeviceSkipIndex; 195 | size_t worksizeLocal = 128; 196 | size_t worksizeMax = 0; // Will be automatically determined later if not overriden by user 197 | size_t size = 16777216; 198 | std::string strAddress; 199 | std::string strInitCode; 200 | std::string strInitCodeFile; 201 | 202 | argp.addSwitch('h', "help", bHelp); 203 | argp.addSwitch('0', "benchmark", bModeBenchmark); 204 | argp.addSwitch('z', "zero-bytes", bModeZeroBytes); 205 | argp.addSwitch('1', "zeros", bModeZeros); 206 | argp.addSwitch('2', "letters", bModeLetters); 207 | argp.addSwitch('3', "numbers", bModeNumbers); 208 | argp.addSwitch('4', "leading", strModeLeading); 209 | argp.addSwitch('5', "matching", strModeMatching); 210 | argp.addSwitch('6', "leading-range", bModeLeadingRange); 211 | argp.addSwitch('7', "range", bModeRange); 212 | argp.addSwitch('8', "mirror", bModeMirror); 213 | argp.addSwitch('9', "leading-doubles", bModeDoubles); 214 | argp.addSwitch('m', "min", rangeMin); 215 | argp.addSwitch('M', "max", rangeMax); 216 | argp.addMultiSwitch('s', "skip", vDeviceSkipIndex); 217 | argp.addSwitch('w', "work", worksizeLocal); 218 | argp.addSwitch('W', "work-max", worksizeMax); 219 | argp.addSwitch('S', "size", size); 220 | argp.addSwitch('A', "address", strAddress); 221 | argp.addSwitch('I', "init-code", strInitCode); 222 | argp.addSwitch('i', "init-code-file", strInitCodeFile); 223 | 224 | if (!argp.parse()) { 225 | std::cout << "error: bad arguments, try again :<" << std::endl; 226 | return 1; 227 | } 228 | 229 | if (bHelp) { 230 | std::cout << g_strHelp << std::endl; 231 | return 0; 232 | } 233 | 234 | // Parse hexadecimal values and/or read init code from file 235 | if (strInitCodeFile != "") { 236 | std::ifstream ifs(strInitCodeFile); 237 | if (!ifs.is_open()) { 238 | std::cout << "error: failed to open input file for init code" << std::endl; 239 | return 1; 240 | } 241 | strInitCode.assign(std::istreambuf_iterator(ifs), std::istreambuf_iterator()); 242 | } 243 | 244 | trim(strInitCode); 245 | const std::string strAddressBinary = parseHexadecimalBytes(strAddress); 246 | const std::string strInitCodeBinary = parseHexadecimalBytes(strInitCode); 247 | const std::string strInitCodeDigest = keccakDigest(strInitCodeBinary); 248 | const std::string strPreprocessorInitStructure = makePreprocessorInitHashExpression(strAddressBinary, strInitCodeDigest); 249 | 250 | mode mode = ModeFactory::benchmark(); 251 | if (bModeBenchmark) { 252 | mode = ModeFactory::benchmark(); 253 | } else if (bModeZeroBytes) { 254 | mode = ModeFactory::zerobytes(); 255 | } else if (bModeZeros) { 256 | mode = ModeFactory::zeros(); 257 | } else if (bModeLetters) { 258 | mode = ModeFactory::letters(); 259 | } else if (bModeNumbers) { 260 | mode = ModeFactory::numbers(); 261 | } else if (!strModeLeading.empty()) { 262 | mode = ModeFactory::leading(strModeLeading.front()); 263 | } else if (!strModeMatching.empty()) { 264 | mode = ModeFactory::matching(strModeMatching); 265 | } else if (bModeLeadingRange) { 266 | mode = ModeFactory::leadingRange(rangeMin, rangeMax); 267 | } else if (bModeRange) { 268 | mode = ModeFactory::range(rangeMin, rangeMax); 269 | } else if(bModeMirror) { 270 | mode = ModeFactory::mirror(); 271 | } else if (bModeDoubles) { 272 | mode = ModeFactory::doubles(); 273 | } else { 274 | std::cout << g_strHelp << std::endl; 275 | return 0; 276 | } 277 | 278 | std::vector vFoundDevices = getAllDevices(); 279 | std::vector vDevices; 280 | std::map mDeviceIndex; 281 | 282 | std::vector vDeviceBinary; 283 | std::vector vDeviceBinarySize; 284 | cl_int errorCode; 285 | 286 | std::cout << "Devices:" << std::endl; 287 | for (size_t i = 0; i < vFoundDevices.size(); ++i) { 288 | // Ignore devices in skip index 289 | if (std::find(vDeviceSkipIndex.begin(), vDeviceSkipIndex.end(), i) != vDeviceSkipIndex.end()) { 290 | continue; 291 | } 292 | 293 | cl_device_id & deviceId = vFoundDevices[i]; 294 | 295 | const auto strName = clGetWrapperString(clGetDeviceInfo, deviceId, CL_DEVICE_NAME); 296 | const auto computeUnits = clGetWrapper(clGetDeviceInfo, deviceId, CL_DEVICE_MAX_COMPUTE_UNITS); 297 | const auto globalMemSize = clGetWrapper(clGetDeviceInfo, deviceId, CL_DEVICE_GLOBAL_MEM_SIZE); 298 | 299 | std::cout << " GPU" << i << ": " << strName << ", " << globalMemSize << " bytes available, " << computeUnits << " compute units" << std::endl; 300 | vDevices.push_back(vFoundDevices[i]); 301 | mDeviceIndex[vFoundDevices[i]] = i; 302 | } 303 | 304 | if (vDevices.empty()) { 305 | return 1; 306 | } 307 | 308 | std::cout << std::endl; 309 | std::cout << "Initializing OpenCL..." << std::endl; 310 | std::cout << " Creating context..." << std::flush; 311 | auto clContext = clCreateContext( NULL, vDevices.size(), vDevices.data(), NULL, NULL, &errorCode); 312 | if (printResult(clContext, errorCode)) { 313 | return 1; 314 | } 315 | 316 | cl_program clProgram; 317 | if (vDeviceBinary.size() == vDevices.size()) { 318 | // Create program from binaries 319 | std::cout << " Loading kernel from binary..." << std::flush; 320 | const unsigned char * * pKernels = new const unsigned char *[vDevices.size()]; 321 | for (size_t i = 0; i < vDeviceBinary.size(); ++i) { 322 | pKernels[i] = reinterpret_cast(vDeviceBinary[i].data()); 323 | } 324 | 325 | cl_int * pStatus = new cl_int[vDevices.size()]; 326 | 327 | clProgram = clCreateProgramWithBinary(clContext, vDevices.size(), vDevices.data(), vDeviceBinarySize.data(), pKernels, pStatus, &errorCode); 328 | if(printResult(clProgram, errorCode)) { 329 | return 1; 330 | } 331 | } else { 332 | // Create a program from the kernel source 333 | std::cout << " Compiling kernel..." << std::flush; 334 | const std::string strKeccak = readFile("keccak.cl"); 335 | const std::string strVanity = readFile("eradicate2.cl"); 336 | const char * szKernels[] = { strKeccak.c_str(), strVanity.c_str() }; 337 | 338 | clProgram = clCreateProgramWithSource(clContext, sizeof(szKernels) / sizeof(char *), szKernels, NULL, &errorCode); 339 | if (printResult(clProgram, errorCode)) { 340 | return 1; 341 | } 342 | } 343 | 344 | // Build the program 345 | std::cout << " Building program..." << std::flush; 346 | 347 | const std::string strBuildOptions = "-D ERADICATE2_MAX_SCORE=" + lexical_cast::write(ERADICATE2_MAX_SCORE) + " -D ERADICATE2_INITHASH=" + strPreprocessorInitStructure; 348 | if (printResult(clBuildProgram(clProgram, vDevices.size(), vDevices.data(), strBuildOptions.c_str(), NULL, NULL))) { 349 | #ifdef ERADICATE2_DEBUG 350 | std::cout << std::endl; 351 | std::cout << "build log:" << std::endl; 352 | 353 | size_t sizeLog; 354 | clGetProgramBuildInfo(clProgram, vDevices[0], CL_PROGRAM_BUILD_LOG, 0, NULL, &sizeLog); 355 | char * const szLog = new char[sizeLog]; 356 | clGetProgramBuildInfo(clProgram, vDevices[0], CL_PROGRAM_BUILD_LOG, sizeLog, szLog, NULL); 357 | 358 | std::cout << szLog << std::endl; 359 | delete[] szLog; 360 | #endif 361 | return 1; 362 | } 363 | 364 | std::cout << std::endl; 365 | 366 | Dispatcher d(clContext, clProgram, worksizeMax == 0 ? size : worksizeMax, size); 367 | for (auto & i : vDevices) { 368 | d.addDevice(i, worksizeLocal, mDeviceIndex[i]); 369 | } 370 | 371 | d.run(mode); 372 | clReleaseContext(clContext); 373 | return 0; 374 | } catch (std::runtime_error & e) { 375 | std::cout << "std::runtime_error - " << e.what() << std::endl; 376 | } catch (...) { 377 | std::cout << "unknown exception occured" << std::endl; 378 | } 379 | 380 | return 1; 381 | } 382 | -------------------------------------------------------------------------------- /help.hpp: -------------------------------------------------------------------------------- 1 | #ifndef HPP_HELP 2 | #define HPP_HELP 3 | 4 | #include 5 | 6 | const std::string g_strHelp = R"( 7 | usage: ./ERADICATE2 [OPTIONS] 8 | 9 | Input: 10 | -A, --address Target address 11 | -I, --init-code Init code 12 | -i, --init-code-file Read init code from this file 13 | 14 | The init code should be expressed as a hexadecimal string having the 15 | prefix 0x both when expressed on the command line with -I and in the 16 | file pointed to by -i if used. Any whitespace will be trimmed. If no 17 | init code is specified it defaults to an empty string. 18 | 19 | Basic modes: 20 | --benchmark Run without any scoring, a benchmark. 21 | --zeros Score on zeros anywhere in hash. 22 | --zero-bytes Score on zero bytes anywhere in hash. 23 | --letters Score on letters anywhere in hash. 24 | --numbers Score on numbers anywhere in hash. 25 | --mirror Score on mirroring from center. 26 | --leading-doubles Score on hashes leading with hexadecimal pairs 27 | 28 | Modes with arguments: 29 | --leading Score on hashes leading with given hex character. 30 | --matching Score on hashes matching given hex string. 31 | 32 | Advanced modes: 33 | --leading-range Scores on hashes leading with characters within 34 | given range. 35 | --range Scores on hashes having characters within given 36 | range anywhere. 37 | 38 | Range: 39 | -m, --min <0-15> Set range minimum (inclusive), 0 is '0' 15 is 'f'. 40 | -M, --max <0-15> Set range maximum (inclusive), 0 is '0' 15 is 'f'. 41 | 42 | Device control: 43 | -s, --skip Skip device given by index. 44 | 45 | Tweaking: 46 | -w, --work Set OpenCL local work size. [default = 64] 47 | -W, --work-max Set OpenCL maximum work size. [default = -i * -I] 48 | -S, --size Set number of salts tried per loop. 49 | [default = 16777216] 50 | 51 | Examples: 52 | ./ERADICATE2 -A 0x00000000000000000000000000000000deadbeef -I 0x00 --leading 0 53 | ./ERADICATE2 -A 0x00000000000000000000000000000000deadbeef -I 0x00 --zeros 54 | 55 | About: 56 | ERADICATE2 is a vanity address generator for CREATE2 addresses that 57 | utilizes computing power from GPUs using OpenCL. 58 | 59 | Author: Johan Gustafsson 60 | Beer donations: 0x000dead000ae1c8e8ac27103e4ff65f42a4e9203 61 | )"; 62 | 63 | #endif /* HPP_HELP */ 64 | -------------------------------------------------------------------------------- /hexadecimal.cpp: -------------------------------------------------------------------------------- 1 | #include "hexadecimal.hpp" 2 | #include 3 | 4 | std::string toHex(const uint8_t * const s, const size_t len) { 5 | std::string b("0123456789abcdef"); 6 | std::string r; 7 | 8 | for (size_t i = 0; i < len; ++i) { 9 | const unsigned char h = s[i] / 16; 10 | const unsigned char l = s[i] % 16; 11 | 12 | r = r + b.substr(h, 1) + b.substr(l, 1); 13 | } 14 | 15 | return r; 16 | } 17 | 18 | std::string::size_type hexValueNoException(char c) { 19 | if (c >= 'A' && c <= 'F') { 20 | c -= 'A' - 'a'; 21 | } 22 | 23 | const std::string hex = "0123456789abcdef"; 24 | const std::string::size_type ret = hex.find(c); 25 | return ret; 26 | } 27 | 28 | std::string::size_type hexValue(char c) { 29 | const std::string::size_type ret = hexValueNoException(c); 30 | if (ret == std::string::npos) { 31 | throw std::runtime_error("bad hex value"); 32 | } 33 | 34 | return ret; 35 | } 36 | 37 | std::string parseHexadecimalBytes(std::string o) { 38 | std::string strRet; 39 | 40 | if (o.size() >= 2 && o.substr(0, 2) == "0x") { 41 | o.erase(0, 2); 42 | } 43 | 44 | if (o.size() % 2 != 0) { 45 | throw std::runtime_error("malformatted hexadecimal data"); 46 | } 47 | 48 | for (size_t i = 0; i < o.size(); i += 2) { 49 | const auto val = hexValue(o[i]) * 16 + hexValue(o[i + 1]); 50 | strRet += val; 51 | } 52 | 53 | return strRet; 54 | } 55 | -------------------------------------------------------------------------------- /hexadecimal.hpp: -------------------------------------------------------------------------------- 1 | #ifndef HPP_HEXADECIMAL 2 | #define HPP_HEXADECIMAL 3 | 4 | #include 5 | 6 | std::string toHex(const uint8_t * const s, const size_t len); 7 | std::string::size_type hexValueNoException(char c); 8 | std::string::size_type hexValue(char c); 9 | std::string parseHexadecimalBytes(std::string o); 10 | 11 | #endif /* HPP_HEXADECIMAL */ 12 | -------------------------------------------------------------------------------- /keccak.cl: -------------------------------------------------------------------------------- 1 | /* This Keccak implementation is an amalgamation of: 2 | * Tiny SHA3 implementation by Markku-Juhani O. Saarinen: 3 | * https://github.com/mjosaarinen/tiny_sha3 4 | * Keccak implementation found in xptMiner-gpu @ Github: 5 | * https://github.com/llamasoft/xptMiner-gpu/blob/master/opencl/keccak.cl 6 | */ 7 | 8 | typedef union { 9 | uchar b[200]; 10 | ulong q[25]; 11 | uint d[50]; 12 | } ethhash; 13 | 14 | #define TH_ELT_SHORT(t, d, c) t = rotate(d, (ulong) 1) ^ c 15 | 16 | #define THETA(s00, s01, s02, s03, s04, \ 17 | s10, s11, s12, s13, s14, \ 18 | s20, s21, s22, s23, s24, \ 19 | s30, s31, s32, s33, s34, \ 20 | s40, s41, s42, s43, s44) \ 21 | { \ 22 | t0 = s00 ^ s01 ^ s02 ^ s03 ^ s04; \ 23 | t1 = s10 ^ s11 ^ s12 ^ s13 ^ s14; \ 24 | t2 = s20 ^ s21 ^ s22 ^ s23 ^ s24; \ 25 | t3 = s30 ^ s31 ^ s32 ^ s33 ^ s34; \ 26 | t4 = s40 ^ s41 ^ s42 ^ s43 ^ s44; \ 27 | \ 28 | TH_ELT_SHORT(t5, t0, t3); \ 29 | TH_ELT_SHORT(t0, t2, t0); \ 30 | TH_ELT_SHORT(t2, t4, t2); \ 31 | TH_ELT_SHORT(t4, t1, t4); \ 32 | TH_ELT_SHORT(t1, t3, t1); \ 33 | \ 34 | s00 ^= t4; s01 ^= t4; s02 ^= t4; s03 ^= t4; s04 ^= t4; \ 35 | s10 ^= t0; s11 ^= t0; s12 ^= t0; s13 ^= t0; s14 ^= t0; \ 36 | s20 ^= t1; s21 ^= t1; s22 ^= t1; s23 ^= t1; s24 ^= t1; \ 37 | s30 ^= t2; s31 ^= t2; s32 ^= t2; s33 ^= t2; s34 ^= t2; \ 38 | s40 ^= t5; s41 ^= t5; s42 ^= t5; s43 ^= t5; s44 ^= t5; \ 39 | } 40 | 41 | #define RHOPI(s00, s01, s02, s03, s04, \ 42 | s10, s11, s12, s13, s14, \ 43 | s20, s21, s22, s23, s24, \ 44 | s30, s31, s32, s33, s34, \ 45 | s40, s41, s42, s43, s44) \ 46 | { \ 47 | t0 = rotate(s10, (ulong) 1); \ 48 | s10 = rotate(s11, (ulong)44); \ 49 | s11 = rotate(s41, (ulong)20); \ 50 | s41 = rotate(s24, (ulong)61); \ 51 | s24 = rotate(s42, (ulong)39); \ 52 | s42 = rotate(s04, (ulong)18); \ 53 | s04 = rotate(s20, (ulong)62); \ 54 | s20 = rotate(s22, (ulong)43); \ 55 | s22 = rotate(s32, (ulong)25); \ 56 | s32 = rotate(s43, (ulong) 8); \ 57 | s43 = rotate(s34, (ulong)56); \ 58 | s34 = rotate(s03, (ulong)41); \ 59 | s03 = rotate(s40, (ulong)27); \ 60 | s40 = rotate(s44, (ulong)14); \ 61 | s44 = rotate(s14, (ulong) 2); \ 62 | s14 = rotate(s31, (ulong)55); \ 63 | s31 = rotate(s13, (ulong)45); \ 64 | s13 = rotate(s01, (ulong)36); \ 65 | s01 = rotate(s30, (ulong)28); \ 66 | s30 = rotate(s33, (ulong)21); \ 67 | s33 = rotate(s23, (ulong)15); \ 68 | s23 = rotate(s12, (ulong)10); \ 69 | s12 = rotate(s21, (ulong) 6); \ 70 | s21 = rotate(s02, (ulong) 3); \ 71 | s02 = t0; \ 72 | } 73 | 74 | #define KHI(s00, s01, s02, s03, s04, \ 75 | s10, s11, s12, s13, s14, \ 76 | s20, s21, s22, s23, s24, \ 77 | s30, s31, s32, s33, s34, \ 78 | s40, s41, s42, s43, s44) \ 79 | { \ 80 | t0 = s00; t1 = s10; s00 ^= (~t1) & s20; s10 ^= (~s20) & s30; s20 ^= (~s30) & s40; s30 ^= (~s40) & t0; s40 ^= (~t0) & t1; \ 81 | t0 = s01; t1 = s11; s01 ^= (~t1) & s21; s11 ^= (~s21) & s31; s21 ^= (~s31) & s41; s31 ^= (~s41) & t0; s41 ^= (~t0) & t1; \ 82 | t0 = s02; t1 = s12; s02 ^= (~t1) & s22; s12 ^= (~s22) & s32; s22 ^= (~s32) & s42; s32 ^= (~s42) & t0; s42 ^= (~t0) & t1; \ 83 | t0 = s03; t1 = s13; s03 ^= (~t1) & s23; s13 ^= (~s23) & s33; s23 ^= (~s33) & s43; s33 ^= (~s43) & t0; s43 ^= (~t0) & t1; \ 84 | t0 = s04; t1 = s14; s04 ^= (~t1) & s24; s14 ^= (~s24) & s34; s24 ^= (~s34) & s44; s34 ^= (~s44) & t0; s44 ^= (~t0) & t1; \ 85 | } 86 | 87 | #define IOTA(s00, r) { s00 ^= r; } 88 | 89 | __constant ulong keccakf_rndc[24] = { 90 | 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, 91 | 0x8000000080008000, 0x000000000000808b, 0x0000000080000001, 92 | 0x8000000080008081, 0x8000000000008009, 0x000000000000008a, 93 | 0x0000000000000088, 0x0000000080008009, 0x000000008000000a, 94 | 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, 95 | 0x8000000000008003, 0x8000000000008002, 0x8000000000000080, 96 | 0x000000000000800a, 0x800000008000000a, 0x8000000080008081, 97 | 0x8000000000008080, 0x0000000080000001, 0x8000000080008008 98 | }; 99 | 100 | // Barely a bottleneck. No need to tinker more. 101 | void sha3_keccakf(ethhash * const h) 102 | { 103 | ulong * const st = h->q; 104 | h->d[33] ^= 0x80000000; 105 | ulong t0, t1, t2, t3, t4, t5; 106 | 107 | // Unrolling and removing PI stage gave negligable performance on GTX 1070. 108 | for (int i = 0; i < 24; ++i) { 109 | THETA(st[0], st[5], st[10], st[15], st[20], st[1], st[6], st[11], st[16], st[21], st[2], st[7], st[12], st[17], st[22], st[3], st[8], st[13], st[18], st[23], st[4], st[9], st[14], st[19], st[24]); 110 | RHOPI(st[0], st[5], st[10], st[15], st[20], st[1], st[6], st[11], st[16], st[21], st[2], st[7], st[12], st[17], st[22], st[3], st[8], st[13], st[18], st[23], st[4], st[9], st[14], st[19], st[24]); 111 | KHI(st[0], st[5], st[10], st[15], st[20], st[1], st[6], st[11], st[16], st[21], st[2], st[7], st[12], st[17], st[22], st[3], st[8], st[13], st[18], st[23], st[4], st[9], st[14], st[19], st[24]); 112 | IOTA(st[0], keccakf_rndc[i]); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /lexical_cast.hpp: -------------------------------------------------------------------------------- 1 | #ifndef HPP_LEXICALCAST 2 | #define HPP_LEXICALCAST 3 | 4 | #include 5 | 6 | namespace lexical_cast { 7 | template 8 | std::string write(const T & o) { 9 | std::ostringstream s; 10 | s << o; 11 | return s.str(); 12 | } 13 | 14 | template 15 | T read(const std::string s) { 16 | std::istringstream ss(s); 17 | T t; 18 | ss >> t; 19 | return t; 20 | } 21 | } 22 | 23 | #endif /* HPP_LEXICALCAST */ -------------------------------------------------------------------------------- /sha3.cpp: -------------------------------------------------------------------------------- 1 | /* https://github.com/mjosaarinen/tiny_sha3 2 | * 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2015 Markku-Juhani O. Saarinen 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | * 25 | */ 26 | 27 | // sha3.c 28 | // 19-Nov-11 Markku-Juhani O. Saarinen 29 | 30 | // Revised 07-Aug-15 to match with official release of FIPS PUB 202 "SHA3" 31 | // Revised 03-Sep-15 for portability + OpenSSL - style API 32 | 33 | #include "sha3.hpp" 34 | 35 | // update the state with given number of rounds 36 | 37 | void sha3_keccakf(uint64_t st[25]) 38 | { 39 | // constants 40 | const uint64_t keccakf_rndc[24] = { 41 | 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, 42 | 0x8000000080008000, 0x000000000000808b, 0x0000000080000001, 43 | 0x8000000080008081, 0x8000000000008009, 0x000000000000008a, 44 | 0x0000000000000088, 0x0000000080008009, 0x000000008000000a, 45 | 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, 46 | 0x8000000000008003, 0x8000000000008002, 0x8000000000000080, 47 | 0x000000000000800a, 0x800000008000000a, 0x8000000080008081, 48 | 0x8000000000008080, 0x0000000080000001, 0x8000000080008008 49 | }; 50 | const int keccakf_rotc[24] = { 51 | 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 52 | 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44 53 | }; 54 | const int keccakf_piln[24] = { 55 | 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 56 | 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1 57 | }; 58 | 59 | // variables 60 | int i, j, r; 61 | uint64_t t, bc[5]; 62 | 63 | #if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ 64 | uint8_t *v; 65 | 66 | // endianess conversion. this is redundant on little-endian targets 67 | for (i = 0; i < 25; i++) { 68 | v = (uint8_t *)&st[i]; 69 | st[i] = ((uint64_t)v[0]) | (((uint64_t)v[1]) << 8) | 70 | (((uint64_t)v[2]) << 16) | (((uint64_t)v[3]) << 24) | 71 | (((uint64_t)v[4]) << 32) | (((uint64_t)v[5]) << 40) | 72 | (((uint64_t)v[6]) << 48) | (((uint64_t)v[7]) << 56); 73 | } 74 | #endif 75 | 76 | // actual iteration 77 | for (r = 0; r < KECCAKF_ROUNDS; r++) { 78 | 79 | // Theta 80 | for (i = 0; i < 5; i++) 81 | bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15] ^ st[i + 20]; 82 | 83 | for (i = 0; i < 5; i++) { 84 | t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1); 85 | for (j = 0; j < 25; j += 5) 86 | st[j + i] ^= t; 87 | } 88 | 89 | // Rho Pi 90 | t = st[1]; 91 | for (i = 0; i < 24; i++) { 92 | j = keccakf_piln[i]; 93 | bc[0] = st[j]; 94 | st[j] = ROTL64(t, keccakf_rotc[i]); 95 | t = bc[0]; 96 | } 97 | 98 | // Chi 99 | for (j = 0; j < 25; j += 5) { 100 | for (i = 0; i < 5; i++) 101 | bc[i] = st[j + i]; 102 | for (i = 0; i < 5; i++) 103 | st[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5]; 104 | } 105 | 106 | // Iota 107 | st[0] ^= keccakf_rndc[r]; 108 | } 109 | 110 | #if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ 111 | // endianess conversion. this is redundant on little-endian targets 112 | for (i = 0; i < 25; i++) { 113 | v = (uint8_t *)&st[i]; 114 | t = st[i]; 115 | v[0] = t & 0xFF; 116 | v[1] = (t >> 8) & 0xFF; 117 | v[2] = (t >> 16) & 0xFF; 118 | v[3] = (t >> 24) & 0xFF; 119 | v[4] = (t >> 32) & 0xFF; 120 | v[5] = (t >> 40) & 0xFF; 121 | v[6] = (t >> 48) & 0xFF; 122 | v[7] = (t >> 56) & 0xFF; 123 | } 124 | #endif 125 | } 126 | 127 | // Initialize the context for SHA3 128 | 129 | int sha3_init(sha3_ctx_t *c, int mdlen) 130 | { 131 | int i; 132 | 133 | for (i = 0; i < 25; i++) 134 | c->st.q[i] = 0; 135 | c->mdlen = mdlen; 136 | c->rsiz = 200 - 2 * mdlen; 137 | c->pt = 0; 138 | 139 | return 1; 140 | } 141 | 142 | // update state with more data 143 | 144 | int sha3_update(sha3_ctx_t *c, const void *data, size_t len) 145 | { 146 | size_t i; 147 | int j; 148 | 149 | j = c->pt; 150 | for (i = 0; i < len; i++) { 151 | c->st.b[j++] ^= ((const uint8_t *)data)[i]; 152 | if (j >= c->rsiz) { 153 | sha3_keccakf(c->st.q); 154 | j = 0; 155 | } 156 | } 157 | c->pt = j; 158 | 159 | return 1; 160 | } 161 | 162 | // finalize and output a hash 163 | 164 | int sha3_final(void *md, sha3_ctx_t *c) 165 | { 166 | int i; 167 | 168 | c->st.b[c->pt] ^= 0x01; // 2019-11-26: Johan Gustafsson - Changed padding byte from 0x06 to 0x01 since I want Keccak, not SHA3. 169 | c->st.b[c->rsiz - 1] ^= 0x80; 170 | sha3_keccakf(c->st.q); 171 | 172 | for (i = 0; i < c->mdlen; i++) { 173 | ((uint8_t *)md)[i] = c->st.b[i]; 174 | } 175 | 176 | return 1; 177 | } 178 | 179 | // compute a SHA-3 hash (md) of given byte length from "in" 180 | 181 | void *sha3(const void *in, size_t inlen, void *md, int mdlen) 182 | { 183 | sha3_ctx_t sha3; 184 | 185 | sha3_init(&sha3, mdlen); 186 | sha3_update(&sha3, in, inlen); 187 | sha3_final(md, &sha3); 188 | 189 | return md; 190 | } 191 | 192 | // SHAKE128 and SHAKE256 extensible-output functionality 193 | 194 | void shake_xof(sha3_ctx_t *c) 195 | { 196 | c->st.b[c->pt] ^= 0x1F; 197 | c->st.b[c->rsiz - 1] ^= 0x80; 198 | sha3_keccakf(c->st.q); 199 | c->pt = 0; 200 | } 201 | 202 | void shake_out(sha3_ctx_t *c, void *out, size_t len) 203 | { 204 | size_t i; 205 | int j; 206 | 207 | j = c->pt; 208 | for (i = 0; i < len; i++) { 209 | if (j >= c->rsiz) { 210 | sha3_keccakf(c->st.q); 211 | j = 0; 212 | } 213 | ((uint8_t *)out)[i] = c->st.b[j++]; 214 | } 215 | c->pt = j; 216 | } 217 | -------------------------------------------------------------------------------- /sha3.hpp: -------------------------------------------------------------------------------- 1 | /* https://github.com/mjosaarinen/tiny_sha3 2 | * 3 | * The MIT License (MIT) 4 | * 5 | * Copyright (c) 2015 Markku-Juhani O. Saarinen 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | * 25 | */ 26 | 27 | // sha3.h 28 | // 19-Nov-11 Markku-Juhani O. Saarinen 29 | 30 | #ifndef SHA3_H 31 | #define SHA3_H 32 | 33 | #include 34 | #include 35 | 36 | #ifndef KECCAKF_ROUNDS 37 | #define KECCAKF_ROUNDS 24 38 | #endif 39 | 40 | #ifndef ROTL64 41 | #define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y)))) 42 | #endif 43 | 44 | // state context 45 | typedef struct { 46 | union { // state: 47 | uint8_t b[200]; // 8-bit bytes 48 | uint64_t q[25]; // 64-bit words 49 | } st; 50 | int pt, rsiz, mdlen; // these don't overflow 51 | } sha3_ctx_t; 52 | 53 | // Compression function. 54 | void sha3_keccakf(uint64_t st[25]); 55 | 56 | // OpenSSL - like interfece 57 | int sha3_init(sha3_ctx_t *c, int mdlen); // mdlen = hash output in bytes 58 | int sha3_update(sha3_ctx_t *c, const void *data, size_t len); 59 | int sha3_final(void *md, sha3_ctx_t *c); // digest goes to md 60 | 61 | // compute a sha3 hash (md) of given byte length from "in" 62 | void *sha3(const void *in, size_t inlen, void *md, int mdlen); 63 | 64 | // SHAKE128 and SHAKE256 extensible-output functions 65 | #define shake128_init(c) sha3_init(c, 16) 66 | #define shake256_init(c) sha3_init(c, 32) 67 | #define shake_update sha3_update 68 | 69 | void shake_xof(sha3_ctx_t *c); 70 | void shake_out(sha3_ctx_t *c, void *out, size_t len); 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /types.hpp: -------------------------------------------------------------------------------- 1 | #ifndef HPP_TYPES 2 | #define HPP_TYPES 3 | 4 | /* The structs declared in this file should have size/alignment hints 5 | * to ensure that their representation is identical to that in OpenCL. 6 | */ 7 | #if defined(__APPLE__) || defined(__MACOSX) 8 | #include 9 | #else 10 | #include 11 | #endif 12 | 13 | enum class ModeFunction { 14 | Benchmark, ZeroBytes, Matching, Leading, Range, Mirror, Doubles, LeadingRange 15 | }; 16 | 17 | typedef struct { 18 | ModeFunction function; 19 | cl_uchar data1[20]; 20 | cl_uchar data2[20]; 21 | } mode; 22 | 23 | #pragma pack(push, 1) 24 | typedef struct { 25 | cl_uchar salt[32]; 26 | cl_uchar hash[20]; 27 | cl_uint found; 28 | } result; 29 | #pragma pack(pop) 30 | 31 | typedef union { 32 | cl_uchar b[200]; 33 | cl_ulong q[25]; 34 | cl_uint d[50]; 35 | } ethhash; 36 | 37 | #endif /* HPP_TYPES */ --------------------------------------------------------------------------------